LIFT算法特征提取流程,附代码
时间: 2023-11-25 11:22:09 浏览: 139
SIFT特征提取程序
LIFT算法的特征提取流程可以概括为以下步骤:
1. 构建高斯金字塔和高斯差分金字塔
2. 在高斯差分金字塔上检测局部极值点
3. 对极值点进行精确定位和筛选
4. 为每个特征点计算主方向
5. 对每个特征点的邻域区域进行特征描述符的计算
下面是LIFT算法的Python实现代码:
```python
import cv2
import numpy as np
def buildGaussianPyramid(img, level):
"""构建高斯金字塔"""
pyr = [img]
for i in range(1, level):
pyr.append(cv2.pyrDown(pyr[i-1]))
return pyr
def buildDoGPyramid(pyr):
"""构建高斯差分金字塔"""
dog_pyr = []
for i in range(1, len(pyr)):
dog_pyr.append(pyr[i] - pyr[i-1])
return dog_pyr
def detectExtrema(dog_pyr, threshold):
"""在高斯差分金字塔上检测局部极值点"""
extrema = []
for i in range(len(dog_pyr)):
prev, curr, nxt = dog_pyr[max(i-1, 0):min(i+2, len(dog_pyr))]
candidates = np.zeros(curr.shape, dtype=np.bool)
candidates[1:-1, 1:-1] = np.logical_and(np.logical_and(curr[1:-1, 1:-1] > curr[:-2, 1:-1], curr[1:-1, 1:-1] > curr[2:, 1:-1]), np.logical_and(curr[1:-1, 1:-1] > curr[1:-1, :-2], curr[1:-1, 1:-1] > curr[1:-1, 2:]))
dx = (curr[1:-1, 2:] - curr[1:-1, :-2]) * 0.5
dy = (curr[2:, 1:-1] - curr[:-2, 1:-1]) * 0.5
ds = (nxt[1:-1, 1:-1] - prev[1:-1, 1:-1]) * 0.5
dxx = (curr[1:-1, 2:] + curr[1:-1, :-2] - 2 * curr[1:-1, 1:-1])
dyy = (curr[2:, 1:-1] + curr[:-2, 1:-1] - 2 * curr[1:-1, 1:-1])
dss = (nxt[1:-1, 1:-1] + prev[1:-1, 1:-1] - 2 * curr[1:-1, 1:-1])
dxy = (curr[2:, 2:] - curr[2:, :-2] - curr[:-2, 2:] + curr[:-2, :-2]) * 0.25
dxs = (nxt[1:-1, 2:] - nxt[1:-1, :-2] - prev[1:-1, 2:] + prev[1:-1, :-2]) * 0.25
dys = (nxt[2:, 1:-1] - nxt[:-2, 1:-1] - prev[2:, 1:-1] + prev[:-2, 1:-1]) * 0.25
D = np.array([[dxx, dxy, dxs], [dxy, dyy, dys], [dxs, dys, dss]])
dD = -np.linalg.det(D[:, :, 1:-1]) + threshold * np.trace(D[:, :, 1:-1]) ** 2
idx = np.argwhere(np.logical_and(candidates, np.abs(curr[1:-1, 1:-1] + 0.5 * np.dot(np.array([dx, dy, ds]).T, np.array([dD, dx, dy]))) >= threshold)
for r, c in idx:
extrema.append((i, r+1, c+1))
return extrema
def refineExtrema(dog_pyr, extrema):
"""对极值点进行精确定位和筛选"""
threshold = 0.03
sigma = 1.5
new_extrema = []
for level, row, col in extrema:
img = dog_pyr[level]
for i in range(5):
dx = (img[row, col+1] - img[row, col-1]) * 0.5
dy = (img[row+1, col] - img[row-1, col]) * 0.5
ds = (dog_pyr[level+1][row, col] - dog_pyr[level-1][row, col]) * 0.5
dxx = img[row, col+1] + img[row, col-1] - 2 * img[row, col]
dyy = img[row+1, col] + img[row-1, col] - 2 * img[row, col]
dss = dog_pyr[level+1][row, col] + dog_pyr[level-1][row, col] - 2 * img[row, col]
dxy = (img[row+1, col+1] - img[row+1, col-1] - img[row-1, col+1] + img[row-1, col-1]) * 0.25
dxs = (dog_pyr[level+1][row, col+1] - dog_pyr[level+1][row, col-1] - dog_pyr[level-1][row, col+1] + dog_pyr[level-1][row, col-1]) * 0.25
dys = (dog_pyr[level+1][row+1, col] - dog_pyr[level+1][row-1, col] - dog_pyr[level-1][row+1, col] + dog_pyr[level-1][row-1, col]) * 0.25
D = np.array([[dxx, dxy, dxs], [dxy, dyy, dys], [dxs, dys, dss]])
offset = -np.linalg.solve(D[:, :, 1] + 1e-8 * np.eye(3), np.dot(D[:, :, 0], np.array([dx, dy, ds])))
if np.abs(offset[0]) < 0.5 and np.abs(offset[1]) < 0.5 and np.abs(offset[2]) < 0.5:
row += int(round(offset[1]))
col += int(round(offset[0]))
level += int(round(offset[2]))
if np.abs(img[row, col]) >= threshold * sigma:
new_extrema.append((level, row, col))
break
return new_extrema
def computeOrientation(img, keypoint):
"""为每个特征点计算主方向"""
sigma = 1.5 * keypoint[0]
radius = int(round(3 * sigma))
kernel_size = 2 * radius + 1
kernel = cv2.getGaussianKernel(kernel_size, sigma)
img = cv2.GaussianBlur(img, (kernel_size, kernel_size), sigma)
x, y = np.meshgrid(np.arange(-radius, radius+1), np.arange(-radius, radius+1))
magnitude = np.sqrt(x**2 + y**2)
orientation = np.rad2deg(np.arctan2(y, x))
orientation[orientation < 0] += 360
histogram = np.zeros(36, dtype=np.float32)
for i in range(keypoint[1]-radius, keypoint[1]+radius+1):
for j in range(keypoint[2]-radius, keypoint[2]+radius+1):
if i < 1 or i >= img.shape[0]-1 or j < 1 or j >= img.shape[1]-1:
continue
w = kernel[i-keypoint[1]+radius] * kernel[j-keypoint[2]+radius] * (magnitude[i-keypoint[1]+radius, j-keypoint[2]+radius] if magnitude[i-keypoint[1]+radius, j-keypoint[2]+radius] > 0.1 else 0)
angle = orientation[i-keypoint[1]+radius, j-keypoint[2]+radius]
bin_idx = int(np.floor(angle / 10))
histogram[bin_idx] +=
阅读全文