OpenCV特征检测(8)检测图像中圆形的函数HoughCircles()的使用

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

在灰度图像中使用霍夫变换查找圆形。

该函数使用霍夫变换的一种修改版本在灰度图像中查找圆形。

例子:

cpp 复制代码
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
    Mat img, gray;
    if( argc != 2 || !(img=imread(argv[1], IMREAD_COLOR)).data)
        return -1;
    cvtColor(img, gray, COLOR_BGR2GRAY);
    // smooth it, otherwise a lot of false circles may be detected
    GaussianBlur( gray, gray, Size(9, 9), 2, 2 );
    vector<Vec3f> circles;
    HoughCircles(gray, circles, HOUGH_GRADIENT,
                 2, gray.rows/4, 200, 100 );
    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]);
         // draw the circle center
         circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 );
         // draw the circle outline
         circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 );
    }
    namedWindow( "circles", 1 );
    imshow( "circles", img );
    waitKey(0);
    return 0;
}

注意:

通常该函数能够很好地检测圆形的中心。然而,它可能无法正确找到半径。如果你知道半径范围,可以通过指定 minRadius 和 maxRadius 来帮助函数。或者,在使用 HOUGH_GRADIENT 方法的情况下,你可以将 maxRadius 设置为一个负数,以仅返回中心而不进行半径搜索,并使用额外的过程来找到正确的半径。

对图像进行轻微的平滑处理也有帮助,除非图像本身已经很平滑。例如,使用大小为 7x7 的高斯核和 1.5x1.5 的 sigma 进行 GaussianBlur() 或类似的模糊处理可能会有帮助。

HoughCircles 是 OpenCV 中用于检测图像中圆形的一个函数。Hough 变换是一种用于检测图像中特定形状的技术,尤其是直线和圆形。HoughCircles 实现了 Hough 变换的一个变种,专门用于检测圆形。

函数原型

cpp 复制代码
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 
)		

参数

  • 参数image: 8 位单通道灰度输入图像。

  • 参数circles: 输出的检测到的圆形向量。每个向量编码为包含 3 或 4 个元素的浮点数向量(x, y, 半径)或(x, y, 半径, 投票数)。

  • 参数method: 检测方法,参见 HoughModes。可用的方法包括 HOUGH_GRADIENT 和 HOUGH_GRADIENT_ALT。

  • 参数dp: 累加器分辨率与图像分辨率的逆比。例如,如果 dp=1,累加器具有与输入图像相同的分辨率。如果 dp=2,累加器的宽度和高度各为输入图像的一半。对于 HOUGH_GRADIENT_ALT,推荐的值是 dp=1.5,除非需要检测一些非常小的圆形。

  • 参数minDist: 检测到的圆形中心之间的最小距离。如果该参数太小,可能会错误地检测到多个相邻的圆形。如果太大,某些圆形可能会被遗漏。

  • 参数param1: 第一个特定于方法的参数。在 HOUGH_GRADIENT 和 HOUGH_GRADIENT_ALT 的情况下,它是传递给 Canny 边缘检测器的较高阈值(较低的阈值是较高阈值的一半)。注意 HOUGH_GRADIENT_ALT 使用 Scharr 算法来计算图像的导数,所以阈值通常应该更高,例如 300 或者适用于正常曝光和对比度较高的图像。

  • 参数param2: 第二个特定于方法的参数。在 HOUGH_GRADIENT 的情况下,它是检测阶段的累加器阈值,用于圆心。该值越小,可能检测到的虚假圆形越多。对应的累加器值较大的圆形将优先返回。在 HOUGH_GRADIENT_ALT 算法中,这是圆形的"完美度"度量。该值越接近 1,算法选择的圆形形状越好。大多数情况下 0.9 应该是合适的。如果你想更好地检测小圆形,可以将其减小到 0.85、0.8 或甚至更小。但同时也要尝试限制搜索范围 [minRadius, maxRadius] 以避免出现许多虚假圆形。

  • 参数minRadius: 最小圆形半径。

  • 参数maxRadius: 最大圆形半径。如果 <= 0,使用最大图像尺寸。如果 < 0,HOUGH_GRADIENT 返回中心而不查找半径。HOUGH_GRADIENT_ALT 总是计算圆形的半径。

代码示例

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>

int main( int argc, char** argv )
{
    // 加载图像

    cv::Mat img = cv::imread("/media/dingxin/data/study/OpenCV/sources/images/qiu.jpg", cv::IMREAD_COLOR );

    if ( !img.data )
    {
        std::cout << "No image data" << std::endl;
        return -1;
    }

    cv::imshow( "Original Image", img );

    // 转换为灰度图
    cv::Mat gray;
    cvtColor( img, gray, cv::COLOR_BGR2GRAY );

    // 高斯模糊减少噪声
    cv::GaussianBlur( gray, gray, cv::Size( 9, 9 ), 2, 2 );

    std::vector< cv::Vec3f > circles;  // 存储检测到的圆形信息

    // 设置参数
    double dp      = 1;             // 累加器分辨率
    double minDist = img.rows / 8;  // 圆心之间的最小距离
    double param1  = 100;           // 边缘检测的高阈值
    double param2  = 30;            // 累加器阈值
    int minRadius  = 0;             // 最小半径
    int maxRadius  = 0;             // 最大半径

    // 使用 HoughCircles 检测圆形
    cv::HoughCircles( gray, circles, cv::HOUGH_GRADIENT, dp, minDist, param1, param2, minRadius, maxRadius );

    // 绘制检测到的圆形
    for ( size_t i = 0; i < circles.size(); i++ )
    {
        cv::Vec3i c = circles[ i ];
        cv::Point center( cvRound( c[ 0 ] ), cvRound( c[ 1 ] ) );
        int radius = cvRound( c[ 2 ] );

        // 绘制圆心
        cv::circle( img, center, 1, cv::Scalar( 0, 100, 100 ), 3, cv::LINE_AA );

        // 绘制圆周
        cv::circle( img, center, radius, cv::Scalar( 255, 0, 0 ), 3, cv::LINE_AA );
    }

    // 显示带有检测出圆形的图像
    
    cv::imshow( "Detected Circles", img );

    // 等待按键后关闭窗口
    cv::waitKey( 0 );

    return 0;
}

运行结果

相关推荐
KieranYin3 分钟前
AI编程 | 概念
人工智能
飞Link13 分钟前
LangChain Core 架构深度剖析与 LCEL 高阶实战
人工智能·架构·langchain
liangdabiao15 分钟前
Seedance 2.0 Skill 一键写好剧本上线了coze的技能商店了,免费
人工智能
喵飞云智AI研发社24 分钟前
本土AI企业发力 喵飞科技AIGC开年分享会助力天津数字化转型
人工智能·科技·aigc
于过26 分钟前
AgentMiddleware is All You Need
人工智能·langchain·llm
LLM精进之路27 分钟前
频域+特征融合:深度学习的黄金组合,顶会顶刊的快速通道
人工智能·计算机视觉·目标跟踪
大橙子打游戏32 分钟前
我做了一个 A2A 协议的 Postman —— A2A-Forge 开源了
人工智能
L-影37 分钟前
Agent中的ReAct:类型、作用与避坑指南(下篇)
人工智能·ai·react
itwangyang52037 分钟前
AIDD-人工智能药物发现与设计-利用深度学习从头设计药物,实现逆转疾病相关转录表型
人工智能·深度学习
陈天伟教授38 分钟前
人工智能应用- 预测新冠病毒传染性:07. 预测不同类型病毒的传播能力
人工智能·神经网络·安全·cnn·xss