admin管理员组文章数量:1025244
I have an array with shape (100, 80, 3)
which is an rgb image.
I have a boolean mask with shape (100, 80)
.
I want each pixel where the mask is True
to have value of pix_val = np.array([0.1, 0.2, 0.3])
.
cols = 100
rows = 80
img = np.random.rand(rows, cols, 3)
mask = np.random.randint(2, size=(rows, cols), dtype=np.bool_)
px = np.array([0.1, 0.2, 0.3])
for ch in range(3):
img[:, :, ch][mask] = px[ch]
I thought broadcasting:
img[mask[:, :, None]] = px
would work. But it did not.
I am looking for a vectorized (efficient) way to implement it.
I have an array with shape (100, 80, 3)
which is an rgb image.
I have a boolean mask with shape (100, 80)
.
I want each pixel where the mask is True
to have value of pix_val = np.array([0.1, 0.2, 0.3])
.
cols = 100
rows = 80
img = np.random.rand(rows, cols, 3)
mask = np.random.randint(2, size=(rows, cols), dtype=np.bool_)
px = np.array([0.1, 0.2, 0.3])
for ch in range(3):
img[:, :, ch][mask] = px[ch]
I thought broadcasting:
img[mask[:, :, None]] = px
would work. But it did not.
I am looking for a vectorized (efficient) way to implement it.
Share Improve this question edited Nov 20, 2024 at 21:02 Christoph Rackwitz 16k5 gold badges39 silver badges51 bronze badges asked Nov 19, 2024 at 11:45 Avi TAvi T 1656 bronze badges 2 |2 Answers
Reset to default 3You can use:
img[mask] = px
Small example:
cols = 3
rows = 4
np.random.seed(0)
img = np.random.rand(rows, cols, 3)
mask = np.random.randint(2, size=(rows, cols), dtype=np.bool_)
px = np.array([0.1, 0.2, 0.3])
Inputs:
# img
array([[[0.5488135 , 0.71518937, 0.60276338],
[0.54488318, 0.4236548 , 0.64589411],
[0.43758721, 0.891773 , 0.96366276]],
[[0.38344152, 0.79172504, 0.52889492],
[0.56804456, 0.92559664, 0.07103606],
[0.0871293 , 0.0202184 , 0.83261985]],
[[0.77815675, 0.87001215, 0.97861834],
[0.79915856, 0.46147936, 0.78052918],
[0.11827443, 0.63992102, 0.14335329]],
[[0.94466892, 0.52184832, 0.41466194],
[0.26455561, 0.77423369, 0.45615033],
[0.56843395, 0.0187898 , 0.6176355 ]]])
# mask
array([[False, True, True],
[False, False, True],
[False, False, False],
[ True, True, True]])
Output:
array([[[0.5488135 , 0.71518937, 0.60276338],
[0.1 , 0.2 , 0.3 ],
[0.1 , 0.2 , 0.3 ]],
[[0.38344152, 0.79172504, 0.52889492],
[0.56804456, 0.92559664, 0.07103606],
[0.1 , 0.2 , 0.3 ]],
[[0.77815675, 0.87001215, 0.97861834],
[0.79915856, 0.46147936, 0.78052918],
[0.11827443, 0.63992102, 0.14335329]],
[[0.1 , 0.2 , 0.3 ],
[0.1 , 0.2 , 0.3 ],
[0.1 , 0.2 , 0.3 ]]])
I'll attempt to explain why your indexing attempt didn't work.
Make a smaller 3d array, and 2d mask:
In [1]: import numpy as np
In [2]: img = np.arange(24).reshape(2,3,4)
In [3]: mask = np.array([[1,0,1],[0,1,1]],bool);mask
Out[3]:
array([[ True, False, True],
[False, True, True]])
Using @mozway's indexing, produces a (4,4) array. The first first 4 is the number of True values in the mask, the second is the trailing dimension:
In [4]: img[mask]
Out[4]:
array([[ 0, 1, 2, 3],
[ 8, 9, 10, 11],
[16, 17, 18, 19],
[20, 21, 22, 23]])
With your indexing attempt, we get an error. (You really should have shown the error message):
In [5]: img[mask[:,:,None]]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[5], line 1
----> 1 img[mask[:,:,None]]
IndexError: boolean index did not match indexed array
along dimension 2; dimension is 4 but corresponding
boolean dimension is 1
With this None
, mask
dimension is (2,3,1). That last 1 doesn't match the 4 of img
. broadcasting
doesn't apply in this context.
Now if we attempt to use mask
in a multiplication, the (2,3,4) and (2,3) don't broadcast together:
In [6]: img*mask
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[6], line 1
----> 1 img*mask
ValueError: operands could not be broadcast together
with shapes (2,3,4) (2,3)
But (2,3,1) does broadcast with (2,3,4), producing a select number of 0
rows:
In [7]: img*mask[:,:,None]
Out[7]:
array([[[ 0, 1, 2, 3],
[ 0, 0, 0, 0],
[ 8, 9, 10, 11]],
[[ 0, 0, 0, 0],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
As I commented, using a boolean mask is equivalent to indexing with nonzero
arrays:
In [13]: I,J = np.nonzero(mask); I,J
Out[13]: (array([0, 0, 1, 1], dtype=int64), array([0, 2, 1, 2], dtype=int64))
In [14]: img[I,J,:]
Out[14]:
array([[ 0, 1, 2, 3],
[ 8, 9, 10, 11],
[16, 17, 18, 19],
[20, 21, 22, 23]])
In the assignment expresion, a size (4,) value can broadcast to the (n,4) indexed img[mask]
. Now if we were attempting to mask other dimensions we might need to make a px[:,None,:]
or something like that.
I have an array with shape (100, 80, 3)
which is an rgb image.
I have a boolean mask with shape (100, 80)
.
I want each pixel where the mask is True
to have value of pix_val = np.array([0.1, 0.2, 0.3])
.
cols = 100
rows = 80
img = np.random.rand(rows, cols, 3)
mask = np.random.randint(2, size=(rows, cols), dtype=np.bool_)
px = np.array([0.1, 0.2, 0.3])
for ch in range(3):
img[:, :, ch][mask] = px[ch]
I thought broadcasting:
img[mask[:, :, None]] = px
would work. But it did not.
I am looking for a vectorized (efficient) way to implement it.
I have an array with shape (100, 80, 3)
which is an rgb image.
I have a boolean mask with shape (100, 80)
.
I want each pixel where the mask is True
to have value of pix_val = np.array([0.1, 0.2, 0.3])
.
cols = 100
rows = 80
img = np.random.rand(rows, cols, 3)
mask = np.random.randint(2, size=(rows, cols), dtype=np.bool_)
px = np.array([0.1, 0.2, 0.3])
for ch in range(3):
img[:, :, ch][mask] = px[ch]
I thought broadcasting:
img[mask[:, :, None]] = px
would work. But it did not.
I am looking for a vectorized (efficient) way to implement it.
Share Improve this question edited Nov 20, 2024 at 21:02 Christoph Rackwitz 16k5 gold badges39 silver badges51 bronze badges asked Nov 19, 2024 at 11:45 Avi TAvi T 1656 bronze badges 2-
1
Look at what
img[mask]
selects. I believe it will be a (n,3) array.px
is (3,) which broadcasts to (1,3) and (n,3). – hpaulj Commented Nov 19, 2024 at 16:53 -
2
The main indexing documentation explains that boolean indexing is equivalent to applying
np.nonzero(mask)
. With a 2dmask
that produces a tuple of 2 indexing arrays. So that's like doingimg[I, J, :]= px
. Broadcasting is used here, but doesn't need extra help from you. – hpaulj Commented Nov 19, 2024 at 18:49
2 Answers
Reset to default 3You can use:
img[mask] = px
Small example:
cols = 3
rows = 4
np.random.seed(0)
img = np.random.rand(rows, cols, 3)
mask = np.random.randint(2, size=(rows, cols), dtype=np.bool_)
px = np.array([0.1, 0.2, 0.3])
Inputs:
# img
array([[[0.5488135 , 0.71518937, 0.60276338],
[0.54488318, 0.4236548 , 0.64589411],
[0.43758721, 0.891773 , 0.96366276]],
[[0.38344152, 0.79172504, 0.52889492],
[0.56804456, 0.92559664, 0.07103606],
[0.0871293 , 0.0202184 , 0.83261985]],
[[0.77815675, 0.87001215, 0.97861834],
[0.79915856, 0.46147936, 0.78052918],
[0.11827443, 0.63992102, 0.14335329]],
[[0.94466892, 0.52184832, 0.41466194],
[0.26455561, 0.77423369, 0.45615033],
[0.56843395, 0.0187898 , 0.6176355 ]]])
# mask
array([[False, True, True],
[False, False, True],
[False, False, False],
[ True, True, True]])
Output:
array([[[0.5488135 , 0.71518937, 0.60276338],
[0.1 , 0.2 , 0.3 ],
[0.1 , 0.2 , 0.3 ]],
[[0.38344152, 0.79172504, 0.52889492],
[0.56804456, 0.92559664, 0.07103606],
[0.1 , 0.2 , 0.3 ]],
[[0.77815675, 0.87001215, 0.97861834],
[0.79915856, 0.46147936, 0.78052918],
[0.11827443, 0.63992102, 0.14335329]],
[[0.1 , 0.2 , 0.3 ],
[0.1 , 0.2 , 0.3 ],
[0.1 , 0.2 , 0.3 ]]])
I'll attempt to explain why your indexing attempt didn't work.
Make a smaller 3d array, and 2d mask:
In [1]: import numpy as np
In [2]: img = np.arange(24).reshape(2,3,4)
In [3]: mask = np.array([[1,0,1],[0,1,1]],bool);mask
Out[3]:
array([[ True, False, True],
[False, True, True]])
Using @mozway's indexing, produces a (4,4) array. The first first 4 is the number of True values in the mask, the second is the trailing dimension:
In [4]: img[mask]
Out[4]:
array([[ 0, 1, 2, 3],
[ 8, 9, 10, 11],
[16, 17, 18, 19],
[20, 21, 22, 23]])
With your indexing attempt, we get an error. (You really should have shown the error message):
In [5]: img[mask[:,:,None]]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[5], line 1
----> 1 img[mask[:,:,None]]
IndexError: boolean index did not match indexed array
along dimension 2; dimension is 4 but corresponding
boolean dimension is 1
With this None
, mask
dimension is (2,3,1). That last 1 doesn't match the 4 of img
. broadcasting
doesn't apply in this context.
Now if we attempt to use mask
in a multiplication, the (2,3,4) and (2,3) don't broadcast together:
In [6]: img*mask
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[6], line 1
----> 1 img*mask
ValueError: operands could not be broadcast together
with shapes (2,3,4) (2,3)
But (2,3,1) does broadcast with (2,3,4), producing a select number of 0
rows:
In [7]: img*mask[:,:,None]
Out[7]:
array([[[ 0, 1, 2, 3],
[ 0, 0, 0, 0],
[ 8, 9, 10, 11]],
[[ 0, 0, 0, 0],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
As I commented, using a boolean mask is equivalent to indexing with nonzero
arrays:
In [13]: I,J = np.nonzero(mask); I,J
Out[13]: (array([0, 0, 1, 1], dtype=int64), array([0, 2, 1, 2], dtype=int64))
In [14]: img[I,J,:]
Out[14]:
array([[ 0, 1, 2, 3],
[ 8, 9, 10, 11],
[16, 17, 18, 19],
[20, 21, 22, 23]])
In the assignment expresion, a size (4,) value can broadcast to the (n,4) indexed img[mask]
. Now if we were attempting to mask other dimensions we might need to make a px[:,None,:]
or something like that.
本文标签: pythonSetting RGB value for a numpy array using boolean indexingStack Overflow
版权声明:本文标题:python - Setting RGB value for a numpy array using boolean indexing - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745564271a2156354.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
img[mask]
selects. I believe it will be a (n,3) array.px
is (3,) which broadcasts to (1,3) and (n,3). – hpaulj Commented Nov 19, 2024 at 16:53np.nonzero(mask)
. With a 2dmask
that produces a tuple of 2 indexing arrays. So that's like doingimg[I, J, :]= px
. Broadcasting is used here, but doesn't need extra help from you. – hpaulj Commented Nov 19, 2024 at 18:49