OpenCV 学习笔记03 直线和圆检测

检测边缘和轮廓不仅重要,还经常用到,它们也是构成其他复杂操作的基础。

直线和形状检测与边缘和轮廓检测有密切的关系。

霍夫hough 变换是直线和形状检测背后的理论基础。霍夫变化是基于极坐标和向量开展的,常规的直线是二维平面直角坐标上建立的

y = kx + b

该直线的参数 k、b 存在有负值,负值则不便于计算(有资料这样撰写的,没有深究,就以此为参考吧),对于极坐标而言,其表达式为

r=x * cosθ + y * sinθ

参数r、θ均可以为正数(极坐标r值永远是大于等于0的数,θ就可以用0~360度表示方便计算。其中r表示直线到原点的最短距离,θ表示x轴与原点到直线最短距离的夹角)。

1 直线检测

直线检测可通过 HoughLines 和 HoughLinesP 函数来完成,

  • HoughLines - 使用标准的Hough变换
  • HoughLinesP - 使用概率Hough变换,因此名称后有一个P

HoughLinesP 属于标准Hough变换的优化版本,它不仅分析点点的子集并且还会估计这些点都属于一条直线的概率。该函数计算代价会少一些,执行会变得更快一些。

HoughLinesP 函数的应用

作用:通过概率Hough变换算法实现对二值图像中的线检测

cv2.HoughLinesP(image, rho, theta, threshold[, minLineLength[, maxLineGap]]) -> lines

参数:

image - 8-bit、单通道single-channel二进制源图像;

HoughLines函数会接受由Canny边缘检测滤波器处理过的单通道二值图像,但不一定必须经过Canny处理;不过经过去噪且只有边缘的图像当作Hough变换的输入会得到不错的效果,因此使用Canny滤波器的返回值是一个普遍的惯例。

rho - 累加器的距离分辨率,单位为像素,一般取值为1。

theta - 累加器的角度分辨率,单位为弧度,一般取值为np.pi/180

threshold - 累加器的阈值参数,只有落在直线上的像素点数大于thresh值才会返回直线。

minLineLength - 最小线段长度,小于该值的直线会被舍弃掉

maxLineGap - 同一直线中允许的最大间隙值(gap between points)

返回值:

lines - 矢量线,每行有 4 个元素组成,(x_1, y_1, x_2, y_2),(x_1, y_1) 和 (x_2, y_2) 分别是开始点和结束点

示例:

 1 import cv2
 2 import numpy as np
 3 
 4 img = cv2.imread('lines.png')
 5 # 将图片转为灰度图
 6 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 7 # 边缘轮廓检测
 8 edges = cv2.Canny(gray,50,120)
 9 
10 minLineLength = 20
11 maxLineGap = 5
12 lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)
13 
14 # 打印lines.shape值,(29, 1, 4)
15 # print(lines.shape)
16 # 打印lines值
17 # print(lines) ♦
18 for line in lines:
19     # 打印line[0].shape,(4,)
20     # print(line[0].shape)
21     # 打印line值 
22     # print(line[0]) ♦ ♦
23     cv2.line(img,(line[0][0],line[0][1]),(line[0][2],line[0][3]),(255,255,0),5)
24 
25 
26 # 边缘检测轮廓绘图
27 cv2.imshow("edges", edges)
28 # Hough变换后绘图
29 cv2.imshow("Hough", img)
30 cv2.waitKey()
31 cv2.destroyAllWindows()

另,第一个 ♦ 输出值(第 17 行)

