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

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

3天内不再提示

SpinalHDL里如何实现Sobel边缘检测

FPGA之家 来源:FPGA之家 作者:FPGA之家 2022-08-26 08:59 次阅读

书接上文,趁着今天休假,采用SpinalHDL做一个小的demo,看看在SpinalHDL里如何优雅的实现Sobel边缘检测

Sobel边缘检测

Sobel边缘检测原理教材网上一大堆,核心为卷积处理。

Sobel卷积因子为:

38aa8124-24d7-11ed-ba43-dac502259ad0.png

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

38bd3ef4-24d7-11ed-ba43-dac502259ad0.png

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

38cce78c-24d7-11ed-ba43-dac502259ad0.png

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

38de788a-24d7-11ed-ba43-dac502259ad0.png

最后,当计算出来的值大于某一阈值时即认为为边缘像素点。

归结起来,Sobel边缘检测分为三大步:卷积计算、灰度计算、阈值比较处理。结合上文实现的bufWindow,在SpinalHDL里实现Sobel边缘检测也就几行代码的事情(如果是写Verilog我还是拒绝的)。

卷积计算

通过bufWindow,我们可以得到一个3x3的矩阵窗口,拿到结果第一步即是计算卷积,由于卷积因子是带符号的,而在做卷积时又需要考虑位宽扩展的事情,在写Verilog时还是需要小心的设计下的,而在SpinalHDL里,两行代码:

val Gx=(windowbuf.io.dataOut.payload(0)(2).expand.asSInt-^windowbuf.io.dataOut.payload(0)(0).expand.asSInt)+|      ((windowbuf.io.dataOut.payload(1)(2).expand.asSInt-^windowbuf.io.dataOut.payload(1)(0).expand.asSInt)<<1)+|      (windowbuf.io.dataOut.payload(2)(2).expand.asSInt-^windowbuf.io.dataOut.payload(2)(0).expand.asSInt)val Gy=(windowbuf.io.dataOut.payload(0)(0).expand.asSInt-^windowbuf.io.dataOut.payload(2)(0).expand.asSInt)+|       ((windowbuf.io.dataOut.payload(0)(1).expand.asSInt-^windowbuf.io.dataOut.payload(2)(1).expand.asSInt)<<1)+|       (windowbuf.io.dataOut.payload(0)(2).expand.asSInt-^windowbuf.io.dataOut.payload(2)(2).expand.asSInt)

首先将bufWindow输出的窗口矩阵值扩展一位位宽转换为有符号值,然后进行计算卷积。计算卷积运用了两个运算符“-^”,"+|"来处理加减运算时的位宽处理(可参照SpinalHDL手册或本公众号的《SpinalHDL—数据类型:UInt/SIn》)。最终得到Gx、Gy。

灰度计算

灰度计算这里采用近似值,通过取绝对值的方式进行实现,在SpinalHDL里也就一行代码的事情:

sobelResult.payload:= (sobelConv.payload(0).abs+| sobelConv.payload(1).abs).fixTo(cfg.dataWidth-1 downto 0,RoundType.ROUNDUP)
由于在卷积计算时有扩展位宽,这里计算最后调用fixTo进行高位饱和处理。最终得到位宽与输入保持一致(想想你在Veirlog里实现这一步要做多少事情,少年)。

阈值比较

阈值比较就很简单了,比较两个值大小取两个极端:

when(sobelResult.payload>io.thresholdValue){      io.dataOut.payload:=(default->true)    }otherwise{      io.dataOut.payload:=(default->false)    }
最终实现Sobel边缘检测代码如下:

case class sobelProc(cfg:lineBufferCfg) extends Component{  require(cfg.lineNum==3)  val io=new Bundle{    val thresholdValue =in UInt(cfg.dataWidth bits)    val dataIn=slave Flow(UInt(cfg.dataWidth bits))    val dataOut=master Flow(UInt(cfg.dataWidth bits))    dataOut.valid.setAsReg().init(False)    dataOut.payload.setAsReg().init(0)  }  noIoPrefix()  val sobel=new Area{    val windowbuf=bufWindow(cfg)    val sobelConv=Reg(Flow(Vec(SInt(),2)))    val sobelResult=Reg(Flow(UInt(cfg.dataWidth bits)))    sobelConv.valid.init(False)    sobelResult.valid.init(False)    io.dataIn<>windowbuf.io.dataIn    val Gx=(windowbuf.io.dataOut.payload(0)(2).expand.asSInt-^windowbuf.io.dataOut.payload(0)(0).expand.asSInt)+|      ((windowbuf.io.dataOut.payload(1)(2).expand.asSInt-^windowbuf.io.dataOut.payload(1)(0).expand.asSInt)<<1)+|      (windowbuf.io.dataOut.payload(2)(2).expand.asSInt-^windowbuf.io.dataOut.payload(2)(0).expand.asSInt)    val Gy=(windowbuf.io.dataOut.payload(0)(0).expand.asSInt-^windowbuf.io.dataOut.payload(2)(0).expand.asSInt)+|           ((windowbuf.io.dataOut.payload(0)(1).expand.asSInt-^windowbuf.io.dataOut.payload(2)(1).expand.asSInt)<<1)+|           (windowbuf.io.dataOut.payload(0)(2).expand.asSInt-^windowbuf.io.dataOut.payload(2)(2).expand.asSInt)    sobelConv.valid:=windowbuf.io.dataOut.valid    sobelConv.payload(0):=Gx    sobelConv.payload(1):=Gy    sobelResult.valid:=sobelConv.valid    sobelResult.payload:= (sobelConv.payload(0).abs+| sobelConv.payload(1).abs).fixTo(cfg.dataWidth-1 downto 0,RoundType.ROUNDUP)    io.dataOut.valid:=sobelResult.valid    when(sobelResult.payload>io.thresholdValue){      io.dataOut.payload:=(default->true)    }otherwise{      io.dataOut.payload:=(default->false)}  }}
区区不到四十行代码,简洁而优雅,基本上就是描述算法,出错概率应该很小吧!

