J Code
J Code

Reputation: 464

Java: Checking if image moved

I want to look within a certain position in an image to see if the selected pixels have changed in color, how would I go about doing this? (Im trying to check for movement)

I was thinking I could do something like this:

public int[] rectanglePixels(BufferdImage img, Rectangle Range) {
  int[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
  int[] boxColors;  
    for(int y = 0; y < img.getHeight(); y++) {
      for(int x = 0; x < img.getWidth; x++) {
        boxColors = pixels[(x & Range.width) * Range.x + (y & Range.height) * Range.y * width]
      }
    }
  return boxColors; 
}

Maybe use that to extract the colors from the position? Not sure if im doing that right, but after that should I re-run this method, compare the two arrays for similarities? and if the number of similarities reach some threshold declare that the image has changed?

Upvotes: 1

Views: 254

Answers (3)

Gabriel Archanjo
Gabriel Archanjo

Reputation: 4597

One approach to detect movement is the analysis of pixel color variation considering the entire image or a subimage in distinct times (n, n-1, n-2, ...). In this case you are considering a fixed camera. You might have two thresholds:

  1. The threshold of color channel variation that defines that two pixels are distinct.
  2. The threshold of distinct pixels between the images to consider there is movement. In other words: two images of the same scene at time n and n-1 have just 10 distinct pixels. It is a real movement or just noise?

Below an example showing how to counter the distict pixels in an image, given a color channel threshold.

for(int y=0; y<imageA.getHeight(); y++){
        for(int x=0; x<imageA.getWidth(); x++){

            redA = imageA.getIntComponent0(x, y);
            greenA = imageA.getIntComponent1(x, y);
            blueA = imageA.getIntComponent2(x, y);

            redB = imageB.getIntComponent0(x, y);
            greenB = imageB.getIntComponent1(x, y);
            blueB = imageB.getIntComponent2(x, y);

            if
            (
                Math.abs(redA-redB)> colorThreshold ||
                Math.abs(greenA-greenB)> colorThreshold||
                Math.abs(blueA-blueB)> colorThreshold
            )
            {
                distinctPixels++;
            }
        }
    }       

However, there are Marvin plug-ins to do so. Check this source code example. It detects and display regions containing "movements", as shown in the image below.

enter image description here

There are more sophisticated approaches that determine/subtract background for this purpose or deal with camera movements. I guess you should start from the simplest scenario and then go to more complex ones.

Upvotes: 1

Skylion
Skylion

Reputation: 2752

Comparing two values through a threshold would serve as good indicator. Perhaps, you could calculate averages for each array to determine color and compare the two? If you do not want a threshold value just use .hashCode();

Upvotes: 0

Kayaman
Kayaman

Reputation: 73548

You should use BufferedImage.getRGB(startX, startY, w, h, rgbArray, offset, scansize) unless you really want to play around with the loops and extra arrays.

Upvotes: 0

Related Questions