图像轮廓,霍夫变换
图像轮廓
\qquad 图像轮廓是一系列相连的点组成的曲线,代表了物体的基本外形,相对于边缘,轮廓是连续的,边缘并不全部连续。寻找轮廓的操作一般用于二值化图,所以通常会使用阈值分割或Canny边缘检测先得到二值图。
查找轮廓
cv2.findContours()函数用于从二值图像中查找图像轮廓,其基本格式如下:
contours,hierarchy=cv2.findContours(image,mode,method,offset)
其参数说明如下:
参数 | 说明 |
---|---|
contours | 为返回的轮廓数组,每个元素都是一个表示轮廓的array对象。 |
hierarchy | 为返回的轮廓的层次结构,是一个numpy.ndarray对象。根据轮廓的嵌套关系,可将轮廓之间的层次关系分为父级和子级,外部的轮廓为父级,内部的轮廓为子级。 |
image | 为原图像。 |
mode | 为轮廓的检索模式,不同检索模式下函数返回的轮廓有所不同。 |
cv2.RETR_LIST | 仅检索所有轮廓,不创建任何父子关系。 |
cv2.RETR_EXTERNAL | 仅检索所有的外部轮廓,不包含子级轮廓。 |
cv2.RETR_CCOMP | 检索所有轮廓并将它们排列为2级层次结构,所有的外部轮廓为1级,所有的子级轮廓为2级。 |
cv2.RETR_TREE | 检索所有轮廓并创建完整的层次列表,如父级、子级、孙子级等。 |
method | 为轮廓的近似方法,决定如何确定轮廓包含的像素点。 |
cv2.CHAIN_APPROX_NONE | 存储所有轮廓点,轮廓的任意两个相邻点是水平、垂直或对角线上的邻居。 |
cv2.CHAIN_APPROX_SIMPLE | 只保存水平、垂直和对角线的端点。 |
cv2.CHAIN_APPROX_TC89_L1 | 应用Teh-Chin链逼近算法中的一种确定轮廓点。 |
offset | 为每个轮廓点移动的可选偏移量。 |
import cv2
import numpy as np
img = cv2.imread('shapes.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print('轮廓:', c)
print('轮廓类型:', type(c))
print('轮廓个数:', len(c))
print('层次:', h)
print('层次类型:', type(h))
for n in (range(3)):
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
cv2.polylines(img3, [c[n]], True, (255, 0, 0), 2) # 绘制轮廓
cv2.imshow('%s' % n, img3) # 显示轮廓图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
绘制轮廓
\qquad cv2.drawContours()函数用于绘制轮廓,其基本格式如下:
image=cv2.drawContours(image,contours,contourIdx,color,thickness,lineType,hierarchy,maxLevel,offset)
其参数说明如下:
参数 | 说明 |
---|---|
image | 为在其中绘制轮廓的图像。 |
contours | 为要绘制的轮廓。 |
contourIdx | 为要绘制的轮廓的索引,大于或等于0时绘制对应的轮廓,负数(通常为-1)表示绘制所有轮廓。 |
color | 为轮廓颜色,颜色为BGR格式。 |
thickness | 为可选参数,表示绘制轮廓时画笔的粗细。 |
lineType | 为可选参数,表示绘制轮廓时使用的线型。 |
hierarchy | 为可选参数,对应cv2.findContours()函数返回的轮廓层次。 |
maxLevel | 为可选参数,表示可绘制的最大轮廓层次深度。 |
offset | 为可选参数,表示绘制轮廓的偏移位置。 |
import cv2
import numpy as np
img = cv2.imread('shapes.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
img3 = cv2.drawContours(img3, c, -1, (0, 0, 255), 2) # 绘制轮廓
cv2.imshow('Contours', img3) # 显示轮廓图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
轮廓特征
1.轮廓的矩
\qquad 轮廓的矩包含了轮廓的各种几何特征,如面积、位置、角度、形状等。cv2.moments()函数用于返回轮廓的矩,其基本格式如下:
ret=cv2.moments(array,binaryImage)
其参数说明如下:
参数 | 说明 |
---|---|
ret | 为返回的轮廓矩,是一个字典对象。大多数矩的含义比较抽象,但其中的零阶矩(m00)表示轮廓的面积。 |
array | 为表示轮廓的数组。 |
binaryImage | 值为True时,会将array对象中的所有非0值设置为1 |
import cv2
import numpy as np
img = cv2.imread('shape2.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
img3 = cv2.drawContours(img3, c, -1, (0, 0, 255), 2) # 绘制轮廓
cv2.imshow('Contours', img3) # 显示轮廓图像
for n in range(len(c)):
m = cv2.moments(c[n])
print('轮廓%s的矩:' % n, m) # 输出轮廓矩
print('轮廓%s的面积:' % n, m['m00']) # 输出轮廓面积
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
2.轮廓面积
\qquad cv2.contourArea()函数用于返回轮廓面积,其基本格式如下:
ret=cv2.contourArea(contour,oriented)
其参数说明如下:
参数 | 说明 |
---|---|
ret | 为返回的面积。 |
contour | 为轮廓。 |
oriented | 为可选参数。其参数值为True时,返回值的正与负表示轮廓是顺时针还是逆时针;参数值为False(默认值)时,函数返回值为绝对值 |
import cv2
import numpy as np
img = cv2.imread('shape2.jpg') # 读取图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for n in range(len(c)):
m = cv2.contourArea(c[n]) # 计算轮廓面积
print('轮廓%s的面积:' % n, m) # 输出轮廓面积
3.轮廓的长度
\qquad cv2.arcLength()函数用于返回轮廓的长度,其基本格式如下:
ret=cv2.arcLength(contour,closed)
其参数说明如下:
参数 | 说明 |
---|---|
ret | 为返回的长度。 |
contour | 为轮廓。 |
closed | 为布尔值,为True时表示轮廓是封闭的。 |
import cv2
import numpy as np
img = cv2.imread('shape2.jpg') # 读取图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for n in range(len(c)):
m = cv2.arcLength(c[n], True) # 计算轮廓长度
print('轮廓%s的长度:' % n, m) # 输出轮廓长度
4. 轮廓的近似多边形
\qquad cv2.approxPolyDP()函数用于返回轮廓的近似多边形,其基本格式如下:
ret=cv2.approxPolyDP(contour,epsilon,closed)
其参数说明如下:
参数 | 说明 |
---|---|
ret | 为返回的近似多边形。 |
contour | 为轮廓。 |
epsilon | 为精度,表示近似多边形接近轮廓的最大距离。 |
closed | 为布尔值,为True时表示轮廓是封闭的。 |
import cv2
import numpy as np
img = cv2.imread('shape3.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
ep = [0.1, 0.05, 0.01]
arcl = cv2.arcLength(c[0], True) # 计算轮廓长度
print(arcl)
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
img3 = cv2.drawContours(img3, c, -1, (0, 0, 255), 2) # 绘制轮廓
for n in range(3):
eps = ep[n]*arcl
img4 = img3.copy()
app = cv2.approxPolyDP(c[0], eps, True) # 获得近似多边形
img4 = cv2.drawContours(img4, [app], -1, (255, 0, 0), 2) # 绘制近似轮廓
cv2.imshow('appro %.2f' % ep[n], img4) # 显示轮廓图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
5.轮廓的凸包
\qquad cv2.convexHull()函数用于返回轮廓的凸包,其基本格式如下:
hull=cv2.convexHull(contour,clockwise,returnPoints)
其参数说明如下:
参数 | 说明 |
---|---|
hull | 为返回的凸包,是一个numpy.ndarray对象,包含了凸包的关键点。 |
contour | 为轮廓。 |
clockwise | 为方向标记,为True时,凸包为顺时针方向;为False(默认值)时,凸包为逆时针方向。 |
returnPoints | 为True(默认值)时,返回的hull中包含的是凸包关键点的坐标;为False时,返回的是凸包关键点在轮廓中的索引。 |
import cv2
import numpy as np
img = cv2.imread('shape3.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 计算轮廓
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
img3 = cv2.drawContours(img3, c, -1, (0, 0, 255), 2) # 绘制轮廓
hull = cv2.convexHull(c[0])
print('returnPoints=True时返回的凸包:\n', hull)
hull2 = cv2.convexHull(c[0], returnPoints=False)
print('returnPoints=False时返回的凸包:\n', hull2)
cv2.polylines(img3, [hull], True, (255, 0, 0), 2) # 绘制凸包
cv2.imshow('Convex Hull', img3) # 显示轮廓图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
6.轮廓的直边界矩形
\qquad 轮廓的直边界矩形是指可容纳轮廓的矩形,且矩形的两条边必须是水平的。直边界矩形不一定是面积最小的边界矩形。cv2.boundingRect()函数用于返回轮廓的直边界矩形,其基本格式如下:
ret=cv2.boundingRect(contour)
其参数说明如下:
参数 | 说明 |
---|---|
ret | 为返回的直边界矩形,它是一个四元组,其格式为(矩形左上角x坐标,矩形左上角y坐标,矩形的宽度,矩形的高度)。 |
import cv2
import numpy as np
img = cv2.imread('shape4.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 计算轮廓
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
cv2.drawContours(img3, c, -1, (0, 0, 255), 2) # 绘制轮廓
ret = cv2.boundingRect(c[0]) # 计算直边矩形
print('直边界矩形:', ret)
pt1 = (ret[0], ret[1])
pt2 = (ret[0]+ret[2], ret[1]+ret[3])
cv2.rectangle(img3, pt1, pt2, (255, 0, 0), 2) # 绘制直边界矩形
cv2.imshow('Rectangle', img3) # 显示结果图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
7.轮廓的旋转矩形
\qquad 轮廓的旋转矩形是指可容纳轮廓的面积最小的矩形。cv2.minAreaRect()函数用于返回轮廓的旋转
矩形,其基本格式如下:
box=cv2.minAreaRect(contour)
其参数说明如下:
参数 | 说明 |
---|---|
box | 为返回的旋转矩形,它是一个三元组,其格式为((矩形中心点x坐标,矩形中心点y坐标),(矩形的宽度,矩形的高度),矩形的旋转角度)。 |
contour | 为用于计算矩形的轮廓。 |
cv2.minAreaRect()函数的返回结果不能直接用于绘制旋转矩形,可用cv2.boxPoints()函数将其转
换为矩形的顶点坐标,其基本格式如下:
points=cv2.boxPoints(box)
其参数说明如下:
参数 | 说明 |
---|---|
points | 为返回的矩形顶点坐标,坐标数据为浮点数。 |
box | 为cv2.minAreaRect()函数返回的矩形数据。 |
import cv2
import numpy as np
img = cv2.imread('shape4.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 计算轮廓
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
cv2.drawContours(img3, c, -1, (0, 0, 255), 2) # 绘制轮廓
ret = cv2.minAreaRect(c[0]) # 计算最小矩形
rect = cv2.boxPoints(ret) # 计算矩形顶点
rect = np.int0(rect) # 转换为整数
cv2.drawContours(img3, [rect], 0, (255, 0, 0), 2) # 绘制旋转矩形
cv2.imshow('Rectangle', img3) # 显示结果图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
8.轮廓的最小外包圆
\qquad cv2.minEnclosingCircle()函数用于返回可容纳轮廓的最小外包圆,其基本格式如下:
center,radius=cv2.minEnclosingCircle(contour)
其参数说明如下:
参数 | 说明 |
---|---|
center | 为圆心。 |
radius | 为半径。 |
contour | 为用于计算最小外包圆的轮廓。 |
import cv2
import numpy as np
img = cv2.imread('shape4.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 计算轮廓
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
cv2.drawContours(img3, c, -1, (0, 0, 255), 2) # 绘制轮廓
(x, y), radius = cv2.minEnclosingCircle(c[0]) # 计算最小圆信息
center = (int(x), int(y))
radius = int(radius)
cv2.circle(img3, center, radius, (255, 0, 0), 2) # 绘制最小圆
cv2.imshow('Circle', img3) # 显示结果图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
9.轮廓的拟合椭圆
\qquad cv2.fitEllipse()函数用于返回轮廓的拟合椭圆,其基本格式如下:
ellipse=cv2.fitEllipse(contour)
其参数说明如下:
参数 | 说明 |
---|---|
ellipse | 为返回的椭圆。 |
contour | 为用于计算拟合椭圆的轮廓。 |
import cv2
import numpy as np
img = cv2.imread('shape4.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 计算轮廓
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
cv2.drawContours(img3, c, -1, (0, 0, 255), 2) # 绘制轮廓
ellipse = cv2.fitEllipse(c[0]) # 计算拟合椭圆
cv2.ellipse(img3, ellipse, (255, 0, 0), 2) # 绘制拟合椭圆
cv2.imshow('ellipse', img3) # 显示结果图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
10.轮廓的拟合直线
\qquad cv2.fitLine()函数用于返回轮廓的拟合直线,其基本格式如下:
line=cv2.fitLine(contour,distType,param,reps,aeps)
其参数说明如下:
参数 | 说明 |
---|---|
line | 为返回的拟合直线。 |
contour | 为用于计算拟合直线的轮廓。 |
distType | 为距离类型参数,决定如何计算拟合直线,可设置为下列常量。 |
cv2.DIST_USER | 用户自定义距离。 |
cv2.DIST_L1 | 用2个点的坐标计算距离,公式为 l x1-x2l +l y1-y2 l。 |
cv2.DIST_L2 | 欧氏距离(两点间的直线距离)。 |
cv2.DIST_C | 用2个点的坐标计算距离,公式为max(lx1-x2l,ly1-y2l)。 |
cv2.DIST_L12 | 用1个点的坐标计算距离,公式为2(sqrt(1+x*x/2)-1)。 |
cv2.DIST_FAIR | 用 1 个点的坐标计算距离,公式为c^2(lxl/c-log(1+lxl/c)),c=1.3998。 |
cv2.DIST_WELSCH | 用1个点的坐标计算距离,公式为c2/2(1-exp(-(x/c)2)),c=2.9846。 |
cv2.DIST_HUBER | 用 1 个点的坐标计算距离,公式为lxl<c?x^2/2:c(lxl-c/2),c=1.345。 |
param | 为距离参数,与距离类型参数有关;其设置为0时,函数将自动选择最优值。 |
reps | 为计算拟合直线需要的径向精度,通常设置为0.01。 |
aeps | 为计算拟合直线需要的角度精度,通常设置为0.01。 |
import cv2
import numpy as np
img = cv2.imread('shape4.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将其转换为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 计算轮廓
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
cv2.drawContours(img3, c, -1, (0, 0, 255), 2) # 绘制轮廓
rows, cols = img.shape[:2]
[vx, vy, x, y] = cv2.fitLine(c[0], cv2.DIST_L2, 0, 0.01, 0.01) # 计算拟合直线
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
cv2.line(img3, (cols-1, righty), (0, lefty), (255, 0, 0), 2) # 绘制拟合直线
cv2.imshow('FitLine', img3) # 显示结果图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
11.轮廓的最小外包三角形
\qquad cv2.minEnclosingTriangle()函数用于返回可容纳轮廓的最小外包三角形,其基本格式如下:
retval,triangle=cv2.minEnclosingTriangle(contour)
其参数说明如下:
参数 | 说明 |
---|---|
retval | 为最小外包三角形的面积。 |
triangle | 为最小外包三角形。 |
contour | 为用于计算最小外包三角形的轮廓。 |
import cv2
import numpy as np
img = cv2.imread('shape4.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将其转换为灰度图像
ret, img2 = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY) # 二值化阈值处理
c, h = cv2.findContours(img2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 计算轮廓
img3 = np.zeros(img.shape, np.uint8)+255 # 按原图大小创建一幅白色图像
cv2.drawContours(img3, c, -1, (0, 0, 255), 2) # 绘制轮廓
retval, triangle = cv2.minEnclosingTriangle(c[0]) # 计算最小外包三角形
triangle = np.int0(triangle)
cv2.polylines(img3, [triangle], True, (255, 0, 0), 2) # 绘制最小外包三角形
cv2.imshow('Triangle', img3) # 显示结果图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
霍夫变换
\qquad 霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,它通过一种投票算法检测具有特定形状的物体。该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。
\qquad 霍夫变换变换是一种利用表决原理的参数估计技术。其基本原理在于利用图像空间和霍夫变换参数空间的点与线的对偶性,把图像空间中的检测问题转换到参数空间。通过在参数空间里进行简单的累加统计,然后在 Hough 参数空间寻找累加器峰值的方法检测直线。Hough 变换的实质是将图像空间内具有一定关系的像元进行聚类,寻找能把这些像元用某一解析形势联系起来的参数空间累计对应点。在参数空间不超过二维的情况下,这种变换效果理想。将原始图像空间的给定的曲线表达形式变为参数空间的一个点,这样就把原始图像中给定曲线的检测问题转化为寻找参数空间的峰值问题,也就是把检测整体特性转化为检测局部特性,例如直线、椭圆、圆、弧线等。简而言之,Hough变换思想是:在原始图像坐标系下的一个点对应了参数坐标系中的一条直线,同样参数坐标系的一条直线对应了原始坐标系下的一个点,然后,原始坐标系下呈现直线的所有点,它们的斜率和截距是相同的,所以它们在参数坐标系下对应于同一个点。这样在原始坐标系下的各个点的投影到参数坐标系下之后,看参数坐标系下没有聚集点,这样的聚集点就对应了原始坐标系下的直线。
霍夫直线变换
cv2.HoughLines()函数利用霍夫变换算法检测图像中的直线,其基本格式如下:
lines=cv2.HoughLines(image,rho,theta,threshold)
其参数说明如下:
参数 | 说明 |
---|---|
lines | 为返回的直线。 |
image | 为原图像,必须是8位的单通道二值图像,通常会在霍夫变换之前,对图像执行阈值处理或Canny边缘检测。 |
rho | 为距离的精度(以像素为单位),通常为1。 |
theta | 为角度的精度,通常使用π/180°,表示搜索所有可能的角度。 |
threshold | 为阈值,值越小,检测出的直线越多。 |
import cv2
import numpy as np
img = cv2.imread('shape6.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
edges = cv2.Canny(gray, 50, 150, apertureSize=3) # 执行边缘检测
lines = cv2.HoughLines(edges, 1, np.pi/180, 200) # 霍夫线变换
img3 = img.copy()
for line in lines: # 逐条绘制直线
rho, theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0, y0 = a*rho, b*rho
pt1 = (int(x0+1000*(-b)), int(y0+1000 * (a))) # 计算直线端点
pt2 = (int(x0-1000*(-b)), int(y0-1000 * (a))) # 计算直线端点
cv2.line(img3, pt1, pt2, (0, 0, 255), 2) # 绘制直线
cv2.imshow('HoughLines', img3) # 显示结果图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
霍夫直线
cv2.HoughLinesP()函数利用概率霍夫变换算法来检测图像中的直线,其基本格式如下:
lines=cv2.HoughLinesP(image,rho,theta,threshold,minLineLength,maxLineGap)
其参数说明如下:
参数 | 说明 |
---|---|
lines | 为返回的直线。 |
image | 为原图像,必须是8位的单通道二值图像,通常会在霍夫变换之前,对图像执行阈值处理或Canny边缘检测。 |
rho | 为距离的精度(以像素为单位),通常为1。 |
theta | 为角度的精度,通常使用π/180°,表示搜索所有可能的角度。 |
threshold | 为阈值,值越小,检测出的直线越多。 |
minLineLength | 为可接受的直线的最小长度,默认值为0。 |
maxLineGap | 为共线线段之间的最大间隔,默认值为0 |
import cv2
import numpy as np
img = cv2.imread('shape6.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
edges = cv2.Canny(gray, 50, 150, apertureSize=3) # 执行边缘检测
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 1,
minLineLength=100, maxLineGap=10) # 概率霍夫线变换
img3 = img.copy()
for line in lines: # 逐条绘制直线
x1, y1, x2, y2 = line[0]
cv2.line(img3, (x1, y1), (x2, y2), (0, 0, 255), 2) # 绘制直线
cv2.imshow('HoughLines', img3) # 显示结果图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
霍夫圆变换
cv2.HoughCircles()函数利用霍夫变换查找图像中的圆,其基本格式如下:
circles=cv2.HoughCircles(image,method,dp,minDist,param1,param2,minRadius,maxRadius)
其参数说明如下:
参数 | 说明 |
---|---|
circles | 为返回的圆。 |
image | 为原图像,必须是8位的单通道二值图像。 |
method | 为查找方法,可设置为cv2.HOUGH_GRADIENT和cv2.HOUGH_GRADIENT _ALT。 |
dp | 为累加器分辨率,它与图像分辨率成反比。例如,如果dp=1,则累加器与输入图像的分辨率相同;如果dp =2,则累加器的宽度和高度是输入图像的一半。 |
minDist | 为圆心间的最小距离。 |
param1 | 为对应Canny边缘检测的高阈值(低阈值是高阈值的一半),默认值为100。 |
param2 | 为圆心位置必须达到的投票数,值越大,检测出的圆越少,默认值为100。 |
minRadius | 为最小圆半径,半径小于该值的圆不会被检测出来。其默认值为0,不起作用。 |
maxRadius | 为最大圆半径,半径大于该值的圆不会被检测出来。其默认值为0,不起作用。 |
import cv2
import numpy as np
img = cv2.imread('shape6.jpg') # 读取图像
cv2.imshow('original', img) # 显示原图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
edges = cv2.Canny(gray, 50, 150, apertureSize=3) # 执行边缘检测
circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 50,
param2=30,minRadius=10, maxRadius=40) # 检测圆
circles = np.uint16(np.around(circles))
img2 = img.copy()
for i in circles[0, :]:
cv2.circle(img2, (i[0], i[1]), i[2], (255, 0, 0), 2) # 画圆
cv2.circle(img2, (i[0], i[1]), 2, (0, 0, 255), 3) # 画圆心
cv2.imshow('circles', img2) # 显示结果图像
cv2.waitKey(0) # 按任意键结束等待
cv2.destroyAllWindows() # 关闭所有窗口
实验素材