簡介
算法的原理姿骏,可以參考這個篇博客:基于灰度的模板匹配算法及老。這里不再贅述,本文使用序貫相似性檢測算法(下面簡稱:SSDA)桐筏,實現對圖像模板的匹配
算法思路
參考博客纸型,可以整理出SSDA算法的整體思路:
- 確定子圖的左上角坐標范圍
- 遍歷所有可能的子圖
- 求模板圖和子圖的圖像均值
- 隨機取不重復的點,求模板圖和子圖中該點的值與其自身圖像均值的絕對誤差
- 累加絕對誤差梅忌,直到超過閾值
- 計算累加次數狰腌,則次數最多的子圖為匹配的最終圖像
代碼
根據算法思路,demo如下:
import time
import random
import cv2
import numpy as np
def Image_Mean_Value(Image):
res = np.sum((Image.astype("float"))) / float(Image.shape[0] * Image.shape[1])
return res
def Image_SSDA(search_img, example_img):
# 確定子圖的范圍
M = search_img.shape[0]
m = example_img.shape[0]
N = search_img.shape[1]
n = example_img.shape[1]
Range_x = M - m - 1
Range_y = N - n - 1
search_img = cv2.cvtColor(search_img, cv2.COLOR_RGB2GRAY)
example_img = cv2.cvtColor(example_img, cv2.COLOR_RGB2GRAY)
# 求模板圖的均值
example_MV = Image_Mean_Value(example_img)
R_count_MAX = 0
Best_x = 0
Best_y = 0
# 遍歷所有可能的子圖
for i in range(Range_x):
for j in range(Range_y):
R_count = 0
Absolute_error_value = 0
# 從搜索圖中截取子圖
subgraph_img = search_img[i:i+m, j:j+n]
# 求子圖的均值
search_MV = Image_Mean_Value(subgraph_img)
# 判斷是否超過閾值
while Absolute_error_value < SSDA_Th:
R_count += 1
# 取隨機的像素點
x = random.randint(0, m - 1)
y = random.randint(0, n - 1)
pv_s = subgraph_img[x][y]
pv_e = example_img[x][y]
# 計算絕對誤差值并累加
Absolute_error_value += abs((pv_e - example_MV) - (pv_s - search_MV))
# 將次數最多的子圖為匹配圖像
if R_count >= R_count_MAX:
R_count_MAX = R_count
Best_x = i
Best_y = j
# 返回最匹配圖像的坐標
return Best_x, Best_y
if __name__ == '__main__':
# 原圖路徑
srcImg_path = "C:\\Users\\PC\\Desktop\\SSDA\\src.jpg"
# 搜索圖像路徑
searchImg_path = "C:\\Users\\PC\\Desktop\\SSDA\\find.jpg"
# SSDA算法閾值
SSDA_Th = 10
src_img = cv2.imread(srcImg_path)
search_img = cv2.imread(searchImg_path)
start = time.perf_counter()
Best_x, Best_y = Image_SSDA(src_img, search_img)
end = time.perf_counter()
print("time:", end - start)
cv2.rectangle(src_img, (Best_y, Best_x), (Best_y + search_img.shape[1], Best_x + search_img.shape[0]), (0, 0, 255), 3)
cv2.imshow("src_img", src_img)
cv2.imshow("search_img", search_img)
cv2.waitKey(0)
說明:
- 閾值的設定:一開始將閾值設置的較大一些牧氮,保證算法的準確度琼腔;在多次測試后可以將閾值降低到合適的值。閾值越大踱葛,算法的精度約高丹莲,耗時也相對的會增加一些
- 隨機像素點的選妊湛蟆:算法中指出堡僻,應當選取不重復的像素點,代碼中直接使用了
random.randint()
來生成隨機數谢床,是會有重復的可能性含,但是概率不大洲赵,這里近似于不重復
結果
運行代碼,匹配結果如下:
總結
算法中指出胶滋,SSDA算法是對傳統(tǒng)模板匹配算法的改進,比傳統(tǒng)匹配算法快幾十到幾百倍悲敷。又上文可知究恤,SSDA算法匹配耗時18秒,我們使用傳統(tǒng)的SSD算法來實現相同的功能來測試下耗時后德。SSD算法的實現可以參考:基于SSD的圖像匹配算法
結果如下:
可以看到兩者都達到了較好的匹配效果部宿,但SSD算法耗時28秒,確實SSDA算法的速度優(yōu)于SSD算法