s32v linux,【ATU Book-S32V】 S32V234 软件浅谈-ISP | S32V ISP kernel 設計指南 (下)

前一篇我們提到 IPUS、IPUV的架構並舉了一個 IPUS 算子的範例,接下來我們繼續來看 IPUV 以及 Histogram 的範例。

b. rgb2y.ipuv(IPUV kernel,使用在範例〝ov10640_default〞graph中)

此算子取自 ov10640_default 範例,主要功能為輸入 3 組 input channel(R,G,B),經算子運算後以 1 個 Y 的 output 輸出。#Engine: IPUS2, IPUS3 (LUT)

#Function:

#LUT with 12 bit in 16 out

# extract max and min

#turn on off via GPR0

#

#step_x, step_in, step_out=1

# no neighborhood used

#input:

#line0: R 16 bit

#line0: G 16 bit

#line0: B 16 bit

#output:

#line0: Y 16 bit

#

# parameters:

# gpr4-gpr6: conversion parameters

# gpr13: maximum ypos

.global rgb2y_start

rgb2y_start:

// scaled to 32768 = 15 bits to allow to deal with overflows

// Y= 0,299xR + 0,587xG + 0,114xB

//mov gpr0,9797   //R*gpr4->Y     :  32768 * 0,299

//mov gpr1,19234  //G*gpr5->Y     :  32768 * 0,587

//mov gpr2,3735   //B*gpr6->Y     :  32768 * 0,114

//gpr3 must not be used as it is parameter for compression

mov confalu,(0 /*unsigned*/ | (1<<1) /*saturate*/ | (15<<4) /*shr*/)

max gpr13,gpr13,ypos

done rgb2y_loop,i

rgb2y_loop:

//Y

mulh vsacc0,vh0,gpr4  // R->Y

mulh vacc0,vh5,gpr5   // G->Y

mulh vacc0,vh10,gpr6  // B->Y

//mov vout0,vacc0

dvot vacc0,rgb2y_loop,ixo

//halt

.global rgb2y_end

rgb2y_end:

rgb2y_start、rgb2y_end此為算子的起終點 label。// scaled to 32768 = 15 bits to allow to deal with overflows

// Y= 0,299xR + 0,587xG + 0,114xB

//mov gpr0,9797   //R*gpr0->Y :  32768 * 0,299

//mov gpr1,19235  //G*gpr1->Y :  32768 * 0,587

//mov gpr2,3735   //B*gpr2->Y :  32768 * 0,114參考 RGB 轉 YUV 公式中的Y = 0.299xR + 0.587xG + 0.114xB

如同註解中所解釋,算子中先初始化 RGB 轉 YUV 公式中所需要的常數,乘上 32768 後,可轉為整數,分別存入 gpr0、gpr1、gpr2 以便後續使用。

但這裡的 gpr0、gpr1、gpr2 皆被標示為註解,那是在哪裡初始化的呢?

回到 VSDK source code 的目錄下尋找,結果在 demo app 的目錄裡面可以發現這些值被定義在cpp[1] 中,且可以發現其初始化的 GPR 為 gpr4、gpr5、gpr6(address 0x54,0x55,0x56),而不是 gpr0、gpr1、gpr2(與後面的 kernel code 呼應)。

2b9866f9f2831136a7391261e5b1e681.png

[1] VisionSDK_S32V2_RTM_1_3_0/s32v234_sdk/demos/isp/isp_ov10640_default/src/main.cppmov confalu,(0 /*unsigned*/ | (1<<1) /*saturate*/ | (15<<4) /*shr*/)算子中會使用到 ALU 做計算,所以需要設定 Register confalu 的初始值。

(15<<4) /*shr*/,前述乘上 32768 ,此設定會將 ALU 的結果位移回來。

其初始值設定為 unsigned 以及 saturate。//Y

mulh vsacc0,vh0,gpr4  // R->Y

mulh vacc0,vh5,gpr5   // G->Y

mulh vacc0,vh10,gpr6  // B->Y利用 RGB 轉 YUV 的公式進行矩陣運算並利用累加器計算 Y 值,最終累加的結果 Y 會存放在 vacc0。dvot vacc0,rgb2y_loop,ixodvot 表示 Pixel Done with VOUT0。同 Pixel Done 指令,但輸出設定為 vacc0。

引入下一組 input,輸出 vout0 並更新 XPOS 值。此 loop 會持續到 XPOS > XSIZE 後停止,詳細說明可參考文件〝如何从无到有完成ISP kernel算子的参数调整〞。

c.histogram.ipus

histogram 算子可利用 IPUS 的 Histogram Engine 進行 input data 出現次數的統計計算。以下舉一個簡單的例子,計算亮度(Y)值的直方圖,並嘗試將圖秀在螢幕上。.global histogram_1to1_start

histogram_1to1_start:

// configure Histogram engine

mov confhist,(0 /*offset*/ | (8<<8) /*scale*/)

done histogram_1to1_loop,i    // load first pixel

histogram_1to1_loop:

// incrment histogram value:

// hist[ina0 >> 8]++

lsr hbinincl,ina0,8

// now we are done and get the next input pixels

done histogram_1to1_loop,ix

halt

.global histogram_1to1_end

histogram_1to1_end:

histogram_1to1_start、histogram_1to1_end此為算子的起終點 label。mov confhist,(0 /*offset*/ | (8<<8) /*shr*/)Histogram Configuration Register,設定 offset 為 0;另外因為我們使用 HBININCL ,所以 scale 參數 donnot care。done histogram_1to1_loop,i // load first pixel一次進 1 個 data,此 data 設定為 Pixel components are 8-bits in size and should be read from the higher 8-bits of the 16-bit OUT matrix。

961b2bd5c350f6cb0f0293a5c6db85c7.png// incrment histogram value:

// hist[ina0 >> 8]++

lsr hbinincl,ina0,8HBININCL 只接受 8 bit 的 data,然而前面提到 input data 為高 8 bit,所以這裡右移 8 bit 之後存入。

done histogram_1to1_loop,ix引入下一組 input 並更新 XPOS 值。

至此,系統會將 video frame 的 Y histogram matrix 儲存在 IPUS Histogram Engine 內,接下來我們可以經由 A53  讀出此矩陣並使用 OpenCV 將其畫在螢幕上,如圖。In main function:

// Histogram Engine initialize

gIpuHist.mIpuIdx = SEQ_IPUS1;

SEQ_HistogramEnable(SEQ_IPUS1);

In Run function:

// Histogram data acquire

SEQ_HistogramGet(&gIpuHist);

// Draw the output frame for each channel

vsdk::Mat frame = lFrame.mUMat.getMat(cv::ACCESS_RW | OAL_USAGE_CACHED);

for (int i = 0; i < IPU_HIST_SIZE; i++) {

cv::line((cv::Mat)frame,

cv::Point(100+i*3,720),

cv::Point(100+i*3,720-10*(gIpuHist.mpData[i])/1280),

cv::Scalar(255, 255, 255), 3, 4);

}

f9393ade11dda683d01dc51ed090ed32.png

The End!!!

02a327b9ee0c8be6a6ff4428cc3ea7c9.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值