Speichern von transparentem PNG als JPEG auf weißem Hintergrund

Nov 26 2020

Angenommen, ich habe ein BGRA-Bild als numpyArray, das ungefähr so aussieht:

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

Das sieht ziemlich einfach aus - drei Farbkanäle + ein Alpha, das die Transparenz der Pixel steuert. Das Speichern dieses Numpy-Arrays in einem PNG-Format führt zu einem Bild, das halbtransparent ist, wie es sein sollte.

Beim Speichern als JPEG wird der Alphakanal jedoch vollständig gelöscht und alle Pixel sind vollständig undurchsichtig.

Da JPEG keine Alpha-Transparenz unterstützt, möchte ich, dass mein halbtransparentes Bild (das obige Numpy-Array) stattdessen auf einem weißen Hintergrund gespeichert wird. Auf diese Weise sieht es so aus, als wären die Pixel immer noch halbtransparent.

Wie kann ich das halbtransparente Numpy-Array auf einem vollständig weißen Hintergrund überlagern? Ich benutze hauptsächlich Numpy und OpenCV.

Antworten

2 MarkSetchell Nov 27 2020 at 10:44

Ich denke, Sie suchen mehr nach abgestufter Alpha-Mischung als nach der einfacheren Alpha-Schwelle, die Freds Antwort gut demonstriert.

Zu Testzwecken habe ich ein Beispielbild mit einem Alpha-Gradienten in der Mitte erstellt. Hier ist es wie ein normales Bild und über einem Schachbrett zusammengesetzt, um die Transparenz zu zeigen, wie es Photoshop tut:

Um Alpha zu mischen, verwenden Sie die Formel:

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

Dabei sind die Werte alle Floats, skaliert im Bereich 0..1


Der Code zum Überblenden von schwarzem und dann weißem Hintergrund lautet wie folgt:

#!/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)

Das gibt dies über schwarz:

Und das über Weiß:

Schlüsselwörter : Bildverarbeitung, Python, OpenCV, Alpha, Alpha-Blending, Alpha-Compositing, Overlay.

1 fmw42 Nov 27 2020 at 06:16

In Python OpenCV Numpy können Sie den Alphakanal vom Bild trennen. Also, wenn imgA das Bild mit Alpha-Kanal ist. Trennen Sie dann das RGB-Bild (img) und den Alphakanal (alpha).

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

Stellen Sie dann die Farbe von img auf Weiß ein, wobei das Alpha schwarz ist

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