模式匹配方法总结及实现
一. 模式匹配简介:
模式匹配 ——> 寻找待匹配图像和全体图像中最相似的部分,常用于物体检测任务。虽然现在使用卷积神经网络做物体检测任务有更好的效果,但是模式匹配是最基本的物体检测方法,它很基础,很重要。
二. 模式匹配算法:
原图像为 I(H X W),待匹配图像为 T(h X w)。
1. 对于图像 I:,for j in range(H-h):for i in range(W-w) 。在一次移动一像素的过程中,计算原图像的一部分 I[j:j+h,i:i+w] 与待匹配图像 T 的相似度 S。
注:像模式匹配这样,从图像的左上角开始向右顺序进行查找的操作称为光栅扫描(Raster Scan),或滑动窗口扫描(Sliding window)。
2. S 最大或者最小的地方即为匹配到的位置。
S 的计算方法主要有 SSD(Sum of Squared Difference:误差平方和)、SAD(Sum of Absolute Differences:误差绝对值和)、NCC(Normalization Cross Correlation:归一化交叉相关)、ZNCC(Zero-mean Normalization Cross Correlation:零均值归一化交叉相关),对于不同的方法,我们需要选择出 S 的最大值或者最小值,然后找到 S 的值对应的在原图像中的位置。
三. 不同的模式匹配标准(不同的 S)
S = SSD(Sum of Squared Difference),S 取最小的值。
python实现核心代码:_v = np.sum((img[y:y+Ht, x:x+Wt] - temp) ** 2)
S = SAD(Sum of Absolute Differences),S 取最小的值。
python实现核心代码:_v = np.sum(np.abs(img[y:y+Ht, x:x+Wt] - temp))
S = NCC(Normalization Cross Correlation),S 取最大的值。求出两个图像的相似度,S 的范围为[-1,1],S 对变化十分敏感。
python实现核心代码:_v = np.sum(img[y:y+Ht, x:x+Wt] * temp)
_v /= (np.sqrt(np.sum(img[y:y+Ht, x:x+Wt]**2)) * np.sqrt(np.sum(temp**2)))
S = ZNCC(Zero-mean Normalization Cross Correlation),S 取最大的值。它比归一化交叉相关更加敏感。图像 I 的平均值为 m_i,图像 T 的平均值为 m_t。S 的范围为 [-1,1]。
python实现核心代码:_v = np.sum((img[y:y+Ht, x:x+Wt]-mi) * (temp-mt))
_v /= (np.sqrt(np.sum((img[y:y+Ht, x:x+Wt]-mi)**2)) * np.sqrt(np.sum((temp-mt)**2)))
四. python实现零均值归一化交叉相关。不同的 S ,读者可举一反三
1 import cv2 as cv 2 3 import numpy as np 4 5 # Read image 6 7 img = cv.imread("../bird.png").astype(np.float32) 8 9 H, W, C = img.shape 10 11 mi = np.mean(img) 12 13 # Read templete image 14 15 temp = cv.imread("../bird_e.png").astype(np.float32) 16 17 Ht, Wt, Ct = temp.shape 18 19 mt = np.mean(temp) 20 21 # Templete matching 22 23 i, j = -1, -1 24 25 v = -1 26 27 for y in range(H-Ht): 28 29 for x in range(W-Wt): 30 31 _v = np.sum((img[y:y+Ht, x:x+Wt]-mi) * (temp-mt)) 32 33 _v /= (np.sqrt(np.sum((img[y:y+Ht, x:x+Wt]-mi)**2)) * np.sqrt(np.sum((temp-mt)**2))) 34 35 if _v > v: 36 37 v = _v 38 39 i, j = x, y 40 41 out = img.copy() 42 43 cv.rectangle(out, pt1=(i, j), pt2=(i+Wt, j+Ht), color=(0,0,255), thickness=1) 44 45 out = out.astype(np.uint8) 46 47 # Save result 48 49 cv.imwrite("out.jpg", out) 50 51 cv.imshow("result", out) 52 53 cv.waitKey(0) 54 55 cv.destroyAllWindows()
五. 实验结果:
六. python实现 S=误差绝对值之和。不同的 S ,读者可举一反三
1 import cv2 2 3 import numpy as np 4 5 # Read image 6 7 img = cv2.imread("../baby.png").astype(np.float32) 8 9 H, W, C = img.shape 10 11 # Read templete image 12 13 temp = cv2.imread("../baby_m.png").astype(np.float32) 14 15 Ht, Wt, Ct = temp.shape 16 17 # Templete matching 18 19 i, j = -1, -1 20 21 v = 255 * H * W * C 22 23 for y in range(H-Ht): 24 25 for x in range(W-Wt): 26 27 _v = np.sum(np.abs(img[y:y+Ht, x:x+Wt] - temp)) 28 29 if _v < v: 30 31 v = _v 32 33 i, j = x, y 34 35 out = img.copy() 36 37 # (0,0,255) 代表红色 38 39 cv2.rectangle(out, pt1=(i, j), pt2=(i+Wt, j+Ht), color=(0,0,255), thickness=2) 40 41 out = out.astype(np.uint8) 42 43 # Save result 44 45 cv2.imwrite("out.jpg", out) 46 47 cv2.imshow("result", out) 48 49 cv2.waitKey(0) 50 51 cv2.destroyAllWindows()
七. 实验结果:
八. 写在最后的话:
感谢您的阅读,如果您觉得本文不错,可以点赞哦!
九. 版权声明:
未经作者允许,请勿随意转载抄袭,抄袭情节严重者,作者将考虑追究其法律责任,创作不易,感谢您的理解和配合!