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

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

3天内不再提示

基于FPGA的图像边缘检测设计

FPGA技术江湖 来源:FPGA技术江湖 2025-02-10 11:30 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

今天给大侠带来基于 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

ee3c4c14-e741-11ef-9310-92fbcf53809c.jpg

2、Create a new custom megafuction variation

ee53748e-e741-11ef-9310-92fbcf53809c.png

3、Memory Compier -> ROM -> Verilog HDL -> 自定义名称

ee5e8fe0-e741-11ef-9310-92fbcf53809c.png

ee6d2d48-e741-11ef-9310-92fbcf53809c.png

ee8659e4-e741-11ef-9310-92fbcf53809c.png

ee9581f8-e741-11ef-9310-92fbcf53809c.png

eea49bca-e741-11ef-9310-92fbcf53809c.png

仿真注意问题:

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颜色值:

http://tool.chinaz.com/tools/selectcolor.aspx

eebfe01a-e741-11ef-9310-92fbcf53809c.png

此次采用是浮点算法来实现灰度图的,我的图片数据是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)begin
    if(rst_n==1'b0)begin
       red_r1   <= 0 ;  
       green_r1 <= 0 ;
       blue_r1  <= 0 ;
    end
    else begin
       red_r1   <= red   * 77 ;        //放大后的值
       green_r1 <= green * 150;
       blue_r1  <= blue  * 29 ;
    end
end


always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        Gray <= 0;    // 三个数之和
    end
    else begin
        Gray <= red_r1 + green_r1 + blue_r1;        
    end
end


always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
       post_data_in <= 0;  //输出的灰度数据
    end
    else begin
       post_data_in <= { Gray[13:9], Gray[13:8], Gray[13:9] };//将Gray值赋值给RGB三个通道
    end
end
四、均值滤波 均值滤波的原理 做图像处理,“把每个像素都用周围的8个像素来做均值操作 ”, 比如:

eecee6be-e741-11ef-9310-92fbcf53809c.png

图通常是最能说明问题的东西, 非常明显的, 这个3*3区域像素的颜色值分别是5,3,6,2,1,9,8,4,7那么中间的1这个像素的过滤后的值就是这些值的平均值, 也就是前面的计算方法:(5+3+6+2+1+9+8+4+7)/9=5 一目了然。那么这个均值滤波有什么用处呢?主要还是平滑图像的用处, 有的图像的锐度很高,用这样的均值算法,可以把锐度降低。使得图像看上去更加自然,下面就有几幅图我们可以看出一些端倪: 原图:

eee784f8-e741-11ef-9310-92fbcf53809c.jpg

平滑处理后:

eefb6f0e-e741-11ef-9310-92fbcf53809c.jpg

这里还是可以明显的感觉到不同的, 没有好坏之分,就是第二幅图片看上去更为平滑。继续我们的问题, 那这里均值平滑是否具有去除噪声的功能呢?我们搞来了椒盐噪声(就是随机的白点,黑点)来试试手:

噪声图(5%):

ef075760-e741-11ef-9310-92fbcf53809c.jpg

平滑处理之后:

ef17efee-e741-11ef-9310-92fbcf53809c.jpg

首先这里的噪声还是比较小的, 只有5%,从均值的效果来看的话, 我可以说几乎没有用,其实直观的想也可以判断, 因为这里的处理并没有剔除这些噪声点, 而只是微弱地降低了噪声,所以效果可以想见的。最后的时候还是贴上一段处理的代码:

voidmeanFilter(unsignedchar*corrupted,unsignedchar*smooth,intwidth,intheight)
{


  memcpy ( smooth, corrupted, width*height*sizeof(unsigned char) );


  for (int j=1;j

简单的从1...width-1来处理, 所以第一个和最后一个像素就简单的抛掉了, 如果只是简单的看看效果还是没有问题的。

如何生成 3*3 的像素阵列。可以利用 ip 核生成移位寄存器 ,方法与 ip 核生成 rom 一样,详情见ip 核 生成 rom操作。

ef2688ce-e741-11ef-9310-92fbcf53809c.png

仿真波形如下 row_1 , row_2 , row_3 是指图像的第一、二、三行的数据,Per_href 是行有效信号(受VGA时序的启发,从 rom 中读取数据时设计了行有效和场有效的控制信号,事半功倍,有了利于仿真查错和数据的控制)。从 3 开始就出现了3*3 的像素阵列,这时候就可以求取周围 8 个像素点的平均值,进行均值滤波。

ef32ab2c-e741-11ef-9310-92fbcf53809c.png

下面这个图表示的是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

ef47aefa-e741-11ef-9310-92fbcf53809c.png

核心代码如下:

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)begin
    if(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};
    end
    else  begin
     if(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};
     end
     else 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}
     end
   end
end


always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        mean_value_add1<=0;
        mean_value_add2<=0;
        mean_value_add3<=0;
    end
    else if(per_href_ff1)begin
        mean_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
end


wire [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分别代表经横向及纵向边缘检测的图像,其公式如下:

ef5f8872-e741-11ef-9310-92fbcf53809c.png

图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小。 ef7cd30a-e741-11ef-9310-92fbcf53809c.png  如果梯度G大于某一阀值则认为该点(x,y)为边缘点。 用的是边缘检测算法。 难点: (1)掌握了 3*3 像素阵列,Gx 与 Gy 就很好计算了。 注意问题:为了避免计算过程中出现负值,所以将正负值分开单独计算,具体见代码) (2)G的计算需要开平方,如何进行开平方运算 Quartus ii 提供了开平方 ip 核,因此我们直接调用就好了 。

ef8fa7aa-e741-11ef-9310-92fbcf53809c.jpg

代码如下:

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)begin
    if(rst_n==1'b0)begin
       p_x_data <=0;
       n_x_data <=0;
       gx_data   <=0;
    end
    else 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 ; 
    end
    else begin
         p_x_data<=0;
         n_x_data<=0;
         gx_data <=0;
    end  
end


always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
       p_y_data <=0;
       n_y_data <=0;
       gy_data   <=0;
    end
    else if(per_href_ff1==1) begin
        p_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 ; 
    end
    else begin
        p_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)begin
    if(rst_n==1'b0)begin
        gxy<=0;
    end
    else begin
        gxy<= gy_data* gy_data + gx_data* gx_data ;
    end
end


wire [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)begin
    if(rst_n==1'b0)begin
        post_y_data_r<=16'h00;
    end
    else if(squart_out>=threshold)
         post_y_data_r<=16'h00  ;
    else
         post_y_data_r<=16'hffff  ;
   
end

六、图片的显示

本来是想用 VGA 来显示图片的,由于条件的限制没能实现,最终只能将处理完的数据输出保存在 .txt 文件中,然后借助网页进行显示。 难点: (1) 如何将数据流输出保存到 .txt 文件中。 (2) 网页的使用及注意事项。 在testbench里加入下面所示代码即可将图片数据保存到 .txt 文本。

代码如下:

     integer w_file;  
     initial
     w_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

efac2362-e741-11ef-9310-92fbcf53809c.png

注意:由于此网站是量身定做的,所以只能显示数据格式为RGB565的16位二进制的数才能正确显示,注意不能有分号,正确格式示例如下,必须严格遵守。

efba6d78-e741-11ef-9310-92fbcf53809c.png

七、结果展示

efcccc48-e741-11ef-9310-92fbcf53809c.jpg

小结:均值滤波处理后的图片有明显的黑边,产生这一现象的原因就是生成 3*3 像素矩阵和取像素值时数据有损失造成的,但是这也是可以优化的,后续我会继续努力不断完善。本次只是简单对一幅图像进行边缘检测,我的后续目标是实现图片的实时处理,这又需要学习很多东西了,SDRAM、摄像头驱动等等等,越学习越发现自己知道的实在是太少了,永远在路上,学无止境。希望我的分享能够帮助一些和我一样热爱 FPGA 图像处理的朋友。 efdd8ccc-e741-11ef-9310-92fbcf53809c.png

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

    关注

    1656

    文章

    22291

    浏览量

    630401
  • 边缘检测
    +关注

    关注

    0

    文章

    94

    浏览量

    18608

原文标题:基于 FPGA 的图像边缘检测系统设计(sobel算法)

文章出处:【微信号:HXSLH1010101010,微信公众号:FPGA技术江湖】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    算法系列:基于 FPGA图像边缘检测系统设计(sobel算法)

    今天给大侠带来基于 FPGA图像边缘检测设计,话不多说,上货。 设计流程如下:mif文件的制作→ 调用 ip 核生成rom以及仿真注意问题→ 灰度处理→ 均值滤波:重点是3*3
    发表于 03-26 16:40

    基于FPGA的实时边缘检测系统设计,Sobel图像边缘检测FPGA图像处理

    摘要 :本文设计了一种 基于 FPGA 的实时边缘检测系统 ,使用OV5640 摄像头模块获取实时的视频图像数据,提取图像
    发表于 05-24 07:45

    基于FPGA的数字图像处理中的边缘检测系统

    `基于FPGA的数字图像处理领域的边缘检测系统。该系统实现了从24位真彩色图片的存储到VGA显示边缘信息。`
    发表于 06-26 13:36

    本科生毕设想做基于FPGA图像边缘检测,用Verilog实现。各位大神给些指导意见啊!!!

    现在大四,面临毕设选题!初步定做基于FPGA图像处理;之前有接触过图像边缘这方面,但做的很烂!现在想当成毕设来做,大神们有没有什么指导意见!!!(毕设只是一部分,还是想从中能学到东西
    发表于 11-10 11:22

    本科毕业设计要做FPGA图像边缘检测算法研究,求各位大神告知需要准备哪些知识

    小弟大四,还在准备考研复试,所以毕业设计到现在才开始准备,还是为了在面试时问起毕业设计可以有话说,当然还是想好好准备毕业设计,想好好学点东西。因为我本科是机械专业,所以对FPGA不是特别了解,想知道需要准备哪方面的知识,看哪些书?在线等回复,谢谢各位大神!
    发表于 03-07 18:49

    基于FPGA图像边缘检测系统设计,用VHDL语言实现该怎么做?

    不知道有没有大神做过:基于FPGA图像边缘检测系统设计,用VHDL语言实现
    发表于 05-10 00:22

    如何利用FPGA实现Laplacian图像边缘检测器的研究?

    图形处理领域,图像处理的速度一直是一个很难突破的设计瓶颈。这里通过研究图像边缘检测器的FPGA实现,来探讨如何利用
    发表于 07-31 06:38

    FPGA学习案例分享】基于FPGA图像边缘检测例程

    ` 本项目利用MP801开发板,通过摄像头采集图像数据,然后在屏幕上显示两种图像:屏幕有一个圆,圆内显示经过了边缘处理的图像,而圆外则显示原始图像
    发表于 11-29 09:52

    请问有图像边缘检测的代码及仿真结果吗?

    基于FPGA图像边缘检测 的相关代码和仿真图 谢谢各位大神。
    发表于 03-31 02:25

    算法系列:基于 FPGA图像边缘检测系统设计(sobel算法)

    发表于 11-22 11:05

    基于FPGA的实时图像边缘检测系统设计(附代码)

    今天给大侠带来基于FPGA的实时图像边缘检测系统设计,由于篇幅较长,分三篇。今天带来第一篇,上篇,话不多说,上货。 这里也超链接了中篇和下篇,方便各位大侠参考学习。基于
    发表于 06-21 18:47

    基于FPGA图像边缘检测

    基于FPGA图像边缘检测 引言     图像边缘
    发表于 01-14 11:07 2125次阅读
    基于<b class='flag-5'>FPGA</b>的<b class='flag-5'>图像</b><b class='flag-5'>边缘</b><b class='flag-5'>检测</b>

    Prewitt图像边缘检测边缘细化的FPGA实现

    摘要! 针对实时图像处理的要求! 使用FPGA图像数据流进行在线PREWITT边缘检测 针对传 统算法需要人工给定阈值和产生的
    发表于 03-29 16:30 46次下载
    Prewitt<b class='flag-5'>图像</b><b class='flag-5'>边缘</b><b class='flag-5'>检测</b>及<b class='flag-5'>边缘</b>细化的<b class='flag-5'>FPGA</b>实现

    实时图像边缘检测的设计及FPGA实现

    文中将FPGA应用于实时图像边缘检测系统,从而实现动态实时图像边缘
    发表于 12-22 17:06 39次下载
    实时<b class='flag-5'>图像</b><b class='flag-5'>边缘</b><b class='flag-5'>检测</b>的设计及<b class='flag-5'>FPGA</b>实现

    数字图像边缘检测FPGA实现

    数字图像边缘检测FPGA实现......
    发表于 01-04 15:31 18次下载