图像在计算机中是以数字矩阵形式存储的,我们常见的图像是JPEG格式,后缀为JPEG或者JPG,此种图像对应的矩阵有三个通道,代表着每个像素有R红,G绿,B蓝三个颜色分量。另一种常见的无损压缩图像格式为PNG,不同于JPEG,此格式的图像在计算机中有四个通道,第四个通道Alpha代表透明度。本文要做的就是将一个PNG图像的前景(RGB通道部分叠加到另一个背景图像上,类似于PS的抠图操作)
下面来看下代码实现部分,首先是python的实现:
import numpy as np
import cv2
foreGroundImage = cv2.imread("foreGroundAsset.png",-1)
## 先将通道分离
b,g,r,a = cv2.split(foreGroundImage)
#得到PNG图像前景部分,在这个图片中就是除去Alpha通道的部分
foreground = cv2.merge((b,g,r))
#得到PNG图像的alpha通道,即alpha掩模
alpha = cv2.merge((a,a,a))
background = cv2.imread("backGround.jpg")
#因为下面要进行乘法运算故将数据类型设为float,防止溢出
foreground = foreground.astype(float)
background = background.astype(float)
cv2.imwrite("alpha.jpg",alpha)
#将alpha的值归一化在0-1之间,作为加权系数
alpha = alpha.astype(float)/255
cv2.imshow("alpha",alpha)
cv2.waitKey(0)
#将前景和背景进行加权,每个像素的加权系数即为alpha掩模对应位置像素的值,前景部分为1,背景部分为0
foreground = cv2.multiply(alpha,foreground)
background = cv2.multiply(1-alpha,background)
outImage = foreground + background
cv2.imwrite("outImage.jpg",outImage)
cv2.imshow("outImg",outImage/255)
cv2.waitKey(0)
同样,给出C++的实现代码:
#include opencv2/opencv.hpp
using namespace cv;
using namespace std;
int main()
{
// 读图像
Mat foreground = imread("puppets.png");
Mat background = imread("ocean.png");
Mat alpha = imread("puppets_alpha.png");
// 为做乘法不溢出,将格式转换为32F的,代表32维浮点数
foreground.convertTo(foreground, CV_32FC3);
background.convertTo(background, CV_32FC3);
// 将alpha掩模的值归一化在0-1之间
alpha.convertTo(alpha, CV_32FC3, 1.0/255); //
// 保存合成图像
Mat ouImage = Mat::zeros(foreground.size(), foreground.type());
// 前景乘以alpha
multiply(alpha, foreground, foreground);
// 背景乘以1-alpha
multiply(Scalar::all(1.0)-alpha, background, background);
// 相加
add(foreground, background, ouImage);
// 显示图像
imshow("alpha blended image", ouImage/255);
waitKey(0);
return 0;
}
结果示意:
本节的内容比较简单,下一节介绍如何检测图像中具有的特殊色块,比如一块橡皮之类的东西。
致力于分享OpenCV有趣且实用的案例~
微信公众号:一支程序媛
关注回复 计算机视觉算法 可以获取免费学习资源(楼主就是靠这些资源拿到百度,阿里等校招offer的哦~)
知乎:一支程序媛,专栏开通中…