kinect+opencv+mfc读取深度和彩色摄像头及截图
来源:互联网 发布:springmvc注解详解源码 编辑:程序博客网 时间:2024/06/01 10:40
接着上面那一篇读彩色摄像头的。http://blog.csdn.net/u013948010/article/details/78289073
在其基础上加上了定时器和读深度摄像头即截图功能。最终结果图是酱紫的:
截图结果
设置定时器
由于好像循环读取并不是很好,所以把打开摄像头和读取视频的代码分开了,并设了一个定时器。当然其中避免不了把一些变量设成全局变量的啦。
定时器
void CopentestDlg::OnTimer(UINT_PTR nIDEvent){ if (1 == nIDEvent) { CaptureVideo(); //捕捉自带摄像头 } else if (2 == nIDEvent) { CaptureKinectVideo(); //捕捉彩色摄像头 } else if (3 == nIDEvent) { CaptureKinectDepthVideo(); //捕捉深度摄像头 } CDialog::OnTimer(nIDEvent);}
初始化摄像头
void CopentestDlg::OnBnClickedButton4(){ // TODO: 在此添加控件通知处理程序代码 //2、定义事件句柄 //创建读取下一帧的信号事件句柄,控制KINECT是否可以开始读取下一帧数据 nextColorFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL); colorStreamHandle = NULL; //保存图像数据流的句柄,用以提取数据 //3、打开KINECT设备的彩色图信息通道,并用colorStreamHandle保存该流的句柄,以便于以后读取 hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, nextColorFrameEvent, &colorStreamHandle); if (FAILED(hr))//判断是否提取正确 { AfxMessageBox(_T("读取错误")); NuiShutdown(); return; } CRect rect; CWnd *pWnd = GetDlgItem(IDC_STATIC); pWnd->GetClientRect(&rect); //获取控件大小 x = rect.Width(); y = rect.Height(); //4、开始读取彩色图数据 //追加文本 pEdit->ReplaceSel(_T("开始读取kinect彩色摄像头数据\r\n")); SetTimer(2, 25, NULL); //定时器,定时时间和帧率一致}
读取摄像头数据
const NUI_IMAGE_FRAME * pImageFrame = NULL; //4.1、无限等待新的数据,等到后返回 if (WaitForSingleObject(nextColorFrameEvent, INFINITE) == 0) { //4.2、从刚才打开数据流的流句柄中得到该帧数据,读取到的数据地址存于pImageFrame hr = NuiImageStreamGetNextFrame(colorStreamHandle, 0, &pImageFrame); if (FAILED(hr)) { AfxMessageBox(_T("不能获取彩色图像")); NuiShutdown(); return; } INuiFrameTexture * pTexture = pImageFrame->pFrameTexture; NUI_LOCKED_RECT LockedRect; //4.3、提取数据帧到LockedRect,它包括两个数据对象:pitch每行字节数,pBits第一个字节地址 //并锁定数据,这样当我们读数据的时候,kinect就不会去修改它 pTexture->LockRect(0, &LockedRect, NULL, 0); //4.4、确认获得的数据是否有效 if (LockedRect.Pitch != 0) { //4.5、将数据转换为OpenCV的Mat格式 for (int i = 0; i < image.rows; i++) { uchar *ptr = image.ptr<uchar>(i); //第i行的指针 //每个字节代表一个颜色信息,直接使用uchar uchar *pBuffer = (uchar*)(LockedRect.pBits) + i * LockedRect.Pitch; for (int j = 0; j < image.cols; j++) { ptr[3 * j] = pBuffer[4 * j]; //内部数据是4个字节,0-1-2是BGR,第4个现在未使用 ptr[3 * j + 1] = pBuffer[4 * j + 1]; ptr[3 * j + 2] = pBuffer[4 * j + 2]; } } cv::Mat dst; cv::resize(image, dst, cv::Size(x, y), 0, 0, 1); cv::imshow("view", dst); } else { AfxMessageBox(_T("获取数据无效")); } //5、这帧已经处理完了,所以将其解锁 pTexture->UnlockRect(0); //6、释放本帧数据,准备迎接下一帧 NuiImageStreamReleaseFrame(colorStreamHandle, pImageFrame); }
开深度摄像头
深度摄像头其实和彩色摄像头的获取非常非常类似,只需要修改其中几个地方,首先初始化变为全局初始化写在OnInitDialog()中,改写为
hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH); //初始化彩色和深度图像
创建并两个视频小窗口
cvNamedWindow("view", CV_WINDOW_AUTOSIZE); cvNamedWindow("depth", CV_WINDOW_AUTOSIZE); HWND hWnd = (HWND)cvGetWindowHandle("view"); HWND hParent = ::GetParent(hWnd); ::SetParent(hWnd, GetDlgItem(IDC_STATIC)->m_hWnd); ::ShowWindow(hParent, SW_HIDE);//隐藏父窗口 HWND hWndDept = (HWND)cvGetWindowHandle("depth"); HWND hParentDept = ::GetParent(hWndDept); ::SetParent(hWndDept, GetDlgItem(IDC_Dept)->m_hWnd); ::ShowWindow(hParentDept, SW_HIDE);//隐藏父窗口
然后深度摄像头获取,和彩色非常相似
void CopentestDlg::OnBnClickedButton5(){ // 打开深度摄像头 //2、定义事件句柄 //创建读取下一帧的信号事件句柄,控制KINECT是否可以开始读取下一帧数据 nextDepthFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //深度图像事件句柄 depthStreamHandle = NULL; //实例打开数据流,这里NUI_IMAGE_TYPE_DEPTH表示深度图像 hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH, NUI_IMAGE_RESOLUTION_640x480, 0, 2, nextDepthFrameEvent, &depthStreamHandle); if (FAILED(hr))//判断是否提取正确 { AfxMessageBox(_T("读取深度错误")); NuiShutdown(); return; } pEdit->ReplaceSel(_T("开始读取kinect深度摄像头数据\r\n")); CRect rect; CWnd *pWnd = GetDlgItem(IDC_Dept); pWnd->GetClientRect(&rect); //获取控件大小 xd = rect.Width(); yd = rect.Height(); SetTimer(3, 25, NULL); //定时器,定时时间和帧率一致}void CopentestDlg::CaptureKinectDepthVideo(){ const NUI_IMAGE_FRAME *pImageFrame_depth = NULL; //深度图像的处理 if (WaitForSingleObject(nextDepthFrameEvent, INFINITE) == 0) { hr = NuiImageStreamGetNextFrame(depthStreamHandle, 0, &pImageFrame_depth); if (FAILED(hr)) { AfxMessageBox(_T("不能读取深度图像")); NuiShutdown(); return ; } INuiFrameTexture * pTexture = pImageFrame_depth->pFrameTexture; NUI_LOCKED_RECT LockedRect; //7.3、提取数据帧到LockedRect,它包括两个数据对象:pitch每行字节数,pBits第一个字节地址 //并锁定数据,这样当我们读数据的时候,kinect就不会去修改它 pTexture->LockRect(0, &LockedRect, NULL, 0); //7.4、确认获得的数据是否有效 if (LockedRect.Pitch != 0) { //7.5、将数据转换为OpenCV的Mat格式 for (int i = 0; i<depthImage.rows; i++) { uchar *ptr = depthImage.ptr(i); //第i行的指针 //每个字节代表一个颜色信息,直接使用uchar uchar *pBuffer = (uchar*)(LockedRect.pBits) + i * LockedRect.Pitch; USHORT *pBufferRun = (USHORT *)pBuffer;//这里需要转换,因为每个深度数据是2个字节,应将BYTE转成USHORT for (int j = 0; j<depthImage.cols; j++) { ptr[j] = 255 - (BYTE)(256 * pBufferRun[j] / 0x1fff); //将数据归一化处理* } } cv::Mat dst; cv::resize(depthImage, dst, cv::Size(xd, yd), 0, 0, 1); cv::imshow("depth", dst); } else { AfxMessageBox(_T("获取数据无效")); } //8、这帧已经处理完了,所以将其解锁 pTexture->UnlockRect(0); //9、释放本帧数据,准备迎接下一帧 NuiImageStreamReleaseFrame(depthStreamHandle, pImageFrame_depth); }}
写一个炫酷的小框框写提示信息
这里用到了Edit Control在工具栏内可以找到,画出来是这样的
然后初始化一下,仍然是写在上面提到的初始化函数中
/*初始化编辑框*/ pEdit = (CEdit*)GetDlgItem(IDC_EDIT1); int nLength = pEdit->GetWindowTextLength(); //选定当前文本的末端 pEdit->SetSel(nLength, nLength);
然后就可以愉快地写内容了
pEdit->ReplaceSel(_T(“打开kinect失败,不能使用kinect读取图像\r\n”));
截图功能
先画一个截图按钮,然后给按钮添加事件处理函数。主要依靠imwrite()函数实现截图并保存的功能
void CopentestDlg::OnBnClickedScreenshot(){ std::string basePath = "./images/"; std::string colorPathPrefix = "Color"; std::string depthPathPrefix = "Depth"; std::string commonPathSuffix = ".jpg"; std::stringstream ss; ss << basePath << count << "-" << colorPathPrefix << commonPathSuffix; std::string colorImagePath = ss.str(); imwrite(colorImagePath, image); std::stringstream ssd; ssd << basePath<<count<<"-" << depthPathPrefix << commonPathSuffix; std::string depthImagePath = ssd.str(); imwrite(depthImagePath, depthImage); count++; pEdit->ReplaceSel(_T("截图成功,已保存到images文件夹中\r\n"));}
程序源码
https://github.com/imcy/kinect
阅读全文
0 0
- kinect+opencv+mfc读取深度和彩色摄像头及截图
- kinect+opencv+mfc读取彩色摄像头
- OpenNI结合OpenCV显示Kinect彩色、深度及融合图像
- opencv2.3读取kinect深度信息和彩色图像
- MFC/OpenCV读取摄像头
- Kinect SDK(1):读取彩色、深度、骨骼信息并用OpenCV显示
- Kinect SDK(1):读取彩色、深度、骨骼信息并用OpenCV显示
- Kinect SDK(1):读取彩色、深度、骨骼信息并用OpenCV显示
- OpenNI+OpenCV对Kinect采集的彩色图和深度图进行滤波
- 用 OpenCV 和OpenNI 2输出kinect 的深度、彩色图
- OpenNI+OpenCV对Kinect采集的彩色图和深度图进行滤波
- MFC利用OpenCV读取摄像头
- Kinect SDK1.0 OpenCV显示彩色、深度、骨骼图
- OpenCV--鼠标响应Kinect彩色图像显示深度信息
- kinect,openni,opencv 获取并显示深度与彩色图像
- Kinect 2 SDK + OpenCV 获取深度彩色图像
- 利用MFC和OpenCV构建GUI程序读取摄像头视频
- win10 64位+Kinect 2.0+VS 2013+opencv开发环境搭建及深度图像读取
- 程序员业余时间修炼指南
- 安卓中相机相册调用总结
- libcoap安装中openssl路径问题
- 加载assetbundle坑记录
- 比较致命的两个错误
- kinect+opencv+mfc读取深度和彩色摄像头及截图
- 给汉字"你" "我" "他" 在Unicode表中的位置(作业)
- netty之事件驱动原理
- 字体图标从下载到使用
- 基于Seq2seq的中文聊天机器人
- 斯坦福大学《机器学习》总结
- 教你如何改变EditText的光标和游标
- NPM
- 【bzoj 1024】生日快乐(dfs)