0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

浅述Sobel算子在HLS上的实现教程

FPGA之家 来源:FPGA科技室 作者:FPGA科技室 2021-07-23 14:53 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

Sobel 原理介绍

索贝尔算子(Sobel operator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量Sobel 卷积因子为:

31c07d38-e10c-11eb-9e57-12bb97331649.png

该算子包含两组 3x3 的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以 A 代表原始图像,Gx 及 Gy 分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:

31c8e838-e10c-11eb-9e57-12bb97331649.png

具体计算如下:

Gx = (-1)*f(x-1, y-1) + 0*f(x,y-1) + 1*f(x+1,y-1)

+(-2)*f(x-1,y) + 0*f(x,y)+2*f(x+1,y)

+(-1)*f(x-1,y+1) + 0*f(x,y+1) + 1*f(x+1,y+1)

= [f(x+1,y-1)+2*f(x+1,y)+f(x+1,y+1)]-[f(x-1,y-1)+2*f(x-1,y)+f(x-1,y+1)]

Gy =1* f(x-1, y-1) + 2*f(x,y-1)+ 1*f(x+1,y-1)

+0*f(x-1,y) 0*f(x,y) + 0*f(x+1,y)

+(-1)*f(x-1,y+1) + (-2)*f(x,y+1) + (-1)*f(x+1, y+1)

= [f(x-1,y-1)+2f(x,y-1)+f(x+1,y-1)]-[f(x-1, y+1) + 2*f(x,y+1)+f(x+1,y+1)]

其中 f(a,b), 表示图像(a,b)点的灰度值;

图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:

31d47bf8-e10c-11eb-9e57-12bb97331649.png

通常,为了提高效率 使用不开平方的近似值

31de8f8a-e10c-11eb-9e57-12bb97331649.png

Sobel 算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。

Sobel 算子在 HLS 上的实现

工程创建

Step1:打开 Vivado HLS 开发工具,单击 Creat New Project 创建一个新工程,设置好工程路径和工程名,一直点击 Next 按照默认设置

Step2:出现如下图所示界面,时钟周期 Clock Period 按照默认 10ns,Uncertaintly 和 Solution Name 均按照默认设置,点击红色箭头部分选择芯片类型,然后点击 OK。

点击 Finish,出现如下界面

32508d6a-e10c-11eb-9e57-12bb97331649.png

Step4:右单击 Source 选项,选择 New File,创建一个名为 Top.cpp 的文件。(一定要加cpp后缀)

Step5:打开刚刚新建的cpp文件,进入编辑状态,输入以下代码

325a9c06-e10c-11eb-9e57-12bb97331649.png

Top.cpp代码

#include “top.h”

void hls_sobel(AXI_STREAM& INPUT_STREAM, AXI_STREAM&

OUTPUT_STREAM, int rows, int cols)

{

//Create AXI streaming interfaces for the core

#pragma HLS INTERFACE axis port=INPUT_STREAM

#pragma HLS INTERFACE axis port=OUTPUT_STREAM

#pragma HLS RESOURCE core=AXI_SLAVE variable=rows metadata=“- bus_bundle CONTROL_BUS”

#pragma HLS RESOURCE core=AXI_SLAVE variable=cols metadata=“-bus_bundle CONTROL_BUS”

#pragma HLS RESOURCE core=AXI_SLAVE variable=return metadata=“-bus_bundle CONTROL_BUS”

#pragma HLS INTERFACE ap_stable port=rows

#pragma HLS INTERFACE ap_stable port=cols

RGB_IMAGE img_0(rows, cols);

RGB_IMAGE img_1(rows, cols);

RGB_IMAGE img_2(rows, cols);

RGB_IMAGE img_3(rows, cols);

RGB_IMAGE img_4(rows, cols);

RGB_IMAGE img_5(rows, cols);

RGB_PIXEL pix(50, 50, 50);

#pragma HLS dataflow

hls::AXIvideo2Mat(INPUT_STREAM, img_0);

hls::Sobel《1,0,3》(img_0, img_1);

hls::SubS(img_1, pix, img_2);

hls::Scale(img_2, img_3, 2, 0);

hls::Erode(img_3, img_4);

hls::Dilate(img_4, img_5);

hls::Mat2AXIvideo(img_5, OUTPUT_STREAM)

}

Step6:再在 Source 中添加一个名为 Top.h 的库函数,并添加如下程序:

32656f00-e10c-11eb-9e57-12bb97331649.png

Top.h代码

#ifndef TOP_H

#define TOP_H

#include “hls_video.h”

// maximum image size

#define MAX_WIDTH 512

#define MAX_HEIGHT 512

// I/O Image Settings

#define INPUT_IMAGE “lena.jpg”

#define OUTPUT_IMAGE “result.jpg”

#define OUTPUT_IMAGE_GOLDEN “result_golden.jpg”

// typedef video library core structures

typedef hls::stream《ap_axiu《32,1,1,1 style=“font-size: inherit;color: inherit;line-height: inherit;”》》 AXI_STREAM;

typedef hls::Scalar《3, unsigned char》 RGB_PIXEL;

typedef hls::MatRGB_IMAGE;

// top level function for HW synthesis

void hls_sobel(AXI_STREAM& src_axi, AXI_STREAM& dst_axi, int rows, int cols);

#endif《/ap_axiu《32,1,1,1》

Step7:在 Test Bench 中,用同样的方法添加一个名为 Test.cpp 的测试程序。添加如下代码:

326e7546-e10c-11eb-9e57-12bb97331649.png

Test.cpp代码

#include “top.h”

#include “opencv_top.h”

using namespace std;

using namespace cv;

int main (int argc, char** argv)

{

//获取图像数据

IplImage* src = cvLoadImage(INPUT_IMAGE);

IplImage* dst = cvCreateImage(cvGetSize(src), src-》depth, src-》nChannels);

//使用HLS库进行处理

AXI_STREAM src_axi, dst_axi;

IplImage2AXIvideo(src, src_axi);

hls_sobel(src_axi, dst_axi, src-》height, src-》width);

AXIvideo2IplImage(dst_axi, dst);

cvSaveImage(OUTPUT_IMAGE,dst);

cvShowImage(“hls_dst”, dst);

//使用OPENCV库进行处理

opencv_image_filter(src, dst);

cvShowImage(“cv_dst”, dst);

cvSaveImage(OUTPUT_IMAGE_GOLDEN,dst);

waitKey(0);

//释放内存

cvReleaseImage(&src);

cvReleaseImage(&dst);

}

Step8:用同样的方法,再在 Test Bench 中创建一个 opencv_top.cpp 和 opencv_top.h 文件,添加如下程序:

3278679a-e10c-11eb-9e57-12bb97331649.png

Opencv_top.cpp代码

#include “opencv_top.h”

#include “top.h”

void opencv_image_filter(IplImage* src, IplImage* dst)

{

IplImage* tmp = cvCreateImage(cvGetSize(src), src-》depth, src-》nChannels);

cvCopy(src, tmp);

cv::Mat)tmp, (cv::Mat)dst, -1, 1, 0);

