首页 > 解决方案 > 将透明图像放在不透明上 - opencv

问题描述

我有这两张图片:

第一的我想把 第一放在第二。在该论坛上搜索后,我尝试以这种方式执行此操作:
在此处输入图像描述

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

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

如何仅复制不透明的像素?

标签: c++opencv

解决方案


我不知道任何直接功能,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想把:sprbackground

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)


推荐阅读