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

    浏览量

    7904

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

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

收藏 人收藏

    评论

    相关推荐

    助力AIoT应用:米尔FPGA开发板实现Tiny YOLO V4

    受限的设备运行,尤其低功耗、实时检测的边缘计算设备中表现出色。相比传统 GPU,FPGA 能在小面积和低功耗下实现类似的推理性能,非常契合 AIoT 应用。像米尔 ZU3EG 这样的 FPGA
    发表于 12-06 17:18

    DSP实现DDR2 PCB布局布线

    电子发烧友网站提供《DSP实现DDR2 PCB布局布线.pdf》资料免费下载
    发表于 10-15 09:16 0次下载
    <b class='flag-5'>在</b>DSP<b class='flag-5'>上</b><b class='flag-5'>实现</b>DDR2 PCB布局布线

    基于 DSP5509 进行数字图像处理中 Sobel 算子边缘检测的硬件连接电路图

    以下是基于 DSP5509 进行数字图像处理中 Sobel 算子边缘检测的硬件设计方案: 一、总体架构 图像采集:使用合适的图像传感器,如 CMOS 传感器,通过相应的接口(如 SPI、I2C 等
    发表于 09-25 15:25

    优化 FPGA HLS 设计

    减少错误并更容易调试。然而,经常出现的问题是性能权衡。高度复杂的 FPGA 设计中实现高性能需要手动优化 RTL 代码,而这对于HLS开发环境生成的 RTL 代码来说是不可能的。然而,存在一些解决方案
    发表于 08-16 19:56

    摩尔线程携手智源研究院完成基于Triton的大模型算子库适配

    里,即成功完成了近60个算子的功能验证,精度符合交付标准,并实现对Bert-large模型的全面支持。FlagGems算子摩尔线程MUSA架构
    的头像 发表于 08-02 11:06 852次阅读

    多FPGA集群实现高级并行编程

    今天我们看的这篇论文介绍了多FPGA集群实现高级并行编程的研究,其主要目标是为非FPGA专家提供一个成熟且易于使用的环境,以便在多个并行运行的设备扩展高性能计算(HPC)应用。
    的头像 发表于 07-24 14:54 1236次阅读

    一种HLS中插入HDL代码的方式

    很多人都比较反感用C/C++开发(HLS)FPGA,大家第一拒绝的理由就是耗费资源太多。但是HLS也有自己的优点,除了快速构建算法外,还有一个就是接口的生成,尤其对于AXI类接口,按照标准语法就可以很方便地生成相关接口。
    的头像 发表于 07-16 18:01 727次阅读
    一种<b class='flag-5'>在</b><b class='flag-5'>HLS</b>中插入HDL代码的方式

    园区智慧用电管理系统的设计与应用

    程瑜 安科瑞电气股份有限公司 上海嘉定 201801 摘要:为解决目前园区用电管理紊乱、数据采集不便、运维智能化水平低等问题。研究搭建出园区智慧用电管理系统。本系统由网关、PC、手机、智能物联网设备等硬件组成。利用RS-485总线通信、数据库管理、GPRS无线传输等技术将智能电表、集中器、数据采集终端及云服务器连接起来进行信息交换与通讯,建立智慧用电管理系统。该系统能够保证用电管理的高效性和性,显著提高了物业服务的工作效率和智能
    的头像 发表于 07-10 09:15 509次阅读
    <b class='flag-5'>浅</b><b class='flag-5'>述</b>园区智慧用电管理系统的设计与应用

    ESP32-C3休眠时中断一直触发是怎么回事?

    目前在用ESP32-C3,用BLE 低功耗后 要启用自动休眠,开启了休眠之后GPIO 中断一直不停触发,不管设置里面内部拉 还是外部47K
    发表于 06-21 14:53

    Arm发布全新终端计算子系统,加速AI体验与产品上市

    全球领先的半导体知识产权(IP)提供商Arm控股有限公司(纳斯达克股票代码:ARM)今日正式推出全新的Arm终端计算子系统(CSS),以推动人工智能(AI)体验的前沿发展,并助力芯片合作伙伴构建基于Arm架构的解决方案时实现
    的头像 发表于 05-30 14:23 559次阅读

    基于FPGA的实时边缘检测系统设计,Sobel图像边缘检测,FPGA图像处理

    60 为阈值得到图8(a)和(b)。 通过对比可以看出,使用 FPGA 进行Sobel边缘检测能够实现与 MATLAB 相近的检测效果,验证了算法的可行性。相对于 MATLAB,FPGA检测同样
    发表于 05-24 07:45

    如何优化HLS仿真脚本运行时间

    需求:由于自己目前一个 HLS 仿真脚本需要运行 1个多小时,先打算通过打印时间戳的方式找出最耗时的部分,然后想办法优化。
    的头像 发表于 02-23 09:29 676次阅读

    AMD-Xilinx的Vitis-HLS编译指示小结

    流水线指令 pragma HLS pipeline 通过流水线提高性能是计算机架构设计的8个伟大思想之一,不管是硬件设计还是软件设计,流水线设计(pipeline)都能够用更多的资源来实现高速
    发表于 12-31 21:20

    【机器视觉】3D抓取—基于模板匹配

    以彩色梯度为例,先进行7*7的高斯模糊,然后利用Sobel算子计算梯度,继而在每个像素点求解出了梯度方向以及幅值,只有超过一定阈值的梯度才会被保留;
    发表于 12-25 14:21 825次阅读
    【机器视觉】3D抓取—基于模板匹配

    OpenCV边缘检测算子Laplace、LoG详解

    一阶导数算子(例如 Sobel 算子)通过对图像求导来确定图像的边缘,数值绝对值较高的点对应了图像的边缘。如果继续求二阶导,原先数值绝对值较高的点对应了过零点。因此,也可以通过找到二阶导数的过零点来检测边缘。
    的头像 发表于 12-21 16:34 2197次阅读
    OpenCV边缘检测<b class='flag-5'>算子</b>Laplace、LoG详解