2016-02-29 79 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

蓝色圆圈是部件,绿圈是最高的堆栈和红色圆圈是其他部分下的部分

我希望这可以帮助其他人在类似问题上工作