【python】OpenCV—Hough Circle Transform

在这里插入图片描述


更多有趣的代码示例,可参考【Programming】


1、功能描述

2、代码实现

载入必要的库

import sys
import cv2 as cv
import numpy as np

函数入口

if __name__ == "__main__":
    main(sys.argv[1:])

读取图片,判断图片读取是否成功

    default_file = '1.jpg'
    filename = argv[0] if len(argv) > 0 else default_file

    # Loads an image
    src = cv.imread(cv.samples.findFile(filename), cv.IMREAD_COLOR)

    # Check if image is loaded fine
    if src is None:
        print('Error opening image!')
        print('Usage: hough_circle.py [image_name -- default ' + default_file + '] \n')
        return -1

在这里插入图片描述

输入图片转成灰度图

    gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    cv.imwrite("gray.jpg", gray)

在这里插入图片描述

灰度图片进行平滑滤波

    gray = cv.medianBlur(gray, 5)
    cv.imwrite("medianBlur.jpg", gray)

在这里插入图片描述

配置好算法需要的参数

    rows = gray.shape[0]
    print(rows)

output

202

调用圆形检测算法

    circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp=1, minDist=rows / 8,
                              param1=100, param2=30,
                              minRadius=30, maxRadius=100)

根据预测的结果绘制出来圆形,包含圆心和圆

    if circles is not None:
        circles = np.uint16(np.around(circles))
        for i in circles[0, :]:
            center = (i[0], i[1])
            # circle center
            cv.circle(src, center, 1, (0, 100, 100), 3)
            # circle outline
            radius = i[2]
            cv.circle(src, center, radius, (255, 0, 255), 3)

在这里插入图片描述
保存结果,可视化结果,退出窗口,退出主函数

    cv.imwrite("circles.jpg", src)
    cv.imshow("detected circles", src)
    cv.waitKey(0)

    return 0

3、效果展示

    circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp=1, minDist=rows / 8,
                              param1=150, param2=30,
                              minRadius=70, maxRadius=200)

输入图片

在这里插入图片描述

平滑后

在这里插入图片描述
检测结果

在这里插入图片描述


    circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp=1, minDist=rows / 8,
                              param1=150, param2=50,
                              minRadius=25, maxRadius=100)

输入图片

在这里插入图片描述
平滑后

在这里插入图片描述

结果

在这里插入图片描述


    circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp=1, minDist=rows / 8,
                              param1=70, param2=30,
                              minRadius=20, maxRadius=100)

输入图片

在这里插入图片描述

灰度图平滑

在这里插入图片描述

检测结果

在这里插入图片描述


    circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp=1, minDist=rows / 8,
                              param1=70, param2=45,
                              minRadius=110, maxRadius=200)

输入图片

在这里插入图片描述

灰度平滑后

在这里插入图片描述

检测结果

在这里插入图片描述


    circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp=1, minDist=rows / 8,
                              param1=70, param2=40,
                              minRadius=20, maxRadius=100)

输入图片

在这里插入图片描述

灰度平滑后

在这里插入图片描述

检测结果

在这里插入图片描述


    circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp=1, minDist=rows / 8,
                              param1=70, param2=40,
                              minRadius=20, maxRadius=70)

输入图片

在这里插入图片描述

灰度平滑后

在这里插入图片描述

检测结果

在这里插入图片描述


    circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp=1, minDist=rows / 8,
                              param1=100, param2=35,
                              minRadius=20, maxRadius=70)

输入图片

在这里插入图片描述

灰度滤波后

在这里插入图片描述
检测结果

在这里插入图片描述

4、完整代码

import sys
import cv2 as cv
import numpy as np

def main(argv):
    default_file = '1.jpg'
    filename = argv[0] if len(argv) > 0 else default_file

    # Loads an image
    src = cv.imread(cv.samples.findFile(filename), cv.IMREAD_COLOR)

    # Check if image is loaded fine
    if src is None:
        print('Error opening image!')
        print('Usage: hough_circle.py [image_name -- default ' + default_file + '] \n')
        return -1

    gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    cv.imwrite("gray.jpg", gray)

    gray = cv.medianBlur(gray, 5)
    cv.imwrite("medianBlur.jpg", gray)

    rows = gray.shape[0]
    print(rows)
    circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp=1, minDist=rows / 8,
                              param1=100, param2=30,
                              minRadius=30, maxRadius=100)

    if circles is not None:
        circles = np.uint16(np.around(circles))
        for i in circles[0, :]:
            center = (i[0], i[1])
            # circle center
            cv.circle(src, center, 1, (0, 100, 100), 3)
            # circle outline
            radius = i[2]
            cv.circle(src, center, radius, (255, 0, 255), 3)
    cv.imwrite("circles.jpg", src)
    cv.imshow("detected circles", src)
    cv.waitKey(0)

    return 0


