如果有别的问题讨论,可以私信我。
如果你看见的时候已经不是2018年,那我可能只剩下书面上的资料。
看了三天ToF相机的文档和程序员指导书,搞懂了基础的数据结构和方法。
数据结构:
BufferParts向量用于存储图像数据,包含了PartInfo结构。
Coord3D是一个包含3D坐标和一个flag的结构体,它可以通过查询来检查数据有效性
typedef std::vector<PartInfo> BufferParts;
struct PartInfo
{
void* pData;//数据指针
size_t size;//数据数组大小
size_t width;//宽
size_t height;//高
BufferPartType partType;//缓冲区数据类型
uint64_t dataFormat;//按Genicam标准数据格式
};
enum BufferPartType
{
Range,
Intensity,
Confidence,
Undefined
};
strcut Coord3D
{
float x;
float y;
float z;
bool IsValid() const {return z==z;//check for NAN}
};
一般采用
ptrPixelFormat->FromString("Coord3D_ABC32f" );时,
BufferParts parts分两个部分,第一部分是三维数据,第二部分是Intensity值。
改了Sample里的几个例程,
1:采集Intensity图像和深度图像(range),并保存成PNG格式。
/*
Author:Spy
The latest version:2018.03.23
Tel:17865190816
*/
#include "stdafx.h"
#include <ConsumerImplHelper/ToFCamera.h>
#include <iostream>
#include <vector>
#include <limits>
#include <opencv2/opencv.hpp>
using namespace GenTLConsumerImplHelper;
using namespace std;
using namespace cv;
int index=0;
int index1 = 0;
class Sample
{
public:
Sample();
int run();
bool onImageGrabbed( GrabResult grabResult, BufferParts );
private:
CToFCamera m_Camera; // the ToF camera
double m_inc; // displacement of translation vector per keystroke
Point3d m_t; // translation vector of camera
Mat m_R; // rotation matrix
double m_phiX; // rotation of camera around x-axis
double m_phiY; // rotation of camera around y-axis
double m_deltaPhi; // increment of rotation angle
double m_deltaF; // increment of the focal length when zooming in and out
double m_f; // pinhole camera's focal length
void Reset();
};
Sample::Sample()
{
Reset();
};
void Sample::Reset()
{
m_inc = 50;
m_deltaPhi = 0.05;
m_phiX = 0.4;
m_phiY = 0.4;
//m_t = Point3d(640, 480, 10);
m_t = Point3d( -1800, 1300, -100 ); // initial position of the camera (chosen at random)
m_f = 10;
m_deltaF = 0.5;
}
int Sample::run()
{
try
{
m_Camera.OpenFirstCamera();
cout << "Connected to camera " << m_Camera.GetCameraInfo().strDisplayName << endl;
cout << "Keyboard navigation: " << endl;
cout << " Arrow keys left/right:\tmove camera horizontally." << endl;
cout << " Arrow keys up/down:\t\tmove camera vertically." << endl;
cout << " Numpad 4/6:\t\t\trotate camera around y axis." << endl;
cout << " Numpad 8/2:\t\t\trotate camera around x axis." << endl;
cout << " Numpad 5:\t\t\treset to initial camera position." << endl;
cout << " Numpad +/-:\t\t\tzoom in and out." << endl;
cout << " q:\t\t\t\tquit program" << endl;
cout << endl << "For keyboard navigation to work, one of the image windows must have the focus." << endl;
// Enable 3D (point cloud) data and intensity data
GenApi::CEnumerationPtr ptrComponentSelector = m_Camera.GetParameter("ComponentSelector");
GenApi::CBooleanPtr ptrComponentEnable = m_Camera.GetParameter("ComponentEnable");
GenApi::CEnumerationPtr ptrPixelFormat = m_Camera.GetParameter("PixelFormat");
ptrComponentSelector->FromString("Range");
ptrComponentEnable->SetValue(true);
ptrPixelFormat->FromString("Coord3D_ABC32f" );
ptrComponentSelector->FromString("Intensity");
//ptrComponentSelector->FromString("Range");
ptrComponentEnable->SetValue(true);
//namedWindow("Range", CV_WINDOW_AUTOSIZE);
namedWindow("Intensity", CV_WINDOW_AUTOSIZE );
namedWindow("depth", CV_WINDOW_AUTOSIZE );
// namedWindow("Point Cloud (distance)", CV_WINDOW_AUTOSIZE );
// Acquire images until the call-back onImageGrabbed indicates to stop acquisition.
m_Camera.GrabContinuous( 2, 1000, this, &Sample::onImageGrabbed );
// Clean-up
m_Camera.Close();
}
catch ( const GenICam::GenericException& e )
{
cerr << "Exception occurred: " << e.GetDescription() << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
bool Sample::onImageGrabbed( GrabResult grabResult, BufferParts parts )
{
int key = 0;
if ( grabResult.status == GrabResult::Timeout )
{
cerr << "Timeout occurred. Acquisition stopped." << endl;
return false; // Indicate to stop acquisition
}
if ( grabResult.status != GrabResult::Ok )
{
cerr << "Image was not grabbed." << endl;
}
else
{
try
{
// Create OpenCV images from grabbed buffer
const int width = (int) parts[0].width;
const int height = (int) parts[0].height;
const int count = width * height;
CToFCamera::Coord3D *pPoint = static_cast<CToFCamera::Coord3D*>(parts[0].pData);
Mat cloud( count, 3, CV_32FC1, parts[0].pData );
Mat intensity = Mat(height, width, CV_16UC1, parts[1].pData);
// Scale the intensity image since it often looks quite dark
double max;
minMaxLoc( intensity, NULL, &max);
intensity /= ( max / std::numeric_limits<uint16_t>::max() );
index = index + 1;
if (index == 10)
{
vector<int> compressiong_params;
compressiong_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compressiong_params.push_back(0);
const char *path = "C:/Users/17865/Desktop/heelo/heelo/VS/Samples/photo/intensity.png";
imwrite(path, intensity, compressiong_params);
cout << "The intensity photo is saved." << endl;
//cout << parts[1].pData<< endl;
}
// Display the intensity image
imshow("Intensity", intensity);
Mat depthimage =Mat(height, width , CV_16UC1);
depthimage.setTo(0);
for (size_t i = 0; i < parts[0].height; i++)
{
for (size_t j = 0; j < parts[0].width; j++)
{
depthimage.at<uint16_t>(i, j) = static_cast<uint16_t>(pPoint->z); // can be NaN; should be in mm
//if (i == 250 && j == 250){
//cout << static_cast<uint16_t>(pPoint->z) << endl;
// }
pPoint++;
}
}
index1 = index1 + 1;
if (index1 == 10)
{
vector<int> compressiong_params;
compressiong_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compressiong_params.push_back(0);
const char *path = "C:/Users/17865/Desktop/heelo/heelo/VS/Samples/photo/depth.png";
imwrite(path, depthimage, compressiong_params);
cout << "The depeth photo is saved." << endl;
//cout << parts[1].pData<< endl;
}
imshow("depth", depthimage);
}
catch (const Exception& e)
{
cerr << e.what() << endl;
}
}
key = waitKey(1);
if (key != -1)
{
switch (key)
{
case 0x260000: // Windows arrow up
case 0x10ff52: // Linux arrow up
m_t.y += m_inc; break; // Move camera up
case 0x280000: // Windows arrow down
case 0x10ff54: // Linux arrow down
m_t.y -= m_inc; break; // Move camera down
case 0x250000: // Windows arrow left
case 0x10ff51: // Linux arrow left
m_t.x += m_inc; break;
case 0x270000: // Windows arrow right
case 0x10ff53: // Linux arrow right
m_t.x -= m_inc; break;
case '+': // Windows numpad +
case 0x10ffab: // Linux numpad +
m_f += m_deltaF; break;
case '-': // Windows numpad -
case 0x10ffad: // Linux numpad -
m_t.z -= m_deltaF; break;
case '4': // Windows numpad 4
case 0x10ffb4: // Linux numpad 4
m_phiY -= m_deltaPhi; break;
case '6': // Windows numpad 6
case 0x10ffb6: // Linux numpad 6
m_phiY += m_deltaPhi; break;
case '2': // Windows numpad 2
case 0x10ffb2: // Linux numpad 2
m_phiX -= m_deltaPhi; break;
case '8': // Windows numpad 8
case 0x10ffb8: // Linux numpad 8
m_phiX += m_deltaPhi; break;
case '5': // Windows numpad 5
case 0x10ffb5: // Linux numpad 5
Reset(); break;
}
//cout << "t=" << m_t << " phiX =" << m_phiX << " phiy= " << m_phiY << " f= " << m_f << endl;
}
return 'q' != (char)key;
}
int main(int argc, char* argv[])
{
int exitCode = EXIT_SUCCESS;
try
{
CToFCamera::InitProducer();
Sample processing;
exitCode = processing.run();
}
catch (GenICam::GenericException& e)
{
cerr << "Exception occurred: " << endl << e.GetDescription() << endl;
exitCode = EXIT_FAILURE;
}
// Release the GenTL producer and all of its resources.
// Note: Don't call TerminateProducer() until the destructor of the CToFCamera
// class has been called. The destructor may require resources which may not
// be available anymore after TerminateProducer() has been called.
if (CToFCamera::IsProducerInitialized())
CToFCamera::TerminateProducer(); // Won't throw any exceptions
return exitCode;
}
保存的图: