14,420,468 members
Rate this:
See more:
I am scanning an image but I want to automatic crop only the scanned area and delete the unused black area from the scanned image.
In other words I want to remove the unwanted color (black) or unwanted edges from the scanned images.

Any body have any idea ???
regards..
Posted
Updated 18-Feb-12 19:13pm
v2

Rate this:

## Solution 2

Since you did not provide any information about the image class you use, I will just invent a very generic one. It basically just stores the red, green and blue components as integer values, has a routine to set these values and one to do a simple check whether the pixel is black (done as mentioned in my reply to your comment on solution 1) as well as a ToString() routine to return the color components as a formated string.

```class Color
{
// Color components
public int R, G, B;

// Set color components
public void SetColor(int R, int G, int B)
{
this.R = R;
this.G = G;
this.B = B;
}

// Basic check, if the pixel is black
public bool isBlack()
{
if (R == 0 && G == 0 && B == 0)
{
return true;
}

return false;
}

// Routine for output purposes
public override string ToString()
{
return "(" + R.ToString() + "," + G.ToString() + "," + B.ToString() + ")";
}
}```

Now, we need a two-dimentional array that serves as image, I will just use a 4x4 matrix for this example.

```int width = 4, height = 4;

Color[,] image = new Color[height, width];```

The image has to be initialized. You said your image has a black edge, so let us make an image with a black border and some colored data in the center, something like this:

```// Example image:
//
// B B B B
// B C C B
// B C C B
// B B B B
//
// B - black
// C - color```

Now comes the initialization of the image which is pretty boring to read, I will just show a shortened version here. When you use a helper class to load your image you do have this data anyway. But for the sake of this example, here is the initialization:

```// 1. Line
image[0, 0] = new Color();
image[0, 0].SetColor(0, 0, 0);

// [..]

// 2. Line
image[1, 0] = new Color();
image[1, 0].SetColor(0, 0, 0);
image[1, 1] = new Color();
image[1, 1].SetColor(255, 0, 0);
image[1, 2] = new Color();
image[1, 2].SetColor(0, 0, 255);

// [..]

// 3. Line
image[2, 0] = new Color();
image[2, 0].SetColor(0, 0, 0);
image[2, 1] = new Color();
image[2, 1].SetColor(0, 255, 0);
image[2, 2] = new Color();
image[2, 2].SetColor(255, 255, 0);

// [..]

image[3, 3] = new Color();
image[3, 3].SetColor(0, 0, 0);```

I will provide you with a link to the full source code of the example at the end, so if any questions arise, just have a look at the source code.

To later be able to compare the input with the result, let's see the image data.

```// "Show" the image
Console.WriteLine("Old Image:\n");

for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Console.Write(image[y, x].ToString() + " ");
}

Console.WriteLine();
}```

The next part is more interesting for you, I guess. As I said in my first solution, my suggestion is to find the min and max X and Y values of the colored area in your image and copy this area into a new image. First, let's find these min and max values.

```int minX = 0,
maxX = 0,
minY = 0,
maxY = 0;

bool gotMin = false;

for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (!image[y, x].isBlack())
{
if (!gotMin)
{
minX = x;
minY = y;

gotMin = true;
}

if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
}
}
}```

If you need any help understanding what's going on there, please have a look at the image I provide at the end. It demonstrates very detailed how I build this algorithm and you can use the method to tweak the algorithm as you might need it.

Now, the area we want to copy is know to us, let's copy the data to a new image. As you can see, these are exactly the same formulas I provided in the first solution.

```int newWidth = maxX - minX + 1;
int newHeight = maxY - minY + 1;

Color[,] newImage = new Color[newHeight, newWidth];

for (int y = minY; y <= maxY; y++)
{
for (int x = minX; x <= maxX; x++)
{
newImage[y - minY, x - minX] = new Color();
newImage[y - minY, x - minX].SetColor(image[y, x].R, image[y, x].G, image[y, x].B);
}
}```

And finally, let's see the result and compare it with the input.

```// "Show" new image
Console.WriteLine("New Image:\n");

for (int y = 0; y < newHeight; y++)
{
for (int x = 0; x < newWidth; x++)
{
Console.Write(newImage[y, x].ToString() + " ");
}

Console.WriteLine();
}```

Of course, you would use other methods to display your image, the console stuff here is just to give you an example.

Well, basically that is what I was talking about in my first solution.

I hope this helps.

Cheerio!

Source code
Iteration analysis
v3
Dave Kreskowiak 19-Feb-12 21:53pm

Nice. The only problem with this is black in a scanned image is rarely ever (0,0,0) black. There has to be some threshold that is considered black.
Johannes Hillert 19-Feb-12 23:07pm

Change "if (R == 0 && G == 0 && B == 0)" in the isBlack routine to something like "if (R < 50 && G < 50 && B < 50)" (20% of 255 ~ 50) and you got a threshold.
Rate this:

## Solution 1

How about going over the whole image and find the minX, maxX and minY, maxY coordinates of the area with colored pixels. Then create a new image with width=maxX-minX and height=maxY-minY and copy the respective area from the first image into the new one.

Just a suggestion, but I hope it helps.

Cheers!
v2
Tamer Hatoum 19-Feb-12 4:20am

but how to find the first colored pixels ??
Johannes Hillert 19-Feb-12 16:45pm

Well, a colored pixel is not black, right? For black pixels the red, green and blue values are zero. Negate that statement and you know the pixel is a colored one.

Okay, I will give you a more detailed idea of how I think you could do this, please refer to my 2nd solution.