当前栏目
一文弄明白 OpenCV Mat 中通道channels的作用
1. 介绍
openCV 是使用 Mat 进行存储图片,记录各种像素信息。那么 Mat 中的像素是如何记录和获取的呢?
在网上找到有很多是C语言写的。在这里我想使用java的语法给大家介绍一下。
如何通过Mat获取到指定区域的像素。RGB,BGR,HSV,GRAY等格式数据的获取。
2. channels 通道
当我们使用Mat.channels() 方法,能够得到当前 Mat 的通道数。 通常返回结果值为:1,2,3,4 这四个结果。
那么这个通道是什么东西呢?
我们知道,所有的图像都是由一个个像素点堆积而成的。而一个像素点,又是由RGB颜色混合而成的。
每一种颜色就是一种通道。每个像素点是多个通道颜色的混合结果。
PS:知识点,RGB三原色可以混淆所有我们肉眼可以见到的颜色。
所以,当我们弄明白通道之后就能明白如何获取Mat中指定坐标的颜色值了。
mat.rows() 是Y轴长度。
mat.cols() 是X轴长度。
示例:
当我们遍历一遍temp的结果会得到:
数据的结果实际情况是:
- r:3.0
- g:0.0
- b:4.0
- a:255 (透明度,0表示透明,255表示不透明)
知识点,OpenCV 中的颜色顺序不是 BGR 格式么?这个顺序不针对 Mat 中的颜色,而是我们使用 Scalar 的时候传入的颜色顺序是 BGR 顺序而已。
new Scalar(10,255,255); //颜色顺序是 B,G,R
我们如果是一个 BGR 格式的 Mat 对象那么颜色值会怎么显示呢?
还是使用上面的 Mat 我们进行转换之后,看看同一个点输出的结果:
数据的结果实际情况是:
- b:4.0
- g:0.0
- r:3.0
就会出现颜色的通道数变化。
不知道注意到了没有,我上面是将rbga直接转成了BGR。
在高位转换的情况下,A通道会被直接丢弃。体现在图像上就会没有透明效果了。
我们如果想确保A通道也转换,可以使用:
Imgproc.cvtColor(rgba, bgra, Imgproc.COLOR_RGBA2BGRA);
2.1 Gray 灰度图转换
当我们将RGBA或者BGR等彩色图像转换为GRAY灰色的时候,Mat的通道数就会被压制为单通道G了。效果如下:
会发现灰色图是只有一个通道的。
按照Gray = R*0.299 + G*0.587 + B*0.114 公式进行的转换。
这个公式叫做Luminosity(亮度算法)。这个算法中RGB的各占比例。都是一个经验值。也就是说没有科学道理。纯粹经验出发调试出来的一个比例。
PS:所以有一个小常识,RGB转Gray,然后再Gray转换回RGB会出现色差。因为在转换过程中避免不了信息丢失。
2.2 小结
当我们弄明白通道数的概念之后。就能够弄明白cvtColor中的各种转换了
Luv,Lab,HSV,RGB,BGR,HLS,YUV,GRAY等等的颜色转换其实都是针对我们的单像素中的通道值在处理。
- 单通道的,是Gray灰度图。
- 双通道的,两个通道值一个为实数,个为虚数。主要是RGB555和RGB565格式的图像,这个通道通常用来计算。
- 三通道的,图片就是彩色图像了,例如RGB,BGR,HSV,HLS等等。
- 四通道的,图片带透明度的图像了。相较于三通道多了一个alpha通道,也就是表示透明度。
我们在使用OpenCV时,新手经常出现Mat错误,就在于通道转换了。因为OpenCV有些算法是必须单通道的。而我们一不小心传了3通道的。或者,Mat是三通道的。与另一个单通道的Mat进行比较处理时,出现通道错误等等。
注意:
我们使用Imgproc.cvtColor方法进行转换的时候。输入的Imgproc.COLOR_RGBA2GRAY等等值是很重要的。需要根据我们的Mat的实际情况进行选择。
我们如果Mat是BGR格式的,我们却选择使用Imgproc.COLOR_RGB2HSV_FULL转换,虽然结果是转换了。但是实际情况是不对的。
因为Imgproc会按照RGB的顺序从double[]数组中提取参数进行计算处理,而不是按照BGR的格式进行提取转换。
2.2.1 Imgproc.COLOR_XXXX解释
简单介绍下ImgProc.COLOR_XXX的信息。其实说破很简单:
其他的就不介绍了,命名中的2代表to。然后将左边的颜色格式转为右边的颜色格式而已。
3. 通道分解和合成
我们如果想操作通道。有很多方法,最简单的是我们直接遍历然后修改通道参数:
或者,我们直接修改指定位置的颜色值:mat.put(x,y,temp);
而我们如果想批量针对通道进行操作,可以使用OpenCV提供的算法:
下面来介绍这三个方法的传值:
使用:
我们如果想只想看到Mat中的红色通道的效果,而不是看灰度图。该怎么处理?
需要结合split方法和merge方法一起使用
使用:将上面split拆解的Mat进行合并
最终我们得到的dst就是一个三通道的图像了,只有R通道有值。(图片是BGR的顺序存储的)
4. 总结
到这里关于通道的介绍就结束了。以上内容基于自己的理解和验证。在openCV4.6 SDK版本,java开发环境下进行的验证。
相关文章
- 一日一技:如果你非要把HTML存到数据库,那么你应该…
- LRU 缓存-keep-alive 实现原理
- 3 个简单的技巧让你的 vue.js 代码更优雅!
- 开源有国界!GitHub、Node.js、React等公开站队,微软对俄禁售
- 聊一聊 WAF CDN 的识别方法
- VFP为公众号添加一个报名功能,代码不多,但谁能得扬名立万
- JSON与XML你不懂就OUT,真相是它们都是字符串
- 手把手教你JS逆向搞定字体反爬并获取某招聘网站信息
- 画一手好的架构图是码农进阶的开始
- 网站运营还是盗版罪犯?这个男人被判欠任天堂1450万美元,服刑3年后打工慢慢还
- J2EE之普通类载入web资源文件的方法
- 你在元宇宙“吃鸡”,我在Web3.0投机,我们都有光明的未来
- 为了生成唯一id,React18专门引入了新Hook:useId
- JS中所有对象隐式转换都是true?除了他...
- 用几行原生JS就可以实现丝滑的元素过渡效果!
- 使用 Rust 编写更快的 React 组件
- 六种方式,教你在SpringBoot初始化时搞点事情!
- C++使用Nginx搭建WEB程序
- Node.js 2021年开发者报告解读:健康稳步的发展中
- 因为没有这个按钮,谷歌、脸书被罚15亿,限期三个月改正