Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

What is the best way to filter an image so that only the pixels close to a certain color are left?

I've downloaded some satellite images from the web where a specific pixel color corresponds to a some type of crop. Thus I would like to filter out with Mathematica those pixels that are specifically for that color so I can next run ComponentMeasurements to obtain the area covered by those pixels, so I was trying to figure out what function to use or build that would just return an image with the pixels that match or are truly similar to the color provided.

share|improve this question
    
Is your question a general image-processing question or specific to Mathematica? –  rm -rf May 9 '12 at 17:53
    
See this post, it might give you some ideas where to start. –  István Zachar May 9 '12 at 18:05
    
What definition of "color" do you want to use? –  belisarius May 9 '12 at 20:41
    
Here's another implementation (an earlier answer of mine). –  Szabolcs May 11 '12 at 7:23
add comment

3 Answers

up vote 17 down vote accepted
i = Import["http://i.stack.imgur.com/zzUdB.gif"];

{h, s, b} = ColorSeparate[i, "HSB"];

Manipulate[
 Column[
  {
   Graphics[{Hue[c], Rectangle[]}, ImageSize -> 40],
   ImageMultiply[i, 
    Binarize[Abs[Mod[ImageData[h] - c, 1, -1/2]] // Image, 
      tolerance] // ColorNegate]
   }
  ],
 {c, 0, 1},
 {{tolerance, 0.1}, 0, 0.5}
 ]

Mathematica graphics Mathematica graphics Mathematica graphics Mathematica graphics

GIF image source

share|improve this answer
4  
Very nice. Version 7 users will need: {h, s, b} = ColorSeparate@ColorConvert[i, "HSB"]; –  Mr.Wizard May 9 '12 at 21:47
    
@Mr.Wizard Good catch! The second argument (the color space) of ColorSeparate is a version 8 addition. –  Sjoerd C. de Vries May 9 '12 at 21:51
1  
@mr.wizard Didn't cross my mind, but makes sense. Done. –  Sjoerd C. de Vries May 9 '12 at 22:07
2  
Note that since Hue is periodic with period 1 you might want to apply a function to the image data of h that reflects this periodicity. For example you could do something like Abs[Mod[ImageData[h] - c, 1, -1/2]]. This way, when filtering on Hue[0] (which is equal to Hue[1]) you'll not only catch the points with hue 0 <= hue < tol but also 1-tol < hue <= 1. –  Heike May 9 '12 at 22:19
1  
+1 Great, but your current code has only 1 slider while images of interfaces have 2. –  Vitaliy Kaurov May 9 '12 at 22:38
show 5 more comments

An answer to this question also appears in this other answer, albeit somewhat hidden. So I've taken the relevant part of my answer there and put it into this function which extracts the desired color by setting all other colors transparent:

colorExpose[im_, col_, tol_: .005] := Module[
  {
   color = Apply[List, ColorConvert[col, "RGB"]],
   r = If[
     ImageColorSpace[im] != "RGB",
     ColorConvert[im, "RGB"], im
     ]
   },
  SetAlphaChannel[r,
   Binarize[r, (Norm[# - color] < tol) &]
   ]
  ]

Here are some examples of how the function can be used:

ra = Import["http://i.stack.imgur.com/zzUdB.gif"]
colorExpose[ColorConvert[ra, "CMYK"], Yellow]
colorExpose[ra, Hue[.5]]

These forms show that the colorspace doesn't matter for the supplied image or the color, because the function always converts to RGBColor before doing the comparisons. The tolerance for the color matching is supplied as a third (optional) argument.

share|improve this answer
add comment

I investigated an alternative approach - a simple brute force technique, not as good as Sjoerd's.

satImage = ImageResize[
 Import["http://upload.wikimedia.org/wikipedia/commons
 /a/ac/Bananal-Island-North-End-Landsat-25-07-1992.gif"], 300]

satellite image from wikipedia

find[pixel_, color_, tolerance_] := If[
   And[
    Abs[color[[1]] - pixel[[1]]] < tolerance ,
    Abs[color[[2]] - pixel[[2]]] < tolerance ,
    Abs[color[[3]] - pixel[[3]]] < tolerance ], pixel, {0, 0, 0}];

Manipulate[
 im = ImageApply[find[#, col, tolerance] &, satImage],
 {col, Blue},
 {{tolerance, 0.2}, 0.1, 1, Appearance -> "Labeled"}]

manipulate

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.