赞
踩
本文分享内容来自图书《学习OpenCV 4:基于Python的算法实战》,该书内容如下:
第1章 OpenCV快速入门;
第2章 图像读写模块imgcodecs;
第3章 核心库模块core;
第4章 图像处理模块imgproc(一);
第5章 图像处理模块imgproc(二);
第6章 可视化模块highgui;
第7章 视频处理模块videoio;
第8章 视频分析模块video;
第9章 照片处理模块photo;
第10章 2D特征模块features2d;
第11章 相机标定与三维重建模块calib3d;
第12章 传统目标检测模块objdetect;
第13章 机器学习模块ml;
第14章 深度神经网络模块dnn
霍夫变换是图像处理中识别基本形状(如线、圆)的方法之一,OpenCV封装了利用霍夫变换检测直线和圆的算法。
OpenCV中支持三种霍夫线变换,即标准霍夫变换和多尺度霍夫变换(HoughLines函数)和累积概率霍夫变换(HoughLinesP函数)。
HoughLines函数的定义如下:
lines = HoughLines(image, rho, theta, threshold, lines=None, srn=None, stn=None, min_theta=None, max_theta=None)
参数说明如下:
image,输入图像,图像需为8位单通道二值图像;
rho,距离分辨率,单位为像素;
theta,角度分辨率,单位为弧度;
threshold,累加平面的阈值参数;
lines,变换检测到的直线(返回值);
srn,对于多尺度的霍夫变换,它是距离分辨率rho的除数距离;
stn,对于多尺度霍夫变换,它是角度分辨率theta的除数距离;
min_theta,检查线条的最小角度,介于0与max_theta之间;
max_theta,检查线条的最大角度,介于min_theta和CV_PI之间。
本节案例使用的输入图像如图5.1所示。
图5.1
使用标准霍夫变换进行直线检测的案例代码如下:
import cv2
import numpy as np
img = cv2.imread('chess_board.jpg')
draw_lines = np.zeros(img.shape[:], dtype=np.uint8)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Canny边缘检测
edges = cv2.Canny(gray, 50, 150)
#经典霍夫线变换
lines = cv2.HoughLines(edges, 1, np.pi / 180, 150)
#绘制检测到的直线
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))
cv2.line(draw_lines, (x1, y1), (x2, y2), (255, 255, 255))
#图像显示
cv2.imshow("draw_lines", draw_lines)
cv2.waitKey(0)
cv2.destroyAllWindows()
标准霍夫变换检测到的直线结果绘制如图5.2所示。
图5.2
累积概率霍夫变换函数HoughLinesP的定义如下:
lines = HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None)
参数说明如下:
image,输入图像,图像需为8位单通道二值图像;
rho,距离分辨率,单位为像素;
theta,角度分辨率,单位为弧度;
threshold,累加平面的阈值参数;
lines,变换检测到的直线(返回值);
minLineLength,小的线段长度;
maxLineGap,同一行两点连接起来的最大的距离;
累积概率霍夫变换案例代码如下:
import cv2
import numpy as np
img = cv2.imread('chess_board.jpg')
draw_lines = np.zeros(img.shape[:], dtype=np.uint8)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Canny边缘检测
edges = cv2.Canny(gray, 50, 150)
#累积概率霍夫线变换
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 90, minLineLength=50, maxLineGap=10)
#绘制检测到的线
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(draw_lines, (x1, y1), (x2, y2), (255, 255, 255), 1, lineType = cv2.LINE_AA)
#图像显示
cv2.imshow("draw_lines", draw_lines)
cv2.waitKey(0)
cv2.destroyAllWindows()
检测到的直线绘制结果如图5.3所示。
图5.3
HoughLines函数中的threshold参数设置的越小就有越多的直线被检测,HoughLinesP函数中的minLineLength和maxLineGap设置时也是这样,设置的越小被检测到的直线则会越多,读者可以根据图像的先验知识设置合适的参数,这样能够达到更加精确的检测效果。
OpenCV中提供了霍夫圆变换的函数HoughCircles,该函数的定义如下:
circles = HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None)
参数说明如下:
image,输入图像,需传入8位单通道二值图像;
method,检测方法;
dp,累加器分辨率与图像分辨率的反比;
minDist,圆心之间最小距离;
circles,找到的圆(返回值)
param1,Canny边缘检测算法的高阈值,低阈值是其一半;
param2,累加器阈值,表示确定一个圆的阈值;
minRadius,待检测圆的最小半径;
maxRadius,待检测圆的最大半径。
本案例使用的输入图像如图5.4所示。
图5.4
霍夫圆变换的案例代码如下:
import cv2
import numpy as np
img = cv2.imread('circle_src.jpg')
#创建纯黑色图片
draw_circle = np.zeros(img.shape[:], dtype=np.uint8)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Canny边缘检测
edges = cv2.Canny(gray, 50, 150)
# 霍夫圆变换
circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 100)
#浮点数转整型数
circles = np.int0(np.around(circles))
# 将检测的圆绘制出来
for i in circles[0, :]:
cv2.circle(draw_circle, (i[0], i[1]), i[2], (255, 255, 255), 2)
#图像显示
cv2.imshow("edges", edges)
cv2.imshow("draw_circle", draw_circle)
cv2.waitKey(0)
cv2.destroyAllWindows()
使用Canny算法进行边缘检测的结果如图5.5所示。
图5.5
使用霍夫圆变换检测的圆的结果如图5.6所示。
图5.6
图5.6中的检测效果不尽人意,有很多的不是期望的圆被检测并绘制出来。本案例中设置的参数dp=1,则累加器与输入图像具有相同的分辨率;设置的minDist为100,即检测的圆之间的最小圆心距离为100。根据图5.35中的圆的信息可以调整输入参数,设置最小圆半径minRadius为130, 最大圆半径maxRadius为180,如下所示:
circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 100, param2=30, minRadius=130, maxRadius=180)
设置新参数后的检测结果如图5.7所示,检测的结果则比较准确。
图5.7
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。