1.1 概述
下面向大家介紹了使用HLS封裝的縮放IP來實(shí)現(xiàn)視頻圖像縮放功能。將HLS封裝的縮放IP加入到OV5640圖像傳輸系統(tǒng),驗(yàn)證圖像放大和縮小功能。
測試使用模塊:OV5640攝像頭,LCD (RGB接口) 屏。
放大測試:將720P分辨率圖像放大到1080P。
放大測試:將640x480分辨率圖像放大到1024x600
縮小測試:將720P分辨率圖像縮小到640x480。
實(shí)現(xiàn)的縮放IP主要用于功能驗(yàn)證,可以在此基礎(chǔ)上,對數(shù)據(jù)流進(jìn)行進(jìn)一步處理,這里不在贅述。
1.2 縮放IP算法介紹
此部分主要介紹實(shí)現(xiàn)縮放的兩種算法,最近鄰插值法和雙線性插值法。其中最近鄰插值法簡單易懂,但是誤差較大。在最近鄰插值法的基礎(chǔ)上,引出雙線性插值法,也就是此次設(shè)計(jì)的目標(biāo)算法。
1.2.1 最近鄰插值法
圖像的縮放很好理解,就是圖像的放大和縮小。傳統(tǒng)的繪畫工具中,有一種叫做“放大尺”的繪畫工具,畫家常用它來放大圖畫。當(dāng)然,在計(jì)算機(jī)上,我們不再需要用放大尺去放大或縮小圖像了,把這個(gè)工作交給程序來完成就可以了。下面就來講講計(jì)算機(jī)怎么來放大縮小圖像。在本文中,我們所說的圖像都是指點(diǎn)陣圖,也就是用一個(gè)像素矩陣來描述圖像的方法,對于另一種圖像:用函數(shù)來描述圖像的矢量圖,不在本文討論之列。
越是簡單的模型越適合用來舉例子,我們就舉個(gè)簡單的圖像:3X3 的256級灰度圖,也就是高為3個(gè)像素,寬也是3個(gè)像素的圖像,每個(gè)像素的取值可以是 0-255,代表該像素的亮度,255代表最亮,也就是白色,0代表最暗,即黑色。假如圖像的像素矩陣如下所示(這個(gè)原始圖把它叫做源圖,Source):
234 38 22
67 44 12
89 65 63
這個(gè)矩陣中,元素坐標(biāo)(x,y)是這樣確定的,x從左到右,從0開始,y從上到下,也是從零開始,這是圖象處理中最常用的坐標(biāo)系,就是這樣一個(gè)坐標(biāo):
如果想把這副圖放大為 4X4大小的圖像,那么該怎么做呢?那么第一步肯定想到的是先把4X4的矩陣先畫出來再說,好了矩陣畫出來了,如下所示,當(dāng)然,矩陣的每個(gè)像素都是未知數(shù),等待著我們?nèi)ヌ畛洌ㄟ@個(gè)將要被填充的圖的叫做目標(biāo)圖,Destination):
然后要往這個(gè)空的矩陣?yán)锩嫣钪盗耍畹闹祻哪睦飦砟兀渴菑脑磮D中來!好,先填寫目標(biāo)圖最左上角的像素,坐標(biāo)為(0,0),那么該坐標(biāo)對應(yīng)源圖中的坐標(biāo)可以由如下公式得出:
srcX=dstX* (srcWidth/dstWidth) , srcY = dstY * (srcHeight/dstHeight)
其中srcWidth為輸入圖像寬度,srcHeight為輸入圖像高度,dstWidth輸出圖像寬度,dstHeight為輸出圖像高度,srcX 、srcY為輸入圖像坐標(biāo)值,dstX、dstY為輸出圖像坐標(biāo)值。
現(xiàn)在到這里很清楚了,直接套用公式,就可以找到對應(yīng)的原圖的坐標(biāo)了(0*(3/4),0*(3/4))=>(0*0.75,0*0.75)=>(0,0)
找到了源圖的對應(yīng)坐標(biāo),就可以把源圖中坐標(biāo)為(0,0)處的234像素值填到目標(biāo)圖的(0,0)這個(gè)位置了。
接下來,如法炮制,尋找目標(biāo)圖中坐標(biāo)為(1,0)的像素對應(yīng)源圖中的坐標(biāo),套用公式:
(1*0.75,0*0.75)=>(0.75,0)
結(jié)果發(fā)現(xiàn),得到的坐標(biāo)里面竟然有小數(shù),這可怎么辦?計(jì)算機(jī)里的圖像可是數(shù)字圖像,像素就是最小單位了,像素的坐標(biāo)都是整數(shù),從來沒有小數(shù)坐標(biāo)。這時(shí)候采用的一種策略就是采用四舍五入的方法(也可以采用直接舍掉小數(shù)位的方法),把非整數(shù)坐標(biāo)轉(zhuǎn)換成整數(shù),好,那么按照四舍五入的方法就得到坐標(biāo)(1,0),完整的運(yùn)算過程就是這樣的:
(1*0.75,0*0.75)=>(0.75,0)=>(1,0)
那么就可以再填一個(gè)像素到目標(biāo)矩陣中了,同樣是把源圖中坐標(biāo)為(1,0)處的像素值38填入目標(biāo)圖中的坐標(biāo)。
依次填完每個(gè)像素,一幅放大后的圖像就誕生了,像素矩陣如下所示:
234 38 22 22
67 44 12 12
89 65 63 63
89 65 63 63
這種放大圖像的方法叫做最近鄰插值算法,這是一種最基本、最簡單的圖像縮放算法,效果也是最不好的,放大后的圖像有很嚴(yán)重的馬賽克,縮小后的圖像有很嚴(yán)重的失真。效果不好的根源就是其簡單的最臨近插值方法引入了嚴(yán)重的圖像失真,比如,當(dāng)由目標(biāo)圖的坐標(biāo)反推得到的源圖的的坐標(biāo)是一個(gè)浮點(diǎn)數(shù)的時(shí)候,采用了四舍五入的方法,直接采用了和這個(gè)浮點(diǎn)數(shù)最接近的像素的值,這種方法是很不科學(xué)的,當(dāng)推得坐標(biāo)值為 0.75的時(shí)候,不應(yīng)該就簡單的取為1,既然是0.75,比1要小0.25 ,比0要大0.75 ,那么目標(biāo)像素值其實(shí)應(yīng)該根據(jù)這個(gè)源圖中虛擬的點(diǎn)四周的四個(gè)真實(shí)的點(diǎn)來按照一定的規(guī)律計(jì)算出來的,這樣才能達(dá)到更好的縮放效果。雙線性插值算法就是一種比較好的圖像縮放算法,它充分的利用了源圖中虛擬點(diǎn)四周的四個(gè)真實(shí)存在的像素值來共同決定目標(biāo)圖中的一個(gè)像素值,因此縮放效果比簡單的最鄰近插值要好很多。
1.2.2 雙線性插值法
已知的紅色數(shù)據(jù)點(diǎn)與待插值得到的綠色點(diǎn)。
假如我們想得到未知函數(shù)f在點(diǎn)P= (x,y) 的值,假設(shè)我們已知函數(shù)f在Q11 =(x1,y1)、Q12 = (x1,y2),Q21 = (x2,y1) 以及Q22 = (x2,y2) 四個(gè)點(diǎn)的值。
首先在x方向進(jìn)行線性插值,得到R1和R2,然后在y方向進(jìn)行線性插值,得到P。
這樣就得到所要的結(jié)果f(x,y)。
其中紅色點(diǎn)Q11,Q12,Q21,Q22為已知的4個(gè)像素點(diǎn).
第一步:X方向的線性插值,在Q12,Q22中插入藍(lán)色點(diǎn)R2,Q11,Q21中插入藍(lán)色點(diǎn)R1;
第二步:Y方向的線性插值,通過第一步計(jì)算出的R1與R2在y方向上插值計(jì)算出P點(diǎn)。
線性插值的結(jié)果與插值的順序無關(guān)。首先進(jìn)行y方向的插值,然后進(jìn)行x方向的插值,所得到的結(jié)果是一樣的。雙線性插值的結(jié)果與先進(jìn)行哪個(gè)方向的插值無關(guān)。
如果選擇一個(gè)坐標(biāo)系統(tǒng)使得四個(gè)已知點(diǎn)坐標(biāo)分別為 (0, 0)、(0, 1)、(1, 0) 和 (1, 1),那么插值公式就可以化簡為
f(x,y)=f(0,0)(1-x)(1-y)+f(1,0)x(1-y)+f(0,1)(1-x)y+f(1,1)xy
具體的雙線性插值算法描述如下:
對于一個(gè)目標(biāo)像素,通過反向變換得到的浮點(diǎn)坐標(biāo)為(i+u,j+v) (其中i、j均為浮點(diǎn)坐標(biāo)的整數(shù)部分,u、v為浮點(diǎn)坐標(biāo)的小數(shù)部分,是取值[0,1)區(qū)間的浮點(diǎn)數(shù)),則這個(gè)像素值 f(i+u,j+v) 可由原圖像中坐標(biāo)為 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所對應(yīng)的周圍四個(gè)像素的值決定,即:
f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
其中f(i,j)表示源圖像(i,j)處的的像素值,以此類推。
比如,剛才的例子,現(xiàn)在假定目標(biāo)圖的像素坐標(biāo)為(1,1),那么反推得到的對應(yīng)于源圖的坐標(biāo)是(0.75 , 0.75),這其實(shí)只是一個(gè)概念上的虛擬像素,實(shí)際在源圖中并不存在這樣一個(gè)像素,那么目標(biāo)圖的像素(1,1)的取值不能夠由這個(gè)虛擬像素來決定,而只能由源圖的這四個(gè)像素共同決定:(0,0)(0,1)(1,0)(1,1),而由于(0.75,0.75)離(1,1)要更近一些,那么(1,1)所起的決定作用更大一些,這從公式1中的系數(shù)uv=0.75×0.75就可以體現(xiàn)出來,而(0.75,0.75)離(0,0)最遠(yuǎn),所以(0,0)所起的決定作用就要小一些,公式中系數(shù)為(1-u)(1-v)=0.25×0.25也體現(xiàn)出了這一特點(diǎn)。
1.3 HLS實(shí)現(xiàn)
1.3.1 工程創(chuàng)建
新建一個(gè)HLS工程,并在Source中新建Top.cpp、Top.h文件,在TestBench中新建Test.cpp并添加測試圖片test1.jpg。
Top.cpp源碼(Source中添加):
#include"top.h"
#include
void hls_video_scaler_top(AXI_STREAM& input, AXI_STREAM& output,int rows, int cols,int drows, int dcols)
{
#pragma HLS INTERFACE axis port=INPUT_STREAM
#pragma HLS INTERFACE axis port=OUTPUT_STREAM
#pragma HLS RESOURCE core=AXI_SLAVE variable=rows metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=cols metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=drows metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=dcols metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=return metadata="-bus_bundle CONTROL_BUS"
#pragma HLS INTERFACE ap_stable register port=dcols
#pragma HLS INTERFACE ap_stable register port=drows
#pragma HLS INTERFACE ap_stable register port=rows
#pragma HLS INTERFACE ap_stable register port=cols
RGB_IMAGE img_0(rows, cols);
RGB_IMAGE img_1(drows, dcols);
#pragma HLS dataflow
hls::AXIvideo2Mat(input,img_0);
hls::Resize(img_0,img_1,HLS_INTER_LINEAR);
hls::Mat2AXIvideo(img_1, output);
}
Top.h源碼(Source中添加):
#ifndef _TOP_H_
#define _TOP_H_
#include"hls_video.h"
#include"ap_int.h"
// maximum image size
#define MAX_WIDTH 4096
#define MAX_HEIGHT 2160
typedefunsignedcharuchar;
// I/O Image Settings
#define INPUT_IMAGE "test1.jpg"
// typedef video library core structures
typedef hls::stream > AXI_STREAM;
typedef hls::Mat RGB_IMAGE;
void hls_video_scaler_top(AXI_STREAM& input, AXI_STREAM& output,int rows, int cols,int drows, int dcols);
#endif
Test.cpp源碼(Test Bench中添加):
#include"top.h"
#include"hls_opencv.h"
#include"iostream"
#include
usingnamespace std;
usingnamespace cv;
int main (int argc, char** argv)
{
IplImage* src = cvLoadImage(INPUT_IMAGE);
CvSize s;
s.width = 1920;
s.height = 1080;
IplImage* dst = cvCreateImage(s, 8, 3);
AXI_STREAM src_axi, dst_axi;
IplImage2AXIvideo(src, src_axi);
hls_video_scaler_top(src_axi, dst_axi, src->height, src->width,s.height,s.width);
AXIvideo2IplImage(dst_axi, dst);
cvShowImage("src",src);
cvShowImage("dst_hls",dst);
waitKey(0);
return 0;
}
測試圖片test1.jpg(Test Bench中添加):
雙擊打開圖片,右擊->屬性->可查看圖片原始分辨率。
1.3.2 綜合和仿真
1、綜合報(bào)告如下:
2、仿真測試如下:直接單擊開始進(jìn)行仿真。可以看到原始的圖片和經(jīng)過縮放的圖片
1) 縮小的圖片(分辨率420x264)
2) 原始圖片(分辨率840x528)
3)放大后的圖片(1920x1080)
從仿真結(jié)果可以看出,縮放后,圖片雖然有拉長或變短,但是圖像仍然比較清晰。
3、導(dǎo)出封裝好的IP
單擊導(dǎo)出供VIVADO使用的IP,生成后的IP如下所示。
1.4 硬件工程創(chuàng)建
1.4.1 硬件平臺(tái)搭建
本章使用的硬件工程,在OV5640 VDMA圖像傳輸?shù)幕A(chǔ)上進(jìn)行修改。將HLS生成的IP添加工程中,將VideoIn to AXI4-Stream的輸出接口與HLS IP的輸入接口連接,HLS IP的輸出接口與VDMA的AXIS接口連接。
1.4.2 SDK工程修改
#include"I2C_16bit.h"
#include"xiicps.h"
#include"xil_io.h"
#include"xhls_video_scaler_top.h"
#define XPAR_HLS_VIDEO_SCALER_TOP_DEVICE_ID XPAR_HLS_VIDEO_SCALER_TOP_0_DEVICE_ID
#define VDMA_BASEADDR XPAR_AXI_VDMA_0_BASEADDR
#define VIDEO_BASEADDR0 0x01000000
#define VIDEO_BASEADDR1 0x02000000
#define VIDEO_BASEADDR2 0x03000000
//VDMA 分辨率設(shè)置
#define H_ACTIVE 1280
#define V_ACTIVE 720
#define H_STRIDE 1280
XHls_video_scaler_top XHls_video_scaler;
XIicPs Iic;
// HLS IP 初始化
void XHls_video_scaler_initialize(void)
{
int status;
status=XHls_video_scaler_top_Initialize(&XHls_video_scaler, XPAR_HLS_VIDEO_SCALER_TOP_DEVICE_ID);
if(0!=status)
{
xil_printf("XPAR_HLS_VIDEO_SCALER FAILED/n");
}
}
// HLS IP參數(shù)設(shè)置
void XHls_video_scaler_setup(u16 row,u16 col,u16 drow,u16 dcol)
{
XHls_video_scaler_top_SetRows(&XHls_video_scaler,row);
XHls_video_scaler_top_SetCols(&XHls_video_scaler, col);
XHls_video_scaler_top_SetDrows(&XHls_video_scaler, drow);
XHls_video_scaler_top_SetDcols(&XHls_video_scaler, dcol);
XHls_video_scaler_top_InterruptGlobalDisable(&XHls_video_scaler);
XHls_video_scaler_top_EnableAutoRestart(&XHls_video_scaler);
XHls_video_scaler_top_Start(&XHls_video_scaler);
}
void main()
{
// Initialize OV5640 regesiter
I2C_config_init();
//Initialize XHls_video_scaler Ip
XHls_video_scaler_initialize();
//set input and output resolution ratio
XHls_video_scaler_setup(720,1280,1080,1920);
//Xil_Out32((VDMA_BASEADDR + 0x030), 0x108B);// enable circular mode
Xil_Out32((VDMA_BASEADDR + 0x030), 0x108B);// enable circular mode
Xil_Out32((VDMA_BASEADDR + 0x0AC), VIDEO_BASEADDR0); // start address
Xil_Out32((VDMA_BASEADDR + 0x0B0), VIDEO_BASEADDR1); // start address
Xil_Out32((VDMA_BASEADDR + 0x0B4), VIDEO_BASEADDR2); // start address
Xil_Out32((VDMA_BASEADDR + 0x0A8), (H_STRIDE*3)); // h offset (H_STRIDE* 3) bytes
Xil_Out32((VDMA_BASEADDR + 0x0A4), (H_ACTIVE*3)); // h size (H_ACTIVE * 3) bytes
Xil_Out32((VDMA_BASEADDR + 0x0A0), V_ACTIVE); // v size (V_ACTIVE)
/*****************從DDR讀數(shù)據(jù)設(shè)置**********************/
Xil_Out32((VDMA_BASEADDR + 0x000), 0x8B); // enable circular mode
Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0); // start address
Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1); // start address
Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR2); // start address
Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*3)); // h offset (H_STRIDE * 3) bytes
Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*3)); // h size (H_ACTIVE * 3) bytes
Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE); // v size (V_ACTIVE)
while (1) ;
}
這里需要注意,OV5640攝像頭的分辨率是720P,VDMA視頻流配置的分辨率也是720P。VDMA輸出的視頻流經(jīng)過HLS 縮放IP后,調(diào)整了輸出顯示的分辨率。
XHls_video_scaler_initialize()和XHls_video_scaler_setup(720,1280,1080,1920)用于HLS IP初始化和參數(shù)設(shè)置。輸入圖像的分辨率是720P,輸出圖像顯示的分辨率是1080P。
1.5 測試驗(yàn)證
使用OV5640攝像頭拍攝同一副圖片,對比直接輸出圖像和經(jīng)過HLS縮放IP的圖像。
1.5.1 放大測試
(1)720P分辨率圖像輸入,1080P分辨率圖像輸出,未使用HLS IP對輸入進(jìn)行縮放處理,效果如下。
可以看到圖像顯示僅占據(jù)一部分界面,這是因?yàn)檩敵龇直媛蚀笥谳斎敕直媛省]斎雸D像僅占據(jù)輸出圖像的一部分。
1)未經(jīng)過HLS縮放IP處理
(2)720P分辨率圖像輸入,采集圖像經(jīng)過HLSIP處理放大到1080P輸出。
可以看到經(jīng)過HLS 縮放IP處理后的圖像被放大,但是圖像整理放大后畫面仍然清晰。
2)經(jīng)過HLS縮放IP放大處理后的圖像
LCD屏放大測試
640X480分辨率輸入,1024x600分辨率輸出。可以看出經(jīng)過放大后的圖像可以在整個(gè)界面顯示。
3)未經(jīng)過HLS 縮放IP處理
4)經(jīng)過HLS 縮放IP處理
1.6.2 縮小測試
拍攝同一視角,720P圖像輸入,640X480分辨率輸出。使用縮放IP,顯示完整的圖像,而不適用縮放IP,圖像僅部分顯示,這是因?yàn)檩斎胼敵龇直媛什灰恢拢瑑H部分輸出。縮小后的圖像任然清晰。
5)未經(jīng)過HLS 縮放IP處理
6)經(jīng)過HLS 縮放IP處理
小結(jié):
HLS 生成的縮放IP可以在一定程度上放大或縮小圖像,并且不失真,但是同時(shí)與純FPGA編寫的代碼實(shí)現(xiàn),HLS消耗的資源也是需要考慮的一個(gè)重要問題。這里我們會(huì)在后面進(jìn)行討論。
編輯:hfy
-
視頻圖像
+關(guān)注
關(guān)注
0文章
47瀏覽量
17472 -
圖象處理
+關(guān)注
關(guān)注
0文章
9瀏覽量
9040 -
圖像傳輸系統(tǒng)
+關(guān)注
關(guān)注
0文章
5瀏覽量
7968 -
HLS
+關(guān)注
關(guān)注
1文章
128瀏覽量
24043
發(fā)布評論請先 登錄
相關(guān)推薦
評論