cvSubS(dst, cvScalar(50,50,50), tmp);

cvScale(tmp, dst, 2, 0);

cvErode(dst, tmp);

cvDilate(tmp, dst);

cvReleaseImage(&tmp);

}

void sw_image_filter(IplImage* src, IplImage* dst)

{

AXI_STREAM src_axi, dst_axi;

IplImage2AXIvideo(src, src_axi);

hls_sobel(src_axi, dst_axi, src-》height, src-》width);

AXIvideo2IplImage(dst_axi, dst);

}

opencv_top.h代码

#ifndef OPENCV_TOP_H___ #define ___OPENCV_TOP_H

#include “hls_opencv.h”

void opencv_image_filter(IplImage* src, IplImage* dst);

void sw_image_filter(IplImage* src, IplImage* dst);

#endif

Step7:在 Test Bench 中添加一张名为 lena.jpg的测试图片

接下来对工程进行编译和仿真

Step1:单击 Project-Project settings 或直接单击快捷按钮。

329dac1c-e10c-11eb-9e57-12bb97331649.png

Step2:选择 Synthesis 选项,然后点击 Browse.。指定一个顶层函数,选定 hls_sobel 为顶层函数,

单击 开始综合

32b39afe-e10c-11eb-9e57-12bb97331649.png

