Fast Way To Apply Custom Function To Every Pixel In Image
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"