基于distanceTransform-距离变换的区域中心提取
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于distanceTransform-距离变换的区域中心提取
这几天在做一个手势识别的项目,其中最的关键一步是提取手掌中心。获得手掌重心通常的做法是计算整个手部的重心,并以该重心位置近似手掌重心,这种方法只适用于没有手指伸出或只有一个手指伸出的情况,否则获得的手掌重心位置将严重偏离真实位置。
距离变换的基本含义是计算一个图像中非零像素点到最近的零像素点的距离,也就是到零像素点的最短距离。因此可以基于距离变换提取手掌重心。
算法基本思想:
(1)将手掌图像二值化,手掌内的区域设为白色,外部区域设为黑色。
(2)将二值化后的图像经过distanceTransform变换,得到dist_image,其中每个像素点的值是该像素点到其最近的零像素点的距离。
(3)找到dist_image的最大值(即圆的半径R),并记录下位置(即圆心坐标)。
代码如下:
[cpp] view plaincopy#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp> #include
<opencv2/highgui/highgui.hpp> #include
<opencv2/imgproc/imgproc.hpp> #include
<vector> using namespace cv; using namespace std; pair<Point,double> DetectInCircles(vector<Point> contour,Mat src)
{ Mat dist_image;
distanceTransform(src,dist_image,CV_DIST_L2,3);
int temp=0,R=0,cx=0,cy=0; int d; for (int
i=0;i<src.rows;i++) for (int j=0;j<src.cols;j++) { /* checks if the point is inside the contour. Optionally computes the signed distance from the point to the contour boundary*/ d = pointPolygonTest(contour, Point2f(j, i), 0); if (d>0)
{ temp=(int)dist_image.ptr<float>(i )[j]; if (temp>R)
{ R=temp;
cy=i;
cx=j; }
} }
return make_pair(Point(cx,cy),R); } int main() { // Read input binary image
Mat src= imread("D:\\mycode\\6.jpg",1); Mat image; cvtColor(src,image,CV_BGR2GRAY);
vector<vector<Point>> contours;
//findContours的输入是二值图像
findContours(image, contours, // a vector of contours CV_RETR_EXTERNAL, // retrieve the external contours
CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours // Print contours' length轮廓的个数cout << "Contours: " << contours.size() << endl; vector<vector<Point>>::const_iterator
itContours= contours.begin(); for ( ;
itContours!=contours.end(); ++itContours)
{ cout << "Size: " <<
itContours->size() << endl;//每个轮廓包含的点
数} //找到最大轮廓int
index=0,maxArea=0; for(unsigned int
i=0;i<contours.size();i++) { int
area=contourArea(contours[i]); if
(area>maxArea) { index=i; maxArea=area; } } // draw black contours on white image Mat
result(image.size(),CV_8U,Scalar(0));
drawContours(result,contours, //画出轮廓
-1, // draw all contours Scalar(255), // in black 2); // with a thickness of 2
pair<Point,double>
m=DetectInCircles(contours[index],image);
cout<<m.first.x<<" "<<m.first.y<<"
"<<m.second<<endl;
circle(src,m.first,3,Scalar(0,0,255),2);
circle(src,m.first,m.second,Scalar(0,0,255),1); namedWindow("result"); imshow("result",src); waitKey(0); return 0; } 结果:
原图dist_image 结果
其中有一点需要注意:
[cpp] view plaincopydistanceTransform(InputArray src, OutputArray dst, int distanceType, int maskSize)