简体   繁体   English

OpenNI 深度图像交换深度显示

[英]OpenNI depth Image swap depth display

I've been able to find/create some code that allows me to open the depth and color stream from the OpenNI enabled camera (It is an Orbbec Astra S to be specific).我已经能够找到/创建一些代码,允许我从启用 OpenNI 的相机(具体来说是 Orbbec Astra S)打开深度和颜色流。 Except unlike with the standard OpenNI Viewer, My stream displays the closest points as darkest and further points as the lighter colors.除了与标准 OpenNI 查看器不同,我的流将最近的点显示为最暗的点,将更远的点显示为较亮的颜色。

How would I be able to change this around so that the points closest to the cameras are shown as lighter (whites) and further away is shown as dark?我如何才能改变这一点,以便最靠近相机的点显示为更亮(白色),而更远的点显示为暗?

#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------------------- - - - - - - - - - -编辑 - - - - - - - - - -

These Images are originally read in as 16bit images, which look like this (note how dark it is):这些图像最初是作为 16 位图像读入的,看起来像这样(注意它有多暗):

在此处输入图片说明

But after converting to an 8bit image, they look as follows:但转换为 8 位图像后,它们看起来如下:

在此处输入图片说明

The image you attached shows that the sensor is capturing the data with directly encoding the distance (in mm) of the object in the depth.您附加的图像显示传感器正在通过直接编码深度中对象的距离(以毫米为单位)来捕获数据。 This is quite normal for such depth cameras.这对于这种深度相机来说是很正常的。 What we want instead for displaying is higher values for objects closer to the sensor (this is totally opposite to the depth image encoding but useful for displaying).我们想要显示的是更接近传感器的物体的更高值(这与深度图像编码完全相反,但对显示有用)。

One can devise a simple depth adjustment function if the operating range of the sensor is known.如果传感器的工作范围已知,则可以设计一种简单的深度调节功能。 For Astra S, the operating range is from 0.35m to 2.5m .对于 Astra S,操作范围为0.35m 至 2.5m So what we want now is a function that converts 0.35m -> 2.5m and 2.5m -> 0.35m.所以我们现在想要的是一个转换 0.35m -> 2.5m 和 2.5m -> 0.35m 的函数。

This is pretty straightforward, the only caveat is that you have to take care of the invalid depth pixel (depth == 0) yourself.这非常简单,唯一需要注意的是您必须自己处理无效的深度像素 (depth == 0)。 Here is the code for doing this:这是执行此操作的代码:

#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;
}

Here is the output renormalized depth image:这是输出的重归一化深度图像:

在此处输入图片说明

If one wants to further explore what happens in such readjustment function, one can have a look at the histogram for image both before and after applying the adjustment.如果想进一步探索在这种重新调整功能中会发生什么,可以查看应用调整前后的图像直方图。

Histogram for input depth image (D):输入深度图像 (​​D) 的直方图:

在此处输入图片说明

Histogram for negative input depth image (-D):负输入深度图像(-D)的直方图:

在此处输入图片说明

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

在此处输入图片说明

Hope this answers your question.希望这能回答你的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM