郭艳飞 宋丽华 简阳
摘 要:由于嵌入式系统的系统资源的有限性,系统上的摄像头设备多通过插值等方法获得伪高分辨率,无法满足文字识别应用的需求。为解决这个问题,文章首先分析了S3C6410嵌入式处理器的camera模块接口的特性,介绍其与CMOS摄像头的硬件连接方法,并在Windows CE6.0操作系统上采用DirectShow技术设计并实现了500万像素高分辨率摄像头驱动。通过实验进行验证分析,结果表明该摄像头驱动运行稳定,对其获得的文字图片进行识别,测试结果显示识别率达到99.5%。
关键词:camera驱动;高分辨率;DirectShow;Windows CE6.0;S3C6410
中图分类号:TP303 文献标识码:A
Abstract:On account of the limitation of system resources in embedded platforms,methods like interpolation are commonly applied to obtain pseudo-high-resolution images,but which cannot meet the requirements of character recognition.In order to solve this problem,the thesis firstly analyzes the camera module interface features of the embedded processor S3C6410,and then introduces the connection method between the camera module interface and CMOS camera hardware.With the application of DirectShow technology in Windows CE6.0,the driver for high-resolution cameras(up to 5 million pixels)has been developed.A verification experiment has been conducted and the result indicates that the camera driver has both high reusability and high stability.A testing experiment has been conducted to verify the high resolution and the result shows that the recognition rate is up to 99.5%.
Keywords:camera driver;high resolution;DirectShow;Windows CE6.0;S3C6410
1 引言(Introduction)
随着嵌入式处理器的发展和硬件成本的不断降低,拍照和摄像功能也在各种嵌入式系统中得到了广泛应用,比如拍照手机,小型监控设备等等[1,2]。但由于嵌入式系统的处理速度和内存空间有限,使得嵌入式手持设备在处理图像数据方面受到限制,所以传统嵌入式系统的摄像头的分辨率都比较低,无法满足人们即时捕获高质量图片和视频的需求。在文字识别方面,通过插值等方法达到伪高分辨率的图像达不到识别要求[3,4],实际捕获高分辨率,高质量图像成为必要条件,因此在基于嵌入式平台,设计并实现一种高有效分辨率的摄像头的驱动程序变得必要且有实际应用价值。
Windows CE是一个紧凑、高效和可扩展的嵌入式操作系统。在多媒体应用方面,微软将DirectShow技术集成在Windows CE6.0系统中,为音视频采集等高性能要求提供了解决方案[5]。本文采用Q5M02A CMOS摄像头模块,在基于S3C6410平台的Windows CE6.0系统下实现实际有效分辨率为500万像素的摄像头驱动,为采集高质量的实时图像提供解决方案。
2 摄像头驱动硬件平台(Hardware platform for camera driver)
2.1 S3C6410硬件平台
S3C6410是SAMSUNG公司基于ARM1176的一款低功率、高性价比、高性能低功耗的RSIC通用微处理器,它采用64/32bit的内部总线架构,融合AXI、AHB、APB总线。典型主频533MHz,最高可达667MHz,CPU内部集成强大的硬件加速器,MFC(Multi-Format video Codec),3D加速器,優化的外部存储器接口,TFT 24bit真彩色LCD控制器,4通道的UART和定时器,32通道的DMA,I2C总线,USB Host,Camera接口等。功能强大,便于各种系统的开发,因此应用十分广泛[6]。
Camera接口的主要性能包括:
(1)最大支持4096×4096像素的相机输入。
(2)编解码/预览镜像和旋转(只对预览图像),有X翻转、Y翻转,90度、180度和270度旋转功能。
(3)支持ITU-R601/656 8位模式。
(4)支持YCbCr4:2:2图像格式。
(5)数据缩放功能。
(6)视频同步信号极性的可编程。
(7)支持LCD控制器直接路径。
(8)编解码/预览输出图像产生(RGB16/18/24位格式和YCbCr4:2:2/YCbCr4:2:0格式)。
(9)支持相机图像捕捉帧控制功能。
(10)支持扫描线消除功能。
(11)支持交错相机输入。
2.2 Q5M02A摄像头模块
Q5M02A摄像头模块采用实际有效像素为500万的CMOS图像传感器,图像处理芯片采用的是CLI6000/CLI6001,此芯片负责图像数据的处理以及与主机的通信。CLI6000/CLI6001将传感器的原始数据拼接成YCbCr4:2:2格式的数据,以适应应用处理器的进一步处理,其功能包括黑电平校正、减少热像素、缺陷像素校正、边缘保持降噪、色彩校正与插值、镜头阴影校正、白平衡和重点控制等等功能。支持多种图像输出格式VGA、SXGA、QVGA等图像输出格式。CLI6000/CLI6001内部寄存器的设置是通过I2C接口进行的。
2.3 摄像头驱动硬件平台的设计与实现
本系统是基于S3C6410的嵌入式开发板,同时S3C6410处理器集成有camera接口,因此像素时钟信号、行同步信号、帧同步信号、复位信号、主时钟信号和像素数据都可以通过camera接口与摄像头模块进行连接。另外,通过系统的I2C总线完成对摄像头内部寄存器的设置。S3C6410处理器与摄像头模块的连接如图1所示。
(1)camera接口
S3C6410集成camera模块,其接口用于连接摄像头模块和处理器,完成两者的数据通讯,该接口发送或者接受摄像头模块的数据和控制信号,然后将得到的数据通过DMA或者FIFO方式送到内存。
S3C6410的camera模块的外部接口定义如下:
a.CIF_MCLK:输出的S3C6410主时钟,当外接的图像处理芯片有独立的时钟时, 该信号可被忽略掉。
b.CIF_PCLK:输入的图像视频像素同步时钟。
c.CIF_VSYNC:输入的图像视频帧同步时钟。
d.CIF_HREF:输入的图像视频行同步时钟。
e.CIF_DD[0]—CIF_DD:输入的图像视频的8位数据[7]。
(2)I2C接口
I2C总线可发送和接收数据,由数据线SDA和时钟线SCL构成的串行总线,最高传送速率100kbps。I2C总线共有三种类型信号:开始信号、应答信号和结束信号。本系统中对摄像头芯片寄存器的设置是通过I2C总线来完成的。
摄像头驱动系统中主时钟是由S3C6410提供,而像素时钟,帧同步,行同步信号是有摄像头模块提供,S3C6410的GPF3口控制摄像头模块的复位信号,而对于摄像头模块寄存器的读写是通过I2C总线来完成的。
3 Windows CE6.0下攝像头驱动的开发(Camera driver development based on Windows CE6.0)
在Windows CE6.0下开发摄像头驱动,为了减少自己的工作量,可以在微软的模板代码的基础上进行开发。由于微软的摄像头模板驱动代码是基于DirectShow技术的分层驱动,现只需开发摄像头的基本控制机制,上层的控制策略部分工作量相对小一些。驱动的整体架构图如图2所示。
本文是在保持MDD层控制策略不变的情况下,对PDD层以下的各个模块进行控制机制开发,PDD层主要是对摄像头驱动涉及的四大模块进行操作,主要包括调用I2C总线配置摄像头图像处理芯片的寄存器,用GPIO模块控制摄像头的复位,PWM模块提供时钟,对camera接口的操作则实现图像数据的采集和处理。
3.1 配置Q5M02A摄像头模块内部寄存器
Q5M02A摄像头模块中的图像处理芯片是CLI6000/CLI6001,对其内部寄存器的配置是通过I2C总线来完成的。Q5M02A输出的图像是逐行扫描的。对其主要寄存器设置如下:
a.自动阴影补偿。
b.对其图像输出格式设置为YCbCr4:2:2。
c.像素时钟PCLK为56MHz。
d.YCbCr数据顺序为CbYCrY。
e.图像的宽度为2560,高度为1920。
对CLI6000/CLI6001芯片的初始化首先需要打开I2C设备,然后设置其通信的时钟频率为2400以及延迟。
3.2 对S3C6410的camera接口的操作
S3C6410集成camera模块,对其接口寄存器的设置主要包括:
a.设置输入图像信号宽为2560像素,高为1920像素。
b.设置输入视频信号的格式为ITU601,YCbCr4:2:0。
c.设置输入图像信号的数据为CbYCrY。
d.根据用户需要设置C通道和P通道图像数据的宽度和高度。
e.设置C通道和P通道图像数据的缩放系数。
f.将C通道和P通道的DMA地址与4组数据信号的寄存器关联起来。
在本系统的摄像头驱动中定义了一个关键的数据结构MODULE_DESCRIPTOR,它对摄像头接口的链接属性进行定义存储,在摄像头驱动初始化的时候被初始化。MODULE_DESCRIPTOR的具体定义如下:
typedef struct _MODULE_DESCRIPTOR
{
BYTE ITUXXX; //对ITU-601/656 8位模式选择
BYTE UVOffset; //Cb,Cr偏移量
BYTE Order422; //YCbYCr的数据存储顺序
BYTE Codec; //选择422格式还是420格式
BYTE HighRst; //复位方式选择
BYTE InvPCLK; //PCLK信号极性选择
BYTE InvVSYNC; //VSYNC信号极性选择
BYTE InvHREF; //HREF信号极性选择
UINT32 SourceHSize; //图像水平宽度
UINT32 SourceVSize; //图像垂直高度
UINT32 SourceHOffset; //水平宽度上的偏移
UINT32 SourceVOffset; //垂直高度上的偏移
UINT32 Clock; //PCLK像素時钟大小
} MODULE_DESCRIPTOR;
摄像头驱动被调用并且抓取数据的整个过程中就包含对camera接口的大部分操作,从在对摄像头图像处理芯片初始化以后,除开摄像头聚焦、复位操作以外,后面的大部分操作都是基于S3C6410的camera接口的,对camera模块的寄存器操作实现了图像数据的抓取、颜色转换、预缩放等功能。驱动中图像获取整个工作流程如图3所示。
对于图像数据的采集过程,在驱动中大致分为三步。
3.2.1 初始化camera设备
摄像头驱动加载时,需要进行初始化,初始化从DierctShow调用设备管理器调用cam_init开始,到设置完camera属性,以及STILL、capture、preview模式的输出格式时结束。
首先需要对camera设备相关的各个设备进行物理地址与虚拟地址进行映射,即GPIO、camera和PWM设备地址映射。
PHYSICAL_ADDRESS ioPhysicalBase={0,0};
ioPhysicalBase.LowPart=S3C6410_BASE_REG_PA_GPIO;
s6410IOP=(S3C6410_GPIO_REG*)MmMapIoSpace(ioPhysicalBase,sizeof(S3C6410_GPIO_REG),FALSE);//GPIO虚地址分配
ioPhysicalBase.LowPart=S3C6410_BASE_REG_PA_CAMIF;
s6410CAM=(S3C6410_CAMIF_REG*)MmMapIoSpace(ioPhysicalBase,sizeof(S3C6410_CAMIF_REG),FALSE);//Camera虚地址分配
ioPhysicalBase.LowPart=S3C6410_BASE_REG_PA_SYSCON;
s6410PWR=(S3C6410_SYSCON_REG*)MmMapIoSpace(ioPhysicalBase,sizeof(S3C6410_SYSCON_REG),FALSE);//PWM时钟虚地址分配
地址映射完成以后,进入PDD函数的初始化。
初始化完成以后,摄像头处理器的寄存器值已经通过I2C写入,camera接口等也进行了相应的设置,摄像头此时就可以开始工作。
3.2.2 数据采集
数据的采集首先需要将摄像头设置为RUN状态,当收到数据后触发中断,然后调用中断服务程序将摄像头sensor中的数据拷贝并填充到相应内存中。采集过程如图4所示。
(1)首先设置寄存器的状态,将摄像头设置为RUN状态,此时有图像视频数据进来。
SetSensorFormat(lModeType);
//为preview和still模式准备buffer,并在寄存器中设置图像的输出格式
CameraSetRegisters(format);
//这个函数主要是为camera接口分配DMA内存空间。
最开始的初始化DMA buffer的函数中,为C通道和P通道分别开辟了缓冲区:
pCodecVirtAddr=(PBYTE)HalAllocateCommonBuffer(&Adapter1,CAPTURE_BUFFER_SIZE,&PhysCodecAddr,FALSE);//为捕捉图像开辟的缓冲区
pPreviewVirtAddr=(PBYTE)HalAllocateCommonBuffer(&Adapter2,PREVIEW_BUFFER_SIZE,&PhysPreviewAddr,FALSE);//为预览图像开辟的缓冲区
缓冲区分配后,需要将DMA缓冲区与YCbCr数据起始地址相关联起来,这里的C通道和P通道的DMA缓冲区分别对应着各自控制信号的起始地址,且关联空间的大小会因图像数据格式不同而相异。例如静态图像采集模式下,图像宽为Width,高为Height,C通道的YCbCr数据4:2:0,则DMA缓冲区地址与camera模块中数据的起始地址对应情况如下:
size=Still_Buffer.FrameSize;
sizeY=Still_Buffer.Width*Still_Buffer.Height;
sizeC=Still_Buffer.Width*Still_Buffer.Height/4;
s6410CAM->CICOYSA1=(UINT32)(PhysCodecAddr.LowPart);
s6410CAM->CICOYSA2=s6410CAM->CICOYSA1;
s6410CAM->CICOYSA3=s6410CAM->CICOYSA1;
s6410CAM->CICOYSA4=s6410CAM->CICOYSA1;
s6410CAM->CICOCRSA1=s6410CAM->
CICOYSA1+sizeY;
s6410CAM->CICOCRSA2=s6410CAM->
CICOCRSA1;
s6410CAM->CICOCRSA3=s6410CAM->
CICOCRSA1;
s6410CAM->CICOCRSA4=s6410CAM->
CICOCRSA1;
s6410CAM->CICOCBSA1=s6410CAM->
CICOCRSA1+sizeC;
s6410CAM->CICOCBSA2=s6410CAM->
CICOCBSA1;
s6410CAM->CICOCBSA3=s6410CAM->
CICOCBSA1;
s6410CAM->CICOCBSA4=s6410CAM->
CICOCBSA1;
針对Capture、Sill、Preview三种模式来对4帧缓存数据的起始地址寄存器进行设置。其中Capture、Preview两种模式缓存的数据帧数为4,所以寄存器CICOYSA1、CICOYSA2、CICOYSA3、CICOYSA4的值分别为缓冲区起始地址、缓冲区起始地址加一帧数据的大小、缓冲区起始地址加上两帧数据的大小、缓冲区起始地址加上三帧数据的大小。但是Still模式缓存的数据帧数为1,所以寄存器CICOYSA1、CICOYSA2、CICOYSA3、CICOYSA4的值均为缓冲区起始地址。
DMA内存空间分配完成后,数据采集需要将camera模块状态设置为ON。
CameraCaptureControl(format,TRUE);//设置camera接口的状态为ON
(2)摄像头状态设置好以后采集图像则会触发摄像头驱动的中断服务线程,紧接着会通过MDD层的Handle_IO()函数通知PDD层调用fillbuffer函数,fillbuffer函数会根据图像格式得到当前帧号,然后根据图像模式不同进行不同大小数据量拷贝。例如对于静态图像的数据拷贝,其代码如下:
CurrentFrame=CameraGetCurrentFrameNum(STILL_CAPTURE_BUFFER);
dwRet=pCsVideoInfoHdr->bmiHeader.biSizeImage;
memcpy(pImage,(void*)m_CameraHWStillBuffer.VirtAddr,dwRet);
(3)设置摄像头状态
将摄像头的状态从取数据前的RUN状态设为PAUSE状态,释放缓冲区,然后将状态设为STOP,反初始化,完成整个驱动的调用。
4 性能测试(Performance testing)
搭建摄像头驱动测试平台,由ARM11核的S3C6410芯片,1GB的NandFlash,256MB的mobile DDR,电源管理单元等,如图5所示。
摄像头传感器的模拟数据经过图像处理芯片的处理,生成YCbCr数据;这些数据通过camera接口的两种类型的DMA通道进入缓冲区;C通道的数据用于生成静态图像以JEPG或者BMP格式存储,P通道的数据则用于液晶屏上的预览显示;测试时根据的屏幕的大小,将预览图像的格式大小设为320×240,而静态图像的大小则可以设置为小于等于2560×1920像素的任意大小。
由于生成的图像可以是RGB565格式16位、RGB32位,以及YUV格式12位(DirectShow不支持YUV格式高像素图像),则选取其中一种格式进行识别率纵向比较,此测试选取的是RGB565格式。通过对RGB16位图像不同分辨率下采集到的图像的文字识别率的对比,发现当分辨率为500万(2560×1920)时,图像的文字识别率最高,能够满足文字识别正确率的高标准要求。用一页相同的仅有文字的样张(A4、宋体5号字)进行测试,其识别结果见表1。
5 结论(Conclusion)
本文介绍了在S3C6410和Windows CE6.0平台下实现基于DirectShow技术的高分辨率摄像头驱动的过程。硬件上采用S3C6410自带的camera接口、I2C总线和GPIO口,以及CMOS摄像头;软件上则基于camera模块的P通道和C通道,分别对两路数据进行相应的处理,比如缩放、颜色空间转换、旋转等,然后经过各自的DMA通道进入缓冲区,缓冲区的数据再根据需求进行处理或者存储。本文为工程人员进行三星ARM系列芯片和Windows CE6.0下高有效分辨率摄像头驱动开发提供了参考。
参考文献(Reference)
[1] Palakodety,Atmaram.CMOS Active Pixel Sensor for Digital Cameras:Current State-of the-Art[D].Master of Science (Computer Engineering).UNIVERSITY OF NORTH TEXAS.May 2007.
[2] 彭铁钢,等.基于ARM的嵌入式视频监控系统设计[J].计算机工程与设计,2010,31(6):1191-1194.
[3] 刘飞,张曦煌.基于嵌入式平台的USB摄像头驱动程序的实现[J].计算机工程与设计,2008,29(8):1994-1996.
[4] 宋丽华,王晶晶,李也白.嵌入式系统下高像素摄像头驱动程序设计与实现[J].小型微型计算机系统,2011,32(4):787-792.
[5] 汪兵,等.Windows CE嵌入式高级编程及其实例详解[M].北京:中国水利水电出版社,2008.
[6] S3C6410X User Manual[M].Samsung Electronics,2008.
作者简介:
郭艳飞(1979-),男,博士,工程师.研究领域:SoC,电子商务.
宋丽华(1979-),女,博士,副教授.研究领域:嵌入式技术,计算机网络协议与通信.
简 阳(1989-),男,硕士生.研究领域:嵌入式系统.