您的位置:首页 > 运维架构

【opencv学习之二十七】Hough霍夫变换寻找直线和圆

2018-01-31 23:44 711 查看
霍夫变换是在图像中寻找直线、圆和其他一些简单形状的方法。霍夫变换有一个很重要的性质就是对图形在图像中残缺、噪声等不敏感,有较强抗干扰性;但其也有缺点,比如要检测的目标曲线要提前定义好,而如果曲线参数过多则计算量呈指数增长;理论上霍夫检测任意预定目标;opencv实现了其部分算法;Hough变换有很长的研究历史,同样也有很多的文献和资料;Hough基本思想是边缘信息A进行f(x)的拟合操作,通过计算拟合权重值来检测图形;衍生出的算法很多;

这里不做理论研究了,简单呈现opencv 霍夫变换的应用;直接上代码:

// 标准霍夫变换-HoughLines(),检测直线
Mat src = imread("D:/ImageTest/sudoku.png");
Mat dstImg = src.clone();
imshow("src", src);
//为了减少数据量,霍夫变换前一般进行边缘检测处理,将边缘二值图输入到变换算子中
cvtColor(src, src, CV_BGR2GRAY);
Mat cannyImg;
Canny(src, cannyImg, 38, 100, 3);
imshow("Canny", cannyImg);
vector<Vec2f> lines;  //定义矢量结构lines用于存放得到的线段矢量(ρ,θ)集合
HoughLines(
cannyImg,//输入原图像
lines,//输出矢量集合(ρ,θ)
1, //以1像素点为单位的距离精度
CV_PI / 180,//以1弧度为单位的角度精度
150//阈值,大于阈值的线段才可以被检测通过并返回到结果中
);
//将线段画在目标图像上
for (size_t i = 0; i < lines.size(); i++)
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a *rho, y0 = b* rho;
pt1.x = cvRound(x0 + 1000 * (-b));
pt1.y = cvRound(y0 + 1000 * (a));
pt2.x = cvRound(x0 - 1000 * (-b));
pt2.y = cvRound(y0 - 1000 * (a));
line(dstImg, pt1, pt2, Scalar(0, 0, 255), 1, CV_AA);
}
imshow("dst", dstImg);
waitKey(0);
效果:



累计霍夫变换:

//累计概率霍夫变换-HoughLinesP()
Mat cannyImg;
Mat src = imread("D:/ImageTest/sudoku.png");
Mat dstImg = src.clone();
imshow("src", src);
cvtColor(src, src, CV_BGR2GRAY);
Canny(src, cannyImg, 32, 100, 3);
vector<Vec4i> lines;  //定义矢量结构lines用于存放得到的线段矢量(x_1,y_1,x_2,y_2)集合
HoughLinesP(cannyImg, lines, 1, CV_PI/180, 150, 50, 10);
//将线段画在目标图像上
for(size_t i = 0; i<lines.size(); i++)
{
Vec4i l = lines[i];
line(dstImg, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 255, 0), 2, CV_AA);
}
imshow("dst", dstImg);
waitKey(0);
效果:



检测圆形:

///霍夫圆变换-HoughCircles()
Mat src = imread("D:/ImageTest/cercle.png");
Mat dst = src.clone();
imshow("src", src);
cvtColor(src, src, CV_BGR2GRAY);
GaussianBlur(src, src, Size(9, 9), 2, 2);//不滤波会有非常非常多的误检圆
vector<Vec3f> circles;//存放经霍夫变换后检测出的圆的输出矢量(x,y,radius)
HoughCircles(src, circles, CV_HOUGH_GRADIENT, 2, 30, 200, 100, 10, 200);
//将圆画在目标图像上
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle(dst, center, 3, Scalar(0, 0, 255), -1, 8, 0);
circle(dst, center, radius, Scalar(0, 255, 0), 3, 8, 0);
}
imshow("dst", dst);
waitKey(0);
效果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: