原理先留着,日后补上。
针对线检测,一般使用累计概率霍夫变换:HoughLineP()函数 检测速度更快。
CV_EXPORTS_W void HoughLinesP( InputArray image, OutputArray lines,
double rho, double theta, int threshold,
double minLineLength = 0, double maxLineGap = 0 );
输入图像必须是八位单通道二进制图像!
第二个参数:输出的lines,存储了检测到的线条的矢量,每条线具有4个元素的矢量(x_1,x_2,y_1,y_2)
真实存储时 [0] [1]表示第一个点 [2][3]表示第二个点
第三个参数:以像素为单位的距离精度,生成极坐标的时候的像素扫描步长
第四个参数:以弧度为单位的角度精度,生成极坐标的时候的角度步长 ,一般取值 CV_PI/180
第五个参数:即识别某部分为图中的一条直线时它在累加平面中必须达到的值,只有获得足够交点的极坐标点才被看作是直线,
大于阈值threshold的线段才可以被检测并返回到结果中
第六个参数: 最小直线长度,默认值0 ,比这个长度短的直线就不能被显现出来
第七个参数:允许将同一行点与点之间连接起来的最大的距离
Img1 = imread("demo.jpg");
if (!Img1.data)
{
cout << "未找到图片" << endl;
return -1;
}
Canny(Img1, GrayImg, 100, 200); //输出即为边缘二值化图像
cvtColor(GrayImg, Img1, COLOR_GRAY2BGR);
imshow("Input Img", GrayImg); //边缘二值化图像
vector<Vec4f> lines;//定义一个矢量结构lines用来存放得到的线段矢量集合
HoughLinesP(GrayImg, lines, 1, CV_PI / 180, 100, 20, 10);
for (size_t i = 0;i < lines.size();i++)
{
Vec4i l = lines[i];
line(Img1, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 1, LINE_AA);
//不能在GrayImg中画线 因为GrayImg为单通道八位图像,不能显示彩色,
//前面的GRAY2BGR是为了能在IMG1中用别的颜色显示出检测的线
}
imshow("Output Img", Img1);
霍夫圆变换 HoughCircle()函数
与线变换相比, 圆变换最大的优势就是不需要原图是二值的, HoughLinesP需要原图为二值图像;
CV_EXPORTS_W void HoughCircles( InputArray image, OutputArray circles,
int method, double dp, double minDist,
double param1 = 100, double param2 = 100,
int minRadius = 0, int maxRadius = 0 );
输入图像为 八位单通道灰度图像即可
输出 circles 为存储了检测到的圆的矢量, 每个矢量包含了三个元素的浮点矢量(x,y,radius)
第三个参数为使用的检测方法,目前只有一种办法可以使用 即霍夫梯度法 HOUGH_GRADIENT
第四个参数dp 通常设置1 使得检测圆心的累加器图像与源图像分辨率相同。
设置为2的话,累加器只有源图像一般大小的高度和宽度
第五个参数 minDist 圆心之间的最小距离,这个参数如果太小,多个相邻的圆可能就被检测成同一个圆
设置太大,某些圆就不能被检测出来
第六个参数 有默认值100,他表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半
第七个参数 有默认值为100, 他表示在检测圆心阶段的累加器的阈值。
它越小,则可以检测更多不存在的圆;越大的话,能通过检测的圆就更加接近完美的圆形
最后俩参数 一个表示圆半径的最小值,一个表示圆半径的最大值,可以直接使用默认,也可以自己规定来辅助检测圆。
cvtColor(Img1,GrayImg,COLOR_BGR2GRAY);
medianBlur(GrayImg, GrayImg, 3);
//因为霍夫圆检测对噪声比较敏感,首先要对图像做中值滤波
//GaussianBlur(GrayImg, GrayImg, Size(7, 7), 1.5, 1.5);
//此滤波方式为释义中推荐 7*7 sigma1.5 1.5
vector<Vec3f> circle1;
HoughCircles(GrayImg, circle1, HOUGH_GRADIENT, 1, 50, 100, 50, 0, 0);
cvtColor(GrayImg, GrayImg, COLOR_GRAY2BGR);
for (size_t i = 0; i < circle1.size(); i++)
{
Vec3f c=circle1[i];
Point center = Point((int)c[0], (int)c[1]);
circle(GrayImg, center, (int)c[2], Scalar(255, 0, 90), 2, LINE_AA);
//画出圆
circle(GrayImg, center, 2, Scalar(255, 90, 90), 2, LINE_AA);
//画出圆心
}
imshow("Output Img", GrayImg);