python+opencv图像拼接
程序员文章站
2022-05-16 10:34:38
...
#目前在看七月的CV课,今天第二节,作业是实现图像拼接
- 使用SIFT特征点检测
- 使用FLANN进行特征点单应性匹配
- 计算第二张相对于第一张的仿射变换
- 使用公式(1-alpha)×原+alpha×仿进行拼接
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
if __name__ == '__main__':
top, bot, left, right = 100, 100, 0, 500
img1 = cv.imread('1.png')
img2 = cv.imread('2.png')
#扩充图像的边界,CONSTANT表示常量法,填充的边界由value参数给定
srcImg = cv.copyMakeBorder(img1, top, bot, left, right, cv.BORDER_CONSTANT, value = (0,0,0))
testImg = cv.copyMakeBorder(img2, top, bot, left, right, cv.BORDER_CONSTANT, value = (0,0,0))
img1gray = cv.cvtColor(srcImg, cv.COLOR_BGR2GRAY)
img2gray = cv.cvtColor(testImg, cv.COLOR_BGR2GRAY)
sift = cv.xfeatures2d_SIFT().create()
#找到关键点和描述子
kp1, des1 = sift.detectAndCompute(img1gray, None)
kp2, des2 = sift.detectAndCompute(img2gray, None)
#FLANN单应性匹配, 单应性指的是图像在投影发生了畸变后仍然能够有较高的检测和匹配准确率
#kdtree建立索引方式的常量参数
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)#chesks指定索引树要被遍历的次数
flann = cv.FlannBasedMatcher(index_params, search_params)
#进行匹配搜索
matches = flann.knnMatch(des1, des2, k=2)
# 寻找距离近的放入good列表
good = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good.append(m)
MIN_MATCH_COUNT = 10
# 如果足够多就进行匹配
if len(good) > MIN_MATCH_COUNT:
# 通过距离近的描述符 找到两幅图片的关键点
src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
# 单应性匹配图关键点匹配线
M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC, 5.0)
matchesMask = mask.ravel().tolist()
#仿射变换的图像
warpImg = cv.warpPerspective(testImg, np.array(M), (testImg.shape[1], testImg.shape[0]), flags = cv.WARP_INVERSE_MAP)
rows, cols = srcImg.shape[:2]
for col in range(cols):
if srcImg[:,col].any() and warpImg[:, col].any():
left = col
break
for col in range(cols-1, 0, -1):
if srcImg[:,col].any() and warpImg[:,col].any():
right = col
break
res = np.zeros([rows,cols,3], np.uint8)
for row in range(rows):
for col in range(cols):
if not srcImg[row, col].any():
res[row, col] = warpImg[row, col]
elif not warpImg[row, col].any():
res[row,col] = srcImg[row, col]
else:
srcImgLen = float(abs(col-left))
testImgLen = float(abs(col-right))
alpha = srcImgLen / (srcImgLen+testImgLen)
res[row, col] = np.clip(srcImg[row,col] * (1-alpha) + warpImg[row, col] * alpha, 0, 255)
#opencv is bgr, matplotlib is rgb
res = cv.cvtColor(res, cv.COLOR_BGR2RGB)
plt.imshow(res)
#否则不进行拼接
else:
matchesMask = None
上一篇: vue开发按钮组件需要准备哪些东西
下一篇: python opencv 图像拼接