车载前置摄像头学习笔记 ———— 摄像头输出数据格式(JPEG)

介绍

 JPEG 的全称是 Joint Photographic Experts Group,是一种常用的图像存储格式, jpg/jpeg是24位的图像文件格式,也是一种高效率的压缩格式。JPEG 是面向连续色调静止图像的一种压缩标准。其最初是使用64 Kbps的通信线路传输 720×576 分辨率压缩后的图像。通过损失极少的分辨率,可以将图像所需存储量减少至原大小的10%。 .jpg/.jpeg 文件并不适合放大观看,输出成印刷品时品质也会受到影响。一般情况下,.jpg/*.jpeg文件只有几十KB,而色彩数最高可达到24位,所以被广泛运用在Internet上。JPEG 的文件格式一般有两种文件扩展名:.jpg和.jpeg。这两种扩展名从本质上讲没有去别的,我们是可以把 .jpg 的文件改名为 .jpeg,而对文件本身不会有任何影响。

类型

标准JPEG

 以24位颜色存储单个光栅图像,是与平台无关的格式,支持最高级别的压缩,不过,这种压缩是有损耗的。此类型图片在网页下载时只能由上而下依序显示图片,直到图片资料全部下载完毕,才能看到全貌。

渐进式JPEG

 此类型在网页下载时,先呈现出图像的粗略外观后,再慢慢地呈现出完整的内容,而且存成渐进式JPG格式的文档比存成标准JPG格式的文档要来得小,所以如果要在网页上使用图像,可以多用这种格式。

JPEG2000

 新一代的影像压缩法,压缩品质更好,其压缩率比标准JPEG高约30%左右,同时支持有损和无损压缩。一个极其重要的特征在于它能实现渐进传输,即先传输图像的轮廓,然后逐步传输数据,让图像由朦胧到清晰显示。它可以改善在无线传输时,因信号不稳造成马赛克现象及位置错乱的情况,改善传输的品质。

压缩类型

顺序式编码(SequentialEncoding)

 编码,解码通过从左到右,从上到下一次扫描完成。

递增式编码(ProgressiveEncoding)

 编码,解码需要多次扫描完成,扫描效果从模糊逐渐清晰。

无失真编码(LosslessEncoding)

 解码后能完全恢复到原图像的采样值。

阶梯式编码(HierarchicalEncoding)

 图像在多个空间分辨率中进行编码,可以根据实际需要选择不同分辨率进行解码。

压缩步骤

颜色转换

 JPEG采用的是YCrCb颜色空间,而BMP采用的是RGB颜色空间,要想对BMP图片进行压缩,首先需要进行颜色空间的转换。YCrCb颜色空间中,Y代表亮度,Cr,Cb则代表色度和饱和度(也有人将Cb,Cr两者统称为色度),三者通常以Y,U,V来表示,即用U代表Cb,用V代表Cr。RGB和YCrCb之间的转换关系如下所示:
  Y = 0.299R+0.587G+0.114B
  Cb = -0.1687R-0.3313G+0.5B+128
  Cr = 0.5R=0.418G-0.0813B+128
 一般来说,C 值 (包括 Cb Cr) 应该是一个有符号的数字, 但这里通过加上128,使其变为8位的无符号整数,从而方便数据的存储和计算。
  R = Y+1.402(Cr-128)
  G = Y-0.34414(Cb-128)-0.71414(Cr-128)
  B = Y+1.772(Cb-128)

DCT变换

 DCT(Discrete Cosine Transform,离散余弦变换),是码率压缩中常用的一种变换编码方法。任何连续的实对称函数的傅里叶变换中只含有余弦项,因此,余弦变换同傅里叶变换一样具有明确的物理意义。DCT是先将整体图像分成NN的像素块,然后针对NN的像素块逐一进行DCT操作。需要提醒的是,JPEG的编码过程需要进行正向离散余弦变换,而解码过程则需要反向离散余弦变换。

量化

 图像数据转换为DCT频率系数之后,还要进行量化阶段,才能进入编码过程。量化阶段需要两个8*8量化矩阵数据,一个是专门处理亮度的频率系数,另一个则是针对色度的频率系数,将频率系数除以量化矩阵的值之后取整,即完成了量化过程。当频率系数经过量化之后,将频率系数由浮点数转变为整数,这才便于执行最后的编码。不难发现,经过量化阶段之后,所有的数据只保留了整数近似值,也就再度损失了一些数据内容。在JPEG算法中,由于对亮度和色度的精度要求不同,分别对亮度和色度采用不同的量化表。前者细量化,后者粗量化。

编码

  在得到DC系数的中间格式和AC系数的中间格式之后,为进一步压缩图象数据,有必要对两者进行熵编码。JPEG标准具体规定了两种熵编码方式:Huffman编码和算术编码。JPEG基本系统规定采用Huffman编码(因为不存在专利问题),但JPEG标准并没有限制JPEG算法必须用Huffman编码方式或者算术编码方式。 Huffman编码:对出现概率大的字符分配字符长度较短的二进制编码,对出现概率小的字符分配字符长度较长的二进制编码,从而使得字符的平均编码长度最短。Huffman编码的原理请参考数据结构中的Huffman树或者最优二叉树。Huffman编码时DC系数与AC系数分别采用不同的Huffman编码表,对于亮度和色度也采用不同的Huffman编码表。因此,需要4张Huffman编码表才能完成熵编码的工作。具体的Huffman编码采用查表的方式来高效地完成。然而,在JPEG标准中没有定义缺省的Huffman表,用户可以根据实际应用自由选择,也可以使用JPEG标准推荐的Huffman表。或者预先定义一个通用的Huffman表,也可以针对一副特定的图像,在压缩编码前通过搜集其统计特征来计算Huffman表的值。

格式

 JPEG图片格式组成部分:SOI(文件头)+APP0(图像识别信息)+ DQT(定义量化表)+ SOF0(图像基本信息)+ DHT(定义Huffman表) + DRI(定义重新开始间隔)+ SOS(扫描行开始)+ EOI(文件尾)。其中粗体部分是必须的,下面我就来解释一下这些信息吧。

SOI文件头

 JPEG文件的开始2个字节都是FF D8这是JPEG协议规定的。

名称 字节数
段标识 1 FF
段类型 1 D8

APP0图像识别信息

名称 字节数 说明
段标识 1 FF -
段类型 1 E0 -
段长度 2 0010 示例表示16个字节。如果有RGB缩略图,此处为16+3n
交换格式 5 4A46494600 示例表示JFIF的ASII码,还可以是TFIF(使用频率很低)
主版本号 1 01 示例表示主版本号为1
次版本 1 01 示例表示次版本号为1
密度单位 1 01 示例表示密度单位为点数/英寸
0 —— 无单位
1 —— 点数/英寸
2 —— 点数/厘米
X像素密度 2 0060 示例表示水平像素密度是96
Y像素密度 2 0060 示例表示垂直像素密度是96
缩略图X像素 1 00 示例表示没有缩略图
缩略图Y像素 1 00 没有缩略图
RGB缩略图 3n - n(缩略图像素总数)=缩略图X像素*缩略图Y像素

DQT定义量化表

名称 字节数 说明
段标识 1 FF
段类型 1 DB
段长度 2 0043 其值=3+n(当只有一个QT时)
QT信息 0-3位 QT号 0=8bit,1字节;否则=16bit,2字节
4-7位 QT精度
QT n n=64×QT精度的字节数

SOF0图像基本信息

名称 字节数 说明
段标识 1 FF
段类型 1 C0
段长度 2 0011 17 = 8 + 3*3,说明组件数量有3个
样本精度 1 08 每个样本的信息是8bit,大多数软件不支持12和16
图片高度 2 01E0 480图片高度与实际一致
图片宽度 2 0140 320图片宽度与实际一致
组件数量 1 03 1 —— 灰度图
3 —— YCbCr彩色图
4 —— CMYK彩色图
组件 ID 1 - 1 —— Y
2 —— Cb
3 —— Cr
4 —— I
5 —— Q
采样系数 0-3位 - 垂直采样系数
4-7位 - 水平采样系数
量化表号 1 - -

DHT定义huffman表

名称 字节数 说明
段标识 1 FF
段类型 1 C4
段长度 2 00 1F 31 = 19(段长度2个字节+HT信息1个字节+HT位表16个字节) + 12(这个数代表HT表有12个字节)
HT信息 0-3位 - HT号
第4位 - 0 —— DC表
1 —— AC表
5-7位 - 必须为0
HT位表 16 - 16个数字值和小于等于256
HT值表 n n=表头16个数的和

SOS扫描行开始

名称 字节数 说明
段标识 1 FF
段类型 1 DA
段长度 2 000C 12 = 6(2个字节的扫描行开始头+1个字节扫描行内组件数量+3个字节的剩余位) + 2×3(扫描行内组件数量,每个组件2个字节)
扫描行内组件数量 1 3 必须∈[1,4],否则错误,通常=3
组件 ID 1 - 1 —— Y
2 —— Cb
3 —— Cr
4 —— I
5 —— Q
Huffman表号 0-3位 AC表号 (其值=0...3)
4-7位 DC表号(其值=0...3)
剩余字节 3 最后3个字节用途暂时不明

EOI文件尾

名称 字节数
段标识 1 FF
段类型 1 D9

其它段

COM(注释)

名称 字节数 说明
段标识 1 FF
段类型 1 FE
段长度 2 - 其值=注释字符的字节数+2
段内容 n - 注释字符

DRI(定义重新开始间隔)

名称 字节数 说明
段标识 1 FF
段类型 1 DD
段长度 2 - -
开始间隔 2 - 复位标记的间隔距离
获取USB摄像头的1080p的JPEG格式的图片20180608_1806.7z 电脑上的系统:ubuntu14.04 // http://www.linuxidc.com/Linux/2011-03/33020.htm // V4L2摄像头获取单幅图片测试程序(MMAP模式) // [日期:2011-03-06] 来源:Linux社区 作者:aokikyon [字体:大 中 小] // // #加了点注释 // // #Rockie Cheng // printf #include #include // memset #include #include #include #include // close write usleep read #include #include #include #include #include #include // mmap #include #include #include #include // pthread_create pthread_join #include #define CLEAR(x) memset (&(x), 0, sizeof (x)) #define REQ_COUNT 6 #define uchar unsigned char struct buffer { void * start; size_t length; }; static char * dev_name = "/dev/video0";//摄像头设备名 static int fd = -1; struct buffer * buffers = NULL; // static unsigned int n_buffers = 0; // 2012-7-13 11:33 camera flag // static int iFlagCamera = 0; volatile int iFlagCamera = 0; // 函数名称:thread1 // 函数功能:用于接受键盘的输入,之后通知thread2抓图 // 参数列表: // 返回值 : void thread1(void) { char ch; printf("\n !!!!Warning!!!!\n Max 1000 color bmp\n Input the char: \n"); printf("\n !!!!press o an capture 1 frame picture! \n"); printf("\n !!!!press t an capture 10 frame picture! \n"); printf("\n !!!!press h an capture 100 frame picture! \n"); while(1) { while((ch=getchar()) != '\n') { printf("%c\n", ch); if('o'==ch) { iFlagCamera = 1; printf("thread1=%d\n", iFlagCamera); } else if('t'==ch) { iFlagCamera = 10; printf("thread1=%d\n", iFlagCamera); } else if('h'==ch) { iFlagCamera = 101; printf("thread1=%d\n", iFlagCamera); } else if('q'==ch) { iFlagCamera = 10001; printf("thread1=%d\n", iFlagCamera
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小趴菜_自动驾驶搬砖人

谢谢大爷赏饭吃

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值