[TI TDA4 J721E](升级版)单屏显示多路摄像头数据(img_mosaic_module节点使用)

          首先感谢阅读,如果您也对TDA4相关的开发感兴趣,我们这边有个学习交流微信群,可以入群和大家一起交流学习。

资历较浅,水平有限,如遇错误,请大家多指正!

保持开源精神,共同分享、进步!

博主WX : AIR_12  我会拉你入群。

链接:TDA4 相关专栏        链接:TDA4  Demo  Gitee开源库

欢迎大家加入,一起维护这个开源库,给更多的朋友提供帮助。


此篇教程的完整资源在这里下载

TITDA4单屏多路显示Demo完整资源ImgMosaic节点的使用教程-C/C++文档类资源-CSDN下载


前几天写了一个关于单屏多显示的帖子:

[TI TDA4]TIOVX 单屏显示多路摄像头数据(Mosaic节点使用)_AIRKernel的博客-CSDN博客

        当时只是研究了其中的一个Demo,这个Demo里面的图像显示还是有点问题,应该是当时作者算法的问题,我也没有详细研究。

        这两天重新梳理了以下,发现有一个Node是专门做这个图像镶嵌的工作的,img_mosaic节点。这个imgMosaic Node的主要作用目前看来就是将图像进行镶嵌到一张大图上,进行显示。比如将多个图像区域,内嵌到一个1920*1080尺寸的image上,然后显示出来。(个人理解,如有不同或者错误,欢迎大家指正一下)。

        这篇博客就写一下这个节点的移植和实际应用。


首先看一下效果图:

这里可以设置屏幕显示2个~多个,应该是可以随意分屏的。这个大家可以去试一下,我这里分了9个。另外,我这里只有一个YUV摄像头,如果有多个,大家可以将多个图像替换进去就可以显示不同的图像了,这个替换比较简单,看到代码就应该明白了。


一、基于Demo的移植

(基于ti-processor-sdk-rtos-j721e-evm-08_00_00_12下的app_usb_disp_templete)

app_usb_disp_templete下载地址如下:

TDA4开发板USB摄像头显示NV12图像完整资源-C/C++文档类资源-CSDN下载


这个Node的相关操作文件,是从

ti-processor-sdk-rtos-j721e-evm-08_00_00_12/vision_apps/apps/dl_demos/app_tidl_avp2路径里面拷贝过来的。

1、拷贝一份app_usb_disp_templete,命名为app_usb_disp。

2、将两个文件:avp_img_mosaic_module.c avp_img_mosaic_module.h,拷贝到app_usb_disp下。(请忽略encode这两个文件,暂时用不到,还有点问题没有解决,后面会专门处理这个问题)。

3、修改concerto.mak内容

这里有四个地方需要修改 添加参与编译的源文件、添加头文件路径、添加库路径

A、        修改TARGET ,这里可以根据自己的需要进行命名。如:vx_app_usb_disp
B、        CSOURCES += app_img_mosaic_module.c
C、        IDIRS += $(IMAGING_IDIRS)
D、        STATIC_LIBS += $(IMAGING_LIBS)
如图,左边是修改过的,右边是修改前的。大家对照以下(忽略encode相关)

 4、main.c中添加头文件 
#include "app_img_mosaic_module.h"
在AppObj中添加一个img的对象:ImgMosaicObj imgMosaicObj;
在AppObj中添加一个 graph,用于执行Mosaic节点。

5、 分别在app_init / app_create_graph / app_verify_graph / app_run_graph_for_one_frame 中添加关于imgMosaic相关的内容。


app_init中对imgMosaic节点进行初始化操作/添加注册图像处理的kernel。
app_create_graph 中创建 graph。
app_verify_graph  中对 graph进行检查。
app_run_graph_for_one_frame 中执行graph。
分别如下图(对应的函数都在刚刚拷贝的两个文件中):

 

本工程的工作总体流程是(具体大家还是跟着代码走读一下):

A、创建了两个Graph,一个用于执行imgMosaic,一个用于执行Display。

B、imgMosaic节点的输入是9个NV12格式的图像组成的array(用户数组),输出是一个1920*1080的image。

C、display节点的输入是imgMosaic节点的输出图像。

D、首先usb摄像头先工作,生成YUV图像,在内存中以指针形式传递出去。

