How can I crop the white space of an image using EmguCV and windows form

267 views Asked by At

My project need to crop the image automatically to remove the white space around the drawing (Lattice).

imgLattice

Here is my code

grayImage = grayImage.ThresholdBinary(new Gray(threshold), new Gray(255));

VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
CvInvoke.FindContours(grayImage, contours, null, RetrType.External, ChainApproxMethod.ChainApproxSimple);

for (int i = 0; i < contours.Size; i++)
{

Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);

    if (rect.Width > minWidth && rect.Height > minHeight)
    {
        CvInvoke.DrawContours(image, contours, i, new MCvScalar(255, 0, 0), 2);
    }

}

imageBox.Image = image;
1

There are 1 answers

1
Rotem On BEST ANSWER

The main issue is that FindContours finds white contours, and the image background is white.

We use ThresholdBinaryInv instead of ThresholdBinary.
ThresholdBinaryInv applies threshold and invert black and white after applying the threshold (the pattern is going to be white on black instead of black on white).


Code sample:

using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using System.Drawing;

namespace Testings
{
    public class Program
    {
        static void Main(string[] args)
        {
            int threshold = 254;
            var image_file_name = @"auxetic_lattice_screen.png";

            Mat image = new Mat(image_file_name, Emgu.CV.CvEnum.ImreadModes.Color);  //Read input image as BGR

            var grayImage = new Image<Gray, System.Byte>(image_file_name); //Read input image as Grayscale

            //grayImage = grayImage.ThresholdBinary(new Gray(threshold), new Gray(255));
            grayImage = grayImage.ThresholdBinaryInv(new Gray(threshold), new Gray(255)); // Use ThresholdBinaryInv - invert black and white so that the pattern be white

            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            CvInvoke.FindContours(grayImage, contours, null, RetrType.External, ChainApproxMethod.ChainApproxSimple);

            int minWidth = grayImage.Width / 2;
            int minHeight = grayImage.Height / 2;
            Mat croppedImage = null;

            for (int i = 0; i < contours.Size; i++)
            {
                Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);

                if (rect.Width > minWidth && rect.Height > minHeight)
                {
                    croppedImage = new Mat(image.Clone(), rect); //Crop the rectangle
                    CvInvoke.DrawContours(image, contours, i, new MCvScalar(255, 0, 0), 2);
                }
            }

            

            //Show images for testing
            CvInvoke.Imshow("grayImage", grayImage);
            CvInvoke.Imshow("image", image);
            CvInvoke.WaitKey();

            CvInvoke.Imwrite("output_image.png", image); //Save output for testing
            CvInvoke.Imwrite("croppedImage.png", croppedImage); //Save output for testing            
        }
    }
}

Result:
enter image description here