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

zysjyyx4  于 2023-03-08  发布在  其他
关注(0)|答案(5)|浏览(208)

假设我有一个3D numpy数组(100*100*4),我想将非255向量([255,255,255,255])转换为[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)

目前这是我的方法,但似乎很慢,有没有更好的方法?任何帮助都表示感谢。

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
nuypyhwy

nuypyhwy1#

您可以执行以下操作:

# 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])
goqiplq2

goqiplq22#

使用broadcasting和布尔数组索引:

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]]])
1tu0hz3e

1tu0hz3e3#

您可以根据条件应用numpy.where来应用值:

s = np.where((s != [255,255,255,255]).any(-1)[:,:,None], [0, 0, 0, 255], s)
iyzzxitl

iyzzxitl4#

我使用了一个较小的数组,其中值的变化较小,这样您就可以轻松地检查我的结果。
这里的第一个想法是调整数据数组的形状,使每一行都是您要针对(255, 255, 255, 255)进行测试的4元组之一,第二个想法是使用.all(axis=1)方法(thank you mozway)获得一个可用于索引视图的1D布尔数组。

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]:
2nc8po8w

2nc8po8w5#

列表[NumPy]:例行公事。
这更像是一个练习:我想做一个现有的变体之间的比较(从问题和答案)。

  • 代码00.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)
    • 输出**:
(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.
    • 备注**:
  • 原始方法比其他3种方法(使用 * NumPy * 的矢量化例程)慢数百倍,这3种方法彼此非常接近(尽管@paime的似乎是最快的)
  • 为了保持变体的一致性(与第一个一致),速度较快的变体也会复制数组,这意味着如果在适当的位置修改数组,它们的性能会稍好一些

相关问题