Hello everybody,
my name is Emanuele Zattin and i'm developing a plug-in implementing a
texture synthesis algorithm described in a paper ("Texture Synthesis
by Non-parametric sampling" by Efros and Leung).
Here attached you can  see my actual implementation which works on
grayscale images. It is anyway VERY slow, which was anyway predictable
judging from the complexity of the algorithm.
I was wondering if translating it to C would make it much faster or if
there are some more speedup techniques i'm just missing.

Thank you very much!!

Emanuele Zattin
#!/usr/bin/python

import math
from gimpfu import *
from Numeric import *

def getpixel(drawable, x, y):
	tile = drawable.get_tile2(FALSE, x, y)
	x_offset = x % 64
        y_offset = y % 64
        pixel = tile[x_offset, y_offset]

	values = []
	for i in range(len(pixel)):
		values.append(ord(pixel[i]))

	if len(values) == 1:
		values.append(255)

	return values

def putpixel(drawable, x, y, value):
	tile = drawable.get_tile2(FALSE, x, y)
	x_offset = x % 64
        y_offset = y % 64
        tile[x_offset, y_offset] = chr(value) + chr(255)

	return	

def texture_synthesis(image, drawable, w):
	# first let's retrieve some useful stats about the current layer
	layer = image.active_layer
	height = layer.height
	width = layer.width

	gimp.tile_cache_ntiles(2 * (width + 63) / 64)

	# where are the transparent pixels?
	gimp.progress_init("Gathering stats...")
	transparent = []
	for i in range(width):
		for j in range(height):
			pixel = getpixel(layer, i, j)
			if pixel[1] < 255:
				transparent.append([i, j])
		gimp.progress_update(float(i-w)/(width-1-2*w))

	if len(transparent) == 0:
		return

	while len(transparent) > 0:

		# which is the next pixel to synthetize?
		neighbours = []
		for index in range(len(transparent)):
			count = 0
			pixel_pos = transparent[index]
			for x in range(max(0, pixel_pos[0]-w), min(width, pixel_pos[0]+w)):
				for y in range(max(0, pixel_pos[1]-w), min(height, pixel_pos[1]+w)):
					pixel = getpixel(layer, x, y)
					if pixel[1] == 255:
						count = count + 1
			neighbours.append(count)

		trans_index = neighbours.index(max(neighbours))
						
		next_pixel_pos = transparent[trans_index]
						
		# create the pattern around that pixel
		pattern = arrayrange((4*w*w+4*w+1))
		pattern.shape = (2*w+1, 2*w+1)
		
		for i in range(2*w+1):
			for j in range(2*w+1):
				# where's the pixel we're gonna check?
				px = next_pixel_pos[0]+i-w
				py = next_pixel_pos[1]+j-w
				
				# is it in the image?
				if px<0 or px>=width or py<0 or py>=height:
					pixel = [-1, 0]
				else:
					pixel = getpixel(layer, px, py)
					
				if pixel[1] == 255:
					pattern[i,j] = pixel[0]
				else:
					if pixel[0] == -1:
						pattern[i,j] = -1
					else:
						pattern[i,j] = 0

		# let's find the closest matches
		max_result = 0
		values = []
		positions = []
		gimp.progress_init("Computing pixel: " + str(len(transparent)) + " more to go")
		for i in range(width):
			for j in range(height):
				result = 0
				dist = pow((next_pixel_pos[0]-i),2) + pow((next_pixel_pos[1]-j),2)
				if dist > 0:
					for x in range(2*w+1):
						for y in range(2*w+1):
							px = i+x-w
							py = j+y-w
							if px>=0 and px<width and py>=0 and py<height:
								pixel = getpixel(layer, px, py)
								if pixel[1] == 255 and pattern[x,y] >=0:
									result = result + 255-abs(pixel[0]-pattern[x, y])

					if result > max_result:
						print "Matching: " + str(float(result)/(255*((2*w+1)*(2*w+1)))) +" ("+ str(i) +","+ str(j) + ")"
						max_result = result
						pixel = getpixel(layer, i, j)
						values = []
						values.append(pixel[0])
						positions = []
						positions.append([i, j])
					elif result == max_result:
						pixel = getpixel(layer, i, j)
						values.append(pixel[0])
						positions.append([i, j])
					
			gimp.progress_update(float(i)/(width-1))

		distances = []
		for i in positions:
			distances.append(pow((next_pixel_pos[0]-i[0]),2) + pow((next_pixel_pos[1]-i[1]),2))

		min_distance_index = distances.index(min(distances))
		min_distance_value = values[min_distance_index]

		putpixel(layer, next_pixel_pos[0], next_pixel_pos[1], min_distance_value)
		layer.update(next_pixel_pos[0], next_pixel_pos[1], 1, 1)

		transparent[trans_index:trans_index+1] = []

register(
	"TextureSynthesis",
	"Synthetize transparent pixels of the current layer",
	"Synthetize transparent pixels of the current layer",
	"Ling Xu, Emanuele Zattin",
	"Ling Xu, Emanuele Zattin",
	"2006",
	"<Image>/Python-Fu/Texture/Synthesis",
	"GRAY*",
	[
		(PF_INT, "w", "Window Size", 9)
	],
	[],
	texture_synthesis)

main()




_______________________________________________
Gimp-developer mailing list
Gimp-developer@lists.XCF.Berkeley.EDU
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Reply via email to