V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
ch2
V2EX  ›  问与答

如何使用 opencv 为图片添加“运动模糊”效果?

  •  
  •   ch2 · 2022-05-15 13:44:12 +08:00 · 723 次点击
    这是一个创建于 683 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求:使用 python 的 opencv 实现 adobe"方向模糊"同款效果,同时需要保留 png 的 alpha 通道
    20220515133448
    已查阅到的的 motion blur 实现会使得带 alpha 通道的图片异常,生成的产物是一片白的

    # -*- coding: utf-8 -*-
    import numpy as np
    import cv2
    from PIL import Image
    
    def motion_blur(image, degree=3, angle=90):
        image=image.convert("RGB")
        array=np.asarray(image)
        image=cv2.cvtColor(array,cv2.COLOR_RGB2BGR)
        image = np.array(image)
        M = cv2.getRotationMatrix2D((degree / 2, degree / 2), angle, 1)
        motion_blur_kernel = np.diag(np.ones(degree))
        motion_blur_kernel = cv2.warpAffine(motion_blur_kernel, M, (degree, degree))
        motion_blur_kernel = motion_blur_kernel / degree
        blurred = cv2.filter2D(image, -1, motion_blur_kernel)
        cv2.normalize(blurred, blurred, 0, 255, cv2.NORM_MINMAX)
        blurred = np.array(blurred, dtype=np.uint8)
        blurred=Image.fromarray(cv2.cvtColor(blurred, cv2.COLOR_BGR2RGB),mode="RGB")
        return blurred
    

    本人不熟悉图像处理的算法,想请教一下如何改进完善这个算法使其支持带有 alpha 通道的 png 图片?

    3 条回复    2022-05-16 16:21:53 +08:00
    paopjian
        1
    paopjian  
       2022-05-15 14:29:36 +08:00
    PNG 是四通道图片啊,你第一步就把 alpha 给抹了
    jaredyam
        2
    jaredyam  
       2022-05-16 10:01:51 +08:00
    你这个函数包含两个部分,一部分是图像简单变换(预处理、后处理),一部分是函数核心(构造滤波器并滤波),我觉得你这个函数可以再拆。简单来看 cv2.filter2D 是逐通道(多通道可能有并行加速?)的,所以你可以:
    1. 先拆出 alpha 处理完并回去;
    2. 逐通道遍历滤波,只滤需要的通道,从而可以一直保持 alpha ;

    至于你说的「一片白」我不是很清楚。
    ch2
        3
    ch2  
    OP
       2022-05-16 16:21:53 +08:00
    最后使用了 pillow 的 ImageFilter 定义了一个卷积核,实现了 5*5 、角度为 90°的方向模糊
    支持 png 的 alpha 通道
    from PIL import Image, ImageFilter
    class MOTION_BLUR(ImageFilter.BuiltinFilter):
    name = "Motion_Blur"
    # fmt: off
    filterargs = (5, 5), 5, 0, (
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    1, 1, 1, 1, 1,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    )
    # fmt: on
    img = Image.new('RGBA', (800, 600), (255, 255, 255, 0))
    img.filter(MOTION_BLUR)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3572 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 04:57 · PVG 12:57 · LAX 21:57 · JFK 00:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.