Can anyone explain me, why this line of simple code is so slow? And can it be improved somehow?

p = Import["http://www.ultimatte-software.com/images/2FSN-TLW-wide03-ultimatte-software-blue.jpg"];

Timing[Image[(ImageData[p] /. {r_, g_, b_} -> {b} 2 - {g} - {r})]]
  • $\begingroup$ You could try ImageApply[2 #[[3]] - #[[2]] - #[[1]] & , p] but it's slightly different... $\endgroup$ – cormullion Nov 27 '13 at 20:09
  • $\begingroup$ Thank you, but it is still too slow for a video stream. I know, that I can use ColorSeparate, and then ImageMultiply and ImageSubtract. But I just think, that using Replacement rules or your suggestion is more elegant. $\endgroup$ – Simon Nov 27 '13 at 20:27
  • $\begingroup$ If you want to use it for video streams, can you elaborate more on the way you process the frames? Are you importing frame after frame or do you import greater chunks? Maybe you import the whole video at once? Then there are faster ways which work on the complete stream. $\endgroup$ – halirutan Nov 27 '13 at 20:47

Here's a reasonably fast way:

p = Import[

img1 = Image[(ImageData[p] /. {r_, g_, b_} -> {b} 2 - {g} - {r})]; // 
  AbsoluteTiming // First
(* 0.423668 *)

img2 = Image[ImageData[p].{-1, -1, 2}]; // AbsoluteTiming // First
(* 0.003273 *)

ImageSubtract[foo, foo2] // ImageData // Max
(* 2.22045*10^-16 *)

To get values between zero and 1, use Clip:

img3 = Image[Clip@ImageData[p].{-1., -1., 2.}]; // 
  AbsoluteTiming // First
(* 0.004997 *)
|improve this answer|||||

Extracting the image data and replacing the pixel-values with rules is definitely not the fastest way to go. A very neat way is to use ImageApply

ImageApply[2 #[[3]] - #[[2]] - #[[1]] &, p]

When you compare the two methods

Timing[Do[Image[(ImageData[p] /. {r_, g_, b_} -> {b} 2 - {g} - {r})], {20}]]
Timing[Do[ImageApply[2 #[[3]] - #[[2]] - #[[1]] &, p], {20}]]

you will see that ImageApply is about 10x faster than the replacement solution.

A very fast solution is the following which is about 40x faster

fc = Compile[{{p, _Real, 1}},
   2 p[[3]] - p[[2]] - p[[1]],
   CompilationTarget -> "C", Parallelization -> True, 
   RuntimeAttributes -> {Listable}];

Timing[Do[Image[fc@ImageData[p]], {20}]]

(* {0.360279, Null} *)
|improve this answer|||||
  • $\begingroup$ This differs form OP's example with that the values are clipped to (0,1). Maybe he needs this, who knows :) $\endgroup$ – Kuba Nov 27 '13 at 20:38
  • $\begingroup$ @Kuba Sometimes it's an advantage that ImageApply scales and clips the values, sometimes it's not.. $\endgroup$ – halirutan Nov 27 '13 at 20:40
  • $\begingroup$ I know, I would use ImageApply. $\endgroup$ – Kuba Nov 27 '13 at 20:41

Image Type Matters

Though halirutan's parallel solution appears quite general, since his compiled function fc is capable to process lists of image data lists (as video processing was intended), it might remain highly dependent on the C compiler type applied. (As parallel processing was done, Timing is inappropriate to do runtime measurements - this will provide the sum of seconds of all respective parallel threads, it should always be done using AbsoluteTiming.)

Testing Michael E2's nice solution twenty times:

First@AbsoluteTiming@Do[Image[ImageData[p].{-1., -1., 2.}], {20}]

I have obtained:


Including the clipping:

First@AbsoluteTiming@Do[Image[Clip@ImageData[p].{-1., -1., 2.}], {20}]

I get


When I had a look at:



I thought utilizing this property both could give a further speed up and would include clipping:

First@AbsoluteTiming@Do[Image[ImageData[p, "Byte"].{-1, -1, 2}, "Byte"], {20}]


Further tests using ColorSeparate and usual additions and subtractions gave only a slight improvement:

First@AbsoluteTiming@Do[Image[#3 + #3 - #1 - #2, "Byte"] &[
    Sequence @@ Map[ImageData[#, "Byte"] &, ColorSeparate[p]]], {20}]


So even on my slow machine a more or less inelegant solution by far would provide the capability for frame rate video processing, at least for frames of that size.

|improve this answer|||||
  • $\begingroup$ Thank you very much for all your solutions, it was very helpful. I actually don't know, who to assign the answer? $\endgroup$ – Simon Nov 30 '13 at 14:53
  • $\begingroup$ You should try out what suits best for your particular video processing framework (you will notice some platform dependencies), and then decide. As in many cases on this platforms, our solutions somehow depend on each other. $\endgroup$ – UDB Nov 30 '13 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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