概述
标题毕业设计接到关于kinect牛体尺识别的题目,自身对于机器视觉这块可以说是菜鸡一枚 ,于是网上各种搜集相关资料,先是对opencv相关知识进行一个大概的了解,然后就是硬着头皮上了,为了毕业,豁出去了。。。
论坛上关于kinect1.0实时获取轮廓相关c++开发的例程少之又少,在浏览论坛上前辈们的代码之后,稍加改动就进行测试,结果如下: 在此附上代码:
#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 bogusrn" << 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 bogusrn" << 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 <opencv2opencv.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 bogusrn" << 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 bogusrn" << endl;
// }
// }
//
// if (cvWaitKey(20) == 27)
// break;
// }
// return 0;
//}
最后
以上就是端庄冰淇淋为你收集整理的kinect1.0+opencv3.4实时获取深度以及彩色图像并进行边缘检测的全部内容,希望文章能够帮你解决kinect1.0+opencv3.4实时获取深度以及彩色图像并进行边缘检测所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复