首页 > 编程知识 正文

图像拼接算法及实现,opencv拼接图片

时间:2023-05-05 12:04:31 阅读:143580 作者:3042

以前被委托进行图像和精灵的项目,学习了图像精灵的原理和实践。 在这里记录包括基本原理和用python写的代码。

图像的拼接,顾名思义就是将两幅或多幅图像拼接在一起,关键是找出两幅图像的重叠部分,在重叠部分进行拼接。

因此,重要的可归纳为两个部分,一是如何找到重叠部分,在图像处理中称为特征点的提取和匹配; 二是根据重叠部分重叠图像,将右图根据重叠部分盖在左图上。

的步骤1 .对各图进行特征提取,对两幅图进行特征匹配。

2 .图像配准和去误差匹配,即从匹配的特征点找到重叠部分的相应坐标,并求出与坐标变换对应的矩阵homography。

3 .根据转换矩阵将右图复制到左图的指定位置。

4 .对重叠边界进行特殊处理,如平滑处理、去裂处理、过渡等。

特征点提取算法:

(1) SIFT算法)尺度不变特征变换

)2) SURF算法)加速鲁棒特征

(3) ORB算法

这些都具有比例不变的特征。 也就是说,在两个图像不同比例的同一物体点上,两个比例因子之间的比例必须等于图像比例。

特征点是关键点,一般为角点、边缘、暗区亮点、亮区暗点、局部极值点。

SIFT是最基本的算法,SURF和ORB都在SIFT的基础上进行了修改,提高了运算速度。

特征点匹配算法:

(1) BF算法

)2) FLANN算法

使用python和opencv库函数实现

ORB算法:

#orBdeforb_extract(img2,img2) :orb=cv2.orb_create ) 10 ) kp1,des1=orb.detectandcompute ) img1,none crossCheck=True ) matches=BF.match ) des2, des2) matches=ss key=lambdax : x.distance (key _ number1=len (kp1 ) key_number2=len ) KP2 ) match _ number (match_number )/float (max _ number ) ) img_orb=cv2.Drawmatches ) img1,

#surfdefsurf_extract(img1, img2) 3360 surf=cv2.xfeatures 2d.surf _ create (100 ) surf.sethessianthreshold ) 10000 ) sift 3360 cv2.xfeaturer surer 、nOctaves、nOctaveLayers、extended、upright ) key1、describe None ) img11=cv2.DrawkeyPoints(img1、key1、img1、color=0 ) ),describe2=surf.detectandcompute none ) img12=cv2.DrawkeyPoints(img2,key2,img2,color=(255,0,0,0 ) trees=5) search_params=DICT(checks=50 ) flann=cv2.flannbasedmatcher (index _ params,search_Params ) mate k=2) key_number1=len(key1) key_number2=len ) key2) match_number=len(match ) max _ number=NP.maxim

good.append([m]) # print("m:", m) good_number = len(good) # print("good:", good_number) score = float(float(good_number)/float(max_number)) img_surf = cv2.drawMatchesKnn(img1, key1, img2, key2, good, None, flags=2) return img_surf, score

SIFT算法:

def sift_extract(img1, img2): # SIFT sift = cv2.xfeatures2d.SURF_create(100) key1, describe1 = sift.detectAndCompute(img1, None) img11 = cv2.drawKeypoints(img1, key1, img1, color=(255, 0, 0)) key2, describe2 = sift.detectAndCompute(img2, None) img12 = cv2.drawKeypoints(img2, key2, img2, color=(255, 0, 0)) # FLANN FLANN_INDEX_KDTREE = 0 index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) search_params = dict(checks=50) flann = cv2.FlannBasedMatcher(index_params, search_params) match = flann.knnMatch(describe1, describe2, k=2) key_number1 = len(key1) key_number2 = len(key2) match_number = len(match) max_number = np.maximum(key_number1, key_number2) score = float(float(match_number) / float(max_number)) img_sift = cv2.drawMatchesKnn(img1, key1, img2, key2, match, None, flags=2) return img_sift, score

特征提取和匹配的主函数:

