Enregistrement PNG transparent au format JPEG sur fond blanc

Nov 26 2020

Disons que j'ai une image BGRA en tant que numpytableau qui ressemble à peu près à ceci:

[[[233 228 230   128]
  [233 228 230   128]
  [233 228 230   0]
  ...
  [164 160 159   65]
  [199 197 196   65]
  [255 255 254   120]]

Cela semble assez simple - trois canaux de couleur + un alpha qui contrôle la transparence des pixels. L'enregistrement de ce tableau numpy au format PNG donne une image semi-transparente comme elle se doit.

Cependant, lors de l'enregistrement au format JPEG, le canal alpha est complètement supprimé et tous les pixels sont complètement opaques.

Comme JPEG ne prend pas en charge la transparence alpha, je voudrais plutôt que mon image semi-transparente (le tableau numpy ci-dessus) soit enregistrée sur un fond blanc. De cette façon, il semblerait que les pixels soient toujours semi-transparents.

Comment superposer le tableau numpy semi-transparent sur un fond entièrement blanc? J'utilise principalement numpy et OpenCV.

Réponses

2 MarkSetchell Nov 27 2020 at 10:44

Je pense que vous recherchez plus un mélange alpha gradué que le seuil alpha plus simple que la réponse de Fred démontre bien.

J'ai fait un exemple d'image avec un dégradé alpha au milieu à des fins de test. Ici, c'est comme une image normale et composée sur un damier pour montrer la transparence comme le fait Photoshop:

Pour faire un mélange alpha, vous utilisez la formule:

result = alpha * Foreground + (1-alpha)*Background

où les valeurs sont tous des flottants mis à l'échelle sur la plage 0..1


Le code de fusion sur fond noir puis blanc est le suivant:

#!/usr/bin/env python3

import cv2
import numpy as np

# Load image, including gradient alpha layer
im = cv2.imread('GradientAlpha.png', cv2.IMREAD_UNCHANGED)

# Separate BGR channels from A, make everything float in range 0..1
BGR = im[...,0:3].astype(np.float)/255
A   = im[...,3].astype(np.float)/255

# First, composite image over black background using:
# result = alpha * Foreground + (1-alpha)*Background
bg  = np.zeros_like(BGR).astype(np.float)     # black background
fg  = A[...,np.newaxis]*BGR                   # new alpha-scaled foreground
bg = (1-A[...,np.newaxis])*bg                 # new alpha-scaled background
res = cv2.add(fg, bg)                         # sum of the parts
res = (res*255).astype(np.uint8)              # scaled back up
cv2.imwrite('OverBlack.png', res)

# Now, composite image over white background
bg  = np.zeros_like(BGR).astype(np.float)+1   # white background
fg  = A[...,np.newaxis]*BGR                   # new alpha-scaled foreground
bg = (1-A[...,np.newaxis])*bg                 # new alpha-scaled background
res = cv2.add(fg, bg)                         # sum of the parts
res = (res*255).astype(np.uint8)              # scaled back up
cv2.imwrite('OverWhite.png', res)

Cela donne ceci sur le noir:

Et ceci sur blanc:

Mots clés : Traitement d'image, Python, OpenCV, alpha, mélange alpha, composition alpha, superposition.

1 fmw42 Nov 27 2020 at 06:16

Dans Python OpenCV Numpy, vous pouvez séparer le canal alpha de l'image. Donc, si imgA est l'image avec canal alpha. Ensuite, séparez l'image RVB (img) et le canal alpha (alpha)

img = imgA[:,:,0:3]
alpha = imgA[:,:,3]

Ensuite, définissez la couleur de img sur blanc où l'alpha est noir

img[alpha == 0] = (255,255,255)