×

签到

分享到微信

打开微信,使用扫一扫进入页面后,点击右上角菜单,

点击“发送给朋友”或“分享到朋友圈”完成分享

使用CNCV库的数据输入问题 已解决 lozenyin2022-10-14 18:08:13 回复 7 查看 技术答疑 使用求助 经验交流
使用CNCV库的数据输入问题
分享到:

本人现在编写了一个函数。使用CNCV库将解码出来的cncodec 数据进行缩放和格式转换成Mat格式的图像再输出。确认输入的cncodec 数据是正确的(可保存成文件输出,图像显示正常)但是输出的画面是是全绿。

image.png


以下是源码

// 缩放到720P  cncodec  -> Mat
int decodeCambrian::decodeCambrian_resize(cncodec  src ,cv::Mat *img){

    //初始化
    cnrtDev_t CV_dev;
    cnrtQueue_t CV_queue = nullptr;
    cncvHandle_t CV_handle = nullptr;
    uint32_t batch_size = 1;
    cncvContextInit(CV_dev, CV_queue, CV_handle);//缩放功能初始化

    //参数转换
    cncvImage srcImg;  // 输入的图像信息
    cncvImage dstImg;  // 输出的图像信息
    memset(&srcImg, 0, sizeof(srcImg));
    memset(&dstImg, 0, sizeof(dstImg));

    //cncodec  to cncvImage
    //【源数据】
    srcImg.width=src .width;
    srcImg.height=src .height;
    srcImg.stride[0]=src .stride[0];
    srcImg.stride[1]=src .stride[1];
    srcImg.planeNum=src .planeNum;
    srcImg.plane[0].size=src .height * src .stride[0];
    srcImg.plane[1].size=(src .height/2)*src .stride[1];
    memcpy(&(srcImg.plane[0].addr),(void *)(src .plane[0].addr),src .plane[0].size);
    memcpy(&(srcImg.plane[1].addr),(void *)(src .plane[1].addr),src .plane[1].size);
    // srcImg.plane[0].addr=malloc(srcImg.plane[0].size);
    // srcImg.plane[1].addr=malloc(srcImg.plane[1].size);
    srcImg.colorSpace=(cncvColorSpace)(src .colorSpace);
    srcImg.pixelFmt=(cncvPixelFormat)(src .pixelFmt);
    srcImg.depth=CNCV_DEPTH_8U;
   
    //Mat to cncvImage 
    dstImg.width=img->cols;
    dstImg.height=img->rows;
    dstImg.stride[0]=(img->step);
    dstImg.pixelFmt=CNCV_PIX_FMT_BGRA;//图像格式
    dstImg.colorSpace=CNCV_COLOR_SPACE_BT_601;//颜色空间
    dstImg.plane[0].size=(img->rows)*(img->step);
    dstImg.plane[0].addr=malloc(dstImg.plane[0].size);
    dstImg.planeNum=1;
    dstImg.depth=CNCV_DEPTH_8U;
   

    //参数获取
    cncvImageDe or_t src_desc_yuv;//输入的图像参数
    createImageDe or(&src_desc_yuv);
    src_desc_yuv->width = srcImg.width;
    src_desc_yuv->height = srcImg.height;
    src_desc_yuv->depth = CNCV_DEPTH_8U;
    src_desc_yuv->pixel_fmt = CNCV_PIX_FMT_NV12;
    src_desc_yuv->color_space = (cncvColorSpace)(src .colorSpace);
    src_desc_yuv->stride[0] = srcImg.stride[0];//地址
    src_desc_yuv->stride[1] = srcImg.stride[1];

    cncvImageDe or_t det_desc_rgba;//输出的图像参数
    createImageDe or(&det_desc_rgba);
    det_desc_rgba->width = dstImg.width;
    det_desc_rgba->height = dstImg.height;
    det_desc_rgba->depth = CNCV_DEPTH_8U;
    det_desc_rgba->pixel_fmt = CNCV_PIX_FMT_BGRA;
    det_desc_rgba->color_space = (cncvColorSpace)(src .colorSpace);
    det_desc_rgba->stride[0] = dstImg.stride[0];

    //感兴趣的区域(默认全局)
    cncvRect *src_rois_yuv = (cncvRect *)malloc(batch_size * sizeof(cncvRect));
    src_rois_yuv[0].x=0;
    src_rois_yuv[0].y=0;
    src_rois_yuv[0].w=srcImg.width;
    src_rois_yuv[0].h=srcImg.height;
    cncvRect *dst_rois_rgba = (cncvRect *)malloc(batch_size * sizeof(cncvRect));
    dst_rois_rgba[0].x=0;
    dst_rois_rgba[0].y=0;
    dst_rois_rgba[0].w=(unsigned int)(dstImg.width);
    dst_rois_rgba[0].h=(unsigned int)(dstImg.height);

    printf("-------------------------------------------------\n\r");
    printf(">>> srcImg   width:%8d,height:%8d  \n\r",srcImg.width,srcImg.height);
    printf(">>> dstImg   width:%8d,height:%8d  \n\r",dstImg.width,dstImg.height);
    printf("-------------------------------------------------\n\r");
    printf("src_rois_yuv :%8d,%8d,%8d,%8d   \n\r",src_rois_yuv[0].x,src_rois_yuv[0].y,src_rois_yuv[0].w,src_rois_yuv[0].h);
    printf("dst_rois_rgba:%8d,%8d,%8d,%8d   \n\r",dst_rois_rgba[0].x,dst_rois_rgba[0].y,dst_rois_rgba[0].w,dst_rois_rgba[0].h);
    printf("-------------------------------------------------\n\r");

    //计算工作空间大小
    void *workspace_switch = nullptr;
    size_t workspace_size_switch;//工作空间大小
    cncvGetResizeConvertWorkspaceSize(batch_size,
                                    src_desc_yuv,
                                    src_rois_yuv,
                                    det_desc_rgba,
                                    dst_rois_rgba,
                                    &workspace_size_switch);
    CNRT_CHECK(cnrtMalloc((void **)&(workspace_switch), workspace_size_switch));//在MLU设备上分配内存,创建工作空间

    //相关工作内存空间创建
    void **srcYDev = NULL;//yuv的Y值,指向MLU上源图像y数据的指针
    void **srcUVDev = NULL;//yuv的UV值,指向MLU上源图像UV数据的指针
    void **dstDev = NULL;//指向用于存储输出数据的MLU空间的指针
    CNRT_CHECK(cnrtMalloc((void **)&srcYDev, batch_size * sizeof(void *)));//在mlu220中创建输入图像内存空间
    CNRT_CHECK(cnrtMalloc((void **)&srcUVDev, batch_size * sizeof(void *)));
    CNRT_CHECK(cnrtMalloc((void **)&dstDev, batch_size * sizeof(void *)));

    //主机内存空间(交换变量)
    size_t srcYDataSize = src .height * src .stride[0];
    size_t srcUVDataSize = (src .height/2) * src .stride[1];
    size_t dstDataSize = (img->rows)*(img->step);
    void **srcYDev_tmp = (void **)(malloc(batch_size * sizeof(void *)));
    void **srcUVDev_tmp = (void **)(malloc(srcYDataSize * sizeof(void *)));
    void **dstDev_tmp = (void **)(malloc(dstDataSize * sizeof(void *)));

    //主机到模块
    CNRT_CHECK(cnrtMalloc((void **)&(srcYDev_tmp[0]), srcYDataSize));//在mlu220中创建输入图像内存空间
    CNRT_CHECK(cnrtMalloc((void **)&(srcUVDev_tmp[0]), srcUVDataSize));
    CNRT_CHECK(cnrtMalloc((void **)&(dstDev_tmp[0]), dstDataSize));

    CNRT_CHECK(cnrtMemcpy(srcYDev_tmp[0],srcImg.plane[0].addr ,srcYDataSize ,CNRT_MEM_TRANS_DIR_HOST2DEV));
    CNRT_CHECK(cnrtMemcpy(srcUVDev_tmp[0],srcImg.plane[1].addr,srcUVDataSize ,CNRT_MEM_TRANS_DIR_HOST2DEV));

    //将主机的内存信息映射到模块的内存中
    CNRT_CHECK(cnrtMemcpy(srcYDev,srcYDev_tmp,batch_size*sizeof(void *),CNRT_MEM_TRANS_DIR_HOST2DEV));
    CNRT_CHECK(cnrtMemcpy(srcUVDev,srcUVDev_tmp,batch_size*sizeof(void *),CNRT_MEM_TRANS_DIR_HOST2DEV));
    CNRT_CHECK(cnrtMemcpy(dstDev,dstDev_tmp,batch_size*sizeof(void *),CNRT_MEM_TRANS_DIR_HOST2DEV));

    //执行图像格式转换(当前版本为0.2.118)
    CNCV_CHECK(cncvResizeConvert(   CV_handle,              // 上下文指针
                                    batch_size,             // 
                                    src_desc_yuv,           //
                                    src_rois_yuv,           //
                                    (void **)srcYDev,       //
                                    (void **)srcUVDev,      //
                                    det_desc_rgba,          //
                                    dst_rois_rgba,          //
                                    (void **)dstDev,        //
                                    workspace_size_switch,  //
                                    workspace_switch,       //
                                    CNCV_INTER_BILINEAR));  //
    CNRT_CHECK(cnrtSyncQueue(CV_queue));//同步队列

    //获取结果
                        //目的地址、源地址,大小,方向
    CNRT_CHECK(cnrtMemcpy(dstImg.plane[0].addr,dstDev_tmp[0],dstDataSize, CNRT_MEM_TRANS_DIR_DEV2HOST));//模块到主机

    printf(">>>dstImg info:w=%d,h=%d,  planeNum=%d, addr=%llu,size=%d \n\r  ",
                    dstImg.width,
                    dstImg.height,
                    dstImg.planeNum,
                    dstImg.plane->addr,
                    dstImg.plane->size);

    //转换图像格式
    cncvStatus_t status;
    status = cncvutils::cncvImageToMat(dstImg, *img);//cncvImage to Mat
    if (status != CNCV_STATUS_SUCCESS) {
        ERROR("error, cannot translate to cv::Mat");
    } else {
        LOG("transform cncvImage to cv::Mat  success!");
        //printf(">>>dstImg.pixelFmt=%d,\n\r",dstImg.pixelFmt);
    }

    //释放内存
    free(src_rois_yuv);
    free(dst_rois_rgba);
    CNRT_CHECK(cnrtFree(srcYDev));
    CNRT_CHECK(cnrtFree(srcUVDev));
    CNRT_CHECK(cnrtFree(dstDev));
    CNRT_CHECK(cnrtFree(workspace_switch));
    CNRT_CHECK(cnrtFree(srcYDev_tmp[0]));
    CNRT_CHECK(cnrtFree(srcUVDev_tmp[0]));
    CNRT_CHECK(cnrtFree(dstDev_tmp[0]));
    free(srcYDev_tmp);
    free(srcUVDev_tmp);
    free(dstDev_tmp);
    delete src_desc_yuv;//回收内存
    delete det_desc_rgba;

    cncvDestroyImage(&srcImg);
    cncvDestroyImage(&dstImg);
   
    cncvDestroy(CV_handle);
    cnrtDestroyQueue(CV_queue);
    cnrtDestroy();

    return 0;

}

我该如何去排查与处理这个问题呢?谢谢!~

版权所有 © 2024 寒武纪 Cambricon.com 备案/许可证号:京ICP备17003415号-1
关闭