RealSense SDK 开发笔记 (三)获取R200的图像(OpenCV Mat)

来源:互联网 发布:mac 不能玩炉石传说么 编辑:程序博客网 时间:2024/05/29 12:18

(转载请注明出处)
由于上合会议期间外面的快递无法到达市内,F200这些天多半是回不来了。。。这里写图片描述
然后就等着我写SR300的吧科科~
上一节的代码的目的是了解SDK的蛋疼,也对手里的摄像头信息有个了解,当我们熟(麻)悉(木)之后很多信息就没必要管了,这节实(不)用(再)为(装)主(哔~),获取R200的彩色、深度和红外帧的数据,转换成Mat类型并显示出来。


看代码吧,到手即用(逃):

查找设备(获取并初始化指定摄像头的Device接口)

这个函数可以和SenseManager配合使用。
初始化SenseManager里面的模块之后,得益于Intel的渣调教,我们不得不自己动手再调一下曝光啥的。

根据iuid查找:

PXCCapture::Device* RealSense::ImplSeek(pxcUID iuid){    cout << "目标IUID:" << iuid << endl;    PXCCapture *Capture;    for (uint_fast8_t idx = 0; idx<UINT_FAST8_MAX; idx += 1)    {        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 << "--------------------------------------------------------------------------------------"<<endl;        wcout << "DCM服务:" <<Impl.friendlyName;        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] <<endl; // 顺便检查一下是否要升级固件         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的。

默认只获取RGBD:

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有两级,一个是行字节数,一个是点字节数。


main函数

/* #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);    }

程序截图:

这里写图片描述

至于为什么不用SenseManager

直接看CPU占用率(相同帧率、分辨率):
上述代码:
这里写图片描述
使用sensemanager的示例程序:
这里写图片描述
SenseManager给DCM喂了金克拉了?这么吃资源…
8逻辑核i7,可见单核心使用率过半,低压U的流畅度估计好不到哪去。

用了SenseManager的程序关了之后,经常枚举设备信息失败,时不时卡在提交流格式的函数上。
DCM驱动渣,优化渣,不过配上自己的渣算法这点资源损失并不算什么(雾)
等情况足够复杂再用吧。

1 0
原创粉丝点击