Subscribe Bookmark RSS Feed

Image analysis

olivier_brack

Community Member

Joined:

Oct 22, 2014

How could I identify pixels groups with quite similar colors (grey for instance) on a picture .jpeg?

1 REPLY
JohnPonte

Staff

Joined:

Jun 17, 2013

I suppose there are a few different approaches you could take to this. One question I have is, are you looking for a specific color (grey, for example) or are you looking to see if for any given pixel, does the pixel color (closely) match the surrounding pixels? I think you are asking about the first scenario, searching for one "target" color. The other question is are you always looking for gray, or would the target color change. The reason I ask is because color is made up of 3 components, red, green and blue. But you can convert rgb to a gray-scale image and then you would only have one component, which would make the code simpler. I will assume you are working with color images, looking for a non-grey color. If that isn't the case, you could simplify the code. 

Here is one approach I think would work nicely for you. We are going to read in our source image, create a target image which is the target color you are looking for, then we will subtract one from the other. Then we can look through the result looking for any pixels that are within our tolerance for "same".

First you would want to read in the image and get the pixel values as three (red, green and blue) matrices.

imgSource = NewImage("$Sample_Images\black rhino footprint.jpg");

{ rSource, gSource, bSource } = imgSource << getPixels("rgb");

win = newWindow("Source image", imgSource);

Next, define your target color you are trying to match to. I will create a gray color for this example, but you could specify any values (between 0.0 - 1.0).

rValue = 0.5;

gValue = 0.5;

bValue = 0.5;

Now lets create new matrices that will represent our target color image. These matrices should be the same size as the source image, with the target color as the value.

{ wd, ht } = imgSource << getSize();

rTarget = J(ht, wd, rValue);

gTarget = J(ht, wd, gValue);

bTarget = J(ht, wd, bValue);

Now lets subtract one from the other (for each color component).

rDiff = abs(rSource - rTarget);

gDiff = abs(gSource - gTarget);

bDiff = abs(bSource - bTarget);

Now we would define what our tolerance is. This is how close we consider to be "the same". Lets say within 2% is close enough to the same.

tolerance = 0.02;

Now we can loop through the diff matrices looking for which values are less than the tolerance. There are two ways to do this. One would be to look at r, g, and b and see if all three of the values are less than the tolerance. The other way would be to combine the three diff matrices into one intensity (gray-scale) matrix and then just look at the one intensity value per pixel. Personally I like that approach better. So I'm going to convert to a gray-scale matrix first.

inten = 0.30*rDiff + 0.59*gDiff + 0.11*bDiff;

Now I'll loop through my intensity matrix comparing each value to the tolerance.

for (y = 1, y <= ht, y++,

  for (x = 1, x < wd, x++,

     if (inten[y,x] < tolerance,

        // Found a pixel that is "the same", lets make it "red" in the original so it shows up

        rSource[y,x] = 1.0;

        gSource[y,x] = 0.0;

        bSource[y,x] = 0.0;

     );

  );

);

Now lets set the new values back to the original image so we can see the pixels we found

imgSource << setpixels("rgb", {rSource, gSource, bSource});

And that's all there is to it!  :-)

Again, if you are working with gray-scale images, searching for gray values, it gets easier because we would just be working with one matrix instead of 3 matrices, for both the source and the target.

You may want to look at some of the image samples I've put on the file exchange. The files, ImageExamples.jsl and ImageDiff.jsl may be most useful. Also, I have some blog posts that talk about doing a color analysis of images, such as Image Analysis of an Elephant's Foot.

I hope this helps!

John