(转载请注明出处)
由于上合会议期间外面的快递无法到达市内,F200这些天多半是回不来了。。。
然后就等着我写SR300的吧科科~
上一节的代码的目的是了解SDK的蛋疼,也对手里的摄像头信息有个了解,当我们熟(麻)悉(木)之后很多信息就没必要管了,这节实(不)用(再)为(装)主(哔~),获取R200的彩色、深度和红外帧的数据,转换成Mat类型并显示出来。
这个函数可以和SenseManager配合使用。
初始化SenseManager里面的模块之后,得益于Intel的渣调教,我们不得不自己动手再调一下曝光啥的。
PXCCapture::Device* RealSense::ImplSeek(pxcUID iuid)
{
cout << "目标IUID:" << iuid << endl;
PXCCapture *Capture;
for (uint_fast8_t idx = 0; idx1)
{
PXCSession::ImplDesc Impl = {};
Impl.group = PXCSession::IMPL_GROUP_SENSOR;
Impl.subgroup = PXCSession::IMPL_SUBGROUP_VIDEO_CAPTURE;
retStatus = Session->QueryImpl(&Impl, idx, &Impl);
if (retStatus < PXC_STATUS_NO_ERROR) continue;
cout << "--------------------------------------------------------------------------------------"<"DCM服务:" <cout <<" *** IUID是:"<< Impl.iuid << endl;
retStatus = Session->CreateImpl(&Impl, &Capture);
if (retStatus < PXC_STATUS_NO_ERROR) continue;
dinfo = { 0 };
retStatus = Capture->QueryDeviceInfo(idx, &dinfo);
if (retStatus < PXC_STATUS_NO_ERROR) { cout << "详细信息:获取失败" << endl; continue; }
wcout << "详细信息:" << endl;
wcout << " 名称:" << dinfo.name << " 位于DCM设备索引 " << dinfo.didx << endl;
wcout << " 可使用视频流:";
if (dinfo.streams&PXCCapture::STREAM_TYPE_COLOR) cout << "COLOR ";
if (dinfo.streams&PXCCapture::STREAM_TYPE_DEPTH) cout << "DEPTH ";
if (dinfo.streams&PXCCapture::STREAM_TYPE_IR) cout << "IR ";
if (dinfo.streams&PXCCapture::STREAM_TYPE_LEFT) cout << "LEFT" ;
if (dinfo.streams&PXCCapture::STREAM_TYPE_RIGHT) cout << "RIGHT "; wcout << endl;
wcout << " 固件版本:V" << dinfo.firmware[0] << "." << dinfo.firmware[1] << "." << dinfo.firmware[2] << "." << dinfo.firmware[3] <// 顺便检查一下是否要升级固件
wcout << " 序列号:" << dinfo.serial << endl; // 最终确定是哪个摄像机就靠它认了
wcout << " 设备标识符:" << dinfo.did << endl;// 不嫌蛋疼的也可以拿它认
if (Impl.iuid != iuid) continue;
cout << "======================================================================================" << endl;
wcout << "√!找到了匹配的" << Capture->DeviceModelToString(dinfo.model)<<" ";
device = Capture->CreateDevice(idx);
return device;
}
if (device == NULL) { cout << "\n没有匹配的设备,"; }
return NULL;
}
暂时遇到一个问题:R200动不动就无法正常读出来信息(这几天解决)
被M$坑完再被Intel坑=_=|||
void StreamInit(int Profile_idx, PXCCapture::Device *dstDevice, bool Dualeye)
{
PXCCapture::Device::StreamProfileSet ProfileSet = {};
if (Dualeye)
{
PXCCapture::StreamType scope = PXCCapture::STREAM_TYPE_COLOR | PXCCapture::STREAM_TYPE_DEPTH | PXCCapture::STREAM_TYPE_LEFT | PXCCapture::STREAM_TYPE_RIGHT;
dstDevice->QueryStreamProfileSet(scope, Profile_idx, &ProfileSet);
ProfileSet.color.options = ProfileSet.depth.options =
ProfileSet.right.options = ProfileSet.left.options =
PXCCapture::Device::STREAM_OPTION_STRONG_STREAM_SYNC;
}
else
{
PXCCapture::StreamType scope = PXCCapture::STREAM_TYPE_COLOR | PXCCapture::STREAM_TYPE_DEPTH | PXCCapture::STREAM_TYPE_IR;
dstDevice->QueryStreamProfileSet(scope, Profile_idx, &ProfileSet);
ProfileSet.color.options = ProfileSet.depth.options =
ProfileSet.ir.options =
PXCCapture::Device::STREAM_OPTION_STRONG_STREAM_SYNC;
}
if (dstDevice->IsStreamProfileSetValid(&ProfileSet))
{
dstDevice->SetStreamProfileSet(&ProfileSet);
cout << "Ready" << endl;
}
else
cout << "Bad ProfileSet" << endl;
}
/*
@Profile_idx:根据上节查询的代码,找到对应的索引号即可
@*dstDevice:对应操作的设备
@Dualeye:是否是R200(我偷懒了,本应该自动判断的)
渣代码渣风格,建议自己写一遍
*/
struct Frames
{
Mat Color;
Mat Depth;
Mat IR;
Mat IR_;
};
由于R200有两个红外帧,所以这里第四个是留给R200的。
Frames Update(PXCCapture::Device *Device , bool Dualeye = true, PXCCapture::StreamType scope = PXCCapture::STREAM_TYPE_COLOR | PXCCapture::STREAM_TYPE_DEPTH)
{
PXCCapture::Sample FrameSamples;
PXCImage::ImageData color8, deth16, _ir,biol16, bior16;
retStatus = Device->ReadStreams(scope, &FrameSamples);
if (retStatus < PXC_STATUS_NO_ERROR) exit(0);// 有错直接退出
Frames frames;
if (Dualeye)
{
#pragma region dualeye
if (scope & PXCCapture::STREAM_TYPE_COLOR)
{
FrameSamples.color->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_RGB24, PXCImage::ROTATION_0_DEGREE, PXCImage::OPTION_ANY, &color8);
Mat Color(Size(320, 240), CV_8UC3, color8.planes[0]); frames.Color = Color;
FrameSamples.color->ReleaseAccess(&color8);
}
if (scope & PXCCapture::STREAM_TYPE_DEPTH)
{
FrameSamples.depth->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_DEPTH, PXCImage::ROTATION_0_DEGREE, PXCImage::OPTION_ANY, &deth16);
Mat Depth(Size(320, 240), CV_16UC1, deth16.planes[0]); frames.Depth = Depth;
FrameSamples.depth->ReleaseAccess(&deth16);
}
if (scope & PXCCapture::STREAM_TYPE_LEFT)
{
FrameSamples.left->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_Y16, PXCImage::ROTATION_0_DEGREE, PXCImage::OPTION_ANY, &biol16);
Mat StroL(Size(320, 240), CV_16UC1, biol16.planes[0]); frames.IR = StroL;
FrameSamples.left->ReleaseAccess(&biol16);
}
if (scope & PXCCapture::STREAM_TYPE_RIGHT)
{
FrameSamples.right->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_Y16, PXCImage::ROTATION_0_DEGREE, PXCImage::OPTION_ANY, &bior16);
Mat StroR(Size(320, 240), CV_16UC1, bior16.planes[0]); frames.IR_ = StroR;
FrameSamples.right->ReleaseAccess(&bior16);
}
#pragma endregion
}
else
{
#pragma region _
if (scope & PXCCapture::STREAM_TYPE_COLOR)
{
FrameSamples.color->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_RGB24, PXCImage::ROTATION_0_DEGREE, PXCImage::OPTION_ANY, &color8);
Mat Color(Size(640, 480), CV_8UC3, color8.planes[0]); frames.Color = Color;
FrameSamples.color->ReleaseAccess(&color8);
}
if (scope & PXCCapture::STREAM_TYPE_DEPTH)
{
FrameSamples.depth->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_DEPTH, PXCImage::ROTATION_0_DEGREE, PXCImage::OPTION_ANY, &deth16);
Mat Depth(Size(640, 480), CV_16UC1, deth16.planes[0]); frames.Depth = Depth;
FrameSamples.depth->ReleaseAccess(&deth16);
}
if (scope & PXCCapture::STREAM_TYPE_IR)
{
FrameSamples.ir->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_Y16, PXCImage::ROTATION_0_DEGREE, PXCImage::OPTION_ANY, &_ir);
Mat _IR(Size(640, 480), CV_16UC1, _ir.planes[0]); frames.IR = _IR;
FrameSamples.left->ReleaseAccess(&_ir);
}
#pragma endregion
}
FrameSamples.ReleaseImages(); return(frames);
}
PXCCapture::Sample 这种结构体里面有名为:*color;*depth;*ir;left;*right;
的PXCImage类型的变量:
对应彩色帧、深度帧、红外帧、双目左红外帧、双目右红外帧的图像数据描述和接口。用ReadStreams来获取StramType包含的类型的图像。
PXCImage::ImageData 这个类型是来描述图像存储信息的(像素格式,首地址,step)。
下面来看看获取图像内容的函数:
AcquireAccess:临时锁定要访问的帧内部数据,并将数据格式化成指定格式,然后告诉ImageData数据的存放信息。
ReleaseAccess:顾名思义,释放刚才锁定的数据内容。
OpenCV的一行代码即可,如彩色图:
Mat bgr(Size(r, c), CV_8UC3, color8.planes[0])
暴力美学如上,而且Mat拷贝只是复制图像的头数据,时间损失很小。
重载用到的参数依次是Size(行,列)、图像类型、数据起始指针。step在这里是自动的,代表最高维度包含的字节数,图象是二维的,step有两级,一个是行字节数,一个是点字节数。
/* #define R200_IUID 自己填写 */
PXCSession *Session =PXCSession::CreateInstance();
pxcStatus retStatus;
int main()
{
PXCCapture::Device *R200_Device;
// Init Device
R200_Device = ImplSeek(R200_IUID);
StreamInit(6, R200_Device, true);
cout << "Streaming..." << endl;
// loop
for (;;)
{
Frames R200_rgbd = Update(R200_Device);
//pipeline
Mat Depth8 = R200_rgbd.Depth.clone();
(Depth8 /= 15).convertTo(Depth8, CV_8UC1, 1, 20);
//show
imshow("Depth8", Depth8);
imshow("Color", R200_rgbd.Color);
waitKey(1);
}
直接看CPU占用率(相同帧率、分辨率):
上述代码:
使用sensemanager的示例程序:
SenseManager给DCM喂了金克拉了?这么吃资源…
8逻辑核i7,可见单核心使用率过半,低压U的流畅度估计好不到哪去。
用了SenseManager的程序关了之后,经常枚举设备信息失败,时不时卡在提交流格式的函数上。
DCM驱动渣,优化渣,不过配上自己的渣算法这点资源损失并不算什么(雾)
等情况足够复杂再用吧。