這篇文章的基礎(chǔ)是《Windows上快速部署Vitis HLS OpenCV仿真庫》,我們使用的版本是Vitis HLS 2022.2,其他版本BUG不清楚,目前已知2021版本有BUG,只能使用其他方式,本文不適合。
這次選擇中值濾波這個常規(guī)算法作為演示算法。
算法原理
算法原理很簡單,我們先介紹均值濾波,因為線性濾波的基礎(chǔ)是均值濾波,中值濾波是在這個基礎(chǔ)上發(fā)展過來的。
均值濾波
圖像均值濾波是一種基本的圖像平滑處理方法,也被稱為“盒子濾波”或“平滑濾波”。它的主要思想是對圖像中的每個像素取一個局部均值,以降低圖像噪聲和細節(jié)對圖像邊緣檢測和其他計算機視覺算法的影響。
具體來說,圖像均值濾波涉及在圖像中移動一個固定尺寸的窗口,例如 的窗口。對于每個窗口,計算窗口內(nèi)所有像素的平均值,并將該值分配給窗口中心的像素。這個過程將重復(fù)應(yīng)用于整個圖像,用于生成平滑的輸出圖像。
在進行圖像處理時,一張圖片可以看做一個矩陣,假設(shè)有個6x6圖片,如下:
處理內(nèi)核如下:
動畫演示處理過程如下
特點
具有非常不具代表性的值的單個像素會顯著影響其鄰域中所有像素的平均值。
當濾波器鄰域跨越邊緣時,濾波器將為邊緣上的像素插入新值,從而模糊該邊緣。如果輸出中需要尖銳的邊緣,這可能是個問題。
這兩個問題都由中值濾波器解決,中值濾波器通常是比均值濾波器更好的降噪濾波器,但計算時間更長。
通常,均值濾波器充當?shù)屯l率濾波器 ,因此減少了圖像中存在的空間強度導(dǎo)數(shù)。
上圖描繪了一個包含更廣泛不同空間頻率的場景。用 3×3 均值濾波器平滑一次后,我們得到
背景中的低空間頻率信息并未受到過濾的顯著影響,但前景對象的(曾經(jīng)清晰的)邊緣已被明顯平滑。用 7×7 均值濾波器過濾后,得到下圖
將此結(jié)果與通過在原始圖像上傳遞 3×3 均值濾波器三次獲得的結(jié)果進行比較
上兩圖說明一個問題:對一幅圖像應(yīng)用大窗口的濾波器和應(yīng)用多次小窗口濾波器效果差不多。
常見變體
此處討論的均值平滑濾波器的變體包括:閾值平均,其中僅當其原始值與平均值之間的差大于預(yù)設(shè)閾值時才改變中心像素值的條件下應(yīng)用平滑。這具有平滑噪聲的效果,圖像細節(jié)的損失較小。
其他不計算鄰域均值的卷積濾波器也經(jīng)常用于平滑。其中最常見的一種是高斯平滑濾波器。
中值濾波
圖像中值濾波是一種常用的非線性濾波方法,也被稱為排序濾波器。它的主要原理是將圖像中每個像素周圍的像素排序,并將排序后的中間值作為該像素的輸出值。
中值濾波可以有效地抑制圖像中的噪聲,同時保留圖像中細節(jié)和邊緣信息。相對于其他線性濾波器(如均值濾波器),它可以在更好地去除噪聲的同時保留圖像的細節(jié)和邊緣上提供更好的性能。
具體地,對于每個像素,中值濾波器會包括 個鄰域像素,其中 和 是正奇數(shù)。它們將以該像素為中心構(gòu)成一個矩形窗口或一個圓形窗口。
窗口大小是中值濾波器的重要參數(shù)。在選擇窗口大小時,應(yīng)該考慮噪聲的特性以及需要保留的圖像細節(jié)。通常情況下,窗口大小越大,中值濾波器能夠去除的噪聲越大,但也會導(dǎo)致圖像模糊。
然后,對于每個像素,將鄰域像素按灰度值進行排序,取排序后的中間值作為該像素的輸出值。這個輸出值將取代原始圖像中的像素值,從而產(chǎn)生一個平滑且噪聲減少的圖像。
中值濾波器的優(yōu)點是它可以在去除噪聲的同時保留圖像中的邊緣和細節(jié),但它的缺點是計算成本較高,并且可能導(dǎo)致圖像的細節(jié)丟失。此外,當噪聲水平很高時,這種濾波器可能無法完全去除噪聲。
所有平滑技術(shù)都可以有效去除信號平滑塊或平滑區(qū)域中的噪聲,但會對邊緣產(chǎn)生不利影響。通常,在降低信號噪聲的同時,保留邊緣也很重要。例如,邊緣對于圖像的視覺特性至關(guān)重要。對于小到中等水平的高斯噪聲,中值濾波器在去除噪聲方面明顯優(yōu)于高斯濾波,同時為給定的固定窗口大小保留邊緣。然而,對于高水平的噪聲,它的性能并不比高斯模糊好多少,而對于散斑噪聲和椒鹽噪聲(脈沖噪聲),它特別有效。正因為如此,中值濾波在數(shù)字圖像處理中得到了非常廣泛的應(yīng)用。
OpenCV實現(xiàn)
使用OpenCV進行算法驗證和Matlab進行算法驗證其實思路差不多,先驗證算法的效果再驗證算法的正確性,這一步使用OpenCV和MatLab一樣,我們就使用OpenCV進行驗證,這一步就不實際展開了,代碼如下:
//-----------------------------------【頭文件包含部分】--------------------------------------- //描述:包含程序所依賴的頭文件 //---------------------------------------------------------------------------------------------- #include"opencv2/core/core.hpp" #include"opencv2/highgui/highgui.hpp" #include"opencv2/imgproc/imgproc.hpp" //-----------------------------------【命名空間聲明部分】--------------------------------------- //描述:包含程序所使用的命名空間 //----------------------------------------------------------------------------------------------- usingnamespacecv; //-----------------------------------【main()函數(shù)】-------------------------------------------- //描述:控制臺應(yīng)用程序的入口函數(shù),我們的程序從這里開始 //----------------------------------------------------------------------------------------------- intmain() { //載入原圖 Matimage=imread("1.jpg"); //創(chuàng)建窗口 namedWindow("中值濾波【原圖】"); namedWindow("中值濾波【效果圖】"); //顯示原圖 imshow("中值濾波【原圖】",image); //進行中值濾波操作 Matout; medianBlur(image,out,7); //顯示效果圖 imshow("中值濾波【效果圖】",out); waitKey(0); }
HLS加速和仿真
上面就完成了算法的介紹和論證,其中論證過程并沒有詳細介紹,因為本篇文章重點不是這個,后續(xù)在介紹這個算法的時候再詳細展開。
HLS工程搭建
新建工程
如下:
第二頁和第三頁不用管,后續(xù)再進行設(shè)置
最后一頁,需要設(shè)置兩個地方,注意一個地方
其中,Uncertainty參數(shù)含義見下,默認不設(shè)置即可。
在UG1399的set_clock_uncertainty章節(jié)有詳細介紹。
【uncertainty】:以 ns 為單位指定,表示時鐘周期中有多少被用作余量。不確定性也可以指定為時鐘周期的百分比。默認的不確定性是時鐘周期的 27%。
也可以使用函數(shù):
set_clock_uncertainty
【uncertainty】:以 ns 為單位指定,表示時鐘周期中有多少被用作余量。不確定性也可以指定為時鐘周期的百分比。默認的不確定性是時鐘周期的 27%。
【clock_list】:應(yīng)用不確定性的時鐘列表。如果未提供,它將應(yīng)用于所有時鐘。
添加源文件
新建xf_median_blur_accel.cpp
#include"xf_median_blur_config.h" staticconstexprint__XF_DEPTH=(HEIGHT*WIDTH*(XF_PIXELWIDTH(TYPE,NPC1))/8)/(PTR_WIDTH/8); voidmedian_blur_accel(ap_uint*img_in,introws,intcols,ap_uint *img_out){ //clang-formatoff #pragmaHLSINTERFACEm_axiport=img_inoffset=slavebundle=gmem0depth=__XF_DEPTH #pragmaHLSINTERFACEm_axiport=img_outoffset=slavebundle=gmem1depth=__XF_DEPTH #pragmaHLSINTERFACEs_axiliteport=rowsbundle=control #pragmaHLSINTERFACEs_axiliteport=colsbundle=control #pragmaHLSINTERFACEs_axiliteport=returnbundle=control //clang-formaton xf::Mat imgInput(rows,cols); xf::Mat imgOutput(rows,cols); //clang-formatoff #pragmaHLSDATAFLOW //clang-formaton //Retrievexf::Matobjectsfromimg_indata: xf::Array2xfMat (img_in,imgInput); //RunxfOpenCVkernel: xf::medianBlur ( imgInput,imgOutput); //Convert_dstxf::Matobjecttooutputarray: xf::xfMat2Array (imgOutput,img_out); return; }//Endofkernel
添加仿真文件
新建xf_median_blur_tb.cpp
#include"common/xf_headers.hpp" #include"xf_median_blur_config.h" intmain(intargc,char**argv){ if(argc!=2){ fprintf(stderr,"Usage:%s",argv[0]); returnEXIT_FAILURE; } cv::Matin_img,out_img,ocv_ref,diff; //Readingintheimage: #ifGRAY in_img=cv::imread(argv[1],0);//readinginthegrayimage #else in_img=cv::imread(argv[1],1);//readinginthecolorimage #endif if(in_img.data==NULL){ fprintf(stderr,"ERROR:Cannotopenimage%s ",argv[1]); returnEXIT_FAILURE; } //creatememoryforoutputimage #ifGRAY ocv_ref.create(in_img.rows,in_img.cols,CV_8UC1); out_img.create(in_img.rows,in_img.cols,CV_8UC1);//creatememoryforoutputimage diff.create(in_img.rows,in_img.cols,CV_8UC1); #else ocv_ref.create(in_img.rows,in_img.cols,CV_8UC3); out_img.create(in_img.rows,in_img.cols,CV_8UC3);//creatememoryforoutputimage diff.create(in_img.rows,in_img.cols,CV_8UC3); #endif //OpenCVreference: cv::medianBlur(in_img,ocv_ref,WINDOW_SIZE); //OpenCLsection: #ifGRAY size_timage_in_size_bytes=in_img.rows*in_img.cols*1*sizeof(unsignedchar); #else size_timage_in_size_bytes=in_img.rows*in_img.cols*3*sizeof(unsignedchar); #endif size_timage_out_size_bytes=image_in_size_bytes; //Callthetopfunction median_blur_accel((ap_uint*)in_img.data,in_img.rows,in_img.cols,(ap_uint *)out_img.data); //Writedownoutputimages: cv::imwrite("hls_out.jpg",out_img);//kerneloutput cv::imwrite("ref_img.jpg",ocv_ref);//referenceimage absdiff(ocv_ref,out_img,diff); //Savethedifferenceimagefordebuggingpurpose: cv::imwrite("error.png",diff); floaterr_per; xf::analyzeDiff(diff,10,err_per); if(err_per>0.0f){ fprintf(stderr,"ERROR:TestFailed. "); return1; }else std::cout<"Test?Passed?"?<
設(shè)置仿真庫
在下面界面設(shè)置相關(guān)參數(shù):
在這個界面設(shè)置
1、Top Function
設(shè)置主函數(shù)的,點擊Browse進行選擇即可。
2、設(shè)置設(shè)計文件Edit cflags,添加調(diào)用的設(shè)計頭文件
添加
-IE:/vitis_hls_image/Vitis_Libraries-2020.2/Vitis_Libraries-2020.2/vision/L1/include-std=c++0x-IH:/FILE/HLS/meanblur/src/build-I./.-D__SDSVHLS__-std=c++0x
3、設(shè)置設(shè)計文件Edit csimflags
-IE:/vitis_hls_image/Vitis_Libraries-2020.2/Vitis_Libraries-2020.2/vision/L1/include-std=c++0x-IH:/FILE/HLS/meanblur/src/build-I./.-D__SDSVHLS__-std=c++0x
接下來設(shè)置仿真庫路徑
1、設(shè)置仿真文件Edit cflags
-IE:/vitis_hls_image/opencv_lib/opencv/build_2/install/include-IE:/vitis_hls_image/Vitis_Libraries-2020.2/Vitis_Libraries-2020.2/vision/L1/include-IH:/FILE/HLS/meanblur/src/build-I.-std=c++0x-D__SDSVHLS__-std=c++0x
2、設(shè)置仿真文件Edit csimflags
-IE:/vitis_hls_image/opencv_lib/opencv/build_2/install/include-IE:/vitis_hls_image/Vitis_Libraries-2020.2/Vitis_Libraries-2020.2/vision/L1/include-IH:/FILE/HLS/meanblur/src/build-I.-std=c++0x-D__SDSVHLS__-std=c++0x
3、設(shè)置Linker Flags,調(diào)用OpenCV庫文件
-LE:/vitis_hls_image/opencv_lib/opencv/build_2/install/x64/mingw/lib-llibopencv_imgcodecs455-llibopencv_imgproc455-llibopencv_core455-llibopencv_highgui455-llibopencv_flann455-llibopencv_features2d455
4、 設(shè)置Input Arguments,這個是調(diào)用仿真圖片,可以后續(xù)再設(shè)置
H:/FILE/HLS/meanblur/src/128x128.png
綜合
點擊綜合按鈕即可開始綜合,結(jié)果如下:
仿真
點擊仿真按鈕得到下圖仿真結(jié)果
下圖從左到右分別為:OpenCV處理的結(jié)果、HLS處理的結(jié)果以及最后的兩個圖像差(無差別即全黑)。
聯(lián)合仿真
點擊聯(lián)合仿真按鈕后等待仿真結(jié)束,然后點擊下面按鈕查看波形:
導(dǎo)出IP
點擊導(dǎo)出IP按鈕等待導(dǎo)出即可。
總結(jié)
今天的例程演示完畢,從建立工程到最后導(dǎo)出IP,基本比較詳細。但是,上面的例程是不能直接應(yīng)用到視頻里的,原因是上面的接口沒經(jīng)過改動,需要從AXI轉(zhuǎn)成AXI-STREAM接口后再再接入到視頻架構(gòu)中即可,這部分我們后續(xù)再詳細說明。
審核編輯:劉清
-
濾波器
+關(guān)注
關(guān)注
162文章
8065瀏覽量
180925 -
計算機視覺
+關(guān)注
關(guān)注
9文章
1706瀏覽量
46555 -
OpenCV
+關(guān)注
關(guān)注
32文章
642瀏覽量
42399 -
HLS
+關(guān)注
關(guān)注
1文章
131瀏覽量
24630
原文標題:如何用 Vitis HLS 實現(xiàn) OpenCV 仿真
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
新手求助,HLS實現(xiàn)opencv算法加速的IP在vivado的使用
Vivado HLS實現(xiàn)OpenCV圖像處理的設(shè)計流程與分析
FPGA高層次綜合HLS之Vitis HLS知識庫簡析
使用Vitis HLS創(chuàng)建屬于自己的IP相關(guān)資料分享
利用Vitis HLS tcl shell一鍵跑通視覺加速例程

Vitis Vision | 利用Vitis HLS tcl shell 一鍵跑通視覺加速例程

Vitis HLS工具簡介及設(shè)計流程
Vitis HLS如何添加HLS導(dǎo)出的.xo文件

Vitis HLS前端現(xiàn)已全面開源
Vitis HLS知識庫總結(jié)
理解Vitis HLS默認行為
AMD全新Vitis HLS資源現(xiàn)已推出

如何在Vitis HLS GUI中使用庫函數(shù)?

評論