[[[ 82 356 943 356]]

 [[ 82 358 943 358]]

 [[455 333 455  39]]

 [[457 333 457  39]]

 [[282 331 309 331]]

 [[145 682 413 682]]

 [[562 121 818 121]]

 [[373 613 376 618]]

 [[402 663 405 668]]

 [[732 708 843 597]]

 [[560 330 560 123]]

 [[355 582 365 599]]

 [[561 331 819 331]]

 [[533 652 729 652]]

 [[285 461 355 581]]

 [[819 330 819 122]]

 [[534 538 730 538]]

 [[196 593 242 514]]

 [[251 498 254 493]]

 [[145 681 178 624]]

 [[457 511 457 455]]

 [[457 668 457 713]]

 [[457 617 457 667]]

 [[732 483 843 594]]

 [[455 433 455 489]]

 [[730 537 730 483]]

 [[457 597 457 541]]

 [[532 651 532 540]]

 [[732 484 843 595]]]

另,第二个 ♦ ♦ 输出值(第 17 行)

[ 82 356 943 356]
[ 82 358 943 358]
[455 333 455  39]
[457 333 457  39]
[282 331 309 331]
[145 682 413 682]
[562 121 818 121]
[373 613 376 618]
[402 663 405 668]
[732 708 843 597]
[560 330 560 123]
[355 582 365 599]
[561 331 819 331]
[533 652 729 652]
[285 461 355 581]
[819 330 819 122]
[534 538 730 538]
[196 593 242 514]
[251 498 254 493]
[145 681 178 624]
[457 511 457 455]
[457 668 457 713]
[457 617 457 667]
[732 483 843 594]
[455 433 455 489]
[730 537 730 483]
[457 597 457 541]
[532 651 532 540]
[732 484 843 595]

图片对比

我们可以发现,原图在Canny函数检测后,其轮廓均能被有效检测出来,在霍夫Hough变换时,需要进一步修改参数才能进行有效检测。

2 圆检测

上述代码是针对直线检测的,函数HoughCircles是实现圆的检测。

HoughCircles函数的应用

作用:使用Hough变换在灰度图像中查找 / 检测圆圈。

HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles

参数:

image - 8位单通道二进制图像。

method - 检测方法,唯一实现的方法是 HOUGH_GRADIENT

dp - 累加器分辨率,其与图像分辨率的反比,若dp = 1,则累加器具有与输入图像相同的分辨率,若dp = 2,则累加器的宽度和高度为输入图像的一半。

minDist - 检测到的圆的中心之间的最小距离,若太小,则除真实的一个外,可能错误地检测到多个相邻的圆圈,若太大,则可能会遗漏一些圆

param1 - 第一个特定于方法的参数。在#HOUGH_GRADIENT的情况下,它是传递给Canny边缘检测器的两个较高阈值(较低的一个小两倍)。

param2 - 第二种方法特定参数。在#HOUGH_GRADIENT的情况下,它是检测阶段圆心的累加器阈值。它越小,可以检测到更多的假圆圈。将首先返回与较大累加器值对应的圆圈。

minRadius - 最小圆半径

maxRadius - 最大圆半径

示例:

import cv2
import numpy as np

planets = cv2.imread('planet_glow.png')
gray_img = cv2.cvtColor(planets, cv2.COLOR_BGR2GRAY)
# 进行中值滤波操作
# 中值滤波将图像的每个像素用邻域 (以当前像素为中心的正方形区域)像素的 中值 代替
img = cv2.medianBlur(gray_img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)

circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,120,param1=100,param2=30,minRadius=0,maxRadius=0)
print(help(cv2.HoughCircles))

circles = np.uint16(np.around(circles))

for i in circles[0,:]:
    # draw the outer circle
    cv2.circle(planets,(i[0],i[1]),i[2],(0,255,0),2)
    # draw the center of the circle
    cv2.circle(planets,(i[0],i[1]),2,(0,0,255),3)

cv2.imwrite("planets_circles.jpg",planets)
cv2.imshow('HoughCircles',planets)
cv2.waitKey()
cv2.destroyAllWindows

运行:

参考:

极坐标系

OpenCV(Python)学习-霍夫变化直线和圆检测

opencv 直线和圆检测,该文中仅有代码,可以借鉴

图像处理之霍夫变换圆检测算法

hough变换是如何检测出直线和圆的

原图:

猜你喜欢

转载自www.cnblogs.com/gengyi/p/10347146.html