2009-09-20 9 views
4

OpenCV prend-il en charge le canal alpha? Ou est-il un moyen de travailler avec png transparent? J'ai besoin de fusionner deux images, où la première est l'arrière-plan et la seconde est l'image qui a été tournée par cvWarpAffine. Je peux le faire en fusionnant les pixels un par un et omettre des pixels avec une certaine valeur, que je définis dans cvScalar dans cvWarpAffine. Cependant, je ne pense pas que cela soit une solution. Merci pour vos suggestionsCanal alpha dans OpenCV

+0

Ceci est l'une des questions les plus anciennes sur ce sujet et attire toujours de nombreux visiteurs. Voici une [réponse plus récente] (https://stackoverflow.com/a/49180468/176769) si vous cherchez du code. – karlphillip

Répondre

8

OpenCV ne prend pas en charge le canal alpha, seul le masquage. Si vous voulez lire en PNG avec alpha, utilisez ImageMagick premier à extraire le canal alpha:

convert input.png -channel Alpha -negate -separate input-mask.png 

Puis, en OpenCV vous pouvez faire qqch comme ceci:

Mat_<float> mask = imread("input-mask.png", 0); 
threshold(mask, mask, 254., 1., THRESH_BINARY); 

... pour obtenir un vrai masque (utilisable comme matrice de masque dans les opérations OpenCV). Ou vous pouvez l'utiliser dans vos propres opérations sans le seuillage. Pour appliquer le masque, il peut aussi être une bonne idée de l'étendre à trois canaux:

std::vector<Mat> marr(3, mask); 
Mat_<Vec<float, 3> > maskRGB; 
merge(marr, maskRGB); 

Après que vous pouvez le tester comme ceci:

imshow("Target", target); 
imshow("Mask", mask*255); 
imshow("Applied", target.mul(maskRGB)); 
waitKey(); 

Note: Ceci est du code OpenCV 2.0 .

2

Voici un script bash que j'ai assemblé pour effectuer la conversion ImageMagick donnée par ypnos sur tous les fichiers png d'un répertoire. Vous pouvez le rendre récursif en remplaçant le * dans la troisième ligne par une commande find.

#!/bin/bash 

for file in * 
do 
    if [[ $file =~ (.+)-mask\.png ]]; then 
     echo "Ignoring mask $file" 
    elif [[ $file =~ (.+)\.png ]]; then 
     echo "Generating mask for $file" 
     basefn=${BASH_REMATCH[1]} 
     convert "$basefn.png" -channel Alpha -negate -separate "$basefn-mask.png" 
    fi 
done 
+0

Une excellente contribution! – ypnos

0

entrée: cam_frame-fond, media_frame-plan, media_frame_alpha - alpha. Sortie: mélangé par alpha transparent. Si media_frame_alpha est IPL_DEPTH_8U, utilisez "cv :: merge", car les matrices doivent avoir une dimension, une taille et des canaux égaux. Travaillez vite si opencv est construit avec sse ou avx. Et plus rapide si vous utilisez cv: GpuMat, vous devez avoir le support nvidia cuda et construire opencv avec cuda.

inline cv::Mat frame_mix_alpha(cv::Mat &cam_frame, 
cv::Mat &media_frame, 
cv::Mat &media_frame_alpha) 
{ 
    Mat suba = media_frame_alpha; 
    //Mat alpha = cvCreateImage(media_frame_alpha.size(), IPL_DEPTH_8U, 1); 
    //cvtColor(media_frame_alpha, alpha, CV_BGR2GRAY); 

    //Mat suba; 
    //Mat rgba[3] = { alpha, alpha, alpha }; 
    //merge(rgba, 3, suba); 

    Mat subb = ~suba; 

    //Mat mincam = min(cam_frame, suba); 
    //Mat minmedia = min(media_frame, subb); 
    //Mat result = (cam_frame - mincam) + (media_frame - minmedia); 
    Mat result = (cam_frame - suba) + (media_frame - subb); 

    return result; 
}