kinect1.0+opencv3.4实时获取深度以及彩色图像并进行边缘检测

标题毕业设计接到关于kinect牛体尺识别的题目,自身对于机器视觉这块可以说是菜鸡一枚 ,于是网上各种搜集相关资料,先是对opencv相关知识进行一个大概的了解,然后就是硬着头皮上了,为了毕业,豁出去了。。。

论坛上关于kinect1.0实时获取轮廓相关c++开发的例程少之又少,在浏览论坛上前辈们的代码之后,稍加改动就进行测试,结果如下: 对深度图以及彩色图进行canny算法边缘检测 这里插入图片描述 在此附上代码:

#include <windows.h>
#include <iostream> 
#include <NuiApi.h>
#include <opencv2/opencv.hpp>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>


using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
	Mat color_image;
	Mat depth_image;

	Mat image_gray, image_edge;
	
	color_image.create(480, 640, CV_8UC3);
	depth_image.create(480, 640, CV_8UC1);

	HRESULT hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_DEPTH|NUI_INITIALIZE_FLAG_USES_COLOR);

	if (FAILED(hr))
	{
		cout << "NuiInitialize failed" << endl;
		return hr;
	}

	HANDLE nextColorFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	HANDLE colorStreamHandle = NULL;

	HANDLE nextDepthFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	HANDLE depthStreamHandle = NULL;

	hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, nextColorFrameEvent, &colorStreamHandle);
	if (FAILED(hr))
	{
		cout << "Could not open color image stream video" << endl;
		NuiShutdown();
		return hr;
	}
	namedWindow("colorImage", CV_WINDOW_AUTOSIZE);



	hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH, NUI_IMAGE_RESOLUTION_640x480, 0, 2, nextDepthFrameEvent, &depthStreamHandle);
	if (FAILED(hr))
	{
		cout << "Could not open depth image stream video" << endl;
		NuiShutdown();
		return hr;
	}
	namedWindow("depthImage", CV_WINDOW_AUTOSIZE);



	while (1)
	{
		const NUI_IMAGE_FRAME * pColorImageFrame = NULL;
		const NUI_IMAGE_FRAME * pDepthImageFrame = NULL;

		if (WaitForSingleObject(nextColorFrameEvent, INFINITE) == 0)
		{
			//4.2、从刚才打开数据流的流句柄中得到该帧数据,读取到的数据地址存于pImageFrame
			hr = NuiImageStreamGetNextFrame(colorStreamHandle, 0, &pColorImageFrame);
			if (FAILED(hr))
			{
				cout << "Could not get color image" << endl;
				NuiShutdown();
				return -1;
			}

			INuiFrameTexture * pTexture = pColorImageFrame->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<color_image.rows; i++)
				{
					uchar *ptr = color_image.ptr<uchar>(i);  //第i行的指针

															//每个字节代表一个颜色信息,直接使用uchar
					uchar *pBuffer = (uchar*)(LockedRect.pBits) + i * LockedRect.Pitch;
					for (int j = 0; j<color_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];
						
					}
				}


				cvtColor(color_image, image_gray, CV_BGR2GRAY);
				GaussianBlur(image_gray, image_gray, Size(7, 7), 1.5, 1.5);
				Canny(image_gray, image_gray, 0, 30, 3);

				imshow(" color_image", image_gray); //显示图像 

			}
			
			else
			{
				cout << "Buffer length of received texture is bogus\r\n" << endl;
			}
			pTexture->UnlockRect(0);
			NuiImageStreamReleaseFrame(colorStreamHandle, pColorImageFrame);
		}

		


		if (WaitForSingleObject(nextDepthFrameEvent, INFINITE) == 0)
		{
			
			hr = NuiImageStreamGetNextFrame(depthStreamHandle, 0, &pDepthImageFrame);
			if (FAILED(hr))
			{
				cout << "Could not get depth image" << endl;
				NuiShutdown();
				return -1;
			}

			INuiFrameTexture * pTexture = pDepthImageFrame->pFrameTexture;
			NUI_LOCKED_RECT LockedRect;

			pTexture->LockRect(0, &LockedRect, NULL, 0);
	
			if (LockedRect.Pitch != 0)
			{
				
				for (int i = 0; i<depth_image.rows; i++)
				{
					uchar *ptr = depth_image.ptr<uchar>(i);  //第i行的指针

															 //深度图像数据含有两种格式,这里像素的低12位表示一个深度值,高4位未使用;
															 //注意这里需要转换,因为每个数据是2个字节,存储的同上面的颜色信息不一样,
					uchar *pBufferRun = (uchar*)(LockedRect.pBits) + i * LockedRect.Pitch;
					USHORT * pBuffer = (USHORT*)pBufferRun;

					for (int j = 0; j<depth_image.cols; j++)
					{

						ptr[j] = 255 - (uchar)(256 * pBuffer[j] / 0x0fff);  //直接将数据归一化处理
					}
				}
				//cout << "均值: " << (sum/a++) << endl;


				blur(depth_image, depth_image, Size(7, 7));
				Canny(depth_image, depth_image, 5, 100);
				imshow("depthImage", depth_image);//显示图像 

			}
			else
			{
				cout << "Buffer length of received texture is bogus\r\n" << endl;
			}
			//5、这帧已经处理完了,所以将其解锁
			pTexture->UnlockRect(0);
			//6、释放本帧数据,准备迎接下一帧 
			NuiImageStreamReleaseFrame(depthStreamHandle, pDepthImageFrame);
		}


		if (cvWaitKey(20) == 27)
			break;
	}


	//7、关闭NUI链接 
	NuiShutdown();
	return 0;
}













