OpenCV中的模板匹配
OpenCV中的模板匹配是支持基于NCC相似度查找的,但是不是很好用,一個主要的原因是查找最大閾值,只能匹配一個,自己比對閾值,又導致無法正確設定閾值范圍,所以問題很多。于是我重新寫了純Python版本的NCC圖像模板匹配的代碼實現了一個Python版本的,簡單易用,支持多尺度,跟多進程并行!
主要思想
主要是基于NCC實現的像素相似度計算,這個OpenCV官方的模板匹配也有這中方式像素相似度計算支持,它的公式描述如下:

就是參照這個公式,然后基于OpenCV提供的積分圖計算函數,實現了NCC相似度比較計算,值在0~1之間,1表示完全相似,0表示完全不相似。
代碼實現
我把整個部分搞成了一個類,調用的方法主要是run_match,就可以直接運行,完成模板匹配。大體的功能跟OpenCV實現的模板匹配功能比較相似,改進的地方就是比較方便的實現多個對象匹配的直接輸出Box框。該類完整的代碼實現如下:
importcv2ascv importnumpyasnp importtime importconcurrent.futures classNCCTemplateMatch: def__init__(self,ref_imgs,target_imgs,scores,tpl_sums,tpl_sqr_sums,target_sums,target_sqr_sums): self.ref_imgs=ref_imgs self.target_imgs=target_imgs self.scores=scores self.tpls_sums=tpl_sums self.tpls_sqsums=tpl_sqr_sums self.target_sums=target_sums self.target_sqsums=target_sqr_sums self.nms_boxes=[] defrun_match(self): num_ps=min(6,len(self.ref_imgs)) #print("num_ps:",num_ps) start=time.perf_counter() withconcurrent.futures.ProcessPoolExecutor(num_ps)asexecutor: matched=executor.map(self.ncc_run,self.ref_imgs,self.target_imgs,self.tpls_sums,self.tpls_sqsums,self.target_sums,self.target_sqsums,self.scores) self.nms_boxes=list(matched) end=time.perf_counter() print(f'Finishedin{round(end-start,2)}seconds') defncc_run(self,tpl_gray,target_gray,tpl_sum,tpl_sqsum,target_sum,target_sqsum,score): print("runonce~~~~") th,tw=tpl_gray.shape min_step=max(1,min(th//16,tw//16)) h,w=target_gray.shape sr=1/(th*tw) t_s1=tpl_sum[th,tw] t_s1_2=t_s1*t_s1*sr t_s1_1=t_s1*sr t_s2=tpl_sqsum[th,tw] sum_t=np.sqrt(t_s2-t_s1_2) row=0 boxes=[] confidences=[] whilerow(h?-?th+1): ????????????col?=?0 ????????????while?col?(w?-?tw+1): ????????????????s1?=?self.get_block_sum(target_sum,?col,?row,?col?+?tw,?row?+?th) ????????????????s2?=?self.get_block_sum(target_sqsum,?col,?row,?col?+?tw,?row?+?th) ????????????????sum1?=?t_s1_1?*?s1 ????????????????ss_sqr?=?s2?-?s1?*?s1?*?sr ????????????????if?ss_sqr?0:??#?fix?issue,?精度問題 ????????????????????ss_sqr?=?0.0 ????????????????sum2?=?sum_t?*?np.sqrt(ss_sqr) ????????????????sum3?=?np.sum(np.multiply(tpl_gray,?target_gray[row:row?+?th,?col:col?+?tw])) ????????????????if?sum2?==?0.0: ????????????????????ncc?=?0.0 ????????????????else: ????????????????????ncc?=?(sum3?-?sum1)?/?sum2 ????????????????if?ncc?>score: boxes.append([col,row,tw,th]) confidences.append(float(ncc)) col+=tw//2 else: col+=min_step row+=min_step #NMSProcess nms_indices=cv.dnn.NMSBoxes(boxes,confidences,0.5,0.5) det_boxes=[] print(nms_indices) foriinrange(len(nms_indices)): rect_box=boxes[nms_indices[i]] det_boxes.append(rect_box) returndet_boxes defget_block_sum(self,integal_img,x1,y1,x2,y2): t1=integal_img[y1,x1] t2=integal_img[y1,x2] t3=integal_img[y2,x1] t4=integal_img[y2,x2] s=t4-t2-t3+t1 returns相關的測試與調用代碼如下:
print("testncc......")
tpl_image=cv.imread("D:/images/llk_tpl.png")
target_image=cv.imread("D:/images/llk.jpg")
tpl_gray=cv.cvtColor(tpl_image,cv.COLOR_BGR2GRAY)
target_gray=cv.cvtColor(target_image,cv.COLOR_BGR2GRAY)
tpl_gray=np.float32(tpl_gray/255.0)
target_gray=np.float32(target_gray/255.0)
tpl_sum,tpl_sqsum=cv.integral2(tpl_gray)
t_sum,t_sqsum=cv.integral2(target_gray)
matcher=NCCTemplateMatch([tpl_gray],[target_gray],[0.85],
[tpl_sum],[tpl_sqsum],[t_sum],[t_sqsum])
matcher.run_match()
forrect_boxinmatcher.nms_boxes[0]:
cv.rectangle(target_image,(rect_box[0],rect_box[1]),
(rect_box[0]+rect_box[2],rect_box[1]+rect_box[3]),(0,0,255),2,8,0)
cv.imshow("result",target_image)
cv.waitKey(0)
cv.destroyAllWindows()
模板圖像:

運行結果如下:


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
算法
+關注
關注
23文章
4784瀏覽量
98044 -
圖像
+關注
關注
2文章
1096瀏覽量
42326 -
OpenCV
+關注
關注
33文章
652瀏覽量
44787
原文標題:只用半小時 | OpenCV手寫圖像模板匹配算法
文章出處:【微信號:CVSCHOOL,微信公眾號:OpenCV學堂】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
熱點推薦
【觸覺智能 Purple Pi OH 開發板體驗】四、(Ubuntu)OpenCV手寫數字識別
]#===============計算最佳匹配值及模板序號======================# matchValue用于存儲所有匹配值matchValue = []# 從images
發表于 09-18 14:01
手寫圖像模板匹配算法在OpenCV中的實現
評論