OpenCV中的模板匹配
OpenCV中的模板匹配是支持基于NCC相似度查找的,但是不是很好用,一個(gè)主要的原因是查找最大閾值,只能匹配一個(gè),自己比對(duì)閾值,又導(dǎo)致無法正確設(shè)定閾值范圍,所以問題很多。于是我重新寫了純Python版本的NCC圖像模板匹配的代碼實(shí)現(xiàn)了一個(gè)Python版本的,簡單易用,支持多尺度,跟多進(jìn)程并行!
主要思想
主要是基于NCC實(shí)現(xiàn)的像素相似度計(jì)算,這個(gè)OpenCV官方的模板匹配也有這中方式像素相似度計(jì)算支持,它的公式描述如下:
就是參照這個(gè)公式,然后基于OpenCV提供的積分圖計(jì)算函數(shù),實(shí)現(xiàn)了NCC相似度比較計(jì)算,值在0~1之間,1表示完全相似,0表示完全不相似。
代碼實(shí)現(xiàn)
我把整個(gè)部分搞成了一個(gè)類,調(diào)用的方法主要是run_match,就可以直接運(yùn)行,完成模板匹配。大體的功能跟OpenCV實(shí)現(xiàn)的模板匹配功能比較相似,改進(jìn)的地方就是比較方便的實(shí)現(xiàn)多個(gè)對(duì)象匹配的直接輸出Box框。該類完整的代碼實(shí)現(xiàn)如下:
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相關(guān)的測(cè)試與調(diào)用代碼如下:
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()模板圖像:
運(yùn)行結(jié)果如下:
-
算法
+關(guān)注
關(guān)注
23文章
4592瀏覽量
92524 -
圖像
+關(guān)注
關(guān)注
2文章
1080瀏覽量
40378 -
OpenCV
+關(guān)注
關(guān)注
29文章
625瀏覽量
41218
原文標(biāo)題:只用半小時(shí) | OpenCV手寫圖像模板匹配算法
文章出處:【微信號(hào):CVSCHOOL,微信公眾號(hào):OpenCV學(xué)堂】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論