E、将usb摄像头生成的YUV数据,复制到imgMosaic节点的输入数组中。

F、执行imgMosaic节点,将输入的数组,生成一个输出的显示图像。

G、将输出的显示图像,传递给display节点,然后执行disp_graph,显示出图像。

D-G 的过程,每一次都会执行一次,将数组更新,然后显示也会更新。


添加完上述这些东西以后,基本上就可以正常编译核运行了。

其中有一个函数是我后来添加的:app_running_imgMosaic,位于app_img_mosaic_module.c内,这个函数用于拷贝摄像头生成的数据,到imgMosaic节点的用户数组内。大家可以通过修改这个函数的传入指针,将不同摄像头的数据传入即可得到想要的数据。

//动态更新imgMosaic节点内的输入数组的内容
//目前此函数仅支持NV12格式数据的拷贝,大家可以根据自己需要改一下,比如可以拷贝BMP图像的RGB数据等等
vx_status app_running_imgMosaic(vx_object_array *array, char *image)
{
    vx_status status = VX_SUCCESS;

    if (status == VX_SUCCESS)
    {
        status = vxGetStatus((vx_reference)(*array));       //查看array状态,如果为空则表示错误
        vx_size arrLen;
        vxQueryObjectArray((*array), VX_OBJECT_ARRAY_NUMITEMS, &arrLen, sizeof(vx_size)); //查询数组内元素的个数

        vx_int32 i;

        for (i = 0; i < arrLen; i++)        //将数据拷贝到数组中
        {
            vx_rectangle_t rect;
            vx_imagepatch_addressing_t image_addr;
            vx_map_id map_id;
            void *data_ptr;
            vx_uint32 img_width;
            vx_uint32 img_height;
            vx_image in_img;

            in_img = (vx_image)vxGetObjectArrayItem((*array), i);                       //获取array内对象的属性,这里是设置为图像格式

            vxQueryImage(in_img, VX_IMAGE_WIDTH, &img_width, sizeof(vx_uint32));        //查询图像宽度
            vxQueryImage(in_img, VX_IMAGE_HEIGHT, &img_height, sizeof(vx_uint32));      //查询图像的高度

            rect.start_x = 0;
            rect.start_y = 0;
            rect.end_x = img_width;
            rect.end_y = img_height;
            status = vxMapImagePatch(in_img,            //向内核申请图像访问的指针地址,用于拷贝用户数据到vx内核空间
                                     &rect,
                                     0,
                                     &map_id,
                                     &image_addr,
                                     &data_ptr,
                                     VX_WRITE_ONLY,
                                     VX_MEMORY_TYPE_HOST,
                                     VX_NOGAP_X);

            memcpy(data_ptr, image, img_width * img_height);    //拷贝数据

            vxUnmapImagePatch(in_img, map_id);                  //释放map_id

            rect.start_x = 0;
            rect.start_y = 0;
            rect.end_x = img_width;
            rect.end_y = img_height / 2;
            status = vxMapImagePatch(in_img, //向内核申请图像访问的指针地址,用于拷贝用户数据到vx内核空间
                                     &rect,
                                     1,
                                     &map_id,
                                     &image_addr,
                                     &data_ptr,
                                     VX_WRITE_ONLY,
                                     VX_MEMORY_TYPE_HOST,
                                     VX_NOGAP_X);

            memcpy(data_ptr, image + img_width * img_height, img_width * img_height / 2); //拷贝数据,这里需要注意拷贝源地址的偏移量

            vxUnmapImagePatch(in_img, map_id); //释放map_id

            vxReleaseImage(&in_img);//释放临时图像
        }
    }
    return status;
}

我会将完整工程放过来,资源上传审核需要时间,链接如下:

TITDA4单屏多路显示Demo完整资源ImgMosaic节点的使用教程-C/C++文档类资源-CSDN下载

 PS:这个不是广告,我自己在用的笔记软件。给大家推荐一款比较实用的在线云笔记 Notion(免费),下载链接如下:

NotionForUbuntu.tar.xz-管理软件文档类资源-CSDN下载


【声明】
【欢迎转载转发,请注明出处。原创比较辛苦,请尊重原创,祝大家学习愉快!】
【博主专注嵌入式开发,具有多年嵌入式软、硬件开发经验,欢迎大家学习交流!】
【如有嵌入式相关项目需求,欢迎私信】


End

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值