3
$\begingroup$

I am playing with some basic genetic algorithms to recreate input images by transparent plane figures (similar like here:). Everything would work great but the speed is terrible. I was looking for a problematic part of my code and I found that function I use - ImageDifference works very slow for CMYK colors (even if you are comparing CMYK to CMYK), but it is much faster for RGB vs RGB comparison.

The problem is that when I combine figures using Graphics like this:

Graphics[{Opacity[0.5], Red, Disk[], Green, Disk[{1, 0}]}]

the result image is in CMYK and hence, to make ImageDifference faster, I have to use ColorConvert (to RGB) which again is quite slow function.

Is there another way in Mathematica to set that all images created by Graphics will be automatically in RGB? Or if you have another ideas how to speed this up, please let me know. :)

Small demonstration:

I have some target image. For example:

target = ImageResize[ExampleData[{"TestImage", "Lena"}], 150]

enter image description here

In every step, I also have some combination of polygons which I want to compare to the target image. So lets say, we have (in some very early stage):

k = 5;(*number of points*)
n = 20;(*number of polygons*)

(*opacity, r, g, b, x, y*)
polygons= 
  Table[{RandomReal[], RandomReal[], RandomReal[], RandomReal[], 
     RandomReal[{0, 1}, k], RandomReal[{0, 1}, k]} // Flatten, {n}];

example1 = Graphics[
   Map[
    {
      Opacity[#[[1]]],
      RGBColor[#[[2]], #[[3]], #[[4]]],
      Polygon[{Take[#, {5, 5 + k - 1}], Take[#, {5 + k, 2 k + 4}]} //Transpose]
      }
     &,
    polygons
    ], ImageSize -> {150, 150}
   ]

enter image description here

For demonstration lets also set:

example2 = ColorConvert[example1, "RGB"];

Now, the difference in applying ImageData for those two representations is quite huge:

(example1 // ImageData); // AbsoluteTiming (*-> 0.0584582*)
(example2 // ImageData); // AbsoluteTiming (*-> 0.000384866*)

Same for the ImageDifference:

ImageDifference[target,example1]; // AbsoluteTiming (*-> 0.0703736*)
ImageDifference[target,example2]; // AbsoluteTiming (*-> 0.000687233*)
$\endgroup$
  • 4
    $\begingroup$ "the result image is in CMYK" ...Um, it isn't? A Graphics is not an Image and doesn't have an intrinsic colour space, unless you Rasterize it or do Image[graphics, ColorSpace -> space]. How are you finding it to be "in CMYK"? $\endgroup$ – Rahul Nov 21 '15 at 16:23
  • 5
    $\begingroup$ Can you at least construct a minimum example to demonstrate this behavior you're seeing? $\endgroup$ – J. M. is away Nov 21 '15 at 16:26
  • $\begingroup$ When you apply ImageData on a result, it will give you matrix of 4-dimensional vectors, which made me think it is in CMYK. $\endgroup$ – matt525252 Nov 22 '15 at 0:12
  • 1
    $\begingroup$ Ah, you're misreading the output; it's still RGB, plus the alpha channel (which shows up due to your Opacity[] directives). Explicitly-set alpha channels slow things down in Mathematica, for some reason... $\endgroup$ – J. M. is away Nov 22 '15 at 2:44
  • $\begingroup$ Ah, okay, thanks for explaining. Anyway, I still see some huge performance difference after applying ColorConvert. I updated my question and added small demonstration. $\endgroup$ – matt525252 Nov 22 '15 at 9:20
4
$\begingroup$

In your present example the operation that is slow is the rasterization of the Graphics expression. This is implicitly performed by both ImageDifference[target,example1] and ColorConvert[example1, "RGB"]. By pre-rasterizing for example2 you remove this costly step and the ImageDifference is two orders of magnitude faster. If you include the rasterization in the timing it is much closer, though interestingly still a bit faster.

ColorConvert[example1, "RGB"] // Head // RepeatedTiming

ImageDifference[target, example1]; // RepeatedTiming

ImageDifference[target, ColorConvert[example1, "RGB"]]; // RepeatedTiming
{0.025, Image}    (* note that the Head is Image *)

{0.030, Null}

{0.025, Null}

This question then becomes: how can one rasterize faster? Unfortunately I do not have a good answer to that. You can Rasterize directly to an Integer array, if that is your target, somewhat faster than using ImageData:

ColorConvert[example1, "RGB"] // ImageData; // RepeatedTiming

Rasterize[example1, "Data"]; // RepeatedTiming
{0.025, Null}

{0.0213, Null}

I am afraid however that this is not helpful in your situation as the integer array cannot be (directly) used as input for ImageDifference.

$\endgroup$

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.