在图像视频监控中,需要在画面中增加监控地点、时间戳等水印,通过我之前写的【opencv交叉编译移植到linux-arm开发板,并做测试】已经可以利用opencv方便的将时间戳打到抓拍的图像上。使用opencv打水印虽然简单方便,但存在两个缺点:
1.putText不可放置中文;
2.应用在视频OSD显然是不方便的,因为海思的region区域管理通常以bmp位图叠加的方式进行OSD,通过阅读官方SDK例程的sample_region源码可以看出,其例程是读入已有的bmp文件叠加在视频流中,例程中bmp是死的,是不会变化的。
而实际应用场景中需要生成变化的OSD并打到图像或视频流中,那么我们可以通过【将字符串生成位图,再叠加到图像视频】实现。
通过阅读大神的博客【海思多媒体(MPP)开发(5)——区域管理(REGION&OSD字符显示)】,可见实现【字符串生成位图】需要使用并移植以下三个工具
1.freetype
2.SDL
3.SDL_ttf
目标明确后,开始着手移植吧。
1.下载freetype源码
http://mirror.yongbok.net/nongnu/freetype/,我下的是2.7.1版本,下载后解压得到文件夹freetype-2.7.1
2.编译安装
这里我们依旧使用cmake-gui进行交叉编译。需要注意的是CMAKE_INSTALL_PREFIX选项,选一个路径,并记住这个路径。这里我选择的是/usr/local路径。
cmake配置好后一次进行make、make install,完成后交叉编译的freetype头文件、库文件夹就分别在/usr/local/include /usr/local/lib中了。
1.下载SDL源码
http://www.libsdl.org/download-1.2.php
下载的是SDL-1.2.15.tar.gz,解压得到SDL-1.2.15文件夹,进入文件夹。
2.编译安装
进入之后进行编译配置
./configure --prefix=/opt/arm --disable-pulseaudio --disable-video-nanox -disable-video-qtopia --disable-static --enable-shared --disable-video-photon --disable-video-ggi --disable-video-svga --disable-video-aalib --disable-video-dummy --disable-video-dga --disable-arts --disable-esd --disable-alsa --disable-video-x11 --disable-nasm --disable-joystick --disable-input-tslib -enable-video-fbcon --host=arm-himix200-linux
注意最后的 --host= 后填你的交叉编译链。配置成功后再进行make、make install,完成后SDL的相关头文件、库就被安装到–prefix=指明的/opt/arm中去了。
1.下载SDL_ttf源码
http://www.libsdl.org/projects/SDL_ttf/release/
下载的是SDL_ttf-2.0.11.tar.gz,解压得到SDL_ttf-2.0.11文件夹,进入。
2.编译安装
进行编译配置,需要注意的就是配置交叉编译链、配置安装目录、配置之前安装的freetype、SDL目录,以及freetype、SDL对应的库文件目录。因为SDL_ttf的编译依赖于SDL和freetype。
./configure --host=arm-himix200-linux -prefix=/opt/arm --with-sdl-prefix=/opt/arm --with-freetype-prefix=/usr.local --without-x LDFLAGS=”-L/usr/local/lib -L/opt/arm/lib -lSDL -lfreetype”
配置完成后进行make、make install。需要注意的是make过程中可能提示xxxx头文件找不到的情况,解决办法有两个:1.在上述配置代码中加入头文件的路径;2.在Makefile里直接加入头文件的路径。两种方法都可以。
测试程序的最终目的就是将字符串转换为bmp位图,并且能运行在arm平台上。借鉴前辈【海思多媒体(MPP)开发(5)——区域管理(REGION&OSD字符显示)】的代码并做简单修改,如下。功能是生成几张时间位图,字符串中包含了中文、英文和符号,证明了生成位图的完整性。
test.c
#include
#include
#include
#include "SDL.h"
#include "SDL_ttf.h"
#include "time.h"
#define FONT_PATH "./UbuntuMono-BI.ttf"
int string_to_bmp(char *pu8Str);
int cnt = 0;
int main()
{
time_t now;
struct tm *ptm;
char timestr[100] = {0};
while(1)
{
usleep(1000000);
time(&now);
ptm = localtime(&now);
snprintf(timestr,100,"时间%d-%02d-%02d %02d:%02d:%02d",ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec);
string_to_bmp(timestr);
memset(timestr,0,100);
if(cnt++ > 5)
{
break;
}
}
return 0;
}
int string_to_bmp(char *pu8Str)
{
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();
}
font = TTF_OpenFont(FONT_PATH, 80);
if ( font == NULL )
{
fprintf(stderr, "Couldn't load %d pt font from %s: %s\n",18,"ptsize", SDL_GetError());
}
SDL_Color forecol = { 0xff, 0xff, 0xff, 0xff };
text = TTF_RenderUTF8_Solid(font, pu8Str, 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;
temp = SDL_ConvertSurface(text,fmt,0);
char savename[10] = {0};
snprintf(savename,10,"%d.bmp",cnt);
printf("savename = %s\n",savename);
SDL_SaveBMP(temp, savename);
SDL_FreeSurface(text);
SDL_FreeSurface(temp);
TTF_CloseFont(font);
TTF_Quit();
return 0;
}
交叉编译命令为
arm-himix200-linux-gcc test.c -I/opt/arm/include/SDL -L/opt/arm/lib -lSDL -lSDL_ttf -lpthread
可以看出使用了动态链接库,故将编译好的可执行文件复制到开发板后,还需要复制所需的so库文件到开发板的/lib目录下。可以先运行以下,缺哪个库就复制哪个库,都在之前交叉编译的SDL、SDL_ttf的lib目录下。
程序运行结果如下
/user/sdl # ./a.out
savename = 0.bmp
savename = 1.bmp
savename = 2.bmp
savename = 3.bmp
savename = 4.bmp
savename = 5.bmp
savename = 6.bmp
运行完后看一下运行目录,已经生成了0~6张位图
/user/sdl # ls
0.bmp 3.bmp 6.bmp
1.bmp 4.bmp UbuntuMono-BI.ttf
2.bmp 5.bmp a.out
将位图复制到ubuntu下,可以看到与预期相符。
如此一来,就可以使用opencv,或者海思的region区域管理给图像视频添加任意水印OSD了。
上述是从别人的例程那赋值粘贴而来,后来代码审核发现内存泄漏问题,原因很简单——fmt没有free。