2016-02-29 69 views
0

進出口尋找建議,以提高我的算法如下圖中搜索部分邊緣提取Suggections OpenCV的

enter image description here

到目前爲止,我有以下

GaussianBlur(canny, canny, Size(5, 5), 2, 2); 
Canny(canny, canny, 100, 200, 5); 
HoughCircles(canny, Part_Centroids, CV_HOUGH_GRADIENT, 2, 30, 100, 50, 50, 60); 

我的邊沿檢測輸出如下像這樣

enter image description here

和Im使用HoughCircle嘗試查找零件。我並沒有取得很大的成功,因爲HoughCircle看起來非常挑剔,而且經常會返回一個圓圈,而這個圓圈並不是真正匹配一部分的圓圈。

改善這種搜索算法

編輯任何建議:

我在下面的意見試過的建議。規範化進行了一些改進,但在修改所需的設置而不是穩定性之前刪除了canny。

我想現在我需要做的是這樣霍夫界具有非常開放的閾值,然後找到一種方式來得分的結果。有沒有什麼好的方法來得分霍夫圓的結果或相關結果與比賽

+0

由於對比度低在做這個圖像之前,我會在做Canny操作之前先對它進行標準化。 – callyalater

+0

在找到HoughCircles之前,您不應該應用canny,因爲HoughCircles本身將應用Canny邊緣檢測 –

+0

您應該提高圖像質量。獲得適當的照明,聚焦你的鏡頭。廢話 - - 廢話 – Piglet

回答

0

的百分比精明的輸出,我想我會後我的解決方案,可能有人會覺得我的經驗教訓是有價值的。

我開始通過採取幾幀,並將它們平均掉。這解決了我在保持強勁邊緣時遇到的一些噪音問題。接下來,我做了一個基本的過濾器和canny邊緣來提取一個體面的邊緣圖。

Scalar cannyThreshold = mean(filter); 
    // Canny Edge Detection 
    Canny(filter, canny, cannyThreshold[0]*(2/3), cannyThreshold[0]*(1+(1/3)), 3); 

接下來,我用的互相關隨diametered模板和商店的比賽是得分超過閾值

// Iterate through diameter ranges 
    for (int r = 40; r < 70; r++) 
    { 
     Mat _mask, _template(Size((r * 2) + 4, (r * 2) + 4), CV_8U); 
     _template = Scalar(0, 0, 0); 
     _mask = _template.clone(); 
     _mask = Scalar(0, 0, 0); 
     circle(_template, Point(r + 4, r + 4), r, Scalar(255, 255, 255), 2, CV_AA); 
     circle(_template, Point(r + 4, r + 4), r/3.592, Scalar(255, 255, 255), 2, CV_AA); 
     circle(_mask, Point(r + 4, r + 4), r + 4, Scalar(255, 255, 255), -1); 

     Mat res_32f(canny.rows, canny.cols, CV_32FC1); 
     matchTemplate(canny, _template, res_32f, CV_TM_CCORR_NORMED, _mask); 
     Mat resize(canny.rows, canny.cols, CV_32FC1); 
     resize = Scalar(0, 0, 0); 
     res_32f.copyTo(resize(Rect((resize.cols - res_32f.cols)/2, (resize.rows - res_32f.rows)/2, res_32f.cols, res_32f.rows))); 
     // Strore Well Scoring Results 
     double minVal, maxVal; 
     double threshold = .25; 
     do 
     { 
      Point minLoc, maxLoc; 
      minMaxLoc(resize, &minVal, &maxVal, &minLoc, &maxLoc); 
      if (maxVal > threshold) 
      { 
       matches.push_back(CircleScore(maxLoc.x, maxLoc.y, r, maxVal,1)); 
       circle(resize, maxLoc, 30, Scalar(0, 0, 0), -1); 
      } 

     } while (maxVal > threshold); 
    } 

我篩選出的最佳匹配界在每個區域

// Sort Matches For Best Match 
    for (size_t i = 0; i < matches.size(); i++) 
    { 
     size_t j = i + 1; 
     while (j < matches.size()) 
     { 
      if (norm(Point2f(matches[i].X, matches[i].Y) - Point2f(matches[j].X, matches[j].Y)) - abs(matches[i].Radius - matches[j].Radius) < 15) 
      { 
       if (matches[j].Score > matches[i].Score) 
       { 
        matches[i] = matches[j]; 
       } 
       matches[j] = matches[matches.size() - 1]; 
       matches.pop_back(); 
       j = i + 1; 
      } 
      else j++; 
     } 
    } 

