
HPatches 数据集实战5步复现 Patch2Pix 论文 MMA 与 Homography 评估1. 环境准备与数据加载在开始复现 Patch2Pix 论文评估前我们需要配置合适的 Python 环境并正确加载 HPatches 数据集。以下是关键步骤# 安装必要库 pip install torch torchvision opencv-python numpy matplotlibHPatches 数据集包含 116 个序列分为两类i_xxx光照变化序列57个v_xxx视角变化序列59个数据集目录结构示例hpatches-sequences-release/ ├── i_xxx1/ │ ├── 1.ppm # 参考图像 │ ├── 2.ppm # 目标图像 │ ├── H_1_2 # 单应性矩阵 │ └── info.txt # 变化类型说明 └── v_xxx2/ ├── 1.ppm ├── 2.ppm ├── H_1_2 └── info.txt数据加载核心代码import os import cv2 import numpy as np def load_hpatches_sequence(seq_path): 加载单个HPatches序列 ref_img cv2.imread(os.path.join(seq_path, 1.ppm), cv2.IMREAD_GRAYSCALE) tgt_img cv2.imread(os.path.join(seq_path, 2.ppm), cv2.IMREAD_GRAYSCALE) H np.loadtxt(os.path.join(seq_path, H_1_2)) with open(os.path.join(seq_path, info.txt)) as f: change_type f.read().strip() return ref_img, tgt_img, H, change_type2. 特征点检测与匹配实现Patch2Pix 的核心创新在于其端到端的特征点检测与匹配网络架构。以下是关键实现步骤2.1 网络架构概述Patch2Pix 采用双分支结构特征提取分支基于 ResNet 的共享权重编码器匹配分支包含可微分的匹配层和精炼模块import torch import torch.nn as nn class Patch2Pix(nn.Module): def __init__(self): super().__init__() # 特征提取网络 self.encoder ResNetFPN() # 匹配网络 self.matcher nn.Sequential( CorrelationLayer(), MatchingLayer(), RefinementModule() ) def forward(self, img1, img2): feat1 self.encoder(img1) feat2 self.encoder(img2) matches self.matcher(feat1, feat2) return matches2.2 匹配点计算实现匹配点计算的三个关键步骤特征提取获取多尺度特征图相关性计算建立特征点对应关系匹配精炼使用迭代优化提升匹配质量def compute_matches(model, img1, img2): 计算图像对间的匹配点 # 转换为PyTorch张量并归一化 img1_tensor normalize(to_tensor(img1)) img2_tensor normalize(to_tensor(img2)) # 前向传播获取匹配 with torch.no_grad(): matches model(img1_tensor.unsqueeze(0), img2_tensor.unsqueeze(0)) # 转换为numpy数组并过滤低质量匹配 matches matches.squeeze().cpu().numpy() valid_matches matches[matches[:,4] 0.7] # 置信度阈值 return valid_matches[:,:4] # 返回(x1,y1,x2,y2)3. MMA 评估指标实现Mean Matching Accuracy (MMA) 是衡量特征匹配质量的核心指标计算步骤如下3.1 MMA 计算原理将参考图像点通过单应性矩阵投影到目标图像计算投影点与实际匹配点的欧氏距离统计不同阈值下的正确匹配比例def compute_mma(matches, H, img_shape, thresholdsrange(1,11)): 计算多阈值下的MMA指标 :param matches: (N,4)数组每行表示(x1,y1,x2,y2) :param H: (3,3)单应性矩阵 :param img_shape: 图像尺寸(h,w) :param thresholds: 误差阈值列表 :return: 各阈值下的MMA值 h, w img_shape query_pts matches[:,:2] # 参考图像点 ref_pts matches[:,2:] # 目标图像点 # 将参考点通过单应性变换投影 query_h np.concatenate([query_pts, np.ones((len(query_pts),1))], axis1) proj_pts (H query_h.T).T proj_pts proj_pts[:,:2] / proj_pts[:,2:] # 齐次坐标转笛卡尔坐标 # 计算投影误差 errors np.linalg.norm(ref_pts - proj_pts, axis1) # 计算各阈值下的准确率 mma [] for thresh in thresholds: correct (errors thresh).mean() mma.append(correct) return np.array(mma)3.2 批量评估实现对整个数据集的评估流程def evaluate_mma(model, dataset_path): sequences [d for d in os.listdir(dataset_path) if d.startswith((i_,v_))] # 初始化结果存储 mma_all np.zeros(10) mma_i np.zeros(10) # 光照变化 mma_v np.zeros(10) # 视角变化 counts {i:0, v:0} for seq in sequences: # 加载数据 seq_path os.path.join(dataset_path, seq) img1, img2, H, change_type load_hpatches_sequence(seq_path) # 计算匹配 matches compute_matches(model, img1, img2) # 计算MMA mma compute_mma(matches, H, img1.shape) # 累计结果 mma_all mma if change_type i: mma_i mma counts[i] 1 else: mma_v mma counts[v] 1 # 计算平均MMA mma_all / len(sequences) mma_i / counts[i] mma_v / counts[v] return {overall: mma_all, illumination: mma_i, viewpoint: mma_v}4. 单应性估计评估除了MMA单应性估计精度也是重要评估指标4.1 单应性矩阵估计使用RANSAC算法从匹配点估计单应性矩阵import cv2 def estimate_homography(matches, ransac_thresh3.0): 从匹配点估计单应性矩阵 :param matches: (N,4)数组(x1,y1,x2,y2) :param ransac_thresh: RANSAC阈值(像素) :return: 估计的单应性矩阵 src_pts matches[:,:2] dst_pts matches[:,2:] H, mask cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, ransac_thresh) return H4.2 单应性精度评估通过角点重投影误差评估单应性估计质量def evaluate_homography(H_pred, H_gt, img_size): 评估单应性矩阵估计精度 :param H_pred: 预测的单应性矩阵 :param H_gt: 真实单应性矩阵 :param img_size: 图像尺寸(w,h) w, h img_size corners np.array([ [0, 0, 1], [0, w-1, 1], [h-1, 0, 1], [h-1, w-1, 1] ]) # 计算真实和预测的角点位置 real_warped (corners H_gt.T) real_warped real_warped[:,:2] / real_warped[:,2:] pred_warped (corners H_pred.T) pred_warped pred_warped[:,:2] / pred_warped[:,2:] # 计算平均重投影误差 mean_dist np.mean(np.linalg.norm(real_warped - pred_warped, axis1)) # 计算不同阈值下的正确率 thresholds [1, 3, 5, 10] correctness [float(mean_dist t) for t in thresholds] return mean_dist, correctness5. 结果分析与论文对比完成评估后我们需要将结果与 Patch2Pix 论文报告的数据进行对比5.1 MMA 结果对比典型 Patch2Pix 论文结果在 HPatches 上阈值(pixel)光照变化(i)视角变化(v)总体162.145.353.7385.472.679.0592.183.487.81096.892.394.65.2 单应性估计对比单应性估计精度角点误差≤3px的比例方法光照变化视角变化总体Patch2Pix89.2%78.5%83.9%SuperPoint82.4%70.1%76.3%D2-Net76.8%65.3%71.1%5.3 可视化分析使用 Matplotlib 绘制 MMA 曲线import matplotlib.pyplot as plt def plot_mma_results(results): thresholds range(1,11) plt.figure(figsize(10,6)) plt.plot(thresholds, results[overall], b-o, labelOverall) plt.plot(thresholds, results[illumination], g--s, labelIllumination) plt.plot(thresholds, results[viewpoint], r-.d, labelViewpoint) plt.xlabel(Threshold (pixels)) plt.ylabel(Matching Accuracy) plt.title(MMA Evaluation on HPatches) plt.grid(True) plt.legend() plt.show()通过以上五个步骤我们完整实现了 Patch2Pix 论文在 HPatches 数据集上的评估流程。实际应用中可以根据需要调整匹配阈值、RANSAC参数等关键参数以获得最佳性能。