海思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


相关文章
|
数据安全/隐私保护 块存储
|
4月前
|
存储 搜索推荐 测试技术
深入探索装机设置:打造个性化与高性能并存的电脑系统
装机设置是一个涉及多个方面的复杂过程,需要我们在硬件选择、操作系统安装、软件安装、性能优化以及个性化设置等多个层面进行综合考虑与实施。通过本文的介绍与探讨,我们希望能够帮助读者打造一个既个性化又高性能的电脑系统,让电脑成为我们工作与生活中的得力助手。同时,我们也希望读者能够在装机过程中不断探索与实践,发掘更多有趣的功能与设置方法,让电脑系统更加符合自己的需求与期望。
60 7
|
网络协议 网络虚拟化
中兴设备show命令大全,涉及中兴业务的网络工程师可以着重了解一下!
中兴设备show命令大全,涉及中兴业务的网络工程师可以着重了解一下!
814 0
|
存储 运维 内存技术
vFW设备开局升级操作指北
vFW设备开局升级操作指北
vFW设备开局升级操作指北
|
运维 虚拟化 Anolis
浪潮信息工程师:谈一谈设备透传虚拟机启动慢背后的原因及其优化方法 | 第 51 期
明天下午4点,一起听浪潮信息工程师解析设备透传虚拟机启动慢的原因及优化方法。
浪潮信息工程师:谈一谈设备透传虚拟机启动慢背后的原因及其优化方法 | 第 51 期
|
SQL 存储 测试技术
|
安全 Linux Android开发
阿里90后工程师利用ARM硬件特性开启安卓8终端“上帝模式”
本文以安卓8终端为载体,介绍阿里安全潘多拉实验室成员研究并提出的内核空间镜像攻击利用技巧。
6896 0