31

黒いコイン内の白い穴を埋めることに問題があるため、塗りつぶされた黒いコインで 0 ~ 255 のバイナリ イメージしか持てません。メディアン フィルターを使用してそれを達成しましたが、その場合、コイン間の接続ブリッジが大きくなり、不可能になります。数回の浸食後にそれらを認識するために...だから、opencvで簡単なfloodFillのようなメソッドが必要です

穴のある私の画像は次のとおりです。

ここに画像の説明を入力

編集:フラッドフィルのような関数は、シードとして X、Y 座標を要求することなく、大きなコンポーネントの穴を埋めなければなりません...

編集: cvDrawContours 関数を使用しようとしましたが、大きな輪郭内の輪郭を塗りつぶしません。

これが私のコードです:

        CvMemStorage mem = cvCreateMemStorage(0);
        CvSeq contours = new CvSeq();
        CvSeq ptr = new CvSeq();
        int sizeofCvContour = Loader.sizeof(CvContour.class);

        cvThreshold(gray, gray, 150, 255, CV_THRESH_BINARY_INV);

        int numOfContours = cvFindContours(gray, mem, contours, sizeofCvContour, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
        System.out.println("The num of contours: "+numOfContours); //prints 87, ok

        Random rand = new Random();
        for (ptr = contours; ptr != null; ptr = ptr.h_next()) {
            Color randomColor = new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat());
            CvScalar color = CV_RGB( randomColor.getRed(), randomColor.getGreen(), randomColor.getBlue());
            cvDrawContours(gray, ptr, color, color, -1, CV_FILLED, 8);
        }
        CanvasFrame canvas6  = new CanvasFrame("drawContours");
        canvas6.showImage(gray);

結果: (各コインの中にブラックホールが見えます)

ここに画像の説明を入力

4

7 に答える 7

54

これを行うには、次の 2 つの方法があります。

1) 輪郭の塗りつぶし :

最初に画像を反転し、画像の輪郭を見つけ、黒で塗りつぶしてから反転します。

des = cv2.bitwise_not(gray)
contour,hier = cv2.findContours(des,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)

for cnt in contour:
    cv2.drawContours(des,[cnt],0,255,-1)

gray = cv2.bitwise_not(des)

結果の画像:

ここに画像の説明を入力

2) 画像のオープニング:

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
res = cv2.morphologyEx(gray,cv2.MORPH_OPEN,kernel)

結果の画像は次のとおりです。

ここに画像の説明を入力

ご覧のとおり、どちらの場合も大きな違いはありません。

NB : グレー - グレースケール画像、すべてのコードは OpenCV-Python にあります

于 2012-04-25T14:33:10.400 に答える
5

単純な膨張と侵食は、ギャップをかなりうまく埋めるだろうと私は想像します。多分これがあなたが探しているものだと思います。

より堅牢な解決策は、画像全体でエッジ検出を実行してから、円のハフ変換を実行することです。簡単なグーグルは、ハフ変換を使用して円のサイズ不変検出のためにさまざまな言語で利用可能なコードサンプルがあることを示しています。

ハフ変換を使用する利点は、アルゴリズムが実際にすべての円のサイズと位置の推定値を提供するため、そのモデルに基づいて理想的な画像を再構築できることです。特にここでの入力画像の品質を考慮すると、オーバーラップすることも非常に堅牢である必要があります(つまり、誤検知の心配が少ないため、結果のしきい値を下げることができます)。

于 2012-04-25T14:31:03.693 に答える
4

形態学的画像再構成のアプリケーションであるFillhole変換を探しているかもしれません。

この変換は、隣接するコインのグループ間のすべての穴を埋めるという犠牲を払ってでも、コインの穴を埋めます。他のポスターによって提案されたハフスペースまたはオープニングベースのソリューションは、おそらくより良い高レベルの認識結果をもたらすでしょう。

于 2012-04-25T14:39:31.213 に答える
2

誰かが cpp の実装を探している場合 -

            std::vector<std::vector<cv::Point> > contours_vector;

            cv::findContours(input_image, contours_vector, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

            cv::Mat contourImage(input_image.size(), CV_8UC1, cv::Scalar(0));
            for ( ushort contour_index = 0; contour_index < contours_vector.size(); contour_index++) {
                cv::drawContours(contourImage, contours_vector, contour_index, cv::Scalar(255), -1);
            }

            cv::imshow("con", contourImage);
            cv::waitKey(0);

ここに画像の説明を入力

ここに画像の説明を入力

于 2018-09-27T16:28:21.533 に答える
1

cvFindContours()関数を使用してみてください。これを使用して、接続されたコンポーネントを見つけることができます。適切なパラメータを使用すると、この関数は各接続コンポーネントの輪郭を含むリストを返します。

穴を表す輪郭を見つけます。次にcvDrawContours()を使用して、選択した輪郭を前景色で塗りつぶし、穴を閉じます。

于 2012-04-25T14:01:28.720 に答える
1

オブジェクトが触れていたり、密集していたり​​すると、輪郭や数学のモフォロジーのオープニングを使用する際に問題が生じると思います。代わりに、次の簡単な解決策を見つけてテストします。この画像だけでなく、他の画像でも非常にうまく機能しています。

http://blogs.mathworks.com/steve/2008/08/05/filling-small-holes/に見られる手順 (最適化) は次のとおりです。

let I: 入力画像

1. filled_I = floodfill(I). // fill every hole in the image.
2. inverted_I = invert(I)`.   
3. holes_I = filled_I AND inverted_I. // finds all holes 
4. cc_list = connectedcomponent(holes_I) // list of all connected component in holes_I.
5. holes_I = remove(cc_list,holes_I, smallholes_threshold_size) // remove all holes from holes_I having size > smallholes_threshold_size.
6. out_I = I OR holes_I. // fill only the small holes.

要するに、アルゴリズムは、すべての穴を見つけて、大きな穴を取り除き、小さな穴だけを元の画像に書き込むだけです。

于 2012-06-04T20:10:42.593 に答える