,,南洋生,
(华中科技大学 光学与电子信息学院,武汉 430074)
20世纪80年代,遥感应用中人们需要获取地物的分布与地物的物质构成,这样的需求使成像光谱技术得到诞生[1]。起初,应用于地物分析的传统大型机载成像光谱仪,空间分辨率限制在米级[2],随着成像探测技术的发展与生产生活的需要,应用于精准农林业分布、病虫检测、水质检测等领域的成像光谱仪逐渐小型化,空间分辨率多在分米或厘米级。目前,基于LCTF[3]的成像光谱仪系统[4]由于其小型化、便携化、功耗低、空间分辨率高等优势,在日常生产生活中逐渐被开发研究。
但是,由于各科研机构的分离性,与成像光谱仪系统硬件配合的软件一直没有适用的框架提出,也没有开源的相关软件在各单位间分享,在开发配套的成像光谱仪软件时,往往花费了大量的重复时间。因此,本文提出了一个适用于LCTF成像光谱仪的软件方案,可扩展性高,方便各单位移植到自己的应用中。
本文的成像光谱仪硬件平台由实验室自主研发,其系统构成框图如图1所示。外界目标物体发射或反射光线经过前置光学系统到达分光器件LCTF,LCTF只允许指定波长的光通过,到达后置光学系统,最终成像在探测模块上,经由终端软件通过通用串行总线(universal serial bus,USB)协议控制LCTF中心透过波长以及成像探测模块,进行光谱图像的采集与显示。
图1 成像光谱仪系统结构框图
分光器件LCTF,基于液晶双折射效应,通过改变对液晶施加的电压大小改变液晶光学特性,对波长进行相位调制,从而实现波段的选择。本文选用的LCTF其波长范围为420 ~ 750 nm,调制分辨率为1 nm,该模块提供了USB接口实现对LCTF的控制。成像探测模块主要由图像传感器与相应外围电路构成,图像传感器有效分辨率为1280 × 960,使用USB控制芯片通过硬件接口配置图像传感器的相应寄存器实现图像数据的输出。因此,终端软件可以基于USB协议,控制成像光谱仪硬件系统实现透过波长的选择与图像的传输控制。
本文设计的成像光谱仪软件主要针对Windows系统的桌面开发,因此采用微软提供的Visual Studio开发套件进行C++程序的开发。桌面程序的开发,需要丰富的界面库支撑,同时为了提高代码的可读性与可扩展性,面向对象编程,使用开源的界面库Qt[5]进行开发。Qt作为一个开源的跨平台的软件开发框架,不仅具有丰富的界面库,同时方便其他平台的开发移植。Qt强大的信号槽机制,能够很容易实现界面控件被触发的响应功能,使线程间的通信变得更加便捷,Qt的事件机制又让动作的触发变得更加灵活。
按照软件开发的流程,首先要明确需求,成像光谱仪软件基本功能就是实现光谱图像的接收、处理、显示以及光谱曲线的分析[6]。为了实现图像接收功能,需要考虑软件与成像光谱仪硬件的通信,实现软件对硬件的控制,需要考虑硬件传输的数据如何在软件端缓存;为了实现图像处理功能,需要考虑软件端何时处理数据,是与数据接收在同一线程还是在另一线程;为了实现显示功能,需要考虑硬件传输的数据经过软件端处理如何传递给界面显示;为了实现光谱曲线的分析,需要考虑如何读取光谱立方体原始数据。因此,开发的光谱仪软件实际可分为四大模块,分别是图像控制与接收模块、图像处理模块、界面显示模块、光谱分析模块。利用面向对象的软件编程思想,即这4个模块可以独立为4个不同的类。
图像控制与接收模块设计为设备类,命名为类CyDevice,负责与成像光谱仪硬件进行通信,为其他模块提供一些可调用控制设备的接口;图像处理模块设计为处理类,命名为类ImageProcess,负责实现图像原始数据到图片数据的转换;界面显示模块即为界面类,命名为类MainWindow,负责用户界面布局,负责实现交互逻辑;光谱分析模块即为光谱分析类,通过新窗口提供,命名为类SpectrumAnalysisDialog,实现光谱分析基本功能,同时为其他的光谱图像处理预留扩展空间。类MainWindow需要控制图像数据的接收与处理,因此需要调用类CyDevice和类ImageProcess的接口,即维护这两个类的实例,如果采用这样的方式,该类的代码又含有响应用户操作的逻辑代码,会显得很冗杂,提高代码维护的难度,降低可读性。因此,再设计一个类,称为类ImageModel,该类维护CyDevice和ImageProcess的实例,为界面类MainWindow提供必要的控制接口,使类MainWindow尽可能的简洁,图像传输与处理的控制代码限制在类ImageModel中维护。
基于Qt开发的桌面程序,至少会有一个线程,也称为主线程或者图像用户界面(graphical user interface,GUI)线程,如果大量逻辑代码都运行在GUI线程中,特别是某些耗时的操作,如数据接收或者处理,将大量占用GUI线程的中央处理器(central processing unit,CPU)时间,从而导致用户点击界面的响应操作滞后,影响用户体验,因此GUI线程应该尽量保证响应用户的操作,减少其他耗时的处理。如果数据接收与处理在同一线程中进行,假设数据接收耗时t接收,数据处理耗时t处理,那么图像显示帧率至多为1/(t接收+t处理),而对于成像光谱仪兼具成像这一特性,将接收与处理并发运行,可以提高帧率,此时帧率主要受限于时间开销较大的一方。因此,最终设计的程序应当至少分配3个线程,GUI主线程用来处理界面,及时响应用户操作,界面不卡顿,同时负责一些短时的控制操作,图像接收线程负责不停地接收硬件传输上来的图像数据,图像处理线程则负责图像处理方面的代码。
由于数据的接收与处理分离到两个线程中进行,因此需要考虑数据在线程间的传递与同步问题,如果数据的缓存空间由二者的任何一方管理,那么另一方必然要调用到对方的接口,加上同步数据的代码,会使得CyDevice和ImageProcess类间具有较高的耦合性,不符合低耦合性的设计理念,会使得两个类的维护互相牵连,提高开发复杂度,增加维护成本。因此,额外设计一个类,管理数据的缓存空间,称为类ImageFifo,将其属性与接口设计为静态类型,不用实例化便可以调用这些接口,且在类中封装易于管理,这样类CyDevice和类ImageProcess间可以通过直接调用类ImageFifo的静态接口,来协调数据的同步与传递。通过这种方式,类CyDevice和类ImageProcess的耦合性大大降低,维护各自的代码更加简单清晰。
因此,通过对成像光谱仪软件的需求分析所提取出的基本功能,将各个功能整理模块化[7],运用面向对象的编程思想,设计不同的类负责不同的功能,考虑类之间低耦合,类内部高内聚[8],设计可扩展、易维护的成像光谱仪软件,其总体方案框图如图2所示。
图2 成像光谱仪软件总体方案框图
接收模块有一个关键性的任务就是解决成像光谱仪软件与硬件间的通信问题,为了使本文研究的成像光谱仪软件设计更加合理,方便后续的功能开发,基于USB通信协议之上,再制定一个属于成像光谱仪应用且易扩展的通信协议,显得很有必要。图像控制与接收模块被设计为类CyDevice,控制命令基于USB协议的控制端点传输,以不同的单字节控制命令码和多字节传输数据,实现对硬件层图像传感器寄存器和LCTF的配置。
对于分光器件LCTF的控制,主要包含LCTF设备的初始化、中心波长的设定、LCTF运行状态的信息反馈。对于成像探测模块的控制与传输,首先需要考虑该模块硬件的初始化操作,其次是成像探测的开始与停止操作。而对于图像传输,成像光谱仪的硬件数据并不是一个标准USB视频(USB Video Class,UVC)格式的数据,所以需要有命令控制帧同步,还需要控制其是否自动曝光,以及手动曝光模式下的曝光时间,需要控制图像传感器的模拟增益设置。
在制定的通信协议的基础上,设计的接口由于软件多线程应用,内部需要通过互斥锁增强线程安全性。数据传输是类CyDevice的关键,成像光谱仪硬件图像数据采用的是USB传输中的批量传输方式,通过发送相应命令码通知硬件进行下一帧的采集,然后调用批量传输的相关接口实现数据接收,其流程图如图3所示。
图3 成像光谱仪软件数据接收接口流程图
成像光谱仪的硬件传输数据是图像传感器的原始数据,即分辨率1 280 × 960,像素位宽为12位,而计算机终端对可显示的图像数据格式有一定的要求。常见的图像格式有灰度图格式,像素位宽8位,取值区间0 ~ 255,显示图片只包含黑白的灰度信息;彩色格式,像素位宽24 bits,由红色、绿色、蓝色三通道构成,每个通道占8位,可以显示彩色图片;彩色透明度格式,相对于彩色格式,多了一个透明度通道,可以显示具有不同透明度的彩色图片。因此,类ImageProcess需要提供图像处理的接口,同时提供一定的弹性预留其他的处理方案,还需要提供一些控制接口供其他类调用,如暂停、拍照、录像的底层接口。
如果将成像光谱仪当做相机应用,其硬件传输的12 bits位宽的原始数据需要选用合适的算法压缩到8 bits,由于系统的噪声首先需要去噪,同时需要一定的图像增强技术对图像进行对比度、边缘细节等信息的增强,这样处理得到的图片显示效果更好。但是,成像光谱仪软件更多的需要体现不同中心波长下的显示效果,如果运用图像增强技术会干扰波长变化对图像数据的影响,不适合成像光谱仪的软件应用。因此,本文研究的成像光谱仪软件在对硬件传输的原始数据去噪后,直接提取高8 bits数据,封装成灰度数据进行显示。但是考虑到,某些场景需要进行图像增强帮助查看场景信息,因此保留图像增强的接口,方便调整需求。为了满足某些需求下的场景空间变换,该类也设计了一些空间变换的接口,例如水平或者垂直镜像。类ImageProcess的关键部分是原始数据到可显示的图像,其运行流程图如图4所示。
图4 成像光谱仪软件原始数据处理流程
中间层类ImageModel封装底层类Cydevice和处理类ImageProcess,为上层的界面模块提供接口方便用户操作逻辑的实现。类ImageModel维护了类CyDevice和类ImageProcess的实例对象,为了提高软件运行效率,还同时维护了两个Qt线程类QThread实例,一个运行图像数据接收的代码,另一个运行图像处理的代码。数据接收与处理部分分别在两个线程中,即导致了无法控制两段代码的运行次序,需要运用一定的技术手段进行图像数据的传递与数据内存空间的访问同步[9],因此设计了类ImageFifo,提供静态接口给数据接收和处理部分的代码进行调用。设计了一个简单结构ImageData,其内部定义了图像数据内存指针m_data、像素位宽m_bitsPerPixel、图像高度m_imageHeight、图像宽度m_imageWidth、当前波长m_wavelength,通过ImageData对象的拷贝传递,实现高效的线程间数据“传递”。类ImageFifo内部实际维护了一个帧缓冲队列,队列成员为ImageData类型,添加了互斥锁进行线程的同步,队列大小初始化时可以调整,并且提前分配好指定大小的数据缓冲内存空间供循环利用。接收与处理线程代码的运行流程图如图5和6所示,这样的方式使得线程间的同步与通信机制明确、易懂、可靠。
图5 接收线程运行流程图
图6 处理线程运行流程图
类MainWindow需要及时处理用户对界面的响应,因此其运行在主线程中,又称为GUI线程。Qt提供的信号槽机制和事件驱动机制大大方便了用户操作响应功能的实现。类MainWindow主要是以用户的操作需求为驱动而设计,需求可能会扩展变更,因此类MainWindow的代码应当清晰整洁,通过调用ImageModel的接口响应用户操作逻辑,保持较高的可维护性。对于用户的界面操作需求,Qt界面框架会捕捉到这些动作,并发出相应的信号,将这些操作信号与类MainWindow合适的槽函数连接,实现界面响应用户的动作。
根据成像光谱仪的成像功能需求,界面类MainWindow需要提供打开、关闭、暂停相机的操作入口,需要提供曝光控制、模拟增益控制的操作入口。而光谱仪功能需要明确光谱图像的采集过程,首先最基本的是功能需要实现分光器件LCTF的初始化以及波长变化,然后需要实现起始波长到终止波长所有波段的白板反射场景的参考图像自动采集,记录当前白板参考场景波长相关的参数信息,按照相同波长设置相同参数的规则,再进行其他场景光谱图像的采集,为光谱分析提供数据准备。
为了保持图像数据信息与波长信息更改的一致性,波长设置的实际动作应当与数据接收在同一线程运行,即GUI主线程发出波长更改操作,更改标志位使接收线程跳出数据接收循环,利用信号槽机制的队列连接,接收线程响应实际动作。白板参考光采集过程都是自动化进行,从起始波长到终止波长,每个波段都需要自动挑选合适的曝光值与增益值,利用二分查找[10]的思想,优化该选择过程,可以提高采集速率。参考光谱采集过程中,使用哈希表[10]存储波长相关的曝光增益值,实现之后其他目标光谱图像采集过程时的参数选择设置。
光谱分析模块是在主窗口点击相应按钮之后,弹出一个子窗口与用户交互,因此,光谱分析功能的接口设计在类SpectrumAnalysisDialog中,可以灵活设计不同的接口与界面实现不同的功能。本文研究的成像光谱仪软件的光谱分析功能,主要需要实现选定图像像素点的光谱曲线的绘制,光谱曲线绘制功能,是实现目标反射光谱的绘制。考虑成像光谱仪应用的波长特性与像素空间分布,目标成像选定像素点的反射率计算公式[11]如下:
(1)
式(1)中,x,y表示图像像素点位置,λ表示波长,V目标(x,y,λ)表示λ波长下的目标图像在像素位置x、y处的像素值,V参考(x,y,λ)表示λ波长下的白板参考图像在像素位置x、y处的像素值,V背景(x,y,λ)表示λ波长下的系统暗电流噪声引起的图像在x、y处的像素值,R参考(x,y,λ)表示λ波长下的图像在像素位置x、y处的反射率。
根据(1)的公式,对于特定目标,可以计算任意位置所有波长下的反射率,从而可以绘制目标图像任意位置的反射率随波长的变化曲线,即光谱曲线。
本文设计的成像光谱仪软件已经在实验室开发的可见光成像光谱仪与近红外成像光谱仪两个平台上使用并测试,均能稳定运行,界面响应流畅无卡顿,并实现了正确的光谱图像采集与显示。在对界面进行极端的点击操作,软件始终能够正确处理请求,无崩溃现象发生。图7显示了波长560 nm下的软件运行状态,图8显示了450 nm、560 nm、720 nm波长下的色卡灰度图像,6个区域分别为红、绿、蓝、青、品红、黄六色。
图7 波长560 nm下的软件运行图
图8 3种波长下的色卡图像
由图8可以看出,随着透过波长的增加,图像整体灰度逐渐升高,这是由于本文采用的LCTF光谱透过率在短波区域较低,而在长波区域较高,尤其是在450 nm附近,透过率极低,只有百分之五左右,导致该波长下成像效果较差。由560 nm和720 nm下的成像可以发现,不同颜色区域对波长的响应不同。绿色波段560 nm下2区域、4区域、6区域灰度值较高,这是因为这3个区域分别为绿色、青色、黄色,都能反射绿波段的光,而720 nm下1区域、5区域、6区域灰度值较高,这是因为这3个区域分别为红色、品红、黄色,都能反射红波段的光。
本文设计并实现的成像光谱仪软件具有很高的可移植性和可扩展性,虽然系统基于本单位研究的成像光谱仪系统,具有一定的特殊性,但是在软件开发过程中,考虑到了这些特殊性,并且预留了相应的接口或者方式供其他硬件方案的软件开发。如类CyDevice的设计主要基于与硬件的通信而开发,虽然本文的通信方式是USB传输,但是如果采用网络传输,利用已知的接口框架只需要在CyDevice层更改通信方式即可,整体软件同样可以运行;如类SpectrumAnalysisDialog提供了光谱分析功能的入口,因此在该类中更改界面布局,提供符合自身应用的其他分析功能,软件同样可以运行。所以,本文提出的软件方案具有很高的弹性,并且这种弹性希望在其他单位开发者参与进来之后,继续优化代码方案,如数据传输层,如果数据接收速度远远超过数据处理速度,有没有更好的缓冲设计,以期实现更完善、更鲁棒的成像光谱仪软件开发框架。