新开的CSDN 博客。准备开始写点东西
初学CV,翻很多文献。找了很多指尖检测的实例。不懂数学的我其实遇到了很多困难。
主要是从候选点获取指尖的算法上面。鲁棒性好像都不是很好。
关于指尖检测
主要下面两种
1.用Opencv 自带的凸包检测
主要步骤下
1.阈值操作 (一般用 前景检测 或者 肤色检测)
2.寻找轮廓
3.寻找凸包
4.选出指尖
凸包结构的点
1.Start
2.Depth_point
3.End
约束的条件
1.Depth 的角度 < 90 度
2.当前组 Start 点 与上一组 End 点的距离 < 20 (第一组 与 最后一组比较 )
则当前组的start点可以认为是指尖
检测效果如下

2.计算重心到轮廓边缘的距离

主要步骤(16年更新:我之前高中没有学过计算几何方面的内容。之前的代码完全靠想象)
1.阈值操作 (一般用 前景检测 或者 肤色检测)
2.寻找轮廓
3.寻找重心
计算一阶矩
4.列举重心到边缘的距离
5.选出指尖点
网上随便找了一张手的图


做完阈值操作后
寻找轮廓
计算重心的坐标
然后获取重心到轮廓距离。
下面这张图
横坐标是点的顺序
纵坐标是重心到轮廓边缘的距离


可以看出图中有 5 个峰值点。
这五个峰值点表示对应的就是 五个手指的位置。
检测效果图如下


换一张

检测结果还是比较精确的 。大拇指的点可能不满足条件未检测到。
如果用最小二乘拟合峰值附近的点几个点 可以获取亚像素精度的指尖点。
void gethandpoint(Mat frame){ Mat show_img; frame.copyTo(show_img); Mat derivative_img=cvCreateMat(300,900,show_img.type()); derivative_img.setTo(255); GaussianBlur(frame, frame, Size(3, 3), 0); threshold(frame,frame,240,255,THRESH_BINARY_INV); vector<vector<Point> > contours; vector<Vec4i> hierarchy; findContours(frame, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); //获取轮廓 int index; double area, maxArea(0); for (int i=0; i < contours.size(); i++) { area = contourArea(Mat(contours[i])); if (area > maxArea) { maxArea = area; index = i; } } //drawContours(frame, contours, index, Scalar(0, 0, 255), 2, 8, hierarchy ); Moments moment = moments(frame, true); Point center(moment.m10/moment.m00, moment.m01/moment.m00); //获取重心 //circle(show_img, center, 8 ,Scalar(0, 0, 255), CV_FILLED); vector<Point> couPoint = contours[index]; float current(0), depth(50000),mosthigher(0); //count Num int q(0),m(0),k(0),j(0),notice(0),spos(0); Point fingerTips_single; Point p, n, r; for(int i=1;i < couPoint.size();i++){ float pn = sqrt(float((couPoint[i].x - center.x) * (couPoint[i].x - center.x) + (couPoint[i].y - center.y) * (couPoint[i].y - center.y)) ); //计算重心到轮廓边缘的距离 line(derivative_img,cvPoint(i,300),cvPoint(i,300-pn/3),Scalar(0,0,0,0)); //line(show_img,couPoint[i],center,Scalar(0,0,0,0)); //cout<<int(pn)<<endl; if (pn>=current) { current=pn;//找出第一次的峰值 } else { m++; if(m ==1 ){ notice=i; fingerTips_single=couPoint[i]; depth=; } if (depth>=pn) { depth=pn; k++; //从峰值向下开始爬。 } else { if(k>20) { //如果爬的步长 > 20 则认为是指尖的候选点。 // spos=notice; if(notice<10) { notice= 10; } //更进一步的获取精确的指尖位置 枚举候选点周围的 10 个点 选出距离重心最大的点 for (int k = notice-10;k<notice+10;k++) { current = sqrt(float((couPoint[k].x - center.x) * (couPoint[k].x - center.x) + (couPoint[k].y - center.y) * (couPoint[k].y - center.y)) ); if(current>mosthigher){ mosthigher = current; spos = k ; } } mosthigher=0; fingerTips_single =couPoint[spos]; //获得的指尖 cout<<"["<<fingerTips_single.x<<","<<fingerTips_single.y<<"]"<<endl; circle(show_img,couPoint[spos],3,Scalar(0,0,0,0),5,CV_AA); } current=0 ; m=0; k=0; k=0; } } //waitKey(0); } imshow("hand",show_img); imshow("derivative_img",derivative_img); }
讯享网
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/53813.html