将numpy数组转换为二进制数组在numpy中

huangapple go评论71阅读模式
英文:

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 &quot;hit&quot;
         ...: 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(&quot;\nACCURACY&quot;)
    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(&quot;Expected result:\n{:}\n&quot;.format(exp))
    for func in FUNCS:
        print(&quot;Probing function: {:s}&quot;.format(func.__name__))
        ret = func(arr)
        if not np.array_equal(exp, ret):
            print(&quot;DIFFERENT result:\n{:}&quot;.format(ret))


def test_perf():
    print(&quot;\nPERFORMANCE&quot;)
    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(&quot;Function results:&quot;)
    for n, t in sorted(res, key=lambda arg: arg[1], reverse=True):
        print(&quot;Function {:s}: {:.3f} seconds&quot;.format(n, t))


def main(*argv):
    test_acc()
    test_perf()


if __name__ == &quot;__main__&quot;:
    print(&quot;Python {:s} {:03d}bit on {:s}\n&quot;.format(&quot; &quot;.join(elem.strip() for elem in sys.version.split(&quot;\n&quot;)),
                                                   64 if sys.maxsize &gt; 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print(&quot;\nDone.\n&quot;)
    sys.exit(rc)

Output:

>
&gt; (py_pc064_03.10_test1_pycoral) [cfati@cfati-5510-0:/mnt/e/Work/Dev/StackExchange/StackOverflow/q075659888]&gt; python ./code00.py
&gt; Python 3.10.7 (main, Sep 7 2022, 15:22:19) [GCC 9.4.0] 064bit on linux
&gt;
&gt;
&gt; ACCURACY
&gt; Expected result:
&gt; [[[255 255 255 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]]
&gt;
&gt; [[ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]
&gt; [ 0 0 0 255]]]
&gt;
&gt; Probing function: _user16971617
&gt; Probing function: _matt_pitkin
&gt; Probing function: _paime
&gt; Probing function: _roman_perekhrest
&gt;
&gt; PERFORMANCE
&gt; Function results:
&gt; Function _user16971617: 17.288 seconds
&gt; Function _matt_pitkin: 0.123 seconds
&gt; Function _roman_perekhrest: 0.109 seconds
&gt; Function _paime: 0.081 seconds
&gt;
&gt; Done.
&gt;

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)

huangapple
  • 本文由 发表于 2023年3月7日 17:05:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75659888.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定