OpenCV 模板匹配去重
程序员文章站
2023-12-25 23:59:51
...
根据不同匹配结果间的距离远近进行去重操作。
检测效果
源码
import cv2
import numpy as np
import time
def get_ready():
#录入模板,主函数仅执行一次,节省资源
template = cv2.imread('./template.png',0)
return template
def get_img(cap):
#从摄像头实时读取一帧图像
_,img_bgr = cap.read()
return img_bgr
def match_template(img_bgr,template):
#调用opencv内部模块进行模板匹配
img_gray = cv2.cvtColor(img_bgr,cv2.COLOR_BGR2GRAY)
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.5 #匹配相似度阈值,越高越精确
loc = np.where(res>=threshold) #numpy进行筛选匹配
loc1 = [] #用于录入目标坐标点
for i in range(len(list(loc[0]))):
loc1.append(list(zip(*loc[::-1]))[i])
return loc1,res
def elim_same(loc1):
#根据匹配结果的坐标间距进行去重
count = len(loc1)
threshold1 = 10 #10个像素点以内则视为同一目标
i = 0
while(i<count):
for j in range(count):
if j != i:
if np.abs(loc1[j][0]-loc1[i][0]) <= threshold1: #x坐标
if np.abs(loc1[j][1]-loc1[i][1]) <= threshold1: #y坐标
loc1[j] = loc1[i] #近似坐标归一处理
i += 1
resl = set(loc1) #去除归一后的多余结果,完成去重
return resl
def draw_write(img_bgr,resl,res):
#绘制图框与相似度数字
for pt in resl:
cv2.rectangle(img_bgr,pt,(pt[0]+w,pt[1]+h),(0,255,0),2)
template_num = round(res[pt[1]][pt[0]],2) #四舍五入取两位小数
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img_bgr,'%s'%template_num,(pt[0],pt[1]-5),font,0.5,(0,255,0),1,cv2.LINE_AA)
def off(cap):
#键盘检测与摄像头释放
k = cv2.waitKey(5) & 0xFF
if k == 27:
cv2.destroyAllWindows()
cap.release()
return k
def main():
k = 0
template = get_ready()
global w,h
w,h = template.shape[::-1]
cap = cv2.VideoCapture(0)
while True:
img_bgr = get_img(cap)
loc1,res = match_template(img_bgr,template)
resl = elim_same(loc1)
draw_write(img_bgr,resl,res)
cv2.imshow('detected',img_bgr)
time.sleep(0.1)
k = off(cap)
if k == 27:
break
if __name__ == '__main__':
main()
代码难点
矩阵处理,较为抽象。
-
numpy.where()
原理:矩阵元素筛选 -
loc1.append(list(zip(*loc[::-1]))[i])
列表切片调换y、x坐标顺序,并用zip(*zipped)完成矩阵转置
list转换为列表格式,并append并入新列表。