接下來是棘手的問題。我想看看哪一部分很可能是最重要的。我通過檢查每個接近半徑總和的部分來做到這一點,然後查看重疊區域中的邊緣是否比另一個更強。任何被覆蓋的圓應該在重疊區域中具有較弱的邊緣。

// Layer Sort On Intersection 
    for (size_t i = 0; i < matches.size(); i++) 
    { 
     size_t j = i + 1; 
     while (j < matches.size()) 
     { 
      double distance = norm(Point2f(matches[i].X, matches[i].Y) - Point2f(matches[j].X, matches[j].Y)); 
      // Potential Overlapping Part 
      if (distance < ((matches[i].Radius+matches[j].Radius) - 10)) 
      { 
       int score_i = 0, score_j = 0; 
       Mat intersect_a(canny.rows, canny.cols, CV_8UC1); 
       Mat intersect_b(canny.rows, canny.cols, CV_8UC1); 
       intersect_a = Scalar(0, 0, 0); 
       intersect_b = Scalar(0, 0, 0); 
       circle(intersect_a, Point(cvRound(matches[i].X), cvRound(matches[i].Y)), cvRound(matches[i].Radius) +4, Scalar(255, 255, 255), -1); 
       circle(intersect_a, Point(cvRound(matches[i].X), cvRound(matches[i].Y)), cvRound(matches[i].Radius/3.592-4), Scalar(0, 0, 0), -1); 
       circle(intersect_b, Point(cvRound(matches[j].X), cvRound(matches[j].Y)), cvRound(matches[j].Radius) + 4, Scalar(255, 255, 255), -1); 
       circle(intersect_b, Point(cvRound(matches[j].X), cvRound(matches[j].Y)), cvRound(matches[j].Radius/3.592-4), Scalar(0, 0, 0), -1); 
       bitwise_and(intersect_a, intersect_b, intersect_a); 
       double a, h; 
       a = (matches[i].Radius*matches[i].Radius - matches[j].Radius*matches[j].Radius + distance*distance)/(2 * distance); 
       h = sqrt(matches[i].Radius*matches[i].Radius - a*a); 
       Point2f p0((matches[j].X - matches[i].X)*(a/distance) + matches[i].X, (matches[j].Y - matches[i].Y)*(a/distance) + matches[i].Y); 
       circle(intersect_a, Point2f(p0.x + h*(matches[j].Y - matches[i].Y)/distance, p0.y - h*(matches[j].X - matches[i].X)/distance), 6, Scalar(0, 0, 0), -1); 
       circle(intersect_a, Point2f(p0.x - h*(matches[j].Y - matches[i].Y)/distance, p0.y + h*(matches[j].X - matches[i].X)/distance), 6, Scalar(0, 0, 0), -1); 
       bitwise_and(intersect_a, canny, intersect_a); 
       intersect_b = Scalar(0, 0, 0); 
       circle(intersect_b, Point(cvRound(matches[i].X), cvRound(matches[i].Y)), cvRound(matches[i].Radius), Scalar(255, 255, 255), 6); 
       bitwise_and(intersect_a, intersect_b, intersect_b); 
       score_i = countNonZero(intersect_b); 
       intersect_b = Scalar(0, 0, 0); 
       circle(intersect_b, Point(cvRound(matches[j].X), cvRound(matches[j].Y)), cvRound(matches[j].Radius), Scalar(255, 255, 255), 6); 
       bitwise_and(intersect_a, intersect_b, intersect_b); 
       score_j = countNonZero(intersect_b); 
       if (score_i < score_j)matches[i].Layer = matches[j].Layer + 1; 
       if (score_j < score_i)matches[j].Layer = matches[i].Layer + 1; 
      } 
      j++; 
     } 
    } 

之後,它很容易提取最好的部分挑(IM相關深度數據以及

enter image description here

藍色圓圈是部件,綠圈是最高的堆棧和紅色圓圈是其他部分下的部分

我希望這可以幫助其他人在類似問題上工作