1、毕业设计(论文) 第34页 毕业设计(论文) 设计(论文)题目:液位监测系统数据采集的设计与实现 学生姓名 专业班级 指导老师 系主任(院长) 5 月 24日 液位监测系统数据采集模块 摘 要 液位监测是针对液体并且遵循特定的步骤对水液体的液位高度进行信息采集,数据计算,结果分析,结果反馈的监测系
2、统。数据采集是液位监测技术中非常重要的一部分,是液位监测系统所要实现的第一步。传统的数据采集方式一般是靠浮力计,变阻计等接触式测量设备来获取液位的信息。本文所讨论的数据采集技术与传统的方式有所不同,它依靠摄像头来捕获液位的图像信息,以linux操作系统及其开源技术为背景,通过对摄像头的图像捕获技术的探索分析来设计符合数据采集模块要求的具体实现。同时通过研究目前流行的图片压缩技术和多对一监测模型,整理出一套集数据压缩,传输,解压,识别,校正,显示为一体的实现方案。设计中使用JPEG格式来存储图像,通过具体实现展示出数据捕获技术和数据压缩技术在液位监测系统中所起到的重要作用。 关键词:数据采
3、集,图像压缩,图像显示 The data collection module of water line surveillance system Abstract The water line surveillance system is a minitor system that ,objected to water and followed certain procedure, to do the operation such as capturing and calculating the information ,analies and return the resu
4、lt.The date collectin module is a very important to the water line surveillance system,and is the first procedure the minitor must do.The traditional approching method is relied on the touched-equipment such as float-instrument or resistance-instrument to capture the water line information.The main
5、content of this design is discuss and implement the water line surveillance system. The main technical based on is Linux OS and its open source technology, through the video technology learn to design a specify the request from the data collection module. In the mean time through to study the presen
6、t fashion image compression technology I turn out to summarize a schema that take compression and transmit and recognize and check right and show together. In the design I use the JPEG format to save image, and through that implement to show the great effect on water line surveillance by the data ca
7、tch and data compression technology. Key word: data collection,image compression,image visual 目 录 液位监测系统数据采集模块 I 第1章 绪论 1 1.1 液位监测系统数据采集技术的发展 1 1.2 图像数据采集技术在嵌入式中的应用 2 第2章 数据采集的理论基础 4 2.1 图像编码 4 2.1.1 哈夫曼编码的原理 5 2.1.2 哈夫曼编码在图像压缩中的实现 6 2.2 算术编码 10 第3章 数据采集的设计实现 12 3.1 JPEG图像压缩过程分析
8、 12 3.1.1 前向DCT变换 12 3.1.2 量化 13 3.1.3 哈夫曼编码 14 3.2 试验图像数据的获取 16 3.2.1 BMP图像的格式 17 3.2.2 BMP图像的翻转和精简图像文件的存储 20 3.3 JPEG图像压缩的实现 20 第4章 数据采集程序的安装与运行 23 4.1 内核的启动 23 4.2 程序的编译 23 4.3 程序的运行 23 小结 24 致谢 24 参考文献 25 附录A video 4 Linux 接口 26 1.ov511芯片的摄像头和的zc301芯片的摄像头: 26 2.ov511驱动加载 26 附录
9、B zc301 驱动 27 1 zc301 驱动 27 2 Video4linux 27 第1章 绪论 1.1 液位监测系统数据采集技术的发展 传统的液位监测系统数据采集技术有浮力计式,变阻计式和杠杆式的。浮力式主要利用水体的浮力特性,水位的高低不同,浮力计在水面的上浮落差也就不同,通过这种落差的测量来得到水位的数据。变阻计式类似于浮力计式的,但是它不需要去测量浮动落差,它根据电力学的原理,将浮动的落差信息转化为电阻的信息,然后通过测量电流的大小来得到水位的高低[6]。杠杆式利用了水压的性质,一般来说,水位越高,在水底的水压压强越大,通过杠杆的性质在去测
10、量水底的压强可是得到水位的高低。 近几十年,液位监测系统数据采集技术发展迅猛,采集技术已经由传统的接触式的浮力计式,电阻计式,杠杆计式发展到目前的超声波水位监测,控制电路水位监测,汽包水位监测,光纤传感器水位监测等方式。超声波水位监测系统主要利用了超声波的反射和波速的性质,由水面系统发出一段超声波,超声波穿透水体达到水底然后被反射回来,反射回来的超声波被液位监测系统接收到,液位监测系统在发送超声波时开始计算时间,当它接收到返回来的越起波后就停止计时,这样可以得到超声波到达水底然后反射回来的总时间,又因为超声波的波速是已知的,于是超声波所经过的路程可以计算出来,这样就得到了水位的高度[3]。
11、 传统的液位监测数据采集技术具有设计简单,成本低的优点,它们的缺点是计算数据不精确,容易损坏,突发情况反馈不及时,安全性没有保障。 现代液位监测系统数据采集技术采用的是非接触式手段,利用高科技技术,如大规模集成电路,光纤电缆,超声波测距等,更加准确的测量出水位并非常及时的反馈给人们,甚至可以自动的对水位检测结果采取相应的措施,但是它们的缺点是所需的成本很高,对设备的质量和性能要求非常严格,操作起来需要专业的操作人员,发生问题不易修复。 为了消除传统的液位监测系统数据采集技术的缺点,吸收现代液位监测系统数据采集技术的优点,同时又能降低系统建设的成本,增加系统的可用性,独立性和稳定性,本设计创
12、造性的使用图像捕获技术来实现液位数据的采集。图像数据采集技术采用了目前先进的图像获取和处理技术,使用廉价稳定的摄像头作为数据的采集设备,运用高效的图像压缩算法来处理图像,使用嵌入式设备作为软件载体,以达到数据采集的高效,精确,稳定,安全的目的。 液位监测系统图像数据采集技术的原理是,使用摄像头拍摄水位图片,采取恰当的曝光手段获得清晰的易处理的RGB颜色模式的BMP格式图片,然后对获得的BMP格式图片采用高效的压缩算法进行压缩处理,得到目前流行的JPEG格式的图像文件,最后把JPEG文件通过网络传输到PC监视机上进行解压运算,分析,比对以得到液位高度。 数据采集模块所需要的设备有zc301芯
13、片的摄像头,装有arm9处理器的嵌入式板,小键盘,USB接口及USB连接线,PC机。选择zc301摄像头是因为zc301的摄像头性能优越,价格低廉,与linux操作系统兼容的比较好。使用arm9处理器是因为arm9处理器占据空间小,所需资源少,性能稳定,特别适合运行linux操作系统及其应用程序。 本设计实现了数据采集模块的主要功能,数据采集模块的主要功能是图片获取,图像压缩,图片传输,图片解压和图片显示。运行数据采集模块程序,它首先是打开zc301摄像头,进行必要的初始化参数,然后朝向液体表面进行拍摄,拍摄得到的是RGB颜色模式的BMP格式的图片,这是最原始的图片,它所占的空间比较大,它可
14、以直接在屏上显示,但是不利于网络传输,因为它占太多的带宽。获得了BMP格式的图像之后数据采集程序会自动将它压缩成目前流行的JPEG格式的图片,压缩比为50:1,压缩生成的JPEG图片将被传输到PC监视机上进行分析研究。后面的第 2章着重讲述了图片的压缩算法。 1.2 图像数据采集技术在嵌入式中的应用 本设计采用linux嵌入式环境。Linux操作系统是Unix的克隆,是一个支持多用户, 多进程,多线程,实时性较好的功能强大而稳定的操作系统,它可以运行x86 PC,Sun Sparc,Digital Alpha,680x0,PowerPC, MIPS等平台上,在本设计中,它运行在arm
15、9平台上。 嵌入式系统被定义为:以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。 嵌入式系统是面向用户、面向产品、面向应用的,如果独立于应用自行发展,则会失去市场。嵌入式处理器的功耗、体积、成本、可靠性、速度、处理能力、电磁兼容性等方面均受到应用要求的制约,这些也是各个半导体厂商之间竞争的热点。嵌入式处理器的应用软件是实现嵌入式系统功能的关键。软件要求固化存储,软件代码要求高质量、高可靠性,系统软件(OS)的高实时性是基本要求。 本设计采用linux嵌入式环境是因为linux操作系统稳定可靠,arm9平台功
16、能强大而设备精简,所占体积小,效率非常高。Linux内核版本为2.0.35,内自带了USB驱动,摄像头采用zc301摄像头,驱动需要自己载入。 本设计的系统流程是这样的,首先将u-boot引导程序烧入嵌入式开发板中,然后运行u-boot,把linux核引导进开发板中,整个过程通过PC机的超级终端minicom控制,PC机与开发板用一条并口线相连,linux 先引导完成,然后就启动linux,当操作系统把控制权交组用户后,用insmod命令动态加载设像头驱动程序,然后编写代码打开摄像头,拍摄图片数据,运行远程服务,对PC机的客户数据请求,服务端把图片数据输给PC机上的客户端,然后在PC机上对
17、图片数据解码保存,需要时在LCD上显示出来。当需要观看动态效果,就要连续的播放图片到LCD显示器上。后面第3章着重讲述了数据采集的实现原理。附录中介绍了video for Linux(video 4 Linux)的接口,以及它的使用。 第2章 数据采集的理论基础 2.1 图像编码 本设计中的实现过程包括三部分: 第一部分为摄像头控制部分,主要工作是编写程序实现摄像头驱动的加载,摄像的打开,设置参数,初始化,读取摄像头芯片信息,然后是摄像头的拍摄,获取位图数据。 第二部分为图像压缩部分,主要工作是对摄像头获取的位图数据进行压缩,形成jpeg文件。 第三部分为图像的传输部
18、分,主要工作是编写服务程序,给一台或多台用于监测图像的PC机提供图像数据传输服务。 系统的框架图如下: 摄像头 嵌入式板 PC机 BMP数据 JPEG数据 数据采集程序 数据传输服务 JPEG编码程序 JPEG解码程序 图2-1系统框架图 在本设计中,图像是以位图的方式被摄像头记录的。位图亦称为点阵图像或绘制图像,是由称作像素(图片元素)的单个点组成的。这些点可以进行不同的排列和染色以构成图样。当放大位图时,可以看见赖以构成整个图像的无数单个方块。 RGB是位图颜色的一种编码方法,用红、绿、蓝三原色的光学强度来表示一种颜色。这是最常见的位图
19、编码方法,可以直接用于屏幕显示[4]。 但是由于摄像头刚拍摄出来的位图所占的储空间很大,不利用图片永久存储和网络传输,因为那样会占用太多的硬盘空间和网络带宽,于是我们必须对位图进行压缩,然后才存储和转输,等到要看图片的时候,再把压缩后的图片解压缩成位图。 目前对位图的压缩方式有很多,但是最流行且压缩效率最高的还是JPEG编码。而JPEG编码原理里面用到到了最重要的两种编码原理,一种是哈夫曼编码,另一种就是算术编码。 2.1.1 哈夫曼编码的原理 哈夫曼编码是压缩编码中常用的一种编码方,JPEG标准中基准模式采用的就是哈夫曼编码。 哈夫曼编码基于不同符号的概率分布,对出现次数较
20、多的符号赋予较短的代码,出现次数较少的符号赋予较长的代码。这里,以一个例子说明如何赋予各个符号哈夫曼码值,即如何生成哈夫曼表。 假设将对由1,2,3,4,5,6,7,共7个数字组成的原信息进行哈夫曼编码,首先应对信息中各个数字出现的次数进行统计,得出各个数字的出现的相对概率。假设各个数据出现的次数如表2-1所示。 表2-1 7个数字的概率分布 数字 1 2 3 4 5 6 7 出现的次数 10 10 10 20 20 25 5 相对概率 0.1 0.1 0.1 0.2 0.2 0.25
21、 0.05 根据表2-1生成哈夫曼树如图2-1所示。 具体的过程是这样的。先将所有的数字随意排列成一行构成7个最底层节点,首先将这一行中最小的两个概率值相加,0.1+0.05=0.15得到新的节点。这时拥有的概率值为0.2,0.2,0.2,0.1,0.1,0.15,0.25,再将这时最小的两个概率值相加,0.1+0.1=0.2得到新的节点。这时拥有的概率值为0.2,0.2,0.2,0.2,0.15,0.25,再将这时最小的两个概率值相加……,直到得到根节点,概率值为1.0为止。相加时,对于概率值相等的多个节点,可以任意选取。 除根节点外,设节点左面的分支为0,右边的分支为1(当然,
22、也可以反 过来),对于各个数值的代码就是从根节点出发到最底层的节点所经过的分支的序列。如4的代码为00,7的码值为1011,通常将4和7称为码值(Code value),00和1011被称为相应的码字(Code word),所有码字和码值的对应关系如表2-2所示。进行压缩编码时,只要将原数字(码值)用码字代替即可。 如果概率统计十分不准确,则压缩效率会很低,甚至起不到压缩效果。 图2-3 由表2-1生成的哈夫曼树 将所有的码字和码值生成一个表,表达码字和码值的对应关系,称为哈夫曼表,为了整字节的输出码字,表中还要有各个码字
23、的长度,例如JPEG标准中推荐的亮度信息直流系数的哈夫曼表如表2-3所示。 表2-2由图2-1得到的码字和码值的对应关系 码值 1 2 3 4 5 6 7 码字 1000 1001 1010 00 01 11 1011 哈夫曼表一般是事先确定的,(也可以在线实时调整)。本文以JPEG中的一个哈夫曼表(表2-3)为例,来说明如何实现哈夫曼编码,解码。 2.1.2 哈夫曼编码在图像压缩中的实现 在JPEG文件格式中,哈夫曼表以哈夫曼码字中位数相
24、同的个数和所有的哈夫曼码值的形式存储,实际上是存储了一个哈夫曼树[5]。根据JPEG文件开始部分对于亮度信息所用的哈夫曼表(对应表2-3)说明字段的可以得到下面两 个数组: bits[17] = { 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; huffval[] ={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; 表2-3 JPEG标注中推荐的亮度信息哈夫曼表 码值 码字的长度 码字 0 1 2 3 4 5 6 7 8 9 10
25、11 2 3 3 3 3 3 4 5 6 7 8 9 00 010 011 100 101 110 1110 11110 111110 1111110 11111110 111111110 这两个数组和上面那个表是对应的。bits[]数组中的元素除bits[0]外,bits[1],bits[2],bits[3],…bits[16]代表哈夫曼代码中长度为1,2,3…16的个数。huffval[]中的各个元素是按照哈夫曼代码长度递增的顺序相对应的哈夫曼值(Huffman value),
26、也即被代表的信息,如果几个元素对应的哈夫曼代码长度相同,顺序可以交换。从这两个数组出发,看看是如何实现编码的。 首先,应该生成哈夫曼表。建立huffcode[],huffcode[],ehufco[],ehufsi[]四个整数型数组,此处它们的元素个数只要大于12即可。 第一步:得到huffsize[]。 int p,l,i,lastp; p = 0; for (l = 1; l <= 16; l++) { i = bits[l]; while (i--) huffsize[p++] = l; } huffsize[p] = 0; /*使huffsize[]
27、最后一个元素为零,是为了后面生成huffcode[]时,能够跳出循环*/ lastp=p; /* lastp-1即是所有码值的个数,后面的程序要用到它*/ 这样, huffsize[]对12个哈夫曼码字的有效位的位数(单位是Bit)都有了记录,这主要使为了编码后输出码字时一定要知道码字的长度。 第二步得到huffcode[],它的各个元素是与huffsize[]各元素相对应的哈夫曼码字。 { int code,si; code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while ( huff
28、size[p] == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } } 从程序中可以看出,相邻的相同长度的哈夫曼码字彼此间差1。长度为si+1的代码中数值最小的代码,是长度为si的代码中数值最大的代码加1后并左移一位,这就能保证没有任何一个代码是另外一个代码的前缀,也就是说11,110这样的两个代码是不允许的。否则,解码时就会出现问题。 第三步得到ehufco[],ehufsi[]。 for (p = 0; p < lastp; p++) { i = huffval[p]; ehuf
29、co[i] = huffcode[p]; ehufsi[i] = huffsize[p]; } 很简单,这里只是将huffcode[],huffsize[]中的元素调整了顺序,赋予了ehufco[],ehufsi[],以val[]的元素为索引值。显然,这样调整后,哈夫曼编码的过程就是一个查表过程。下面看看哈夫曼编码及输出编码信息的过程,事先定义一结构体: struct save { int put_bits;/*记录目前缓存中的数据的位数*/ int put_buffer;/*输出缓存*/ } 两个成员应初始化为0,save在对整个信息源(比如一幅图像)进行哈夫曼
30、编码的过程中有效。
哈夫曼码字往往不正好是整数个字节,而在存储时计算机中文件的存储是以字节为单位的,这里将以C语言程序为例说明如何将哈夫曼编码后的数据逐字节的输出。假设要对v(-1 31、缓存中的数据的位数 */
put_buffer <<=24 - put_bits;/*将码字移到紧靠原有数据的位置*/
put_buffer |= saved.put_buffer;/*将码字和缓存中的旧有数据放在一起*/
while (put_bits >= 8) {
int c = (int) ((put_buffer >> 16) & 0xFF);
emit_byte(c);/*输出一个字节的数据 */
if (c == 0xFF) {
emit_byte( 0); /*遵循JPEG规范,在编码数据0XFF后,加上0X00*/
}
put_buffer 32、 <<= 8;
put_bits -= 8;
}
saved.put_buffer = put_buffer; /*将未输出的数据保留*/
saved.put_bits = put_bits;/*记录未输出数据的位数*/
}
这里为哈夫曼码字的输出开辟了24bits的缓存(put_buffer的低24位),数据总是在缓存的最左端。每当缓存中的数据大于一个字节时,就调用emit_byte( )函数输出一个字节到输出缓存中。每次往24bits的缓存中送数据时,缓存中至少有24-7=17Bits的空间,故每次数据的长度不应超过17Bits。
以上面的程序为基础构成循环,就可以






