Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NumPy - Faster way to implement threshold value ceiling

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?

like image 228
Jason Avatar asked Jan 30 '14 14:01

Jason


People also ask

What makes NumPy faster?

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.

Does NumPy have Ceiling function?

ceil. Return the ceiling of the input, element-wise. The ceil of the scalar x is the smallest integer i, such that i >= x .

Is NumPy faster than array?

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.


2 Answers

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
like image 140
Hooked Avatar answered Oct 06 '22 16:10

Hooked


You can use clip:

  • http://docs.scipy.org/doc/numpy/reference/generated/numpy.clip.html

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])
like image 20
YXD Avatar answered Oct 06 '22 15:10

YXD