海思人脸识别(1)

您所在的位置:网站首页 海思3516d开发板 海思人脸识别(1)

海思人脸识别(1)

2023-08-20 11:39| 来源: 网络整理| 查看: 265

海思人脸识别(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