书接上文,趁着今天休假,采用spinalhdl做一个小的demo,看看在spinalhdl里如何优雅的实现sobel边缘检测。
sobel边缘检测
sobel边缘检测原理教材网上一大堆,核心为卷积处理。
sobel卷积因子为:
该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以a代表原始图像,gx及gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:
图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:
通常,为了提高效率 使用不开平方的近似值:
最后,当计算出来的值大于某一阈值时即认为为边缘像素点。
归结起来,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)
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.datainwindowbuf.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)true) }otherwise{ io.dataout.payload:=(default->false) } }} 区区不到四十行代码,简洁而优雅,基本上就是描述算法,出错概率应该很小吧!
仿真
做图像处理的小伙伴想想在做仿真验证时需要怎么搞,matlab生成灰度图像二进制数据放在文件里,然后仿真时再导入,仿真完成后将结果保存到文件里,最后再在matlab里做对比。 太麻烦。spinalhdl提供了仿真支持,而spinalhdl是基于scala的,可以完美实现整个仿真验证流程:从图片直接获取数据,然后进行仿真验证,仿真结果直接再次生成图片。
英特尔将在2021实现首发7nm产品
Juniper防火墙IPSec VPN的配置
盘点分析HDD和SSD硬盘在企业级及消费级市场的变化
疫情后的5个变化趋势和5G生态系统建设
LCD面板涨价20%,电视机或将迎来集体涨价局面
SpinalHDL里如何实现Sobel边缘检测
折叠手机的“是非曲折”、“叠叠不休”
英特尔将携手产业生态推动5G在垂直领域的应用创新落地
用于智能电话与平板电脑的立体声空间阵列 IC LM48903 (TI)
三星Galaxy Note 10 Lite售价曝光,或将于2020年1月中旬推出
雨雪传感器有开关量信号,有485输出信号吗?
中兴通讯全力支持中国电信构建精品通信网络
西门子推出以嵌入式工控机为基础的边缘应用硬件平台
什么是振荡裕量?振荡裕量的计算方法介绍
小蚁智能摄像机室外版评测 不管是室内还是室外都能做到不错的监控效果
STRADVISION“3D感知网络”,引领ADAS领域革命浪潮
功率半导体器件(IGBT、MOSFET和SiC)设计企业:上海陆芯获数亿元D轮融资,强化车规级功率器件市场突破
苹果iPhone 8基于AR:Siri终于能“看到”这个世界了!
真是离大谱!性能如此优越的ESD防静电监控系统竟然鲜为人知?
美高森美发布兼容AMD EPYC处理器的Adaptec智能存储产品