2017-07-16 3 views
1

Salut ce que j'ai est un couple de Mat que je veux superposer (dans un ordre personnalisé). Le Mat contient des polygones opencv (ce qui signifie beaucoup de transparence). Ce Mat j'ai besoin de superposer/fusionner. Mais pas avec l'alpha classique qui se mélange plus avec une opacité à 100% mais avec de la transparence.OpenCv overlay deux Mat (dessins pas images) avec transparence

Ceci est un simple exemple de code de ce que je veux fusionner.

Mat m1, m2; 
m1.create(Point{ 100,100 }, CV_8UC4); 
m2.create(Point{ 100,100 }, CV_8UC4); 

cv::polylines(m1, std::vector<Point>{ Point{ 2,20 },Point{ 20,40 } }, true, Scalar(6, 6, 255)); 
cv::polylines(m2, std::vector<Point>{Point{ 100,100 }, Point{ 0,0 } }, true, Scalar(192, 112, 0)); 

S'il vous plaît noter que je ne peux pas dessiner les polygones directement dans un Mat pour diverses raisons.

Je pensais que peut-être m1.copyTo(m2); fonctionnera, mais tout son remplaçant (y compris. Fond noir)

Toute idée comment l'obtenir fusionné/prochaine sans l'arrière-plan? Puis-je construire le mauvais problème?

+2

Créer un masque des morceaux que vous souhaitez copier (je suppose que tout ce qui est pas noir), et ensuite utiliser 'copyTo' avec ce masque. –

+0

@ DanMašek savez-vous une fonction intelligente pour détecter le noir/tout en plus du noir? J'ai essayé 'cv :: threshold (m1, m1, 1, 255, cv :: THRESH_BINARY);' mais ça ne marche pas très bien. – user1234

+1

ajouter des exemples d'images des dessins. – Micka

Répondre

2

Je suppose que vous avez eu un problème de recherche de noir dans ces images, car elles n'ont pas été initialisées (cela est devenu évident en mode débogage). Si nous commençons par une matrice remis à zéro, et tirer en utilisant une couleur 4 canaux, de sorte que les lignes sont visibles, nous obtenons des intrants tels que celui-ci:

entrée 1:

Input 1

Entrée 2 :

Input 2

maintenant, nous pouvons utiliser inRange pour trouver tous les pixels sur (0,0,0,0). Puisque nous voulons un masque de tous les pixels non noirs, nous venons de l'inverser en soustrayant de 255. (c.-à-mask = 255 - mask)

Masque:

Mask

Enfin, utilisez le masque comme second paramètre de copyTo.

Résultat:

Result

code:

#include <opencv2/opencv.hpp> 

int main() 
{ 
    cv::Mat m1(100, 100, CV_8UC4, cv::Scalar(0, 0, 0, 0)); 
    cv::Mat m2(100, 100, CV_8UC4, cv::Scalar(0, 0, 0, 0)); 

    cv::polylines(m1 
     , std::vector<cv::Point>{cv::Point{2, 20}, cv::Point{20, 40}} 
     , true, cv::Scalar(6, 6, 255, 255)); 
    cv::polylines(m2 
     , std::vector<cv::Point>{cv::Point{100, 100}, cv::Point{0, 0}} 
     , true, cv::Scalar(192, 112, 0, 255)); 

    cv::Mat mask; 
    cv::inRange(m2, cv::Scalar(0, 0, 0, 0), cv::Scalar(0, 0, 0, 0), mask); 
    mask = 255 - mask; // invert the mask 

    cv::Mat result(m1.clone()); 
    m2.copyTo(result, mask); 

    cv::imwrite("transp_in_1.png", m1); 
    cv::imwrite("transp_in_2.png", m2); 
    cv::imwrite("transp_mask.png", mask); 
    cv::imwrite("transp_res.png", result); 

    return 0; 
} 

au lieu d'inverser le masque, vous pouvez inverser la direction dans laquelle vous copiez. (À savoir tout Ecraser noir m2 avec des trucs de m1)

cv::Mat mask; 
cv::inRange(m2, cv::Scalar(0, 0, 0, 0), cv::Scalar(0, 0, 0, 0), mask); 

cv::Mat result(m2.clone()); 
m1.copyTo(result, mask);