百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

使用 HLS 的 FPGA 的边缘检测

bigegpt 2024-08-10 12:11 4 浏览

使用 HLS 的 FPGA 的边缘检测

利用 HLS 功能创建图像处理解决方案,在FPGA中实现边缘检测 (Sobel)。

本项目中用到的东西



介绍

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 边缘检测的工作原理是检测图像在水平和垂直方向上的梯度变化。为此,将两个卷积滤波器应用于原始图像,然后组合这些卷积滤波器的结果以确定梯度的大小。


执行

如果我们使用传统的 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,内容包括:-

  • HLS::CvtColor - 将根据其配置在颜色和灰度之间转换颜色空间。
  • HLS::Gaussian - 将对图像执行高斯模糊以减少图像中存在的噪声。
  • HLS::Sobel - 根据其配置在垂直或水平方向执行 Sobel 卷积。将需要在我们的 IP 核中使用两个实现。
  • HLS::AddWeighted - 允许使用来自垂直和水平 Sobel 算子的结果来执行结果幅度计算。上面这些不是我们将使用的所有 HLS 函数,我们还需要使用其他函数。

互联

在FPGA内部移动图像数据的最佳方法是使用 AXI 流。AXI允许创建高性能图像处理路径,其中元素可以根据需要轻松添加或创建。

Vivado IP 库中存在多个 IP 模块,可实现视频输入和输出与 AXI 流之间的转换,以及其他图像处理功能,例如混合器(mixers)和色彩空间转换器( color space converters)。

因此,我们希望 Sobel IP 核能够接受 AXI Stream 输入并以相同的 AXI Stream 格式生成输出。为此,我们使用以下函数允许在 AXI 流和 HLS 函数使用的 HLS::Mat 格式之间进行转换。

  • HLS::AXIvideo2Mat - 从 AXI 流转换为用于 AXI 流输入的 HLS::Mat 格式。
  • HLS::Mat2AXIvideo - 从 HLS::Mat 格式转换为 AXI Stream 格式,用于 AXI Stream 输出。

C 综合和优化

与 Verilog 和 VHDL 设计不同,我们用来描述设计的高级语言是不可控的。这意味着当 HLS 工具将 C 转换为 Verilog 或 VHDL 时,它必须经过多个阶段才能创建输出我们需要的 RTL。

  • 调度Scheduling - 确定操作及其发生的顺序。
  • 绑定Binding - 将操作分配给设备内可用的逻辑资源。
  • 控制逻辑提取Control Logic Extraction - 提取控制逻辑并创建控制结构,例如状态机的行为。


由于 HLS 工具在运行综合时必须在性能和逻辑资源之间进行权衡,因此在实现过程中将遵循许多规则。这些可能会影响生成的 IP 核的性能,例如流水操作(HLS 编码中的常见结构)。

当然,我们可能希望更改 HLS 工具在 C 综合期间做出的决定以获得更好的性能,可以 C 中使用 #pragmas 来做到这一点。

对于本次设计,我们将使用 Dataflow pragma 来确保我们可以达到最高的帧速率。


为了能够使用此编译指示,我们需要确保 HLS 综合工具并行执行两个 Sobel 操作。如果我们先执行一个 Sobel 操作,然后按顺序执行另一个操作,这将无法应用此优化。公众号:OpenFPGA

因此,我们需要将高斯模糊的结果分成两条平行路径,然后在 AddWeighted 阶段重新组合。为此,我们使用下面函数:

  • HLS::Duplicate - 这将输入图像复制到两个单独的输出图像中,我们可以并行处理这些图像。

编写代码

了解所有这些之后,我们就可以编写用于 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 时,我们可以看到测试输入图像的结果如下。



有了仿真结果,我们就可以导出内核并将其添加到 Vivado 硬件设计中。

但是,在我们执行此操作之前,还需要检查分析、在 Vivado HLS 中查看并确认两个 Sobel 函数并行运行的结果。


使用 Vivado HLS 中的导出 RTL 选项导出 IP 核

硬件实现

导出核心后,您将在/solutionX/imp 目录下找到一个 zip 文件。该目录包含刚刚新创建的 Sobel IP ,将核添加到 Vivado IP库中。

然后 Vivado IP 中,可以看到相关IP,如下:

搭建BD,如下:

将IP集成到图像处理链中(注意图中的HLS符号)

