2017-04-08 151 views
5

在任務中,我得到了一個不連續的邊緣圖像,怎麼能關閉它?換言之,使曲線連續。 形狀可以是任何種類,造成這種coutour影子。如何使圖像的不連續輪廓一致?

enter image description here

+0

您可以嘗試擴張或適合花鍵/多項式輪廓點。 –

+0

我試過膨脹和多項式方法,前者容易受噪音影響,最後一個不能完成這項任務,並且如果有任何方法可以獲得與給定曲線最接近的曲線? – wanger

+0

形狀總是橢圓形的?例如,它可能是您正在尋找的廣場嗎? –

回答

4

這裏有一些想法,可以讓你開始。我不想在OpenCV中編寫和調試C++的負載 - 通常人們會提出問題並且不會再次登錄,或者花費幾個小時來處理某些事情,然後他們告訴您他們提供的單個樣本映像根本沒有代表性他們的實際圖像和25分鐘解釋的方法完全不合適。


一個想法是形態膨脹 - 你可以這樣做,在這樣的命令行中使用ImageMagick的:

convert gappy.jpg -threshold 50% -morphology dilate disk:5 result.png 

enter image description here


另一個想法可能是找到所有「行結束」像素與命中和小姐形態。這在OpenCV中可用,但我正在使用ImageMagick來保存編碼/調試。結構元素是這樣的:

enter image description here

希望你可以看到,第一個(最左邊的)結構元素表示東西線的西方端,並且所述第二個表示的北端南北線等。如果你還沒有得到它,最後一個是東西南西線的西南端​​。

基本上,我覺得行結束,然後用藍色像素擴張它們,疊加層到原:

convert gappy.jpg -threshold 50% \ 
    \(+clone -morphology hmt lineends -morphology dilate disk:1 -fill blue -opaque white -transparent black \) \ 
    -flatten result.png 

enter image description here

這裏有一個特寫前後:

enter image description here

你還可以找到沒有鄰居的單身像素,使用「峯」結構元素,像這樣:

enter image description here

,然後你可以找到所有的峯值和紅色像素這樣的擴張他們:

convert gappy.jpg -threshold 50% \ 
    \(+clone -morphology hmt Peaks:1.9 -fill red -morphology dilate disk:2 -opaque white -transparent black \) \ 
    -flatten result.png 

enter image description here

這裏前後特寫:

enter image description here

根據您的原始圖像的外觀,您可能會反覆應用上述想法,直到輪廓完整爲止 - 也許您可以通過充水並檢測輪廓「持有水」而沒有洪水到處填寫「泄漏」

顯然你會做白色的紅色峯和藍色的線結束來完成你的輪廓 - 我只是用顏色來說明我的技術。

1

馬克Setchell的答案是一個有趣的方式來學習新的東西。我的方法非常簡單直接。

我從頭頂上獲得了以下解決方案。它涉及夾在兩個形態學操作

之間的簡單模糊運算我已經解釋了什麼我已經沿着代碼中完成:

#---- I converted the image to gray scale and then performed inverted binary threshold on it. ---- 

img = cv2.imread('leaf.jpg') 
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
ret, thresh = cv2.threshold(gray, 127, 255, 1) 

enter image description here

#---- Next I performed morphological erosion for a rectangular structuring element of kernel size 7 ---- 

kernel = np.ones((7, 7),np.uint8) 
erosion = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel, iterations = 2) 
cv2.imshow('erosion', erosion) 

enter image description here

#---- I then inverted this image and blurred it with a kernel size of 15. The reason for such a huge kernel is to obtain a smooth leaf edge ---- 

ret, thresh1 = cv2.threshold(erosion, 127, 255, 1) 
blur = cv2.blur(thresh1, (15, 15)) 
cv2.imshow('blur', blur) 

enter image description here

#---- I again performed another threshold on this image to get the central portion of the edge ---- 

ret, thresh2 = cv2.threshold(blur, 145, 255, 0) 

#---- And then performed morphological erosion to thin the edge. For this I used an ellipse structuring element of kernel size 5 ---- 

