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.

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.

  • $\begingroup$ Is your question a general image-processing question or specific to Mathematica? $\endgroup$
    – rm -rf
    Commented May 9, 2012 at 17:53
  • $\begingroup$ See this post, it might give you some ideas where to start. $\endgroup$ Commented May 9, 2012 at 18:05
  • $\begingroup$ What definition of "color" do you want to use? $\endgroup$ Commented May 9, 2012 at 20:41
  • $\begingroup$ Here's another implementation (an earlier answer of mine). $\endgroup$
    – Szabolcs
    Commented May 11, 2012 at 7:23

3 Answers 3

i = Import["https://i.sstatic.net/zzUdB.gif"];

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

   Graphics[{Hue[c], Rectangle[]}, ImageSize -> 40],
    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

  • 4
    $\begingroup$ Very nice. Version 7 users will need: {h, s, b} = ColorSeparate@ColorConvert[i, "HSB"]; $\endgroup$
    – Mr.Wizard
    Commented May 9, 2012 at 21:47
  • $\begingroup$ @Mr.Wizard Good catch! The second argument (the color space) of ColorSeparate is a version 8 addition. $\endgroup$ Commented May 9, 2012 at 21:51
  • 1
    $\begingroup$ @mr.wizard Didn't cross my mind, but makes sense. Done. $\endgroup$ Commented May 9, 2012 at 22:07
  • 2
    $\begingroup$ 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. $\endgroup$
    – Heike
    Commented May 9, 2012 at 22:19
  • 1
    $\begingroup$ +1 Great, but your current code has only 1 slider while images of interfaces have 2. $\endgroup$ Commented May 9, 2012 at 22:38

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

satImage = ImageResize[
 /a/ac/Bananal-Island-North-End-Landsat-25-07-1992.gif"], 300]

satellite image from wikipedia

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

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



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
   Binarize[r, (Norm[# - color] < tol) &]

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

ra = Import["https://i.sstatic.net/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.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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