Image Stitching with OpenCV and Python

Image Stitching with OpenCV and Python
在本教程中,您將學(xué)習(xí)如何使用Python,OpenCV和cv2.createStitcher和cv2.Stitcher_create函數(shù)執(zhí)行圖像拼接。
使用今天的代碼,您將可以將多張圖像拼接在一起,從而創(chuàng)建出拼接圖像的全景圖。

就在不到兩年前,我發(fā)布了有關(guān)圖像拼接和全景圖構(gòu)建的兩個(gè)指南:

  1. Fundamentals of image stitching
  2. Real-time panorama and image stitching

這兩個(gè)教程都涵蓋了典型圖像拼接算法的基礎(chǔ)知識(shí),該算法至少需要四個(gè)關(guān)鍵步驟:

  1. 從兩個(gè)輸入圖像中檢測(cè)關(guān)鍵點(diǎn)(DoG,Harris等)并提取局部不變描述符(SIFT,SURF等)
  2. 在圖像之間匹配描述符
  3. 使用RANSAC算法通過匹配的特征向量估計(jì)單應(yīng)矩陣(homography matrix)
  4. 使用從步驟#3獲得的單應(yīng)性矩陣應(yīng)用翹曲變換(warping transformation)

但是,我最初的實(shí)現(xiàn)最大的問題是它們不能處理兩個(gè)以上的輸入圖像。
在今天的教程中,我們將重新討論OpenCV的圖像拼接,包括如何將兩個(gè)以上的圖像拼接在一起成為全景圖像。
第一部分將簡(jiǎn)要回顧OpenCV的圖像拼接算法,該算法通過cv2.createStitcher和cv2.Stitcher_create函數(shù)嵌入OpenCV庫(kù)本身。
從那里,我們將審查我們的項(xiàng)目結(jié)構(gòu),并實(shí)現(xiàn)可用于圖像拼接的Python腳本。
我們將回顧第一個(gè)腳本的結(jié)果,注意其局限性,然后實(shí)施第二個(gè)Python腳本,該腳本可用于在美學(xué)上使圖像拼接效果更加令人滿意。
最后,我們將檢查第二個(gè)腳本的結(jié)果,并再次注意任何限制或缺點(diǎn)。

OpenCV的圖像拼接算法

今天我們將在此處使用的算法類似于Brown和Lowe在2007年的論文《具有不變特征的自動(dòng)全景圖像拼接》中提出的方法。
Automatic Panoramic Image Stitching with Invariant Features
與以前的對(duì)圖像輸入順序敏感的圖像拼接算法不同,Brown and Lowe方法更健壯,使其對(duì)以下內(nèi)容不敏感:

  1. 圖像順序
  2. 圖像方向
  3. 光照變化
  4. 實(shí)際上不是全景圖的一部分的有噪聲圖像

此外,通過使用增益補(bǔ)償和圖像融合來產(chǎn)生更加美觀的輸出全景圖像。

對(duì)該算法進(jìn)行完整,詳細(xì)的介紹超出了本文的范圍,因此,如果您有興趣了解更多信息,請(qǐng)參閱原始出版物。

cv2.createStitcher and cv2.Stitcher_create

OpenCV已經(jīng)通過cv2.createStitcher(OpenCV 3.x)和cv2.Stitcher_create(OpenCV 4)函數(shù)實(shí)現(xiàn)了類似于Brown和Lowe論文的方法。
OpenCV 3.x的cv2.createStitcher的功能簽名:

createStitcher(...)
    createStitcher([, try_use_gpu]) -> retval

請(qǐng)注意,此函數(shù)只有一個(gè)參數(shù)try_gpu,可用于改善整個(gè)圖像拼接管道。 OpenCV的GPU支持有限,而且我永遠(yuǎn)無法使該參數(shù)正常工作,因此我建議始終將其保留為False。
OpenCV 4的cv2.Stitcher_create函數(shù)具有類似的簽名:

Stitcher_create(...)
    Stitcher_create([, mode]) -> retval
    .   @brief Creates a Stitcher configured in one of the stitching
    .   modes.
    .   
    .   @param mode Scenario for stitcher operation. This is usually
    .   determined by source of images to stitch and their transformation.
    .   Default parameters will be chosen for operation in given scenario.
    .   @return Stitcher class instance.

要執(zhí)行實(shí)際的圖像拼接,我們需要調(diào)用.stitch方法:

OpenCV 3.x:
stitch(...) method of cv2.Stitcher instance
    stitch(images[, pano]) -> retval, pano
OpenCV 4.x:
stitch(...) method of cv2.Stitcher instance
    stitch(images, masks[, pano]) -> retval, pano
    .   @brief These functions try to stitch the given images.
    .   
    .   @param images Input images.
    .   @param masks Masks for each input image specifying where to
    .   look for keypoints (optional).
    .   @param pano Final pano.
    .   @return Status code.

此方法接受輸入圖像列表,然后嘗試將它們拼接成全景圖,然后將輸出的全景圖圖像返回給調(diào)用函數(shù)。

