0

バイナリ イメージで輪郭を見つけ、小さなものを除外する関数を実装しようとしています。

これが私のコードとサンプル画像です。これは、小さな領域のブロブを削除する非常にシンプルな機能です。しかし、領域の輪郭ではなく、「エッジの輪郭」を取得し続けています。:S

    private IplImage RemoveNoise( IplImage image, int minArea )
    {

        List<CvPoint[]> listOfPoints = new List<CvPoint[]>();

        CvSeq<CvPoint> contoursRaw;

        List<ContourData> contours = new List<ContourData>();
        using( CvMemStorage storage = new CvMemStorage() )
        {
            //find contoures
            //Cv.FindContours( image, storage, out contoursRaw );
            Cv.FindContours( image, storage, out contoursRaw, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple );
            //contoursRaw = Cv.ApproxPoly( contoursRaw, CvContour.SizeOf, storage, ApproxPolyMethod.DP, 3, true );

            while( contoursRaw != null )
            {
                CvSeq<CvPoint> result = contoursRaw;
                double area = Cv.ContourArea( result );

                //filter out small regions
                if( area >= minArea )
                {                   
                    List<CvPoint> points = new List<CvPoint>();
                    int i = 0;
                    while( result[ i ] != null )
                    {
                        points.Add( new CvPoint( result[ i ].Value.X, result[ i ].Value.Y ) );
                        i++;
                    }
                    listOfPoints.Add( points.ToArray() );

                }
                contoursRaw = contoursRaw.HNext;
            }
        }

        // draw large regions
        IplImage output = new IplImage( image.Size, image.Depth, 1 );
        output.Set( CvColor.Black );
        CvPoint[][] ArrayOfPoints = listOfPoints.ToArray();
        output.FillPoly( ArrayOfPoints, CvColor.White );

        return output;
    }

領域の輪郭ではなく、「エッジの輪郭」を取得し続けるのはなぜですか?

結果は次のとおりです。 ここに画像の説明を入力してください ここに画像の説明を入力

4

1 に答える 1

1

これを試して。

IplImage input = new IplImage(@"C:\Users\20396600\Downloads\cont.jpg");
IplImage gray = new IplImage(input.Size, BitDepth.U8, 1);
IplImage invert = gray.Clone();
input.CvtColor(gray, ColorConversion.BgrToGray);
gray.Threshold(invert, 70, 255, ThresholdType.BinaryInv);
RemoveNoise(invert, 150);

private IplImage RemoveNoise(IplImage image, int minArea)
{
    IplImage output = new IplImage(image.Size, BitDepth.U8, 3);//image.Depth, 1);
    output.Set(CvColor.Black);
    CvSeq<CvPoint> contoursRaw;

    using (CvMemStorage storage = new CvMemStorage())
    {
        //find contours
        Cv.FindContours(image, storage, out contoursRaw, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple);

        //Taken straight from one of the OpenCvSharp samples
        using (CvContourScanner scanner = new CvContourScanner(image, storage, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple))
        {
            foreach (CvSeq<CvPoint> c in scanner)
            {
                //Some contours are negative so make them all positive for easy comparison
                double area = Math.Abs(c.ContourArea());
                //Uncomment below to see the area of each contour
                //Console.WriteLine(area.ToString());
                if (area >= minArea)
                {
                    List<CvPoint[]> points = new List<CvPoint[]>();
                    List<CvPoint> point = new List<CvPoint>();
                    foreach (CvPoint p in c.ToArray())
                        point.Add(p);

                    points.Add(point.ToArray());

                    //Use FillPoly instead of DrawContours as requested
                    output.FillPoly(points.ToArray(), CvColor.Red, LineType.AntiAlias);

                    //-1 means fill the polygon
                    //output.DrawContours(c, CvColor.White, CvColor.Green, 0, -1, LineType.AntiAlias);

                    //Uncomment two lines below to see contours being drawn gradually
                    //Cv.ShowImage("Window", output);
                    //Cv.WaitKey();
                }
            }
        } 
    }
    output.SaveImage("output.png");

    return output;
}

説明の依頼を受け、秘伝のタレがこちら。

  1. 画像を反転すると、輪郭を適切に見つけるのに役立ちます。FindContour は、黒い背景にある白いオブジェクトを見つけたいと考えています。
  2. ContourArea() は負の値を返していたので、 Math.Abs​​() は必要なものに絞り込むのに役立ちます。
  3. -1 が厚さとして渡された場合、DrawContour() 関数は輪郭を塗りつぶします。

他のすべては、OpenCvSharp ダウンロードで提供されるサンプルと非常によく似ています。お役に立てれば。

編集:別のチャネルを介して、作成者は DrawContours の代わりに FillPoly を使用できるようにするよう求めたため、それを反映するようにサンプル コードが更新されました。

于 2016-02-15T20:52:42.703 に答える