使用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 ...
随机推荐
- [开源]eCharts配置简化包OptionCreator[typescript版]
eCharts存在问题 配置eCharts的option,对于大部分的开发者来说,复杂情况下是一件繁琐的事情.为什么繁琐,大致有以下这些原因 大小写敏感:在没有IDE的智能提示下,很容易写错,而且即使 ...
- .net core Web API参数绑定规则
参数推理绑定 先从一个问题说起,微信小程序按照WebAPI定义的参数传递,Get请求服务器端可以正常接收到参数,但是Post请求取不到. Web API代码(.netcore 3.1)如下: [Htt ...
- HDFS和MR的配置和使用
一.分布式HDFS的安装和启动 ①在$HADOOP_HOME/etc/hadoop/core-site.xml文件 <configuration> <property> < ...
- 曹工说面试:当应用依赖jar包的A版本,中间件jar包依赖B版本,两个版本不兼容,这还怎么玩?
背景 大一点的公司,可能有一些组,专门做中间件的:假设,某中间件小组,给你提供了一个jar包,你需要集成到你的应用里.假设,它依赖了一个日期类,版本是v1:我们应用也依赖了同名的一个日期类,版本是v2 ...
- 洛谷 P4910 帕秋莉的手环
题意 多组数据,给出一个环,要求不能有连续的\(1\),求出满足条件的方案数 \(1\le T \le 10, 1\le n \le 10^{18}\) 思路 20pts 暴力枚举(不会写 60pts ...
- 协同合约HACKATHON 0X03;
协同合约HACKATHON 0X03; 使用Fetch.AI技术开发一个共享行程协同合约.超过100,000个FET代币奖励. 介 绍 拼车是对你的钱包和环境都非常有益的,因此UberPool™等共享 ...
- Python爬虫:手把手教你写迷你爬虫架构
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:我爱学Python 语言&环境 语言:继续用Python开路 ...
- vscode F2无法使用
rope库可能存在bug 解决方法: "python.jediEnabled": false //自动补全用微软自带
- JavaScript学习 Ⅲ
六. 面向对象 对象属于一种复合的数据类型,在对象中可以保存多个不同的数据类型的属性. 对象分类 内建对象 由ES标准种定义的对象.比如:Math String Number 宿主对象 由JS的运行环 ...
- java 面向对象(二十五):内部类:类的第五个成员
内部类:类的第五个成员 1.定义: Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类.2.内部类的分类:成员内部类(静态.非静态 ) vs 局部内部类(方法内.代码块内.构 ...