status變量指示圖像拼接是否成功,并且可以是四個(gè)變量之一:

  • OK = 0:圖像拼接成功。
  • ERR_NEED_MORE_IMGS = 1:如果您收到此狀態(tài)碼,則需要更多輸入圖像來構(gòu)建全景圖。
    通常,如果在輸入圖像中沒有檢測(cè)到足夠的關(guān)鍵點(diǎn),則會(huì)發(fā)生此錯(cuò)誤。
  • ERR_HOMOGRAPHY_EST_FAIL = 2:當(dāng)RANSAC單應(yīng)性估計(jì)失敗時(shí),會(huì)發(fā)生此錯(cuò)誤。
    同樣,您可能需要更多圖像,或者圖像沒有足夠的可區(qū)分的獨(dú)特紋理/對(duì)象來精確匹配關(guān)鍵點(diǎn)。
  • ERR_CAMERA_PARAMS_ADJUST_FAIL = 3:我之前從未遇到過此錯(cuò)誤,所以我對(duì)此不太了解,但是要點(diǎn)在于,這與無法從輸入圖像中正確估計(jì)相機(jī)的內(nèi)在/外在特性有關(guān)。
    如果遇到此錯(cuò)誤,則可能需要參考OpenCV文檔,甚至需要深入研究OpenCV C ++代碼。

現(xiàn)在,我們已經(jīng)回顧了cv2.createStitcher,cv2.Stitcher_create和.stitch方法,讓我們繼續(xù)實(shí)際使用OpenCV和Python實(shí)現(xiàn)圖像拼接。

基本圖像拼接結(jié)果

但是全景周圍的黑色區(qū)域呢? 那些是什么?
這些區(qū)域從執(zhí)行構(gòu)建全景所需的透視扭曲開始。
有一種方法可以消除它們……但是我們將需要在下一部分中實(shí)現(xiàn)一些其他邏輯。

使用OpenCV和Python更好的圖像拼接器

我們的第一個(gè)圖像拼接腳本是一個(gè)良好的開端,但是全景圖本身周圍的黑色區(qū)域并不是我們所謂的“美觀”。
更重要的是,您不會(huì)從內(nèi)置于iOS,Android等的流行圖像拼接應(yīng)用程序中看到這樣的輸出圖像。
因此,我們將對(duì)腳本進(jìn)行一些修改,并包括一些其他邏輯以創(chuàng)建更美觀的全景圖。
我將再次重申此方法是一種破解。
我們將審查基本的圖像處理操作,包括閾值,輪廓提取,形態(tài)學(xué)操作等,以便獲得所需的結(jié)果。
據(jù)我所知,OpenCV的Python綁定無法為我們提供手動(dòng)提取全景圖的最大內(nèi)部矩形區(qū)域所需的信息。 如果有,請(qǐng)?jiān)谠u(píng)論中讓我知道。
所有這些代碼都與我們之前的腳本相同,但有一個(gè)例外。
--crop命令行參數(shù)已添加。 在終端中為該參數(shù)提供1時(shí),我們將繼續(xù)進(jìn)行裁剪操作。
下一步是我們開始實(shí)現(xiàn)其他功能的地方:

局限和缺點(diǎn)

在上一教程中,我演示了如何構(gòu)建實(shí)時(shí)全景圖和圖像拼接算法-本教程基于以下事實(shí):我們手動(dòng)執(zhí)行關(guān)鍵點(diǎn)檢測(cè),特征提取和關(guān)鍵點(diǎn)匹配,從而使我們能夠使用所用的單應(yīng)性矩陣將我們的兩個(gè)輸入圖像扭曲成全景圖。
而且,盡管OpenCV內(nèi)置的cv2.createStitcher和cv2.Stitcher_create函數(shù)能夠構(gòu)造準(zhǔn)確,美觀的全景圖,但該方法的主要缺點(diǎn)之一是,它抽象了對(duì)單應(yīng)性矩陣的所有訪問。
實(shí)時(shí)全景圖構(gòu)建的一種假設(shè)是,場(chǎng)景本身在內(nèi)容方面變化不大。
一旦我們計(jì)算了初始單應(yīng)性估計(jì),我們只需要偶爾重新計(jì)算矩陣即可。
無需執(zhí)行全面的關(guān)鍵點(diǎn)匹配和RANSAC估計(jì),就可以在構(gòu)建全景圖時(shí)極大地提高了速度,因此,如果無法訪問原始的單應(yīng)性矩陣,采用OpenCV的內(nèi)置圖像拼接算法并對(duì)其進(jìn)行實(shí)時(shí)轉(zhuǎn)換將是一個(gè)挑戰(zhàn)。

總結(jié)

在今天的教程中,您學(xué)習(xí)了如何使用OpenCV和Python執(zhí)行多個(gè)圖像拼接。
使用OpenCV和Python,我們能夠?qū)⒍鄠€(gè)圖像拼接在一起并創(chuàng)建全景圖像。
我們輸出的全景圖像不僅在縫合位置上準(zhǔn)確,而且在美學(xué)上也令人愉悅。
但是,使用OpenCV的內(nèi)置圖像拼接類的最大缺點(diǎn)之一是,它抽象了許多內(nèi)部計(jì)算,包括由此產(chǎn)生的單應(yīng)性矩陣本身。
如果您嘗試執(zhí)行實(shí)時(shí)圖像拼接,如我們?cè)谇耙黄恼轮兴龅哪菢樱瑒t可能會(huì)發(fā)現(xiàn)緩存單應(yīng)性矩陣并且僅偶爾執(zhí)行關(guān)鍵點(diǎn)檢測(cè),特征提取和特征匹配是有益的。
跳過這些步驟并使用緩存的矩陣執(zhí)行透視變形可以減少管道的計(jì)算負(fù)擔(dān),并最終加快實(shí)時(shí)圖像拼接算法的速度,但是不幸的是,OpenCV的cv2.createStitcher Python綁定無法為我們提供對(duì)原始矩陣。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容