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