# opencv的模板匹配方法

2021-09-30 13:34:54  阅读：108  来源： 互联网

# 模板匹配

``````import cv2
import numpy as np

result = cv2.matchTemplate(img, tpl, cv2.TM_CCORR_NORMED)
# 返回的max_loc 是按照Opencv 的坐标(x, y)，不是numpy的(row, col)
(_, max_val, _, max_loc) = cv2.minMaxLoc(result)
# 利用最大值*0.99 作为阈值，阈值可根据情况设置
threshold = max_val * 0.99
# loc = [[x1, x2, x3...], [y1, y2, y3]]  注意和numpy的row col转换
loc = np.where(result >= threshold)

tr = img.copy()
for pt in zip(*loc[::-1]):
cv2.rectangle(tr, pt, (pt[0] + tw, pt[1] + th), (0, 0, 255), 1)
``````

``````result = cv2.matchTemplate(img, tpl, cv2.TM_CCORR_NORMED)
``````

`loc`返回值是一个二维矩阵：`[[row0, row1, row2, ...],[col0, col1, col2, ...]]``(row0, col0)`是指在result中row0行col0列符合条件。

`*loc[::-1]`最前方的*，是解除一层[]，例如`a = np.array([[1, 2],[5, 6]])``*a``[1, 2], [5, 6]`

``````th, tw = tpl.shape[:2]
loc = np.where(result >= threshold)
score = result[result >= max_val*0.99] # 返回的是值，值原来顺序变为一维矩阵

xmin = np.array(loc[1])
ymin = np.array(loc[0])
xmax = xmin + tw
ymax = ymin + th
# 全部转为一维列向量
xmin, ymin, xmax, ymax = xmin.reshape(-1, 1), ymin.reshape(-1, 1), xmax.reshape(-1, 1), ymax.reshpae(-1, 1)
score = score.reshape(-1, 1)

data_hlist = []
data_hlist.append(xmin); data_hlist.append(ymin); data_hlist.append(xmax); data_hlist.append(ymax); data_hlist.append(score)
data_hstack = np.hstack(data_hlist) #按照 xmin, ymin, xmax, ymax, score 顺序
thresh = 0.3 #设置NMS交互比
keep_dets = py_nms(data_hstack, thresh)
dets = data_hstack[keep_dets]

tr = img.copy()
for rec in dets:
cv2.rectangle(tr, (int(rec[0]), int(rec[1])), (int(rec[2]), int(rec[3])), (0, 0, 255), 2)
``````

``````# NMS 非极大值抑制
def py_nms(dets, thresh):
"""Pure Python NMS baseline."""
# x1、y1、x2、y2、以及score賦值
# （x1、y1）（x2、y2）為box的左上和右下角坐标
x1 = dets[:, 0]
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, 4]
# 每一个候选框的面积
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
# order是按照score降序排序的有，返回的是索引数组，[::-1]为了将升序变为降序
order = scores.argsort()[::-1]
keep = []
while order.size > 0:
i = order[0]
keep.append(i)
# 计算当前概率最大矩形框与其他矩形框的相交框的坐标，得到的是向量
xx1 = np.maximum(x1[i], x1[order[1:]]) # x1[i]虽然为一个数，但是由于numpy的broadcast机制，xx1是一个数组
yy1 = np.maximum(y1[i], y1[order[1:]])
xx2 = np.minimum(x2[i], x2[order[1:]])
yy2 = np.minimum(y2[i], y2[order[1:]])
# 计算相交框的面积,注意矩形框不相交时w或h算出來会是负数，用0代替
w = np.maximum(0.0, xx2 - xx1 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
# 计算重叠度IOU：重叠面积/（面积1+面积2-重叠面积）
ovr = inter / (areas[i] + areas[order[1:]] - inter)
# 找到重叠度不高于阈值的矩形框索引
inds = np.where(ovr <= thresh)[0]
# 将order序列更新，由于前面得到的矩形框索引要比矩形框在原order序列中的索引小1，所以要把这个1加回來
order = order[inds + 1]
return keep
``````

2. 关于本站的所有留言、评论、转载及引用，纯属内容发起人的个人观点，与本站观点和立场无关；
3. 关于本站的所有言论和文字，纯属内容发起人的个人观点，与本站观点和立场无关；
4. 本站文章均是网友提供，不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属；如您发现该文章侵犯了您的权益，可联系我们第一时间进行删除；
5. 本站为非盈利性的个人网站，所有内容不会用来进行牟利，也不会利用任何形式的广告来间接获益，纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。