重磅干貨,第一時(shí)間送達(dá)
圖像拼接是計(jì)算機(jī)視覺(jué)中最成功的應(yīng)用之一。如今,很難找到不包含此功能的手機(jī)或圖像處理API。 在這篇文章中,我們將討論如何使用Python和OpenCV執(zhí)行圖像拼接。鑒于一對(duì)共享一些共同區(qū)域的圖像,我們的目標(biāo)是“縫合”它們并創(chuàng)建全景圖像場(chǎng)景。 在整篇文章中,我們將介紹一些最著名的計(jì)算機(jī)視覺(jué)技術(shù)。這些包括:
我們探索了許多特征提取算子,如SIFT,SURF,BRISK和ORB。你可以使用這款Colab筆記本,甚至可以用你的照片試試。[這里我已經(jīng)調(diào)試好源碼并上傳到github上面] 特征檢測(cè)和提取給定一對(duì)像上面那樣的圖像,我們想要把它們拼接起來(lái)創(chuàng)建一個(gè)全景場(chǎng)景。值得注意的是,兩個(gè)圖像都需要共享一些共同的區(qū)域。 此外,即使圖片在以下一個(gè)或多個(gè)方面存在差異,我們的解決方案也必須強(qiáng)大:
朝這個(gè)方向邁出的第一步是提取一些感興趣的關(guān)鍵點(diǎn)和特征。但是,這些功能需要具有一些特殊屬性。 我們首先考慮一個(gè)簡(jiǎn)單的解決方案。 一開(kāi)始可能使用簡(jiǎn)單些的方法,諸如使用Harris Corners之類(lèi)的算法提取關(guān)鍵點(diǎn)。然后,我們可以嘗試根據(jù)歐幾里德距離之類(lèi)的相似度量來(lái)匹配相應(yīng)的關(guān)鍵點(diǎn)。我們知道,角點(diǎn)(corner)有一個(gè)很好的屬性:它們對(duì)旋轉(zhuǎn)是不變的。 這意味著,一旦我們檢測(cè)到一個(gè)角點(diǎn),如果我們旋轉(zhuǎn)圖像,那個(gè)角點(diǎn)仍將存在。 但是,如果我們旋轉(zhuǎn)然后縮放圖像怎么辦?在這種情況下,我們會(huì)很難,因?yàn)榻屈c(diǎn)不是規(guī)模不變的。也就是說(shuō),如果我們放大圖像,先前檢測(cè)到的角可能會(huì)變成一條線! 總之,我們需要對(duì)旋轉(zhuǎn)和縮放不變的特征。這就是SIFT,SURF和ORB等更強(qiáng)大的方法的用武之地。 像SIFT和SURF這樣的方法試圖解決角點(diǎn)檢測(cè)算法的局限性。 為了解決這個(gè)限制,像SIFT這樣的方法使用高斯差分(DoD)。我們的想法是在同一圖像的不同比例版本上應(yīng)用DoD。它還使用相鄰像素信息來(lái)查找和細(xì)化關(guān)鍵點(diǎn)和相應(yīng)的描述子。 首先,我們需要加載2個(gè)圖像,查詢圖片和訓(xùn)練圖片。最初,我們首先從兩者中提取關(guān)鍵點(diǎn)和描述符。我們可以通過(guò)使用OpenCV detectAndCompute()函數(shù)一步完成。請(qǐng)注意,為了使用detectAndCompute(),我們需要一個(gè)關(guān)鍵點(diǎn)檢測(cè)器和描述符對(duì)象的實(shí)例。它可以是ORB,SIFT或SURF等。另外,在將圖像饋送到detectAndCompute()之前,我們將它們轉(zhuǎn)換為灰度。 def detectAndDescribe(image, method=None): ''' Compute key points and feature descriptors using an specific method ''' assert method is not None, 'You need to define a feature detection method. Values are: 'sift', 'surf'' # detect and extract features from the image if method == 'sift': descriptor = cv2.xfeatures2d.SIFT_create() elif method == 'surf': descriptor = cv2.xfeatures2d.SURF_create() elif method == 'brisk': descriptor = cv2.BRISK_create() elif method == 'orb': descriptor = cv2.ORB_create() # get keypoints and descriptors (kps, features) = descriptor.detectAndCompute(image, None) return (kps, features) 使用SIFT檢測(cè)關(guān)鍵點(diǎn)和描述子 使用SURF檢測(cè)關(guān)鍵點(diǎn)和描述子 使用BRISK和漢明距離檢測(cè)關(guān)鍵點(diǎn)和描述子 使用ORB和漢明距離檢測(cè)關(guān)鍵點(diǎn)和描述子 我們可以看到,我們從兩個(gè)圖像中都有大量的特征。
def createMatcher(method,crossCheck): KNN不返回給定特征的單個(gè)最佳匹配,而是返回k個(gè)最佳匹配注意,k的值必須是由用戶預(yù)先定義的。如我們預(yù)期的那樣,KNN提供了一個(gè)更的的候選特征集合。但是,我們需要確保所有這些匹配對(duì)在進(jìn)一步發(fā)展之前都是健壯的。
為了確保KNN返回的特征具有良好的可比性,SIFT論文的作者提出了一種稱為比率測(cè)試(Ratio Testing)的技術(shù)。基本上,我們迭代KNN返回的每個(gè)對(duì)并執(zhí)行距離測(cè)試。對(duì)于每對(duì)特征(f1,f2),如果f1和f2之間的距離在一定比例內(nèi),我們保留它,否則,我們將它丟棄。此外,必須手動(dòng)選擇比率值。 使用KNN和RIFT測(cè)試對(duì)SIFT特征進(jìn)行特征匹配 在SIFT功能上使用Brute Force Matcher進(jìn)行特征匹配 這種轉(zhuǎn)換稱為Homography matrix(單應(yīng)性矩陣)。簡(jiǎn)而言之,如果Homography是3x3矩陣,可用于許多應(yīng)用,例如相機(jī)姿態(tài)估計(jì),透視校正和圖像拼接。如果Homography是2D變換。它將點(diǎn)從一個(gè)平面(圖像)映射到另一個(gè)平面。讓我們看看我們是如何得到它的。
我們可以看到線性回歸模型很容易受到異常值的影響。那是因?yàn)樗噲D減少平均誤差。因此,它傾向于支持最小化從所有數(shù)據(jù)點(diǎn)到模型本身的總距離的模型。這包括異常值。 相反,RANSAC僅將模型擬合到被識(shí)別為內(nèi)點(diǎn)的點(diǎn)子集上。 這個(gè)特性對(duì)我們的用例非常重要。在這里,我們將使用RANSAC來(lái)估計(jì)Homography矩陣。事實(shí)證明,Homography對(duì)我們傳遞給它的數(shù)據(jù)質(zhì)量非常敏感。因此,重要的是有一個(gè)算法(RANSAC)可以過(guò)濾明顯不屬于數(shù)據(jù)分布的點(diǎn)。 最小二乘與RANSAC模型擬合的比較。請(qǐng)注意數(shù)據(jù)中的大量異常值 # Apply panorama correction width = trainImg.shape[1] + queryImg.shape[1] height = trainImg.shape[0] + queryImg.shape[0] result = cv2.warpPerspective(trainImg, H, (width, height)) result[0:queryImg.shape[0], 0:queryImg.shape[1]] = queryImg plt.figure(figsize=(20,10)) plt.imshow(result) plt.axis('off') plt.show() 謝謝閱讀!
demo 2
可能存在的報(bào)錯(cuò) (1)Qt 鏈接報(bào)錯(cuò) version `Qt_5' not found]
解決方案:https://www.cnblogs.com/sunchaothu/p/9962675.html (2)AttributeError: module 'cv2.cv2' has no attribute 'xfeatures2d' 需要回退版本到3.4.2.16,記得要先卸載之前安裝好的opencv-python 解決方案:https://blog.csdn.net/weixin_43167047/article/details/82841750 代碼:https://github.com/DWCTOD/AI_study 原文鏈接: https:///image-panorama-stitching-with-opencv-2402bde6b46c |
|