3

Suppose I have a 2D array im of real values between 0 and 1, representing a grayscale image. I can turn im into an image very efficiently with Image[im] (in fact, on my machine, AbsoluteTiming@Image[im] returns 0. for a 1920 by 1080 array). I would like to colorize im by applying a ColorDataFunction, for example, ColorData["AvocadoColors"], to each entry of im. My first thought was to use Image@Map[ColorData["AvocadoColors"], im, {2}], but this is unreasonably expensive, taking nearly a minute for a 1920 by 1080 array. What is a more efficient way to produce the same output?

David Zhang
  • 2,316
  • 15
  • 25
  • 1
    Colorize[im, ColorFunction->"AvocadoColors"]? – kglr Feb 17 '15 at 18:08
  • @kguler Remember to ColorFunctionScaling -> False. – Kuba Feb 17 '15 at 18:11
  • @kguler I just came back to post that, that's the correct solution. Why don't you post it? – Szabolcs Feb 17 '15 at 18:12
  • @kguler Did you mean Colorize[Image[im], ColorFunction -> "AvocadoColors"]? When I execute your code, I'm told that Colorize is Expecting an integer matrix or an image instead of {<<1>>}. – David Zhang Feb 17 '15 at 18:17
  • David, yes. @Kuba, not sure if it is needed here. – kglr Feb 17 '15 at 18:27
  • 1
    @Szabolcs, just posted the comment as answer. Your deleted answer seems to be faster on a few example images i tried. – kglr Feb 17 '15 at 18:32
  • @kguler Yes, agree, it was rather comment for visitors. This is devil's option ;) – Kuba Feb 17 '15 at 18:32
  • @MrWizard I understood this question as asking about how to create an Image object. The duplicate doesn't show this. – Szabolcs Feb 17 '15 at 20:27
  • @Szabolcs Even if it isn't addressing precisely the same question, the duplicate does give a solution to my problem (which is faster than all the answers below, to boot). I'm happy with this being marked as duplicate. – David Zhang Feb 17 '15 at 20:33
  • @DavidZhang If you're happy with that then it's fine. – Szabolcs Feb 17 '15 at 20:33

2 Answers2

3
im = ExampleData[{"TestImage", "Aerial"}];

Colorize[im, ColorFunction -> "AvocadoColors"] // Timing // First
(* 0.093750 *)

versus

ImageApply[List @@ ColorData["AvocadoColors"][#] &, im] // Timing // First
(* 0.265625 *)

ImageApply[List @@ Blend["AvocadoColors", #] &, im] // Timing // First (thanks: @Kuba *)
(* 0.109375 *)

For a larger image:

imlarge = Image[ RandomReal[1, {1080, 1920}]];

f1 = Colorize[#, ColorFunction -> "AvocadoColors"] &;
f2 = Image@Raster[ImageData[#, DataReversed -> True], ColorFunction -> "AvocadoColors"] &;
f3 = ImageApply[List @@ Blend["AvocadoColors", #] &, #] &;

First[Timing@#[imlarge]] & /@ {f1, f2, f3}
{2.234375, 2.140625, 3.093750}
kglr
  • 394,356
  • 18
  • 477
  • 896
  • Is this really the fastest it can be done? I was hoping, since Image[im] is so fast, that I might be able to apply a ColorDataFunction in a comparable amount of time. For me, these all take several seconds for a 1920 by 1080 image. – David Zhang Feb 17 '15 at 19:22
  • @DavidZhang, i am sure answers with faster methods will trickle in if you wait a few hours/days. – kglr Feb 17 '15 at 20:18
2

Raster will be helpful, as it has the ColorFunction option and it can be directly converted back to an Image.

Let img be a grayscale image:

img = ColorConvert[ExampleData[{"TestImage", "Lena"}], "Grayscale"]

Image@Raster[ImageData[img, DataReversed -> True], ColorFunction -> "Rainbow"]

Mathematica graphics

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263