OpenCV for iOS 3 及 玩转EV3 之: 在iPhone上做手势检测 并控制E

1 前言

去年我做了一段时间iPhone和LEGO EV3 机器人的研究,当时已经开发了iOS的EV3 wifi版SDK,能够使得iOS与EV3进行互动,但这还远远达不到我曾经设想的效果,且看我之前的博文: 【iOS与EV3混合机器人编程系列之一】iOS要干嘛?EV3可以更酷!

iPhone不仅仅要作为EV3 的大脑,还要是EV3的眼睛,脸,还有姿态感觉(陀螺仪)。因此,我之后转向视觉的研究,就是希望使iPhone可以变成EV3的眼睛。

前两篇关于OpenCV for iOS的文章只是分享搭建平台的基本方法,本篇文章将分享更具体的实践,就是用手机的摄像头识别手势,然后控制EV3机器人的行走: 视频链接: ?from=s1.8-1-1.2

这边我暂时不便放出整个程序,但在这里分享我的思路还有一些关键代码。

2 获取视频帧能够进行处理

这个在前面的OpenCV for iOS 2 blog有介绍:

– (void)processImage:(cv::Mat &)image{[self handDetectionWithImage:image];}

这里我把手势检测的放在一个method中进行处理,接下来一步一步介绍手势的处理流程:

OpenCV手势处理流程Step 1:通过HLS颜色获取可能是手的区域并处理

我采用HLS颜色区域来获取皮肤区域,如果是手的话当然就是手的区域。

Mat HLSimage;Mat blurImage;cvtColor(image, HLSimage, CV_BGR2HLS);// Step 1.3:根据皮肤颜色范围获取皮肤区域:int imageRow = HLSimage.rows;int imageCol = HLSimage.cols;for (int row = 0; row < imageRow; row++) {for (int col = 0; col < imageCol; col++) {uchar H = HLSimage.at<cv::Vec3b>(row,col)[0];uchar L = HLSimage.at<cv::Vec3b>(row,col)[1];uchar S = HLSimage.at<cv::Vec3b>(row,col)[2];double LS_ratio = ((double) L) / ((double) S);bool skin_pixel = (S >= 50) && (LS_ratio > 0.5) && (LS_ratio < 3.0) && ((H <= 14) || (H >= 165));if (!skin_pixel) {HLSimage.at<cv::Vec3b>(row,col)[0] = 0;HLSimage.at<cv::Vec3b>(row,col)[1] = 0;HLSimage.at<cv::Vec3b>(row,col)[2] = 0;}}}// Step 1.4: 转换为RGBMat skinImage;cvtColor(HLSimage, skinImage, CV_HLS2RGB);// Step 1.5: 对皮肤区域进行二值及平滑处理Mat gray;cvtColor(skinImage, gray, CV_RGB2GRAY);Mat binary;threshold(gray, binary, 50, 255, THRESH_BINARY);Step 2: 利用YUV的U分量获取轮廓并进行形态学操作利用边缘分离相同颜色区域

比如说手和脸的颜色是一样的,那么用他们的边缘分开,U分量的边缘比较明显:

// Step 2.1:转换为YUVMat yuvImage;cvtColor(image, yuvImage, CV_BGR2YUV);// Step 2.2:取出U分量vector<Mat> yuvImages;split(yuvImage, yuvImages);Mat& uImage = yuvImages[1];// Step 2.3: 形态学梯度操作Mat structure_element(5, 5, CV_8U, Scalar(1));morphologyEx(uImage, uImage, MORPH_GRADIENT, structure_element);threshold(uImage, uImage, 10, 255, THRESH_BINARY_INV|THRESH_OTSU);medianBlur(binary, binary, 5);(int row = 0; row < imageRow; row++) {for (int col = 0; col < imageCol; col++) {binary.at<uchar>(row,col) = uImage.at<uchar>(row,col) & binary.at<uchar>(row,col);}}Step 3 :获取可能是手的轮廓区域并进行处理获得多边形角点 // Step 3.1:寻找轮廓vector<vector<cv::Point>> contours;vector<Vec4i> hierarchy;findContours( binary, contours, hierarchy,CV_RETR_TREE, CV_CHAIN_APPROX_NONE );// Step 3.2:找到最大轮廓int indexOfBiggestContour = -1;int sizeOfBiggestContour = 0;for (int i = 0; i < contours.size(); i++){if(contours[i].size() > sizeOfBiggestContour){sizeOfBiggestContour = int(contours[i].size());indexOfBiggestContour = i;}}// Step 3.3:检查轮廓,获取手的信息if(indexOfBiggestContour > -1 && sizeOfBiggestContour > 400){// 获取轮廓多边形approxPolyDP(Mat(contours[indexOfBiggestContour]), contours[indexOfBiggestContour], 1.5, true);// 获取轮廓矩形框cv::Rect rect = boundingRect(Mat(contours[indexOfBiggestContour]));cv::RotatedRect rotatedRect = fitEllipse(Mat(contours[indexOfBiggestContour]));angle = rotatedRect.angle;power = rotatedRect.size.height/rotatedRect.size.width;//NSLog(@”power:%f angle:%f\n”,power,angle);//ellipse(image, rotatedRect, Scalar(0,0,200));Point2f rect_points[4];rotatedRect.points( rect_points );for( int j = 0; j < 4; j++ )line( image, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,200), 1, 8 );Mat temp = binary;cv::Rect saveRect;if (rect.width > rect.height) {saveRect = cv::Rect(rect.x,rect.y -(rect.width/2 – rect.height/2),rect.width,rect.width);} else {saveRect = cv::Rect(rect.x – (rect.height/2 – rect.width/2),rect.y,rect.height,rect.height);}//tempRect = CGRectMake(saveRect.x, saveRect.y, saveRect.width, saveRect.height);if (saveRect.x >= 0 && saveRect.y >= 0 && saveRect.x+saveRect.width <= temp.cols && saveRect.y+saveRect.height <= temp.rows) {Mat ROIImage;ROIImage = temp(saveRect);CvSize size(96,96);resize(ROIImage, ROIImage, size);tempImage = [self UIImageFromCVMat:ROIImage];rectangle(image, saveRect.tl(), saveRect.br(), Scalar(0,0,200));}// 在image中画出轮廓drawContours(image, contours, indexOfBiggestContour, Scalar(255,100,100));Step 4:获取手指信息人生最大的错误是不断担心会犯错

OpenCV for iOS 3 及 玩转EV3 之: 在iPhone上做手势检测 并控制E

相关文章:

你感兴趣的文章:

标签云: