海思3559万能平台搭建:OSD的自动反色

简介: OSD的自动反色

前言

 OSD功能在之前两篇中已经满足了大部分的应用场景,为了进一步提升效率和自适应环境亮度和反色,这里介绍改进方法

效率提升

 我们之前整体的流程框架是这样的:TTF初始化,打开字体,区域初始化后while1通过SDL_CreateRGBSurface创建大的位图,再分别渲染小的位图通过SDL_LowerBlit叠到大位图上,  memcpy大位图数据到海思的区域结构体BITMAP_S,然后释放资源

 每次需要通过TTF_RenderUTF8_Solid渲染更新内容没法避免,而且这个是必须每次都释放的,一定要记得SDL_FreeSurface。但是频繁的SDL_CreateRGBSurface和SDL_FreeSurface就没有必要了,可以只创建一次,然后while1通过SDL_FillRect来达到更新的作用(不然就都糊一起啦)

 海思的区域设置部分不需要改动

HI_VOID osd_init(HI_VOID *arg)
{ 
    HI_S32 s32Ret;
    if (TTF_Init() < 0 ) 
    {  
        fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError());  
        SDL_Quit();
    }  
    font = TTF_OpenFont(FONT_PATH, 29); 
    if ( font == NULL ) 
    {  
        fprintf(stderr, "Couldn't load %d pt font from %s: %s\n",18,"ptsize", SDL_GetError());  
        // return -1;
    }  
    pthread_t luma_update_id;
    s32Ret=pthread_create(&luma_update_id, NULL, &luma_update_task,NULL);
    if(s32Ret != 0)
    {
        SAMPLE_PRT("pthread video_process_osd create failed\n");
        // return -HI_FAILURE;
    }
    pthread_detach(luma_update_id);
    video_process_s* pstPara;
    pstPara = (video_process_s*)arg;
    time_t now;
    struct tm *ptm;
    char timestr[OSD_LENGTH] = {0};
    char lost_target_info_str[OSD_LENGTH] = {0};
    char other_info_str[OSD_LENGTH] = {0};
    char trk_str[OSD_LENGTH] = {0};
    char frame_str[OSD_LENGTH] = {0};
    osd_fmt = (SDL_PixelFormat*)malloc(sizeof(SDL_PixelFormat));
    hi_memset(osd_fmt,sizeof(SDL_PixelFormat),0,sizeof(SDL_PixelFormat));
    osd_fmt->BitsPerPixel = 16;
    osd_fmt->BytesPerPixel = 2;
    osd_fmt->colorkey = 0xffffffff;
    osd_fmt->alpha = 0xff;
    osd_bottom_left = SDL_CreateRGBSurface(SDL_SWSURFACE, OSD_BOTTOM_LEFT_W, OSD_BOTTOM_LEFT_H, 
                                    osd_fmt->BitsPerPixel,osd_fmt->Rmask, osd_fmt->Gmask, osd_fmt->Bmask, osd_fmt->Amask);
    osd_top_left = SDL_CreateRGBSurface(SDL_SWSURFACE, OSD_TOP_LEFT_W, OSD_TOP_LEFT_H, 
                                    osd_fmt->BitsPerPixel,osd_fmt->Rmask, osd_fmt->Gmask, osd_fmt->Bmask, osd_fmt->Amask);
    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); 
    snprintf(lost_target_info_str,100,"脱靶信息:X:%02d,Y:%02d",osd_fmt->BitsPerPixel,osd_fmt->BytesPerPixel);
    snprintf(other_info_str,100,"视场角信息:X:%02d,Y:%02d,焦距:%02d",osd_fmt->BitsPerPixel,osd_fmt->BytesPerPixel,osd_fmt->BytesPerPixel);
    snprintf(trk_str,100,"跟踪器状态:检测?识别?跟踪? ");
    snprintf(frame_str,100,"帧率:%02d",osd_fmt->BytesPerPixel);
    string_to_bmp_bottom_left(lost_target_info_str,other_info_str,timestr);
    string_to_bmp_top_left(trk_str,frame_str);
    RGN_AddOsdToVpss_bottom_left(pstPara->VpssChn);
    RGN_AddOsdToVpss_top_left(pstPara->VpssChn);
}
HI_S32 string_to_bmp_bottom_left(char *pu8Str_losttargrt_info,char *pu8Str_other_info,char *pu8Str_time)
{
    SDL_Rect bounddst,boundsrc;
    // printf("before TTF_RenderUTF8_Solid\n");
    osd_time_text            = TTF_RenderUTF8_Solid(font, pu8Str_time, forecol);
    osd_losttarget_info_text = TTF_RenderUTF8_Solid(font, pu8Str_losttargrt_info, forecol);
    osd_other_info_text      = TTF_RenderUTF8_Solid(font, pu8Str_other_info, forecol);
    boundsrc.x = 0;
  boundsrc.y = 0;
    boundsrc.w = OSD_BOTTOM_LEFT_W;
    boundsrc.h = OSD_BOTTOM_LEFT_H;
    SDL_FillRect(osd_bottom_left,&boundsrc,SDL_MapRGB(osd_bottom_left->format, 0, 0, 0));//起到更新作用
    boundsrc.x = 0;
  boundsrc.y = 0;
  boundsrc.w = osd_losttarget_info_text->w;
  boundsrc.h = osd_losttarget_info_text->h;
    bounddst.x = 0;
  bounddst.y = 0;
  bounddst.w = osd_losttarget_info_text->w;
  bounddst.h = osd_losttarget_info_text->h;
  SDL_LowerBlit(osd_losttarget_info_text, &boundsrc, osd_bottom_left, &bounddst); 
    // SDL_UpdateRect(osd_losttarget_info_text,0,0,osd_losttarget_info_text->w,osd_losttarget_info_text->h); 
  boundsrc.x = 0;
  boundsrc.y = 0;
  boundsrc.w = osd_other_info_text->w;
  boundsrc.h = osd_other_info_text->h;
    bounddst.x = 0;
  bounddst.y = osd_losttarget_info_text->h;
  bounddst.w = osd_other_info_text->w;
  bounddst.h = osd_other_info_text->h;
  SDL_LowerBlit(osd_other_info_text, &boundsrc, osd_bottom_left, &bounddst);
    // SDL_UpdateRect(osd_other_info_text,0,0,osd_other_info_text->w,osd_other_info_text->h);
    boundsrc.x = 0;
  boundsrc.y = 0;
  boundsrc.w = osd_time_text->w;
  boundsrc.h = osd_time_text->h;
    bounddst.x = 0;
  bounddst.y = osd_losttarget_info_text->h+osd_other_info_text->h;
  bounddst.w = osd_time_text->w;
  bounddst.h = osd_time_text->h;
  SDL_LowerBlit(osd_time_text, &boundsrc, osd_bottom_left, &bounddst);
    // SDL_UpdateRect(osd_time_text,0,0,osd_time_text->w,osd_time_text->h);
     for(int uj=0;uj<hSubcnt[1];uj++)
    {
        for(int ui=0;ui<wSubcnt[1];ui++)
        {
            int uk=uj*wSubcnt[1]+ui;
            if(g_aRectLuma[1][uk]>luma_value)
            {
                unsigned short int *dptr=(unsigned short int*)osd_bottom_left->pixels;                  
                for(int osd_h=0;osd_h<OSD_BOTTOM_LEFT_H;osd_h++)
                {
                    for(int osd_w=0;osd_w<OSD_BOTTOM_LEFT_W;osd_w++)
                    {
                       dptr[osd_h*OSD_BOTTOM_LEFT_W+osd_w]=(dptr[osd_h*OSD_BOTTOM_LEFT_W+osd_w])& 0x8000;
                    }
                }
            }
        }
    }
    hi_memset(stBitmap_bottom_left.pData, (2*OSD_BOTTOM_LEFT_W*OSD_BOTTOM_LEFT_H),0, (2*OSD_BOTTOM_LEFT_W*OSD_BOTTOM_LEFT_H));
  hi_memcpy(stBitmap_bottom_left.pData, (2*OSD_BOTTOM_LEFT_W*OSD_BOTTOM_LEFT_H),osd_bottom_left->pixels, (2*OSD_BOTTOM_LEFT_W*OSD_BOTTOM_LEFT_H));
    stBitmap_bottom_left.u32Width = OSD_BOTTOM_LEFT_W;
    stBitmap_bottom_left.u32Height = OSD_BOTTOM_LEFT_H;  
    SDL_FreeSurface(osd_time_text);  
    SDL_FreeSurface(osd_losttarget_info_text); 
    SDL_FreeSurface(osd_other_info_text); 
    return 0;
}

 另外令人疑惑的是SDL_UpdateRect看起来是更新窗口的函数,一旦调用就会导致段错误,对SDL库理解不深,暂时放下以后在研究吧