//老毛桃一键还原,安全高效 稳定可靠 全面兼容WINDOWS系统。本程序基于Ghost(v11.02)内核,具有良好的安全和稳定性,真正达到快速备份还原;全面支持和兼容32位和64位的Windows等主流操作系统平台,支持最新的Windows7操作系统,Vista、XP、2000、2003等更不在话下;支持备份还原隐藏分区,大大降低被误删除或被破坏的可能性,使您无后顾之忧。
http://www.laomaotao.net/?O1527


//#include <opencv2/opencv.hpp>
//#include <iostream>
//using namespace std;
//using namespace cv;
//
//static void help() 
//{
//	cout << "usage:hit any key to quit!" << endl
//		<< "kinect opening..." << endl;
//}
//
//int main(int argc, char** argv) 
//{
//
//	help();
//
//	VideoCapture capture(CV_CAP_OPENNI);
//
//	if (!capture.isOpened()) {
//		cerr << "no device has derected!" << endl;
//		return -1;
//	}
//	cout << "width" << capture.get(CV_CAP_PROP_FRAME_WIDTH) << endl
//		<< "heigth" << capture.get(CV_CAP_PROP_FRAME_HEIGHT) << endl;
//
//	std::string rgb_wnd = "RGB Camera";
//	std::string depth_wnd = "Depth Camera";
//	namedWindow(rgb_wnd, CV_WINDOW_AUTOSIZE);
//	namedWindow(depth_wnd, CV_WINDOW_AUTOSIZE);
//
//	for (;;) {
//		Mat depthMap;
//		Mat rgbImage;
//
//		capture.grab();
//
//		//depthMap XYZ in meters (CV_32FC3),xyz就是获取的点云中每一点的空间位置
//		capture.retrieve(depthMap, CV_CAP_OPENNI_POINT_CLOUD_MAP);
//
//		//color image (CV_8UC3)
//		capture.retrieve(rgbImage, CV_CAP_OPENNI_BGR_IMAGE);
//
//		imshow(rgb_wnd, rgbImage);
//		imshow(depth_wnd, depthMap);
//
//		if (waitKey(30) >= 0) {
//			break;
//		}
//	}
//	return 0;
//}













