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...

Showing posts with label image. Show all posts
Showing posts with label image. Show all posts

August 17, 2012

Faster Pixel manipulation inside blender

Storing a pixel lookuptable in a dict, although unordered, is probably faster for lookup and manipulation. How true is this? Well, throw some sample images at it and timeit() compared to some other structures.
px_list = [ 
    1, 2, 3, 4, 5, 6, 7, 8,
    9, 10,11,12,13,14,15,16,
    17,18,19,20,21,22,23,24,
    25,26,27,28,29,30,31,32]



def idx_to_co(idx, width):
    r = int(idx / width)
    c = idx % width
    return r, c

def px_list_to_dict(px_list, width):
    px_dict = {}
    for idx, px in enumerate(px_list):
        px_dict[idx_to_co(idx, width)] = px

    return px_dict

image_width = 8
px_dict = px_list_to_dict(px_list, image_width)

# unordered, but much faster lookup than list
for i in px_dict:
    print(i)


import bpy

D = bpy.data
img = D.images['moop2.png']

img_width = img.size[0]
img_height = img.size[1]

# slowest part is the transfer from pixel array to list
pxs = list(img.pixels)

num_values = len(pxs)
px_list = [pxs[i:i+4] for i in range(num_values)[::4]]


def idx_to_co(idx, width):  
    r = int(idx / width)  
    c = idx % width  
    return r, c  


def px_list_to_dict(px_list, width):
    px_dict = {}
    for idx, px in enumerate(px_list):
        px_dict[idx_to_co(idx, width)] = px

    return px_dict


px_dict = px_list_to_dict(px_list, img_width)

print(px_dict[(30,30)])
How about using tuple for lookup? ..still have to time this, but it looks interesting, it has to be faster in some way because it is an immutable structure.

August 07, 2012

adjusting image pixels (walkthrough)

Experiment with small images

For example experiment along using this image (24px wide, 7px high)

Number of pixels

This shows how to get the number of pixels in an image
import bpy

D = bpy.data

test_file = 'firefly_test_pattern_2.tga'
img = D.images[test_file]

# double division symbol forces integer result.
# 'pixels' here are ungrouped, every sequence of 
# 4 consecutive items in pixels is an rgba when
# combined
print( len(img.pixels)//4)

Dimensions

This shows how to get the width and height of an image
import bpy

D = bpy.data

test_file = 'firefly_test_pattern_2.tga'
img = D.images[test_file]

#alias if you can
w = width = img.size[0]
h = height = img.size[1]

print('image width: %d' % w)
print('image height: %d' % h)

Indexing!

This shows how to extract the array of pixels into a new list, for faster access.
import bpy
D = bpy.data

test_file = 'firefly_test_pattern_2.tga'
img = D.images[test_file]

# work on a copy instead, it's much faster
pixels = list(img.pixels)

# this collects every 4 items in pixels and stores them inside a tuple
# and sticks all tuples into the grouped_list
grouped_list = [pixels[ipx:ipx+4] for ipx in range(0, len(pixels), 4)]

print(len(grouped_list))
print(grouped_list)

coordinates from pixel index and back

This shows how to extract the array of pixels into a new list, for faster access.
import bpy
D = bpy.data

test_file = 'firefly_test_pattern_2.tga'
img = D.images[test_file]
pixels = list(img.pixels)
grouped_list = [pixels[ipx:ipx+4] for ipx in range(0, len(pixels), 4)]

some convenience functions

contrast and compare the above, with the following slightly more convenient ways to name objects. Some objects deserve short names. and

August 02, 2012

Firefly removal in blender

This is a continuation of the previous post about Adjusting image pixels internally in Blender with bpy

firefly removal

In optimal lighting conditions fireflies don't really occur often in cycles, I can't remember seeing any lately. here's a script that first creates a simulation of fireflies then removes them. results in this:

TBC

As you can see it's probably an ok simulation, looking at it tells me something about a potential algorithm.
  • collect all whites
  • sample colour from the surrounding non white pixels
Most images don't have any pixels that are fully white, so i won't include a check for all surrounding pixels.

Finished firefly removal script can be found here: link

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