def main(): img1 = cv2.imread("a.PNG") img2 = cv2.imread("b.PNG") img3, score_orb = orb_extract(img1, img2) plt.subplot(311), plt.imshow(img3), plt.title('ORB'), plt.axis('off') img4, score_surf = surf_extract(img1, img2) plt.subplot(312), plt.imshow(img4), plt.title('SURF'), plt.axis('off') img5, score_sift = sift_extract(img1, img2) plt.subplot(313), plt.imshow(img5), plt.title('SIFT'), plt.axis('off') print("surf:", score_surf) print("sift:", score_sift) plt.show()if __name__ == "__main__": main()

效果:
SIFT算法的特征点一般都是最多的。

图像拼接的最大难度应是特征点的提取与匹配了,这里就详细介绍这个部分,其余步骤可大概了解。

这里附上图像拼接的全部代码:

# 图像拼接import cv2 as cvimport numpy as npfrom matplotlib import pyplot as pltimport timeMIN = 10start_time = time.time()m1 = cv.imread('a.PNG')img2 = cv.imread('b.PNG')height2 = int(img2.shape[0])width2 = int(img2.shape[1])dim = (width2, height2)img1 = cv.resize(m1, dim, interpolation=cv.INTER_AREA)gray1 = cv.cvtColor(img1, cv.COLOR_RGB2GRAY)gray2 = cv.cvtColor(img2, cv.COLOR_RGB2GRAY)print('img1 Dimensions : ', img1.shape)print('img2 Dimensions : ', img2.shape)plt.imshow(img1, ), plt.show()plt.imshow(img2, ), plt.show()# SURFsurf = cv.xfeatures2d.SURF_create(10000, nOctaves=4, extended=False, upright=True)gray1 = cv.cvtColor(img1, cv.COLOR_RGB2GRAY)gray2 = cv.cvtColor(img2, cv.COLOR_RGB2GRAY)kp1, describe1 = surf.detectAndCompute(gray1, None)kp2, describe2 = surf.detectAndCompute(gray2, None)# FLANNFLANN_INDEX_KDTREE = 0indexParams = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)searchParams = dict(checks=50)flann = cv.FlannBasedMatcher(indexParams, searchParams)match = flann.knnMatch(describe1, describe2, k=2)good = []for i, (m, n) in enumerate(match): if m.distance < 0.75 * n.distance: good.append(m)################################### RANSAC:findhomographyif len(good) > MIN: src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2) ano_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2) M, mask = cv.findHomography(src_pts, ano_pts, cv.RANSAC, 5.0) warpImg = cv.warpPerspective(img2, np.linalg.inv(M), (img1.shape[1] + img2.shape[1], img2.shape[0])) direct = warpImg.copy() direct[0:img1.shape[0], 0:img1.shape[1]] = img1 simple = time.time()################################### # cv.namedWindow("Result", cv.WINDOW_NORMAL) # cv.imshow("Result",warpImg) rows, cols = img1.shape[:2] left = 0 right = cols for col in range(0, cols): if img1[:, col].any() and warpImg[:, col].any(): # 开始重叠的最左端 left = col break for col in range(cols - 1, 0, -1): if img1[:, col].any() and warpImg[:, col].any(): # 重叠的最右一列 right = col break res = np.zeros([rows, cols, 3], np.uint8) for row in range(0, rows): for col in range(0, cols): if not img1[row, col].any(): res[row, col] = warpImg[row, col] elif not warpImg[row, col].any(): res[row, col] = img1[row, col] else: srcImgLen = float(abs(col - left)) testImgLen = float(abs(col - right)) alpha = srcImgLen / (srcImgLen + testImgLen) res[row, col] = np.clip(img1[row, col] * (1 - alpha) + warpImg[row, col] * alpha, 0, 255) warpImg[0:img1.shape[0], 0:img1.shape[1]] = res final = time.time() img3 = cv.cvtColor(direct, cv.COLOR_BGR2RGB) plt.imshow(img3, ), plt.show() img4 = cv.cvtColor(warpImg, cv.COLOR_BGR2RGB) plt.imshow(img4, ), plt.show() print("simple stitch cost %f" % (simple - start_time)) print("n total cost %f" % (final - start_time)) # cv.imwrite("simpletons.png", direct) # cv.imwrite("bestowal.png", warpImg) cv.imshow("pictures", img4) cv.waitKey() cv.destroyAllWindows()else: print("not enough matches!")

效果:

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。