if __name__ == "__main__":
    main(sys.argv[1:])

5、涉及到的库函数

cv2.HoughCircles 是 OpenCV 库中的一个函数,用于在图像中检测圆形的存在。它基于霍夫变换的圆检测算法,可以在给定的图像中检测并返回所有检测到的圆的信息,如圆的中心坐标和半径。

在这里插入图片描述

circles = cv2.HoughCircles(image, method, dp, minDist, param1, param2, minRadius, maxRadius)
  • image:输入的单通道灰度图像。函数将在该图像中进行圆检测。

  • method:霍夫变换的检测方法。常用的有 cv2.HOUGH_GRADIENTcv2.HOUGH_GRADIENT_ALTcv2.HOUGH_GRADIENT_ALTcv2.HOUGH_GRADIENT 的改进方法。

  • dp:图像分辨率与累加器分辨率的比值。例如,dp=1时,累加器和输入图像有相同的分辨率;dp=2时,累加器是输入图像一半大的宽高。

  • minDist:检测到的圆的中心之间的最小距离。如果设置得太小,可能会检测到多个相邻的圆;如果设置得太大,可能会漏掉一些圆。

  • param1:Canny边缘检测的高阈值。对于 cv2.HOUGH_GRADIENTcv2.HOUGH_GRADIENT_ALT,这是 Canny 边缘检测的高阈值,低阈值是该参数的一半。

  • param2:累加器阈值。对于 cv2.HOUGH_GRADIENT,它表示检测阶段圆心的累加器阈值,值越小,检测出的圆越多;对于 cv2.HOUGH_GRADIENT_ALT,它表示圆形的“完美性”度量,值越接近1,算法选择的圆形形状越好。

  • minRadius:需要检测的最小圆半径。

  • maxRadius:需要检测的最大圆半径。如果设置为<=0,则使用最大图像尺寸;如果<0,且 method=cv2.HOUGH_GRADIENT时,用来查找圆心而忽略半径的查找,method=cv2.HOUGH_GRADIENT_ALT 不受影响,始终会去找半径。

返回值

  • circles:返回的圆形的点,是一个三维数组。对于 HOUGH_GRADIENTHOUGH_GRADIENT_ALT 两种方法,返回的圆形数组形式有差异。通常,返回的数组中包含了检测到的圆的中心坐标和半径。

注意事项

  • 输入图像的质量对函数的检测效果有很大的影响,通常需要进行适当的预处理,如平滑、边缘检测等。
  • 参数的选择对检测的结果有重要的影响,需要根据具体的应用场景进行调整和优化。
  • 函数返回的圆的信息需要进一步处理和分析,以满足实际应用的需求。

应用场景

  • cv2.HoughCircles 函数在很多领域都有重要的应用,如医学影像分析、工业机器视觉、自动驾驶等。例如,在医学影像分析中,常常需要检测和分析图像中的各种病变和器官,如肿瘤、血管等。使用 cv2.HoughCircles 函数,可以有效地在医学影像中检测出各种形状的病变,为医生的诊断和治疗提供重要的参考依据。

6、参考


更多有趣的代码示例,可参考【Programming】

