2017-07-16 6 views
1

Hallo, was ich habe, ist ein paar Mat, die ich (in einer benutzerdefinierten Reihenfolge) überlagern möchte. Die enthält einige opencv Polygone (was eine Menge Transparenz bedeutet). Diese Ich muss überlagern/zusammenführen. Aber nicht mit der klassischen Alpha-Mischung mehr wie mit einer 100% Opazität, sondern mit Transparenz.OpenCv Overlay zwei Mat (Zeichnungen nicht Bilder) mit Transparenz

Dies ist ein einfacher Beispielcode von dem, was ich zusammenführen möchte.

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)); 

Bitte beachten Sie, dass ich nicht die Polygone direkt in einem Mat aus verschiedenen Gründen ziehen.

dachte ich, dass vielleicht m1.copyTo(m2); funktionieren wird, aber sein überschreibt alles (inkl. Der schwarze Hintergrund)

Jede Idee, wie es ohne den Hintergrund verschmolzen/überarbeitbar zu bekommen? Kann ich die Matte falsch konstruieren?

+2

Erstellen einer Maske der Stücke, die Sie kopieren möchten (i alles erraten, die nicht schwarz ist), und verwenden Sie dann 'copyTo' mit dieser Maske. –

+0

@ DanMašek kennst du irgendeine clevere Funktion, um das Schwarz/alles außer dem Schwarzen zu erkennen? Ich habe versucht 'cv :: threshold (m1, m1, 1, 255, cv :: THRESH_BINARY);' aber es funktioniert nicht sehr gut. – user1234

+1

fügen Sie Beispielbilder der Zeichnungen hinzu. – Micka

Antwort

2

Ich vermute, Sie hatten ein Problem bei der Suche nach Schwarz in diesen Bildern, da sie nicht initialisiert wurden (es wurde im Debug-Modus offensichtlich). Wenn wir mit einem genullt Matrix beginnen, und zeichnen Sie eine 4-Kanal-Farbe verwendet wird, so dass die Linien sichtbar sind, wir Eingänge wie folgt erhalten:

Eingang 1:

Input 1

Eingang 2 :

Input 2

Jetzt können wir inRange verwenden, um alle Pixel auf (0,0,0,0) zu finden. Da wir eine Maske alles nicht-schwarzer Pixel wollen, kehren wir nur durch von 255 subtrahiert wird (dh mask = 255 - mask)

Maske:

Mask

Schließlich verwendet die Maske als zweiten Parameter von copyTo.

Ergebnis:

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; 
} 

Statt der Maske invertieren, können Sie die Richtung umkehren, in dem Sie kopieren. (Das heißt überschreiben alles schwarz in m2 mit Sachen von 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);