特征描述符
当我们进行完角点检测后,我们就可以在不同的图片中寻找相同的特征了。
但是不同的图像会存在平移,旋转,光照等种种情况,我们必须保证,这些检测的特征在不同的图像上是不变的,只有这样,在能得到在不同的图像上进行相同特征的检测。而harris角点虽然具有一定的不变性,但是这种不变性对于特征的匹配的作用不大。
所以,我们可以为每一个特征设计一个描述符,这个描述符有两个作用
不变性: 即使图像被变换,描述符也不应该改变
区分力: 每一个点的描述符应该是高度唯一的
简单的特征描述符
假设我们将以特征为中心的5×5的窗口的所有像素保存下载,这样就可以将这个5×5的窗口当作一个特征描述符(只有平移不变形)
因为对于不同的特征,他周围的像素只有极小的可能是相同的,所以,我们完全在两个图像中通过这个5×5的窗口来匹配,如果,这个5×5的窗口是相同的,则意味着,这是一个相同的特征
但是显而易见,这个简单的特征描述符仅具有平移不变形。
MOFS特征描述符
Brown发表的一篇论文Multi-Image Matching using Multi-Scale Oriented Patches有提到一种特征描述符
这种描述符对于旋转和投影有尺度不变性。
MOFS特征描述符将特征点周围40×40像素区域子采样得到一个8×8的定向图像块。
我们根据特征点的梯度方向,将图片旋转至特征点的梯度方向水平,保证旋转不变性,
之后,我们进行子采样得到一个8×8的矩阵。
之后我们将这个8×8的图像规范化为一个零均值和单位方差。这将保持仿射不变性
class MOPSFeatureDescriptor(FeatureDescriptor):
def describeFeatures(self, image, keypoints):
image = image.astype(np.float32)
image /= 255.
windowSize = 8
desc = np.zeros((len(keypoints), windowSize * windowSize))
grayImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
grayImage = ndimage.gaussian_filter(grayImage, 0.5)
for i, f in enumerate(keypoints):
transMx = np.zeros((2, 3))
angle = (np.pi/180)*f.angle
tran1 = np.array([
[1, 0, -f.pt[0]],
[0, 1, -f.pt[1]],
[0, 0, 1]
])
rot = np.array([
[math.cos(angle), -math.sin(angle), 0],
[math.sin(angle), math.cos(angle), 0],
[0, 0, 1]
])
scal = np.array([
[0.2, 0, 0],
[0, 0.2, 0],
[0, 0, 1]
])
tran2 = np.array([
[1, 0, 4].
[0, 1, 4],
[0, 0, 1]
])
transMx = np.dot(np.dot(np.dot(tran2,scal),rot), tran1)
transMx = transMx[:2, [0, 1, 3]]
destImage = cv2.warpAffine(grayImage, transMx,
(windowSize, windowSize), flags=cv2.INTER_LINEAR)
# 归一化 u = np.mean(destImage)
sigma = np.std(destImage)
normed = ((destImage-u)/sigma) if sigma**2 >= 1e-10 else np.zeros(np.shape(destImage))
desc[i] = normed.flatten()
return desc
图像匹配
当我们得到两个图像的特征描述符,我们就需要确定两个图像中所提取角点是否一致,我们就需要提供一个有效的算法来判断两者是否一致