霍夫圆检测原理+实战

🍊 作者简介:秃头小粟,致力于用最通俗的语言描述问题

🍊往期回顾:霍夫线目标检测原理详解霍夫线目标检测代码实战

🍊近期目标:拥有2000粉丝
🍊支持小苏:点赞👍🏼、收藏⭐、评论📩

霍夫圆目标检测原理+实战

霍夫圆目标检测原理

霍夫线目标检测的原理前面已经详细介绍过了。本次我们将简单讲一下霍夫圆目标检测的原理并进行实际练习。在霍夫线目标检测中,我已经非常详细地给出了线目标检测的原理。如果不清楚,请先理解。 🥗🥗🥗

在这篇文章中,我可能不会很详细地介绍原理,但它一定会很受欢迎。 【因为用通俗易懂的语言描述问题是我写作的目的】其实线目标检测的原理很相似。我会用线目标检测和圆目标检测来对比,让大家直观的了解霍夫圆目标检测。 🍒🍒🍒

在霍夫直线目标检测中我们的期待求得的未知量是两个,斜率k和截距b;而霍夫圆目标检测的未知量则变成了三个,分别为圆心坐标(a,b)和半径r。在霍夫直线目标检测中我们的参数空间是二维的,那么霍夫圆目标检测的参数空间应该就为三维的,因为有三个未知参数嘛🥙🥙🥙

不知道这样的描述大家能不能理解哈,再换一种表述方式。我们知道在图像空间的x-y坐标系中,圆的方程为:(x-a)2+(y-b)2=r2。现我们将其转换到a-b-r的三维参数空间,其表达式为:(a-x)2+(b-y)2=r2。在霍夫直线目标检测原理中我们给出了下列结论:

  • 图像空间x-y中的一点对应于参数空间k-b中的一条直线。
  • 图像空间中的一条直线对应于参数空间k-b中的一个点。

那么对应圆目标检测来说有怎样的结论呢?我们都可以思考思考。类比思考起来也很容易哈,==对应图像空间圆上的一点(x0,y0)对应于参数空间应该是一个三维的锥面。==这个三维曲面如下:即不同的半径r下都会对应一个圆,这样就构成了一个圆锥面。【这里所有不同r下的圆心坐标都为(x0,y0)】

image-20220323105453705

​那么我们若取图像空间圆上的两点,则在参数空间中对应于两个锥面。以此类推,若取图像空间圆上的所有点,对应于参数空间将会有许多锥面,且这些锥面会有一个共同的交点坐标M(a , b , r ),则根据这个M点坐标我们就可以求出原图像空间中的圆啦🍋🍋🍋

有没有发现霍夫线目标检测的思路类似,但是存在寻找共同路口的问题。上面的思路消耗了很多计算,所以改进了霍夫圆目标检测,它是基于梯度(gradient)来计算的,我这里比较期待的可能是怎么用代码目标检测圆,所以就不赘述了在这里介绍这种基于梯度(gradient)的圆目标检测。大家别着急,这里有一个链接供大家查看:基于梯度(gradient)的霍夫圆目标检测。

实践中的霍夫圆目标检测

这里先给出官网中对霍夫圆目标检测的介绍:HoughCircles()函数介绍。同样的我也会对这个函数进行一定的中文讲解。

  • HoughCircles()函数🌸
void cv::HoughCircles	(	InputArray 	image,
                            OutputArray 	circles,
                            int 	method,
                            double 	dp,
                            double 	minDist,
                            double 	param1 = 100,
                            double 	param2 = 100,
                            int 	minRadius = 0,
                            int 	maxRadius = 0 
)	
    
    
    
    

//InputArray 	image               输入(input)的图像,必须是8位单通道图像。
//OutputArray 	circles             返回目标检测到圆的信息,用一个向量保存这个向量编码(code)为3或4个元素的浮点型向量(x,y,	radius)或(x,y,radius,votes) ,x,y表示横纵坐标,radius表示圆的半径,votes表示投票数 
//int 	method                      目标检测的方法。目前可用的方法有HOUGH_GRADIENT和HOUGH_GRADIENT_ALT
//double dp                         图像分辨率与累加器分辨率之比。例如若dp=1, 则累加器与输入(input)图片有相同的分辨率, 若dp=2,累加器的宽度和高度只有其一半
//double minDist                    被测圆中心之间的最小距离。如果该参数太小,可能会在目标检测出多个相交的圈。如果它太大,可能会漏掉一些圆。
//double param1 = 100               第一个method-specific参数。对于HOUGH_GRADIENT和HOUGH_GRADIENT_ALT,它是传递给Canny边缘目标检测器的两者中较高的阈值(Threshold)(是较低的阈值(Threshold)的两倍)。注意,HOUGH_GRADIENT_ALT使用Scharr算法来计算图(computational graph)像导数,所以阈值(Threshold)通常应该较高,例如300或正常曝光和对比度图像。
//double param2 = 100               第二个method-specific参数。对于HOUGH_GRADIENT,则为目标检测阶段圆中心的累加器阈值(Threshold)。它越小,可能目标检测到的假圆就越多。与较大累加器值相对应的圆将首先返回。在HOUGH_GRADIENT_ALT算法中,这是圆的“完美度”度量。越接近1,算法选择的圆的形状越好。在大多数情况下,0.9应该可以。如果你想更好地目标检测小圆,你可以将其降低到0.85,0.8或更少。。但同时也要限制搜索范围[minRadius, maxRadius],以避免许多错误的圆。
//int minRadius = 0                 需要目标检测圆的最小半径
//int maxRadius = 0                 需要目标检测圆的最大半径,如果该值等于0, 则使用图像的最大尺寸;如果小于0, 则返回圆心位置

下面给出C++的实现代码,这也是opencv官方给的,当然HoughCircles()函数部分你需要手动调剂一些参数以更好的完成目标检测任务。


#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
    const char* filename = argc >= 2 ? argv[1] : "E:\\毫米波雷达\\circle.jpg";
    // Loads an image
    Mat src = imread(samples::findFile(filename), IMREAD_COLOR);
    // Check if image is loaded fine
    if (src.empty()) {
        printf(" Error opening image\n");
        printf(" Program Arguments: [image_name -- default %s] \n", filename);
        return EXIT_FAI(人工智能(Artificial Intelligence))LURE;
    }
    Mat gray;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    medianBlur(gray, gray, 5);
    vector<Vec3f> circles;
    HoughCircles(gray, circles, HOUGH_GRADIENT, 1,
        80,  // change this value to detect circles with different distances to each other
        100, 20, 1, 0 // change the last two parameters
   // (min_radius & max_radius) to detect larger circles
    );
    for (size_t i = 0; i < circles.size(); i++)
    {
        Vec3i c = circles[i];
        Point center = Point(c[0], c[1]);
        // circle center
        circle(src, center, 1, Scalar(0, 0, 100), 2, LINE_AA);
        // circle outline
        int radius = c[2];
        circle(src, center, radius, Scalar(100, 0, 0), 2, LINE_AA);
    }
    imshow("detected circles", src);
    waitKey();
    return EXIT_SUCCESS;
}

输出结果:可以看出目标检测效果不是很好。当然,很有可能是我调的参数不好。你可以自己试试。

image-20220324160311603

呼呼呼~~🌻🌻🌻所以霍夫圆目标检测的原理和代码实践就讲到这里了,大家去试试吧🥗🥗🥗



如果文章对你有帮助,那么🛴🛴🛴

咻咻咻咻~~duang~~点个赞呗

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2022年3月24日 下午4:28
下一篇 2022年3月25日 上午11:22

相关推荐