视频的字符叠加,简称OSD,是FPGA图像处理的基本操作,网上也有很多参考例程,但大多无法实现动态字符叠加,目前网上同行给出的方案有如下:
使用字模软件生成点阵信息,一般是十六进制,然后把点阵信息初始化到FPGA,也就是上电复位是写入寄存器中,或是写入RAM或ROM中,然后输出到显示器;
这样的方法很简单很直接,但有个问题,我要输出不同的字符,然后把所有需要的字符都用字模软件生成点阵信息?这也太麻烦了吧?
相比之下,本方案就很实用了;本方案优势如下:
1、使用软件动态配置字符,SDK写入;
2、字符的显示位置、颜色等软件动态配置;
3、软硬件(PL、PS)交互方案,对于学生而言可以提高项目的高端性;
缺点:由于加载了国标字库,所以ram占用较大,只适用于zynq系列期间,A7和低配的K7都不适用;
OSD采用HLS方案实现,处理流程部分代码如下:
void overlayosd(vstream_t &video_in, vstream_t &video_out, unsigned int *pMem, int rows, int cols)
{
#pragma HLS INTERFACE axis port=video_in
#pragma HLS INTERFACE axis port=video_out
#pragma HLS INTERFACE m_axi port=pMem offset=slave
#pragma HLS INTERFACE s_axilite port=rows
#pragma HLS INTERFACE s_axilite port=cols
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE s_axilite port=overly_x
#pragma HLS INTERFACE s_axilite port=overly_y
#pragma HLS INTERFACE s_axilite port=overly_w
#pragma HLS INTERFACE s_axilite port=overly_h
hls::Mat<IMG_MAX_ROWS, IMG_MAX_COLS, HLS_8UC3> img_in(rows, cols);
hls::Mat<IMG_MAX_ROWS, IMG_MAX_COLS, HLS_8UC3> img_out(rows, cols);
#pragma HLS dataflow
hls::AXIvideo2Mat(video_in, img_in);
overlyOnMat(img_in, img_out, pMem);
hls::Mat2AXIvideo(img_out, video_out);
}
需要完整HLS代码的兄弟可以看完文章后再最后的福利章节得到源码的获取渠道;
开发板:zynq7100开发板;
开发环境:vivado2019.1;
输入:OV5640摄像头,输入分辨率1280X720;
输出:HDMI,输出分辨率1280X720;
工程BD如下:
代码架构如下:
SDK主函数代码如下:
#include "xiicps.h"
#include "xil_io.h"
#include "xparameters.h"
#include "helai_vdma.h"
#include "xoverlayosd.h"
#include "xil_cache.h"
XIicPs Iic;
XOverlayosd overlayosdInstance;
#define X_PIXCEL 1280 //图像宽度
#define Y_PIXCEL 720 //图像高度
#define X_START 0 //字符起始x坐标
#define Y_START 0 //字符起始y坐标
#define OSD_COLOR 0xff000000 //osd字符颜色
#define OSD_BAKGROUND 0x00000000 //osd字符背景颜色
unsigned int overlayDomain[X_PIXCEL*Y_PIXCEL];
const char *showStr = "台湾一定要收复"; //字符
void main(){
I2C_config_init();
XOverlayosd_Initialize(&overlayosdInstance, XPAR_OVERLAYOSD_0_DEVICE_ID);
XOverlayosd_Set_pMem(&overlayosdInstance, (u32)overlayDomain);
XOverlayosd_EnableAutoRestart(&overlayosdInstance);
XOverlayosd_Start(&overlayosdInstance);
XOverlayosd_Set_overly_x(&overlayosdInstance, 0);
XOverlayosd_Set_overly_y(&overlayosdInstance, 0);
XOverlayosd_Set_overly_w(&overlayosdInstance, X_PIXCEL);
XOverlayosd_Set_overly_h(&overlayosdInstance, Y_PIXCEL);
XOverlayosd_Set_cols(&overlayosdInstance, X_PIXCEL);
XOverlayosd_Set_rows(&overlayosdInstance, Y_PIXCEL);
helai_vdma();
while(1){
int pos;
pos = Y_START*X_PIXCEL+X_START;
uArgbPrintf(showStr, overlayDomain+pos, X_PIXCEL, OSD_COLOR, OSD_BAKGROUND);
Xil_DCacheFlushRange((INTPTR)overlayDomain, sizeof(overlayDomain));
usleep(300000);
}
}
OSD字符的颜色,显示位置,显示颜色等信息都可以在宏定义处修改,很方便;
zynq7100开发板连接:
在图像左上角顶点输出黑色字符如下:
在图像左上角顶点输出蓝色字符如下:
在图像中部输出绿色不同字符如下: