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

    浏览量

    7825

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

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

收藏 人收藏

    评论

    相关推荐

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

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

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

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

    如何用HLS实现UART呢?

    UART 是一种旧的串行通信机制,但仍在很多平台中使用。它在 HDL 语言中的实现并不棘手,可以被视为本科生的作业。在这里,我将通过这个例子来展示在 HLS实现它是多么容易和有趣。
    的头像 发表于 11-20 09:50 347次阅读
    如何用<b class='flag-5'>HLS</b><b class='flag-5'>实现</b>UART呢?

    如何用HLS实现UART

    UART 是一种旧的串行通信机制,但仍在很多平台中使用。它在 HDL 语言中的实现并不棘手,可以被视为本科生的作业。在这里,我将通过这个例子来展示在 HLS实现它是多么容易和有趣。
    的头像 发表于 11-20 09:48 294次阅读
    如何用<b class='flag-5'>HLS</b><b class='flag-5'>实现</b>UART

    什么是DASH和HLS流?

    -自适应流- HTTP) HLS(HTTP- Live-流) 两种协议的工作方式相似——数据被编码(分割)成块并发送到客户端进行查看。 一、HLS(HTTP直播) HLS(即HTTP Live
    的头像 发表于 10-09 17:16 548次阅读
    什么是DASH和<b class='flag-5'>HLS</b>流?

    迅为RK3568开发板Scharr滤波器算子边缘检测

    。Scharr 算子Sobel 算子的不同点是平滑部分,其中心元素占的权重更重,相当于使用较小标准差的高斯函数,也就是更瘦高的模板。 Scharr
    发表于 10-09 11:03

    HLS中RTL无法导出IP核是为什么?

    请教一下,我HLS里面要将以下程序生成IP核,C Synthesis已经做好了,但是export RTL的时候一直在运行 int sum_single(int A int B
    发表于 09-28 06:03

    迅为iTOP-RK3568开发板Sobel 算子边缘检测

    。在技术,它是一离散性差分算子,用来运算图像亮度函数的梯度之近似值。图像 的任何一点使用此算子,将会产生对应的梯度矢量或是其法矢量。 索贝尔算子
    发表于 09-18 10:27

    图像锐化的Sobel、Laplacian算子基础知识介绍

    Sobel 算子是一种用于边缘检测的离散微分算子,它结合了高斯平滑和微分求导
    的头像 发表于 09-13 09:52 768次阅读
    图像锐化的<b class='flag-5'>Sobel</b>、Laplacian<b class='flag-5'>算子</b>基础知识介绍

    将VIVADO HLS设计移植到CATAPULT HLS平台

    电子发烧友网站提供《将VIVADO HLS设计移植到CATAPULT HLS平台.pdf》资料免费下载
    发表于 09-13 09:12 2次下载
    将VIVADO <b class='flag-5'>HLS</b>设计移植到CATAPULT <b class='flag-5'>HLS</b>平台

    嵌入式HLS 案例开发步骤分享——基于Zynq-7010/20工业开发板(4)

    sobel_demo.h 中已定义,分辨率均为 1920*1080 。 图 74Sobel 算子 sobel_demo.cpp 中已定
    发表于 08-24 14:54

    什么是PRelu算子?PRelu算子调优经历-先行篇

    TFLm推理引擎的默认实现,PRelu算子的运行时间竟然高达188ms。 于是小编本着工程师本有的探索精神,决定迎难而上,彻底将它优化一下。 所谓知己知彼,百战不殆,首先我们来看一下什么叫做PRelu算子。 PRelu,看着好像
    的头像 发表于 08-24 08:50 772次阅读
    什么是PRelu<b class='flag-5'>算子</b>?PRelu<b class='flag-5'>算子</b>调优经历-先行篇

    机器学习算法的5种基本算子

    机器学习算法的5种基本算子 机器学习是一种重要的人工智能技术,它是为了让计算机能够通过数据自主的学习和提升能力而发明的。机器学习算法是机器学习的核心,它是指让计算机从数据中进行自主学习并且可以实现
    的头像 发表于 08-17 16:11 1320次阅读

    调用HLS的FFT库实现N点FFT

    HLS中用C语言实现8192点FFT,经过测试,实验结果正确,但是时序约束不到100M的时钟,应该是设计上的延时之类的比较大,暂时放弃这个方案,调用HLS中自带的FFT库(hls:f
    的头像 发表于 07-11 10:05 634次阅读
    调用<b class='flag-5'>HLS</b>的FFT库<b class='flag-5'>实现</b>N点FFT

    调用HLS的FFT库实现N点FFT(hls:fft)

    HLS中用C语言实现8192点FFT,经过测试,实验结果正确,但是时序约束不到100M的时钟,应该是设计上的延时之类的比较大,暂时放弃这个方案
    的头像 发表于 07-07 09:08 1011次阅读
    调用<b class='flag-5'>HLS</b>的FFT库<b class='flag-5'>实现</b>N点FFT(<b class='flag-5'>hls</b>:fft)