web-dev-qa-db-fra.com

Comment charger des images png avec 4 canaux?

J'ai essayé de charger des fichiers .png avec un canal de transparence (RGB et Alph) sans succès. Il semble que openCV retire le 4ème canal de l'image. Existe-t-il une méthode pour charger l'image avec les 4 canaux complets, y compris le canal alpha, même si je devais modifier le code source d'OpenCV et le reconstruire?

38
Mohammad Elwakeel

Si vous utilisez OpenCV 2 ou OpenCV 3, vous devez utiliser les drapeaux IMREAD_ * (comme mentionné à ici ).

C++

using namespace cv;
Mat image = imread("image.png", IMREAD_UNCHANGED);

Python

import cv2
im = cv2.imread("image.png", cv2.IMREAD_UNCHANGED)
61
Satya Mallick

Selon la documentation , OpenCV prend en charge le canal alpha sur les PNG.

Appelez simplement la fonction imread en utilisant CV_LOAD_IMAGE_UNCHANGED comme indicateurs comme ceci:

cvLoadImage("file.png", CV_LOAD_IMAGE_UNCHANGED)
14

La bonne façon de lire un PNG transparent est d'utiliser le 4ème canal comme canal alpha. La plupart du temps, on veut un fond blanc, si c'est le cas, le code ci-dessous peut être utilisé pour la composition alpha.

def read_transparent_png(filename):
    image_4channel = cv2.imread(filename, cv2.IMREAD_UNCHANGED)
    alpha_channel = image_4channel[:,:,3]
    rgb_channels = image_4channel[:,:,:3]

    # White Background Image
    white_background_image = np.ones_like(rgb_channels, dtype=np.uint8) * 255

    # Alpha factor
    alpha_factor = alpha_channel[:,:,np.newaxis].astype(np.float32) / 255.0
    alpha_factor = np.concatenate((alpha_factor,alpha_factor,alpha_factor), axis=2)

    # Transparent Image Rendered on White Background
    base = rgb_channels.astype(np.float32) * alpha_factor
    white = white_background_image.astype(np.float32) * (1 - alpha_factor)
    final_image = base + white
    return final_image.astype(np.uint8)

Un blog détaillé à ce sujet est ici ici .

12
Nikhil

La meilleure façon possible de charger une image png avec les 4 canaux est;

img= cv2.imread('imagepath.jpg',negative value)

Selon la documentation openCV,
Si la valeur de Flag est,
1) = 0 Retourne une image en niveaux de gris.
2) <0 Retourne l'image chargée telle quelle (avec canal alpha).

1
0xPrateek

Si vous voulez dessiner cette image transparente sur une autre image, ouvrez votre image comme répondu par @ satya-mallick, puis utilisez cette méthode:

/**
 * @brief Draws a transparent image over a frame Mat.
 * 
 * @param frame the frame where the transparent image will be drawn
 * @param transp the Mat image with transparency, read from a PNG image, with the IMREAD_UNCHANGED flag
 * @param xPos x position of the frame image where the image will start.
 * @param yPos y position of the frame image where the image will start.
 */
void drawTransparency(Mat frame, Mat transp, int xPos, int yPos) {
    Mat mask;
    vector<Mat> layers;

    split(transp, layers); // seperate channels
    Mat rgb[3] = { layers[0],layers[1],layers[2] };
    mask = layers[3]; // png's alpha channel used as mask
    merge(rgb, 3, transp);  // put together the RGB channels, now transp insn't transparent 
    transp.copyTo(frame.rowRange(yPos, yPos + transp.rows).colRange(xPos, xPos + transp.cols), mask);
}
1
Derzu