红外热成像下篇–叠加字符OSD

背景

前段时间不是玩了下红外热成像,视频可见我的公众号和视频号:

还有个瑕疵:视频上没有实时显示相应的温度(叠加在视频上),这段时间就把它给实现了,视频可见我的公众号和视频号。

在视频上实现温度信息叠加,里面一个主要技术点就是字符OSD,这里使用了一种IPC芯片通用的字符OSD方案(RK、海思等方案都适用):freetype + sdl + Soc的图层处理硬件模块。

首先介绍下前面这3个东东:

  • freetype:

    FreeType库是一个完全免费(开源)的、高质量的且可移植的字体引擎,它提供统一的接口来访问多种字体格式文件,包括TrueType, OpenType, Type1, CID, CFF, Windows FON/FNT, X11 PCF等。

  • sdl:

    SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。现SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。

  • Soc的图层处理硬件模块
    一般IPC芯片算力都比较低,但几乎都带有2D图层的硬件处理模块,如这里RK的RGA。

原理其实很简单:

  1. 通过 freetype 来处理要叠加的字符。
  2. 然后用 sdl 生成相应的bmp图
  3. 再转为ipc的soc芯片能支持叠加的位图(这一步要根据具体的soc支持情况来,有些支持sdl的16位 rgb565 就不需要转)。
  4. 最后叠加到对应的图像数据上去。一般都使用soc提供的相应硬件接口。

注: sdl默认生成的是16位 rgb565 格式的图,而我这里使用的 rv1109/rv1126的OSD叠加的图只支持32位ARGB888格式,所以需要手动转换下。

实现

首先交叉编译好要用的freetypeSDLSDL_ttf这三个库,一般都通过buidlroot来编译,具体细节这就不多说了。

最后上主要的代码,这里以RK的rv1109/rv1126为例:


SDL_PixelFormat *fmt;
TTF_Font *font;  
//图面结构
SDL_Surface *text, *temp;  

if (TTF_Init() < 0 ) 
{  
    fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError());  
    SDL_Quit();
}  

//打开字库,设字体为80号
font = TTF_OpenFont("simsun_cn_3000.ttf", 30);  //字体库需自己准备
if ( font == NULL ) 
{  
    fprintf(stderr, "Couldn't load %d pt font from %s: %s\n",18,"ptsize", SDL_GetError());  
}  
//设置字体颜色
SDL_Color forecol = { 0x00,0x00, 0x00}; //3个参数分别代表rgb  
//SDL渲染字符  
text = TTF_RenderUTF8_Solid(font, str, forecol);
//定义格式    
fmt = (SDL_PixelFormat*)malloc(sizeof(SDL_PixelFormat));
memset(fmt,0,sizeof(SDL_PixelFormat));
fmt->BitsPerPixel = 16;  //每像素位数
fmt->BytesPerPixel = 2; //每像素字节数
fmt->colorkey = 0xffffffff;
fmt->alpha = 0xff;  //透明度 0<=alpha<=255

//渲染字符,默认RGB565格式
temp = SDL_ConvertSurface(text,fmt,0);

BITMAP_S stBitmap;
//将渲染后的Surface转换成Bitmap,转成RV1126支持的ARGB8888格式
SurfaceWord_ToBMP(temp, &stBitmap, forecol);  

//释放资源
SDL_FreeSurface(text);  
SDL_FreeSurface(temp);   
TTF_CloseFont(font);     
TTF_Quit(); 
free(fmt);
fmt = NULL;

//使用RK自带的RGN来叠加图片
OSD_REGION_INFO_S RngInfo;
RngInfo.enRegionId = 5;
RngInfo.u32PosX = bitmap_PosX;
RngInfo.u32PosY = bitmap_PosY;
RngInfo.u32Width = bitmap_width;
RngInfo.u32Height = bitmap_height;
RngInfo.u8Enable = 1;
RngInfo.u8Inverse = 0;
printf("# ENABLE RGN enRegionId[%d]: < u32PosX:%d,u32PosY:%d,u32Width:%d,u32Height:%d> for 100ms...\n", 
        RngInfo.enRegionId, RngInfo.u32PosX, RngInfo.u32PosY,
        RngInfo.u32Width, RngInfo.u32Height);

int ret = RK_MPI_VENC_RGN_SetBitMap(0, &RngInfo, &stBitmap);  //
if (ret) {
    printf("ERROR: set rgn stBitmap(enable) failed! ret=%d\n", ret);
    if (stBitmap.pData)
    free(stBitmap.pData);
    //break;
    return -1;
}

// free stBitmap
free(stBitmap.pData);
stBitmap.pData = NULL;

参考

https://blog.csdn.net/m0_50887633/article/details/134448395