Message Boards Message Boards

0
|
7828 Views
|
4 Replies
|
2 Total Likes
View groups...
Share
Share this post:

Speed up image creation from Graphics[] primitives?

I am working on a project where I've discovered via profiling that the performance hot spot is a function that looks like:

oneline[g_, tweight_, 
  lweight_] := {RGBColor[g[[1]], g[[2]], g[[3]], g[[4]]], 
  Thickness[tweight*g[[5]]], 
  Line[{lweight*g[[6 ;; 7]], lweight*g[[8 ;; 9]]}]};

render[i_]:=Image[Graphics[oneline[#, 0.5, 200] & /@ i]] // 
 ImageResize[#, {200, 200}] &

Basically, I have a set of colored lines that I'm rendering into a Graphics[] object that I then render to a 200x200 Image that I later extract pixel data from with ImageData. In my tests, I'm creating around 100 images each with 80 lines - which takes around 6.3 seconds (measured w/ AbsoluteTiming) on my 2018 macbook pro w/ Mathematica 11.3. Given that it works out to drawing 8000 lines and creating only 100 images that are 200x200, I was expecting this to run much faster.

Is there a better way to create 2D Images from Graphics objects built out of graphics primitives that will run faster?

POSTED BY: Matthew Sottile
4 Replies

Conversion of Graphics to Image usually requires a rasterization and unfortunately it is the case here. Image constructor internally calls Rasterize when the input argument is a Graphics object. The only exception is Graphics[Raster[..]], where the image data is extracted directly from Raster. You can use ImageSize option of Graphics in your render function to avoid ImageResize call:

render3[i_, size_] := Image[Graphics[oneline[#, 0.5, 200] & /@ i, ImageSize -> size]]
POSTED BY: Piotr Wendykier
Posted 5 years ago

All the time seems to be in the Image[]. The rest is fast. I would contact tech support to see if the developers in that group can explain why. Sorry I could not be more helpful.

Regards

POSTED BY: Updating Name

Matthew,

You should provide some sample data otherwise its hard to say without trying things out. One thing that I notice is that imageResize is slow and not needed because you can specify the resolution in Image:

This is much faster

AbsoluteTiming[
 Image[RandomReal[1, {500, 500, 3}], ImageSize -> {200, 200}]]

than

AbsoluteTiming[
 Image[RandomReal[1, {500, 500, 3}]] // ImageResize[#, {200, 200}] &]

But beyond that I can't duplicate what you are doing without data.

Regards,

Neil

POSTED BY: Neil Singer

I'm using random data for test input. If each image has 80 lines to be rendered with my code above, then I would generate it as:

i=Table[RandomReal[{0, 1}, 9], {i, 1, 80}]
render[i]//AbsoluteTiming

Your code is going to be faster as you wrote it because it isn't compositing the image from graphics primitives - it's going from a 2D array of numbers and creating a raster image from it. My code above is creating the Image from a set of Graphics primitives, not a 2D array of numbers. Adding ImageSize->{200,200} to my code doesn't change the performance in a useful way. In fact, changing render to:

render2[i_] := Image[Graphics[oneline[#, 0.5, 200] & /@ i], ImageSize -> {200, 200}]

Takes 7.3 seconds, where the original render[] takes 6.5 seconds on the same input.

pop = Table[Table[RandomReal[{0,1},9],{i,1,80}],{j,1,100}];

In[23]:= ((render /@ pop) // AbsoluteTiming)[[1]]

Out[23]= 6.52233

In[24]:= ((render2 /@ pop) // AbsoluteTiming)[[1]]

Out[24]= 7.26737
POSTED BY: Matthew Sottile
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract