0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SpinalHDL里如何實(shí)現(xiàn)Sobel邊緣檢測(cè)

FPGA之家 ? 來(lái)源:FPGA之家 ? 作者:FPGA之家 ? 2022-08-26 08:59 ? 次閱讀

書(shū)接上文,趁著今天休假,采用SpinalHDL做一個(gè)小的demo,看看在SpinalHDL里如何優(yōu)雅的實(shí)現(xiàn)Sobel邊緣檢測(cè)。

Sobel邊緣檢測(cè)

Sobel邊緣檢測(cè)原理教材網(wǎng)上一大堆,核心為卷積處理。

Sobel卷積因子為:

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

該算子包含兩組3x3的矩陣,分別為橫向及縱向,將之與圖像作平面卷積,即可分別得出橫向及縱向的亮度差分近似值。如果以A代表原始圖像,Gx及Gy分別代表經(jīng)橫向及縱向邊緣檢測(cè)的圖像灰度值,其公式如下:

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

圖像的每一個(gè)像素的橫向及縱向灰度值通過(guò)以下公式結(jié)合,來(lái)計(jì)算該點(diǎn)灰度的大?。?/p>

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

通常,為了提高效率使用不開(kāi)平方的近似值:

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

最后,當(dāng)計(jì)算出來(lái)的值大于某一閾值時(shí)即認(rèn)為為邊緣像素點(diǎn)。

歸結(jié)起來(lái),Sobel邊緣檢測(cè)分為三大步:卷積計(jì)算、灰度計(jì)算、閾值比較處理。結(jié)合上文實(shí)現(xiàn)的bufWindow,在SpinalHDL里實(shí)現(xiàn)Sobel邊緣檢測(cè)也就幾行代碼的事情(如果是寫(xiě)Verilog我還是拒絕的)。

卷積計(jì)算

通過(guò)bufWindow,我們可以得到一個(gè)3x3的矩陣窗口,拿到結(jié)果第一步即是計(jì)算卷積,由于卷積因子是帶符號(hào)的,而在做卷積時(shí)又需要考慮位寬擴(kuò)展的事情,在寫(xiě)Verilog時(shí)還是需要小心的設(shè)計(jì)下的,而在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輸出的窗口矩陣值擴(kuò)展一位位寬轉(zhuǎn)換為有符號(hào)值,然后進(jìn)行計(jì)算卷積。計(jì)算卷積運(yùn)用了兩個(gè)運(yùn)算符“-^”,"+|"來(lái)處理加減運(yùn)算時(shí)的位寬處理(可參照SpinalHDL手冊(cè)或本公眾號(hào)的《SpinalHDL—數(shù)據(jù)類(lèi)型:UInt/SIn》)。最終得到Gx、Gy。

灰度計(jì)算

灰度計(jì)算這里采用近似值,通過(guò)取絕對(duì)值的方式進(jìn)行實(shí)現(xiàn),在SpinalHDL里也就一行代碼的事情:

sobelResult.payload:= (sobelConv.payload(0).abs+| sobelConv.payload(1).abs).fixTo(cfg.dataWidth-1 downto 0,RoundType.ROUNDUP)
由于在卷積計(jì)算時(shí)有擴(kuò)展位寬,這里計(jì)算最后調(diào)用fixTo進(jìn)行高位飽和處理。最終得到位寬與輸入保持一致(想想你在Veirlog里實(shí)現(xiàn)這一步要做多少事情,少年)。

閾值比較

閾值比較就很簡(jiǎn)單了,比較兩個(gè)值大小取兩個(gè)極端:

when(sobelResult.payload>io.thresholdValue){      io.dataOut.payload:=(default->true)    }otherwise{      io.dataOut.payload:=(default->false)    }
最終實(shí)現(xiàn)Sobel邊緣檢測(cè)代碼如下:

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)}  }}
區(qū)區(qū)不到四十行代碼,簡(jiǎn)潔而優(yōu)雅,基本上就是描述算法,出錯(cuò)概率應(yīng)該很小吧!

仿真

做圖像處理的小伙伴想想在做仿真驗(yàn)證時(shí)需要怎么搞,matlab生成灰度圖像二進(jìn)制數(shù)據(jù)放在文件里,然后仿真時(shí)再導(dǎo)入,仿真完成后將結(jié)果保存到文件里,最后再在matlab里做對(duì)比。 太麻煩。SpinalHDL提供了仿真支持,而SpinalHDL是基于Scala的,可以完美實(shí)現(xiàn)整個(gè)仿真驗(yàn)證流程:從圖片直接獲取數(shù)據(jù),然后進(jìn)行仿真驗(yàn)證,仿真結(jié)果直接再次生成圖片。

審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Verilog
    +關(guān)注

    關(guān)注

    28

    文章

    1343

    瀏覽量

    109925
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4722

    瀏覽量

    68234
  • sobel
    +關(guān)注

    關(guān)注

    0

    文章

    12

    瀏覽量

    7890

原文標(biāo)題:FPGA圖像處理——老戲新說(shuō)

