4

I am trying to make a scanning application. That application will scan the document and will display image in a picture box. The problem I am facing is image (Documents image which kept in the scanner or say ‘real ’image) is displaying inside another image with some background (That background color is also changing) its look like this image.
enter image description here
I have tried lot of things but nothing giving me a perfect result I tried it with a forge.net. Here is the code I have tried.

public static System.Drawing.Image AforgeAutoCrop(Bitmap selectedImage) { Bitmap autoCropImage = null; try { autoCropImage = selectedImage; // create grayscale filter (BT709) Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721); Bitmap grayImage = filter.Apply(autoCropImage); // create instance of skew checker DocumentSkewChecker skewChecker = new DocumentSkewChecker(); // get documents skew angle double angle = skewChecker.GetSkewAngle(grayImage); // create rotation filter RotateBilinear rotationFilter = new RotateBilinear(-angle); rotationFilter.FillColor = Color.White; // rotate image applying the filter Bitmap rotatedImage = rotationFilter.Apply(grayImage); new ContrastStretch().ApplyInPlace(grayImage); new Threshold(100).ApplyInPlace(grayImage); BlobCounter bc = new BlobCounter(); bc.FilterBlobs = true; // bc.MinWidth = 500; //bc.MinHeight = 500; bc.ProcessImage(grayImage); Rectangle[] rects = bc.GetObjectsRectangles(); MemoryStream writeName = new MemoryStream(); if (rects.Length == 0) { System.Windows.Forms.MessageBox.Show("No rectangle found in image "); } else if (rects.Length == 1) { Bitmap cropped = new Crop(rects[0]).Apply(autoCropImage); autoCropImage = cropped; // pictureBox1.Image = cropped; } else if (rects.Length > 1) { // get largets rect Console.WriteLine("Using largest rectangle found in image "); var r2 = rects.OrderByDescending(r => r.Height * r.Width).ToList(); //var r2 = rects.OrderByDescending(r => r.Height < 1500 && r.Width < 1000).ToList(); Bitmap cropped = new Crop(r2[0]).Apply(autoCropImage); Graphics gr = Graphics.FromImage(cropped); gr.DrawRectangles(new Pen(Color.Red), rects); autoCropImage = cropped; // pictureBox1.Image = cropped; } else { Console.WriteLine("Huh? on image "); } } catch(Exception ex) { MessageBox.Show(ex.Message); } return autoCropImage; } 
2
  • "No perfect result" is very far from beeing a real question - voting to close. By the way, I would not try something like that using GDI+, better utilize a tool like ImageMagick (imagemagick.org/script/index.php) for it, or the corresponding .NET API (imagemagick.codeplex.com) Commented Aug 2, 2012 at 14:29
  • @DocBrown its very useful thank you. I have tried AForge instead of ImageMagick. Thanks again. Commented Aug 2, 2012 at 15:06

4 Answers 4

4

i changed your code to this and works well. thanks

 public static System.Drawing.Image AforgeAutoCrop(Bitmap selectedImage) { Bitmap autoCropImage = null; try { autoCropImage = selectedImage; // create grayscale filter (BT709) Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721); Bitmap grayImage = filter.Apply(autoCropImage); // create instance of skew checker DocumentSkewChecker skewChecker = new DocumentSkewChecker(); // get documents skew angle double angle = skewChecker.GetSkewAngle(grayImage); // create rotation filter RotateBilinear rotationFilter = new RotateBilinear(-angle); rotationFilter.FillColor = Color.White; // rotate image applying the filter Bitmap rotatedImage = rotationFilter.Apply(grayImage); new ContrastStretch().ApplyInPlace(rotatedImage); new Threshold(100).ApplyInPlace(rotatedImage); BlobCounter bc = new BlobCounter(); bc.FilterBlobs = true; // bc.MinWidth = 500; //bc.MinHeight = 500; bc.ProcessImage(rotatedImage); Rectangle[] rects = bc.GetObjectsRectangles(); if (rects.Length == 0) { System.Windows.Forms.MessageBox.Show("No rectangle found in image "); } else if (rects.Length == 1) { autoCropImage = rotatedImage.Clone(rects[0], rotatedImage.PixelFormat); ; } else if (rects.Length > 1) { // get largets rect Console.WriteLine("Using largest rectangle found in image "); var r2 = rects.OrderByDescending(r => r.Height * r.Width).ToList(); autoCropImage = rotatedImage.Clone(r2[1], rotatedImage.PixelFormat); } else { Console.WriteLine("Huh? on image "); } } catch (Exception ex) { MessageBox.Show(ex.Message); } return autoCropImage; } 
Sign up to request clarification or add additional context in comments.

Comments

3

I assume you always have an image with a distinct foreground and background, and you want to do something like a zealous crop of the background.

In this case I would do something similar to region growning. Start at a point where you can be guaranteed a background pixel.

Get another image (or matrix or whatever), initialized to zeros, and set the corresponding pixel value to 1. If any neighboring pixels are within a threshold value in the original image, move to them recursively and set their corresponding pixel values to 0 as well.

That is:

map = 0's, size of image function f(x,y,image,map) if map(x,y) is not 0 return if pixel value at image(x,y)<T map(x,y) = 1; for all neighbors of x,y function([neighbor coordinates],image,map) else map(x,y) = 2; end 

Now map should have all background pixels as 1 and forground as 2. You can change this to allow multiple objects and thresholds and so forth. You might want threshold to be a value change rather than an absolute value.

Then simply find the min and max x and y and store the pixels in that range to a new image.

I hope this was along the lines of what you need.

3 Comments

you are correct. This is something what i required. do you have any idea to do this in c#.
Look here for pixel manipulation. Look here for cropping. The rest should be fairly simple to translate to C/C++/C# if you are familiar enough with them.
Ok i will try your solution and will updated here. Hoping it will solve my probs ..Thanks Bill..:-)
1

You can use AForge.NET Image Processing
Edge detector: http://www.aforgenet.com/framework/features/edge_detectors_filters.html

1 Comment

So u can use EdgeDetector to find borders of your book: aforgenet.com/framework/features/edge_detectors_filters.html
0

Mostafa HK's code worked for me. I'm using this function to pre-process YouTube thumbnails (to strip the black edges; a common problem), and I did have to make a couple of minor corrections to his code:

1) got rid of the rotation (not sure what that was for)

2) I lowered the threshold from 100 to 25.

3) When cloning the final image, I perform the clone off the original autoCropImage and not the rotatedImage (again, not sure what the rotation was for).

