Skip to content Skip to sidebar Skip to footer

Fast Way To Apply Custom Function To Every Pixel In Image

I'm looking for a faster way to apply a custom function to an image which I use to remove a blue background. I have a function that calculates the distance each pixel is from appro

Solution 1:

This should be a lil bit faster ... ;)

import numpy as np 
blue = np.full_like(image, [76,150,250])
mask = np.sum((image-blue)**2,axis=-1) < 12000
image[mask] = [255,0,255]

Here you're generating the ideal blue image, squaring the difference of the images pixel by pixel, then summing over the last axis (the rgb vectors) before generating a mask and using it to modify values in the original image.

Solution 2:

An approach incorporating the answers of @dash-tom-bang and @kevinkayaks

# Assume the image is of shape (h, w, 3)# Precompute some data
RDIST = np.array([(76 - r)**2 for r in range(256)])
GDIST = np.array([(150 - g)**2 for g in range(256)])
BDIST = np.array([(240 - b)**2 for b in range(256)])

# Calculate and apply mask
mask = (RDIST[image[:,:,0]] + GDIST[image[:,:,1]] + BDIST[image[:,:,2]]) < 12000
image[mask] = [255,255,255]

Solution 3:

This is just a shot in the dark but maybe precomputing some data would help? I don't know for sure but the table lookup may be faster than the add and multiply?

defsquare(x): # maybe there's a library function for this?return x*x

RDIST = [square(76 - r) for r inrange(256)]
GDIST = [square(150 - g) for g inrange(256)]
BDIST = [square(240 - b) for b inrange(256)]

defdist_to_blue(pix):
    return RDIST[pix[0]] + GDIST[pix[1]] + BDIST[pix[2]]

I suspect too if you have a way to just get an array of pixels per row that might be faster, instead of indexing each individual pixel, but I don't know the libraries in play.

Solution 4:

There are some ways to accelerate your Numpy code by getting ride of for loops, like using Numpy's ufuncs (+, -, *, **, <...), aggregations (sum, max, min, mean...), broadcasting, masking, fancy indexing. The code below may give you some tips:

dist = np.expand_dims(np.array([76, 150, 240]), axis=0)
image[np.where(np.sum((image-dist)**2, axis=2) < 12000)]=255

Solution 5:

from scipy.spatial.distance import cdist

blue = np.array([76, 150, 250])

defcrush_color(image, color, thr = np.sqrt(12000), new = np.array([255, 255, 255]));
    dist_to_color = cdist(image.reshape(-1, 3), color, 'sqeuclidean').reshape(image.shape[:-1])
    image[dist_to_color[..., None] < thr**2] = new

crush_color(image, blue)

1) instead of doing distance manually, use cdist which will calculate the distances (squared ueclidean in this case) much faster even than numpy broadcasting.

2) Do the replacement in place

Post a Comment for "Fast Way To Apply Custom Function To Every Pixel In Image"