kernel1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) 
final = cv2.morphologyEx(thresh2, cv2.MORPH_ERODE, kernel1, iterations = 2) 
cv2.imshow(final', final) 

enter image description here

希望這有助於:)

2

這裏有一個稍微不同的方式來完成它使用ImageMagick

1)閾值和擴張輪廓

convert 8y0KL.jpg -threshold 50% -morphology dilate disk:11 step1.gif 

enter image description here

2)較小的量

convert step1.gif -morphology erode disk:8 step2.gif 

enter image description here

3)墊由1像素的所有周圍的黑色侵蝕,並用白色floodfill外部並所有除去填充1個像素大約

convert step2.gif -bordercolor black -border 1 -fill white -draw "color 0,0 floodfill" -alpha off -shave 1x1 step3.gif 

enter image description here

4)以較小的量腐蝕並獲得過渡白色邊緣。請注意,我們從擴張11開始,然後我們侵蝕8,然後我們現在侵蝕3。所以8 + 3 = 11應該讓我們回到中線附近。

convert step3.gif -morphology erode disk:3 -morphology edgein diamond:1 step4.gif 

enter image description here

5)創建動畫比較

convert -delay 50 8y0KL.jpg step4.gif -loop 0 animation.gif 

enter image description here

+0

有趣!它只是表明 - 我試圖保留這兩個中等大小的斑點在左上角! –

1

這裏還有一個建議,即是多 「的計算機視覺文學」 爲主。作爲經驗法則的預處理步驟,通常是減少所有邊緣以確保它們大約爲1個像素厚度的好主意。流行的邊緣細化方法是non-maximal suppression(NMS)。

然後,我將開始分析圖像,並找到我有的所有連接組件。 OpenCV已經提供了connectedComponents函數。一旦確定了連通分量組,就可以爲每個組擬合貝塞爾曲線。將貝塞爾曲線擬合成一組二維點的自動方法可在Graphics Gem書中找到。他們的方法也有C代碼available。擬合貝塞爾曲線的目標是儘可能多地高度理解每個組件組。

接下來,你需要加入這些Bezier曲線一起。在Shpitalni and Lipson的工作中可以使用使用端點聚類連接線的方法。在那篇文章中,看一下他們的自適應聚類方法,名爲「實體鏈接和端點聚類」

最後,將所有曲線組合在一起後,您可以擬合最終的貝塞爾曲線,所有點都必須得到一個漂亮自然的邊緣貼圖。

作爲一個附註,你可以在cartoon curve extraction看看Ming-Ming Cheng的作品。有可用於該方法here too基於OpenCV的代碼,而是將輸出以下一次應用到你的形象:

enter image description here

免責聲明:
我可以證明貝塞爾曲線擬合算法的性能,我個人使用它,它工作得很好。 Cheng的曲線提取算法的效果也很好,但是,由於使用了梯度檢測(這有一種使細線變粗的傾向),它會產生外形很薄的不好看的「斑點」。如果您可以找到解決此「增厚」效應的方法,則可以跳過Bezier曲線提取並直接跳入端點聚類以將曲線連接在一起。

希望這會有所幫助!

0

您可以嘗試使用距離變換

% binarize 
im=rgb2gray(im); im=im>100; 

% Distance transform 
bd=bwdist(im); 
maxDist = 5; 
bd(bd<maxDist)=0; 
bw=bwperim(bd); bw=imclearborder(bw); 
bw=imfill(bw,'holes'); 
bw=bwperim(bwmorph(bw,'thin',maxDist)); 

figure,imagesc(bw+2*im),axis image 

enter image description here

1

我的建議:

  • 找到端點;這些是最多隻有一個鄰居的像素,在細化步驟後放棄「厚」端點。端點應該成對出現。

  • 從所有端點開始,增大數字磁盤直到遇到另一個不是同級的端點。

您可以預處理該組端點併爲最近鄰居搜索(例如2D樹)做好準備,而不是增加磁盤。您需要修改搜索以避免碰到同伴。

這種方法不依賴於標準的功能,但它的優勢在於尊重原來的輪廓。

在圖片,原始像素是白色或綠色的時候都端點。黃色像素是在最近端點對之間繪製的數字線段。

enter image description here