反色功能

 SDL和海思对于黑色的算法应该是不一样的,也可能是海思的小bug,海思会认为SDL位图这边的黑色是透明色!RGB的值实测在0x80之下好像都没起到作用。更换颜色很容易,变成黑色很困难

而海思自己的反色机制又是个摆设

 所以只能通过我们手动获取区域亮度,调好阈值,在超过指定亮度时,将我们的白色每个数值&0x8000达到反色的效果

 获取区域两度的函数海思的vpss部分给出HI_MPI_VPSS_GetRegionLuma,缺点是其占用资源极大,为了在方便实用的同时兼顾效率,可以单独开个线程获取亮度


HI_VOID *luma_update_task(HI_VOID*arg)
{
    VIDEO_REGION_INFO_S     stRegionInfo_top_left;
    VIDEO_REGION_INFO_S     stRegionInfo_bottom_left;
    RECT_S   LumaRect_top_left[64]={0};
    RECT_S   LumaRect_bottom_left[64]={0};
     /* 获取区域亮度copy from suxuandong */
    wSubcnt[0]=osd_top_left_wh[0][0]/OSDGRIDSIZE;
    hSubcnt[0]=osd_top_left_wh[0][1]/OSDGRIDSIZE;
    stRegionInfo_top_left.u32RegionNum=wSubcnt[0]*hSubcnt[0];
    for(int uj=0;uj<hSubcnt[0];uj++)
        {
            for(int ui=0;ui<wSubcnt[0];ui++)
            {
                LumaRect_top_left[uj*wSubcnt[0]+ui].s32X=osd_top_left_xy[0][0]+ui*OSDGRIDSIZE;
                LumaRect_top_left[uj*wSubcnt[0]+ui].s32Y=osd_top_left_xy[0][1]+uj*OSDGRIDSIZE;
                LumaRect_top_left[uj*wSubcnt[0]+ui].u32Width=OSDGRIDSIZE;
                LumaRect_top_left[uj*wSubcnt[0]+ui].u32Height=OSDGRIDSIZE;
            }
        }
    stRegionInfo_top_left.pstRegion=(RECT_S*)(LumaRect_top_left);
    /* 获取区域亮度copy from suxuandong */
    wSubcnt[1]=osd_bottom_left_wh[0][0]/OSDGRIDSIZE;
    hSubcnt[1]=osd_bottom_left_wh[0][1]/OSDGRIDSIZE;
    stRegionInfo_bottom_left.u32RegionNum=wSubcnt[1]*hSubcnt[1];
    for(int uj=0;uj<hSubcnt[1];uj++)
        {
            for(int ui=0;ui<wSubcnt[1];ui++)
            {
                LumaRect_bottom_left[uj*wSubcnt[1]+ui].s32X=osd_bottom_left_xy[0][0]+ui*OSDGRIDSIZE;
                LumaRect_bottom_left[uj*wSubcnt[1]+ui].s32Y=osd_bottom_left_xy[0][1]+uj*OSDGRIDSIZE;
                LumaRect_bottom_left[uj*wSubcnt[1]+ui].u32Width=OSDGRIDSIZE;
                LumaRect_bottom_left[uj*wSubcnt[1]+ui].u32Height=OSDGRIDSIZE;
            }
        }
    stRegionInfo_bottom_left.pstRegion=(RECT_S*)(LumaRect_bottom_left);
    while(1)
    {
         sleep(5);
         HI_MPI_VPSS_GetRegionLuma(0, 0, &stRegionInfo_top_left,g_aRectLuma[0], GETLUMAMILISECS);
         HI_MPI_VPSS_GetRegionLuma(0, 0, &stRegionInfo_bottom_left,g_aRectLuma[1], GETLUMAMILISECS);
    }
}

 线程的打开在上面初始化做了,对于反色的处理,在叠加部分给出

