OpenCv накладывает два Mat (рисунки, а не изображения) с прозрачностью

Привет, что у меня есть пара Mat что я хочу наложить (в произвольном порядке). Mat содержит некоторые полигоны opencv (что означает большую прозрачность). это Mat Мне нужно наложить / объединить. Но не с классическим альфа-смешиванием, а с прозрачностью 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

Решение

Я подозреваю, что у вас была проблема с поиском черного на этих изображениях, так как они не были инициализированы (это стало очевидным в режиме отладки). Если мы начнем с обнуленной матрицы и будем рисовать с использованием 4-канального цвета, чтобы линии были видны, мы получим следующие данные:

Вход 1:

Вход 1

Вход 2:

Вход 2

Теперь мы можем использовать inRange найти все пиксели, установленные на (0,0,0,0). Поскольку нам нужна маска всех не черных пикселей, мы просто инвертируем ее, вычитая из 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;
}

Вместо того, чтобы инвертировать маску, вы можете инвертировать направление копирования. (т.е. перезаписать все черным в 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);
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]