我已經使用OpenCV函數和C++將兩個圖像拼接在一起。現在我面臨一個問題,即最終的圖像包含一個大的黑色部分。如何從圖像中刪除黑色部分?
最終圖像應該是包含有效部分的矩形。 我的形象是:
如何刪除黑色款?
我已經使用OpenCV函數和C++將兩個圖像拼接在一起。現在我面臨一個問題,即最終的圖像包含一個大的黑色部分。如何從圖像中刪除黑色部分?
最終圖像應該是包含有效部分的矩形。 我的形象是:
如何刪除黑色款?
mevatron
的答案是黑色區域的數量最小化同時保留完整圖像的一種方法。
另一種選擇是去除完整的黑色區域,在這個區域中也會丟失圖像的某些部分,但結果會是一個整齊的長方形圖像。以下是Python代碼。
在這裏,你會發現圖像的三個主要的角落如下:
我已標記的值。 (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),你得到的結果如下:
因此,您裁剪圖像以糾正矩形區域。
img2 = img[:y,:x].copy()
下面是結果:
See, the problem is that you lose some parts of the stitched image.
:因爲我更熟悉C++,並試圖將代碼(在Python中)轉換爲C++,但無法成功。如果您可以請C++語言共享相同的代碼,我會非常感激。 –
我很抱歉,我不擅長C++。但如果你告訴我,如果你對我的方法中的任何步驟有任何疑問,我可以用更簡單的方式解釋。 –
:我已經完成了所有的步驟,直到approxpolyDP,但我不知道如何計算C中座標點的乘積,我認爲你也使用了僞代碼。可以告訴我如何計算C中座標點的乘積或者給我任何鏈接,其中有人使用了你的C類型的方法。在應用approxpoly()方法後,我的圖像是參考[http://i.imgur.com/Qfoyt.jpg?1]。希望你也得到了應用approxpolyDp()後的輸出圖像相同。 –
您可以使用threshold,findContours和boundingRect來做到這一點。
所以,這裏是一個快速的腳本,用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]]
最終看起來像這樣:
注:排序可能沒有必要用生圖像,但使用壓縮圖像引起了一些壓縮僞像使用低閾值時展現出來,所以這就是爲什麼我使用排序進行後處理。
希望有幫助!
+1偉大的工作示例。 – karlphillip
你也許可以使用cvFindContours讓您的圖像內容的範圍,然後裁剪到... – LiMuBei
同時加入圖片在問題中,使用'imwrite'輸出結果並添加它。這比添加屏幕截圖要好,因爲那些回答你問題的人需要從圖像中刪除不需要的區域。 –
您的工作區很整潔。 – wengseng