2014-04-04 81 views
1

我有一個圖像,在這裏我需要刪除不代表檢測到的曲線的「白色」僞影。我想保留代表曲線的白色像素,但要去除遠離曲線的像素異常值。去除僞影后,我想對圖像中的點進行平滑曲線擬合。OpenCV - 從圖像中刪除「白色」僞影並擬合曲線

這是我的形象:

white detected curve

的圖像是隻有黑白點的8位灰度圖像的圖像。 「曲線」中的白色像素是感興趣的區域,其中大部分僅爲單個像素厚。一些白色像素相互連接,但不是全部。一些白色像素散佈在兩邊。我想刪除這些白色像素,因爲它們對整體形狀沒有貢獻,因爲我想爲它們擬合光滑的曲線。

到目前爲止,我試圖做dilation,然後erosion,closingblack hat操作。他們中的任何一個似乎都沒有給我預期的結果。 我還嘗試遍歷圖像中的所有點,找到亮點,在圍繞該像素的3x3鄰域中查找,並將值設置爲0,前提是它沒有超過兩個相同的鄰居。

我可以申請什麼以達到我想要的效果?另外,一旦我有了最終的「乾淨」輸出,我該如何使圖像中的點平滑曲線?

+0

我認爲,擴張後更大的侵蝕應該在保持曲線的組成部分的同時去除大部分僞影。爲了適應曲線,你可以嘗試一些霍夫投票方法。 – ChronoTrigger

+0

@ChronoTrigger不,更糟。被檢測的表面或者完全消失,具有比被認爲是噪聲的必要更多的像素。我正在尋找一種方法來保存檢測到的邊緣。也許類似於連接組件方法? – Eagle

+0

@ChronoTrigger什麼是Hough投票計劃?你有幾個鏈接到我可以學習東西的文檔/實現? – Eagle

回答

0

我不知道如何擬合曲線,如果在另一個問題中提出這個問題,你會很高興。


關於噪音:此功能應該做的伎倆,我用它來消除黑色和等待圖像中的噪音。 它是一本書一個代碼示例:

掌握的OpenCV與實用計算機視覺項目 - 丹尼爾Lelis 巴喬

我的這些包括在哪裏這個功能被實例化的頭說:

#include "opencv2/opencv.hpp" 
#include <stdio.h> 
#include <iostream> 
#include <vector> 

using namespace cv; 
using namespace std; 

mask是你想要過濾的圖像,它可以去掉在分析過的任何5個像素中沒有點的點... 希望它有幫助s

void removePepperNoise(Mat &mask) 
{ 
// For simplicity, ignore the top & bottom row border. 
for (int y=2; y<mask.rows-2; y++) { 
    // Get access to each of the 5 rows near this pixel. 
    uchar *pThis = mask.ptr(y); 
    uchar *pUp1 = mask.ptr(y-1); 
    uchar *pUp2 = mask.ptr(y-2); 
    uchar *pDown1 = mask.ptr(y+1); 
    uchar *pDown2 = mask.ptr(y+2); 

    // For simplicity, ignore the left & right row border. 
    pThis += 2; 
    pUp1 += 2; 
    pUp2 += 2; 
    pDown1 += 2; 
    pDown2 += 2; 
    for (int x=2; x<mask.cols-2; x++) { 
     uchar v = *pThis; // Get the current pixel value (either 0 or 255). 
     // If the current pixel is black, but all the pixels on the 2-pixel-radius-border are white 
     // (ie: it is a small island of black pixels, surrounded by white), then delete that island. 
     if (v == 0) { 
      bool allAbove = *(pUp2 - 2) && *(pUp2 - 1) && *(pUp2) && *(pUp2 + 1) && *(pUp2 + 2); 
      bool allLeft = *(pUp1 - 2) && *(pThis - 2) && *(pDown1 - 2); 
      bool allBelow = *(pDown2 - 2) && *(pDown2 - 1) && *(pDown2) && *(pDown2 + 1) && *(pDown2 + 2); 
      bool allRight = *(pUp1 + 2) && *(pThis + 2) && *(pDown1 + 2); 
      bool surroundings = allAbove && allLeft && allBelow && allRight; 
      if (surroundings == true) { 
       // Fill the whole 5x5 block as white. Since we know the 5x5 borders 
       // are already white, just need to fill the 3x3 inner region. 
       *(pUp1 - 1) = 255; 
       *(pUp1 + 0) = 255; 
       *(pUp1 + 1) = 255; 
       *(pThis - 1) = 255; 
       *(pThis + 0) = 255; 
       *(pThis + 1) = 255; 
       *(pDown1 - 1) = 255; 
       *(pDown1 + 0) = 255; 
       *(pDown1 + 1) = 255; 
      } 
      // Since we just covered the whole 5x5 block with white, we know the next 2 pixels 
      // won't be black, so skip the next 2 pixels on the right. 
      pThis += 2; 
      pUp1 += 2; 
      pUp2 += 2; 
      pDown1 += 2; 
      pDown2 += 2; 
     } 
     // Move to the next pixel. 
     pThis++; 
     pUp1++; 
     pUp2++; 
     pDown1++; 
     pDown2++; 
    } 
} 
+0

我不想刪除白色像素。我想保留曲線中白色像素的結構,但是我想擺脫那些離曲線很遠的白色像素。我不確定你的代碼試圖做什麼,但是,我會嘗試看看它是否有效。 – Eagle

+0

該代碼從圖像中刪除5x5塊中的單個「黑色像素」(我使用它的時間是我的噪音是黑色的)。我沒有注意到你的像素島的比例與你的線相同。對不起,不好的方法,它不會解決你的問題。 – nico

+0

你的代碼指出我正確的方向。我有一個想法之後,尋找橫跨對角線的像素,如下所示:http://stackoverflow.com/questions/22898881/opencv-fit-a-curve-to-a-set-of-points。當線段用於近似曲線時,輸出看起來很好。然而,理想情況下,我會喜歡光滑的曲線,因爲我無法擺脫所有的異常點,而不會冒着檢測到的曲線上一堆點的損失風險。除非我能夠正確地擬合曲線,否則我現在必須以某種方式進行折衷。 – Eagle