海思人脸识别(1) |
您所在的位置:网站首页 › 海思3516d开发板 › 海思人脸识别(1) |
海思人脸识别(1) – YUV2BGR
这可能是全网第一个YUV转BGR(B0B1B2…G0G1G2…R0R1R2…)的博客。
网上全部都是yuv2rgb(B0G0R0B1G1R1…),而且代码都不规整,没有做出最后的效果。所以自己在实际过程中整理了一份YUV2BGR的详细过程。 任务要求:人脸识别模型要求图像输入格式BGR(B0B1B2…G0G1G2…R0R1R2…),输入图片的大小是1024 * 576,需要先在外面把图片缩放和格式转化。 需要用到的模块VI、VPSS、IVE 需要理解的视频格式YUV420SP、RGB vi模块:这里我们摄像头采用BT.601接口。 VPSS模块:需要对源视频流进行裁剪,1920 * 1080->1024 * 576的缩放 IVE模块:是海思媒体处理芯片智能分析系统中的硬件加速模块,也是这次的重点模块。 接下来的两幅图片详细说明这两种格式的区别,图片来源于HI IVE API参考: 网上都是IVE_IMAGE_TYPE_U8C3_PACKAGE,所以直接调用fwrite写入大小为stDst.u32Width * stDst.u32Height * 3就行了 注意看IVE_IMAGE_TYPE_U8C3_PLANER的格式,指针数组VirAddr[3]按顺序分别存储B、G、R的指针,所以代码部分需要做出相应的改变(这也是我研究很久后才发现的)。 废话不多说,上代码,如下代码参考https://github.com/openhisilicon/HIVIEW/blob/master/mod/svp/3516d/nnie/sample/vpss_capture.cpp代码,做出小部分更改 HI_S32 yuvFrame2rgb(VIDEO_FRAME_S* pVBuf) { HI_S32 ret; IVE_SRC_IMAGE_S stSrc; IVE_SRC_IMAGE_S stDst; IVE_HANDLE IveHandle; IVE_CSC_CTRL_S stCscCtrl; HI_BOOL bInstant = HI_TRUE; unsigned char *pImage; stSrc.au64PhyAddr[0] = pVBuf->u64PhyAddr[0]; stSrc.au64PhyAddr[1] = pVBuf->u64PhyAddr[1]; stSrc.au64PhyAddr[2] = pVBuf->u64PhyAddr[2]; stSrc.au64VirAddr[0] = pVBuf->u64VirAddr[0]; stSrc.au64VirAddr[1] = pVBuf->u64VirAddr[1]; stSrc.au64VirAddr[2] = pVBuf->u64VirAddr[2]; stSrc.au32Stride[0] = pVBuf->u32Stride[0]; stSrc.au32Stride[1] = pVBuf->u32Stride[1]; stSrc.au32Stride[2] = pVBuf->u32Stride[2]; stSrc.u32Width = pVBuf->u32Width; stSrc.u32Height = pVBuf->u32Height; switch (pVBuf->enPixelFormat) { case PIXEL_FORMAT_YVU_PLANAR_420: stSrc.enType = IVE_IMAGE_TYPE_YUV420P; break ; case PIXEL_FORMAT_YVU_SEMIPLANAR_420: stSrc.enType = IVE_IMAGE_TYPE_YUV420SP; break ; default: printf("unsupported PixelFormat yet, %d\n", pVBuf->enPixelFormat); break ; } stDst.au32Stride[0] = pVBuf->u32Width; stDst.au32Stride[1] = pVBuf->u32Width; stDst.au32Stride[2] = pVBuf->u32Width; stDst.u32Width = pVBuf->u32Width; stDst.u32Height = pVBuf->u32Height; //stDst.enType = IVE_IMAGE_TYPE_U8C3_PACKAGE; stDst.enType = IVE_IMAGE_TYPE_U8C3_PLANAR; // 重点,重点,重点,需要使用这种格式 //if(img.cols != pVBuf->u32Width || img.rows != pVBuf->u32Height || !stDst.au64VirAddr[0]) { ret = HI_MPI_SYS_MmzAlloc_Cached(&stDst.au64PhyAddr[0], (HI_VOID **)&stDst.au64VirAddr[0], NULL,HI_NULL, stDst.u32Height*stDst.u32Width*3); if (HI_FAILURE == ret) { printf("MmzAlloc_Cached failed!\n"); return HI_FAILURE; } printf("MmzAlloc_Cached OK!\n"); } // 重点,重点,重点,加上偏移的大小是stDst.au32Stride[0]*stDst.u32Height stDst.au64PhyAddr[1] = stDst.au64PhyAddr[0] + stDst.au32Stride[0]*stDst.u32Height; stDst.au64PhyAddr[2] = stDst.au64PhyAddr[1] + stDst.au32Stride[1]*stDst.u32Height; stDst.au64VirAddr[1] = stDst.au64VirAddr[0] + stDst.au32Stride[0]*stDst.u32Height; stDst.au64VirAddr[2] = stDst.au64VirAddr[1] + stDst.au32Stride[1]*stDst.u32Height; stCscCtrl.enMode = IVE_CSC_MODE_PIC_BT601_YUV2RGB; ret = HI_MPI_IVE_CSC(&IveHandle, &stSrc, &stDst, &stCscCtrl, bInstant); if (HI_FAILURE == ret) { printf("YUV Convert to RGB failed!\n"); return HI_FAILURE; } pImage = (unsigned char *)stDst.au64VirAddr[0]; if(NULL == pImage) { printf( "stDst.au64VirAddr[0] is null!\n"); return HI_FAILURE; } FILE *pfd; uint64_t count = 0; pfd = fopen("/home/buffer/1024_576.bgr", "wb+"); fflush(pfd); // 重点:注意写入数据的大小stDst.u32Width*stDst.u32Height fwrite((HI_VOID *)stDst.au64VirAddr[0], stDst.u32Width*stDst.u32Height, 1, pfd); fflush(pfd); fwrite((HI_VOID *)stDst.au64VirAddr[1], stDst.u32Width*stDst.u32Height, 1, pfd); fflush(pfd); fwrite((HI_VOID *)stDst.au64VirAddr[2], stDst.u32Width*stDst.u32Height, 1, pfd); printf( "after fwrite()!\n"); fflush(pfd); return 0; }最后将1024_576.bgr转化成BMP即可(转换bmp的代码去网上搜索即可),最终效果如下。如果有任何问题或者疑问,欢迎留言。 图片来源于网络,如侵权,联系我删除。 参考链接: https://github.com/openhisilicon/HIVIEW/blob/master/mod/svp/3516d/nnie/sample/vpss_capture.cpp |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |