使用opencv为没有透明通道的图像加入透明通道
在图像处理中,我们经常需要处理带透明通道的图片,比如为图片或视频添加水印,为图片或视频添加字幕、贴图等。然而,我们的素材图片未必总是带有透明通道。比如,素材的背景本该透明的地方,却是黑色和白色。有时,我们甚至需要让素材本身有图像的部分半透明。接下来,我将介绍两个方法,一种是使用opencv内置方法,另一种是自己写代码,来为图像添加透明通道。
1.首先,是opencv中的cvtColor方法。
C++: void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );
参数解释:
. InputArray src: 输入图像即要进行颜色空间变换的原图像,可以是Mat类
. OutputArray dst: 输出图像即进行颜色空间变换后存储图像,也可以Mat类
. int code: 转换的代码或标识,即在此确定将什么制式的图片转换成什么制式的图片,后面会详细将
. int dstCn = 0: 目标图像通道数,如果取值为0,则由src和code决定
我们可以令code参数为COLOR_BGRABGRA,将图像转化为带透明通道的图片。这里要注意,加上的透明通道,默认值为255,也就是说,默认将图像转换为不透明图。如果需要对图像的透明度进行调整,则还需要另写代码。下面是部分代码,来验证默认值确实为255。
std::string path = "E:/140.jpg";
Mat image = cv::imread(image_path);
std::cout << "原图像通道数: " << image.channels() << std::endl;
cvtColor(image, image, COLOR_BGR2BGRA);
std::cout << "转换后图像通道数: " << image.channels() << std::endl;
for (int i = ; i < image.rows; i++) {
for (int j = ; j < image.cols; j++) {
std::cout<<(int)image.at<Vec4b>(i, j)[]<<std::endl;
}
}
得到的输出为:

代码中,image.at可以获取图像像素值,而中括号内,0代表B,1代表G,2代表R,3代表A,所以括号中为3。而强制类型转换为int,则是因为在opencv中,单像素的类型为uchar,如果直接标准输出,则会输出一大堆字符,而不是我们想要的像素值。如果图像在读取的时候没有要求读取透明通道,或者图像本身没有透明通道,那么图像的通道数默认为3,可以简单地说,这个内置方法,就是为图像的通道数组多加了一列作为透明通道,这个数组类型为Mat类型。
2.接下来,是手写代码的方法
由上述说明可知,默认方法所做的就是给图像的通道数组再加上一列,而这一列所表示的,就是图像每个像素的透明度。而这个透明度数组,也是一个Mat类型数组。
所以,我们可以新建一个Mat类型数组,数组大小与图像的分辨率一致。这里,我们还可以以图像的灰度图作为参考,将图像的每个像素以灰度值来设置透明度,这样一来,就实现了图像按像素值自动的调整每一个像素点的透明度。创建透明通道的方法如下:
//创建透明通道
cv::Mat createAlpha(cv::Mat& src)
{
cv::Mat alpha = cv::Mat::zeros(src.rows, src.cols, CV_8UC1);
cv::Mat gray = cv::Mat::zeros(src.rows, src.cols, CV_8UC1); //根据灰度创建透明度通道
cv::cvtColor(src, gray, cv::COLOR_RGB2GRAY); for (int i = ; i < src.rows; i++)
{
for (int j = ; j < src.cols; j++)
{
//透明度为灰度的两倍,可自行调整 alpha.at<uchar>(i, j) = gray.at<uchar>(i, j) * ;
}
} return alpha;
}
这个alpha,就是图像的透明通道。然而,这里的透明通道仅仅是被创建了出来,并没有被加入图像中。我们可以使用opencv中的split和merge函数来添加透明通道。其中,split函数作用是分割图像的通道,merge函数则是合并图像的各通道。我们可以先把原图像的各个通道分开,然后再连带着透明通道合并,就得到了带透明通道的图像。代码如下:
int addAlpha(cv::Mat& src, cv::Mat& dst, cv::Mat& alpha)
{
if (src.channels() == )
{
return -;
}
else if (src.channels() == )
{
cv::cvtColor(src, src, cv::COLOR_GRAY2RGB);
} dst = cv::Mat(src.rows, src.cols, CV_8UC4); std::vector<cv::Mat> srcChannels;
std::vector<cv::Mat> dstChannels;
//分离通道
cv::split(src, srcChannels); dstChannels.push_back(srcChannels[]);
dstChannels.push_back(srcChannels[]);
dstChannels.push_back(srcChannels[]);
//添加透明度通道
dstChannels.push_back(alpha);
//合并通道
cv::merge(dstChannels, dst); return ;
}
再处理的过程中,先调用createAlpha函数创建透明通道,再调用addAlpha函数加入透明通道即可。下面放一个测试结果。
原图:

加入透明通道:

可以看到,一些像素变成了全透明,而一些像素是半透明。如果把这个图贴在其他图上的话,看的更明显一点:

