OpenNI depth 图像交换深度显示
OpenNI depth Image swap depth display
我已经能够 find/create 一些代码,允许我从支持 OpenNI 的相机(具体来说是 Orbbec Astra S)打开深度和颜色流。与标准 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 位图像读入的,看起来像这样(注意它有多暗):
但转换为 8 位图像后,它们看起来如下:
您所附的图像显示传感器正在捕获数据,并直接编码物体在深度中的距离(以毫米为单位)。这对于此类深度相机来说是很正常的。我们想要显示的是靠近传感器的物体的更高值(这与深度图像编码完全相反,但对显示有用)。
如果已知传感器的工作范围,可以设计一个简单的深度调整功能。对于 Astra S,工作范围是 0.35m to 2.5m。所以我们现在想要的是一个转换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;
}
这是输出的重归一化深度图像:
如果想进一步探索这种调整功能发生了什么,可以查看应用调整前后图像的直方图。
输入深度图像 (D) 的直方图:
负输入深度图像的直方图 (-D):
(maxVal-(D-minVal)) 的直方图:
希望这能回答您的问题。
我已经能够 find/create 一些代码,允许我从支持 OpenNI 的相机(具体来说是 Orbbec Astra S)打开深度和颜色流。与标准 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 位图像读入的,看起来像这样(注意它有多暗):
但转换为 8 位图像后,它们看起来如下:
您所附的图像显示传感器正在捕获数据,并直接编码物体在深度中的距离(以毫米为单位)。这对于此类深度相机来说是很正常的。我们想要显示的是靠近传感器的物体的更高值(这与深度图像编码完全相反,但对显示有用)。
如果已知传感器的工作范围,可以设计一个简单的深度调整功能。对于 Astra S,工作范围是 0.35m to 2.5m。所以我们现在想要的是一个转换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;
}
这是输出的重归一化深度图像:
如果想进一步探索这种调整功能发生了什么,可以查看应用调整前后图像的直方图。
输入深度图像 (D) 的直方图:
负输入深度图像的直方图 (-D):
(maxVal-(D-minVal)) 的直方图:
希望这能回答您的问题。