這篇文章的基礎是《Windows上快速部署Vitis HLS OpenCV仿真庫》,我們使用的版本是Vitis HLS 2022.2,其他版本BUG不清楚,目前已知2021版本有BUG,只能使用其他方式,本文不適合。
這次選擇中值濾波這個常規算法作為演示算法。
算法原理
算法原理很簡單,我們先介紹均值濾波,因為線性濾波的基礎是均值濾波,中值濾波是在這個基礎上發展過來的。
均值濾波
圖像均值濾波是一種基本的圖像平滑處理方法,也被稱為“盒子濾波”或“平滑濾波”。它的主要思想是對圖像中的每個像素取一個局部均值,以降低圖像噪聲和細節對圖像邊緣檢測和其他計算機視覺算法的影響。
具體來說,圖像均值濾波涉及在圖像中移動一個固定尺寸的窗口,例如 的窗口。對于每個窗口,計算窗口內所有像素的平均值,并將該值分配給窗口中心的像素。這個過程將重復應用于整個圖像,用于生成平滑的輸出圖像。
在進行圖像處理時,一張圖片可以看做一個矩陣,假設有個6x6圖片,如下:
處理內核如下:
動畫演示處理過程如下
特點
具有非常不具代表性的值的單個像素會顯著影響其鄰域中所有像素的平均值。
當濾波器鄰域跨越邊緣時,濾波器將為邊緣上的像素插入新值,從而模糊該邊緣。如果輸出中需要尖銳的邊緣,這可能是個問題。
這兩個問題都由中值濾波器解決,中值濾波器通常是比均值濾波器更好的降噪濾波器,但計算時間更長。
通常,均值濾波器充當低通頻率濾波器 ,因此減少了圖像中存在的空間強度導數。
上圖描繪了一個包含更廣泛不同空間頻率的場景。用 3×3 均值濾波器平滑一次后,我們得到
背景中的低空間頻率信息并未受到過濾的顯著影響,但前景對象的(曾經清晰的)邊緣已被明顯平滑。用 7×7 均值濾波器過濾后,得到下圖
將此結果與通過在原始圖像上傳遞 3×3 均值濾波器三次獲得的結果進行比較
上兩圖說明一個問題:對一幅圖像應用大窗口的濾波器和應用多次小窗口濾波器效果差不多。
常見變體
此處討論的均值平滑濾波器的變體包括:閾值平均,其中僅當其原始值與平均值之間的差大于預設閾值時才改變中心像素值的條件下應用平滑。這具有平滑噪聲的效果,圖像細節的損失較小。
其他不計算鄰域均值的卷積濾波器也經常用于平滑。其中最常見的一種是高斯平滑濾波器。
中值濾波
圖像中值濾波是一種常用的非線性濾波方法,也被稱為排序濾波器。它的主要原理是將圖像中每個像素周圍的像素排序,并將排序后的中間值作為該像素的輸出值。
中值濾波可以有效地抑制圖像中的噪聲,同時保留圖像中細節和邊緣信息。相對于其他線性濾波器(如均值濾波器),它可以在更好地去除噪聲的同時保留圖像的細節和邊緣上提供更好的性能。
具體地,對于每個像素,中值濾波器會包括 個鄰域像素,其中 和 是正奇數。它們將以該像素為中心構成一個矩形窗口或一個圓形窗口。
窗口大小是中值濾波器的重要參數。在選擇窗口大小時,應該考慮噪聲的特性以及需要保留的圖像細節。通常情況下,窗口大小越大,中值濾波器能夠去除的噪聲越大,但也會導致圖像模糊。
然后,對于每個像素,將鄰域像素按灰度值進行排序,取排序后的中間值作為該像素的輸出值。這個輸出值將取代原始圖像中的像素值,從而產生一個平滑且噪聲減少的圖像。
中值濾波器的優點是它可以在去除噪聲的同時保留圖像中的邊緣和細節,但它的缺點是計算成本較高,并且可能導致圖像的細節丟失。此外,當噪聲水平很高時,這種濾波器可能無法完全去除噪聲。
所有平滑技術都可以有效去除信號平滑塊或平滑區域中的噪聲,但會對邊緣產生不利影響。通常,在降低信號噪聲的同時,保留邊緣也很重要。例如,邊緣對于圖像的視覺特性至關重要。對于小到中等水平的高斯噪聲,中值濾波器在去除噪聲方面明顯優于高斯濾波,同時為給定的固定窗口大小保留邊緣。然而,對于高水平的噪聲,它的性能并不比高斯模糊好多少,而對于散斑噪聲和椒鹽噪聲(脈沖噪聲),它特別有效。正因為如此,中值濾波在數字圖像處理中得到了非常廣泛的應用。
OpenCV實現
使用OpenCV進行算法驗證和Matlab進行算法驗證其實思路差不多,先驗證算法的效果再驗證算法的正確性,這一步使用OpenCV和MatLab一樣,我們就使用OpenCV進行驗證,這一步就不實際展開了,代碼如下:
//-----------------------------------【頭文件包含部分】--------------------------------------- //描述:包含程序所依賴的頭文件 //---------------------------------------------------------------------------------------------- #include"opencv2/core/core.hpp" #include"opencv2/highgui/highgui.hpp" #include"opencv2/imgproc/imgproc.hpp" //-----------------------------------【命名空間聲明部分】--------------------------------------- //描述:包含程序所使用的命名空間 //----------------------------------------------------------------------------------------------- usingnamespacecv; //-----------------------------------【main()函數】-------------------------------------------- //描述:控制臺應用程序的入口函數,我們的程序從這里開始 //----------------------------------------------------------------------------------------------- intmain() { //載入原圖 Matimage=imread("1.jpg"); //創建窗口 namedWindow("中值濾波【原圖】"); namedWindow("中值濾波【效果圖】"); //顯示原圖 imshow("中值濾波【原圖】",image); //進行中值濾波操作 Matout; medianBlur(image,out,7); //顯示效果圖 imshow("中值濾波【效果圖】",out); waitKey(0); }
HLS加速和仿真
上面就完成了算法的介紹和論證,其中論證過程并沒有詳細介紹,因為本篇文章重點不是這個,后續在介紹這個算法的時候再詳細展開。
HLS工程搭建
新建工程
如下:
第二頁和第三頁不用管,后續再進行設置
最后一頁,需要設置兩個地方,注意一個地方
其中,Uncertainty參數含義見下,默認不設置即可。
在UG1399的set_clock_uncertainty章節有詳細介紹。
【uncertainty】:以 ns 為單位指定,表示時鐘周期中有多少被用作余量。不確定性也可以指定為時鐘周期的百分比。默認的不確定性是時鐘周期的 27%。
也可以使用函數:
set_clock_uncertainty
【uncertainty】:以 ns 為單位指定,表示時鐘周期中有多少被用作余量。不確定性也可以指定為時鐘周期的百分比。默認的不確定性是時鐘周期的 27%。
【clock_list】:應用不確定性的時鐘列表。如果未提供,它將應用于所有時鐘。
添加源文件
新建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?"?<
設置仿真庫
在下面界面設置相關參數:
在這個界面設置
1、Top Function
設置主函數的,點擊Browse進行選擇即可。
2、設置設計文件Edit cflags,添加調用的設計頭文件
添加
-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、設置設計文件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
接下來設置仿真庫路徑
1、設置仿真文件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、設置仿真文件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、設置Linker Flags,調用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、 設置Input Arguments,這個是調用仿真圖片,可以后續再設置
H:/FILE/HLS/meanblur/src/128x128.png
綜合
點擊綜合按鈕即可開始綜合,結果如下:
仿真
點擊仿真按鈕得到下圖仿真結果
下圖從左到右分別為:OpenCV處理的結果、HLS處理的結果以及最后的兩個圖像差(無差別即全黑)。
聯合仿真
點擊聯合仿真按鈕后等待仿真結束,然后點擊下面按鈕查看波形:
導出IP
點擊導出IP按鈕等待導出即可。
總結
今天的例程演示完畢,從建立工程到最后導出IP,基本比較詳細。但是,上面的例程是不能直接應用到視頻里的,原因是上面的接口沒經過改動,需要從AXI轉成AXI-STREAM接口后再再接入到視頻架構中即可,這部分我們后續再詳細說明。
審核編輯:劉清
-
濾波器
+關注
關注
161文章
7876瀏覽量
179066 -
計算機視覺
+關注
關注
8文章
1701瀏覽量
46148 -
OpenCV
+關注
關注
31文章
635瀏覽量
41595 -
HLS
+關注
關注
1文章
130瀏覽量
24217
原文標題:如何用 Vitis HLS 實現 OpenCV 仿真
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
新手求助,HLS實現opencv算法加速的IP在vivado的使用
Vivado HLS實現OpenCV圖像處理的設計流程與分析
FPGA高層次綜合HLS之Vitis HLS知識庫簡析
使用Vitis HLS創建屬于自己的IP相關資料分享
利用Vitis HLS tcl shell一鍵跑通視覺加速例程
![利用<b class='flag-5'>Vitis</b> <b class='flag-5'>HLS</b> tcl shell一鍵跑通視覺加速例程](https://file.elecfans.com/web1/M00/D7/92/o4YBAF_qn3-AcJX6AABl2I7fkuU070.png)
Vitis Vision | 利用Vitis HLS tcl shell 一鍵跑通視覺加速例程
![<b class='flag-5'>Vitis</b> Vision | 利用<b class='flag-5'>Vitis</b> <b class='flag-5'>HLS</b> tcl shell 一鍵跑通視覺加速例程](https://file.elecfans.com/web1/M00/DB/A4/o4YBAGAJ4HuAUy1HAADIz0Q3feg536.png)
Vitis HLS工具簡介及設計流程
Vitis HLS前端現已全面開源
Vitis HLS知識庫總結
理解Vitis HLS默認行為
AMD全新Vitis HLS資源現已推出
![AMD全新<b class='flag-5'>Vitis</b> <b class='flag-5'>HLS</b>資源現已推出](https://file1.elecfans.com/web2/M00/82/20/wKgaomREmyqAMDmOAAAdFC8hyjQ866.png)
如何在Vitis HLS GUI中使用庫函數?
![如何在<b class='flag-5'>Vitis</b> <b class='flag-5'>HLS</b> GUI中使用庫函數?](https://file1.elecfans.com/web2/M00/90/A9/wKgZomTcNDaAcqFmAAAt4OHi_oA924.png)
評論