使用opencv为没有透明通道的图像加入透明通道的更多相关文章
- 多通道(Multichannel)单通道(singlechannel)图像概念梳理
在做机器视觉时,常常要将一个多通道图像分离成几个单通道图像或者将几个单通道图像合成一个多通道图像,以方便图像处理,但是.写这篇博客,是为加深对这两个概念的理解,下面会给出部分OpenCV对单通道与多通 ...
- OpenCV计算机视觉学习(2)——图像算术运算 & 掩膜mask操作(数值计算,图像融合,边界填充)
在OpenCV中我们经常会遇到一个名字:Mask(掩膜).很多函数都使用到它,那么这个Mask到底是什么呢,下面我们从图像基本运算开始,一步一步学习掩膜. 1,图像算术运算 图像的算术运算有很多种,比 ...
- OpenCV中IplImage图像格式与BYTE图像数据的转换
最近在将Karlsruhe Institute of Technology的Andreas Geiger发表在ACCV2010上的Efficent Large-Scale Stereo Matchin ...
- OpenCV学习笔记:如何扫描图像、利用查找表和计时
目的 我们将探索以下问题的答案: 如何遍历图像中的每一个像素? OpenCV的矩阵值是如何存储的? 如何测试我们所实现算法的性能? 查找表是什么?为什么要用它? 测试用例 这里我们测试的,是一种简单的 ...
- OpenCV 编程简单介绍(矩阵/图像/视频的基本读写操作)
PS. 因为csdn博客文章长度有限制,本文有部分内容被截掉了.在OpenCV中文站点的wiki上有可读性更好.而且是完整的版本号,欢迎浏览. OpenCV Wiki :<OpenCV 编程简单 ...
- opencv::将两幅图像合并后,在同一个窗口显示;并将合并的图像流保存成视频文件
/** * @file main-opencv.cpp * @date July 2014 * @brief An exemplative main file for the use of ViBe ...
- 使用GDI+保存带Alpha通道的图像
带Alpha通道的图像(ARBG)在通过GDIPlus::Bitmap::FromHBITMAP等转为GDI+位图,再存储时,透明区域会变成纯黑(也有可能是纯白?). 网上找了两段保持透明的实现代 ...
- 【opencv学习笔记七】访问图像中的像素与图像亮度对比度调整
今天我们来看一下如何访问图像的像素,以及如何改变图像的亮度与对比度. 在之前我们先来看一下图像矩阵数据的排列方式.我们以一个简单的矩阵来说明: 对单通道图像排列如下: 对于双通道图像排列如下: 那么对 ...
- 【opencv系列02】OpenCV4.X图像读取与显示
一.读取图片 opencv中采用imread() 函数读取图像 imread(filename, flags=None) filename 图片的路径 flags 图像读取方式 ● c ...
随机推荐
- css3增加的的属性值position:stricky
position:sticky sticky 英文字面意思是粘,粘贴.这是一个结合了 position:relative 和 position:fixed 两种定位功能于一体的特殊定位,适用于一些特殊 ...
- Web移动端 自适应缩放界面
在开发App端的网页时,要适配iphone.ipad.ipod.安卓等各种机型,一般是直接使用em.px转em.界面缩放. 本章是通过将界面缩放,等比例显示在各机型上.过程中遇到了些问题和大坑~ 然后 ...
- [JAVA]移位运算(左移<<,右移>>和无符号右移>>>)
一.背景知识 整数在内存中是以二进制的形式存在的,而且存的是该整数的补码.最高位代表符号位,正数为0,负数为1 正数的补码是其二进制本身,负数的补码则是 符号位保持1不变,其他位按位取反再加1,+0和 ...
- 核心知识点:python入门
目录 一.python入门day1-day24 day01-03 编程语言 day04 变量 day05 垃圾回收机制(GC机制) 1 引用计数 2 标记清除 3 分代回收 day05 程序交互与基本 ...
- VSCode 配 uni-app
CLI工程 全局安装vue-cli npm install -g @vue/cli 通过cli创建uni-app项目 vue create -p dcloudio/uni-preset-vue uni ...
- 在spyder中无法import module
如果在anaconda中下载安装了模块,但是在spyder中无法import,可能是因为两个python环境并不一致,在promote重新conda install spyder即可
- bzoj3791作业*
bzoj3791作业 题意: 对一个01序列进行染色,每次能将一个区间染上色(可覆盖之前染的),共能染k次,求最大正确染色个数.n≤100000,m≤50. 题解: 结论:染k次最多能把序列分成2*k ...
- 使用PowerShell自动编译部署前端
前言 最近在开发一套管理系统,做了前后端分离. 后台使用的是Asp.Net Core 3.1 前端使用的是Vue+Ant Design 自己搞了一台云服务器,打算把系统部署到云服务器上.以供外网访问. ...
- 太慢不能忍!CPU又拿硬盘和网卡开刀了!
总线技术 我是CPU一号车间的阿Q,最近为了一件事儿搞得我挺烦的. 当初我们CPU工厂刚刚来到主板上建厂时,那时候主板上的单位还不多,跟我们打交道最多的就是内存那家伙了. 后来,键盘.鼠标.硬盘.网卡 ...
- MacOS中Mysql设置默认字符集
一.查看字符集 mysql> show variables like 'character%'; +--------------------------+-------------------- ...