I'm writing a script to modify the luminance of a RGB image using NumPy and CV2 via converting from RGB to YCrCb and back again. However, the loop I'm using takes a while to execute, and am wondering if there is a faster way.
import cv2 as cv, numpy as np
threshold = 64
image = cv.imread("motorist.jpg", -1)
image.shape # Evaluates to (1000, 1500, 3)
im = cv.cvtColor(image, cv.COLOR_RGB2YCR_CB)
for row in image:
for col in row:
if col[0] > threshold:
col[0] = threshold
image = cv.cvtColor(im, cv.COLOR_YCR_CB2RGB)
cv.imwrite("motorist_filtered.jpg", image)
That nested loop implementing the threshold comparison takes at least 5-7 seconds to execute. Is there a faster method to implement this functionality?
NumPy is fast because it can do all its calculations without calling back into Python. Since this function involves looping in Python, we lose all the performance benefits of using NumPy. For a 10,000,000-entry NumPy array, this functions takes 2.5 seconds to run on my computer.
ceil. Return the ceiling of the input, element-wise. The ceil of the scalar x is the smallest integer i, such that i >= x .
NumPy Arrays are faster than Python Lists because of the following reasons: An array is a collection of homogeneous data-types that are stored in contiguous memory locations. On the other hand, a list in Python is a collection of heterogeneous data types stored in non-contiguous memory locations.
The idea is to create a mask that lets you use the numpy's vectorization. Since the shape is (n,m,3)
, loop over the first two dimensions and grab the first index of the last dimension with [:,:,0]
idx = image[:,:,0] > threshold
image[idx,0] = threshold
You can use clip
:
Usage:
result = im.copy()
result[..., 0] = np.clip(im[..., 0], 0, threshold)
Or to modify in-place:
np.clip(im[..., 0], 0, threshold, out=im[..., 0])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With