Click here to Skip to main content
14,420,468 members
Rate this:
Please Sign up or sign in to vote.
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:
Please Sign up or sign in to vote.

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!


Links

Source code
Iteration analysis
   
v3
Comments
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:
Please Sign up or sign in to vote.

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
Comments
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.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100