I think the real secret sauce was lowering the threshold. This reduced the number of rectangles the code was finding, and now I am properly cropping all forms of thumbnails (widescreen with black on the top and bottom AND fullscreen with black on the left and right).

 public static System.Drawing.Image AforgeAutoCrop(Bitmap selectedImage) { Bitmap autoCropImage = null; try { autoCropImage = selectedImage; // create grayscale filter (BT709) Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721); Bitmap grayImage = filter.Apply(autoCropImage); // create instance of skew checker DocumentSkewChecker skewChecker = new DocumentSkewChecker(); // get documents skew angle double angle = 0; // skewChecker.GetSkewAngle(grayImage); // create rotation filter RotateBilinear rotationFilter = new RotateBilinear(-angle); rotationFilter.FillColor = Color.White; // rotate image applying the filter Bitmap rotatedImage = rotationFilter.Apply(grayImage); new ContrastStretch().ApplyInPlace(rotatedImage); new Threshold(25).ApplyInPlace(rotatedImage); BlobCounter bc = new BlobCounter(); bc.FilterBlobs = true; // bc.MinWidth = 500; //bc.MinHeight = 500; bc.ProcessImage(rotatedImage); Rectangle[] rects = bc.GetObjectsRectangles(); if (rects.Length == 0) { // CAN'T CROP } else if (rects.Length == 1) { autoCropImage = autoCropImage.Clone(rects[0], autoCropImage.PixelFormat); ; } else if (rects.Length > 1) { // get largets rect Console.WriteLine("Using largest rectangle found in image "); var r2 = rects.OrderByDescending(r => r.Height * r.Width).ToList(); autoCropImage = autoCropImage.Clone(r2[0], autoCropImage.PixelFormat); } else { Console.WriteLine("Huh? on image "); } } catch (Exception ex) { //MessageBox.Show(ex.Message); //CAN'T CROP } return autoCropImage; } 

https://stackoverflow.com/search?q=youtube+thumbnail+crop

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.