Featured post

new redirect for blender.org bpy docs.

http://www.blender.org/api/blender_python_api_current/ As of 10/11 november 2015 we can now link to the current api docs and not be worr...

August 01, 2012

Adjusting image pixels internally in Blender with bpy

The naive approach

Tasked with representing some big data, let's see if blender can handle it. Here is some exploring first.
adjusting the pixel on the last two lines above takes the most time. This image shows what the result is, zoomed in.


baby steps

This is relatively fast, but it's only 120 pixels in total. Try changing to 400*300 and you can expect it to take a lot longer, far too long to scale for big data.


results in something profoundly uninteresting
If that isn't a good method, then perhaps construct the data and overwrite image_object in one go. You'll probably want to make sure the dimensions make sense.

What we know - end of naive

with a 40*30 image, i don't expect to notice much time difference but i'll know if the operation is possible.
dm = [(1.0) for i in range(4800)]
bpy.data.images['pixeltest'].pixels = dm
# turns them all white, so maybe try constructing the array first, then assigning.
This leads to a much faster way of pushing pixels. First create the image, then the array, then modify the array, then overwrite the image with the array data. The snippet below overwrites with a dark gray.

And it seems that the speed is now closer to acceptable, here is a version that does a 400*300 px overwrite. 4000*3000 will still take 10 seconds or so (on 2.4ghz 2core) but that's not too bad.

Great, what good is that to me?

I can think of a few applications but Firefly removal would be a top option. Find outliers and average the px values with the surrounding pixels

Finished firefly removal script can be found here: link

5 comments:

  1. I am trying to iterate through pixels of an image using python in blender but am a little stuck. I am not great at programming. This snippet looks promising in helping me achieve this, but I am a little confused how to view the image.

    So far here is my code:
    import bpy

    img = bpy.data.images.load('C:/Users/Owner/Desktop/rgb.png')
    num_pixels = len(img.pixels)
    print(num_pixels)
    print(img.pixels[:4])

    ReplyDelete
  2. I have several other posts about pixels, click on the label 'pixels' in the side menu for the other posts.

    ReplyDelete
  3. just a note:
    img.pixels[:]=myarray[:]
    is about 50% faster than
    img.pixels=myarray.
    I didn't find a faster way untill now

    ReplyDelete
  4. Is it faster to push pixel data directly than to use bpy.data.images.load(“path”)?

    ReplyDelete
    Replies
    1. You can do this experiment yourself. I predict data.images.load() will be faster because it uses optimized C code, you pass it a file-name it then does the work for you. The speed of pushing values manually with python will depend on how you code it, but it will still be slower than the images.load() function, and will be most noticeable at large pixel counts.

      I suggest posting a question on http://blender.stackexchange.com/ if you want more detailed answers.

      Delete

Please use Blender.StackExchange.com for python scripting questions unrelated to this post.