ImageVerifierCode 换一换
格式:DOCX , 页数:16 ,大小:90.98KB ,
资源ID:6787861      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/6787861.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Kinect+OpenNI学习笔记之9不需要骨骼跟踪的人体手部分割.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Kinect+OpenNI学习笔记之9不需要骨骼跟踪的人体手部分割.docx

1、Kinect+OpenNI学习笔记之9不需要骨骼跟踪的人体手部分割Kinect+OpenNI学习笔记之9(不需要骨骼跟踪的人体手部分割)前言手势识别非常重要的一个特点是要体验要好,即需要以用户为核心。而手势的定位一般在手势识别过程的前面,在上一篇博文Kinect+OpenNI学习笔记之8(Robert Walter手部提取代码的分析)中已经介绍过怎样获取手势区域,且取得了不错的效果,但是那个手势部位的提取有一个大的缺点,即需要人站立起来,当站立起来后才能够分隔出手。而手势在人之间的交流时,并不一定要处于站立状态,所以这不是一个好的HCI。因此本文介绍的手势部位的提取并不需要人处于站立状态,同样

2、取得了不错的效果。实验说明其实,本实验实现的过程非常简单。首先通过手部的跟踪来获取手所在的坐标,手部跟踪可以参考本人前面的博文:Kinect+OpenNI学习笔记之7(OpenNI自带的类实现手部跟踪)。当定位到手所在的坐标后,因为该坐标是3D的,因此在该坐标领域的3维空间领域内提取出手的部位即可,整个过程的大概流程图如下:OpenCV知识点总结:调用Mat:copyTo()函数时,如果需要有mask操作,则不管源图像是多少通道的,其mask矩阵都要定义为单通道,另外可以对一个mask矩阵画一个填充的矩形来达到使mask矩阵中对应ROI的位置的值为设定值,这样就不需要去一一扫描赋值了。在使用O

3、penCV的Mat矩阵且需要对该矩阵进行扫描时,一定要注意其取值顺序,比如说列和行的顺序,如果弄反了,则经常会报内存错误。实验结果本实验并不要求人的手一定要放在人体的前面,且也不需要人一定是处在比较简单的背景环境中,本实验结果允许人处在复杂的背景环境下,且手可以到处随便移动。当然了,环境差时有时候效果就不太好。下面是3张实验结果的截图,手势分隔图1:手势分隔图2:手势分隔图3:实验主要部分代码即注释(附录有工程code下载链接):main.cpp:#include #include opencv2/highgui/highgui.hpp#include opencv2/imgproc/imgp

4、roc.hpp#include #include copenni.cpp#include #define DEPTH_SCALE_FACTOR 255./4096.#define ROI_HAND_WIDTH 140#define ROI_HAND_HEIGHT 140#define MEDIAN_BLUR_K 5int XRES = 640;int YRES = 480;#define DEPTH_SEGMENT_THRESH 5using namespace cv;using namespace xn;using namespace std;int main (int argc, char

