使用OpenCV进行Alpha前景与背景图混合

左上方:前景图像。右上方:Alpha蒙版。左下:背景图像。右下:最终的合成图像。

 

在本教程中,我们将学习如何Alpha混合两个图像。想要在另一个图像上叠加一个透明的PNG图像吗?

 

什么是Alpha混合?

Alpha混合是将前景图像与背景图像叠加在一起的过程。透明度通常是图像的第四个通道(例如,在透明的PNG中),但是它也可以是单独的图像。这种透明蒙版通常称为alpha蒙版或alpha遮罩。

 

在本文顶部的功能图像中,前景图像显示在左上方,灰度alpha蒙版显示在右上方,背景图像显示在左下方,以及通过混合获得的合成图像右下角显示使用alpha蒙版的前景图像和背景图像。

 

alpha混合背后的数学很简单。在图像的每个像素处,我们都需要使用Alpha遮罩(α)组合前景图像颜色(F)和背景图像颜色(B )。

 

注意:α公式中使用的值实际上是alpha蒙版中的像素值除以255。因此,在下面的公式中,0 =< α =< 1

 

I = α F +(1-α)B

 

从上面的方程式,您可以进行以下观察。

 

当为时α = 0,输出像素颜色为背景。

当为时α = 1,输出像素颜色仅是前景。

当0 <α <1输出像素颜色是背景和前景的混合色时。为了进行逼真的混合,alpha蒙版的边界通常具有介于0和1之间的像素。

 

如何在OpenCV(C ++ / Python)中实现Alpha混合?

 

让我们来看一个用C ++和Python编写的示例,看看如何在OpenCV中实现α混合。在后面的部分中,我们还将展示C ++代码的有效实现。

 

#include opencv2/opencv.hpp using namespace cv;using namespace std; int main(int argc, char** argv){     // Read the images    Mat foreground = imread("puppets.png");    Mat background = imread("ocean.png");    Mat alpha = imread("puppets_alpha.png");         // Convert Mat to float data type    foreground.convertTo(foreground, CV_32FC3);    background.convertTo(background, CV_32FC3);        // Normalize the alpha mask to keep intensity between 0 and 1    alpha.convertTo(alpha, CV_32FC3, 1.0/255); //      // Storage for output image    Mat ouImage = Mat::zeros(foreground.size(), foreground.type());     // Multiply the foreground with the alpha matte    multiply(alpha, foreground, foreground);      // Multiply the background with ( 1 - alpha )    multiply(Scalar::all(1.0)-alpha, background, background);      // Add the masked foreground and background.    add(foreground, background, ouImage);          // Display image    imshow("alpha blended image", ouImage/255);    waitKey(0);         return 0;}

 

Alpha混合:Python

 

import cv2 # Read the imagesforeground = cv2.imread("puppets.png")background = cv2.imread("ocean.png")alpha = cv2.imread("puppets_alpha.png") # Convert uint8 to floatforeground = foreground.astype(float)background = background.astype(float) # Normalize the alpha mask to keep intensity between 0 and 1alpha = alpha.astype(float)/255 # Multiply the foreground with the alpha matteforeground = cv2.multiply(alpha, foreground) # Multiply the background with ( 1 - alpha )background = cv2.multiply(1.0 - alpha, background) # Add the masked foreground and background.outImage = cv2.add(foreground, background) # Display imagecv2.imshow("outImg", outImage/255)cv2.waitKey(0)

使用OpenCV(C ++)进行有效的Alpha混合

上面的代码很干净,但效率却不尽如人意。请注意,我们对前景图像进行了两次遍历-一次是与alpha乘以,另一次是与蒙版背景相加。同样,我们在背景图片上进行了多次传递。

 

对于小型(例如250×250)和中型(例如800×800)图像,上述方法很好,但是如果我们对效率特别感兴趣,特别是对于大型图像(例如2000×2000),则可以直接处理数据以获得更好的性能。以下是相同的CPP代码。

void alphaBlend(Mat& foreground, Mat& background, Mat& alpha, Mat& outImage){     // Find number of pixels.      int numberOfPixels = foreground.rows * foreground.cols * foreground.channels();      // Get floating point pointers to the data matrices     float* fptr = reinterpret_cast<float*>(foreground.data);     float* bptr = reinterpret_cast<float*>(background.data);     float* aptr = reinterpret_cast<float*>(alpha.data);     float* outImagePtr = reinterpret_cast<float*>(outImage.data);      // Loop over all pixesl ONCE     for(        int i = 0;        i < numberOfPixels;        i++, outImagePtr++, fptr++, aptr++, bptr++     )     {         *outImagePtr = (*fptr)*(*aptr) + (*bptr)*(1 - *aptr);     }}

运行时比较

 

在下表中,我们显示了两种方法在各种大小的图像上的运行时比较。这些数字是超过3000次跑步的平均时间。如您所见,对于较大的图像,一次通过图像的有效方法所花费的时间不到一半!目前尚不清楚为什么单次通过方法对于小图像会稍差一些。

 

 

相关图片源码下载地址:关注“图像算法”微信公众号,回复图像混合

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值