簡體   English   中英

邊緣提取建議OpenCV

[英]Edge Extraction Suggections OpenCV

我正在尋找改善我的算法以搜索下圖中的零件的建議

在此處輸入圖片說明

到目前為止,我有以下

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看上去很挑剔,並且經常返回一個實際上並不是部分最佳匹配的圓圈。

關於改進此搜索算法的任何建議

編輯:

我已經嘗試了以下評論中的建議。 歸一化進行了一些改進,但是在霍夫圓之前刪除了Canny,從而更改了所需的設置,但沒有更改穩定性。

我認為現在我需要做一些像霍夫圈那樣的非常開放的閾值,然后找到一種對結果進行評分的方法。 是否有任何好的方法可以對霍夫圓的結果進行評分或將結果與canny輸出相關以進行匹配百分比

我以為我會發布我的解決方案,因為有人會發現我學到的教訓很有價值。

我首先拍攝了幾幀並將其平均。 這解決了我在保留強邊緣時遇到的一些噪音問題。 接下來,我做了一個基本的過濾器和Canny邊緣,以提取一個體面的邊緣貼圖。

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

之后,很容易提取出最適合的部分(Im也與深度數據相關)

在此處輸入圖片說明

藍色的圓圈是部分,綠色的圓圈是最高的堆棧,紅色的圓圈是在其他部分下面的部分。

我希望這可以幫助其他人解決類似的問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM