【问题标题】:Edge Extraction Suggections OpenCV边缘提取建议 OpenCV
【发布时间】:2016-06-13 05:10:08
【问题描述】:

我正在寻找改进算法以在下图中搜索零件的建议

到目前为止,我有以下内容

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);

我的边缘检测输出如下所示

我使用 HoughCircle 来尝试找到零件。不过,我并没有取得很大的成功,因为 HoughCircle 看起来非常挑剔,并且经常返回一个并不是真正适合某个部分的圆圈。

关于改进此搜索算法的任何建议

编辑:

我已经尝试了以下 cmets 中的建议。规范化做了一些改进,但在霍夫圆改变了所需的设置而不是稳定性之前移除了精明。

我认为现在我需要做一些类似于具有非常开放阈值的霍夫圈的事情,然后找到一种方法来对结果进行评分。有没有什么好的方法可以对霍夫圆的结果进行评分或将结果与匹配百分比的精明输出相关联

【问题讨论】:

  • 由于这张图片的对比度很低,我会在进行 Canny 操作之前先对其进行归一化。
  • 你不应该在找到 HoughCircles 之前应用 canny,因为 HoughCircles 本身会应用 canny 边缘检测
  • 您应该提高图像质量。获得一些适当的照明,聚焦你的镜头。废话->废话

标签: c++ opencv vision


【解决方案1】:

我想我会发布我的解决方案,因为有人可能会发现我的经验教训很有价值。

我首先拍摄了几帧并将它们平均出来。这解决了我在保留强边缘时遇到的一些噪音问题。接下来我做了一个基本的过滤器和精巧的边缘来提取一个像样的边缘图。

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

接下来,我使用与增加直径模板的互相关并存储得分超过阈值的匹配项

    // 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++;
        }
    }

之后很容易提取最好的部分来挑选(我也与深度数据相关

蓝色圆圈是零件,绿色圆圈是最高的堆栈,红色圆圈是在其他零件下方的零件。

我希望这可以帮助解决类似问题的其他人

【讨论】:

    猜你喜欢
    • 2010-10-28
    • 2018-10-24
    • 1970-01-01
    • 2012-09-12
    • 1970-01-01
    • 2012-01-28
    • 2017-07-06
    • 2013-09-12
    • 2017-01-02
    相关资源
    最近更新 更多