我有这两个图像:
和
我想放在第二位。在那个论坛上搜索后,我尝试用这种方式做到这一点:
cv::Mat dst(std::max(background.rows, small->rows),std::max(background.cols, small->cols), CV_8UC4);
background.copyTo(dst);
small->copyTo(dst);
cv::imwrite(path_to_save.str(), dst);
不幸的是,结果我只得到了第二张图像。我认为透明像素被视为白色像素,并覆盖了第一张图像中的像素。
如何只复制非透明像素?
答案 0 :(得分:2)
我不知道来自opencv
的任何直接函数,但是我写了明确的方法来做到这一点。
CV_8UC4
。在使用该示例时,您可以轻松地将该方法扩展到其他版本。void merge_images(cv::Mat* background, cv::Mat* upcoming, int x, int y)
{
auto handle_cv_8uc4 = [=](int i, int j)
{
if(upcoming->at<cv::Vec4b>(j, i)[3] > 10)//10 is only epsilon for trash hold, you can put also 0 or anything else.
{
background->at<cv::Vec4b>(y+j, x+i) = upcoming->at<cv::Vec4b>(j, i);
}
};
auto handle_cv_8uc3 = [=](int i, int j)
{
background->at<cv::Vec4b>(y+j, x+i)[0] = upcoming->at<cv::Vec3b>(j, i)[0];
background->at<cv::Vec4b>(y+j, x+i)[1] = upcoming->at<cv::Vec3b>(j, i)[1];
background->at<cv::Vec4b>(y+j, x+i)[2] = upcoming->at<cv::Vec3b>(j, i)[2];
background->at<cv::Vec4b>(y+j, x+i)[3] = 255;
};
for(int i = 0; i < upcoming->cols; i++)
{
for(int j = 0; j < upcoming->rows; j++)
{
if(j + y >= background->rows)
{
break;
}
if(x + i >= background->cols)
{
return;
}
switch(upcoming->channels())
{
case 3:
{
handle_cv_8uc3(i, j);
break;
}
case 4:
{
handle_cv_8uc4(i, j);
break;
}
default:
{
//maybe error?
}
}
}
}
}
我认为这段代码说明了自己。如果不清楚,请随时提出。
现在,如果您要使用该代码,则假设您有background
和spr
,并且想将spr
放入background
:
cv::Mat dst(background.rows, background.cols, CV_8UC4);
merge_images(&dst, &background, 0, 0);
merge_images(&dst, &spr, 50, 50);
cv::Mat dst(background.rows, background.cols, CV_8UC4);
准备背景大小的矩阵(以避免修改原始背景)
merge_images(&dst, &background, 0, 0);
为准备好的副本添加背景
merge_images(&dst, &spr, 50, 50);
添加图像,使其左角位于(50,50)