performance - The fastest way to work with ndimage in python? -
i have function iterates on ndimage (converts image 1 color space another). works slow (2 cores cpu, 2.3 ghz, image size = 3 mp):
1) brute-force approach (loop): 27 seconds
def imagergbtoycrcb(rgb_image): """ converts image rgb ycrcb. overwrites. """ w, h = rgb_image.shape[0], rgb_image.shape[1] y in range(h): x in range(w): rgb = rgb_image[x][y] ycrcb = rgbtoycrcb(rgb) rgb_image[x][y] = ycrcb return rgb_image def rgbtoycrcb(rgb): """ converts rgb vector ycrcb vector keyword arguments: rgb -- list of size 3: [r,g,b] returns: ycrcr color (list of size 3: [y,cr,cb]) """ r,g,b = float(rgb[0]),float(rgb[1]),float(rgb[2]) y = 0.299*r + 0.587*g + 0.114*b cb = 128 - 0.1687*r - 0.3313*g + 0.5*b cr = 128 + 0.5*r - 0.4187*g - 0.0813*b return [y,cr,cb] 2) vectorization approach (numpy.apply_along_axis, numpy.dot): 90 seconds (???)
import numpy np matr_to_ycrcb_mult = np.array([ [0.299, 0.587, 0.114], [0.5, -0.4187, -0.0813], [-0.1687, -0.3313, 0.5] ]) vec_to_ycrcb_add = np.array([ 0, 128, 128 ]) matr_to_rgb_mult = np.array([ [1,1.402,0], [1,-0.71414,-0.34414], [1,0,1.772] ]) vec_to_rgb_add = np.array([ -128*1.402, 128*1.05828, -128*1.772 ]) def imagergbtoycrcb(rgb_image): rgb_image = np.apply_along_axis(rgbtoycrcb, 2, rgb_image) return rgb_image def rgbtoycrcb(rgb): """ converts rgb vector ycrcb vector """ return np.dot(matr_to_ycrcb_mult,rgb) + vec_to_ycrcb_add is there faster way process ndimage?
have implemented vectorization concepts correctly?
apply_along_axis convenience function not vectorize operation, iteration still takes place in python land.
your rgbtoycrcb function needs tiny change operate whole image. in function new_rgbtoycrcb2 slice out r, g, b (these views original image data, no copying) , stack them @ end.
you can reshape , use dot product without slicing , glueing, may faster (function new_rgbtoycrcb2):
import numpy np skimage.data import coffee def imagergbtoycrcb(rgb_image): """ converts image rgb ycrcb. overwrites. """ w, h = rgb_image.shape[0], rgb_image.shape[1] y in range(h): x in range(w): rgb = rgb_image[x][y] ycrcb = rgbtoycrcb(rgb) rgb_image[x][y] = ycrcb return rgb_image def rgbtoycrcb(rgb): """ converts rgb vector ycrcb vector keyword arguments: rgb -- list of size 3: [r,g,b] returns: ycrcr color (list of size 3: [y,cr,cb]) """ r,g,b = float(rgb[0]),float(rgb[1]),float(rgb[2]) y = 0.299*r + 0.587*g + 0.114*b cb = 128 - 0.1687*r - 0.3313*g + 0.5*b cr = 128 + 0.5*r - 0.4187*g - 0.0813*b return [y,cr,cb] def new_rgbtoycrcb(image): r, g, b = image[..., 0], image[..., 1], image[..., 2] y = 0.299*r + 0.587*g + 0.114*b cb = 128 - 0.1687*r - 0.3313*g + 0.5*b cr = 128 + 0.5*r - 0.4187*g - 0.0813*b return np.dstack((y, cr, cb)) def new_rgbtoycrcb2(image): m = np.array([[0.299, 0.587, 0.114], [0.5, - 0.4187, - 0.0813], [-0.1687, - 0.3313, 0.5]]) result = m.dot(image.reshape(-1, 3).t).t result[..., 1:] += 128.0 return result.reshape(image.shape) image = coffee() / 255.0 result = new_rgbtoycrcb(image) print(np.allclose(result, imagergbtoycrcb(image)))
Comments
Post a Comment