初学opencv/特征匹配

环境:opencv 2.4

尺度不变特征变换(SIFT),这个算法可以帮助我们提取图像中的关键点并计算它们的描述符。 特征点检测和匹配是计算机视觉中一个很有用的技术,常见的有FAST。其中,ORB算法中,是采用了FAST作为特征点检测算子,ORB检测算法具备旋转不变性和抗噪声性。

#coding:utf-8
import numpy as np
import cv2
import matplotlib.pyplot as plt
import datetime

"""
opencv 2.4中没有drawMatches函数,定义一个drarMatches函数
"""
#定义一个drawmatches函数
def drawMatches(img1, kp1, img2, kp2, matches):
    # Create a new output image that concatenates the two images together
    # (a.k.a) a montage
    rows1 = img1.shape[0]
    cols1 = img1.shape[1]
    rows2 = img2.shape[0]
    cols2 = img2.shape[1]

    out = np.zeros((max([rows1,rows2]),cols1+cols2,3), dtype='uint8')

    # Place the first image to the left
    out[:rows1,:cols1] = np.dstack([img1, img1, img1])

    # Place the next image to the right of it
    out[:rows2,cols1:] = np.dstack([img2, img2, img2])

    # For each pair of points we have between both images
    # draw circles, then connect a line between them
    for mat in matches:

        # Get the matching keypoints for each of the images
        img1_idx = mat.queryIdx
        img2_idx = mat.trainIdx

        # x - columns
        # y - rows
        (x1,y1) = kp1[img1_idx].pt
        (x2,y2) = kp2[img2_idx].pt

        # Draw a small circle at both co-ordinates
        # radius 4
        # colour blue
        # thickness = 1
        cv2.circle(out, (int(x1),int(y1)), 4, (201, 186, 131), 1)   
        cv2.circle(out, (int(x2)+cols1,int(y2)), 4, (28, 127, 135), 1)

        # Draw a line in between the two points
        # thickness = 1
        # colour blue
        cv2.line(out, (int(x1),int(y1)), (int(x2)+cols1,int(y2)), (137, 69, 148), 1)


    # Show the image
    cv2.imshow('Matched Features', out)
    cv2.waitKey(0)
    cv2.destroyWindow('Matched Features')

    # Also return the image if you'd like a copy
    return out


beaver = cv2.imread('images/haha.PNG')
#彩色图
#plt.imshow(cv2.cvtColor(beaver,cv2.COLOR_BGR2RGB))
#灰度图
gray = cv2.cvtColor(beaver,cv2.COLOR_BGR2GRAY)
#SIFT特征检测器opencv2.4中不能使用xfeatures2d.SIFT_create()
sift=cv2.SIFT()
keypoints = sift.detect(beaver,None)
#在图片中将特征点显示
beaver_sift = cv2.drawKeypoints(beaver,keypoints,None)
#找到关键点和描述符(128*kp)
kp,des = sift.compute(gray,keypoints)
#plt.imshow(cv2.cvtColor(beaver_sift, cv2.COLOR_BGR2RGB))
#plt.show()

#
#img1 = cv2.imread('images/box.png')
#img2 = cv2.imread('images/box_in_scene.png')
#img1 = cv2.imread('images/haha1.PNG')
#img2 = cv2.imread('images/haha.PNG')
img1 = cv2.imread('images/jianjian.jpg')
img2 = cv2.imread('images/jianjian1.jpg')

#plt.subplot(1,2,1)
#plt.imshow(cv2.cvtColor(img1,cv2.COLOR_BGR2RGB))
#plt.subplot(1,2,2)
#plt.imshow(cv2.cvtColor(img2,cv2.COLOR_BGR2RGB))

gray1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)

#采用ORB特征检测算法
orb = cv2.ORB(1000, 1.2)
#detectAndCompute()一步到位直接找到关键点并计算出其描述符
(kp1,des1) = orb.detectAndCompute(gray1, None)
(kp2,des2) = orb.detectAndCompute(gray2, None)
#采用暴力匹配的方式
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1,des2)
matches = sorted(matches, key=lambda val: val.distance)
out = drawMatches(gray1, kp1, gray2, kp2, matches[:30])


"""
kp1, des1 = sift.detectAndCompute(gray1, None)
kp2, des2 = sift.detectAndCompute(gray2, None)

#采用Hellinger距离定义匹配特征
des1 = des1 / np.repeat(np.sum(des1, axis = 1).reshape(des1.shape[0], 1), des1.shape[1], axis=1)
des2 = des2 / np.repeat(np.sum(des2, axis = 1).reshape(des2.shape[0], 1), des2.shape[1], axis=1)
dist_mat = np.sqrt(np.abs(1.0 - np.dot(np.sqrt(des1), np.sqrt(des2).transpose())))
min_arg = np.argsort(dist_mat, axis=1)
good_matches = []
for i in range(dist_mat.shape[0]):
    m, n = min_arg[i][0:2]
    if dist_mat[i][m] < dist_mat[i][n] * 0.75:
        dmatch = cv2.DMatch(i, m, 0, dist_mat[i][m]) # _queryIdx, _trainIdx, _imgIdx, _distance
        good_matches.append(dmatch)

out = drawMatches(gray1, kp1, gray2, kp2, good_matches[:30])

"""

结果:

特征点描述
这里写图片描述
ORB检测算法和采用Hellinger距离进行特征匹配都具有旋转不变性
这里写图片描述
实验表明采用Hellinger距离的匹配效果更好
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值