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.

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)

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

3 Answers 3

up vote 7 down vote accepted

ReplaceAll doesn't work on atoms.

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

True

share|improve this answer
    
Thanks, that sort of makes sense to me. –  Aky Apr 4 '13 at 10:34
    
But you could try List@@img, and there are still some problems –  belisarius Apr 4 '13 at 11:44
    
@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? –  Aky Apr 4 '13 at 11:55
    
@Aky Try (List @@ Image[ExampleData[{"TestImage", "Tree"}]] /. {x_, y_, z_, w_} -> x // InputForm) /. RawArray :> List –  belisarius Apr 4 '13 at 12:44

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.

share|improve this answer

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]

share|improve this answer

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.