//#include <Windows.h>
//#include "NuiApi.h"
//#include <opencv2\opencv.hpp>  
//#include<iostream>
//#include <d3d11.h>
//
//using namespace std;
//using namespace cv;
//
//const int MAX_DISTANCE = 3500;
//const int MIN_DISTANCE = 200;
//
//const LONG m_depthWidth = 640;
//const LONG m_depthHeight = 480;
//
//const LONG m_colorWidth = 640;
//const LONG m_colorHeight = 480;
//const LONG cBytesPerPixel = 4;
//
//int main()
//{
//	Mat image_rgb;
//	Mat image_depth;
//
//	image_rgb.create(480, 640, CV_8UC3);
//	image_depth.create(480, 640, CV_8UC1);
//	INuiSensor*  m_pNuiSensor = NULL;
//	if (m_pNuiSensor != NULL)
//	{
//		return 0;
//	}
//
//	int iSensorCount;
//	HRESULT hr = NuiGetSensorCount(&iSensorCount);
//
//	hr = NuiCreateSensorByIndex(iSensorCount - 1, &m_pNuiSensor);
//
//	hr = m_pNuiSensor->NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH);
//
//	//判断是否出错
//	if (FAILED(hr))
//	{
//		cout << "NuiInitialize failed" << endl;
//		return hr;
//	}
//
//	//彩色图像获取下一帧事件
//	HANDLE nextColorFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//	//彩色图像事件句柄
//	HANDLE colorStreamHandle = NULL;
//	//深度图像获取下一帧事件
//	HANDLE nextDepthFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//	//深度图像事件句柄
//	HANDLE depthStreamHandle = NULL;
//
//	//实例打开数据流,这里NUI_IMAGE_TYPE_COLOR表示彩色图像
//	hr = m_pNuiSensor->NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, nextColorFrameEvent, &colorStreamHandle);
//
//	if (FAILED(hr))//判断是否提取正确
//	{
//		cout << "Could not open color image stream video" << endl;
//		m_pNuiSensor->NuiShutdown();
//		return hr;
//	}
//
//	//实例打开数据流,这里NUI_IMAGE_TYPE_DEPTH表示深度图像
//	hr = m_pNuiSensor->NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH, NUI_IMAGE_RESOLUTION_640x480, 0, 2, nextDepthFrameEvent, &depthStreamHandle);
//
//	if (FAILED(hr))//判断是否提取正确
//	{
//		cout << "Could not open color image stream video" << endl;
//		m_pNuiSensor->NuiShutdown();
//		return hr;
//	}
//
//
//
//	cv::namedWindow("depth", CV_WINDOW_AUTOSIZE);
//	moveWindow("depth", 300, 600);
//	cv::namedWindow("colorImage", CV_WINDOW_AUTOSIZE);
//	moveWindow("colorImage", 0, 200);
//
//	while (1)
//	{
//		NUI_IMAGE_FRAME pImageFrame_rgb;
//		NUI_IMAGE_FRAME pImageFrame_depth;
//
//		//无限等待新的彩色数据,等到后返回
//		if (WaitForSingleObject(nextColorFrameEvent, 0) == 0)
//		{
//			//从刚才打开数据流的流句柄中得到该帧数据,读取到的数据地址存于pImageFrame
//			hr = m_pNuiSensor->NuiImageStreamGetNextFrame(colorStreamHandle, 0, &pImageFrame_rgb);
//			if (FAILED(hr))
//			{
//				cout << "Could not get color image" << endl;
//				m_pNuiSensor->NuiShutdown();
//				return -1;
//			}
//
//			INuiFrameTexture *pTexture = pImageFrame_rgb.pFrameTexture;
//			NUI_LOCKED_RECT lockedRect;
//
//			//提取数据帧到LockedRect,它包括两个数据对象:pitch每行字节数,pBits第一个字节地址
//			//并锁定数据,这样当我们读数据的时候,kinect就不会去修改它
//
//
//			pTexture->LockRect(0, &lockedRect, NULL, 0);
//			//确认获得的数据是否有效
//			if (lockedRect.Pitch != 0)
//			{
//				//将数据转换为OpenCV的Mat格式
//				for (int i = 0; i < image_rgb.rows; i++)
//				{
//					//第i行的指针
//					uchar *prt = image_rgb.ptr(i);
//
//					//每个字节代表一个颜色信息,直接使用uchar
//					uchar *pBuffer = (uchar*)(lockedRect.pBits) + i * lockedRect.Pitch;
//
//					for (int j = 0; j < image_rgb.cols; j++)
//					{
//						prt[3 * j] = pBuffer[4 * j];//内部数据是4个字节,0-1-2是BGR,第4个现在未使用
//						prt[3 * j + 1] = pBuffer[4 * j + 1];
//						prt[3 * j + 2] = pBuffer[4 * j + 2];
//					}
//				}
//
//				imshow("colorImage", image_rgb);
//				//解除锁定
//				pTexture->UnlockRect(0);
//				//释放帧
//				m_pNuiSensor->NuiImageStreamReleaseFrame(colorStreamHandle, &pImageFrame_rgb);
//			}
//			else
//			{
//				cout << "Buffer length of received texture is bogus\r\n" << endl;
//			}
//
//			BOOL nearMode;
//			INuiFrameTexture* pColorToDepthTexture;
//
//
//			//深度图像的处理
//			if (WaitForSingleObject(nextDepthFrameEvent, INFINITE) == 0)
//			{
//
//				hr = m_pNuiSensor->NuiImageStreamGetNextFrame(depthStreamHandle, 0, &pImageFrame_depth);
//
//				if (FAILED(hr))
//				{
//					cout << "Could not get color image" << endl;
//					NuiShutdown();
//					return -1;
//				}
//
//				hr = m_pNuiSensor->NuiImageFrameGetDepthImagePixelFrameTexture(depthStreamHandle, &pImageFrame_depth, &nearMode, &pColorToDepthTexture);
//				INuiFrameTexture *pTexture = pImageFrame_depth.pFrameTexture;
//				NUI_LOCKED_RECT lockedRect;
//				NUI_LOCKED_RECT ColorToDepthLockRect;
//
//				pTexture->LockRect(0, &lockedRect, NULL, 0);
//				pColorToDepthTexture->LockRect(0, &ColorToDepthLockRect, NULL, 0);
//
//				for (int i = 0; i < image_depth.rows; i++)
//				{
//					uchar *prt = image_depth.ptr<uchar>(i);
//
//					uchar* pBuffer = (uchar*)(lockedRect.pBits) + i * lockedRect.Pitch;
//					//这里需要转换,因为每个深度数据是2个字节,应将BYTE转成USHORT
//					USHORT *pBufferRun = (USHORT*)pBuffer;
//
//					for (int j = 0; j < image_depth.cols; j++)
//					{
//						//先向,将数据归一化处理,对深度距离在300mm-3500mm范围内的像素,映射到【0—255】内,
//						//超出范围的,都去做是边缘像素
//						if (pBufferRun[j] << 3 > MAX_DISTANCE) prt[j] = 255;
//						else if (pBufferRun[j] << 3 < MIN_DISTANCE) prt[j] = 0;
//						else prt[j] = (BYTE)(256 * (pBufferRun[j] << 3) / MAX_DISTANCE);
//					}
//				}
//				imshow("depth", image_depth);
//
//
//
//				//接下来是对齐部分,将前景抠出来
//
//				//存放深度点的参数
//				NUI_DEPTH_IMAGE_POINT* depthPoints = new NUI_DEPTH_IMAGE_POINT[640 * 480];
//				if (ColorToDepthLockRect.Pitch != 0)
//				{
//					HRESULT hrState = S_OK;
//
//					//一个能在不同空间坐标转变的类(包括:深度,彩色,骨骼)
//					INuiCoordinateMapper* pMapper;
//
//					//设置KINECT实例的空间坐标系
//					hrState = m_pNuiSensor->NuiGetCoordinateMapper(&pMapper);
//
//					if (FAILED(hrState))
//					{
//						return hrState;
//					}
//
//					//重要的一步:从颜色空间映射到深度空间。参数说明:
//					//【参数1】:彩色图像的类型
//					//【参数2】:彩色图像的分辨率
//					//【参数3】:深度图像的分辨率
//					//【参数4】:深度图像的个数
//					//【参数5】:深度像素点数
//					//【参数6】:取内存的大小,个数。类型为NUI_DEPTH_IMAGE_PIXEL
//					//【参数7】:存放映射结果点的参数
//					hrState = pMapper->MapColorFrameToDepthFrame(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, NUI_IMAGE_RESOLUTION_640x480,
//						640 * 480, (NUI_DEPTH_IMAGE_PIXEL*)ColorToDepthLockRect.pBits, 640 * 480, depthPoints);
//
//					if (FAILED(hrState))
//					{
//						return hrState;
//					}
//
//
//					//显示的图像
//					Mat show;
//					show.create(480, 640, CV_8UC3);
//					show = 0;
//
//					for (int i = 0; i < image_rgb.rows; i++)
//					{
//						for (int j = 0; j < image_rgb.cols; j++)
//						{
//							uchar *prt_rgb = image_rgb.ptr(i);
//							uchar *prt_show = show.ptr(i);
//							//在内存中偏移量
//							long index = i * 640 + j;
//							//从保存了映射坐标的数组中获取点
//							NUI_DEPTH_IMAGE_POINT depthPointAtIndex = depthPoints[index];
//
//							//边界判断
//							if (depthPointAtIndex.x >= 0 && depthPointAtIndex.x < image_depth.cols &&
//								depthPointAtIndex.y >= 0 && depthPointAtIndex.y < image_depth.rows)
//							{
//								//深度判断,在MIN_DISTANCE与MAX_DISTANCE之间的当成前景,显示出来
//								//这个使用也很重要,当使用真正的深度像素点再在深度图像中获取深度值来判断的时候,会出错
//								if (depthPointAtIndex.depth >= MIN_DISTANCE && depthPointAtIndex.depth <= MAX_DISTANCE)
//								{
//									prt_show[3 * j] = prt_rgb[j * 3];
//									prt_show[3 * j + 1] = prt_rgb[j * 3 + 1];
//									prt_show[3 * j + 2] = prt_rgb[j * 3 + 2];
//								}
//							}
//						}
//					}
//					imshow("show", show);
//				}
//
//				delete[]depthPoints;
//
//				pTexture->UnlockRect(0);
//				m_pNuiSensor->NuiImageStreamReleaseFrame(depthStreamHandle, &pImageFrame_depth);
//			}
//
//			else
//			{
//				cout << "Buffer length of received texture is bogus\r\n" << endl;
//			}
//		}
//
//		if (cvWaitKey(20) == 27)
//			break;
//	}
//	return 0;
//}

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值