2016-10-07 46 views
2

OpenNI対応カメラ(特定のOrbbec Astra Sです)から深度と色のストリームを開くことができるコードをいくつか検索/作成できました。標準のOpenNI Viewerとは異なり、Myストリームは最も近い点を最も暗い点とそれ以上の点をより明るい色として表示します。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; 
} 

------------------- ------------------- EDIT

これらの画像は、もともと(それがどのように暗い注意してください)このようになり、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

1は、さらに、このような再調整機能で何が起こるか模索したい場合は、1が見ることができ画像のヒストグラムで、調整を適用する前後の両方に適用されます。入力深度画像のため

ヒストグラム(D):

enter image description here

ヒストグラム用(maxVal-(D-:負入力深度画像(-D)用

enter image description here

ヒストグラムminVal)):

enter image description here

あなたの質問にお答えします。

+0

x軸の値は距離になりますが、Y軸はどうなりますか?私はおそらくピクセルの数を考えていますか?それらの線に沿ったもの –

+0

本質的にヒストグラムなので、y軸は特定の深度値を持つピクセルの頻度またはカウントを示します。また、いくつかの無効な深さピクセル(値== 0)があるので、ヒストグラムにはピークがあります。 – masad

関連する問題