英文:
Convert numpy array to binary array in numpy
问题
我有一个3D的NumPy数组(100*100*4)
。我想要将非[255,255,255,255]
的向量转换为[0,0,0,255]
。
# 生成一个NumPy数组
np.random.seed(seed=777)
s = np.random.randint(low=0, high=255, size=(100, 100, 4))
print(s)
目前这是我的方法,但似乎很慢,有更好的方法吗?任何帮助都将不胜感激。
def foo(x):
y = np.full_like(x, 255)
for iy, ix in np.ndindex(x.shape[0:2]):
if not np.all(x[iy, ix] == 255):
y[iy, ix] = np.array([0, 0, 0, 255])
return
英文:
Say I have a 3D numpy array (100*100*4)
. I would like to convert non-255 vector ([255,255,255,255]) to [0,0,0,255]
# genearte a numpy array
np.random.seed(seed=777)
s = np.random.randint(low=0, high = 255, size=(100, 100, 4))
print(s)
Currently this is my approach but seems very slow, is there a better way? Any help is appreciated.
def foo(x):
y= np.full_like(x, 255)
for iy, ix in np.ndindex(x.shape[0:2]):
if not np.all(x[iy, ix] == 255):
y[iy, ix] = np.array([0, 0, 0, 255])
return
答案1
得分: 1
你可以执行以下操作:
# 获取布尔数组,其中条目等于[255, 255, 255, 255]
b = (s[:, :] == np.array([255, 255, 255, 255])).all(axis=2)
# 将b为False的值设置为[0, 0, 0, 255]
s[~b] = np.array([0, 0, 0, 255])
英文:
You could do the following:
# get boolean array where entries are equal to [255, 255, 255, 255]
b = (s[:, :] == np.array([255, 255, 255, 255])).all(axis=2)
# set values where b is False to [0, 0, 0, 255]
s[~b] = np.array([0, 0, 0, 255])
答案2
得分: 1
import numpy as np
s = np.array(
[
[
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 200, 255, 255],
[200, 255, 255, 255],
[200, 255, 255, 255],
],
[
[255, 255, 255, 255],
[200, 255, 255, 255],
[255, 200, 255, 255],
[255, 255, 200, 255],
[255, 255, 200, 255],
]
]
)
mask = (s != 255).any(axis=-1)
s[mask] = [0, 0, 0, 255]
>>> s
array([[[255, 255, 255, 255],
[255, 255, 255, 255],
[ 0, 0, 0, 255],
[ 0, 0, 0, 255],
[ 0, 0, 0, 255]],
[[255, 255, 255, 255],
[ 0, 0, 0, 255],
[ 0, 0, 0, 255],
[ 0, 0, 0, 255],
[ 0, 0, 0, 255]]])
英文:
Use broadcasting and boolean array indexing:
import numpy as np
s = np.array(
[
[
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 200, 255, 255],
[200, 255, 255, 255],
[200, 255, 255, 255],
],
[
[255, 255, 255, 255],
[200, 255, 255, 255],
[255, 200, 255, 255],
[255, 255, 200, 255],
[255, 255, 200, 255],
]
]
)
mask = (s != 255).any(axis=-1)
s[mask] = [0, 0, 0, 255]
>>> s
array([[[255, 255, 255, 255],
[255, 255, 255, 255],
[ 0, 0, 0, 255],
[ 0, 0, 0, 255],
[ 0, 0, 0, 255]],
[[255, 255, 255, 255],
[ 0, 0, 0, 255],
[ 0, 0, 0, 255],
[ 0, 0, 0, 255],
[ 0, 0, 0, 255]]])
答案3
得分: 1
以下是翻译好的部分:
"我使用了一个较小的数组,其中值的变化较小,以便您可以轻松检查我的结果。
这里的第一个想法是重塑数据数组,使得每一行都是您想要测试的4元组之一 (255, 255, 255, 255)
,
第二个想法是使用 .all(axis=1)
方法(感谢 mozway 的建议)以获得一个可用于索引视图的一维布尔数组。
import numpy as np
np.random.seed(2023-3-7)
# 常量
MILLE_VENTI = np.array((255, 255, 255, 255), dtype=int)
REPLACEMENT = np.array((0, 0, 0, 255), dtype=int)
H, W, D = 6, 6, 4
# 您的数组(具有更高概率的 MILLE_VENTI)和其视图
s = np.random.randint(low=254, high=256, size=(H, W, D))
v = s.reshape(-1, 4) # v 是 s 的视图
# 计算一维布尔数组并检查是否有“命中”
is_milleventi = (v == MILLE_VENTI).all(axis=1)
print(*((n, arr) for n, arr in enumerate(v) if is_milleventi[n]))
# 将替代值分配给不满足条件的行
v[~is_milleventi] = REPLACEMENT
# 检查原始数组是否已正确修改
print(s)
输出:
(29, array([255, 255, 255, 255]))
[[[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]]
[[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]]
[[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]]
[[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]]
[[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[255 255 255 255]]
[[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]
[0 0 0 255]]]
<details>
<summary>英文:</summary>
I used a smaller array with a smaller variation of values, so that you can check my results easily.
Here the first idea is to reshape the data array so that each of the rows is one of the 4-uple that you want to test against `(255, 255, 255, 255)`,
the second one is to use the `.all(axis=1)` method ([thank you mozway][1]) to have a 1D Boolean array that can be used to index the view.
In [189]: import numpy as np
...: np.random.seed(2023-3-7)
...:
...: # CONSTANTS
...: MILLE_VENTI = np.array((255, 255, 255, 255), dtype=int)
...: REPLACEMENT = np.array(( 0, 0, 0, 255), dtype=int)
...: H, W, D = 6, 6, 4
...:
...: # your array (with a higher chance of a MILLE_VENTI) and a view of it
...: s = np.random.randint(low=254, high = 256, size=(H, W, D))
...: v = s.reshape(-1,4) # v is a VIEW of s
...:
...: # compute a 1D boolean array and check if we have a "hit"
...: is_milleventi = (v==MILLE_VENTI).all(axis=1)
...: print(*((n, arr) for n, arr in enumerate(v) if is_milleventi[n]))
::::
...: # assign the replacement values to the rows that DO NOT satisfy condition
...: v[~is_milleventi] = replacement
...:
...: # check that the original array has been correctly mofified
...: print(s)
(29, array([255, 255, 255, 255]))
[[[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]]
[[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]]
[[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]]
[[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]]
[[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[255 255 255 255]]
[[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]
[ 0 0 0 255]]]
In [190]:
[1]: https://stackoverflow.com/a/75662903/2749397
</details>
# 答案4
**得分**: 1
以下是您要翻译的部分:
Listing [\[NumPy\]: Routines](https://numpy.org/doc/stable/reference/routines.html#routines).
This is more like an exercise: I wanted to do a comparison between the existing variants (from question and answers).
*code00.py*:
```python
#!/usr/bin/env python
import sys
import timeit
import numpy as np
def _user16971617(arr):
ret = np.full_like(arr, 255)
for iy, ix in np.ndindex(arr.shape[0:2]):
if not np.all(arr[iy, ix] == 255):
ret[iy, ix] = np.array([0, 0, 0, 255])
return ret
def _matt_pitkin(arr):
ret = np.copy(arr)
b = (ret[:, :] == np.array([255, 255, 255, 255])).all(axis=2)
ret[~b] = np.array([0, 0, 0, 255])
return ret
def _paime(arr):
ret = np.copy(arr)
mask = (ret != 255).any(axis=-1)
ret[mask] = [0, 0, 0, 255]
return ret
def _roman_perekhrest(arr):
ret = np.copy(arr)
return np.where((ret != [255, 255, 255, 255]).any(-1)[:, :, None], [0, 0, 0, 255], ret)
FUNCS = (
_user16971617,
_matt_pitkin,
_paime,
_roman_perekhrest,
)
def test_acc():
print("ACCURACY")
arr = np.array((
(
(255, 255, 255, 255),
(255, 0, 0, 0),
(255, 255, 0, 0),
(255, 0, 255, 0),
(255, 0, 0, 255),
(0, 255, 255, 0),
(0, 255, 0, 255),
(0, 0, 255, 255),
), (
(1, 2, 3, 4),
(0, 255, 0, 0),
(1, 2, 255, 0),
(1, 0, 2, 255),
(255, 255, 255, 0),
(255, 255, 0, 255),
(255, 0, 255, 255),
(0, 255, 255, 255),
)), dtype=np.uint8)
exp = np.array((((0, 0, 0, 255),) * arr.shape[1],) * arr.shape[0], dtype=np.uint8)
exp[0][0] = (255, 255, 255, 255)
print("Expected result:\n{:}\n".format(exp))
for func in FUNCS:
print("Probing function: {:s}".format(func.__name__))
ret = func(arr)
if not np.array_equal(exp, ret):
print("DIFFERENT result:\n{:}".format(ret))
def test_perf():
print("PERFORMANCE")
arr = np.random.randint(low=0, high = 255, size=(100, 100, 4), dtype=np.uint8)
res = []
for func in FUNCS:
res.append((func.__name__, timeit.timeit(lambda: func(arr), number=200)))
print("Function results:")
for n, t in sorted(res, key=lambda arg: arg[1], reverse=True):
print("Function {:s}: {:.3f} seconds".format(n, t))
def main(*argv):
test_acc()
test_perf()
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
英文:
Listing [NumPy]: Routines.
This is more like an exercise: I wanted to do a comparison between the existing variants (from question and answers).
code00.py:
#!/usr/bin/env python
import sys
import timeit
import numpy as np
def _user16971617(arr):
ret = np.full_like(arr, 255)
for iy, ix in np.ndindex(arr.shape[0:2]):
if not np.all(arr[iy, ix] == 255):
ret[iy, ix] = np.array([0, 0, 0, 255])
return ret
def _matt_pitkin(arr):
ret = np.copy(arr)
b = (ret[:, :] == np.array([255, 255, 255, 255])).all(axis=2)
ret[~b] = np.array([0, 0, 0, 255])
return ret
def _paime(arr):
ret = np.copy(arr)
mask = (ret != 255).any(axis=-1)
ret[mask] = [0, 0, 0, 255]
return ret
def _roman_perekhrest(arr):
ret = np.copy(arr)
return np.where((ret != [255, 255, 255, 255]).any(-1)[:, :, None], [0, 0, 0, 255], ret)
FUNCS = (
_user16971617,
_matt_pitkin,
_paime,
_roman_perekhrest,
)
def test_acc():
print("\nACCURACY")
arr = np.array((
(
(255, 255, 255, 255),
(255, 0, 0, 0),
(255, 255, 0, 0),
(255, 0, 255, 0),
(255, 0, 0, 255),
(0, 255, 255, 0),
(0, 255, 0, 255),
(0, 0, 255, 255),
), (
(1, 2, 3, 4),
(0, 255, 0, 0),
(1, 2, 255, 0),
(1, 0, 2, 255),
(255, 255, 255, 0),
(255, 255, 0, 255),
(255, 0, 255, 255),
(0, 255, 255, 255),
)), dtype=np.uint8)
exp = np.array((((0, 0, 0, 255),) * arr.shape[1],) * arr.shape[0], dtype=np.uint8)
exp[0][0] = (255, 255, 255, 255)
print("Expected result:\n{:}\n".format(exp))
for func in FUNCS:
print("Probing function: {:s}".format(func.__name__))
ret = func(arr)
if not np.array_equal(exp, ret):
print("DIFFERENT result:\n{:}".format(ret))
def test_perf():
print("\nPERFORMANCE")
arr = np.random.randint(low=0, high = 255, size=(100, 100, 4), dtype=np.uint8)
res = []
for func in FUNCS:
res.append((func.__name__, timeit.timeit(lambda: func(arr), number=200)))
print("Function results:")
for n, t in sorted(res, key=lambda arg: arg[1], reverse=True):
print("Function {:s}: {:.3f} seconds".format(n, t))
def main(*argv):
test_acc()
test_perf()
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.\n")
sys.exit(rc)
Output:
>
> (py_pc064_03.10_test1_pycoral) [cfati@cfati-5510-0:/mnt/e/Work/Dev/StackExchange/StackOverflow/q075659888]> python ./code00.py
> Python 3.10.7 (main, Sep 7 2022, 15:22:19) [GCC 9.4.0] 064bit on linux
>
>
> ACCURACY
> Expected result:
> [[[255 255 255 255]
> [ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]]
>
> [[ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]
> [ 0 0 0 255]]]
>
> Probing function: _user16971617
> Probing function: _matt_pitkin
> Probing function: _paime
> Probing function: _roman_perekhrest
>
> PERFORMANCE
> Function results:
> Function _user16971617: 17.288 seconds
> Function _matt_pitkin: 0.123 seconds
> Function _roman_perekhrest: 0.109 seconds
> Function _paime: 0.081 seconds
>
> Done.
>
Notes:
-
Original approach is hundreds of times slower than the other 3 (which make use of NumPy's vectorized routines) which are pretty close to each other (although @paime's seems to be the fastest)
-
In order to keep variants consistent (with the 1<sup>st</sup> one), the faster ones also copy the array. That translates to a (small) penalty, meaning that they will perform slightly better if modifying the array in place
答案5
得分: 0
你可以使用 numpy.where
来根据条件应用数值:
s = np.where((s != [255, 255, 255, 255]).any(-1)[:, :, None], [0, 0, 0, 255], s)
英文:
You can apply numpy.where
to apply values depending on condition:
s = np.where((s != [255,255,255,255]).any(-1)[:,:,None], [0, 0, 0, 255], s)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论