图像拼接是一种通过结合多个图像来创建一个单一、更广阔的图像视角的技术。本文特别介绍了使用Harris角点检测算法来识别图像中的关键特征点,以及应用RANSAC算法来确保这些特征点之间的精确匹配,从而实现高质量的图像对齐和无缝拼接
代码思路
- Harris角点检测:使用Harris角点检测算法来识别图像中的角点,这些角点用于后续的图像匹配和拼接。
- 角点位置提取:从Harris角点响应中提取显著的角点,并使用非极大值抑制技术确保角点之间保持一定的最小距离。
- 特征描述符提取:为每个检测到的角点生成局部特征描述符,这些描述符用于在不同图像间进行角点匹配。
- 特征匹配:通过比较不同图像的特征描述符,找出最佳匹配的特征点对,这是图像拼接前的关键步骤。
- RANSAC算法估计最佳平移:使用RANSAC算法估算图像间的最佳平移向量,从而准确地对齐和拼接两幅图像。
- 图像拼接:根据RANSAC算法得到的平移参数,将两幅图像拼接成一幅更大的图像。
Harris角点检测
‘harris_corner_detection’ 该函数计算图像的Harris角点响应。通过计算图像的梯度、梯度的乘积,以及这些乘积的高斯滤波,最后计算每个像素的Harris响应值。
- 梯度计算:
使用高斯滤波器的导数计算图像在x和y方向上的梯度(Ix和Iy)。高斯滤波同时减少噪声的影响。 - 构建Harris矩阵的元素:
计算梯度的平方和乘积(Ix2, Iy2, IxIy),并使用高斯滤波平滑这些值,以获得积分效应。 - 计算Harris响应:
使用公式R = det(M) - k * trace(M)^2来计算每个像素的Harris响应,其中M是由梯度构成的结构张量。这里使用了简化版本,考虑det(M)与trace(M)的比例。
def harris_corner_detection(image, sigma=1):
# Compute gradients
Ix = gaussian_filter(image, sigma=sigma, order=[0, 1])
Iy = gaussian_filter(image, sigma=sigma, order=[1, 0])
# Compute products of derivatives
Ix2 = gaussian_filter(Ix**2, sigma)
Iy2 = gaussian_filter(Iy**2, sigma)
IxIy = gaussian_filter(Ix * Iy, sigma)
# Compute the Harris response
detM = Ix2 * Iy2 - IxIy**2
traceM = Ix2 + Iy2
R = detM / (traceM + 1e-6)
return R
角点位置提取
‘get_harris_points’ 根据Harris响应选择显著的角点。首先,设定一个阈值来选择较强的角点,然后采用非极大值抑制,确保角点之间有足够的空间分布。
- 阈值处理:
基于Harris响应的最大值设定一个阈值,选取超过此阈值的点作为角点候选。 - 非极大值抑制:
确保选取的角点在其周围(由min_dist定义)具有最大的响应,从而避免角点过于集中。
def get_harris_points(harrisim, min_dist=10, threshold=0.1):
# Calculate the threshold value based on the maximum value in the Harris response image.
corner_threshold = harrisim.max() * threshold
# Create a binary image that marks where the Harris response values are above the threshold.
harrisim_t = (harrisim > corner_threshold) * 1
# Find coordinates of these pixels.
coords = np.array(harrisim_t.nonzero()).T
# Get the Harris response values of these coordinates for sorting.
candidate_values = [harrisim[c[0], c[1]] for c in coords]
# Sort indices by corner strength in descending order.
indices = np.argsort(candidate_values)[::-1]
# Create an array to allow marking the vicinity of corners as occupied.
allowed_locations = np.zeros(harrisim.shape, dtype=bool)
# Avoid edges by marking the minimum distance from the image boundary as True.
allowed_locations[min_dist:-min_dist, min_dist:-min_dist] = True
# List to hold the final coordinates of detected corners.
filtered_coords = []
# Iterate through sorted corner candidates.
for i in indices:
r, c = coords[i]
if allowed_locations[r, c]: # Check if the spot is still available.
# If unoccupied, add to the final list and mark the surrounding area as occupied.
filtered_coords.append((r, c))
allowed_locations[(r-min_dist):(r+min_dist+1), (c-min_dist):(c+min_dist+1)] = False