V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
XIVN1987
V2EX  ›  Python

求教 numpy 数组运算简化,去掉 for 循环。。

  •  
  •   XIVN1987 · 301 天前 · 1793 次点击
    这是一个创建于 301 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码如下,中间那三行两层 for 循环迭代的代码,是否可以去掉 for 循环??感谢指点。。

    def jpeg2png(path, name, mask=(255, 255, 255), limit=32):
        img = Image.open(path)
        
        arr = np.array(img.convert('RGBA'))
    
        for i in range(arr.shape[0]):
            for j in range(arr.shape[1]):
                arr[i,j,3] = 0x00 if np.all(np.abs(arr[i,j,:3] - mask) < limit) else 0xFF      # alhpa channel
    
        Image.fromarray(arr).save(f'{name}.png')
    
    4 条回复    2024-02-01 19:05:17 +08:00
    xiaotang3011
        1
    xiaotang3011  
       301 天前
    np.where
    holy5pb
        2
    holy5pb  
       301 天前   ❤️ 1
    ```python
    def jpeg2png(path, name, mask=(255, 255, 255), limit=32):
    img = Image.open(path)

    arr = np.array(img.convert('RGBA'))

    # np.where
    condition = np.all(np.abs(arr[:, :, :3] - mask) < limit, axis=2)
    arr[:, :, 3] = np.where(condition, 0x00, 0xFF) # alpha channel

    Image.fromarray(arr).save(f'{name}.png')
    ```
    XIVN1987
        3
    XIVN1987  
    OP
       301 天前
    @holy5pb
    试过了,,可以,,感谢大神。。
    sampeng
        4
    sampeng  
       301 天前
    是的,可以用 NumPy 的广播功能来去除 for 循环。NumPy 是一个强大的科学计算库,它允许你对整个数组或矩阵进行快速操作,而不需要显式地编写循环。在你的例子中,你可以使用 NumPy 的布尔索引来直接设置 alpha 通道的值。

    下面是一个如何用 NumPy 的广播和布尔索引来替换掉 for 循环的例子:

    from PIL import Image
    import numpy as np

    def jpeg2png(path, name, mask=(255, 255, 255), limit=32):
    img = Image.open(path)

    arr = np.array(img.convert('RGBA'))

    # 创建一个布尔掩码,其中接近指定 mask 颜色的像素为 True
    mask_arr = np.all(np.abs(arr[:, :, :3] - mask) < limit, axis=-1)

    # 设置 alpha 通道为 0 (透明) 在 mask_arr 为 True 的地方,否则设置为 255 (不透明)
    arr[:, :, 3] = np.where(mask_arr, 0x00, 0xFF)

    Image.fromarray(arr).save(f'{name}.png')

    # 使用函数转换图片
    jpeg2png('input.jpg', 'output')
    在这个改写后的函数中,np.where 函数用于选择性地替换数组中的元素。mask_arr 是一个与输入图像同样形状的布尔数组,它标志了所有需要被设置为透明的像素。np.where 根据 mask_arr 的值来设置 arr 的 alpha 通道,如果 mask_arr 为 True 则设置为 0x00 ,否则设置为 0xFF 。

    这种方法比双层 for 循环更有效,因为它利用了 NumPy 的内部优化来处理数组操作,从而可以显著提升性能,特别是在处理大图像时。


    善用工具。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3098 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 14:43 · PVG 22:43 · LAX 06:43 · JFK 09:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.