利用 HLS 功能创建图像处理解决方案,在FPGA中实现边缘检测 (Sobel)。
<center>FPGA Zybo</center>
Apeman 1080P HD Action Camera
HLS是高层综合(High level Synthesis),是将C或者c++语言编译为FPGA能够读懂和运行的RTL级别的语言。通过HLS这个过程可以显著加快FPGA的设计进程,而不用从底层的FPGA语言编起,如果是商业项目,通过HLS可以节省时间并降低成本。
HLS 的一个重要应用是图像或信号处理,我们可能已经用 C 或 C++ 创建了一个高级模型,或者我们希望使用开源行业标准框架,例如 OpenCV。
在本项目中,我们将研究如何使用 HLS 构建 Sobel 边缘检测 IP 核,然后将其包含在我们选择的 Xilinx FPGA 中。
所选器件可以是传统的 FPGA,例如 Spartan 7 或 Artix 7,或者也可以在异构 SoC 的可编程逻辑中实现,例如 Zynq 7000 或 Zynq MPSoC。
在我们进入应用程序编写之前,应该先简单介绍一下 Sobel 算法的工作原理。Sobel 算法根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。
Sobel 边缘检测的工作原理是检测图像在水平和垂直方向上的梯度变化。为此,将两个卷积滤波器应用于原始图像,然后组合这些卷积滤波器的结果以确定梯度的大小。
Sobel卷积滤波器
如果我们使用传统的 VHDL / Verilog RTL 在 FPGA 中实现这一点,那么开发时间将会很长。因为我们需要为卷积创建行缓冲区,然后实现幅度计算。我们还需要创建一个测试平台,以确保我们的代码在进行实施之前能按预期工作。
幸运的是,当我们使用 HLS 时,我们可以跳过很多繁重的工作,让 Vivado HLS 实现低级别的 Verilog/VHDL RTL 难以实现的是事情。
设计时将使用 Vivado HLS 及其 HLS_OpenCV 和 HLS_Video 库。
第一个库 HLS_OpenCV 允许使用非常流行的 OpenCV 框架。而 HLS_Video提供了许多可以加速为可编程逻辑的图像处理功能。
而HLS_Video库中也包括我们需要使用的Sobel_IP,内容包括:-
在FPGA内部移动图像数据的最佳方法是使用 AXI 流。AXI允许创建高性能图像处理路径,其中元素可以根据需要轻松添加或创建。
Vivado IP 库中存在多个 IP 模块,可实现视频输入和输出与 AXI 流之间的转换,以及其他图像处理功能,例如混合器(mixers)和色彩空间转换器( color space converters)。
因此,我们希望 Sobel IP 核能够接受 AXI Stream 输入并以相同的 AXI Stream 格式生成输出。为此,我们使用以下函数允许在 AXI 流和 HLS 函数使用的 HLS::Mat 格式之间进行转换。
与 Verilog 和 VHDL 设计不同,我们用来描述设计的高级语言是不可控的。这意味着当 HLS 工具将 C 转换为 Verilog 或 VHDL 时,它必须经过多个阶段才能创建输出我们需要的 RTL。
HLS转化成RTL流程
由于 HLS 工具在运行综合时必须在性能和逻辑资源之间进行权衡,因此在实现过程中将遵循许多规则。这些可能会影响生成的 IP 核的性能,例如流水操作(HLS 编码中的常见结构)。
当然,我们可能希望更改 HLS 工具在 C 综合期间做出的决定以获得更好的性能,可以 C 中使用 #pragmas 来做到这一点。
对于本次设计,我们将使用 Dataflow pragma 来确保我们可以达到最高的帧速率。
数据流流水线
为了能够使用此编译指示,我们需要确保 HLS 综合工具并行执行两个 Sobel 操作。如果我们先执行一个 Sobel 操作,然后按顺序执行另一个操作,这将无法应用此优化。公众号:OpenFPGA
因此,我们需要将高斯模糊的结果分成两条平行路径,然后在 AddWeighted 阶段重新组合。为此,我们使用下面函数:
了解所有这些之后,我们就可以编写用于 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_BGR2GRAY>(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<HLS_GRAY2RGB>(img_5, img_6);
hls::Mat2AXIvideo(img_6, OUTPUT_STREAM);
}
#include "hls_video.h"
#include <ap_fixed.h>
#define MAX_WIDTH 1280
#define MAX_HEIGHT 720
typedef hls::stream<ap_axiu<24,1,1,1> > AXI_STREAM;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC1> GRAY_IMAGE;
void image_filter(AXI_STREAM& INPUT_STREAM, AXI_STREAM& OUTPUT_STREAM);//int rows, int cols);
当然,希望能够同时运行 C Simulation 和 Co Simulation,还需要一个可以用来测试算法的测试台。
#include <hls_opencv.h>
#include "cvt_colour.hpp"
#include <iostream>
using namespace std;
int main (int argc, char** argv) {
IplImage* src;
IplImage* dst;
AXI_STREAM src_axi, dst_axi;
src = cvLoadImage("test.bmp");
dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
IplImage2AXIvideo(src, src_axi);
image_filter(src_axi, dst_axi);//src->height,src->width);
AXIvideo2IplImage(dst_axi, dst);
cvSaveImage("op.bmp", dst);
cvReleaseImage(&src);
cvReleaseImage(&dst);
}
当我们运行 C Simulation 时,我们可以看到测试输入图像的结果如下。
用于C和Co仿真的输入测试图像
仿真Sobel的结果
有了仿真结果,我们就可以导出内核并将其添加到 Vivado 硬件设计中。
但是,在我们执行此操作之前,还需要检查分析、在 Vivado HLS 中查看并确认两个 Sobel 函数并行运行的结果。
显示并行Sobel操作的分析视图
使用 Vivado HLS 中的导出 RTL 选项导出 IP 核
导出核心后,您将在/solutionX/imp 目录下找到一个 zip 文件。该目录包含刚刚新创建的 Sobel IP ,将核添加到 Vivado IP库中。
然后 Vivado IP 中,可以看到相关IP,如下:
搭建BD,如下:
将IP集成到图像处理链中(注意图中的HLS符号)
❝https://github.com/ATaylorCEngFIET/Hackster
本项目来源:https://www.hackster.io/adam-taylor/fpga-based-edge-detection-using-hls-192ad2
版权归hackster所有