本方案利用 HLS 功能創(chuàng)建圖像處理解決方案,在可編程邏輯中實現(xiàn)邊緣檢測 (Sobel)。
介紹
高級綜合 (HLS) 允許我們在開發(fā) FPGA 應(yīng)用程序時在更高的抽象級別上工作,如果是商業(yè)項目,有望節(jié)省時間并降低非經(jīng)常性成本。
HLS 的一個重要應(yīng)用是圖像或信號處理,我們可能已經(jīng)用 C 或 C++ 創(chuàng)建了一個高級模型,或者我們希望使用開源行業(yè)標(biāo)準(zhǔn)框架,例如 OpenCV。
在本項目中,我們將研究如何使用 HLS 構(gòu)建 Sobel 邊緣檢測 IP 核,然后將其包含在我們選擇的 Xilinx FPGA 中。
所選器件可以是傳統(tǒng)的 FPGA,例如 Spartan Seven 或 Artix,或者也可以在異構(gòu) SoC 的可編程邏輯中實現(xiàn),例如 Zynq 7000 或 Zynq MPSoC。
理論
在我們進入應(yīng)用程序之前,我應(yīng)該先簡單介紹一下 Sobel 算法的工作原理。Sobel 算法通過識別圖像中的邊緣并強調(diào)它們以便可以輕松識別它們來發(fā)揮作用。通常這將創(chuàng)建一個灰度圖像,其中邊緣被識別為灰色/白色陰影。
Sobel 邊緣檢測的工作原理是檢測圖像在水平和垂直方向上的梯度變化。為此,將兩個卷積濾波器應(yīng)用于原始圖像,然后組合這些卷積濾波器的結(jié)果以確定梯度的大小。
執(zhí)行
如果我們使用傳統(tǒng)的 VHDL / Verilog RTL 方法在 FPGA 中實現(xiàn)這一點,那么開發(fā)時間將不會很短。因為我們需要為卷積創(chuàng)建行緩沖區(qū),然后實現(xiàn)幅度計算。我們還需要創(chuàng)建一個測試平臺,以確保我們的代碼在進行實施之前按預(yù)期工作。
幸運的是,當(dāng)我們使用 HLS 時,我們真的可以跳過很多繁重的工作,讓 Vivado HLS 實現(xiàn)較低級別的 Verilog/VHDL RTL 實現(xiàn)。
為了在這個更高的抽象級別上工作,我們將使用 Vivado HLS 及其 HLS_OpenCV 和 HLS_Video 庫。
第一個庫 HLS_OpenCV 允許我們使用非常流行的 OpenCV 框架。而 HLS 視頻庫提供了許多可以加速為可編程邏輯的圖像處理功能。
而是有益的HLS視頻庫包括我們需要創(chuàng)建一個索貝爾IP核心,內(nèi)容包括:-
HLS::CvtColor - 這將根據(jù)其配置在顏色和灰度之間轉(zhuǎn)換顏色方案。
HLS::Gaussian - 這將對圖像執(zhí)行高斯模糊以減少圖像中存在的噪聲。
HLS::Sobel - 根據(jù)其配置在垂直或水平方向執(zhí)行 Sobel 卷積。我們將需要在我們的 IP 核中使用這兩個實現(xiàn)。
HLS::AddWeighted - 這允許我們使用來自垂直和水平 Sobel 算子的結(jié)果來執(zhí)行結(jié)果幅度計算。
這些不是我們將使用的所有 HLS 函數(shù),因為我們需要使用其他函數(shù)。我們需要包含這些附加功能,以便更輕松地使用 HLS 優(yōu)化和與 Vivado 設(shè)計的接口。
界面
在可編程邏輯內(nèi)部移動圖像數(shù)據(jù)的最佳方法是使用 AXI 流。
這允許創(chuàng)建高性能圖像處理路徑,其中元素可以根據(jù)需要輕松添加或創(chuàng)建。
Vivado IP 庫中存在多個 IP 模塊,可實現(xiàn)視頻輸入和輸出與 AXI 流之間的轉(zhuǎn)換。以及其他圖像處理功能,例如混合器和色彩空間轉(zhuǎn)換器。
因此,我們希望我們的 Sobel IP 核能夠接受 AXI Stream 輸入并以相同的 AXI Stream 格式生成其輸出。為此,我們使用以下函數(shù)允許在 AXI 流和 HLS 函數(shù)使用的 HLS::Mat 格式之間進行轉(zhuǎn)換。
HLS::AXIvideo2Mat - 從 AXI 流轉(zhuǎn)換為用于 AXI 流輸入的 HLS::Mat 格式。
HLS::Mat2AXIvideo - 從 HLS::Mat 格式轉(zhuǎn)換為 AXI Stream 格式,用于 AXI Stream 輸出。
C 綜合和優(yōu)化
與 Verilog 和 VHDL 設(shè)計不同,我們用來描述設(shè)計的高級語言是不定時的。這意味著當(dāng) HLS 工具將 C 轉(zhuǎn)換為 Verilog 或 VHDL 時,它必須經(jīng)過多個階段才能創(chuàng)建輸出 RTL
調(diào)度 - 確定操作及其發(fā)生的順序。
綁定 - 將操作分配給設(shè)備內(nèi)可用的邏輯資源。
控制邏輯提取 - 提取控制邏輯并創(chuàng)建控制結(jié)構(gòu),例如狀態(tài)機以控制模塊的行為。
由于 HLS 工具在運行綜合時必須在性能和邏輯資源之間進行權(quán)衡,因此在實現(xiàn)過程中將遵循許多規(guī)則。這些可能會影響生成的 IP 核的性能,例如循環(huán)(HLS 編碼中的常見結(jié)構(gòu))保持滾動。
當(dāng)然,我們可能希望更改 HLS 工具在 C 綜合期間做出的決定以獲得更好的性能。我們可以在我們的 C 中使用 #pragmas 來做到這一點,我們可以使用幾個。
對于這個實現(xiàn),我們將使用 Dataflow pragma 來確保我們可以達到最高的幀速率。
為了能夠使用此編譯指示,我們需要確保 HLS 綜合工具并行執(zhí)行兩個 Sobel 操作。這將允許我們在 HLS C 綜合期間指定數(shù)據(jù)流優(yōu)化,從而優(yōu)化通過函數(shù)的數(shù)據(jù)流。實際上,數(shù)據(jù)流優(yōu)化是粗粒度流水線。
如果我們先執(zhí)行一個 Sobel 操作,然后按順序執(zhí)行另一個操作,我們將無法應(yīng)用此優(yōu)化。
因此,我們需要將高斯模糊的結(jié)果分成兩條平行路徑,然后在 AddWeighted 階段重新組合。為此,我們使用函數(shù)
HLS::Duplicate - 這將輸入圖像復(fù)制到兩個單獨的輸出圖像中,我們可以并行處理這些圖像。
軟件
了解所有這些之后,我們就可以編寫用于 Sobel IP 核的代碼
#include "cvt_colour.hpp"
void image_filter(AXI_STREAM& INPUT_STREAM, AXI_STREAM& OUTPUT_STREAM)//, int rows, int cols)
{
#pragma HLS INTERFACE axis port=INPUT_STREAM
#pragma HLS INTERFACE axis port=OUTPUT_STREAM
RGB_IMAGE ?img_0(MAX_HEIGHT, MAX_WIDTH);
GRAY_IMAGE img_1(MAX_HEIGHT, MAX_WIDTH);
GRAY_IMAGE ?img_2(MAX_HEIGHT, MAX_WIDTH);
GRAY_IMAGE ?img_2a(MAX_HEIGHT, MAX_WIDTH);
GRAY_IMAGE ?img_2b(MAX_HEIGHT, MAX_WIDTH);
GRAY_IMAGE ?img_3(MAX_HEIGHT, MAX_WIDTH);
GRAY_IMAGE ?img_4(MAX_HEIGHT, MAX_WIDTH);
GRAY_IMAGE ?img_5(MAX_HEIGHT, MAX_WIDTH);
RGB_IMAGE ?img_6(MAX_HEIGHT, MAX_WIDTH);
;
#pragma HLS dataflow
hls::AXIvideo2Mat(INPUT_STREAM, img_0);
hls::CvtColor
hls::GaussianBlur<3,3>(img_1,img_2);
hls::Duplicate(img_2,img_2a,img_2b);
hls::Sobel<1,0,3>(img_2a, img_3);
hls::Sobel<0,1,3>(img_2b, img_4);
hls::AddWeighted(img_4,0.5,img_3,0.5,0.0,img_5);
hls::CvtColor
hls::Mat2AXIvideo(img_6, OUTPUT_STREAM);
}
#include ?"hls_video.h"
#include
#define MAX_WIDTH ?1280
#define MAX_HEIGHT 720
typedef hls::stream
typedef hls::Mat
typedef hls::Mat
void image_filter(AXI_STREAM& INPUT_STREAM, AXI_STREAM& OUTPUT_STREAM);//int rows, int cols);
當(dāng)然,我們希望能夠同時運行 C Simulation 和 Co Simulation,因此我們需要一個可以用來測試算法的測試臺。
當(dāng)我們運行 C Simulation 時,我們可以看到測試輸入圖像的結(jié)果如下。
有了 C 仿真和 Co 仿真結(jié)果,我們可以導(dǎo)出內(nèi)核并將其添加到 Vivado 硬件設(shè)計中。
但是,在我們執(zhí)行此操作之前,您可能需要檢查分析、在 Vivado HLS 中查看并確認(rèn)兩個 Sobel 函數(shù)并行運行。
我們可以使用 Vivado HLS 中的導(dǎo)出 RTL 選項導(dǎo)出 IP 核,如果我們希望我們可以進一步配置 IP 核參數(shù)
實現(xiàn)核心
導(dǎo)出核心后,您將在
該文件可以添加到我們的 Vivado IP 存儲庫中,然后包含在 Vivado 框圖中
有了這一切集成,您可以構(gòu)建應(yīng)用程序和目標(biāo)到您選擇的開發(fā)板。
編輯:黃飛
?
評論
查看更多