opencv之模板匹配和霍夫变换(七)

opencv之模板匹配和霍夫变换(七)


一、模板匹配

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

  • 不会有边缘填充。

  • 类似于卷积,滑动比较,挨个比较象素。

  • 返回结果大小是:目标图大小-模板图大小-1。

在这里插入图片描述

匹配方法

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

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

    匹配方法不同,返回矩阵的值的含义也会有所区别。以下是几种常用的匹配方法及其返回值含义:

    1. cv2.TM_SQDIFFcv2.TM_SQDIFF_NORMED

      返回值越接近0,表示匹配程度越好。最小值对应的最佳匹配位置。

    2. cv2.TM_CCORRcv2.TM_CCORR_NORMED

      返回值越大,表示匹配程度越好。最大值对应的最佳匹配位置。

    3. cv2.TM_CCOEFFcv2.TM_CCOEFF_NORMED

      返回值越大,表示匹配程度越好。最大值对应的最佳匹配位置。

案例

import numpy as np
import cv2 as cv

# 读图
img = cv.imread("images/game.png")# 目标图
temp = cv.imread("images/temp.png")#  模板图
# 转灰度
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
temp_gray = cv.cvtColor(temp, cv.COLOR_BGR2GRAY)
# 模板匹配,拿到匹配结果,返回匹配成都矩阵
res = cv.matchTemplate(img_gray, temp_gray, cv.TM_CCOEFF_NORMED)
# 设置阈值,使用np.where()
threshold = 0.8
loc = np.where(res >= threshold)
# 获取模板宽高
h,w = temp.shape[:2]
# 解包,拿到坐标
# for pt in zip(*loc[::-1]):# pt ===>(y,x),所以翻转一下
#     cv.rectangle(img, pt, (pt[0] + temp.shape[1], pt[1] + temp.shape[0]), (0, 0, 255), 2)
for pt in zip(*loc):# pt ===>(y,x),所以翻转一下
    left_upper = pt[::-1] # 翻转一下(x,y)
    right_lower = (pt[1] + w, pt[0] + h)
    cv.rectangle(img, left_upper, right_lower, (0, 0, 255), 2,cv.LINE_AA)
# 绘制出匹配的部分并且框出来
cv.imshow("img", img)
cv.waitKey()
cv.destroyAllWindows()

在这里插入图片描述

二、霍夫变换

2.1 理解霍夫变换

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

2.2 霍夫直线变换

使用API

lines=cv2.HoughLines(image, rho, theta, threshold)

  • image:输入图像,通常为二值图像,其中白点表示边缘点,黑点为背景。
  • rho:r的精度,以像素为单位,表示霍夫空间中每一步的距离增量, 值越大,考虑越多的线。
  • theta:角度θ的精度,通常以弧度为单位,表示霍夫空间中每一步的角度增量。值越小,考虑越多的线。
  • threshold:累加数阈值,只有累积投票数超过这个阈值的候选直线才会被返回。

返回值:cv2.HoughLines 函数返回一个二维数组,每一行代表一条直线在霍夫空间中的参数 (rho, theta)

2.3 统计概率霍夫直线变换

前面的方法又称为标准霍夫变换,它会计算图像中的每一个点,计算量比较大,另外它得到的是整一条线(r和θ),并不知道原图中直线的端点。所以提出了统计概率霍夫直线变换(Probabilistic Hough Transform),是一种改进的霍夫变换,它在获取到直线之后,会检测原图中在该直线上的点,并获取到两侧的端点坐标,然后通过两个点的坐标来计算该直线的长度,通过直线长度与最短长度阈值的比较来决定该直线要不要被保留。

使用API

lines=cv2.HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=0, maxLineGap=0)

  • image:输入图像,通常为二值图像,其中白点表示边缘点,黑点为背景。
  • rho:极径分辨率,以像素为单位,表示极坐标系中的距离分辨率。
  • theta:极角分辨率,以弧度为单位,表示极坐标系中角度的分辨率。
  • threshold:阈值,用于过滤掉弱检测结果,只有累计投票数超过这个阈值的直线才会被返回。
  • lines(可选):一个可初始化的输出数组,用于存储检测到的直线参数。
  • minLineLength(可选):最短长度阈值,比这个长度短的线会被排除。
  • maxLineGap(可选):同一直线两点之间的最大距离。当霍夫变换检测到一系列接近直角的线段时,这些线段可能是同一直线的不同部分。maxLineGap参数指定了在考虑这些线段属于同一直线时,它们之间最大可接受的像素间隔。

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

2.4 霍夫圆变换

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

使用API

circles=cv2.HoughCircles(image, method, dp, minDist, param1, param2)

  • image:输入图像,通常是灰度图像。

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

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

  • minDist:检测到的圆心之间的最小允许距离,以像素为单位。在霍夫变换检测圆的过程中,可能会检测到许多潜在的圆心。minDist 参数就是为了过滤掉过于接近的圆检测结果,避免检测结果过于密集。当你设置一个较小的 minDist 值时,算法会尝试找出尽可能多的圆,即使是彼此靠得很近的圆也可能都被检测出来。相反,当你设置一个较大的 minDist 值时,算法会倾向于只检测那些彼此间存在一定距离的独立的圆。

案例

案例一:霍夫直线变换

import numpy as np
import cv2 as cv

img = cv.imread("images/huofu.png")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 边缘检测
dst = cv.Canny(gray, 30, 70)
# 霍夫直线变换:lienes=cv2.HoughLines(img,rho,theta,threshold) # threshold是阈值,rho和theta是精度
lines = cv.HoughLines(dst, 0.8, np.pi / 180, 90)
# 遍历lines,去取每条直线的rho和theta
for line in lines:
    rho ,theta = line[0] # lines是二维数组,[[rho,theta]]
    sin_theta = np.sin(theta)
    cos_theta = np.cos(theta)
    x1,x2 = 0,img.shape[1]
    y1=int((rho-x1*cos_theta)/sin_theta)
    y2=int((rho-x2*cos_theta)/sin_theta)
    cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)

cv.imshow("img",img)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

案例二:统计概率霍夫直线变换

# 统计概率霍夫直线变换
import numpy as np
import cv2 as cv

img = cv.imread("images/huofu.png")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 边缘检测
dst = cv.Canny(gray, 30, 70)
# 统计概率霍夫直线变换
lines = cv.HoughLinesP(dst, 1, np.pi / 180, 10, minLineLength=10, maxLineGap=10)
for line in lines:
    x1, y1, x2, y2 = line[0]
    cv.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2,cv.LINE_AA)

cv.imshow("img", img)
cv.waitKey()
cv.destroyAllWindows()

在这里插入图片描述

案例三:霍夫圆变换

# 霍夫圆变换
import numpy as np
import cv2 as cv

img = cv.imread("images/huofu.png")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 边缘检测
dst = cv.Canny(gray, 30, 70)
# 霍夫圆变换
circles = cv.HoughCircles(dst, cv.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=0, maxRadius=0)
# 数据处理
circles = np.uint16(np.around(circles))
for circle in circles:
    x,y,r = circle[0]
    cv.circle(img, (x,y), r, (0,255,0), 2,cv.LINE_AA)
cv.imshow("img", img)
cv.waitKey()
cv.destroyAllWindows()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值