@egeres method of using using the distance to a target color to create an alpha value is really neat and creates a much nicer result. Here it is using numpy:
import numpy as np
import matplotlib.pyplot as plt
def color_to_alpha(im, target_color):
alpha = np.max(
[
np.abs(im[..., 0] - target_color[0]),
np.abs(im[..., 1] - target_color[1]),
np.abs(im[..., 2] - target_color[2]),
],
axis=0,
)
ny, nx, _ = im.shape
im_rgba = np.zeros((ny, nx, 4), dtype=im.dtype)
for i in range(3):
im_rgba[..., i] = im[..., i]
im_rgba[..., 3] = alpha
return im_rgba
target_color = (0.0, 0.0, 0.0)
im = plt.imread("img.png")
im_rgba = color_to_alpha(im, target_color)
For completeness I've included a comparison with the mask-based version applied to the matplotlib logo below:
from pathlib import Path
import matplotlib.pyplot as pl
import numpy as np
def color_to_alpha(im, alpha_color):
alpha = np.max(
[
np.abs(im[..., 0] - alpha_color[0]),
np.abs(im[..., 1] - alpha_color[1]),
np.abs(im[..., 2] - alpha_color[2]),
],
axis=0,
)
ny, nx, _ = im.shape
im_rgba = np.zeros((ny, nx, 4), dtype=im.dtype)
for i in range(3):
im_rgba[..., i] = im[..., i]
im_rgba[..., 3] = alpha
return im_rgba
def color_to_alpha_mask(im, alpha_color):
mask = (im[..., :3] == alpha_color).all(axis=2)
alpha = np.where(mask, 0, 255)
ny, nx, _ = im.shape
im_rgba = np.zeros((ny, nx, 4), dtype=im.dtype)
im_rgba[..., :3] = im
im_rgba[..., -1] = alpha
return im_rgba
# load example from images included with matplotlib
fn_img = Path(plt.__file__).parent / "mpl-data" / "images" / "matplotlib_large.png"
im = plt.imread(fn_img)[..., :3] # get rid of alpha channel already in image
target_color = [1.0, 1.0, 1.0]
im_rgba = color_to_alpha(im, target_color)
im_rgba_masked = color_to_alpha_mask(im, target_color)
fig, axes = plt.subplots(ncols=3, figsize=(12, 4))
[ax.set_facecolor("lightblue") for ax in axes]
axes[0].imshow(im)
axes[0].set_title("original")
axes[1].imshow(im_rgba)
axes[1].set_title("using distance to color")
axes[2].imshow(im_rgba_masked)
axes[2].set_title("mask on color")