yolov3在hi3516上实现区域检测《一》(在hi3516DV300上使用VGS接口函数实现画线和矩形)

1:首先找到原NNIE画框函数的C文件:sam_comm_nnie.c文件,HI_S32 SAMPLE_COMM_SVP_NNIE_FillRect(VIDEO_FRAME_INFO_S *pstFrmInfo, SAMPLE_SVP_NNIE_RECT_ARRAY_S* pstRect, HI_U32 u32Color)该函数就是我们检测到目标后执行的画框函数。我们分析他发现,该函数使用的是VGS接口实现画框,仿照这个函数我们可自己实现画框架。

自定义一个画款函数DrawRectOnImage

HI_S32 DrawRectOnImage(VIDEO_FRAME_INFO_S* pstFrmInfo, RECT_S* pstRect, HI_U32 u32Color, HI_U32 rectWidth, HI_U32 rectHeight, HI_U32 rectOffsetX, HI_U32 rectOffsetY)
{
    VGS_HANDLE VgsHandle = -1;
    HI_S32 s32Ret = HI_SUCCESS;
    VGS_TASK_ATTR_S stVgsTask;
    VGS_ADD_COVER_S stVgsAddCover;

    s32Ret = HI_MPI_VGS_BeginJob(&VgsHandle);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("Vgs begin job fail, Error(%#x)\n", s32Ret);
        return s32Ret;
    }

    stVgsTask.stImgOut = *pstFrmInfo;

	//memcpy(&stVgsTask.stImgIn, pstFrmInfo, sizeof(VIDEO_FRAME_INFO_S));
    //memcpy(&stVgsTask.stImgOut, pstFrmInfo, sizeof(VIDEO_FRAME_INFO_S));

    stVgsAddCover.enCoverType = COVER_QUAD_RANGLE;
    stVgsAddCover.u32Color = u32Color;
    stVgsAddCover.stDstRect.s32X = pstRect->s32X + rectOffsetX;
    stVgsAddCover.stDstRect.s32Y = pstRect->s32Y + rectOffsetY;
    stVgsAddCover.stDstRect.u32Width = rectWidth;
    stVgsAddCover.stDstRect.u32Height = rectHeight;

    stVgsAddCover.stQuadRangle.bSolid = HI_FALSE;
    stVgsAddCover.stQuadRangle.u32Thick = 2;

    stVgsTask.stImgIn = *pstFrmInfo;

	//memcpy(stVgsAddCover.stQuadRangle.stPoint, pstRect->astRect[i][j].astPoint, sizeof(pstRect->astRect[i][j].astPoint));
    s32Ret = HI_MPI_VGS_AddCoverTask(VgsHandle, &stVgsTask, &stVgsAddCover);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VGS_AddCoverTask fail, Error(%#x)\n", s32Ret);
        HI_MPI_VGS_CancelJob(VgsHandle);
        return s32Ret;
    }

    s32Ret = HI_MPI_VGS_EndJob(VgsHandle);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VGS_EndJob fail, Error(%#x)\n", s32Ret);
        HI_MPI_VGS_CancelJob(VgsHandle);
        return s32Ret;
    }

    return s32Ret;
}

添加在SAMPLE_COMM_SVP_NNIE_FillRect官方给的代码下面,在这里我们区别与NNIE画框函数就在于不让此函数进行帧图像判断。

解释一下这段代码的大制作用:

函数名称修改为DrawRectOnImage,传入参数pstFrmInfo为一个图像帧的指针,pstRect为矩形框的位置信息,u32Color为矩形框的颜色。

函数内部进行了以下操作:

  1. 检查矩形框的总数,如果为0,则直接返回。
  2. 开始VGS任务。
  3. 复制输入的图像帧信息到VGS任务的输入和输出图像信息中。
  4. 设置覆盖物属性:
    • 将覆盖物类型设置为矩形覆盖(COVER_RECT)。
    • 将矩形框的颜色设置为输入的u32Color
    • 将矩形框的线型设置为非实心(HI_FALSE)。
    • 将矩形框的线宽设置为2。
  5. 遍历矩形框数组,每次循环设置一个矩形框的位置和大小,并调用HI_MPI_VGS_AddCoverTask函数添加覆盖物任务。
  6. 结束VGS任务。
  7. 返回执行结果。

该函数通过使用VGS提供的API来创建VGS任务,并根据输入的矩形框位置信息和颜色,通过添加覆盖物任务,实现在图像帧上绘制矩形框的功能。函数返回执行结果,如果成功则返回HI_SUCCESS,否则返回相应的错误码。

接着在相应的头文件上添加函数声明

2:接着在调用yolov3视频检测的画框函数内使用

 代码如下,起作用部分都已注释