项目源码

?

https://github.com/ATaylorCEngFIET/Hackster



相关推荐

5分钟搭建公网https网页文件服务器,免费权威TLS证书

请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习前言本文主要讲解如何快速搭建一个https网页文件服务器,并免费申请权威机构颁发的tls证...

nginx负载均衡配置(nginx负载均衡配置两个程序副本)

Nginx是什么没有听过Nginx?那么一定听过它的“同行”Apache吧!Nginx同Apache一样都是一种WEB服务器。基于REST架构风格,以统一资源描述符(UniformResources...

19《Nginx 入门教程》Nginx综合实践

今天我们将基于Nginx完成两个比较有用的场景,但是用到的Nginx的配置非常简单。内部Yum源搭建内部Pip源搭建1.实验环境ceph1centos7.6内网ip:172.16....

Nginx性能调优与优化指南(nginx优化配置大全)

Nginx性能调优需要结合服务器硬件资源、业务场景和负载特征进行针对性优化。以下是一些关键优化方向和具体配置示例:一、Nginx配置优化1.进程与连接数优化nginxworker_process...

C++后端开发必须彻底搞懂Nginx,从原理到实战(高级篇)

本文为Nginx实操高级篇。通过配置Nginx配置文件,实现正向代理、反向代理、负载均衡、Nginx缓存、动静分离和高可用Nginx6种功能,并对Nginx的原理作进一步的解析。当需...

【Nginx】史上最全的Nginx配置详解

Nginx服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里,http块又包括http全局块和server块。Nginx是非常重要的负载均衡中间件,被广泛应用于大型...

【Nginx】Nginx 4种常见配置实例(nginx基本配置与参数说明)

本文主要介绍nginx4种常见的配置实例。Nginx实现反向代理;Nginx实现负载均衡;Nginx实现动静分离;Nginx实现高可用集群;Nginx4种常见配置实例如下:一、Nginx反向代理配...

使用nginx+allure管理自动化测试报告

allure在自动化测试中经常用来生成漂亮的报告,但是网上及官网上给出的例子都仅仅是针对单个测试用例文件的形式介绍的,实际使用中,自动化测试往往需要包含不止一个产品或项目,本文介绍如何使用nginx+...

nginx配置文件详解(nginx配置文件详解高清版)

Nginx是一个强大的免费开源的HTTP服务器和反向代理服务器。在Web开发项目中,nginx常用作为静态文件服务器处理静态文件,并负责将动态请求转发至应用服务器(如Django,Flask,et...

SpringCloud Eureka-服务注册与发现

1.Eureka介绍1.1学习Eureka前的说明目前主流的服务注册&发现的组件是Nacos,但是Eureka作为老牌经典的服务注册&发现技术还是有必要学习一下,原因:(1)一些早期的分布式微服...

微服务 Spring Cloud 实战 Eureka+Gateway+Feign+Hystrix

前言我所在项目组刚接到一个微服务改造需求,技术选型为SpringCloud,具体需求是把部分项目使用SpringCloud技术进行重构。本篇文章中介绍了Eureka、Gateway、Fe...

深度剖析 Spring Cloud Eureka 底层实现原理

你作为一名互联网大厂后端技术开发人员,在构建分布式系统时,是不是常常为服务的注册与发现而头疼?你是否好奇,像SpringCloudEureka这样被广泛使用的组件,它的底层实现原理到底是怎样的...

热爱生活,喜欢折腾。(很热爱生活)

原文是stackoverflow的一则高票回答,原文链接可能之前也有人翻译过,但是刚好自己也有疑惑,所以搬运一下,个人水平有限所以可能翻译存在误差,欢迎指正(如侵删)。尽管classmethod和st...

GDB调试的高级技巧(详细描述gdb调试程序的全过程)

GDB是我们平时调试c/c++程序的利器,查起复杂的bug问题,比打印大法要好得多,但是也不得不说,gdb在默认情况下用起来并不是很好用,最近学习到几个高级点的技巧,分享下:一美化打印先上个例子...

Arduino 实例(二十三)Arduino 给Python 编译器发送信息

1首先Python需要安装Pyserial库,在命令提示符中输入pipintallpyserial若是遇到提示‘pip‘不是内部或外部命令,也不是可运行的程序或批处理文件,则需要设置环境变...