pythonmatplotlibtransparent

How to create transparent waveform in python


I can’t figure out how to make the graph transparent. I have a waveform graph from audio and fill the space with a background, I’m trying, but the background still appears on the graph.

def generate_waveform_image(save_dir, audio_file, output_filename, color='white', alpha=0, figsize=(12, 2), dpi=75):
        fig, ax = plt.subplots(figsize=figsize, dpi=dpi, frameon=False)
        plt.subplots_adjust(left=0, right=1, bottom=0, top=1)
        samples, sr = librosa.load(audio_file, sr=None, mono=True)
        times = np.arange(len(samples)) / sr
        ax.plot(times, samples, color=color, alpha=alpha, linewidth=0.1)
        ax.margins(0, 0)
        ax.axis('off')
        plt.savefig(os.path.join(save_dir, f'{output_filename}.png'), transparent=True, bbox_inches='tight',
                    pad_inches=0)

I tried everything and still_between, the background fills the entire image, but I need it to be like this:

enter image description here

ax.fill_between(times, -1, 1, color='gray', alpha=1)

Solution

  • plt.savefig(..., transparent=True) makes the background transparent. But you seem to want to have the foreground transparent.

    Here is an approach:

    import matplotlib; matplotlib.use('agg')
    
    import matplotlib.pyplot as plt
    from PIL import Image
    import numpy as np
    
    fig, ax = plt.subplots(figsize=(12, 2))
    
    values = np.random.randn(5000) * np.random.randn(5000).cumsum()
    ax.plot(values, color='black', lw=1)
    ax.margins(x=0)  # no margins left and right
    ax.axis('off')  # hide the axes
    fig.patch.set_alpha(0)  # transparent
    plt.subplots_adjust(bottom=0, left=0, top=1, right=1)  # remove padding around the main plot
    fig.canvas.draw()  # "draw" is needed to fill in the pixels
    
    buffer, (width, height) = fig.canvas.print_to_buffer()
    data = np.array(np.frombuffer(buffer, np.uint8).reshape((height, width, 4)))
    
    data[:, :, 3] = 255 - data[:, :, 3]  # invert the transparency of all pixels
    data[:, :, :3] = 0  # make all pixels black while keeping the new transparency
    
    img = Image.fromarray(data)
    img.save("transparent_waveform.png")
    

    This is how the image looks inside Gimp:

    matplotlib save image with transparent foreground