2011-10-04 101 views
4

我正在使用OpenCV進行項目工作。我需要精確地從高清照片中剪出一些物體。 我正在使用四叉樹將我的照片分割成幾部分,然後計算每個四邊形的均勻性以確定一個對象是否位於四邊形中。 我根據四邊形的均勻性將不同的閾值應用於Canny一些濾波器。 我希望這個描述是可以理解的。如何增加輪廓精度?

此算法適用於某些類型的對象,但我與其他一些對象卡住了。 在這裏我的問題的一些例子:我想要一種方法來削平我的輪廓。 第一個屏幕截圖是使用canny過濾器和floodfill後的第一個屏幕截圖。第二個是最終的屏蔽結果。

http://pastebin.com/91Pgrd2D


爲了實現這個結果,我用cvFindContours()所以我有輪廓,但我不能找到一種方法來處理他們像我想要的。

+0

你有什麼輪廓問題?你想更平滑他們? – Adrian

+0

@AdrianPopovici:那種,我希望他們能夠從我的物體上結合曲線,而不必擁有所有的人工製品。這裏是原始圖片:http://imageshack.us/photo/my-images/15/ex5gl.jpg/ – Turgal

+0

在找到輪廓之前,您可以在B&W圖像上運行一些濾鏡,例如高斯濾鏡,然後設置閾值,這可以使輪廓平滑一些,但可能並不適合所有點的確切對象。您可以使用輪廓線做的另一件事是使用AproxPoly,然後應用樣條線或其他東西。 – Adrian

回答

5

也許你可以使用某種平均濾波器來近似曲線,然後使用帶有小梯度的AproxPoly來平滑它。 下面是一個類似的方法:

void AverageFilter(CvSeq * contour, int buff_length) 
{ 
    int n = contour->total, i, j; 
    if (n > buff_length) 
    { 
     CvPoint2D32f* pnt; 
     float* sampleX = new float[buff_length]; 
     float* sampleY = new float[buff_length]; 

     pnt = (CvPoint2D32f*)cvGetSeqElem(contour, 0); 
     for (i = 0; i < buff_length; i++) 
     { 
      if (i >= buff_length/2) 
      { 
       pnt = (CvPoint2D32f*)cvGetSeqElem(contour, i + 1 - buff_length/2); 
      } 
      sampleX[i] = pnt->x; 
      sampleY[i] = pnt->y; 
     } 

     float sumX = 0, sumY = 0; 

     for (i = 1; i < n; i++) 
     { 
      pnt = (CvPoint2D32f*)cvGetSeqElem(contour, i); 
      for (j = 0; j < buff_length; j++) 
      { 
       sumX += sampleX[j]; 
       sumY += sampleY[j]; 
      } 
      pnt->x = sumX/buff_length; 
      pnt->y = sumY/buff_length; 
      for (j = 0; j < buff_length - 1; j++) 
       { 
        sampleX[j] = sampleX[j+1]; 
        sampleY[j] = sampleY[j+1]; 
       } 
      if (i <= (n - buff_length/2)) 
      { 
       pnt = (CvPoint2D32f*)cvGetSeqElem(contour, i + buff_length/2 + 1); 
       sampleX[buff_length - 1] = pnt->x; 
       sampleY[buff_length - 1] = pnt->y; 
      } 
      sumX = 0; 
      sumY = 0; 
     } 
     delete[] sampleX; 
     delete[] sampleY; 
    } 
} 

你給它的輪廓和你想做的平均點的緩衝區的大小。 如果您認爲輪廓太厚,因爲某些平均點太靠近,那麼這就是Aproxpoly進來的地方,因爲它減少了點數。 但是選擇一個合適的漸變,所以你不要太尖銳。

srcSeq = cvApproxPoly(srcSeq,sizeof(CvContour),storage, CV_POLY_APPROX_DP, x, 1); 

玩'x'看看你如何得到更好的結果。

+0

感謝這正是我所需要的。但它對於我使用的每個切片都會造成奇怪的東西。更多buff_lenght越高,「線條」越強。 http://imageshack.us/f/831/seqs.png/我正在處理它,但如果你直接知道它來自哪裏,它會有所幫助:) – Turgal

+0

那麼,buff_length是你想包括多少點當前點的平均值,也應該是奇數(13,15,17,19 ...),所以對於13的buff_length,每個點將從前6個點的平均值中重新計算,本身和接下來的6個點點。如果您使用CV_CHAIN_APPROX_NONE獲得等高線,您將獲得更多積分,以便獲得更好的平均值。之後,您可以使用AproxPoly和一個小值參數,如1-2 – Adrian

+0

@Adrien:感謝您的編輯,它對奇數更好,我的不好:) – Turgal