1.直线检测原理
参见:
https://blog.csdn.net/qq_47233366/article/details/123639022?spm=1001.2014.3001.5501
2.车道线检测
参见:
https://blog.csdn.net/qq_47233366/article/details/123671701
3.圆检测
3.1 原理
参见:
https://blog.csdn.net/DIPDWC/article/details/117513601
3.2 步骤
- 中值滤波,去燥
- 边缘检测,发现可能的圆心
- 从候选圆心开始计算最佳半径大小
3.3 API
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 );
参数说明:
InputArray: 输入图像,数据类型一般用Mat型即可,需要是8位单通道灰度图像
OutputArray:存储检测到的圆的输出矢量,是Vec3f类型的vector,其中三个值分别是圆心的x,y和半径r
method:使用的检测方法,目前opencv只有霍夫梯度法一种方法可用,该参数填HOUGH_GRADIENT即可(opencv 4.1.0下)
dp:double类型的dp,用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。上述文字不好理解的话,来看例子吧。例如,如果dp= 1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器便有输入图像一半那么大的宽度和高度。
minDist:为霍夫变换检测到的圆的圆心之间的最小距离
param1:它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半。
param2:也是第三个参数method设置的检测方法的对应的参数,对当前唯一的方法霍夫梯度法HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。
minRadius:表示圆半径的最小值
maxRadius:表示圆半径的最大值
3.4 代码
int main()
{
cv::Mat img = cv::imread("/Users/xialz/Downloads/3.png");
cv::Mat gray_img;
cv::cvtColor(img, gray_img, cv::COLOR_BGR2GRAY);
// cv::Mat threshold_img;
// cv::threshold(gray_img, threshold_img, 120, 255, cv::THRESH_BINARY);
cv::Mat gauss_img;
//cv::GaussianBlur(threshold_img, gauss_img, Size(5,5), 1);
cv::medianBlur(gray_img, gauss_img, 5);
// cv::Mat canny_img;
// cv::Canny(gauss_img, canny_img, 180, 255);
// cv::imshow("canny", canny_img);
std::vector<Vec3f> circles;
cv::HoughCircles(gauss_img, circles, cv::HOUGH_GRADIENT, 1, 50, 180, 60, 50, 200);
for (auto &i : circles)
{
//画圆
cv::circle(img, cv::Point(i[0], i[1]), i[2], cv::Scalar(0,255,0), 2);
//画圆心
cv::circle(img, cv::Point(i[0], i[1]), 2, cv::Scalar(0, 0, 255), 2);
}
cv::imshow("img", img);
cv::waitKey(0);
return 0;
}
原图:
检测结果图
=几点说明=
- 对于上边的硬币识别是不需要二值化的,二值化反而导致颜色深的硬币,全变成黑色,反而找不到边缘了
- 霍夫圆检测自带边缘检测,不需要用canny了