OpenCv 用透明度覆盖两个 Mat(绘图而不是图像)
OpenCv overlay two Mat (drawings not images) with transparency
您好,我有几个 Mat
,我想叠加(按自定义顺序)。 Mat
包含一些 opencv 多边形(这意味着很多透明度)。这个Mat
我需要overlay/merge。但不是经典的 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);
可能会起作用,但它会覆盖所有内容(包括黑色背景)
知道如何在没有背景的情况下获得它 merged/overlayed 吗?请问我垫子搭错了吗?
我怀疑您在寻找这些图像中的黑色时遇到了问题,因为它们没有初始化(在调试模式下很明显)。如果我们从一个归零矩阵开始,并使用 4 通道颜色绘制,以便线条可见,我们得到如下输入:
输入 1:
输入 2:
现在,我们可以使用 inRange
来查找所有设置为 (0,0,0,0) 的像素。因为我们想要一个所有 non-black 像素的掩码,我们只需从 255 中减去它来反转它。(即 mask = 255 - mask
)
掩码:
最后,使用掩码作为copyTo
的第二个参数。
结果:
代码:
#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;
}
您可以反转复制的方向,而不是反转蒙版。 (即用 m1
中的内容覆盖 m2
中的所有黑色内容)
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);
您好,我有几个 Mat
,我想叠加(按自定义顺序)。 Mat
包含一些 opencv 多边形(这意味着很多透明度)。这个Mat
我需要overlay/merge。但不是经典的 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);
可能会起作用,但它会覆盖所有内容(包括黑色背景)
知道如何在没有背景的情况下获得它 merged/overlayed 吗?请问我垫子搭错了吗?
我怀疑您在寻找这些图像中的黑色时遇到了问题,因为它们没有初始化(在调试模式下很明显)。如果我们从一个归零矩阵开始,并使用 4 通道颜色绘制,以便线条可见,我们得到如下输入:
输入 1:
输入 2:
现在,我们可以使用 inRange
来查找所有设置为 (0,0,0,0) 的像素。因为我们想要一个所有 non-black 像素的掩码,我们只需从 255 中减去它来反转它。(即 mask = 255 - mask
)
掩码:
最后,使用掩码作为copyTo
的第二个参数。
结果:
代码:
#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;
}
您可以反转复制的方向,而不是反转蒙版。 (即用 m1
中的内容覆盖 m2
中的所有黑色内容)
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);