<think>好的,用户想了解如何在Python中实现霍夫变换。首先,我需要回忆霍夫变换的基本原理。霍夫变换主要用于检测图像中的几何形状,比如直线、圆等。用户提到的是Hough Transform,但没有具体说明是直线还是圆,所以可能需要先回答直线检测,再扩展到圆。 接下来,我需要查找相关的Python库。常见的图像处理库有OpenCV和scikit-image。OpenCV的cv2.HoughLines和cv2.HoughLinesP函数常用于直线检测,而scikit-image的hough_line和hough_circle可能更适合自定义实现。用户可能需要具体的代码示例,所以应该提供两种库的实现方法。 然后,考虑用户可能的背景。如果用户是初学者,可能需要详细的步骤解释,比如边缘检测、参数空间累加器等。此外,霍夫变换的参数如阈值、rho和theta的分辨率对结果影响很大,需要说明如何调整这些参数。 用户的问题中提到“实现或教程”,所以除了代码,还应解释每一步的作用。比如,Canny边缘检测是预处理步骤,将图像转换为边缘图,这样霍夫变换能更有效地检测直线。接着,参数空间的构建和累加器的使用是关键部分,需要说明如何将边缘点映射到参数空间。 另外,考虑到用户可能对数学原理感兴趣,需要简要提及霍夫变换的数学基础,即极坐标方程$ρ = x\cosθ + y\sinθ$,并说明每个边缘点对应一条正弦曲线,在参数空间中的交点即为检测到的直线。 可能还需要比较OpenCV和scikit-image的不同实现方式,比如HoughLinesP使用概率霍夫变换,效率更高,适合检测长线段。而自定义实现可以帮助理解底层原理,但计算量较大。 最后,提供相关问题的建议,帮助用户深入学习,比如参数调优、性能优化和应用场景。同时,确保代码示例正确,并引用站内的参考资料,比如引用[5]提到的累加器初始化,这在代码中有所体现。</think>### 霍夫变换的Python实现方法 霍夫变换(Hough Transform)是一种用于检测图像中几何形状(如直线、圆等)的经典算法。以下是两种基于Python的实现方式,分别使用OpenCV和自定义实现: --- #### **1. 使用OpenCV实现直线检测** OpenCV提供了内置的霍夫变换函数`cv2.HoughLines`和`cv2.HoughLinesP`(概率霍夫变换),适合快速实现: ```python import cv2 import numpy as np # 读取图像并转为灰度图 image = cv2.imread('input.jpg') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 边缘检测(Canny) edges = cv2.Canny(gray, 50, 150) # 霍夫直线检测 lines = cv2.HoughLinesP(edges, rho=1, # ρ的分辨率(单位:像素) theta=np.pi/180,# θ的分辨率(单位:弧度) threshold=100, # 累加器阈值 minLineLength=50,# 最小线段长度 maxLineGap=10) # 最大线段间隙 # 绘制检测到的直线 for line in lines: x1, y1, x2, y2 = line[0] cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite('output.jpg', image) ``` --- #### **2. 自定义霍夫变换(以直线检测为例)** 以下代码展示了如何从零实现霍夫变换的核心逻辑: ```python import numpy as np import cv2 from skimage.transform import hough_line, hough_line_peaks # 图像预处理 image = cv2.imread('input.jpg', cv2.IMREAD_GRAYSCALE) edges = cv2.Canny(image, 50, 150) # 生成霍夫变换参数空间 hspace, angles, distances = hough_line(edges) # 检测峰值(即最可能的直线参数) accumulator, theta, rho = hough_line_peaks(hspace, angles, distances, threshold=100) # 绘制检测结果 fig, ax = plt.subplots() ax.imshow(edges, cmap='gray') for _, angle, dist in zip(accumulator, theta, rho): y0 = (dist - 0 * np.cos(angle)) / np.sin(angle) y1 = (dist - edges.shape[1] * np.cos(angle)) / np.sin(angle) ax.plot((0, edges.shape[1]), (y0, y1), '-r') plt.savefig('output_custom.jpg') ``` --- #### **关键步骤解析** 1. **边缘检测**:使用Canny算法提取图像边缘,减少噪声干扰。 2. **参数空间构建**:将直线参数$(\rho, \theta)$离散化,构建累加器数组[^5]。 3. **投票机制**:每个边缘点通过方程$\rho = x\cos\theta + y\sin\theta$映射到参数空间,累加器计数交点数量。 4. **峰值检测**:选择累加器中计数最高的参数对作为检测到的直线。 --- #### **参数调优建议** - `rho`和`theta`分辨率:值越小,检测精度越高,但计算量增加。 - `threshold`:控制直线检测的灵敏度,值越大,检测到的直线越显著。 - 对于圆形检测,可改用`cv2.HoughCircles`,需调整半径范围和圆心间距参数。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值