OpenCv覆盖两个具有透明度的Mat(图形而非图像)

时间:2017-07-16 17:01:34

标签: c++ opencv overlays

我所拥有的是我要覆盖的几个Mat(按自定义顺序)。 Mat保留了一些opencv多边形(这意味着很多透明度)。这个Mat我需要重叠/合并。但不是经典的alpha混合更像是100%的不透明度,而是具有透明度。

这是我想要合并的简单示例代码。

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

请注意,由于各种原因,我无法在一个Mat中直接绘制多边形。

我认为也许m1.copyTo(m2);会起作用,但它会覆盖所有内容(包括黑色背景)

知道如何在没有背景的情况下合并/重叠它吗?我可以把垫子弄错了吗?

1 个答案:

答案 0 :(得分:2)

我怀疑你在这些图片中寻找黑色时遇到了问题,因为它们没有被初始化(在调试模式下变得明显)。如果我们从一个归零矩阵开始,并使用一个4通道颜色绘制,以便线条可见,我们得到如下输入:

输入1:

Input 1

输入2:

Input 2

现在,我们可以使用inRange查找设置为(0,0,0,0)的所有像素。由于我们需要所有非黑色像素的遮罩,我们只需通过从255减去它来反转它。(即mask = 255 - mask

面膜:

Mask

最后,使用掩码作为copyTo的第二个参数。

结果:

Result

代码:

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

您可以反转复制的方向,而不是反转蒙版。 (即用m2中的内容覆盖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);