Reputation:
I want to change the red value > 100 of image[1] to RGB(0,0,0) - image[2] - using Python.
Now: [1]: https://i.sstatic.net/cZhVG.jpg
Target: [2]: https://i.sstatic.net/bcTU0.png
For example, if it's RGB(120,60,90) it should be RGB(0,0,0)
data = np.array(img)
print(data)
Terminal:
[[[10 8 6]
[10 8 6]
[10 8 6]
...
[ 8 7 5]
[ 8 7 5]
[ 8 7 5]]
[[10 8 6]
[10 8 6]
[10 8 6]
...
[ 8 7 5]
[ 8 7 5]
[ 8 7 5]]
[[10 8 6]
[10 8 6]
[10 8 6]
...
[ 8 7 5]
[ 8 7 5]
[ 8 7 5]]
...
I know that
data[..., 0]
is for the red channel.
Upvotes: 2
Views: 1837
Reputation: 8952
Here's a one-liner:
(rgb[..., 0] < 100)[..., np.newaxis] * rgb
This also works (haven't tested which is faster):
rgb[rgb[..., 0] > 100] *= 0
Here's the result on a random (3, 5, 3)
array:
>>> import numpy as np
>>> rgb = np.random.randint(0, 255, (3, 5, 3), dtype="uint8")
>>> rgb
array([[[159, 204, 134],
[208, 224, 176],
[177, 57, 26],
[213, 191, 17],
[ 71, 205, 162]],
[[124, 94, 64],
[ 41, 231, 130],
[ 90, 235, 124],
[ 18, 237, 101],
[ 92, 86, 250]],
[[104, 107, 251],
[ 27, 247, 214],
[123, 129, 88],
[199, 105, 225],
[ 29, 223, 117]]], dtype=uint8)
>>>
>>> (rgb[..., 0] < 100)[..., np.newaxis] * rgb
array([[[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 71, 205, 162]],
[[ 0, 0, 0],
[ 41, 231, 130],
[ 90, 235, 124],
[ 18, 237, 101],
[ 92, 86, 250]],
[[ 0, 0, 0],
[ 27, 247, 214],
[ 0, 0, 0],
[ 0, 0, 0],
[ 29, 223, 117]]], dtype=uint8)
EDIT: I did some very simple benchmarking on a 500x500 pixel "image":
In [1]: import numpy as np
In [2]: rgb = np.random.randint(0, 255, (500, 500, 3), dtype="uint8")
In [3]: rgb_copy = rgb.copy()
In [4]: %timeit rgb_copy[rgb[..., 0] > 100] *= 0
6.63 ms ± 15 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [5]: rgb_copy = rgb.copy()
In [6]: %timeit rgb_copy[rgb[..., 0] > 100] = np.array([0, 0, 0])
3.25 ms ± 14.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [7]: rgb_copy = rgb.copy()
In [8]: %timeit new_rgb = rgb * (rgb[..., 0] < 100)[..., np.newaxis]
1.24 ms ± 2.91 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Pretty similar results although my first suggestion seems to perform the best in my testing.
Upvotes: 0
Reputation: 79
if you're simply trying to change the values in the NumPy array, then just use NumPy's fancy indexing
data[data[..., 0] > 100] = np.array([0, 0, 0])
Upvotes: 1
Reputation: 113930
red_channel = data[..., 0]
mask = red_chanel > 100
data[mask] = [0,0,0]
I think ... you might have to get a bit fancier
data[mask][...,0] = 0
data[mask][...,1] = 0
data[mask][...,2] = 0
(there is probably an easier way to set it but that should work)
Upvotes: 0