将透明图像放置在不透明的图像上-OpenCV

时间:2019-09-07 12:33:07

标签: c++ opencv

我有这两个图像:

first
enter image description here
我想放在第二位。在那个论坛上搜索后,我尝试用这种方式做到这一点:

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

不幸的是,结果我只得到了第二张图像。我认为透明像素被视为白色像素,并覆盖了第一张图像中的像素。

如何只复制非透明像素?

1 个答案:

答案 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?
                }
            }

        }
    }
}

我认为这段代码说明了自己。如果不清楚,请随时提出。 现在,如果您要使用该代码,则假设您有backgroundspr,并且想将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)