2016-10-07 6 views
2

OpenNI 사용 가능 카메라 (특정 Orbbec Astra S)에서 깊이와 색상을 열 수있는 코드를 찾고/만들 수있었습니다. 표준 OpenNI 뷰어와 달리, 내 스트림은 가장 가까운 점을 가장 어둡게 표시하고 밝은 점으로 표시합니다.OpenNI 깊이 이미지 스왑 깊이 표시

카메라에 가장 가까운 점을 밝게 (흰색) 표시하고 멀리있는 부분을 어둡게 보이게하려면 어떻게 바꿀 수 있습니까?

#include "stdafx.h" 
#include "OpenNI.h" 
#include <iostream> 
#include <iomanip> 
#include <fstream> 
#include <string> 
#include <array> 
// OpenCV Header 
#include <opencv2/core/core.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/calib3d/calib3d.hpp> 

using namespace std; 
using namespace cv; 
using namespace openni; 

//Recorder 

int main(int argc, char** argv) 
{ 
    Device device; 
    VideoStream DepthStream,ColorStream; 
    VideoFrameRef DepthFrameRead,ColorFrameRead; 

    const char* deviceURI = openni::ANY_DEVICE; 
    if (argc > 1) 
    { 
     deviceURI = argv[1]; 
    } 

    Status result = STATUS_OK; 
    result = OpenNI::initialize(); 
    result = device.open(deviceURI); 
    result = DepthStream.create(device, openni::SENSOR_DEPTH); 
    result = DepthStream.start(); 
    result = ColorStream.create(device, openni::SENSOR_COLOR); 
    result = ColorStream.start(); 

     device.setImageRegistrationMode(ImageRegistrationMode::IMAGE_REGISTRATION_DEPTH_TO_COLOR); 

    int framenum = 0; 
    Mat frame; 
    while (true) 
    { 
     if (DepthStream.readFrame(&DepthFrameRead) == STATUS_OK) 
     { 
      cv::Mat cDepthImg(DepthFrameRead.getHeight(), DepthFrameRead.getWidth(), 
       CV_16UC1, (void*)DepthFrameRead.getData()); 

      cv::Mat c8BitDepth; 
      cDepthImg.convertTo(c8BitDepth, CV_8U, 255.0/(8000)); 
      cv::imshow("Orbbec", c8BitDepth); 

     } 

     if (ColorStream.readFrame(&ColorFrameRead) == STATUS_OK) 
     { 
      ColorStream.readFrame(&ColorFrameRead); 
      const openni::RGB888Pixel* imageBuffer = (const openni::RGB888Pixel*)ColorFrameRead.getData(); 

      frame.create(ColorFrameRead.getHeight(), ColorFrameRead.getWidth(), CV_8UC3); 
      memcpy(frame.data, imageBuffer, 3 * ColorFrameRead.getHeight()*ColorFrameRead.getWidth() * sizeof(uint8_t)); 

      cv::cvtColor(frame, frame, CV_BGR2RGB); //this will put colors right 
      cv::imshow("frame", frame); 
      framenum++; 
     } 

     if (cvWaitKey(30) >= 0) 
     { 
      break; 
     } 
    } 
    DepthStream.destroy(); 
    ColorStream.destroy(); 
    device.close(); 
    OpenNI::shutdown(); 
    return 0; 
} 

------------------- 편집 -------------------

이 이미지는 원래 (그것이 얼마나 어두운 주)과 같이 16 비트 이미지로 읽습니다 :

enter image description here

다음과 같이 그러나 8 비트 이미지로 변환 한 후, 그들이 보게 :

enter image description here

+0

캡처 한 깊이 이미지 예제를 몇 가지 제공 할 수 있습니까? – masad

+0

@masad는 위 사진을 추가했습니다. 손이 검은 색이 아니며 작동 거리 내에 있음을 유의하십시오.그러나 가까이 있기 때문에 배경 벽보다 훨씬 더 어둡게 표현됩니다. –

답변

2

첨부 된 이미지는 센서가 깊이에서 물체의 거리 (mm)를 직접 인코딩하여 데이터를 캡처하고 있음을 보여줍니다. 이러한 깊이 카메라의 경우에는 정상입니다. 우리가 대신 표시하고자하는 것은 센서에 더 가까운 객체에 대한 더 높은 값입니다 (이는 깊이 이미지 인코딩과 완전히 반대이지만 표시에 유용함).

센서의 작동 범위가 알려지면 간단한 깊이 조절 기능을 고안 할 수 있습니다. Astra S의 경우 작동 범위는 0.35m to 2.5m입니다. 이제 우리가 원하는 것은 0.35m -> 2.5m 및 2.5m -> 0.35m을 변환하는 기능입니다.

이것은 매우 간단합니다. 유일한주의 사항은 잘못된 깊이 픽셀 (깊이 == 0)을 직접 처리해야한다는 것입니다. 여기

#include "include\opencv\cv.h" 
#include "include\opencv\highgui.h" 


cv::Mat adjustDepth(const cv::Mat& inImage) 
{ 
    // from https://orbbec3d.com/product-astra/ 
    // Astra S has a depth in the range 0.35m to 2.5m 
    int maxDepth = 2500; 
    int minDepth = 350; // in mm 

    cv::Mat retImage = inImage; 

    for(int j = 0; j < retImage.rows; j++) 
     for(int i = 0; i < retImage.cols; i++) 
     { 
      if(retImage.at<ushort>(j, i)) 
       retImage.at<ushort>(j, i) = maxDepth - (retImage.at<ushort>(j, i) - minDepth); 
     } 

     return retImage; 
} 


int main() 
{ 
    cv::Mat inImage; 
    inImage = cv::imread("testImage.png", CV_LOAD_IMAGE_UNCHANGED); 

    cv::Mat adjustedDepth = adjustDepth(inImage); 
    cv::Mat dispImage; 
    adjustedDepth.convertTo(dispImage, CV_8UC1, 255.0f/2500.0f); 
    cv::imshow(" ", dispImage); 

    //cv::imwrite("testImageAdjusted.png", adjustedDepth); 
    //cv::imwrite("savedImage.png", dispImage); 

    cv::waitKey(0); 
    return 0; 
} 

출력 재 정규화 깊이 이미지 : 다음은이 작업을 수행하는 코드는

enter image description here

하나 더 같은 구획 정리 기능에서 발생하는 탐구하고자하는 경우, 하나는 모양을 가질 수있다 조정을 적용하기 전후의 이미지 히스토그램에서 입력 깊이 이미지

히스토그램 (D) :

enter image description here

히스토그램 (maxVal- (D- : 음성 입력 깊이 이미지 (-D) 용

enter image description here

히스토그램 minVal)) :

enter image description here

희망 사항이 귀하의 질문에 대한 답변입니다.

+0

x 축의 값이 거리가되는 것을 볼 수 있습니다. Y 축은 어떻게 될까요? 나는 픽셀 수를 생각하고 있나? 또는 그 라인을 따라 무엇인가 –

+0

본질적으로 히스토그램입니다. 그렇기 때문에 y 축은 특정 깊이 값을 가진 픽셀의 빈도 또는 개수를 보여줍니다. 또한 잘못된 깊이 픽셀 (값 == 0)이 여러 개 있으므로 히스토그램의 피크가 있습니다. – masad

관련 문제