Python-初学openCV——图像预处理(七)——模板匹配、霍夫变换

目录

一、模板匹配

1、匹配方法

2、绘制轮廓

二、霍夫变换

1、概念

2、(标准)霍夫直线变换

3、统计概率霍夫直线变换

4、霍夫圆变换


一、模板匹配

模板匹配就是用模板图(通常是一个小图)在目标图像(通常是一个比模板图大的图片)中不断的滑动比较,通过某种比较方法来判断是否匹配成功,找到模板图所在的位置

1、匹配方法

python 复制代码
res=cv2.matchTemplate(image, templ, method)

image:原图像,这是一个灰度图像或彩色图像(在这种情况下,匹配将在每个通道上独立进行)

templ:模板图像,也是灰度图像或与原图像相同通道数的彩色图像

method:匹配方法:

cv2.TM_CCOEFF; cv2.TM_CCOEFF_NORMED

cv2.TM_CCORR; cv2.TM_CCORR_NORMED

cv2.TM_SQDIFF; cv2.TM_SQDIFF_NORMED

res:函数在完成图像模板匹配后返回一个结果矩阵,这个矩阵的大小与原图像不相同。矩阵的每个元素表示原图像中相应位置与模板图像匹配的相似度

(SQDIFF的两种方法,返回值越接近0,匹配程度越好,最小值对应的最佳匹配位置;

CCORR的两种方法,返回值越大,匹配程度越好,最大值对应的最佳匹配位置;

CCOEFF的两种方法,返回值越大,匹配程度越好,最大值对应的最佳匹配位置。)

2、绘制轮廓

找的目标图像中匹配程度最高的点,我们可以设定一个匹配阈值来筛选出多个匹配程度高的区域

python 复制代码
loc=np.where(array > 0.8)    #返回array中所有大于0.8的元素索引的数组
zip(*loc)    #对loc解包,把单独的参数传递给zip,将这些数组按元素一一配对(表示一个坐标点)

案例:

python 复制代码
import cv2 as cv
import numpy as np
# 读图
img=cv.imread("../images/game.png")
gray_img=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
temp=cv.imread("../images/temp.png")
gray_temp=cv.cvtColor(temp,cv.COLOR_BGR2GRAY)
h,w=gray_temp.shape
# 模板匹配 拿到匹配结果矩
res=cv.matchTemplate(gray_img,gray_temp,cv.TM_CCOEFF_NORMED)
# 设置阈值
thresh=0.8
# 获取匹配上的结果的索引
loc=np.where(res>=thresh)
# 解包,拿到成对的x y索引
# print(zip(*loc))
for i in zip(*loc):
    x,y=i[1],i[0]
    cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),1)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

二、霍夫变换

1、概念

霍夫变换 是图像处理的一种技术,主要用于检测图像中的直线、圆等几何形状。基本思想就是将图像空间中的点映射到参数空间 中,通过在参数空间中寻找累计最大值实现对特定形状的检测

2、(标准)霍夫直线变换

python 复制代码
lines=cv2.HoughLines(image, rho, theta, threshold)

lines:一个二维数组,每一行代表一条直线在霍夫空间中的参数 (rho, theta)

image:输入图像,通常为二值图像,白点表示边缘点,黑点为背景

rho:r的精度,以像素为单位,表示霍夫空间中每一步的距离增量, 值越大,考虑越多的线

theta:角度θ的精度,通常以弧度为单位,表示霍夫空间中每一步的角度增量。值越小,考虑越 多的线

threshold:累加数阈值,只有累积投票数超过这个阈值的候选直线才会被返回

python 复制代码
import cv2 as cv
import numpy as np

img=cv.imread("../../images/huofu.png")
gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
_,binary=cv.threshold(gray,127,255,cv.THRESH_BINARY)
# 边缘检测
edges=cv.Canny(binary,30,70)
#霍夫变换  返回的是[r,theta]
lines=cv.HoughLines(edges,0.8,np.pi/180,90)
for line in lines:
    r,theta=line[0]
    sin_theta=np.sin(theta)
    cos_theta=np.cos(theta)
    x1,x2=0,img.shape[1]
    y1=int((r-x1*cos_theta)/sin_theta)
    y2=int((r-x2*cos_theta)/sin_theta)
    cv.line(img,(x1,y1),(x2,y2),(0,255,0),1)

3、统计概率霍夫直线变换

一种改进的霍夫变换,它在获取到直线之后,会检测原图中在该直线上的点,并获取到两侧的端点坐标,然后通过两个点的坐标来计算该直线的长度,通过直线长度与最短长度阈值的比较来决定该直线要不要被保留

python 复制代码
cv2.HoughLinesP(image, rho, theta, threshold, lines, minLineLength, maxLineGap)

image:通常为二值图像,其中白点表示边缘点,黑点为背景

rho:极径分辨率,以像素为单位,表示极坐标系中的距离分辨率

theta:极角分辨率,以弧度为单位,表示极坐标系中角度的分辨率

threshold:阈值,用于过滤掉弱检测结果,只有累计投票数超过这个阈值的直线才会被返回

lines(可选):一个可初始化的输出数组,用于存储检测到的直线参数

minLineLength(可选):最短长度阈值,比这个长度短的线会被排除

maxLineGap(可选):同一直线两点之间的最大距离

(返回值是一个二维数组,每个元素是一个包含4个元素的数组,分别表示每条直线的起始点和结束点在图像中的坐标(x1, y1, x2, y2) )

4、霍夫圆变换

霍夫圆变换跟直线变换类似,它可以从图像中找出潜在的圆形结构,并返回它们的中心坐标和半径。只不过线是用(r,θ)表示,圆是用(x_center,y_center,r)来表示,从二维变成了三维,数据量变大了很多;所以一般使用霍夫梯度法减少计算量

python 复制代码
circles=cv2.HoughCircles(image, method, dp, minDist, param1, param2)

circles:一个二维numpy数组,包含所有满足条件的圆的参数

image:通常是灰度图像

method:霍夫梯度法,可以是 cv2.HOUGH_GRADIENT,这是唯一在OpenCV中用于圆检测的方法

dp:累加器分辨率与输入图像分辨率之间的降采样比率,用于加速运算但不影响准确性。设置为1 表示霍夫梯度法中累加器图像的分辨率与原图一致

minDist:检测到的圆心之间的最小允许距离,以像素为单位。为了过滤掉过于接近的圆检测结果,避免检测结果过于密集。

param1 和 param2:是在使用**cv2.HOUGH_GRADIENT** 方法时的特定参数

param1(可选):阈值1,决定边缘强度的阈值

param2:阈值2,控制圆心识别的精确度。较高的 param2 值意味着对圆的检测更严格,只有 在累加器中积累了足够高的响应值才认为是真实的圆;较低的 param2 值则会降低 检测的门槛,可能会检测到更多潜在的圆,但也可能包含更多的误检结果