2

First off I am new to this and also coding. I apologize in advance for anything that is misleading.

I am currently writing a Java program that uses an image as input. What I have currently is scanning each pixel by the width and height of the image saving the HSB in an array and then outputting the percentage of each color in the image. I now want to omit the background from that calculation. To start off lets just say the background is white. There are also pixels in the image that are not in the background that is white though.

thank you,

Hunter Zolomon
  • 97
  • 1
  • 2
  • 9
  • 1
    Consider [ImageMagick](http://www.imagemagick.org/script/index.php). It is a free open source software for image processing. There is [java bridge implementation](http://im4java.sourceforge.net/) to call ImageMagick commands from your java code. [Here is im4java developer guide](http://im4java.sourceforge.net/docs/dev-guide.html#imageCommands) –  Apr 21 '16 at 18:52
  • Please consider providing a code sample so community can help you – Entea Apr 21 '16 at 18:53
  • Also check the following links: http://www.imagemagick.org/discourse-server/viewtopic.php?t=23738 and http://www.imagemagick.org/Usage/draw/#matte –  Apr 21 '16 at 18:54

4 Answers4

1

Oh, it's not as simple as you hope.
You cannot simply detect what's a background and what is part of image pixel by pixel.

You might try looking at this post to see how to remove one color layer of the image. But detecting if the white pixel is a part of background or already the image?!

There are multiple possible ways:

  • assuming that background is just around and when (looking from any side to the center) color changes, that is the end of the "background". You can check every row and column from side to center and keep record of where the "background" color ends.
  • or similar approach - if at least at one (of four) direction looking from the pixel to the side there is no color changes (it goes white all the way to the side), than it is part of background.
  • Or just take a look at another post. From this you can try working your way up.

Anyway - you have to create a logic of detecting which (i.e.) white pixels are part of the picture and which are part of background.

I hope this at least gives you a bit more knowledge.

Adil Soomro
  • 37,609
  • 9
  • 103
  • 153
Mike B
  • 2,756
  • 2
  • 16
  • 28
  • I was thinking about doing the first bullet point you had stated. I was having an issue when let's say the image was a rabbit. The white space between the ears would be the background, but if it had a white spot on it's fur this would not be the background. – Hunter Zolomon Apr 21 '16 at 19:34
  • I really like the idea of your second bullet point though. I will do more research on that topic! Thanks a lot very helpful! – Hunter Zolomon Apr 21 '16 at 19:41
  • @HunterZolomon always allowed to mark my answer as the best one. :D Good luck with your _fights_ – Mike B Apr 21 '16 at 19:50
  • And about problem - if ears make a closed area of background than it's WAY more complicated. I don't even have an idea for an algorithm. If the area between ears is not closed, then my second idea works. It can be optimized, but the approach is good imo. – Mike B Apr 21 '16 at 19:51
  • Well i had to add a few for statements. I ended up using your bullet point two and it seemed to have work. Unfortunately the run-time increased by a significant amount, but that for another post. Thank you for the idea though! – Hunter Zolomon Apr 21 '16 at 20:51
  • Yeah. I thought the performance might be an issue. But at least it works. The first good step. – Mike B Apr 21 '16 at 20:54
0

I am not sure what you mean. There is no code, so I can only give you an example. From what I have understood, you want to skip doing a calculation when the color is the same as the background. That is very simple. You can do something like this:

for(int x = 0; x < width; x++) {
    for(int y = 0; y < height; y++) {
        Color pixelColor = get pixel color at x and y;
        Color backgroundColor = the background color;
        if(pixelColor != backgroundColor) {
            //Calculation will be done here
        }
    }
}

If this does not help you or you have any other questions, ask me.

JasonPh
  • 147
  • 1
  • 9
  • I am still unsure of how to format my code when pasting into the textbox. I only want to skip calculation for the background. Not if the color is the same color as the background. That is what I am having trouble with. I know how to omit the background color from calculation, but it is also including color which is not the background (but same color as the background). – Hunter Zolomon Apr 21 '16 at 19:08
0

Here is an example of full working code.

You can add a cursor to pick color and jslider for fuzz or threshold. Use backColor and threshold for your needs.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Convert {
    private static final Color backColor = new Color(255,255,255);
    private static final int THRESHOLD = 35;
    private static final int TRANSPARENT = 0;  // 0x00000000;

    static File base  = new File("f://mortar1.png");
    static File base2 = new File("f://outtrans.png");

    public static void main(String[] args) throws IOException {
        System.out.println("Convert.main()");
        for (File file : base.listFiles()) 
        {
            BufferedImage initImage = ImageIO.read(base);
            int width = initImage.getWidth(null),
              height = initImage.getHeight(null);

            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics g = image.getGraphics();
            g.drawImage(initImage, 0, 0, null);

            System.out.println("before: " + image.getRGB(0, 0));
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int pixel = image.getRGB(x, y);
                    Color color = new Color(pixel);

                    int dr = Math.abs(color.getRed()   - backColor.getRed()),
                    dg = Math.abs(color.getGreen() - backColor.getGreen()),
                    db = Math.abs(color.getBlue()  - backColor.getBlue());

                    if (dr < THRESHOLD && dg < THRESHOLD && db < THRESHOLD) {
                        image.setRGB(x, y, TRANSPARENT);
                    }
                }
            }
            System.out.println("   after: " + image.getRGB(0, 0));

           File file = new File("f://outtrans1.png");
            ImageIO.write(image, "png", file);
        }
    }
}
Alejandro
  • 7,290
  • 4
  • 34
  • 59
azhar
  • 1
  • 1
  • 3
0

Or simple set a png file with empty fill..

This idea seems good for me. But if you don't agree, please, tell me causes)

Maria
  • 199
  • 3
  • 15