My project need to crop the image automatically to remove the white space around the drawing (Lattice).
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;
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
}
}
}