数字图像
我们的图像是存储在存储器里面 ,那么存储器存储格式归根结底不外乎0和1。
再往高点也就是数据的基本类型,以0和1去存储,每一个内存单元可以存储8位的二进制数
0000 0000
再往高走,图像也可以看成一个数组,数组存的就是一个一个的像素。
数组[] = 像素的集合
数字图像在存储器里面是如何存储的呢?
image.png image.png
三通道RGB可以表示多少种颜色呢?
16 * 16 * 16 = 4096(4位)
256 * 256 * 256 = 16777216(8位),即 1600W色
人眼可以识别的是 32 * 32 * 32 = 1048576种
我们可以使用RGB来表示几乎所有的颜色,为何还有单通道的存在呢?因为单通道内存开销小。
下面我们看下Bitmap.Config
public static enum Config {
ALPHA_8,// 只有明暗度(透明度),每一个像素占8位
ARGB_4444,// 4通道,一个像素的每个通道占4位,一共16位
ARGB_8888,// 4通道,一个像素的每个通道占8位,一共32位
HARDWARE,// 硬件表示,只有01010101
RGBA_F16,// float类型单通道表示16位的数
RGB_565;// 3通道 R占5位 G占6位 B占5位 共16位
private Config() {
}
}
颜色深度
一个像素所占的数据位数,比如ARGB_8888,就是32位深度的图片
图像模式
1. 位图模式
只占1位深度,只有黑白两种颜色(黑白打印机)
2. 灰度模式
8位深度,可以表示0-255之间的不同灰度(黑灰白图片)
3. 双色调模式
只有一个通道,可以表现色彩,是单色调、双色调、三色调和四色调的统称
4. RGB模式
24位深度 真彩
5. CMYK模式
印刷专业使用
6. Lab模式
24位深,L亮度 a色彩分量由绿色向红色过度 b色彩分量由蓝色向黄色过度
7. 索引颜色模式
只能表现256种颜色
上节课我们知道,OpenCV是以大部分的C的函数和少量的C++的类构成的。这里面有一个很重要的东西就是cv的命名空间。
using namespace cv;
OpenCV在2.0以后才开始使用Mat数据结构,如果不使用cv命名空间,我们就需要这样写才能使用Mat。
cv::Mat
所以推荐大家使用命名空间方式,可以减少很多不必要的麻烦。
下面我们重点看下Mat
Mat是用来保存图像和其他矩阵的一个数据结构,默认情况下尺寸为0,通过Mat我们可以对图片进行转换
Mat imgData(h, w, CV_8UC4, (unsigned char *) pixels);
imgData是我们自定义的函数名,它就像一个对象一样,我们可以对这个对象进行操作。
下面介绍一下各个参数的含义:
h:图片的高
w:图片的宽
CV_8UC4:cv-表明是OpenCV里面使用; 8-指的是8位,即每一个通道代表的位数;U-无
符号unsigned;C-char类型;4-通道数
(unsigned char *) pixels:强转成无符号char类型
• CV_8U - 8位无符号整型 ( 0..255 )
• CV_8S - 8位有符号整型 ( -128..127 )
• CV_16U - 16位无符号整型( 0..65535 )
• CV_16S - 16位有符号整型 ( -32768..32767 )
• CV_32S - 32位有符号整型 ( -2147483648..2147483647 )
• CV_32F - 32位 floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
• CV_64F - 64位 floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
下面是我们之前做的灰度图的代码
Mat imgData(h, w, CV_8UC4, (unsigned char *) pixels);
uchar *ptr = imgData.ptr(0);
for (int i = 0; i < w * h; i++) {
// 灰度值计算公式 R * 0.3 + G * 0.59 + B * 0.11
uchar gray = (uchar) (ptr[4 * i + 2] * 0.299 + ptr[4 * i + 1] * 0.587 +
ptr[4 * i + 0] * 0.114);
ptr[4*i+0]=gray;
ptr[4*i+1]=gray;
ptr[4*i+2]=gray;
}
那么我们是怎么确定图像通道具体是哪个呢?
可以这样做(第四个通道不能改0,即变成全透明 ):
ptr[4*i+0];
ptr[4*i+1]=0;
ptr[4*i+2]=0;
经过测试,ptr[4*i+0]为蓝色通道部分
依次进行,我们可以得出:
ptr[4*i+0]=gray; // blue
ptr[4*i+1]=gray;// green
ptr[4*i+2]=gray; // red
ptr[4*i+3]=gray; // alpha
*上述代码可以得出BGRA的顺序,实际上是Bitmap做了处理,下面是获取图片的代码:
Bitmap resultImg = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Bitmap中ARGB_8888实际通道顺序是BGRA
通道分离
在OpenCV中,有专门的函数去处理颜色通道的分离和合并。
网友评论