算法系列:基于 FPGA 的图像边缘检测系统设计(sobel算法)
算法系列:基于 FPGA 的图像边缘检测系统设计(sobel算法)
今天给大侠带来基于 FPGA 的图像边缘检测设计,话不多说,上货。
设计流程如下:
mif文件的制作→ 调用ip核生成rom以及仿真注意问题→ 灰度处理→ 均值滤波:重点是3*3 像素阵列的生成→ sobel边缘检测→ 图片的显示→ 结果展示 。
一、mif文件的制作
受资源限制,将图片像素定为 160 * 120,将图片数据制成 mif 文件,对 rom ip 核进行初始化。mif文件的制作方法网上有好多办法,因此就不再叙述了,重点说mif文件的格式。
mif文件的格式为:
WIDTH=16 ; //数据位宽
DEPTH=19200 ; // rom 深度即图片像素点的个数
ADDRESS_RADIX=UNS ; //地址数据格式
DATA_RADIX=BIN ; //数据格式
CONTENT
BEGIN
0:1010110011010000 ; // 地址 :数据 ;注意格式要和上面定义的保持统一
1:1010110011010000 ;
2:1010010010110000 ;
......
19198:1110011011111001 ;
19199:1110011011011000 ;
END;
二、ip 核生成 rom 及仿真时需要注意的问题
ip 核生成 rom
1、Tools -> MegaWizard Plug-In Manager
2、Create a new custom megafuction variation
3、Memory Compier -> ROM -> Verilog HDL -> 自定义名称
仿真注意问题:
1、仿真时要注意是否有 altera_mf 库文件,否则会报错。
Module 'altsyncram' is not define
解决方案:
(1).下载 altera_mf 库文件;
(2). 仿真时将 altera_mf.v 与其他文件一起加入到 project 中。
2、要将 .mif 文件放在仿真工程目录下,即与 .mpf 文件在一起,否则将不会有数据输出。
三、灰度处理
任何颜色都由红、绿、蓝三原色组成,假如原来某点的颜色为( R,G,B )那么,我们可以通过下面几种方法,将其转换为灰度:
浮点算法:Gray=0.299R+0.587G+0.114B
平均值法:Gray=(R+G+B)/3;
仅取单色(如绿色):Gray=G;
将计算出来的Gray值同时赋值给 RGB 三个通道即RGB为(Gray,Gray,Gray),此时显示的就是灰度图。通过观察调色板就能看明了。 通过观察可知,当RGB三个通道的值相同时即为灰色,Gray的值越大,颜色越接近白色,反之越接近黑色(这是我自己的理解,不严谨错误之处请大神指正)。
这是在线调色板网址,可以进去自己研究一下。
站长工具颜色代码查询、RGB颜色值:
此次采用是浮点算法来实现灰度图的,我的图片数据是RGB565 格式 ,难点: 如何进行浮点运算。思路:先将数据放大,然后再缩小。
例如:
Gray=0.299R+0.587G+0.114B转化为 Gray=(77R+150G+29B)>>8 即可,这里有一个技巧,若 a 为 16 位即 a [15:0],那么 a>>8 与 a [15:8]是一样的。 核心代码如下:
always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginred_r1 <= 0 ; green_r1 <= 0 ;blue_r1 <= 0 ;endelse beginred_r1 <= red * 77 ; //放大后的值green_r1 <= green * 150;blue_r1 <= blue * 29 ;end
endalways @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginGray <= 0; // 三个数之和endelse beginGray <= red_r1 + green_r1 + blue_r1; end
endalways @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginpost_data_in <= 0; //输出的灰度数据endelse beginpost_data_in <= { Gray[13:9], Gray[13:8], Gray[13:9] };//将Gray值赋值给RGB三个通道end
end
四、均值滤波
均值滤波的原理
做图像处理, “把每个像素都用周围的8个像素来做均值操作 ”, 比如:
图通常是最能说明问题的东西,非常明显的,这个3*3区域像素的颜色值分别是5,3,6,2,1,9,8,4,7那么中间的1这个像素的过滤后的值就是这些值的平均值,也就是前面的计算方法:(5+3+6+2+1+9+8+4+7)/9=5一目了然。
那么这个均值滤波有什么用处呢?主要还是平滑图像的用处,有的图像的锐度很高,用这样的均值算法,可以把锐度降低。使得图像看上去更加自然,下面就有几幅图我们可以看出一些端倪:
原图:
平滑处理后:
这里还是可以明显的感觉到不同的, 没有好坏之分,就是第二幅图片看上去更为平滑。继续我们的问题, 那这里均值平滑是否具有去除噪声的功能呢?我们搞来了椒盐噪声(就是随机的白点,黑点)来试试手:
噪声图(5%):
平滑处理之后:
首先这里的噪声还是比较小的, 只有5%,从均值的效果来看的话, 我可以说几乎没有用,其实直观的想也可以判断, 因为这里的处理并没有剔除这些噪声点, 而只是微弱地降低了噪声,所以效果可以想见的。 最后的时候还是贴上一段处理的代码:
void meanFilter (unsigned char* corrupted, unsigned char* smooth, int width, int height)
{memcpy ( smooth, corrupted, width*height*sizeof(unsigned char) );for (int j=1;j<height-1;j++){for (int i=1;i<width-1;i++){smooth [ j*width+i ] = ( corrupted [ (j-1)*width+(i-1) ] + corrupted [ (j-1)*width+i] + corrupted [ (j-1)*width+(i+1) ] +corrupted [ j*width+(i-1) ] + corrupted [ j*width+i] + corrupted [ j*width+(i+1) ] +corrupted [ (j+1)*width+(i-1) ] + corrupted [ (j+1)*width+i] + corrupted [ (j+1)*width+(i+1) ] ) / 9;}}
}
简单的从1...width-1来处理, 所以第一个和最后一个像素就简单的抛掉了, 如果只是简单的看看效果还是没有问题的。
如何生成 3*3 的像素阵列。可以利用 ip 核生成移位寄存器 ,方法与 ip 核生成 rom 一样,详情见 ip 核 生成 rom 操作 。
仿真波形如下 row_1 , row_2 , row_3 是指图像的第一、二、三行的数据,Per_href 是行有效信号(受VGA时序的启发,从 rom 中读取数据时设计了行有效和场有效的控制信号,事半功倍,有了利于仿真查错和数据的控制)。从 3 开始就出现了3*3 的像素阵列,这时候就可以求取周围 8 个像素点的平均值,进行均值滤波。
下面这个图表示的是FPGA 如何将矩阵数据处理成并行的像素点,可以结合下面的代码好好理解,这也是精华所在。
正方形红框框起来的是第一个完整的 3*3 矩阵,长方形红框框起来的是并行的像素点,在此基础上就可以求得平均值,进行均值滤波。
从下图也能看到 3*3 矩阵从左往右滑动。
第一个3*3 阵列。
0 1 2 -- > p11 p12 p13
3 4 5 -- > p21 p22 p23
6 7 8 -- > p31 p32 p33
核心代码如下:
reg [5:0]p_11,p_12,p_13; // 3 * 3 卷积核中的像素点
reg [5:0]p_21,p_22,p_23;
reg [5:0]p_31,p_32,p_33;
reg [8:0]mean_value_add1,mean_value_add2,mean_value_add3;//每一行之和always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begin{p_11,p_12,p_13} <= {5'b0,5'b0,5'b0} ;{p_21,p_22,p_23} <= {15'b0,15'b0,15'b0};{p_31,p_32,p_33} <= {15'b0,15'b0,15'b0};endelse beginif(per_href_ff0==1&&flag_do==1)begin{p_11,p_12,p_13}<={p_12,p_13,row_1};{p_21,p_22,p_23}<={p_22,p_23,row_2};{p_31,p_32,p_33}<={p_32,p_33,row_3};endelse begin{p_11,p_12,p_13}<={5'b0,5'b0,5'b0};{p_21,p_22,p_23}<={5'b0,5'b0,5'b0}{p_31,p_32,p_33}<={5'b0,5'b0,5'b0}endend
endalways @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginmean_value_add1<=0;mean_value_add2<=0;mean_value_add3<=0;endelse if(per_href_ff1)beginmean_value_add1<=p_11+p_12+p_13;mean_value_add2<=p_21+ 0 +p_23;mean_value_add3<=p_31+p_32+p_33;end
endwire [8:0]mean_value;//8位数之和
wire [5:0]fin_y_data; //平均数,除以8,相当于左移三位。assign mean_value=mean_value_add1+mean_value_add2+mean_value_add3;
assign fin_y_data=mean_value[8:3];
五、sobel 边缘检测
边缘检测的原理
该算子包含两组 3x3 的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。A代表原始图像的 3*3 像素阵列,Gx及Gy分别代表经横向及纵向边缘检测的图像,其公式如下:
图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小。
如果梯度G大于某一阀值则认为该点(x,y)为边缘点。
用的是边缘检测算法。
难点:
(1)掌握了 3*3 像素阵列,Gx 与 Gy 就很好计算了。
注意问题:为了避免计算过程中出现负值,所以将正负值分开单独计算,具体见代码)
(2)G的计算需要开平方,如何进行开平方运算
Quartus ii 提供了开平方 ip 核,因此我们直接调用就好了 。
代码如下:
reg [8:0] p_x_data ,p_y_data ; // x 和 y 的正值之和
reg [8:0] n_x_data ,n_y_data ; // x 和 y 的负值之和
reg [8:0] gx_data ,gy_data ; //最终结果always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginp_x_data <=0;n_x_data <=0;gx_data <=0;endelse if(per_href_ff1==1) begin p_x_data <= p_13 + (p_23<<1) + p_33 ;n_x_data <= p_11 + (p_12<<1 )+ p_13 ;gx_data <= (p_x_data >=n_x_data)? p_x_data - n_x_data : n_x_data - p_x_data ; endelse beginp_x_data<=0;n_x_data<=0;gx_data <=0;end
endalways @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginp_y_data <=0;n_y_data <=0;gy_data <=0;endelse if(per_href_ff1==1) beginp_y_data <= p_11 + (p_12<<1) + p_13 ;n_y_data <= p_31 + (p_32<<1) + p_33 ;gy_data <= (p_y_data >=n_y_data)? p_y_data - n_y_data : n_y_data - p_y_data ; endelse beginp_y_data <=0;n_y_data <=0;gy_data <=0;end
end//求平方和,调用ip核开平方
reg [16:0] gxy; // Gx 与 Gy 的平方和
always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begingxy<=0;endelse begingxy<= gy_data* gy_data + gx_data* gx_data ;end
endwire [8:0] squart_out ;
altsquart u1_altsquart ( //例化开平方的ip核.radical (gxy),.q (squart_out), //输出的结果.remainder());//与阈值进行比较
reg [15:0] post_y_data_r;
always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginpost_y_data_r<=16'h00;endelse if(squart_out>=threshold)post_y_data_r<=16'h00 ;elsepost_y_data_r<=16'hffff ;end
六、图片的显示
本来是想用 VGA 来显示图片的,由于条件的限制没能实现,最终只能将处理完的数据输出保存在 .txt 文件中,然后借助网页进行显示。
难点:
(1) 如何将数据流输出保存到 .txt 文件中。
(2) 网页的使用及注意事项。
在testbench里加入下面所示代码即可将图片数据保存到 .txt 文本。
代码如下:
integer w_file; initialw_file = $fopen("data_out_3.txt"); //保存数据的文件名always @(posedge clk or negedge rst_n) begin if(flag_write==1&&post_href==1)//根据自己的需求定义$fdisplay(w_file,"%b",post_y_data); end
网页的界面如下,将参数设置好以后就可以显示图片。
下载链接:
链接:https://pan.baidu.com/s/1pwkJHtAxVHWWijSLczH0Ng
提取码:e87j
注意:由于此网站是量身定做的,所以只能显示数据格式为RGB565的16位二进制的数才能正确显示,注意不能有分号,正确格式示例如下,必须严格遵守。
七、结果展示
小结:均值滤波处理后的图片有明显的黑边,产生这一现象的原因就是生成 3x 3 像素矩阵和取像素值时数据有损失造成的,但是这也是可以优化的,后续我会继续努力不断完善。
本次只是简单对一幅图像进行边缘检测,我的后续目标是实现图片的实时处理,这又需要学习很多东西了,SDRAM、摄像头驱动等等等,越学习越发现自己知道的实在是太少了,永远在路上,学无止境。希望我的分享能够帮助一些和我一样热爱FPGA图像处理的朋友。
【QQ交流群】
群号:173560979,进群暗语:FPGA技术江湖粉丝。
多年的FPGA企业开发经验,各种通俗易懂的学习资料以及学习方法,浓厚的交流学习氛围,QQ群目前已有1000多名志同道合的小伙伴,无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有。
【微信交流群】
现微信交流群已建立08群,人数已达数千人,欢迎关注“FPGA技术江湖”微信公众号,可获取进群方式。
完
后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。
江湖偌大,继续闯荡,愿大侠一切安好,有缘再见!
算法系列:基于 FPGA 的图像边缘检测系统设计(sobel算法)相关推荐
- Matlab与FPGA图像处理系列——基于FPGA的实时边缘检测系统设计,sobel边缘检测流水线实现
注:下载链接的资源是图片存 ROM 后读取进行 Sobel 检测显示在 VGA上,可供参考. 摘要:本文设计了一种基于 FPGA 的实时边缘检测系统,使用OV5640 摄像头模块获取实时的视频图像数据 ...
- 基于FPGA的图像边缘检测系统设计
边缘检测算法的实现 Sobel和Prewitt算子都是基于3*3模板的,所以我们再进行边缘检测的时候,也需要产生一个3*3的模板.本次毕业设计产生3*3的模板的办法是,用RAM来存储图像的前两行数据, ...
- 基于FPGA的图像中值滤波原理与实现
图像中值滤波的FPGA实现 项目简述 中值滤波器原理 中值滤波器的实现 测试模块的代码 仿真结果 下板结果 总结 项目简述 中值滤波器在去除尖端噪声中非常重要,是信号处理中最长用到的滤波器.图像中的一 ...
- 基于FPGA的实时图像边缘检测系统设计(上)
今天给大侠带来基于FPGA的实时图像边缘检测系统设计,由于篇幅较长,分三篇.今天带来第一篇,上篇,话不多说,上货. 导读 随着科学技术的高速发展,FPGA在系统结构上为数字图像处理带来了新的契机.图像 ...
- verilog 算法加速模块设计流程_基于FPGA的图像加速器的设计
基于 FPGA 的图像加速器的设计 摘 要 介绍了一种基于 FPGA 的图像加速器的设计.本文硬件加速器的实质是通过流水线 设计来减少多余的操作达到加速的目的的, 内存是由 DMA 控制器访问, 之后 ...
- 基于FPGA的图像浮雕效果实现
基于FPGA的图像浮雕效果实现 项目简述 算法原理及MATLAB实现 浮雕效果的FPGA实现 FPGA工程代码 下板效果 参考文献 总结 项目简述 为什么要做这个小项目,因为最近正在在学习FPGA开源 ...
- 图像的梯度方向matlab,基于梯度方向的图像边缘检测方法与流程
本发明具体涉及一种基于梯度方向的图像边缘检测方法. 背景技术: 边缘检测是图像处理的基本问题,在图像分割.特征提取.视觉导航等领域有广泛的应用.基于微分的边缘检测算法如Sobel算子.Prewitt算 ...
- 毫米波雷达系列 | 基于前后向空间平滑的MUSIC算法详解
毫米波雷达系列 | 基于前后向空间平滑的MUSIC算法详解 文章目录 毫米波雷达系列 | 基于前后向空间平滑的MUSIC算法详解 DOA阵列模型 MUSIC算法 空间平滑算法 整体流程 仿真代码 忙了 ...
- 基于FPGA的通信显示系统设计
一.系统介绍 本设计给出了一种基于FPGA的通信显示系统设计方法,采用EDA作为开发工具,QuartusII作为运行程序的平台,结合所学知识设计一个基于FPGA的通信显示系统设计,通过串口调试器发送图 ...
- 路径规划算法:基于灰狼优化(GWO)的路径规划算法- 附代码
路径规划算法:基于灰狼优化(GWO)的路径规划算法- 附代码 文章目录 路径规划算法:基于灰狼优化(GWO)的路径规划算法- 附代码 1.算法原理 1.1 环境设定 1.2 约束条件 1.3 适应度函 ...
最新文章
- MVC5 + EF6 完整入门教程三
- 安卓模拟器BlueStacks 安装使用教程(图解)
- Ubuntu 安装软件的三种方式
- bootstrap--响应式框架页面环境配置
- 《深入理解Java虚拟机》笔记4——类文件结构
- java jks 转pfx_JKS和PFX文件相互转换方法
- mysql 阿里云 版本_关于阿里云centos版本,mysql5.7的一些注意事项
- php加密数据解密,php 数据加密解密
- Linux_service cloudera-scm-server start failed
- 【ArcGIS|空间分析】微博签到数据分析(全国大学生GIS技能大赛试题)
- python设置excel格式_Python使用xlwt写excel并设置写入格式
- 拿出大把真金白银回购护盘,真心实意的格力,为何买不到股民信任
- Matlab:绘制正弦曲线与余弦曲线
- laravel框架中Cache缓存类中的原子锁
- 爸妈上班却顶着凛冽的寒风骑着自行车
- 手机python代码查询四六级准考证_四六级查准考证号的网站是什么
- php退款系统设计思路,关于退款的10篇文章推荐
- 移动硬盘识别为本地硬盘_如果仅在硬盘已经旋转时才能识别硬盘,该怎么办?
- 背光的工作原理及结构
- 数学 计算机 生物学,数据:中国高校数学、物理、化学、生物、计算机5大学科实力排名!...
热门文章
- 《Conditional BERT Contextual Augmentation》论文笔记
- 计算机播放音乐没声音为什么,电脑没声音是怎么回事?教你怎么修复
- 关于注册苹果开发者账号时登录遇到的提示未知错误
- 服务器怎么在线播放flv视频,服务器无法播放flv文件
- Pandas的列表值处理技巧,避免过多循环加快处理速度
- 《常用控制电路》学习笔记——数控直流恒流源电路
- Luat合宙ESP32C3教程-点亮ST7735驱动1.8寸TFT液晶屏
- python中shift函数_Pandas Shift函数的基础入门学习笔记
- wav音乐里面竟然有病毒?
- HTML5个人学习笔记(一)