本文基于opencv官方文档,是本人的学习笔记。版本是在linux下的opencv4.2.0,全部程序调通可运行,无bug。

import cv2 as cv
import numpy as np

# OpenCV中的霍夫曼变换

# 上面说明的所有内容都封装在OpenCV函数cv.HoughLines()中。
# 它只是返回一个:math:(rho,theta)值的数组。
# $ρ$以像素为单位,$θ$以弧度为单位。
# 第一个参数,输入图像应该是二进制图像,
# 因此在应用霍夫变换之前,请应用阈值或使用Canny边缘检测。
# 第二和第三参数分别是$ρ$和$θ$精度。第四个参数是阈值,
# 这意味着应该将其视为行的最低投票。请记住,票数取决于线上的点数。因此,它表示应检测到的最小线长。

img = cv.imread(cv.samples.findFile('girl.jpg'))
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 150, apertureSize=3)
lines = cv.HoughLines(edges, 1, np.pi / 180, 200)
for line in lines:
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a * rho
    y0 = b * rho
    x1 = int(x0 + 1000 * (-b))
    y1 = int(y0 + 1000 * (a))
    x2 = int(x0 - 1000 * (-b))
    y2 = int(y0 - 1000 * (a))
    cv.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv.imwrite('houghlines3.jpg', img)
cv.imshow('img', img)
cv.waitKey(0)

# 在霍夫变换中,您可以看到,即使对于带有两个参数的行,也需要大量计算。
# 概率霍夫变换是我们看到的霍夫变换的优化。它没有考虑所有要点。
# 取而代之的是,它仅采用随机的点子集,足以进行线检测。只是我们必须降低阈值。
# OpenCV的实现基于Matas,J.和Galambos,C.和Kittler, J.V.
# 使用渐进概率霍夫变换对行进行的稳健检测[145]。
# 使用的函数是cv.HoughLinesP()。它有两个新的论点。
# - minLineLength - 最小行长。小于此长度的线段将被拒绝。
# - maxLineGap - 线段之间允许将它们视为一条线的最大间隙。
# 最好的是,它直接返回行的两个端点。在以前的情况下,您仅获得线的参数,并且必须找到所有点。
# 在这里,一切都是直接而简单的。
img = cv.imread(cv.samples.findFile('hui.jpg'))
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edges = cv.Canny(img, 50, 150, apertureSize=3)
lines = cv.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength=100, maxLineGap=10)
for line in lines:
    x1, y1, x2, y2 = line[0]
    cv.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv.imwrite('houghlines5.jpg', img)
cv.imshow('img', img)
cv.waitKey(0)
cv.destroyAllWindows()

# 霍夫圆检测
# image为输入图像,需要灰度图
# method为检测方法,常用CV_HOUGH_GRADIENT
# dp为检测内侧圆心的累加器图像的分辨率于输入图像之比的倒数,
# 如dp=1,累加器和输入图像具有相同的分辨率,如果dp=2,累计器便有输入图像一半那么大的宽度和高度
# minDist表示两个圆之间圆心的最小距离
# param1有默认值100,它是method设置的检测方法的对应的参数,
# 对当前唯一的方法霍夫梯度法cv2.HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半
# param2有默认值100,它是method设置的检测方法的对应的参数,
# 对当前唯一的方法霍夫梯度法cv2.HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值,它越小,
# 就越可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了
# minRadius有默认值0,圆半径的最小值
# maxRadius有默认值0,圆半径的最大值

img = cv.imread('cirl.png', 0)
img = cv.medianBlur(img, 5)
cimg = cv.cvtColor(img, cv.COLOR_GRAY2BGR)
circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1, 20,
                          param1=50, param2=40, minRadius=0, maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
    # 绘制外圆
    cv.circle(cimg, (i[0], i[1]), i[2], (0, 255, 0), 2)
    # 绘制圆心
    cv.circle(cimg, (i[0], i[1]), 2, (0, 0, 255), 3)
cv.imshow('detected circles', cimg)
cv.waitKey(0)
cv.destroyAllWindows()