Python 图像拼接
我在旋转瓶子时录制了视频。然后我从视频中获取帧,并从所有图像中剪切中心块 因此,对于所有帧,我都得到了以下图像:Python 图像拼接,python,opencv,image-processing,Python,Opencv,Image Processing,我在旋转瓶子时录制了视频。然后我从视频中获取帧,并从所有图像中剪切中心块 因此,对于所有帧,我都得到了以下图像: 我试着把它们缝起来以获得全景图,但结果不好。 我使用了以下程序: import glob #rom panorama import Panorama import sys import numpy import imutils import cv2 def readImages(imageString): images = [] # Get images
我试着把它们缝起来以获得全景图,但结果不好。 我使用了以下程序:
import glob
#rom panorama import Panorama
import sys
import numpy
import imutils
import cv2
def readImages(imageString):
images = []
# Get images from arguments.
for i in range(0, len(imageString)):
img = cv2.imread(imageString[i])
images.append(img)
return images
def findAndDescribeFeatures(image):
# Getting gray image
grayImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Find and describe the features.
# Fast: sift = cv2.xfeatures2d.SURF_create()
sift = cv2.xfeatures2d.SIFT_create()
# Find interest points.
keypoints = sift.detect(grayImage, None)
# Computing features.
keypoints, features = sift.compute(grayImage, keypoints)
# Converting keypoints to numbers.
keypoints = numpy.float32([kp.pt for kp in keypoints])
return keypoints, features
def matchFeatures(featuresA, featuresB):
# Slow: featureMatcher = cv2.DescriptorMatcher_create("BruteForce")
featureMatcher = cv2.DescriptorMatcher_create("FlannBased")
matches = featureMatcher.knnMatch(featuresA, featuresB, k=2)
return matches
def generateHomography(allMatches, keypointsA, keypointsB, ratio, ransacRep):
if not allMatches:
return None
matches = []
for match in allMatches:
# Lowe's ratio test
if len(match) == 2 and (match[0].distance / match[1].distance) < ratio:
matches.append(match[0])
pointsA = numpy.float32([keypointsA[m.queryIdx] for m in matches])
pointsB = numpy.float32([keypointsB[m.trainIdx] for m in matches])
if len(pointsA) > 4:
H, status = cv2.findHomography(pointsA, pointsB, cv2.RANSAC, ransacRep)
return matches, H, status
else:
return None
paths = glob.glob("C:/Users/andre/Desktop/Panorama-master/frames/*.jpg")
images = readImages(paths[::-1])
while len(images) > 1:
imgR = images.pop()
imgL = images.pop()
interestsR, featuresR = findAndDescribeFeatures(imgR)
interestsL, featuresL = findAndDescribeFeatures(imgL)
try:
try:
allMatches = matchFeatures(featuresR, featuresL)
_, H, _ = generateHomography(allMatches, interestsR, interestsL, 0.75, 4.0)
result = cv2.warpPerspective(imgR, H,
(imgR.shape[1] + imgL.shape[1], imgR.shape[0]))
result[0:imgL.shape[0], 0:imgL.shape[1]] = imgL
images.append(result)
except TypeError:
pass
except cv2.error:
pass
result = imutils.resize(images[0], height=260)
cv2.imshow("Result", result)
cv2.imwrite("Result.jpg", result)
cv2.waitKey(0)
导入全局
#rom全景导入全景
导入系统
进口numpy
导入imutils
进口cv2
def readImages(图像字符串):
图像=[]
#从参数中获取图像。
对于范围(0,len(imageString))中的i:
img=cv2.imread(imageString[i])
images.append(img)
返回图像
def FindAndDescripteFeatures(图像):
#获取灰度图像
grayImage=cv2.CVT颜色(图像,cv2.COLOR\u BGR2GRAY)
#查找并描述功能。
#Fast:sift=cv2.xfeature2d.SURF_create()
sift=cv2.xfeature2d.sift_create()
#找到兴趣点。
关键点=筛选检测(灰度图像,无)
#计算功能。
关键点,特征=sift.compute(灰度图像,关键点)
#将关键点转换为数字。
keypoints=numpy.float32([kp.pt表示关键点中的kp])
返回关键点、特征
def匹配功能(功能A、功能B):
#慢速:featureMatcher=cv2.DescriptorMatcher_create(“蛮力”)
featureMatcher=cv2.DescriptorMatcher_创建(“法兰基”)
matches=featureMatcher.knnMatch(featuresA,featuresB,k=2)
复赛
def生成全息图(所有匹配项、关键点SA、关键点SB、比率、ransacRep):
如果不是所有匹配项:
一无所获
匹配项=[]
对于所有匹配中的匹配:
#洛韦比检验
如果len(match)==2和(match[0]。距离/匹配[1]。距离)<比率:
匹配项。追加(匹配项[0])
pointsA=numpy.float32([keypointsA[m.queryIdx]表示匹配中的m])
pointsB=numpy.float32([keypointsB[m.trainIdx]表示匹配中的m])
如果len(pointsA)>4:
H、 状态=cv2.findHomography(点SA、点SB、cv2.RANSAC、ransacRep)
返回匹配项,H,状态
其他:
一无所获
path=glob.glob(“C:/Users/andre/Desktop/Panorama master/frames/*.jpg”)
images=readImages(路径[:-1])
而len(图像)>1:
imgR=images.pop()
imgL=images.pop()
兴趣sr,功能sr=查找和描述功能(imgR)
兴趣SL,功能SL=查找和描述功能(imgL)
尝试:
尝试:
allMatches=matchFeatures(featuresR,featuresL)
_,H,u=生成单纯形(所有匹配项,兴趣sr,兴趣tl,0.75,4.0)
结果=cv2.1(imgR,H,
(imgR.shape[1]+imgL.shape[1],imgR.shape[0]))
结果[0:imgL.shape[0],0:imgL.shape[1]=imgL
images.append(结果)
除类型错误外:
通过
除cv2.0错误外:
通过
结果=imutils.resize(图像[0],高度=260)
cv2.imshow(“结果”,结果)
cv2.imwrite(“Result.jpg”,Result)
cv2.等待键(0)
我的结果是:也许有人知道热做得更好?我认为使用框架上的小木块应该可以去除圆度。。。但是
数据:我设法取得了一个不错的结果。我只是稍微重写了您的代码,下面是更改的部分:
def generateTransformation(allMatches, keypointsA, keypointsB, ratio):
if not allMatches:
return None
matches = []
for match in allMatches:
# Lowe's ratio test
if len(match) == 2 and (match[0].distance / match[1].distance) < ratio:
matches.append(match[0])
pointsA = numpy.float32([keypointsA[m.queryIdx] for m in matches])
pointsB = numpy.float32([keypointsB[m.trainIdx] for m in matches])
if len(pointsA) > 2:
transformation = cv2.estimateRigidTransform(pointsA, pointsB, True)
if transformation is None or transformation.shape[1] < 1 or transformation.shape[0] < 1:
return None
return transformation
else:
return None
paths = glob.glob("a*.jpg")
images = readImages(paths[::-1])
result = images[0]
while len(images) > 1:
imgR = images.pop()
imgL = images.pop()
interestsR, featuresR = findAndDescribeFeatures(imgR)
interestsL, featuresL = findAndDescribeFeatures(imgL)
allMatches = matchFeatures(featuresR, featuresL)
transformation = generateTransformation(allMatches, interestsR, interestsL, 0.75)
if transformation is None or transformation[0, 2] < 0:
images.append(imgR)
continue
transformation[0, 0] = 1
transformation[1, 1] = 1
transformation[0, 1] = 0
transformation[1, 0] = 0
transformation[1, 2] = 0
result = cv2.warpAffine(imgR, transformation, (imgR.shape[1] +
int(transformation[0, 2] + 1), imgR.shape[0]))
result[:, :imgL.shape[1]] = imgL
cv2.imshow("R", result)
images.append(result)
cv2.waitKey(1)
cv2.imshow("Result", result)
def generateTransformation(所有匹配项、关键点SA、关键点SB、比率):
如果不是所有匹配项:
一无所获
匹配项=[]
对于所有匹配中的匹配:
#洛韦比检验
如果len(match)==2和(match[0]。距离/匹配[1]。距离)<比率:
匹配项。追加(匹配项[0])
pointsA=numpy.float32([keypointsA[m.queryIdx]表示匹配中的m])
pointsB=numpy.float32([keypointsB[m.trainIdx]表示匹配中的m])
如果len(pointsA)>2:
transformation=cv2.EstimaterialGidTransform(pointsA,pointsB,True)
如果转换为None或transformation.shape[1]<1或transformation.shape[0]<1:
一无所获
回归变换
其他:
一无所获
路径=glob.glob(“a*.jpg”)
images=readImages(路径[:-1])
结果=图像[0]
而len(图像)>1:
imgR=images.pop()
imgL=images.pop()
兴趣sr,功能sr=查找和描述功能(imgR)
兴趣SL,功能SL=查找和描述功能(imgL)
allMatches=matchFeatures(featuresR,featuresL)
转换=生成转换(allMatches,interestsR,interestsL,0.75)
如果转换为无或转换[0,2]<0:
images.append(imgR)
持续
变换[0,0]=1
变换[1,1]=1
变换[0,1]=0
变换[1,0]=0
转换[1,2]=0
结果=cv2.warpAffine(imgR,transformation,(imgR.shape[1]+
int(变换[0,2]+1),imgR.shape[0]))
结果[:,:imgL.shape[1]]=imgL
cv2.imshow(“R”,结果)
images.append(结果)
cv2.等待键(1)
cv2.imshow(“结果”,结果)
所以我改变的关键是图像的变换。我使用estimategidtransform()
而不是findHomography()
来计算图像的变换。从该变换矩阵中,我仅提取坐标转换x,该坐标转换位于生成的变换的[0,2]
单元中。我将其他变换矩阵元素设置为等同变换(无缩放、无透视、无旋转或y平移)。然后我将其传递给warpAffine()
,以转换imgR
,方法与warpprospective()
相同
你可以这样做,因为你有稳定的相机和旋转物体的位置,你可以用一个物体的正前方视图来捕捉。这意味着您不必进行任何透视/缩放/旋转图像校正,只需通过x轴将它们“粘合”在一起即可
我认为你的方法失败了,因为你实际上观察瓶子稍微倾斜的相机视图或瓶子不在中间。