Search code examples
c#winformsimage-processingemgucvmathematical-lattices

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


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;

Solution

  • 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