张祖昊,王云光
(1.上海理工大学 医疗器械与食品学院,上海 200093;2.上海健康医学院 医疗器械学院,上海 201318)
数字图像处理技术在机器视觉和计算机视觉技术领域起着至关重要的作用。越来越多的领域不断对图像处理提出新的要求,在图像处理算法复杂性持续增加的同时还要满足图像分辨率和每秒传输帧数(Frames Per Second,FPS)[1-3]要求。医疗领域的电子内窥镜需要在手术时将人体内部的画面实时且清晰地输出到显示屏上[4-5]。目前电子内窥镜的分辨率普遍在1 280×720 以上,因此对系统带宽、数据吞吐率要求较高,软硬件协同工作是最佳的解决方案。朱炎均[6]使用ZedBoard 完成320×240 分辨率视频实时处理,由于没有使用DMA 技术,因此整体带宽提升不多;李振宇[7]使用Zynq 完成VGA 格式1 280×720 分辨率视频实时处理,但是由于输出的不是HDMI 信号,因此应用范围较窄。虽然传统的FPGA 可以利用其并行特性提高系统吞吐率,但在开发图像处理算法时使用Verilog 效率很低[8-9],ARM+DSP 难以解决该问题。
本文采用Xilinx 公司的Zynq-7000 系列可编程(System On Chip,SOC)ARM+FPGA 异构设计作为视频图像处理平台,该平台主要由处理系统(Processing System,PS)和可编程逻辑(Programmable Logic,PL)两部分构成[10]。其中PS部分包含两块ARM Cortex-A9 双核处理器,负责系统控制;PL 部分由Xilinx 7 系列FPGA 构成,负责视频信号采集、处理、缓存和输出工作。系统采用OV5640 作为图像传感器,HDMI 显示器作为视频输出,使用Xilinx 公司的Vivado HLS作为图像处理算法开发工具,将C/C++转换成RTL Verilog代码并封装成IP,可在提高系统整体带宽和吞吐率的同时,大大加快图像处理算法的开发速度。
系统由采集、处理、缓存、显示4 部分组成,系统结构如图1 所示。系统由PS 和PL 通过AXI4 总线连接协同完成。采集部分使用Zynq 的PS 端对OV5640 摄像头的寄存器组发送不同寄存器值,完成摄像头初始化工作。再通过Zynq的PL 端自定义OV5640 完成数据采集工作;图像处理使用Xilinx HLS 开发工具,将C/C++转换成Verilog 语言并封装成IP,使用PL 将其例化;视频缓存使用Xilinx 官方提供的VD⁃MA(Video Direct Memory Access)IP,实现3 帧画面缓存,以避免画面闪烁和撕裂等现象;视频显示通过Zynq 的PL 端输出IP,将视频信号以HDMI 的时序输出。
由于Zynq 将ARM 与FPGA 集成在一起,开发工作既要设计ARM 的应用程序,又要设计FPGA 部分的硬件逻辑设计,因此Zynq 开发需要遵循软硬件协同开发方式,以达到提升开发效率和产品性能目的。Zynq-7000 系列嵌入式开发步骤如下:①在Vivado 中创建新的工程;②使用IP 集成器创建处理器系统;③生成顶层HDL 并导出设计到SDK;④创建应用测试程序;⑤设计验证[11]。其中Vivado 是FP⁃GA 的硬件开发,生成的顶层HDL 文件就是硬件设计生成的结果。将其导入到SDK 后再创建应用测试程序,进行相应的软件开发。测试程序根据HDL 提供的BSP(Board Sup⁃port Package)板级支持包中提供的硬件资源完成指定任务。合理分配硬件和软件的任务分工也是软硬件协同开发十分重要的一步,本设计将OV5640 摄像头和VDMA 初始化配置工作交给软件处理,剩下所有视频信号采集、处理和输出工作全部交给硬件完成。
图2 为使用VivadoIP 集成器创建的Block Designer 工程图,其中的核心模块是ov5640_capture_data_0,ov5640_so⁃bel_0,axi_vdma_0 和DVI_Transmitter_0,分别对应采集、处理、缓存和显示。下面分别从数据流通路和控制流通路介绍该硬件设计原理。
Fig.2 Vivado block design图2 Vivado 块设计
当PS 将OV5640 配置完成后,其数据引脚就会在每个像素时钟周期输出一个8bit 的数据信号到ov5640_cap⁃ture_data_0 模块的cam_data[7:0]输入引脚。该模块功能是采集摄像头输出的数据并将其从RGB565 格式转换成视频流RGB888 格式输出。然后数据从ov5640_capture_data_0 的cmos_rgb 引脚输出到v_vid_in_axis4s_0 模块的vid_io_in 引脚。该模块功能是将视频信号转换成AXI4-Stream 视频协议信号[12]。经过转换后数据从v_vid_in_axis4s_0 的video_out 引脚输出到HLS 图像处理模块的INPUT_STREAM 引脚,该模块功能就是对视频信号进行实时处理,可以嵌入一层或多层不同的HLS 模块实现不同的图像处理算法。经过图像处理后,数据从HLS 模块的OUT⁃PUT_STREAM 引脚输出到axi_vdma_0 的S_AXIS_S2MM 引脚。该模块在PS 对其初始化配置完成后即可直接对DDR3进行读写操作,实现画面的帧缓存功能[13]。VDMA 和DDR3 之间还需要通过AXI SmartConnect 和Zynq 的AXI HP总线进行连接,因此数据会从axi_vdma_0 模块的M_AX⁃IS_MM2S 引脚流出到axi_smc 模块的S01_AXI 引脚,再从M00_AXI 引脚流出到Zynq 模块的S_AXI_HP0 引脚,此时即完成画面帧缓存的数据通路。然后进行画面输出显示数据流。当一帧画面缓存完成后,DDR3 中的数据就会通过Zynq 模块的S_AXI_HP0 输出到axi_smc 模块的M00_AXI引脚,再从S00_AXI 引脚输出到axi_vdma_0 模块的M_AXI_MM2S 引脚,完成VDMA 模块对DDR3 的读操作。axi_vdma_0 接收到DDR3 数据后再从M_AXIS_MM2S 引脚输出到v_axi4s_vid_out_0 模块的video_in 引脚,该模块功能与v_vid_in_axi4s_0 的功能相反,是将AXI4-Stream 协议信号格式转换成视频流信号格式[14]。经过v_axi4s_vid_out_0模块转换后从vid_io_out 引脚输出到DVI_Transmitter_0 模块的Video_In 引脚,该模块功能是将视频流信号转换成HDMI 信号格式输出到HDMI 接口上,最后通过TMDS 引脚输出到HDMI 显示器,完成画面输出显示的数据通路。
控制流通路所有的控制信号均由Zynq 模块发出,系统需要完成的控制有:①OV5640 初始化配置;②VDMA 初始化配置;③整个系统的复位和时钟信号。OV5640 的控制流通路通过Zynq 模块的GPIO_0 引脚输出到emio_sccb 引脚,来往于OV5640 的寄存器中写配置信息。VDMA 时钟控制流通路通过Zynq 模块的M_AXI_GP0 引脚输出控制信号到ps7_0_axi_periph 模块的S00_AXI 引脚,该模块是AXI Inter⁃connect 的一个实例,可让Zynq 模块同时与多个AXI4 总线协议模块互联,在ps7_0_axi_periph 输出端分出4 个AXI 输出引脚,分别用来控制VDMA、axi_dynclk_0 和v_tc_0。其中axi_dynclk_0 是动态时钟生成器实例,用来管理整个系统时钟信号;v_tc_0 是视频时序生成器实例,用来控制HD⁃MI 输出时序。复位控制流通路通过Zynq 模块的FCLK_RESET0_N 引脚输出到rst_ps7_0_50M 模块,该模块是处理器系统复位实例,用来控制整个系统的复位工作。系统控制流通路通过这些控制信号使整个系统完成采集、处理、缓存和显示功能。
本系统图像处理模块使用Vivado HLS 开发,在HLS 中移植了大量的OpenCV 函数库,可以调用移植后的OpenCV函数库对图像进行处理[15-16]。但是需要注意的是,HLS 中的OpenCV 函数库与OpenCV 函数库并不完全相同。OpenCV 函数是不能直接综合的,因此必须由可综合的库函数替换,主要原因是OpenCV 函数涉及到动态内存分配,在FPGA 中动态内存分配是不可综合的行为。图3 为使用OpenCV 与HLS 视频库进行图像处理流程。
Fig.3 Image processing flow of Opencv and HLS video library图3 OpenCV 与HLS 视频库图像处理流程
与传统OpenCV 图像处理相比,使用HLS 视频库进行图像处理需要将OpenCV 格式的数据转换成AXI 视频格式,该操作通过IplImage2AXIvideo 函数完成;然后将AXI 视频格式转换成Mat 格式,该操作通过AXIvideo2Mat 函数完成;之后就可调用HLS 中移植的OpenCV 函数库进行图像处理。这里调用的是Sobel 强边缘检测对图像处理效果进行测试,处理完之后再将Mat 格式转换成AXI 视频格式,最后还原成OpenCV 格式,这样就完成了使用HLS 中OpenCV视频库对视频图像进行处理的过程。可以通过这个过程在PC 上使用一张图像验证图像处理算法效果。当验证通过之后,再把图中方框部分封装成一个RTL 级IP 核,嵌入到前面的Vivado 硬件设计的Block Design 采集模块和缓存模块中间,即可以实现实时视频图像处理功能。
图4 为PC 上使用HLS 进行Csimulation 处理的效果图片,实现的是水平Sobel 梯度算子的掩膜计算。可以看到,经过图像处理后,右图很好地将原图中垂直边缘检测出来,效果显著。
Fig.4 Simulation processing effect of HLS video library on PC图4 PC 上HLS 视频库仿真处理效果
SDK 软件部分需要完成的工作有:①初始化EMIO;②初始化OV5640 摄像头;③配置VDMA;④初始化显示时序控制器;⑤设置显示模式。图5 是SDK 应用程序设计流程。
SDK 中所有的工作都是通过调用BSP(Board Support Package)中的库函数完成的,而该BSP 是根据前面的Vivado硬件设计部分提供的。首先初始化Zynq 上的两个EMIO 引脚,将其用作SCCB 通信引脚,因为这里只需要对OV5640进行写寄存器操作,所以这里的时钟线和数据线都设置成输出管脚,这里封装了一个emio_init 函数用于初始化EMIO 引脚;然后初始化OV5640 摄像头,通过调用一个封装好的ov5640_init 函数,先检查ov5640 是否正确连接,如果检查通过则调用sccb_write_reg16 函数,往ov5640 不同的寄存器地址内写入不同的寄存器值。这里OV5640 被配置成DVP(Digital Video Port)输出接口、1 280×720 分辨率和30FPS(Frame Per Second)。接下来配置VDMA,调用一个封装好的run_vdma_frame_buffer 函数,该函数内部包括配置帧缓存地址、写通道配置、读通道配置、开启写通道和开启读通道配置等。VDMA 配置成3 帧图像缓存功能。初始化视频时序控制器调用DisplayInitialize 函数,包括VTC(Video Timing Controller)和动态时钟配置。通过Display⁃SetMode 函数设置显示模式和启动显示图像,采用Display⁃Start 函数启动VTC 开始工作输出图像到HDMI 接口。图6是SDK 主要调用的函数截图。
Fig.5 SDK initialization engineering application process图5 SDK 初始化工程应用程序流程
Fig.6 Functions mainly called by SDK application图6 SDK 应用程序主要调用的函数
本设计使用Alinx 公司的AX7Z020 开发板作为测试平台。为测试整个系统工程,方便后期使用,还需将程序固化到Flash 中,以免每次启动工程都需要通过JTAG 接口烧写。Zynq 启动由ARM 主导,包括FPGA 程序的加载,启动阶段如下:①阶段0。在上电复位或热复位之后,处理器首先执行BootRom 中的代码,此为最初启动设置。BootRom存放了一段不可更改的代码,在非JTAG 模式下执行,代码包含Quad-SPI、SD 的驱动,还有一个很重要的作用是把阶段①的代码搬运到OCM 中,就是FSBL 代码(First Stage Boot Loader);②阶段①的作用是初始化PS 端配置,也就是在Vivado 工程配置Zynq 核,包括DDR、MIO、SLCR 寄存器。如果有PL 端程序就加载PL 端bitstream,加载bare-metal 应用程序到DDR 存储器,交接给bare-metal 应用程序[17]。因此,根据上面描述,需要再生成一个FSBL 引导程序,完成MIO 分配、时钟、DDR 控制器、SD、QSPI 控制器初始化工作,再通过启动模式查找bitstream 配置FPGA,然后搜索应用程序加载到DDR,最后交给应用程序执行。将FSBL 引导程序和整个工程生成的bitstream 文件放在一起,再生成一个boot.bin 文件放到SD 卡的根目录下,将开发板设置为SD卡启动模式,连上电源和显示屏,打开电源开关,就能看到如图7 的测试结果图像。
Fig.7 Test results图7 测试结果
本文在Zynq-7000 开发平台AX7Z020 上使用Xilinx Vivado 开发工具实现了CMOS OV5640 摄像头采集数据,通过HLS 工具实现Sobel 快速边缘检测算法,通过Video In to AXI4-Stream 和AXI4-Stream to Video Out 将视频信号在通用信号格式和AXI4-Stream 专用信号格式之间进行转换,通过VDMA 实现视频信号的3 帧DDR 缓存功能;通过自定义HDMI 输出IP 将画面显示到显示屏上,最终通过SDK 应用程序控制整个FPGA 工程运行。采用软硬件协同的设计方法使系统更具有可控性和灵活性。同时,在该系统框架上可以很方便地进行图像处理算法验证和研究工作。
但是,本文只完成了整个视频图像处理数据流和控制流的设计工作,没有在PS 和PL 硬件之间留出控制接口,因此当程序运行起来后无法通过PS 实时控制PL 端。下一步研究工作是在PS 端设计UI 界面,通过UI 来实时控制PL 端的工作情况,如此可以使得系统针对不同图像问题执行不同的图像处理算法,并在后续引入自动图像评估和加载不同算法等功能。