图像位深度 8位 16位 24位 32位区别对比 RGB 真彩色 基本概念:(大小,深度,通道)位深度数据类型转换原理 Mat数据读取(opencv里的imread)

Posted Dontla

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图像位深度 8位 16位 24位 32位区别对比 RGB 真彩色 基本概念:(大小,深度,通道)位深度数据类型转换原理 Mat数据读取(opencv里的imread)相关的知识,希望对你有一定的参考价值。

位深度

位深度是指在记录数字图像的颜色时,计算机实际上是用每个像素需要的二进制数值位数来表示的。计算机之所以能够显示颜色,是采用了一种称作“位”( bit ) 的记数单位来记录所表示颜色的数据。当这些数据按照一定的编排方式被记录在计算机中,就构成了一个数字图像的计算机文件。“位”( bit )是计算机存储器里的最小单元,它用来记录每一个像素颜色的值。图像的色彩越丰富,“位”就越多。每一个像素在计算机中所使用的这种位数就是“位深度”。

黑白二色的图像是数字图像中最简单的一种,它只有黑、白两种颜色,也就是说它的每个像素只有1位颜色,位深度是1,用2的一次幂来表示;考虑到位深度平均分给R, G, B和Alpha,而只有RGB可以相互组合成颜色。所以4位颜色的图,它的位深度是4,只有2的4次幂种颜色,即16种颜色或16种灰度等级 ) 。8位颜色的图,位深度就是8,用2的8次幂表示,它含有256种颜色 ( 或256种灰度等级 )。24位颜色可称之为真彩色,位深度是24,它能组合成2的24次幂种颜色,即:16777216种颜色 ( 或称千万种颜色 ),超过了人眼能够分辨的颜色数量。当我们用24位来记录颜色时,实际上是以2^(8×3),即红、绿、蓝 ( RGB ) 三基色各以2的8次幂,256种颜色而存在的,三色组合就形成一千六百万种颜色。
示例:8位颜色的图,位深度就是8,用2的8次幂表示,它含有256种颜色 ( 或256种灰度等级 )。
更通俗的讲,8位颜色的图,每个存储1个像素一般可存放8位二进制。也就是8个01进行排列组合,排列组合的结果有2的8次幂=256种颜色。我们把每个像素可表示颜色的2的幂指数称为深度。

位深度及通道表示方法

CV_<bit_depth>(S|U|F)C<number_of_channels>
 1--bit_depth---比特数---代表8bite,16bites,32bites,64bites---举个例子吧--比如说,如
    如果你现在创建了一个存储--灰度图片的Mat对象,这个图像的大小为宽100,100,那么,现在这张
    灰度图片中有10000个像素点,它每一个像素点在内存空间所占的空间大小是8bite,8--所以它对
    应的就是CV_8
 2--S|U|F--S--代表---signed int---有符号整形
           U--代表--unsigned int--无符号整形
           F--代表--float---------单精度浮点型
 3--C<number_of_channels>----代表---一张图片的通道数,比如:
     1--灰度图片--grayImg-----单通道图像
     2--RGB彩色图像-----------3通道图像
     3--带Alph通道的RGB图像----4通道图像

为什么要数据类型转换

OpenCV中默认加载图像imread函数的返回是通道顺序为BGR色彩色图像,范围是0~255之间,数据类型是CV_8UC的每个通道占一个字节。但是实际上我们在图像处理过程把像素值看成了数据对待,数据处理与计算过程中就会产生各种浮点数据、正数或者负数,如果我们不对字节数据进行提前转换就会导致精度丢失问题或者数据溢出问题,最终就无法达成图像处理算法想要的结果。最后再说一次,图像是特殊的数据!套用一句很经典的话就是,理论上理论与实践是一致的,实际上理论与实践之间还有有点距离,这个就要靠工程人员经验解决。

opencv里的位深度

在使用opencv的imread函数读取图像时,由于后面我没加flag参数,读取的图像全部被默认转换成通道顺序为BGR色彩色图像,范围是0~255之间,数据类型是CV_8UC的每个通道占一个字节,用print(image.dtype)打印数据类型都是uint8,如果要查看原图像信息,可能需在imread函数后加上特定flag,参见:
python opencv imread(filename, flags=None) 读取图像 flags cv::ImreadModes 参数上哪看去?

后来实测,加了flag也看不到……

不管是用cv.imread()函数读取8位图片(右键图片属性可看到的那个),还是24位图片,还是读取后将图片转换成灰度图,打印dtype数据类型都是uint8,其中打印读取的8位图片和24位图片都是三层数组,打印转换成灰度图的则是一层数组,根据各个文章中介绍的8位图bgr:2+3+3的位分配,猜测opencv在读取的时候将其映射map转换到24位即8+8+8上了,只是猜测,日后有待考证!

测试代码

# -*- encoding: utf-8 -*-
"""
@File    : test_191123_图像的位深度.py
@Time    : 2019/11/23 9:49
@Author  : Dontla
@Email   : sxana@qq.com
@Software: PyCharm
"""
import cv2 as cv

img = cv.imread('24.png', cv.IMREAD_GRAYSCALE)
cv.imshow('window', img)
print(type(img))  # <class 'numpy.ndarray'>
print(img.dtype)  # uint8
print(img.shape)  # (840, 1120)
cv.waitKey(0)

cv.destroyAllWindows()

参考文章1:8位, 16位,24位,32位图片显示原理及对比

参考文章2:opencv中图像基础(大小,深度,通道)

引用文章3:OpenCV中各种类型Mat数据读取

参考文章4:位深度

参考文章5:OpenCv学习笔记(二)–Mat矩阵(图像容器)的创建及CV_8UC1,CV_8UC2等参数详解

以上是关于图像位深度 8位 16位 24位 32位区别对比 RGB 真彩色 基本概念:(大小,深度,通道)位深度数据类型转换原理 Mat数据读取(opencv里的imread)的主要内容,如果未能解决你的问题,请参考以下文章

颜色模式中8位,16位,24位,32位色彩是啥意思

求单色位图,16色位图,24色位图和256色位图之间的区别?

ps转16位图少了字节

C#图片灰度处理(位深度24→位深度8),用灰度数组byte[]新建一个8位灰度图像Bitmap 。

如何使用 OpenCV C++ 将 24 位深度的 PNG 图像转换为 8 位深度的 PNG 图像

8位16位32位单片机区别