2012-05-17 185 views
10

我已經使用OpenCV函數和C++將兩個圖像拼接在一起。現在我面臨一個問題,即最終的圖像包含一個大的黑色部分。如何從圖像中刪除黑色部分?

最終圖像應該是包含有效部分的矩形。 我的形象是:

enter image description here

如何刪除黑色款?

+0

你也許可以使用cvFindContours讓您的圖像內容的範圍,然後裁剪到... – LiMuBei

+2

同時加入圖片在問題中,使用'imwrite'輸出結果並添加它。這比添加屏幕截圖要好,因爲那些回答你問題的人需要從圖像中刪除不需要的區域。 –

+4

您的工作區很整潔。 – wengseng

回答

16

mevatron的答案是黑色區域的數量最小化同時保留完整圖像的一種方法。

另一種選擇是去除完整的黑色區域,在這個區域中也會丟失圖像的某些部分,但結果會是一個整齊的長方形圖像。以下是Python代碼。

在這裏,你會發現圖像的三個主要的角落如下:

enter image description here

我已標記的值。 (1,x2), (x1,1), (x3,y3)。它基於你的圖像從(1,1)開始的假設。

代碼:

第一步驟同mevatron的。模糊圖像以去除噪點,對圖像進行閾值處理,然後查找輪廓。

import cv2 
import numpy as np 

img = cv2.imread('office.jpg') 
img = cv2.resize(img,(800,400)) 

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
gray = cv2.medianBlur(gray,3) 

ret,thresh = cv2.threshold(gray,1,255,0) 
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) 

現在找到最大的輪廓,這是你的形象。這是爲了避免噪音,如果有的話(很可能不會有)。或者你可以使用mevatron的方法。

max_area = -1 
best_cnt = None 

for cnt in contours: 

    area = cv2.contourArea(cnt) 
    if area > max_area: 
     max_area = area 
     best_cnt = cnt 

現在近似輪廓以刪除找到的輪廓值中不必要的點,但它保留所有角值。

approx = cv2.approxPolyDP(best_cnt,0.01*cv2.arcLength(best_cnt,True),True) 

現在我們找到了角落。

首先,我們找到(x3,y3)。這是最遠的點。所以x3*y3將會非常大。所以我們找到所有對點的產品並選擇最大產品對。

far = approx[np.product(approx,2).argmax()][0] 

Next(1,x2)。這是第一個元素是一個,然後第二個元素是最大的點。

ymax = approx[approx[:,:,0]==1].max() 

Next(x1,1)。它是第二個元素是1的點,那麼第一個元素是最大的。

xmax = approx[approx[:,:,1]==1].max() 

現在我們找到了minimum values in (far.x,xmax) and (far.y, ymax)

x = min(far[0],xmax) 
y = min(far[1],ymax) 

如果您繪製(1,1)的矩形和(X,Y),你得到的結果如下:

enter image description here

因此,您裁剪圖像以糾正矩形區域。

img2 = img[:y,:x].copy() 

下面是結果:

enter image description here

See, the problem is that you lose some parts of the stitched image.

+1

:因爲我更熟悉C++,並試圖將代碼(在Python中)轉換爲C++,但無法成功。如果您可以請C++語言共享相同的代碼,我會非常感激。 –

+0

我很抱歉,我不擅長C++。但如果你告訴我,如果你對我的方法中的任何步驟有任何疑問,我可以用更簡單的方式解釋。 –

+0

:我已經完成了所有的步驟,直到approxpolyDP,但我不知道如何計算C中座標點的乘積,我認爲你也使用了僞代碼。可以告訴我如何計算C中座標點的乘積或者給我任何鏈接,其中有人使用了你的C類型的方法。在應用approxpoly()方法後,我的圖像是參考[http://i.imgur.com/Qfoyt.jpg?1]。希望你也得到了應用approxpolyDp()後的輸出圖像相同。 –

0

您可以使用活動輪廓(氣球/蛇)來精確選擇黑色區域。示範可以發現here。 OpenCV提供活動輪廓,請查詢cvSnakeImage

+0

你能告訴我如何實施它去除黑色部分嗎? –

8

您可以使用thresholdfindContoursboundingRect來做到這一點。

所以,這裏是一個快速的腳本,用python界面做這件事。

stitched = cv2.imread('stitched.jpg', 0) 
(_, mask) = cv2.threshold(stitched, 1.0, 255.0, cv2.THRESH_BINARY); 

# findContours destroys input 
temp = mask.copy() 
(contours, _) = cv2.findContours(temp, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 

# sort contours by largest first (if there are more than one) 
contours = sorted(contours, key=lambda contour:len(contour), reverse=True) 
roi = cv2.boundingRect(contours[0]) 

# use the roi to select into the original 'stitched' image 
stitched[roi[1]:roi[3], roi[0]:roi[2]] 

最終看起來像這樣: enter image description here

注:排序可能沒有必要用生圖像,但使用壓縮圖像引起了一些壓縮僞像使用低閾值時展現出來,所以這就是爲什麼我使用排序進行後處理。

希望有幫助!

+0

+1偉大的工作示例。 – karlphillip

相關問題