static HI_VOID* SAMPLE_SVP_NNIE_Yolov3_ViToVo_thread(HI_VOID* pArgs)
{
    HI_S32 s32Ret;
    SAMPLE_SVP_NNIE_PARAM_S *pstParam;
    SAMPLE_SVP_NNIE_YOLOV3_SOFTWARE_PARAM_S *pstSwParam;
    VIDEO_FRAME_INFO_S stBaseFrmInfo;
    VIDEO_FRAME_INFO_S stExtFrmInfo;
    HI_S32 s32MilliSec = 20000;
    VO_LAYER voLayer = 0;
    VO_CHN voChn = 0;
    HI_S32 s32VpssGrp = 0;
    HI_S32 as32VpssChn[] = {VPSS_CHN0, VPSS_CHN1};

    pstParam = &s_stYolov3NnieParam;
    pstSwParam = &s_stYolov3SoftwareParam;

     struct timespec start_time,end_time;
    float use_time =0;

    // 假设有一个图像帧和矩形框的位置信息
    //VIDEO_FRAME_INFO_S frameInfo;
    RECT_S rect;

    // 设置图像帧的属性
    // ...

    // 设置矩形框的位置信息
    rect.s32X = 5000;         // 矩形框的左上角X坐标
    rect.s32Y = 5000;         // 矩形框的左上角Y坐标
    rect.u32Width = 5000000;      // 矩形框的宽度
    rect.u32Height = 8000000;     // 矩形框的高度

    // 设置其他参数
    HI_U32 color = 0xFF0000;        // 矩形框的颜色(红色0xFF0000,绿色0x0000FF00)
    HI_U32 rectWidth = 200;           // 矩形框的线宽
    HI_U32 rectHeight = 1000;
    HI_U32 rectOffsetX = 100000;         // 矩形框相对于原始位置的X偏移量
    HI_U32 rectOffsetY = 100000;         // 矩形框相对于原始位置的Y偏移量

    
    while (HI_FALSE == s_bNnieStopSignal)
    {
        clock_gettime(CLOCK_REALTIME, &start_time);
            s32Ret = HI_MPI_VPSS_GetChnFrame(s32VpssGrp, as32VpssChn[1], &stExtFrmInfo, s32MilliSec);
        if(HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_GetChnFrame failed, VPSS_GRP(%d), VPSS_CHN(%d)!\n",
                s32Ret,s32VpssGrp, as32VpssChn[1]);
            continue;
        }

        s32Ret = HI_MPI_VPSS_GetChnFrame(s32VpssGrp, as32VpssChn[0], &stBaseFrmInfo, s32MilliSec);
        SAMPLE_CHECK_EXPR_GOTO(HI_SUCCESS!=s32Ret, EXT_RELEASE,
            "Error(%#x),HI_MPI_VPSS_GetChnFrame failed, VPSS_GRP(%d), VPSS_CHN(%d)!\n",
            s32Ret,s32VpssGrp, as32VpssChn[0]);

        s32Ret = SAMPLE_SVP_NNIE_Yolov3_Proc_ViToVo(pstParam,pstSwParam, &stExtFrmInfo,
        stBaseFrmInfo.stVFrame.u32Width,stBaseFrmInfo.stVFrame.u32Height);
        SAMPLE_CHECK_EXPR_GOTO(HI_SUCCESS!=s32Ret, BASE_RELEASE,
            "Error(%#x),SAMPLE_SVP_NNIE_YOLOV3_Proc failed!\n", s32Ret);
            
        // 开始绘制
        HI_S32 ret = DrawRectOnImage(&stBaseFrmInfo, &rect, color, rectWidth, rectHeight, rectOffsetX, rectOffsetY);

        // 检查绘制结果
        if (ret != HI_SUCCESS)
        {
            printf("Failed to draw rectangle on image, ret = %d\n", ret);
        }
        else
        {
            printf("Rectangle is successfully drawn on image.\n");
        }

        //Draw rect
        s32Ret = SAMPLE_COMM_SVP_NNIE_FillRect(&stBaseFrmInfo, &(pstSwParam->stRect), 0x0000FF00);
        SAMPLE_CHECK_EXPR_GOTO(HI_SUCCESS!=s32Ret, BASE_RELEASE,
            "SAMPLE_COMM_SVP_NNIE_FillRect failed, Error(%#x)!\n", s32Ret);

        s32Ret = HI_MPI_VO_SendFrame(voLayer, voChn, &stBaseFrmInfo, s32MilliSec);
        SAMPLE_CHECK_EXPR_GOTO(HI_SUCCESS!=s32Ret, BASE_RELEASE,
            "HI_MPI_VO_SendFrame failed, Error(%#x)!\n", s32Ret);

       clock_gettime(CLOCK_REALTIME, &end_time);
       use_time = (float)(end_time.tv_sec - start_time.tv_sec)*1000 + (end_time.tv_nsec - start_time.tv_nsec) / 1000000.0;
       SAMPLE_SVP_TRACE_INFO("The use time is %f  \n", use_time);
	

        BASE_RELEASE:
            s32Ret = HI_MPI_VPSS_ReleaseChnFrame(s32VpssGrp,as32VpssChn[0], &stBaseFrmInfo);
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n",
                    s32Ret,s32VpssGrp,as32VpssChn[0]);
            }

        EXT_RELEASE:
            s32Ret = HI_MPI_VPSS_ReleaseChnFrame(s32VpssGrp,as32VpssChn[1], &stExtFrmInfo);
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n",
                    s32Ret,s32VpssGrp,as32VpssChn[1]);
            }

    }

    return HI_NULL;
}

(由于找坐标调试我一直没有调试好,目前只实现了画线功能,下一步实现画框,然后进行区域检测)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值