文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    基于FPGA的Sobel邊緣檢測(cè)工作原理

    Sobel 邊緣檢測(cè)的工作原理是檢測(cè)圖像在水平和垂直方向上的梯度變化。為此,將兩個(gè)卷積濾波器應(yīng)用于原始圖像,然后組合這些卷積濾波器的結(jié)果以確定梯度的大小。
    發(fā)表于 12-14 11:34 ?1382次閱讀

    基于FPGA的實(shí)時(shí)邊緣檢測(cè)系統(tǒng)設(shè)計(jì),Sobel圖像邊緣檢測(cè),F(xiàn)PGA圖像處理

    60 為閾值得到圖8(a)和(b)。 通過(guò)對(duì)比可以看出,使用 FPGA 進(jìn)行Sobel邊緣檢測(cè)能夠實(shí)現(xiàn)與 MATLAB 相近的檢測(cè)效果,驗(yàn)
    發(fā)表于 05-24 07:45

    基于 DSP5509 進(jìn)行數(shù)字圖像處理中 Sobel 算子邊緣檢測(cè)的硬件連接電路圖

    以下是基于 DSP5509 進(jìn)行數(shù)字圖像處理中 Sobel 算子邊緣檢測(cè)的硬件設(shè)計(jì)方案: 一、總體架構(gòu) 圖像采集:使用合適的圖像傳感器,如 CMOS 傳感器,通過(guò)相應(yīng)的接口(如 SPI、I2C 等
    發(fā)表于 09-25 15:25

    關(guān)于圖像邊緣檢測(cè)器的VHDL的實(shí)現(xiàn)該怎么下手,求大神指教!

    準(zhǔn)備要做一個(gè)以VHDL實(shí)現(xiàn)圖像邊緣檢測(cè)器,用的是sobel算子,不怎么會(huì)寫(xiě)VHDL的代碼,請(qǐng)各路大神指教,感激不盡!
    發(fā)表于 12-02 18:58

    基于FPGA的Sobel邊緣檢測(cè)實(shí)現(xiàn)

    我們?cè)诖嘶A(chǔ)上修改,從而實(shí)現(xiàn),基于FPGA的動(dòng)態(tài)圖片的Sobel邊緣檢測(cè)、中值濾波、Canny算子邊緣
    發(fā)表于 08-29 15:41

    基于FPGA的邊緣檢測(cè)Sobel算法

    轉(zhuǎn)帖摘要: 針對(duì)嵌入式軟件無(wú)法滿足數(shù)字圖像實(shí)時(shí)處理速度問(wèn)題,提出用硬件加速器的思想,通過(guò)FPGA實(shí)現(xiàn)Sobel邊緣檢測(cè)算法。通過(guò)乒乓操作、并行處理數(shù)據(jù)和流水線設(shè)計(jì),大大提高算法的處理速
    發(fā)表于 11-29 08:57

    Labview圖像處理——邊緣檢測(cè)

    邊緣的灰度值過(guò)度較為明顯,梯度算子可以得到較好的邊緣檢測(cè)結(jié)果。邊緣提取其實(shí)也是一種濾波,不同的算子有不同的提取效果。比較常用的方法有三種,Sobel
    發(fā)表于 12-01 12:16

    邊緣檢測(cè)的幾種微分算子

    一、邊緣檢測(cè)邊緣檢測(cè)的幾種微分算子:一階微分算子:Roberts、Sobel、Prewitt二階微分算子:Laplacian、Log/Mar
    發(fā)表于 07-26 08:29

    【米爾MYS-8MMX開(kāi)發(fā)板免費(fèi)試用】-VI.Sobel邊緣檢測(cè)(ZMJ)

    【米爾MYS-8MMX開(kāi)發(fā)板】-VI.Sobel邊緣檢測(cè)(ZMJ)1.功能簡(jiǎn)介本案例使用 GStreamer API 通過(guò) ARM Cotrex-A53 從 USB 攝像頭獲取 MJPEG 格式視頻
    發(fā)表于 09-10 15:41

    SpinalHDL實(shí)現(xiàn)優(yōu)雅的添加待跟蹤波形信號(hào)

    SpinalHDL,我們一樣可以實(shí)現(xiàn)優(yōu)雅的添加待跟蹤波形信號(hào)。姿勢(shì)一在Verilog代碼,我們想要添加波形跟蹤信號(hào)時(shí)往往在待跟蹤信號(hào)上添加廠商約束原語(yǔ),如下所示:so easy!貌
    發(fā)表于 06-22 14:37

    迅為iTOP-RK3568開(kāi)發(fā)板Sobel 算子邊緣檢測(cè)

    ,是最為常用的邊緣檢測(cè)算子,但是得到的邊緣較粗,可能出現(xiàn)偽邊緣。 cv2.Sobel 函數(shù)功能: 使用
    發(fā)表于 09-18 10:27

    sobel_FPGA l邊緣檢測(cè)

    sobel_FPGA l邊緣檢測(cè).源代碼。
    發(fā)表于 05-03 16:42 ?9次下載

    基于CORDIC的高速Sobel算法實(shí)現(xiàn)

    為提高圖像邊緣檢測(cè)的處理速度,提出一種基于CORDIC的高速Sobel算法實(shí)現(xiàn)。
    的頭像 發(fā)表于 10-05 09:54 ?3525次閱讀
    基于CORDIC的高速<b class='flag-5'>Sobel</b>算法<b class='flag-5'>實(shí)現(xiàn)</b>

    FPGA圖像處理的Sobel邊緣檢測(cè)

    Sobel邊緣檢測(cè) Sobel邊緣檢測(cè)原理教材網(wǎng)上一大堆,核心為卷積處理。
    的頭像 發(fā)表于 03-22 09:45 ?2910次閱讀
    FPGA圖像處理的<b class='flag-5'>Sobel</b><b class='flag-5'>邊緣</b><b class='flag-5'>檢測(cè)</b>

    Sobel算子原理介紹與實(shí)現(xiàn)方法

    索貝爾算子(Sobel operator)主要用作邊緣檢測(cè),在技術(shù)上,它是一離散性差分算子,用來(lái)運(yùn)算圖像亮度函數(shù)的灰度之近似值。在圖像的任何一點(diǎn)使用此算子,將會(huì)產(chǎn)生對(duì)應(yīng)的灰度矢量或是其法矢量S
    的頭像 發(fā)表于 07-21 17:27 ?1.3w次閱讀