OpenCV(python)一键入门--十八篇(霍夫线和霍夫圆检测)

举报
拓佑豪 发表于 2021/08/07 19:07:58 2021/08/07
【摘要】 简单介绍霍夫线和霍夫圆检测

本系列OpenCV博客旨在以最简单的方式分享OpenCV知识,欢迎大家交流和提出指导意见

凡是有本文未详细介绍的函数,都可以在以往的博客找到介绍及其使用方法


本期介绍函数:

cv.HoughLines

cv.HoughLinesP

cv.HoughCircles


1:霍夫直线检测

import cv2 as cv
import numpy as np

def canny_demo(image):
    t = 80
    canny_output = cv.Canny(image, t, t * 2)
    return canny_output

src = cv.imread("D:/sudoku.png")
cv.imshow("input", src)

binary = canny_demo(src)
cv.imshow("binary", binary)

lines = cv.HoughLines(binary, 1, np.pi / 180, 150, None, 0, 0)
if lines is not None:
    for i in range(0, len(lines)):
        rho = lines[i][0][0]
        theta = lines[i][0][1]
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a * rho
        y0 = b * rho
        pt1 = (int(x0 + 1000 * (-b)), int(y0 + 1000 * (a)))
        pt2 = (int(x0 - 1000 * (-b)), int(y0 - 1000 * (a)))
        cv.line(src, pt1, pt2, (0, 0, 255), 3, cv.LINE_AA)


cv.imshow("hough line demo", src)
cv.waitKey(0)
cv.destroyAllWindows()

图像霍夫变换是一种很有用的图像变换,通过把图像的坐标从平面坐标系变换极坐标,可以发现原来在平面坐标难以提取的几何特征信息(如:直线、圆等等)。

假设有如下的直线参数方程:
r = xcosθ + ysinθ
其中角度θ指r与X轴之间的夹角,r为到直线几何垂直距离。

如果有很多点在霍夫空间的曲线交于一点(如下图图四),便可以说明他们有相同的θ和r。

1):cv.HoughLines 霍夫线

函数原型:lines = cv.HoughLines(image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]])

  • lines:线的输出向量。每行由2或3个元素向量组成
  • rho:累加器的距离分辨率(以像素为单位)
  • theta:以弧度为单位的累加器的角度分辨率
  • threshold:累加器阈值。图像在霍夫空间每个像素点都是一条曲线。经过每个(r,θ)都+1,如果多个曲线都在同个(r,θ)相交且大于给定的阈值,说明可能存在一条直线在霍夫空间的该点处。
  • lines:输出直线
  • srn、stn:多尺度霍夫变换时候小的参数,经典的霍夫变换不需要此参数
  • srn:对于多尺度霍夫变换,它是距离分辨率 rho 的除数。粗略累加器距离分辨率为 rho ,精确累加器分辨率为 rho/srn 。如果 srn=0 和 stn=0 ,则使用经典的霍夫变换。否则,这两个参数都应为正。
  • stn:对于多尺度 Hough 变换,它是距离分辨率 theta 的除数。
  • min_theta:最小尺度,必须介于 0 和 max_theta 之间。
  • max_theta:最大尺度,必须介于 min_theta 和 CV_PI 之间。

效果如下:

照常贴上原图素材:

sudoku.png

霍夫直线检测其实还有另一个api。也就是

2):cv.HoughLinesP 霍夫线

函数原型:lines = cv.HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]])

  • image:输入的二值图像
  • lines:返回的直线两个点
  • rho :极坐标r得步长
  • theta:角度步长
  • threshold:累加器阈值
  • minLineLength:最小线段长度
  • maxLineGap:线段间隔

案例如下:

import cv2 as cv
import numpy as np


def canny_demo(image):
    t = 80
    canny_output = cv.Canny(image, t, t * 2)
    return canny_output


src = cv.imread("D:/sudoku.png")
cv.imshow("input", src)

binary = canny_demo(src)
cv.imshow("binary", binary)

linesP = cv.HoughLinesP(binary, 1, np.pi / 180, 50, None, 50, 10)
if linesP is not None:
    for i in range(0, len(linesP)):
        l = linesP[i][0]
        cv.line(src, (l[0], l[1]), (l[2], l[3]), (0, 0, 255), 1, cv.LINE_AA)


cv.imshow("hough line demo", src)
cv.waitKey(0)
cv.destroyAllWindows()

效果如下:


2:霍夫圆检测

import cv2 as cv
import numpy as np

src = cv.imread("D:/coin.png")
cv.imshow("input", src)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
gray = cv.GaussianBlur(gray, (9, 9), 2, 2)

dp = 2
param1 = 100
param2 = 80

circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp, 10, None, param1, param2, 20, 100)
for c in circles[0,:]:
    cx, cy, r = c
    cv.circle(src, (cx, cy), 2, (0, 255, 0), 2, 8, 0)
    cv.circle(src, (cx, cy), r, (0, 0, 255), 2, 8, 0)

cv.imshow("hough demo", src)
cv.waitKey(0)
cv.destroyAllWindows()

函数原型:circles=cv.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]])

  • image:单通道灰度图像
  • cycles:检测到的圆的信息,如:圆形,半径
  • method:检测方法。我们直接使用cv.HOUGH_GRADIENT霍夫梯度法即可
  • dp:图像分辨率的变化。默认1的时候保持和原图一样的大小
  • param1:边缘提取的高阈值
  • param2:霍夫空间的累加阈值
  • minRadius:最小圆半径
  • maxRadius:最大圆半径。如果 <= 0,则使用最大图像尺寸。如果 < 0,则返回中心而不找到半径。

效果如下:

附上素材图像:

coin.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。