仿真

做图像处理的小伙伴想想在做仿真验证时需要怎么搞,matlab生成灰度图像二进制数据放在文件里,然后仿真时再导入,仿真完成后将结果保存到文件里,最后再在matlab里做对比。 太麻烦。SpinalHDL提供了仿真支持,而SpinalHDL是基于Scala的,可以完美实现整个仿真验证流程:从图片直接获取数据,然后进行仿真验证,仿真结果直接再次生成图片。

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

    关注

    28

    文章

    1326

    浏览量

    109302
  • 代码
    +关注

    关注

    30

    文章

    4555

    浏览量

    66767
  • sobel
    +关注

    关注

    0

    文章

    12

    浏览量

    7825

原文标题:FPGA图像处理——老戏新说

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

收藏 人收藏

    评论

    相关推荐

    基于FPGA的Sobel边缘检测工作原理

    Sobel 边缘检测的工作原理是检测图像在水平和垂直方向上的梯度变化。为此,将两个卷积滤波器应用于原始图像,然后组合这些卷积滤波器的结果以确定梯度的大小。
    发表于 12-14 11:34 1120次阅读

    关于图像边缘检测器的VHDL的实现该怎么下手,求大神指教!

    准备要做一个以VHDL实现图像边缘检测器,用的是sobel算子,不怎么会写VHDL的代码,请各路大神指教,感激不尽!
    发表于 12-02 18:58

    基于FPGA的Sobel边缘检测实现

    我们在此基础上修改,从而实现,基于FPGA的动态图片的Sobel边缘检测、中值滤波、Canny算子边缘
    发表于 08-29 15:41

    基于FPGA的边缘检测Sobel算法

    转帖摘要: 针对嵌入式软件无法满足数字图像实时处理速度问题,提出用硬件加速器的思想,通过FPGA实现Sobel边缘检测算法。通过乒乓操作、并行处理数据和流水线设计,大大提高算法的处理速
    发表于 11-29 08:57

    源码交流=图像处理 实现图像去噪、滤波、锐化、边缘检测

    之后的图像NO.7:Sobel边缘检测之后的图像【改进分析】暂无【源码下载】https://www.lanzous.com/iajjk5i密码:8czs【程序展示】% 功能:MATLAB实现
    发表于 04-01 19:03

    【正点原子FPGA连载第二十八章V7725摄像头Sobel边缘检测-领航者 ZYNQ 之嵌入式开发指南

    原子公众号,获取最新资料第二十八章V7725摄像头Sobel边缘检测边缘检测是图像处理和计算机视觉中的基本问题,
    发表于 09-07 15:48

    Labview图像处理——边缘检测

    边缘的灰度值过度较为明显,梯度算子可以得到较好的边缘检测结果。边缘提取其实也是一种滤波,不同的算子有不同的提取效果。比较常用的方法有三种,Sobel
    发表于 12-01 12:16

    边缘检测的几种微分算子

    一、边缘检测边缘检测的几种微分算子:一阶微分算子:Roberts、Sobel、Prewitt二阶微分算子:Laplacian、Log/Mar
    发表于 07-26 08:29

    【米尔MYS-8MMX开发板免费试用】-VI.Sobel边缘检测(ZMJ)

    【米尔MYS-8MMX开发板】-VI.Sobel边缘检测(ZMJ)1.功能简介本案例使用 GStreamer API 通过 ARM Cotrex-A53 从 USB 摄像头获取 MJPEG 格式视频
    发表于 09-10 15:41

    SpinalHDL实现优雅的添加待跟踪波形信号

    SpinalHDL,我们一样可以实现优雅的添加待跟踪波形信号。姿势一在Verilog代码,我们想要添加波形跟踪信号时往往在待跟踪信号上添加厂商约束原语,如下所示:so easy!貌
    发表于 06-22 14:37

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

    ,是最为常用的边缘检测算子,但是得到的边缘较粗,可能出现伪边缘。 cv2.Sobel 函数功能: 使用
    发表于 09-18 10:27

    sobel_FPGA l边缘检测

    sobel_FPGA l边缘检测.源代码。
    发表于 05-03 16:42 9次下载

    基于CORDIC的高速Sobel算法实现

    为提高图像边缘检测的处理速度,提出一种基于CORDIC的高速Sobel算法实现
    的头像 发表于 10-05 09:54 3332次阅读
    基于CORDIC的高速<b class='flag-5'>Sobel</b>算法<b class='flag-5'>实现</b>

    FPGA图像处理的Sobel边缘检测

    Sobel边缘检测 Sobel边缘检测原理教材网上一大堆,核心为卷积处理。
    的头像 发表于 03-22 09:45 2663次阅读
    FPGA图像处理的<b class='flag-5'>Sobel</b><b class='flag-5'>边缘</b><b class='flag-5'>检测</b>

    Sobel算子原理介绍与实现方法

    索贝尔算子(Sobel operator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量S
    的头像 发表于 07-21 17:27 9318次阅读