海思Hi3519A開發(8.在海思上實現 countNonZero)

1 對 IVE_IMAGE_S 的分析

這部分內容來自海思文檔 HiIVE API 參考 ,文檔中有更多圖像類型的說明內容。

說明

定義二維廣義圖像信息。

定義

typedef struct hiIVE_IMAGE_S
{
HI_U64 au64PhyAddr[3]; /* RW;The physical address of the image */
HI_U64 au64VirAddr[3]; /* RW;The virtual address of the image */
HI_U32 au32Stride[3]; /* RW;The stride of the image */
HI_U32 u32Width; /* RW;The width of the image */
HI_U32 u32Height; /* RW;The height of the image */
IVE_IMAGE_TYPE_E enType; /* RW;The type of the image */
}IVE_IMAGE_S;

成員

成員名稱 描述
au64PhyAddr[3] 廣義圖像的物理地址數組
au64VirAddr[3] 廣義圖像的虛擬地址數組
au32Stride[3] 廣義圖像的跨度
u32Width 廣義圖像的寬度
u32Height 廣義圖像的高度
enType 廣義圖像的圖像類型

二維廣義圖像類型表

類型 圖像描述 內存地址 跨度
IVE_IMAGE_TYPE_U8C1 8bit 無符號單通道圖像 僅用到 IVE_IMAGE_S 中的 au64PhyAddr[0]、au64VirAddr[0] 僅用到 u32Stride[0]

圖像描述

如果圖片類型爲 IVE_IMAGE_TYPE_U8C1 時,n 取 8。
1

關於對 Width 和 Stride 的理解,請參考 yuv 圖像裏的stride和plane的解釋

2 代碼實現

根據上一小節的分析,我們知道 Width 是小於等於 Stride 的。當輸入的圖片格式是 U8C1 時,圖片的 Width 等於 Stride。當然下面的代碼也可以進一步簡化。
這裏的代碼是想參考 opencv 的 countNonZero 函數,返回值是灰度值不爲0的像素數。同時也打印出各個像素點的灰度值。
但是此方法耗時過長,對720x576的圖像處理一次時間爲0.28s,推薦使用3 使用海思 IVE 實現 countNonZero

代碼

/*
As we all know, au32Stride[0] greater than u32Width
*/
static HI_U32 CountNonZero(IVE_IMAGE_S *pstImg)
{
	HI_U16 u16Row;
    HI_U16 u16List;
	HI_U8* u8copy;		//read
	HI_U8* u8origin;	//change line
    HI_U16 height;
    HI_U16 width;

	HI_U16 NonZeroCount = 0;

    height = pstImg->u32Height;
    width  = pstImg->u32Width;    
	
	u8copy	 = (HI_U8 *)(HI_UL)pstImg->au64VirAddr[0];
	u8origin = (HI_U8 *)(HI_UL)pstImg->au64VirAddr[0];

    for (u16Row = 0; u16Row < height; ++u16Row)
    {
		for(u16List = 0; u16List < width; ++u16List)
		{
			printf("%d ", *u8copy);
			if(*u8copy != 0)
			{
				NonZeroCount++;
			}
			u8copy += 1;
		}
		printf("\n");
        u8origin += pstImg->au32Stride[0]; //switch to the next line
		u8copy = u8origin;
    }

	return NonZeroCount;
}

效果

  • 先使用 CV 生成一張 64x64 的圖像,其中 10~19 行是黑色部分。
#include <iostream>
#include <stdio.h>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>

using namespace cv;
using namespace std;

int main()
{		
	Mat image(64, 64, CV_8UC1);
		
	for (int i = 0; i < image.rows; i++)	
	{
		uchar* p = image.ptr<uchar>(i);
		for (int j = 0; j < image.cols; j++)
		{
			if (i < 20 && i>=10)     
			{
				p[j] = 0;
			}
			else
			{
				p[j] = 255;
			}
		}
	}

	imwrite("demo.jpg", image);
		
	return 0;
}
  • 轉化爲 yuv 格式圖像
    ffmpeg -i demo.jpg -pix_fmt gray demo.yuv
  • 結果
    1

3 使用海思 IVE 實現 countNonZero

閱讀文檔後發現,海思已經提供了類似的統計函數(我哭了)
HI_S32 HI_MPI_IVE_Hist(IVE_HANDLE *pIveHandle, IVE_SRC_IMAGE_S *pstSrc, IVE_DST_MEM_INFO_S *pstDst, HI_BOOL bInstant);
計算公式:
1
2
在使用前需要聲明和初始化數組 IVE_DST_MEM_INFO_S stCount,使用完需要釋放
在程序中的具體位置可以參閱海思Hi3519A開發(11.海思IVE使用模板總結(FILE->IVE->FILE))

//在 hiSAMPLE_IVE_SFD_S 結構體裏裏聲明
IVE_DST_MEM_INFO_S stCount;
//在 SAMPLE_IVE_Sfd_Uninit 函數裏釋放
IVE_MMZ_FREE(pstSfd->stCount.u64PhyAddr, pstSfd->stCount.u64VirAddr);
//在 SAMPLE_IVE_Sfd_Init 函數裏初始化 
HI_U32 u32Size = IVE_HIST_NUM * sizeof(HI_U32);
s32Ret = SAMPLE_COMM_IVE_CreateMemInfo(&(pstSfd->stCount), u32Size);
SAMPLE_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, SFD_INIT_FAIL, "Error(%#x),Create Count mem info failed!\n", s32Ret);

HI_MPI_IVE_Hist 的具體使用,輸入爲統計用的數組 stCount 和待測試圖片 pstImg,返回值爲灰度值爲255的像素個數。

static HI_U32 SAMPLE_IVE_Count(IVE_DST_MEM_INFO_S stCount, IVE_SRC_IMAGE_S *pstImg)
{
    HI_S32 s32Ret;
	HI_U32 Num;
    HI_U32* pu32Count;
    IVE_HANDLE IveHandle;
    HI_BOOL bBlock = HI_TRUE;
    HI_BOOL bFinish = HI_FALSE;

    s32Ret = HI_MPI_IVE_Hist(&IveHandle, pstImg, &stCount, HI_TRUE);
    SAMPLE_CHECK_EXPR_RET(HI_SUCCESS != s32Ret,s32Ret,"Error(%#x),HI_MPI_IVE_Hist failed!\n",s32Ret); 
    
    s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
    while (HI_ERR_IVE_QUERY_TIMEOUT == s32Ret)
    {
        s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
    }
    SAMPLE_CHECK_EXPR_RET(HI_SUCCESS != s32Ret,s32Ret,"Error(%#x),HI_MPI_IVE_Query failed!\n",s32Ret);

	pu32Count = SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U32, stCount.u64VirAddr);
	Num = *(pu32Count + 255);

    return Num; 
}

使用舉例

HI_U32 CntNonZero;
CntNonZero = SAMPLE_IVE_Count(pstSfd->stCount, &pstSfd->FgImg);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章