『OpenCV3』霍夫变换
Posted hellcat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了『OpenCV3』霍夫变换相关的知识,希望对你有一定的参考价值。
霍夫变换常用于检测直线特征,经扩展后的霍夫变换也可以检测其他简单的图像结构。
在霍夫变换中我们常用公式
ρ = x*cosθ + y*sinθ
表示直线,其中ρ是圆的半径(也可以理解为原点到直线的距离),θ是直线与水平线所成的角度(0~180°),确定了它们,也就确定一条直线了,和下图略有出入的是实际的原点定在图片左上角。
原理是对于输入的二值图像中的像素点(有值的),按照步长(参数三参数四对应rho和theta的步长)分别计算出每个点上的所有可能的直线。记录下每条直线经过的点数(即存在多个点计算出的直线有交集),按照阈值(参数五)筛选符合条件的图像。
霍夫变换
霍夫变换接收二值化的输入,即已经进行初步的轮廓检测之后,才进行直线检测;输出一组cv::Vec2f,通常用vector<CV::Vec2f>接收,所以我们通常使用Canny检测之后进行霍夫变换。
输出的两个float数字表示(rho, theta),使用cv::line绘图,因其参数需要的是线段的两个端点,所以我们不得不进行还原操作。
void hough() { cv::Mat image = cv::imread("road.png"); cv::Mat midImage; cv::Canny(image, midImage, 50, 200, 3); std::vector<cv::Vec2f> lines; cv::HoughLines(midImage, lines, 1, CV_PI / 180, 150); // 输入的时二值图像,输出vector向量 for (size_t i=0; i < lines.size(); i++) { float rho = lines[i][0]; //就是圆的半径r float theta = lines[i][1]; //就是直线的角度 cv::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)); cv::line(image, pt1, pt2, cv::Scalar(55, 100, 195), 1); //Scalar函数用于调节线段颜色,就是你想检测到的线段显示的是什么颜色 cv::imshow("边缘检测后的图", midImage); cv::imshow("最终效果图", image); } }
概率霍夫变换
概率霍夫变换输出Vec4i,直接输出了每一条线段的首尾,绘图更加方便。它是霍夫变换的改进版,由于算法的改进(会沿着搜寻到的直线扫描图像),可以进一步检测到线段的长度,除了最小投票数(参数五)外,可以额外限制最小线段长度(参数六)和同一线段最大像素间距(参数七)。
void houghp() { cv::Mat image = cv::imread("road.png"); cv::Mat midImage; cv::Canny(image, midImage, 50, 200, 3); std::vector<cv::Vec4i> lines; cv::HoughLinesP(midImage, lines, 1, CV_PI / 180, 50); // 输入的时二值图像,输出vector向量 for (int i=0; i < lines.size(); i++) { cv::Point pt1(lines[i][0], lines[i][1]); cv::Point pt2(lines[i][2], lines[i][3]); cv::line(image, pt1, pt2, cv::Scalar(0, 255, 255)); } cv::imshow("概率霍夫变换", image); }
以上是关于『OpenCV3』霍夫变换的主要内容,如果未能解决你的问题,请参考以下文章