- SIFT方法检测特征点
import cv2
import numpy as np
def cv_show(name, image):
cv2.imshow(name, image)
cv2.waitKey(0)
cv2.destroyAllWindows()
def detectAndDescribe(image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
descriptor = cv2.xfeatures2d.SIFT_create()
(kps, features) = descriptor.detectAndCompute(image, None)
kps = np.float32([kp.pt for kp in kps])
return (kps, features)
过程描述:
创建一个sift生成器
使用创建的sift生成器的detectAndCompute
方法进行特征点检测
得到图片的特征点信息 - 特征点匹配
def matchKeypoints(kpsA, kpsB, featuresA, featuresB, ratio = 0.75, reprojThresh = 4.0):
matcher = cv2.BFMatcher()
rawMatches = matcher.knnMatch(featuresA, featuresB, 2)
matches = []
for m in rawMatches:
if len(m) == 2 and m[0].distance < m[1].distance * ratio:
matches.append((m[0].trainIdx, m[0].queryIdx))
if len(matches) > 4:
ptsA = np.float32([kpsA[i] for (_, i) in matches])
ptsB = np.float32([kpsB[i] for (i, _) in matches])
(H, status) = cv2.findHomography(ptsA, ptsB, cv2.RANSAC, reprojThresh)
return (matches, H, status)
return None
- 匹配的特征点可视化
def drawMatches(imageA, imageB, kpsA, kpsB, matches, status):
(hA, wA) = imageA.shape[:2]
(hB, wB) = imageB.shape[:2]
vis = np.zeros((max(hA, hB), wA + wB, 3), dtype="uint8")
vis[0:hA, 0:wA] = imageA
vis[0:hB, wA:] = imageB
for ((trainIdx, queryIdx), s) in zip(matches, status):
if s == 1:
ptA = (int(kpsA[queryIdx][0]), int(kpsA[queryIdx][1]))
ptB = (int(kpsB[trainIdx][0]) + wA, int(kpsB[trainIdx][1]))
cv2.line(vis, ptA, ptB, (0, 255, 0), 1)
cv_show("drawImg", vis)
return vis
- 图像拼接
def stitch(imageA,imageB, ratio=0.75, reprojThresh=4.0,showMatches=False):
(kpsA, featuresA) = detectAndDescribe(imageA)
(kpsB, featuresB) = detectAndDescribe(imageB)
M = matchKeypoints(kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh)
if M is None:
return None
(matches, H, status) = M
result = cv2.warpPerspective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))
cv_show('result', result)
result[0:imageB.shape[0], 0:imageB.shape[1]] = imageB
cv_show('result', result)
if showMatches:
vis = drawMatches(imageA, imageB, kpsA, kpsB, matches, status)
return (result, vis)
return result
- 进行拼接
imageA = cv2.imread('E:/SIFTDemo/test4/test4_4.jpg')
cv_show("imageA", imageA)
imageB = cv2.imread('E:/SIFTDemo/test4/test4_3.jpg')
cv_show("imageB", imageB)
(kpsA, featuresA) = detectAndDescribe(imageA)
(kpsB, featuresB) = detectAndDescribe(imageB)
(matches,H,status) = matchKeypoints(kpsA, kpsB, featuresA, featuresB)
print(H)
drawMatches(imageA, imageB, kpsA, kpsB, matches, status)
stitch(imageA, imageB)
注意:对于图片的放置顺序需要注意,imageA表示放置右边的图,imageB表示放置左边的图。如果图片位置放置不对,就无法得到最终预期的拼接结果。