5、 *argv) COpenNI openni; int hand_depth; Rect roi; roi.x = XRES/2; roi.y = YRES/2; roi.width = ROI_HAND_WIDTH; roi.height = ROI_HAND_HEIGHT; if(!openni.Initial() return 1; namedWindow(color image, CV_WINDOW_AUTOSIZE); namedWindow(depth image, CV_WINDOW_AUTOSIZE); namedWindow(hand_segment, CV_WINDOW_A

6、UTOSIZE);/显示分割出来的手的区域 if(!openni.Start() return 1; while(1) if(!openni.UpdateData() return 1; /*获取并显示色彩图像*/ Mat color_image_src(openni.image_metadata.YRes(), openni.image_metadata.XRes(), CV_8UC3, (char *)openni.image_metadata.Data(); Mat color_image; cvtColor(color_image_src, color_image, CV_RGB2BG

7、R); circle(color_image, Point(hand_point.X, hand_point.Y), 5, Scalar(255, 0, 0), 3, 8); imshow(color image, color_image); /*获取并显示深度图像*/ Mat depth_image_src(openni.depth_metadata.YRes(), openni.depth_metadata.XRes(), CV_16UC1, (char *)openni.depth_metadata.Data();/因为kinect获取到的深度图像实际上是无符号的16位数据 Mat de

8、pth_image; depth_image_src.convertTo(depth_image, CV_8U, DEPTH_SCALE_FACTOR); imshow(depth image, depth_image); /*下面的代码是提取手的轮廓部分*/ hand_depth = hand_point.Z * DEPTH_SCALE_FACTOR; roi.x = hand_point.X - ROI_HAND_WIDTH/2; roi.y = hand_point.Y - ROI_HAND_HEIGHT/2; if(roi.x = XRES) roi.x = XRES; if(roi.

9、y = YRES) roi.y = YRES; /取出手的mask部分 /不管原图像时多少通道的,mask矩阵声明为单通道就ok Mat hand_segment_mask(depth_image.size(), CV_8UC1, Scalar:all(0); for(int i = roi.x; i std:min(roi.x+roi.width, XRES); i+) for(int j = roi.y; j std:min(roi.y+roi.height, YRES); j+) hand_segment_mask.at(j, i) = (hand_depth-DEPTH_SEGMENT

10、_THRESH) depth_image.at(j, i) & (hand_depth+DEPTH_SEGMENT_THRESH) depth_image.at(j,i); medianBlur(hand_segment_mask, hand_segment_mask, MEDIAN_BLUR_K); Mat hand_segment(color_image.size(), CV_8UC3); color_image.copyTo(hand_segment, hand_segment_mask); imshow(hand_segment, hand_segment); waitKey(20);

11、 copenni,cpp:#ifndef COPENNI_CLASS#define COPENNI_CLASS#include #include #include using namespace xn;using namespace std;static DepthGenerator depth_generator;static HandsGenerator hands_generator;static XnPoint3D hand_point;static std:mapXnUserID, vector hands_track_points;class COpenNIpublic: COpe

12、nNI() context.Release();/释放空间 bool Initial() /初始化 status = context.Init(); if(CheckError(Context initial failed!) return false; context.SetGlobalMirror(true);/设置镜像 xmode.nXRes = 640; xmode.nYRes = 480; xmode.nFPS = 30; /产生颜色node status = image_generator.Create(context); if(CheckError(Create image ge

13、nerator error!) return false; /设置颜色图片输出模式 status = image_generator.SetMapOutputMode(xmode); if(CheckError(SetMapOutputMdoe error!) return false; /产生深度node status = depth_generator.Create(context); if(CheckError(Create depth generator error!) return false; /设置深度图片输出模式 status = depth_generator.SetMapO

14、utputMode(xmode); if(CheckError(SetMapOutputMdoe error!) return false; /产生手势node status = gesture_generator.Create(context); if(CheckError(Create gesture generator error!) return false; /*添加手势识别的种类*/ gesture_generator.AddGesture(Wave, NULL); gesture_generator.AddGesture(click, NULL); gesture_generat

15、or.AddGesture(RaiseHand, NULL); gesture_generator.AddGesture(MovingHand, NULL); /产生手部的node status = hands_generator.Create(context); if(CheckError(Create hand generaotr error!) return false; /产生人体node status = user_generator.Create(context); if(CheckError(Create gesturen generator error!) return fal

16、se; /视角校正 status = depth_generator.GetAlternativeViewPointCap().SetViewPoint(image_generator); if(CheckError(Cant set the alternative view point on depth generator!) return false; /设置与手势有关的回调函数 XnCallbackHandle gesture_cb; gesture_generator.RegisterGestureCallbacks(CBGestureRecognized, CBGestureProg

17、ress, NULL, gesture_cb); /设置于手部有关的回调函数 XnCallbackHandle hands_cb; hands_generator.RegisterHandCallbacks(HandCreate, HandUpdate, HandDestroy, NULL, hands_cb); /设置有人进入视野的回调函数 XnCallbackHandle new_user_handle; user_generator.RegisterUserCallbacks(CBNewUser, NULL, NULL, new_user_handle); user_generator.

18、GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_ALL);/设定使用所有关节(共15个) /设置骨骼校正完成的回调函数 XnCallbackHandle calibration_complete; user_generator.GetSkeletonCap().RegisterToCalibrationComplete(CBCalibrationComplete, NULL, calibration_complete); return true; bool Start() status = context.StartGeneratingA

19、ll(); if(CheckError(Start generating error!) return false; return true; bool UpdateData() status = context.WaitNoneUpdateAll(); if(CheckError(Update date error!) return false; /获取数据 image_generator.GetMetaData(image_metadata); depth_generator.GetMetaData(depth_metadata); return true; /得到色彩图像的node Im

20、ageGenerator& getImageGenerator() return image_generator; /得到深度图像的node DepthGenerator& getDepthGenerator() return depth_generator; /得到人体的node UserGenerator& getUserGenerator() return user_generator; /得到手势姿势node GestureGenerator& getGestureGenerator() return gesture_generator; public: DepthMetaData d

21、epth_metadata; ImageMetaData image_metadata;/ static std:mapXnUserID, vector hands_track_points;private: /该函数返回真代表出现了错误,返回假代表正确 bool CheckError(const char* error) if(status != XN_STATUS_OK ) /QMessageBox:critical(NULL, error, xnGetStatusString(status); cerr error : xnGetStatusString( status ) hands_

22、generator.StartTracking(*pIDPosition); hands_generator.StartTracking(*pIDPosition); /手势开始检测的回调函数 static void XN_CALLBACK_TYPE CBGestureProgress(xn:GestureGenerator &generator, const XnChar *strGesture, const XnPoint3D *pPosition, XnFloat fProgress, void *pCookie) / COpenNI *openni = (COpenNI*)pCooki

23、e; / openni-hands_generator.StartTracking(*pPosition); hands_generator.StartTracking(*pPosition); /手部开始建立的回调函数 static void XN_CALLBACK_TYPE HandCreate(HandsGenerator& rHands, XnUserID xUID, const XnPoint3D* pPosition, XnFloat fTime, void* pCookie) / COpenNI *openni = (COpenNI*)pCookie; XnPoint3D pro

24、ject_pos; depth_generator.ConvertRealWorldToProjective(1, pPosition, &project_pos); / openni-hand_point = project_pos; /返回手部所在点的位置 hand_point = project_pos; pairXnUserID, vector hand_track_point(xUID, vector(); hand_track_point.second.push_back(project_pos); hands_track_points.insert(hand_track_poin

25、t); /手部开始更新的回调函数 static void XN_CALLBACK_TYPE HandUpdate(HandsGenerator& rHands, XnUserID xUID, const XnPoint3D* pPosition, XnFloat fTime, void* pCookie) / COpenNI *openni = (COpenNI*)pCookie; XnPoint3D project_pos; depth_generator.ConvertRealWorldToProjective(1, pPosition, &project_pos); / openni-h

26、and_point = project_pos; /返回手部所在点的位置 hand_point = project_pos; hands_track_points.find(xUID)-second.push_back(project_pos); /销毁手部的回调函数 static void XN_CALLBACK_TYPE HandDestroy(HandsGenerator& rHands, XnUserID xUID, XnFloat fTime, void* pCookie) / COpenNI *openni = (COpenNI*)pCookie; /openni-hand_poi

27、nt.clear(); /返回手部所在点的位置 hands_track_points.erase(hands_track_points.find(xUID); /有人进入视野时的回调函数 static void XN_CALLBACK_TYPE CBNewUser(UserGenerator &generator, XnUserID user, void *p_cookie) /得到skeleton的capability,并调用RequestCalibration函数设置对新检测到的人进行骨骼校正 generator.GetSkeletonCap().RequestCalibration(us

28、er, true); /完成骨骼校正的回调函数 static void XN_CALLBACK_TYPE CBCalibrationComplete(SkeletonCapability &skeleton, XnUserID user, XnCalibrationStatus calibration_error, void *p_cookie) if(calibration_error = XN_CALIBRATION_STATUS_OK) skeleton.StartTracking(user);/骨骼校正完成后就开始进行人体跟踪了 else UserGenerator *p_user = (UserGenerator*)p_cookie; skeleton.RequestCalibration(user, true);/骨骼校正失败时重新设置对人体骨骼继续进行校正 private: XnStatus status; Context context;

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1