最优化方法实现亚像素精度模板匹配

本文最后更新于:2023年4月15日 晚上

之前实现了 通过函数拟合实现亚像素模板匹配 ,但由于模型是自己创建的,用于拟合真实模型,必定会引入误差,可以使用不拟合建模的方法直接最优化获取亚像素模板匹配结果。

实现思路

  1. 和拟合的亚像素模板匹配类似,在像素级的模板匹配基础上,在其附近搜索亚像素位置。

  2. 构建一个关于亚像素位置的模型,那就需要想办法将位置设置为模型参数,构建损失函数。

  3. 通过最优化的方法搜索使得损失函数最低的模型参数,将其作为结果输出。

Python 实现

在像素级模板匹配结果附近搜索精确解;

利用 OpenCV 的 remap 函数进行线性插值,得到亚像素图像,与模板比对 MSE 作为 Loss 函数,优化就完了。

示例函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import cv2
import numpy as np
from scipy.optimize import minimize


def img_subpixel_match(img, golden_img):

H, W = golden_img.shape[:2]

res = cv2.matchTemplate(img, golden_img, cv2.TM_SQDIFF)
min_score, _, (x_pos, y_pos), _ = cv2.minMaxLoc(res)

x_map = np.arange(W).astype('float32') + x_pos
y_map = np.arange(H).astype('float32') + y_pos

xmap, ymap = np.meshgrid(x_map, y_map)

def Loss(X):
dx, dy = X
X_list = xmap + dx
Y_list = ymap + dy
loss = ((cv2.remap(img, X_list, Y_list, cv2.INTER_LINEAR) - golden_img) ** 2).sum()
return loss

x0 = np.asarray((0.0, 0.0))
opt_res = minimize(Loss, x0, method='COBYLA')

sub_pix_x = x_pos + opt_res.x[0]
sub_pix_y = y_pos + opt_res.x[1]

return sub_pix_x, sub_pix_y

该结果相比于 Halcon 的 NCC 模板亚像素精度匹配的结果偏差:

Pixel X Y
偏差 0.0123 0.0208

该偏差要小于曲线拟合的误差,我觉得问题在于少了中间的模型拟合,少了中间的误差。

参考资料



文章链接:
https://www.zywvvd.com/notes/study/image-processing/template-match/opti-subpixel-tm/opti-subpixel-tm/


最优化方法实现亚像素精度模板匹配
https://www.zywvvd.com/notes/study/image-processing/template-match/opti-subpixel-tm/opti-subpixel-tm/
作者
Yiwei Zhang
发布于
2023年4月10日
许可协议