效果

b78c5be671274adbb369c67d38ab5263.png


相关文章
|
数据安全/隐私保护 块存储
|
3月前
|
存储 自然语言处理 搜索推荐
探索OS Copilot——那款让你瞬间变身超级用户、编程如呼吸般自然、文件管理如同魔法般的神奇操作系统辅助神器!
【9月更文挑战第4天】“OS Copilot”是一款高效的操作系统辅助软件,通过智能化手段简化电脑使用,涵盖智能命令建议、代码片段生成、文件管理及任务自动化等强大功能。其简洁的界面与友好的用户体验使其成为提升生产力的理想选择,无论是专业人士还是普通用户都能从中受益。从安装到实际应用都非常流畅,能显著提升工作效率,是优化数字生活的得力助手。
47 0
|
网络协议 网络虚拟化
中兴设备show命令大全,涉及中兴业务的网络工程师可以着重了解一下!
中兴设备show命令大全,涉及中兴业务的网络工程师可以着重了解一下!
835 0
b站每天收集经验,升级LV6(半自动化)
b站每天收集经验,升级LV6(半自动化)
b站每天收集经验,升级LV6(半自动化)
|
运维 虚拟化 Anolis
浪潮信息工程师:谈一谈设备透传虚拟机启动慢背后的原因及其优化方法 | 第 51 期
明天下午4点,一起听浪潮信息工程师解析设备透传虚拟机启动慢的原因及优化方法。
浪潮信息工程师:谈一谈设备透传虚拟机启动慢背后的原因及其优化方法 | 第 51 期
|
SQL 存储 测试技术
|
安全 Linux Android开发
阿里90后工程师利用ARM硬件特性开启安卓8终端“上帝模式”
本文以安卓8终端为载体,介绍阿里安全潘多拉实验室成员研究并提出的内核空间镜像攻击利用技巧。
6905 0
|
机器人 容器 安全
带你读《工业机器人系统及应用》之三:驱动系统
本书聚焦于工业机器人,涵盖其组成结构、电气控制及实践应用,重点从使用的角度展开介绍,不涉及数学原理分析。书中综合了机械、控制、计算机、传感器、驱动等专业的知识,包含大量新近的工业机器人产品实例,并配有丰富的图表和数据手册,为机器人的设计、生产、布置、操作和维护提供全流程的详细指南。