为什么使用PIL获得颜色量化伪像?

问题描述 投票:0回答:1

我正在使用程序包gif here将matplotlib图串接到gif中。但是,由于颜色的原因,图像中出现了伪像。我不知道正式的词,而是“下采样”。

原始图看起来像这样:example_image

平滑色彩一致的颜色变化。

但是,当我使用该程序包转换为gif时,我得到了:

gif_output

希望您能看到在颜色中发生的量化/下采样。

实际运行的代码非常短(我添加了一行代码,试图使颜色校正正常工作,但是没有用,上载的gif就是这种校正,但是看起来与它相同在做之前)

def frame(func):
    """
    Decorator for a matplotlib plot function.

    Example:
    ```
    @gif.frame
    def plot(x, y):
        plt.figure(figsize=(5, 5))
        plt.scatter(x, y)
        plt.xlim((0, 100))
        plt.ylim((0, 100))
    ```
    """

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        buffer = io.BytesIO()
        func(*args, **kwargs)
        plt.savefig(buffer, format="png")
        buffer.seek(0)
        image = Image.open(buffer)
        ### ADDED IN AFTER THE FACT ###
        image = image.convert('RGBA', palette=Image.ADAPTIVE)
        ### ### ### ### ### ### ### ###
        plt.close()
        return image

    return wrapper


def save(frames, path, duration=100):
    """
    Save decorated frames to an animated gif.

    - frames (list): collection of frames built with the frame decorator
    - path (str): filename with relative or absolute path
    - duration (int): milliseconds between frames
    """
    frames[0].save(
        path,
        save_all=True,
        append_images=frames[1:],
        optimize=True,
        duration=duration,
        loop=0,
    )

任何想法,我可以使用PIL包做什么,当写出gif时,它将保持色彩图的连续性吗? dpi /文件大小是否必须很大才能保持这一点?

这里是生成图的代码,以防万一:

@gif.frame
def plot_signal_and_ft(t, t_step):
    ### Setup ###
    dims = (501,501)
    x = np.linspace(0,100,dims[0])
    y = np.linspace(0,100,dims[1])
    u = float(100/dims[0])
    cen = [50.0, 50.0]
    xx, yy = np.meshgrid(x, y, sparse=True)
    signal = np.zeros(dims)
    r = 25*(0.003125*np.exp(5.66643*(t/t_step))+0.046875)
    offset = 1.0 + ((25.0-1.0)/(t_step))*t
    pos1 = np.sqrt((xx-cen[0]+offset)*(xx-cen[0]+offset)+(yy-cen[1])*(yy-cen[1]))
    pos2 = np.sqrt((xx-cen[0]-offset)*(xx-cen[0]-offset)+(yy-cen[1])*(yy-cen[1]))
    sigma, mu = r, 0
    signal += np.exp(-( (pos1-mu)**2 / ( 2.0 * sigma**2 ) ) )
    signal += np.exp(-( (pos2-mu)**2 / ( 2.0 * sigma**2 ) ) )

    # FT
    F = np.fft.fftshift(np.fft.fft2(signal))
    max_real = 10.0
    max_imag = 3.0

    ### PLOTTING ###
    f, ax = plt.subplots(figsize=(6, 6), nrows=2, ncols=2, dpi=100)
    # SIGNAL 
    sig = ax[0,0].imshow(signal, cmap = plt.cm.Greys, vmin=0, vmax=1, origin="lower")
    ax[0,0].axis("off")
    ax[0,0].set_title("Signal", fontsize="medium", fontweight="bold",fontfamily="serif")
    divider = make_axes_locatable(ax[0,0])
    cax = divider.append_axes("right", size="5%", pad=0.1)
    cbar = f.colorbar(sig, cax=cax)
    cbar.set_ticklabels(["0.0", "0.2", "0.4", "0.6", "0.8", "1.0"])
    # REAL
    real = ax[1,0].imshow(np.real(F), cmap=mpl.cm.RdBu, clim=(-max_real, max_real), 
                        norm=MidpointNormalize(midpoint=0.0, vmin=-max_real, vmax=max_real), 
                        origin="lower")
    ax[1,0].axis("off")
    ax[1,0].set_title("R[FT]", fontsize="medium", fontweight="bold",fontfamily="serif")
    divider = make_axes_locatable(ax[1,0])
    cax = divider.append_axes("right", size="5%", pad=0.1)
    f.colorbar(real, cax=cax)
    # IMAG
    imag = ax[1,1].imshow(np.imag(F), cmap=mpl.cm.PiYG, clim=(-max_imag, max_imag), 
                        norm=MidpointNormalize(midpoint=0.0, vmin=-max_imag, vmax=max_imag), 
                        origin="lower")
    ax[1,1].axis("off")
    ax[1,1].set_title("Im[FT]", fontsize="medium", fontweight="bold",fontfamily="serif")
    divider = make_axes_locatable(ax[1,1])
    cax = divider.append_axes("right", size="5%", pad=0.1)
    f.colorbar(imag, cax=cax)
    # MAGNITUDE
    mag = ax[0,1].imshow(np.absolute(F), cmap=plt.cm.hot, clim=(0, max_real), 
                     norm=MidpointNormalize(midpoint=max_real/2, vmin=0, vmax=max_real), 
                     origin="lower")
    ax[0,1].axis("off")
    ax[0,1].set_title("||FT||", fontsize="medium", fontweight="bold",fontfamily="serif")
    divider = make_axes_locatable(ax[0,1])
    cax = divider.append_axes("right", size="5%", pad=0.1)
    f.colorbar(mag, cax=cax)

    plt.tight_layout()

t_steps = 10
frames = []
traj = [t for t in range(t_steps)] + [t_steps-t for t in range(t_steps)]
for t in traj:
    frame = plot_signal_and_ft(t, t_steps)
    frames.append(frame)

gif.save(frames, "./test_double.gif", duration=150)
python python-3.x matplotlib python-imaging-library gif
1个回答
1
投票

我什至都不了解您的一半代码,因此,如果我的回答有任何错误,我深表歉意,但是我对数字图像有很好的理解。

不幸的是,gif格式仅支持256种颜色变化,这将永远不会产生像样的渐变。您可以探索一些选项,例如图像抖动(在pilimage.converthttps://pillow.readthedocs.io/en/stable/reference/Image.html中可用),但是在执行.gif时,您大多会遇到这种质量问题。存在一些复杂的解决方案,可以在.gif中获取更多颜色,但是尺寸会增加很多,而这些解决方案都超出了我的想象,因此我将让您进行研究(请阅读注释:https://techterms.com/definition/gif)。

我建议尝试查看您是否可以在项目中使用其他格式。但是同样,我什至不知道你到底在做什么。

© www.soinside.com 2019 - 2024. All rights reserved.