在协议类型里面我们可以看到我们主要使用了三种协议,分别是 axis、ap_stable 和 ap_ctrl_hs 三种,这些协议的详细解释我们均可以在官方手册 ug902 中找到,其中 ap_ctrl_hs 的时序操作如下图所示,说简单点就是复位完成等待 ap_start 信号开始进行操作

综合完毕,我们对代码进行仿真测试,单击 开始仿真

33ed078e-e10c-11eb-9e57-12bb97331649.png

仿真结果如下,与通过 OPENCV 实现的 Sobel 检测结果基本一致。

33f6f532-e10c-11eb-9e57-12bb97331649.png

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • sobel
    +关注

    关注

    0

    文章

    12

    浏览量

    8244

原文标题:Sobel 算子在 HLS 上的实现

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Triton-RISCV 完成 RISC-V 原生编译适配,SG2044 平台验证 AI 算子 RVV 加速性能

    中国科学院软件研究所智能软件研究中心与如意RISC-V软件生态的持续推动下,Triton-RISCV项目正式开源。该项目基于主流AI算子编译框架Triton,首次实现RISC-V
    的头像 发表于 05-09 17:03 1392次阅读
    Triton-RISCV 完成 RISC-V 原生编译适配,SG2044 平台验证 AI <b class='flag-5'>算子</b> RVV 加速性能

    摩尔线程携手上海AI实验室Day-0适配DeepSeek-V4核心算子

    MTT S5000 完成了核心算子的Day-0适配。目前算子通过率已超80%,真正实现了模型发布与国产算力适配的同步落地。这一成果不仅为开发者提供了无缝部署体验,更彰显了 Kern
    的头像 发表于 04-30 16:24 2102次阅读

    一文掌握瑞芯微RK系列NPU算子支持全景:覆盖6大平台,新增硬件加速算子,嵌入式AI开发不踩坑

    嵌入式 AI 领域,瑞芯微(Rockchip)RK 系列 NPU 凭借低功耗、高兼容性的特性,广泛应用于智能监控、边缘计算、物联网设备等场景。近期发布的《RKNN Compiler Support
    的头像 发表于 02-06 16:33 1737次阅读
    一文掌握瑞芯微RK系列NPU<b class='flag-5'>算子</b>支持全景:覆盖6大平台,新增硬件加速<b class='flag-5'>算子</b>,嵌入式AI开发不踩坑

    HLS设计中的BRAM使用优势

    高层次综合(HLS)是一种将高级编程语言(如C、C++或SystemC)转换为硬件描述语言(HDL)的设计方法。FPGA设计中,设计者可以灵活地利用FPGA内部的资源,如块RAM(BRAM)。虽然
    的头像 发表于 01-28 14:36 494次阅读

    通过vivado HLS设计一个FIR低通滤波器

    Vivado HLS是一款强大的高层次综合工具,可将C/C++代码转换为硬件描述语言(HDL),显著提升FPGA开发效率。
    的头像 发表于 01-20 16:19 621次阅读
    通过vivado <b class='flag-5'>HLS</b>设计一个FIR低通滤波器

    如何在TensorFlow Lite Micro中添加自定义操作符(2)

    一篇中,小编给大家抽丝剥茧的介绍了TFLm中实现一个算子所涉及的文件,以及每个文件的具体作用,包括:功能实现
    的头像 发表于 12-26 10:53 1758次阅读

    详解JPEG解码MCU实现挑战

    物联网和嵌入式应用中,图像处理早已不再是高性能处理器的专属任务。越来越多的场景需要在资源受限的微控制器(MCU)实现图像显示,而JPEG (Joint Photographic Experts
    的头像 发表于 12-26 10:29 1617次阅读

    蜂鸟处理器+OV5640摄像头模块开发

    的寄存器配置保存在查找表中,Reg Config模块电后自动将寄存器配置通过I2C接口发送给摄像头;Frame Capture提供摄像头的时钟驱动,并接收其采集的RGB数据,写到FIFO中,FIFO实现
    发表于 10-31 07:59

    如何利用Verilog HDLFPGA实现SRAM的读写测试

    本篇将详细介绍如何利用Verilog HDLFPGA实现SRAM的读写测试。SRAM是一种非易失性存储器,具有高速读取和写入的特点。FPGA中
    的头像 发表于 10-22 17:21 4641次阅读
    如何利用Verilog HDL<b class='flag-5'>在</b>FPGA<b class='flag-5'>上</b><b class='flag-5'>实现</b>SRAM的读写测试

    深入解析面向不同市场的多样化Arm计算子系统

    如果你曾基于 Arm 技术开发过产品,很大机会已经感受到了 Arm 计算子系统 (Arm Compute Subsystems, Arm CSS) 所带来的强劲性能。
    的头像 发表于 09-06 14:09 1175次阅读
    深入解析面向不同市场的多样化Arm计<b class='flag-5'>算子</b>系统

    使用VerilogFPGA实现FOC电机控制系统

    自动驾驶、电动滑板车、无人机甚至工业自动化领域,高性能电机控制是不可或缺的核心技术。而如果你对硬件有足够的热情,你会发现:传统用 MCU 实现 FOC(Field-Oriented Control,磁场定向控制)也能“搬”到 FPGA
    的头像 发表于 08-21 15:27 5734次阅读
    使用Verilog<b class='flag-5'>在</b>FPGA<b class='flag-5'>上</b><b class='flag-5'>实现</b>FOC电机控制系统

    基于FPGA的压缩算法加速实现

    本设计中,计划实现对文件的压缩及解压,同时优化压缩中所涉及的信号处理和计算密集型功能,实现对其的加速处理。本设计的最终目标是证明充分并行化的硬件体系结构 FPGA
    的头像 发表于 07-10 11:09 2690次阅读
    基于FPGA的压缩算法加速<b class='flag-5'>实现</b>

    如何在Unified IDE中创建视觉库HLS组件

    最近我们分享了开发者分享|AMD Vitis HLS 系列 1 - AMD Vivado IP 流程(Vitis 传统 IDE)和开发者分享|AMD Vitis HLS 系列 2:AMD
    的头像 发表于 07-02 10:55 1750次阅读
    如何在Unified IDE中创建视觉库<b class='flag-5'>HLS</b>组件

    使用AMD Vitis Unified IDE创建HLS组件

    这篇文章开发者分享|AMD Vitis HLS 系列 1 - AMD Vivado IP 流程(Vitis 传统 IDE) 的基础撰写,但使用的是 AMD Vitis Unified IDE,而不是之前传统版本的 Vitis
    的头像 发表于 06-20 10:06 2687次阅读
    使用AMD Vitis Unified IDE创建<b class='flag-5'>HLS</b>组件

    如何使用AMD Vitis HLS创建HLS IP

    本文逐步演示了如何使用 AMD Vitis HLS 来创建一个 HLS IP,通过 AXI4 接口从存储器读取数据、执行简单的数学运算,然后将数据写回存储器。接着会在 AMD Vivado Design Suite 设计中使用此 HLS
    的头像 发表于 06-13 09:50 2403次阅读
    如何使用AMD Vitis <b class='flag-5'>HLS</b>创建<b class='flag-5'>HLS</b> IP