getprocaddress得到为0_拼接图像得到全景图
目錄:
本文參考上面這個鏈接,實現多張圖像的拼接,構建一張全景圖。
根據多個圖像創建全景圖的步驟為:
原理比較復雜,本文先不講解,OpenCV中已經實現了全景圖拼接的算法,它們是 cv2.createStitcher (OpenCV 3.x) 和 cv2.Stitcher_create(OpenCV 4) 。
該算法對以下條件具有較好的魯棒性:
- 輸入圖像的順序
- 圖像的方向
- 光照變化
- 圖像噪聲
一、函數介紹
OpenCV 3.x 的 cv2.createStitcher 函數原型為:
createStitcher(...)createStitcher([, try_use_gpu]) -> retval這個函數有一個參數 try_use_gpu,它可以用來提升圖像拼接整個過程的速度。
OpenCV 4 的 cv2.Stitcher_create 函數原型為:
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.要執行實際的圖像拼接,我們需要調用 .stitch 方法:
OpenCV 3.x: stitch(...) method of cv2.Stitcher instancestitch(images[, pano]) -> retval, panoOpenCV 4.x: stitch(...) method of cv2.Stitcher instancestitch(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.該方法接收一個圖像列表,然后嘗試將它們拼接成全景圖像,并進行返回。
變量 status=0表示圖像拼接是否成功。
二、圖像拼接算法實現
先把三張圖片讀取出來存放到列表里:
img_dir = 'pictures/stitching' names = os.listdir(img_dir)images = [] for name in names:img_path = os.path.join(img_dir, name)image = cv2.imread(img_path)images.append(image)圖片順序沒有影響,我試了一下,不同的圖片順序,輸出全景圖都相同。
然后構造圖像拼接對象stitcher, 要注意的是,OpenCV 3 和 4 的構造器是不同的。
import imutils stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create()再把圖像列表傳入.stitch函數,該函數會返回狀態和拼接好的全景圖(如果沒有錯誤):
status, stitched = stitcher.stitch(images)完整代碼如下:
import os import cv2 import imutilsimg_dir = 'pictures/stitching' names = os.listdir(img_dir)images = [] for name in names:img_path = os.path.join(img_dir, name)image = cv2.imread(img_path)images.append(image)stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create() status, stitched = stitcher.stitch(images)if status==0:cv2.imwrite('pictures/stitch.jpg', stitched)OpenCV真的很強大,這短短幾行,就實現了拼接全景圖。
全景圖如下:
呃,全景圖是實現了,但是周圍出現了一些黑色區域。
這是因為構建全景時會做透視變換,透視變換時會產生這些黑色區域。
所以需要做進一步處理,裁剪出全景圖的最大內部矩形區域,也就是只保留下圖中紅色虛線邊框內的全景區域。
三、圖像拼接算法改進
獲取圖像列表并得到初步全景圖,這兩步還是相同的:
img_dir = 'pictures/stitching' names = os.listdir(img_dir)images = [] for name in names:img_path = os.path.join(img_dir, name)image = cv2.imread(img_path)images.append(image)stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create() status, stitched = stitcher.stitch(images)在全景圖四周各添加10像素寬的黑色邊框,以確保能夠找到全景圖的完整輪廓:
stitched = cv2.copyMakeBorder(stitched, 10, 10, 10, 10, cv2.BORDER_CONSTANT, (0, 0, 0))再將全景圖轉換為灰度圖,并將不為0的像素全置為255,作為前景,其他像素灰度值為0,作為背景。
gray = cv2.cvtColor(stitched, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)現在有了全景圖的二值圖,再應用輪廓檢測,找到最大輪廓的邊界框,
注:和輪廓相關的詳細講解可以查看 這篇文章。
cnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnt = max(cnts, key=cv2.contourArea) # 獲取最大輪廓mask = np.zeros(thresh.shape, dtype="uint8") x, y, w, h = cv2.boundingRect(cnt) # 繪制最大外接矩形框(內部填充) cv2.rectangle(mask, (x, y), (x + w, y + h), 255, -1)這個白色矩形框是整個全景圖可以容納下的最小矩形區域。
接下來就是最難,也是最巧妙的部分了,先創建mask的兩個副本:
- minRect,這個mask的白色區域會慢慢縮小,直到它剛好可以完全放入全景圖內部。
- sub,這個mask用于確定minRect是否需要繼續減小,以得到滿足要求的矩形區域。
不斷地對minRect進行腐蝕操作,然后用minRect減去之前得到的閾值圖像,得到sub,
再判斷sub中是否存在非零像素,如果不存在,則此時的minRect就是我們最終想要的全景圖內部最大矩形區域。
sub和minRect在while循環中的變化情況如下動圖所示:
因為OpenCV中灰度圖像素值范圍0-255,如果兩個數相減得到負數的話,會直接將其置為0;如果兩個數相加,結果超過了255的話,則直接置為255。
比如下面這個圖,左圖中白色矩形可以完全包含在全景圖中,但不是全景圖的最大內接矩形,用它減去右邊的閾值圖,
因為黑色像素減白色像素,會得到黑色像素,所以其結果圖為全黑的圖。
所以上面那個while循環最終得到的minRect就是減去閾值圖得到全黑圖的面積最大的矩形區域。
好了,我們已經得到全景圖的內置最大矩形框了,接下來就是找到這個矩形框的輪廓,并獲取其坐標:
cnts, hierarchy = cv2.findContours(minRect.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnt = max(cnts, key=cv2.contourArea) # 計算最大輪廓的邊界框 (x, y, w, h) = cv2.boundingRect(cnt)# 使用邊界框坐標提取最終的全景圖 stitched = stitched[y:y + h, x:x + w]得到最終結果圖如下:
完整代碼如下:
import os import cv2 import imutils import numpy as npimg_dir = '/images' names = os.listdir(img_dir)images = [] for name in names:img_path = os.path.join(img_dir, name)image = cv2.imread(img_path)images.append(image)stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create() status, stitched = stitcher.stitch(images)# 四周填充黑色像素,再得到閾值圖 stitched = cv2.copyMakeBorder(stitched, 10, 10, 10, 10, cv2.BORDER_CONSTANT, (0, 0, 0)) gray = cv2.cvtColor(stitched, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)cnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnt = max(cnts, key=cv2.contourArea)mask = np.zeros(thresh.shape, dtype="uint8") x, y, w, h = cv2.boundingRect(cnt) cv2.rectangle(mask, (x, y), (x + w, y + h), 255, -1)minRect = mask.copy() sub = mask.copy()# 開始while循環,直到sub中不再有前景像素 while cv2.countNonZero(sub) > 0:minRect = cv2.erode(minRect, None)sub = cv2.subtract(minRect, thresh)cnts, hierarchy = cv2.findContours(minRect.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnt = max(cnts, key=cv2.contourArea) x, y, w, h = cv2.boundingRect(cnt)# 使用邊界框坐標提取最終的全景圖 stitched = stitched[y:y + h, x:x + w]cv2.imwrite('final.jpg', stitched)如果覺得有用,就點個贊吧(? ??_??)?。
總結
以上是生活随笔為你收集整理的getprocaddress得到为0_拼接图像得到全景图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 疲劳驾驶数据集_人工检查,11 个类、9
- 下一篇: c盘哪些文件可以删除_Win7下C盘哪些