9
$\begingroup$

I haven't been able to figure out why the following doesn't work:

img = Image[ExampleData[{"TestImage", "Tree"}], "Real"]
img /. {r_, g_, b_} :> 1 - {r, g, b} (* Image left unchanged *)

Looking at the full form of img, I see that the pixels are stored as lists of three real numbers each, so I don't get why the pattern won't match.

This works though, giving me the "negative" image that I expected from the previous code also:

Image[ImageData[img] /. {r_, g_, b_} :> 1 - {r, g, b}]

So what's the problem with the first code?

(Kindly note that the image processing problem that the above code happens to perform is of no interest to me here; I just chose it as an example, so don't misdirect your effort showing how it could be done using library functions. Here, I'm only interested in understanding why the rule application didn't work)

$\endgroup$
4
  • $\begingroup$ Maybe compare img // Dimensions to ImageData[img] // Dimensions ? $\endgroup$ Commented Apr 4, 2013 at 10:07
  • $\begingroup$ Yes, I hadn't realised that Image was an atomic type $\endgroup$
    – Aky
    Commented Apr 4, 2013 at 10:42
  • $\begingroup$ Does wrapping an image ExampleData returns here -- in another Image change anything? $\endgroup$
    – BoLe
    Commented Apr 4, 2013 at 13:13
  • $\begingroup$ @BoLe I just did it to convert the image type to "Real". $\endgroup$
    – Aky
    Commented Apr 4, 2013 at 15:59

3 Answers 3

7
$\begingroup$

ReplaceAll doesn't work on atoms.

img = Image[ExampleData[{"TestImage", "Tree"}], "Real"]
AtomQ@img

True

$\endgroup$
4
  • $\begingroup$ Thanks, that sort of makes sense to me. $\endgroup$
    – Aky
    Commented Apr 4, 2013 at 10:34
  • $\begingroup$ But you could try List@@img, and there are still some problems $\endgroup$ Commented Apr 4, 2013 at 11:44
  • $\begingroup$ @belarius I didn't understand your point. Trying to replace the Head of an atom doesn't ordinarily do anything, does it? List@@5==5 is True, for example, and so is List@@img==img. I've probably misunderstood the point you're trying to make, so could you please explain? $\endgroup$
    – Aky
    Commented Apr 4, 2013 at 11:55
  • $\begingroup$ @Aky Try (List @@ Image[ExampleData[{"TestImage", "Tree"}]] /. {x_, y_, z_, w_} -> x // InputForm) /. RawArray :> List $\endgroup$ Commented Apr 4, 2013 at 12:44
9
$\begingroup$

Since version 9, Image is an atomic object (AtomQ) and thus it's internal data structures cannot be directly manipulated through Part or pattern matching.

Don't let the fact that it has an InputForm and FullForm with apparent structure confuse you. This is for convenience only (to make it human readable) and happens with other atomic objects too, such as Rational/Graph/etc. In reality you just can't take an Image apart.

Use ImageData and other Image* functions to extract data.

$\endgroup$
5
$\begingroup$

Image[ ] is a kind of wrapper that contains information about the image: the size, the color map, and of course the ImageData. There are lots of functions that deal directly with the image wrapper, for instance, you can accomplish the task you asked using

ImageApply[(1 - #) &, img]

More generally, you can define your own function f and then do: ImageApply[f, img]

$\endgroup$

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.