在OpenCV中,哪种方法是执行阿尔法蒙版最有效的方式?

8
我知道OpenCV只支持二进制掩码。
但是我需要做一个覆盖图层,其中我有一个灰度掩码,指定了覆盖层的透明度。

例如,如果掩码中的像素为50%白色,则应该对该像素执行alpha=beta=0.5,gamma = 0.0的cv :: addWeighted操作。

现在,如果没有opencv库函数,您会建议哪种算法最有效?

3个回答

5
我为解决问题做了类似的事情。
typedef double Mask_value_t;
typedef Mat_<Mask_value_t> Mask;
void cv::addMasked(const Mat& src1, const Mat& src2, const Mask& mask, Mat& dst)
{
  MatConstIterator_<Vec3b> it1 = src1.begin<Vec3b>(), it1_end = src1.end<Vec3b>(); 
  MatConstIterator_<Vec3b> it2 = src2.begin<Vec3b>();
  MatConstIterator_<Mask_value_t> mask_it = mask.begin();
  MatIterator_<Vec3b> dst_it = dst.begin<Vec3b>();

  for(; it1 != it1_end; ++it1, ++it2, ++mask_it, ++dst_it)
    *dst_it = (*it1) * (1.0-*mask_it) + (*it2) * (*mask_it);
}

目前我还没有使用断言来优化和确保这段代码的安全性。
工作假设:所有的Mat和掩码都是相同尺寸的,且Mat是普通的三通道彩色图像。


4

我有一个类似的问题,我想应用透明的png图像。我的解决方案是使用Mat表达式:

void AlphaBlend(const Mat& imgFore, Mat& imgDst, const Mat& alpha)
{
    vector<Mat> vAlpha;
    Mat imgAlpha3;
    for(int i = 0; i < 3; i++) vAlpha.push_back(alpha);
    merge(vAlpha,imgAlpha3)

    Mat blend = imgFore.mul(imgAlpha3,1.0/255) +
                imgDst.mul(Scalar::all(255)-imgAlpha3,1.0/255);
    blend.copyTo(imgDst);
}

-1

OpenCV支持RGBA图像,您可以使用mixchannelssplitmerge函数将图像与灰度掩码组合起来。希望这正是您所寻找的!

使用此方法,您可以将灰度掩码与图像组合在一起,如下所示:

    cv::Mat gray_image, mask, rgba_image;
    std::vector<cv::Mat> result;
    cv::Mat image = cv::imread(image_path);
    cv::split(image, result);
    cv::cvtColor(image, gray_image, CV_BGR2GRAY);
    cv::threshold(gray_image, mask, 128, 255, CV_THRESH_BINARY);
    result.push_back(mask);
    cv::merge(result, rgba_image);
    imwrite("rgba.png", rgba_image);

请注意,您不能使用cv::imshow查看RGBA图像,如read-rgba-image-opencv所述,并且您不能将图像保存为jpeg格式,因为该格式不支持透明度。似乎您可以使用cv::cvtcolor组合通道,如opencv-2-3-convert-mat-to-rgba-pixel-array所示。

1
谢谢,但如果我将一个RGBA图片放在另一个图片上方会发生什么?它会根据Alpha通道调整上层图片的透明度吗? - Barney Szabolcs
我尚未尝试使用类似于cv :: addWeighted的方法来合并两个rgba图像,但我想根据方程dst = saturate(src1 * alpha + src2 * beta + gamma)可以实现。 - cwadding

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接