Kinect+OpenNI學習筆記之12(簡單手勢所表示數字識別) 實驗總結由本次實驗的操作過程可以看出,識別效果抗干擾能力比較差差。因此后續的工作是建立一個手勢識別的數據庫,尋找一個好的手部特征向量,和一個好的分類器。這有可能將是本人研究生畢業論文的研究方向,加油void COpenNICBGestureProgressGestureGenerator generator, const XnChar *strGesture, const XnPoint3D *pPosition, XnFloat fProgress, void *pCookievoid COpenNIHandCreateHandsGenerator rHands, Xreturn hand_generator_;bool COpenNICheckErrorconst char *errorifstatus_ XN_STATUS_OK cerr hand_generator_.StartTracking*pEndPosition;bool COpenNIStartstatus_ context_.StartGeneratingAll;ifCheckErrorStart generating error return false;return true;bool COpenNIUpdateDatastatus_ context_.WaitNoneUpdateAll;if ifCheckErrorCreate hand generaotr error return false;//產生人體 nodestatus_ user_generator_.Createcontext_;ifCheckErrorCreate gesturen generator error return false;//視角校正status_ context_.SetGlobalMirrortrue;//設置鏡像xmode_.nXRes 640;xmode_.nYRes 480;xmode_.nFPS 30;//產生顏色 nodestatus_ image_generator_.Createcontext_;ifCheckErrorCreate image generator error /*手部銷毀的回調函數*/static void XN_CALLBACK_TYPE HandDestroyHandsGenerator rHands, XnUserID xUID, XnFloat fTime, void* pCookie;XnStatus status_;Context context_;XnMapOutputMode xmode_;UserGenerator us stdmap hand_points_; //為了存儲不同手的實時點而設置的stdmap hands_track_points_; //為了繪畫后面不同手部的跟蹤軌跡而設定的private/*該函數返回真代表出現了錯誤,返回假代表正確*/bool CheckErrorconst char* error;/*表示有人體進入的回調函數*/static void XN_CALinclude include include include include include using namespace xn;using namespace std;class COpenNIpublicCOpenNI;COpenNI;/*OpenNI 的內部初始化,屬性設置*/bool Initial;/*啟動 OpenNI 讀取 Kinect 數據*/bo number_result 5;ifnumber_result 0 number_result 1 number_result 2 number_result 3 number_result 4 number_result 5number_result -1;/*在手勢識別圖上顯示匹配的數字*/ circlehand_recognition_image, PointitUser-second.X, itUser-second.Y, 3, Scalar0, 255, 255, 3, 8;circlehand_recognition_image, PointitUser-second.X, itUser-second.Y 25, 3, Sc /*統計在中心點 2 以上凸點的個數*/ifapprox_poly_curvehulli.y SEGMENT_POINT2_DISTANCE dis2 0 convex_assist_above_point2;convex_number_above_point2;// /*對求出的多邊形擬合 findContourshand_segment_mask, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE;//找出 mask 圖像的輪廓Mat hand_recognition_image Matzeroscolor_image.rows, color_image.cols, CV_8UC3;forint i hands_roi.atitUser-first MAX_HANDS_NUMBER.y YRES;imshowcolor image, color_image;/*獲取并顯示深度圖像*/Mat depth_image_srcopenni.depth_metadata_.YRes, openni.depth_metadata_.XRes Mat color_image;cvtColorcolor_image_src, color_image, CV_RGB2BGR;Mat hand_segment_maskcolor_image.size, CV_8UC1, Scalarall0;forauto itUser openni.hand_points_.cbegin; itUser unsigned int point_y1 0;unsigned int point_y2 0;int number_result -1;bool recognition_flag false; //開始手部數字識別的標志vector color_array;//采用默認的 10 種顏色color_array.push_backScalar255, 0, 0;ccopenni 類采用前面博文設計的,這里給出主函數代碼部分。main.cppinclude include opencv2/highgui/highgui.hppinclude opencv2/imgproc/imgproc.hppinclude include copenni.cppinclude define DEPTH_SCALE_FACTOR 255./4 實驗主要部分代碼及注釋本次實驗程序實現過程和上面的系統流程圖類似,大概過程如下1. 求出手部的掩膜2. 求出掩膜的輪廓3. 求出輪廓的多變形擬合曲線4. 求出多邊形擬合曲線的凸包集,找出凸點5. 求出多變形擬合曲線的凹陷集,找出凹點6. 利用上面的凸凹點和手部中心點的幾何關系來做簡單的數字手勢識別 數字“5”的識別結果數字“4”的識別結果數字“3”的識別結果數字“2”的識別結果數字“1”的識別結果參數 3 是一個含有 4 個元素的結構體的集合,如果在 c的版本中,該參數可以直接用 vector來代替,Vec4i 中的 4 個元素分別表示凹陷曲線段的起始坐標索引,終點坐標索引,離凸包集曲線最遠點的坐標索引 以及此時的最遠距離值,這 4 個值都是整數。在 c 版本的 opencv 中一般不是保存的索引,而是坐標值,如下所示struct CvConvexityDefectCvPoin表示在 1969 行的位置出錯,也就是 CV_Assert ptnum 3 ;出錯,說明出錯時此處的 ptnum 3。簡單的說就是用 convexityDefects函數來對多邊形曲線進行凹陷檢測時,必須要求參數 1 曲線本身至少有 2 個點也不知道這樣分析對不 對。因此本人在本次程序 convexityDefects函數前加入了 ifMatapprox_poly_c不過這里需要重新對這 3 個參數做個詳細的說明第 1 個參數雖然寫的是 contour,字面意思是輪廓,但是本人實驗過很多次,發現如果該參數為目標通過輪廓檢測得 到的原始輪廓的話,則程序運行到onvexityDefects函數時會報內存錯誤。因此本程序中采用的不是物體原始的輪廓,而是經過多項式曲線擬合 后的輪廓,即多項式曲線,這樣程序就會順利地運行得很好。http//www.xinxi其中輪廓的提取,多邊形擬合曲線的求法,凸包集和凹陷集的求法都是采用 opencv 中自帶的函數。手勢數字的識別是利用凸包點以及凹陷點和手部 中心點的幾何關系,簡單的做了下邏輯判別了(可以肯定的是這種方法很爛),具體的做法是先在手部定位出 2 個中心點坐標,這 2 個中心點坐標之間的距離閾值由 程序設定,其中一個中心點就是利用 OpenNI 跟蹤得到的手部位置。有了這 2 個中心點的坐標,在程序前言這篇文章是本人玩 kinect 時做的一個小實驗,即不采用機器學習等類似AI 的方法來做簡單的手勢數字識別,當然了,該識別的前提是基于本人前面已提取出手部的博文 Robert Walter 手部提取代碼的分析的基礎上進行的。由于是純數學形狀上來判別手勢,所以只是做了個簡單的 05 的數字識別系統,其手勢的分割部分效果還不錯因為其核心代碼是由 OpenNI 提供的,手勢數字識別時容易受