首先对图片进行预处理,是图片的分配率大小在合适的范围内,避免图片太大占满整个电脑屏幕。
1
2
3
4
5
6
7
8
9
10
11
|
from PIL import Image def produceImage(file_in, width, height, file_out): image = Image. open (file_in) resized_image = image.resize((height, width), Image.ANTIALIAS) resized_image.save(file_out) if __name__ = = '__main__' : file_in = 'right2.png' #输入文件的文件名 width = 500 #文件大小 height = 500 file_out = 'right11.png' #生成文件的文件名 produceImage(file_in, width, height, file_out) |
输出图片之后就可以对两张图片进行拼接了。
两张图像要能拼接在一起成为一张图像,就需要这两张图像中存在有重合的部分。通过这些重合的部分使用sift特征点匹配的算法,来寻找到重合部分的特征点。
需要注意的是,虽然sift算法比Harris角点的效果更好,但是也会出现错误点,并非完美的匹配方法。
在以下的代码中,MyStitcher类里面的内容就是对图像实现拼接的主要过程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
import cv2 import numpy as np class MyStitcher: # 拼接函数 def stitch( self , images, ratio = 0.75 , reprojThresh = 4.0 , showMatches = False ): # 获取输入图片 (imageB, imageA) = images # 检测A、B图片的SIFT关键特征点,并计算特征描述子 (kpsA, featuresA) = self .detectAndDescribe(imageA) (kpsB, featuresB) = self .detectAndDescribe(imageB) # 匹配两张图片的所有特征点,返回匹配结果 M = self .matchKeypoints(kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh) # 如果返回结果为空,没有匹配成功的特征点,退出算法 if M is None : return None # 否则,提取匹配结果 # H是3x3视角变换矩阵 (matches, H, status) = M # 将图片A进行视角变换,result是变换后图片 result = cv2.warpPerspective(imageA, H, (imageA.shape[ 1 ] + imageB.shape[ 1 ], imageA.shape[ 0 ])) # 将图片B传入result图片最左端 result[ 0 :imageB.shape[ 0 ], 0 :imageB.shape[ 1 ]] = imageB # 检测是否需要显示图片匹配 if showMatches: # 生成匹配图片 vis = self .drawMatches(imageA, imageB, kpsA, kpsB, matches, status) # 返回结果 return (result, vis) # 返回匹配结果 return result def detectAndDescribe( self , image): # 将彩色图片转换成灰度图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 建立SIFT生成器 descriptor = cv2.xfeatures2d.SIFT_create() # 检测SIFT特征点,并计算描述子 (kps, features) = descriptor.detectAndCompute(image, None ) # 将结果转换成NumPy数组 kps = np.float32([kp.pt for kp in kps]) # 返回特征点集,及对应的描述特征 return (kps, features) def matchKeypoints( self , kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh): # 建立暴力匹配器 matcher = cv2.DescriptorMatcher_create( "BruteForce" ) # 使用KNN检测来自A、B图的SIFT特征匹配对,K=2 rawMatches = matcher.knnMatch(featuresA, featuresB, 2 ) matches = [] for m in rawMatches: # 当最近距离跟次近距离的比值小于ratio值时,保留此匹配对 if len (m) = = 2 and m[ 0 ].distance < m[ 1 ].distance * ratio: # 存储两个点在featuresA, featuresB中的索引值 matches.append((m[ 0 ].trainIdx, m[ 0 ].queryIdx)) # 当筛选后的匹配对大于4时,计算视角变换矩阵 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) # 如果匹配对小于4时,返回None return None def drawMatches( self , imageA, imageB, kpsA, kpsB, matches, status): # 初始化可视化图片,将A、B图左右连接到一起 (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 ) # 返回可视化结果 return vis # 读取拼接图片 imageA = cv2.imread( "left11.png" ) imageB = cv2.imread( "right11.png" ) # 把图片拼接成全景图 mystitcher = MyStitcher() (result, vis) = mystitcher.stitch([imageA, imageB], showMatches = True ) # 显示所有图片 cv2.imshow( "Image A" , imageA) cv2.imshow( "Image B" , imageB) cv2.imshow( "Keypoint Matches" , vis) cv2.imshow( "Result" , result) cv2.waitKey( 0 ) cv2.destroyAllWindows() |
以上就是python计算机视觉实现全景图像拼接示例的详细内容,更多关于python计算机视觉全景拼接的资料请关注服务器之家其它相关文章!
原文链接:https://blog.csdn.net/weixin_44382897/article/details/109596470