C++ OpenNI深度图像交换深度显示

C++ OpenNI深度图像交换深度显示,c++,image,opencv,depth,openni,C++,Image,Opencv,Depth,Openni,我已经能够找到/创建一些代码,允许我从启用OpenNI的摄像头打开深度和颜色流(具体来说是Orbbec Astra S)。除了与标准OpenNI查看器不同之外,My stream将最近的点显示为最暗的点,将更远的点显示为较亮的颜色 我怎样才能改变这一点,使离摄像机最近的点显示为较亮(白色),而离摄像机较远的点显示为较暗 #include "stdafx.h" #include "OpenNI.h" #include <iostream> #include <iomanip&g

我已经能够找到/创建一些代码,允许我从启用OpenNI的摄像头打开深度和颜色流(具体来说是Orbbec Astra S)。除了与标准OpenNI查看器不同之外,My stream将最近的点显示为最暗的点,将更远的点显示为较亮的颜色

我怎样才能改变这一点,使离摄像机最近的点显示为较亮(白色),而离摄像机较远的点显示为较暗

#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;
}
#包括“stdafx.h”
#包括“OpenNI.h”
#包括
#包括
#包括
#包括
#包括

但在转换为8位图像后,它们的外观如下所示:


您所附的图像显示传感器正在捕获数据,并直接对深度中物体的距离(单位:mm)进行编码。这对于这种深度相机来说是很正常的。我们想要显示的是更靠近传感器的对象的更高值(这与深度图像编码完全相反,但对显示有用)

如果已知传感器的工作范围,可以设计一个简单的深度调节功能。对于Astra S,工作范围为。所以我们现在需要的是一个函数,它可以转换0.35m->2.5m和2.5m->0.35m

这非常简单,唯一的警告是您必须自己处理无效的深度像素(depth==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;
}
#包括“include\opencv\cv.h”
#包括“include\opencv\highgui.h”
cv::Mat调整深度(常数cv::Mat和inImage)
{
//从https://orbbec3d.com/product-astra/
//阿斯特拉S的深度范围为0.35米至2.5米
int最大深度=2500;
int minDepth=350;//单位为毫米
cv::Mat retImage=inImage;
对于(int j=0;j
以下是输出的重整化深度图像:

如果想进一步探索这种重新调整功能会发生什么,可以在应用调整前后查看图像的直方图

输入深度图像的直方图(D):

负输入深度图像的直方图(-D):

(maxVal-(D-minVal))的直方图:


希望这能回答您的问题。

您能给出一些您拍摄的深度图像示例吗?@masad在上面添加了一些图片。请注意,手不是黑色的,并且在工作距离内。但是因为它很近,所以它比背景中的墙暗得多。我可以看到x轴上的值是距离,Y轴是什么?我想可能是像素数?或者沿着这些线的一些东西本质上是一个直方图,所以y轴显示具有特定深度值的像素的频率或计数。还要注意,由于存在大量无效的深度像素(值==0),因此直方图在那里有一个峰值。