所谓模板匹配,就是在给定的图片中查找和模板最相似的区域,该算法的输入包括模板和图片,整个任务的思路就是按照滑窗的思路不断的移动模板图片,计算其与图像中对应区域的匹配度,最终将匹配度最高的区域选择为最终的结果。
- 原图像(I):在这幅图中,找到与模板相匹配的区域
- 模板(T):与原图像进行比对的图像块
获得上述图像后,查找最大值所在的位置,那么该位置对应的区域就被认为是最匹配的。对应的区域就是以该点为定点,长宽和模板图像一样大小的矩阵。
做一个梅西的模板,以梅西的脸部为模板,分别检测几种不同的检测方法
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('images/messi5.jpg', 0)
img2 = img.copy()
template = cv.imread('images/messi_face.jpg', 0)
w, h = template.shape[::-1]
# All the 3 methods for comparison in a list
methods = ['cv.TM_CCOEFF', 'cv.TM_CCORR', 'cv.TM_SQDIFF']
for meth in methods:
img = img2.copy()
method = eval(meth)
# Apply template Matching
res = cv.matchTemplate(img, template, method)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
# If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv.rectangle(img, top_left, bottom_right, 255, 2)
plt.subplot(121), plt.imshow(res, cmap='gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img, cmap='gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.suptitle(meth)
plt.show()
cv.TM_CCOEFF:
cv.TM_CCORR:
cv.TM_SQDIFF:
注: 可以看到使用cv.TM_CCORR的结果不如我们预期的那样好。
在上面我们搜索了梅西的脸的图像,在图像中只出现了一次。假设您正在搜索一个多次出现的对 象,cv.minMaxLoc()不会给出所有的位置。在这种情况下,我们将使用阈值化。在这个例子中,我们将使用著名游戏马里奥的截图,我们将在其中找到硬币。
python zip()函数:
- zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
- 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。zip(*loc[::-1])
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img_rgb = cv.imread('images/mario.jpg')
img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
template = cv.imread('images/coin.jpg', 0)
w, h = template.shape[::-1]
res = cv.matchTemplate(img_gray, template, cv.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
cv.imshow('res.png', img_rgb)
cv.waitKey(0)
cv.destroyAllWindows()
霍夫变换常用来提取图像中的直线和圆等几何形状,详情如下介绍:
假设有一个大小为100 * 100的图片,使用霍夫变换检测图片中的直线,则步骤如下所示:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from matplotlib import font_manager
#设置字体
my_font = font_manager.FontProperties(fname="C:/Windows/Fonts/STHUPO.TTF")
#1、加载图片,转换二值图
img = cv.imread("./images/feilin.jpg")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 100)
#2、霍夫线变换
lines = cv.HoughLines(edges, 0.8, np.pi / 180, 150)
#3、将检测到的线绘制在图像上(注意是极坐标)
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))
cv.line(img, (x1, y1), (x2, y2), (0, 255, 0))
#4、图像显示
plt.figure(figsize=(10,8), dpi=100)
plt.imshow(img[:,:,::-1])
plt.title("霍夫变换线检测", fontproperties=my_font)
plt.xticks([]), plt.yticks([])
plt.show()
介绍:cv.circle(img,(520,430),300,(255,0,0),8)
- 在img原始图片中划圈,其圈的中心点为(520,430),半径=300,颜色为(255,0,0),粗细=8
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from matplotlib import font_manager
#字体设置
my_font = font_manager.FontProperties(fname="C:/Windows/Fonts/STHUPO.TTF")
#1、读取图像,并转换为灰度图
plants = cv.imread("./images/star.jpg")
gray_img = cv.cvtColor(plants, cv.COLOR_BGR2GRAY)
#2、进行中值滤波,去除噪点
img = cv.medianBlur(gray_img, 7)
#3、霍夫圆检测
circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1, 100, param1=100, param2=30, minRadius=0, maxRadius=100)
#4、将检测结果绘制在图像上
for i in circles[0, :]: #遍历矩阵每一行的数据
#绘制图形
cv.circle(plants, (i[0], i[1]), i[2], (0,0,255), 2)
#绘制圆心
cv.circle(plants, (i[0], i[1]), 2, (0,0,255), 3)
#5、图像显示
plt.figure(figsize=(10, 8), dpi=100)
plt.imshow(plants[:,:,::-1])
plt.title("霍夫变换圆检测", fontproperties=my_font)
plt.xticks([]),plt.yticks([])
plt.show()