找回密码
 注册
关于网站域名变更的通知
查看: 476|回复: 1
打印 上一主题 下一主题

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

[复制链接]

该用户从未签到

跳转到指定楼层
1#
 楼主| 发表于 2024-3-26 16:45 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x

今天给大侠带来基于 FPGA 的图像边缘检测设计,话不多说,上货。


& K+ P/ |. T% X; R3 X9 ~

设计流程如下:mif文件的制作→ 调用 ip 核生成rom以及仿真注意问题→ 灰度处理→ 均值滤波:重点是3*3 像素阵列的生成→ sobel边缘检测→ 图片的显示→ 结果展示 。

# k( \5 j0 F, U/ f5 A

4 d* J' z2 M. G, d/ K3 u1 ~5 j
一、mif文件的制作7 W: R! F4 |; o( O8 v. c  j

6 K9 _% E* t3 x' X

- T4 h1 }$ Y4 z       受资源限制,将图片像素定为 160 * 120,将图片数据制成 mif 文件,对 rom ip 核进行初始化。mif文件的制作方法网上有好多办法,因此就不再叙述了,重点说mif文件的格式。& O$ l- D( r( h% K- S

# s. e4 a/ W: X5 I. q& w, j
% T1 J$ e# o- \* {: C
mif文件的格式为:
, I2 s' ]3 f% ~8 w" z% c

( ?; W/ @0 Y+ w/ ]WIDTH=16 ;    //数据位宽

$ j9 o6 A4 k' YDEPTH=19200 ;   // rom 深度即图片像素点的个数
, M: W# @2 R7 k2 q0 j% F$ aADDRESS_RADIX=UNS ;   //地址数据格式: V4 ~7 e+ N) G5 ~% Z9 s$ Y- Y
DATA_RADIX=BIN ;   //数据格式% \. K; a5 P8 O" V* Q( G; }
CONTENT8 T- E  i; S) J8 W$ x- k
BEGIN
. F! Y; p! d+ h  h5 a0:1010110011010000 ;     // 地址 :数据 ;注意格式要和上面定义的保持统一
$ n. E. q$ i3 o/ N1 E1:1010110011010000 ;* r' p) r$ ]5 n: i  [8 y5 E* H
2:1010010010110000 ;2 L/ l* l" y0 v; Y3 b
......
& Q/ {% E" W7 t# m1 x19198:1110011011111001 ;
" X8 C1 V! o7 v19199:1110011011011000 ;
, D# N: s2 j& `( N7 @3 I- O) z* tEND;0 N+ o6 D4 a2 H# `
6 f! V0 r( X# V8 c
% W# {( B3 v2 ^

二、ip 核生成 rom 及仿真时需要注意的问题

ip 核生成 rom

1、Tools -> MegaWizard Plug-In Manager

- y/ n% O* B% ]3 \- j% I

  \. c% @. g/ [; e( ?
% X1 O3 v" e" _$ c* N  A" i

2、Create a new custom megafuction variation


) G, W8 A: Q# k' ?: J, j3 x1 R


9 G' e. \/ P- `7 V" q! o; s. C* j( P; U. P

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

" |$ Q: u; }% D. Z& I$ V: N


' h6 J, e& s+ H7 ~$ f; b$ t/ @9 f( v# X3 q! B: f  P

: i  I0 S* ?1 [- C6 x% B
/ m8 R9 |, v4 _


+ w. h' z: ~2 i+ {- `
9 X0 m) b# q4 p0 h( L0 g" T4 Z' y

0 Y# |4 C: q! z4 ^. m% I
! V( S+ G) w5 e- {; M# O


7 [7 e0 a. w- }' A. |2 r  E1 b9 L& l* q, f4 l' P9 k! ~8 t0 m' R  g
仿真注意问题:
% C* c' ^. p) v# E3 K
" [' T1 M- [4 O6 h
1、仿真时要注意是否有 altera_mf 库文件,否则会报错。' A( P* O0 D. Y- X) ~+ \
Module 'altsyncram' is not define- s8 a& C; ?/ O3 B0 V2 V% c/ Y7 @" f
解决方案:4 _7 B) h/ @* l4 ]
(1).下载 altera_mf 库文件;8 i$ K( w8 Y! Q& O9 `; T" z( Y
- p4 P  Z* o& j5 u
(2). 仿真时将 altera_mf.v 与其他文件一起加入到 project 中。

7 K: l% N8 d* l" f- k
! S0 a( h/ r9 q9 r' k

0 F) C% ~- x: @7 N, a2、要将 .mif 文件放在仿真工程目录下,即与 .mpf 文件在一起,否则将不会有数据输出。& `% J; \4 R1 X$ f1 m/ e( P3 {& _

; J7 K5 @% n- o+ j三、灰度处理
4 S+ b+ b! l- P% m1 m
        任何颜色都由红、绿、蓝三原色组成,假如原来某点的颜色为( R,G,B )那么,我们可以通过下面几种方法,将其转换为灰度:# m* E# P$ F% I! J" H
; f+ E% e  b5 ~( ?+ [0 j
  • 浮点算法:Gray=0.299R+0.587G+0.114B
  • 平均值法:Gray=(R+G+B)/3;
  • 仅取单色(如绿色):Gray=G;
    ( O6 \7 I; e8 H8 M% z
        将计算出来的Gray值同时赋值给 RGB 三个通道即RGB为(Gray,Gray,Gray),此时显示的就是灰度图。通过观察调色板就能看明了。 通过观察可知,当RGB三个通道的值相同时即为灰色,Gray的值越大,颜色越接近白色,反之越接近黑色(这是我自己的理解,不严谨错误之处请大神指正)。这是在线调色板网址,可以进去自己研究一下。
% [) g9 _0 R* T( a% M( N; c" g# y: \6 X7 P7 G( A

站长工具颜色代码查询、RGB颜色值:

; m: b/ g" D& @6 ^
1 {; @4 `. {! N6 h5 u

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

$ h* ]% ]( w2 W* e9 A


7 j) ^' B  g; U
: |# u0 _" ?: c# Z6 A: l0 K9 W" K8 O
        此次采用是浮点算法来实现灰度图的,我的图片数据是RGB565 格式 ,难点: 如何进行浮点运算。思路:先将数据放大,然后再缩小。; S; j2 l0 z- N+ b

4 y4 C! m8 b7 k( ^% @

( L% Q$ L, m7 I7 E例如:
3 |$ ]( k6 W/ O1 s
$ @5 z( P8 v% S: ~% I8 c
5 @: y# b( e' E. M4 V4 |. K
Gray=0.299R+0.587G+0.114B转化为 Gray=(77R+150G+29B)>>8 即可,这里有一个技巧,若 a 为 16 位即 a [15:0],那么 a>>8 与 a [15:8]是一样的。0 r* M% T  w- k+ j  u" i. O

/ [% A- T4 m) V) d% u

. u+ e) q0 c1 v8 m核心代码如下:

* s$ R& _. I. m. H4 f9 L7 R$ f
+ ^1 S. o/ b( w. }* }always  @(posedge clk or negedge rst_n)begin   

. o; f$ e: A& {  ~; {1 _( a- L; v3 O3 o& k3 M
( b! C6 `* m( g% n' ^- W, l
        if(rst_n==1'b0)begin
; f1 _! _9 S; O( b( v# Y          red_r1   <= 0 ;         
9 z2 ]4 H6 s" D( Q( V( u0 i( _          green_r1 <= 0 ;      6 p+ w% o5 a8 z& o3 E4 w! R  t
          blue_r1  <= 0 ;   
: u% Q1 H% e+ E' W: C% G* N/ u       end   
: V2 l% F, `: Q) e" s. K       else begin      
7 x5 |. U9 s% W       red_r1   <= red   * 77 ;        //放大后的值      
. J% l* h3 h' ]# {, _       green_r1 <= green * 150;      9 w  K+ e3 m5 y: T1 }9 Z3 G
       blue_r1  <= blue  * 29 ;   
# E; Y+ O$ e; l( ]8 |% k! E       end5 o2 w! C: ~9 e
end
& U2 W0 j) U2 h5 [/ a# Z" W  V6 @; U

( z% a1 Y- G- a" w) k. C9 p
8 I7 D# N- j% Jalways  @(posedge clk or negedge rst_n)begin   
, c" O0 L' k6 u: l* D
       if(rst_n==1'b0)begin              
( c6 S3 p& b( B2 d* j2 {               Gray <= 0;    // 三个数之和   0 v0 {) l" [+ I- d  r$ o
       end   ' y  W: ^3 t& ^" \; b1 ~; J( k8 F! H
       else begin        - g) X' a5 o0 d
               Gray <= red_r1 + green_r1 + blue_r1;) ?" e. `. {- @0 t5 h5 p
       end" X0 M* m' ], Y! q" P5 t
end
, ?5 h/ v( P; B4 f6 M3 [# L+ k  p1 A, [6 Y$ l( G/ ]" J7 a/ l/ C$ G
, K+ a  ~" ^6 c( O0 `0 l/ Z' M
always  @(posedge clk or negedge rst_n)begin   9 i( D( }8 f9 [4 b- {
       if(rst_n==1'b0)begin      
( X( c: T: ^7 @; A2 o) K       post_data_in <= 0;  //输出的灰度数据   
4 M0 d0 A# Q) |3 }/ n       end   4 l! f( \; d: @6 y# d6 @
       else begin      8 q9 a7 P9 K+ ]
              post_data_in <= { Gray[13:9], Gray[13:8], Gray[13:9] };//将Gray值赋值给RGB三个通道   
" V! |/ e. x3 R/ \# L       end% E9 D/ T/ D, z0 |  W. h- O
end
- ]! K2 Z9 y8 E9 X
* m# N$ S9 H) U. c. q9 h& b) S
; U7 j4 ^9 x. l& q4 l: I. i
# U) k+ g) O7 ^! o% r% R' J1 G
; K( ~. {0 `, s4 ^% O& E

6 d( j' ?7 w+ E. p四、均值滤波
5 P/ O# f3 A0 P; j4 V* N. @
均值滤波的原理做图像处理, “把每个像素都用周围的8个像素来做均值操作 ”, 比如:
' [  A" x: m; @3 a% E8 l( O9 u; Y8 G
( ~% M& {4 d- a( \6 I7 |

! X( P7 G" h' x6 D. e+ b( h( q4 f# M# [  B3 t. y
. E& F* @! u" N& f( j
        图通常是最能说明问题的东西, 非常明显的, 这个3*3区域像素的颜色值分别是5,3,6,2,1,9,8,4,7那么中间的1这个像素的过滤后的值就是这些值的平均值, 也就是前面的计算方法:(5+3+6+2+1+9+8+4+7)/9=5
5 e# x5 N! ?! G5 q  T. D1 j  O: \! s9 }
+ r: t, E4 ], R- i- [! U
       一目了然。那么这个均值滤波有什么用处呢?主要还是平滑图像的用处, 有的图像的锐度很高,用这样的均值算法,可以把锐度降低。使得图像看上去更加自然,下面就有几幅图我们可以看出一些端倪:原图:  8 D3 b7 y: L3 X: Z9 S$ a7 Z
               6 j: @9 Q$ [$ v3 C. A9 W
2 J* H* q  c1 J" b* }, ]
2 Q7 q: w+ n, ]1 a
# D; J1 `8 c$ H6 _5 a, i
平滑处理后:
) c, C! x/ `* \7 f
/ p$ Z6 F$ f7 a* c8 ^

  z, k& I0 Q" e) n8 G% F1 C" c, T# @- D% C5 @& ]

- p7 J6 ?0 m1 ]& {7 B1 |: j
7 C, T/ a* c2 P( H& i/ T
; e0 n& c& h# K7 g9 |) B. {) g

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

: L3 J/ D! e: C; B' C6 {6 j8 k
噪声图(5%):

* W6 n. o# \/ y2 |+ J; {* y2 {! S: l! I- S8 }

- O9 D2 U) W5 x& h) u

2 p7 J6 K1 _2 i0 o
/ B; M, `  h& s9 [1 k, d平滑处理之后:
$ t% w1 l* O) G4 Z

; v* F0 T& @# y" a/ Q( L9 Y, c5 ]/ p2 \* N" X
9 V* P* |; p; Q/ I! t
: [, N6 {  E  h1 M5 ^6 a$ {& F
        首先这里的噪声还是比较小的, 只有5%,从均值的效果来看的话, 我可以说几乎没有用,其实直观的想也可以判断, 因为这里的处理并没有剔除这些噪声点, 而只是微弱地降低了噪声,所以效果可以想见的。 最后的时候还是贴上一段处理的代码:+ C' e' D. @+ Q7 _
& E& z9 r6 d* w2 s$ r3 ?8 R8 m/ R
void meanFilter (unsigned char* corrupted, unsigned char* smooth, int width, int height)
2 B* T  B6 W6 @7 ]5 r
{2 m* Q8 I6 L# L. V7 ^9 r- T- n
7 ^  @. y% S2 p+ k) a, |7 V
  mEMCpy ( smooth, corrupted, width*height*sizeof(unsigned char) );

1 }3 a$ l( Q8 S0 d4 z  _1 B/ D( W" D9 U2 d+ L; l, ~$ @6 }

6 ~# Z1 w; Z1 K3 Y0 a3 P4 ?& t7 i2 Y0 W
  for (int j=1;j<height-1;j++)  
: u( X5 E5 L: B  r+ w
       {   : k# E' x+ q* @8 G" ?4 @: U
          for (int i=1;i<width-1;i++)   3 R7 Z7 y! i7 l+ S* e! e
          {      
* H9 z! w2 z- |: ^# _           smooth [ j*width+i ] = (  corrupted [ (j-1)*width+(i-1) ] + corrupted [ (j-1)*width+i] + corrupted [ (j-1)*width+(i+1) ] +% i0 x- M, w; J5 j9 @
                    
, [$ t6 R9 [, ~0 b9 O     corrupted [ j*width+(i-1) ]    + corrupted [ j*width+i]   + corrupted [ j*width+(i+1) ] +% Q- \1 v; G- {7 S
     corrupted [ (j+1)*width+(i-1) ] + corrupted [ (j+1)*width+i] + corrupted [ (j+1)*width+(i+1) ] ) / 9;   4 R3 m3 ~* |0 m  Q! M

1 D& m: u* @! |# [
1 O- K5 B; [. d2 K8 m
            }  
; y* I+ y: o- o( j        }
% m) G2 {; S  ]# ]2 l. g- j3 B     }
6 }" M  U3 i* b8 D% z5 I" ?. c5 `" q; q* X

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

6 ^( O0 O& c. B9 |: D  |7 A4 Q
如何生成 3*3 的像素阵列。可以利用 ip 核生成移位寄存器 ,方法与 ip 核生成 rom 一样,详情见 ip 核 生成 rom 操作 。

4 K4 h1 n0 k5 r+ ~% m2 J! a- G! |+ t! K7 z: J7 G
5 c+ ?4 e  C1 ?5 L$ h
- p9 y0 V4 W1 U5 H. [. L" g- K8 P4 A1 N
8 `9 [/ e9 I2 G/ v  i9 U, |" L; H2 m
        仿真波形如下 row_1 , row_2 , row_3 是指图像的第一、二、三行的数据,Per_href 是行有效信号(受VGA时序的启发,从 rom 中读取数据时设计了行有效和场有效的控制信号,事半功倍,有了利于仿真查错和数据的控制)。从 3 开始就出现了3*3 的像素阵列,这时候就可以求取周围 8 个像素点的平均值,进行均值滤波。
2 n. }8 U/ B- @. d( h, `& g- a1 w. D' q: T3 U( J, I9 v

4 j" w0 x: E, V0 z. z# D' C% ~
- m* ~' g# B6 |, D" `; F

% J6 f3 c4 x+ c
) T  a# e6 y- q  W7 k+ t* i
        下面这个图表示的是FPGA 如何将矩阵数据处理成并行的像素点,可以结合下面的代码好好理解,这也是精华所在。
: _; r, K+ Q( U/ `$ E5 q) c% M2 K- }2 D+ @/ q* I6 T- {8 J2 _
( m  c" E, {+ w1 K8 U; Q! a/ V1 P" _
       正方形红框框起来的是第一个完整的 3*3 矩阵,长方形红框框起来的是并行的像素点,在此基础上就可以求得平均值,进行均值滤波。
. C0 m3 N# L# K
4 \* C- i4 K/ Y$ B- [7 P

# Y: v# I; s, A, g( d9 q. X从下图也能看到 3*3 矩阵从左往右滑动。) e1 v, j! J  }

1 b" r/ w# c  ?5 c$ @

7 d6 d. @. ?$ W+ e第一个3*3 阵列。
3 ]' y9 |4 {) z0 i0 {/ T
* w  L3 v1 \( f' n

% T: F: ^6 r6 x0  1  2   -- >  p11 p12 p13
$ T/ X/ s+ t9 e3  4  5   -- >  p21 p22 p23
+ ?' m9 z8 c7 k  y9 b6  7  8   -- >  p31 p32 p33' V% {4 Z& N9 o: m
: i8 L6 D  ?+ @: J" v
& l& a' m( N, c
. p3 F& M6 H: x3 H% O; M
核心代码如下:+ h# S2 k8 q/ O+ ?) A- b
7 j2 U9 Q+ k$ w. f- ?' |

6 G8 J% }! P7 E3 X0 ~
" E% b9 o& D8 h- m
& s7 Y% p- @' m$ Freg [5:0]p_11,p_12,p_13;  // 3 * 3 卷积核中的像素点

, W9 P* V7 T* X7 `' Z( G7 ]( J5 Wreg [5:0]p_21,p_22,p_23;
7 j+ A9 }, K& U, O# Ureg [5:0]p_31,p_32,p_33;
0 `  C5 ^5 C. r* G# s+ U% Y* Wreg [8:0]mean_value_add1,mean_value_add2,mean_value_add3;//每一行之和6 J6 g! p3 [8 u7 |9 i

5 G* L# N0 k4 ?: f% r
+ T4 T3 q, @9 y: q  X8 u

0 I9 ?( |: n0 Ualways  @(posedge clk or negedge rst_n)begin

/ x. M: M$ W3 s& n7 ?   0 \4 W- k! H" o$ V" b
       if(rst_n==1'b0)begin        
* L6 `( {' E1 B* G. {% g  Z           {p_11,p_12,p_13} <= {5'b0,5'b0,5'b0}   ;        
3 R5 u9 C* N2 n  ]9 }% y           {p_21,p_22,p_23} <= {15'b0,15'b0,15'b0};        : k' q, X1 c  G9 u4 ~" m$ x' P
          {p_31,p_32,p_33} <= {15'b0,15'b0,15'b0};   $ i5 T2 A, b/ A6 b+ i# b
      
2 p. G5 c; h3 y  Y$ O. C
4 L1 ?- X* N8 \( d, c, e" S, N% ]* J# d
# N" Z$ u9 s4 C! P
         end   
5 ^+ ]! l, _  d" e+ X" {/ h       else  begin     
( G& W) @; L  |0 C       if(per_href_ff0==1&&flag_do==1)begin, g3 ~# ^  i  C5 B0 U/ I+ |
        {p_11,p_12,p_13}<={p_12,p_13,row_1};; v$ R' D5 ]3 F: x. M7 _( l
        {p_21,p_22,p_23}<={p_22,p_23,row_2};
% ~! S4 d8 u- P5 I1 J4 k+ t        {p_31,p_32,p_33}<={p_32,p_33,row_3};0 h% o% N( O9 h/ V0 W
   
* a5 R( a2 G3 o4 b# O4 m& u     end2 z# m! {6 R' S4 E- J) W6 w+ A! f
     else begin
7 l( G, i. V7 j! T  V            {p_11,p_12,p_13}<={5'b0,5'b0,5'b0};
0 J8 G4 l" X0 r            {p_21,p_22,p_23}<={5'b0,5'b0,5'b0}
- ], j" |/ H4 b" m- s            {p_31,p_32,p_33}<={5'b0,5'b0,5'b0}     6 _' n' b/ D# e! x5 U

- ~0 [7 k( u; w5 A1 B, @9 c
/ c9 N  P: U9 Z8 B3 ^7 v' T3 _
       end* X- Q4 H! p- I% w
   
( {8 L& B" Y7 N& \+ T: ?: N    end
$ h8 ]1 s" N% J- I/ I  i
5 i/ N* O' M0 `
# V0 J2 v4 Z. [  R0 @  ]) k
end
( p. V- s4 P1 P# i5 ?* W
! i( l% I  b" ^* F  c4 X, c# Z$ K

" H9 z1 H) E  ?/ Z3 ]+ u5 W* p& B# ?  F0 p* e3 W

7 y% u$ M0 X; V" u! l8 ~always  @(posedge clk or negedge rst_n)begin! t0 y+ @4 k5 I+ t0 N9 p
    if(rst_n==1'b0)begin! u  C$ j4 ^* S9 V! t  @/ `
        mean_value_add1<=0;
, B, Z, X( h; m# K; K6 }        mean_value_add2<=0;# h9 c2 G+ M9 g+ \. E0 k; d& m
        mean_value_add3<=0;
( T. j) a) D5 W% C; m. x" h0 \: y2 t# v7 D
5 I+ w4 v5 o6 i& [1 o( g% Q  I+ _
    end% j4 T- q6 _9 H, C+ k3 k- k
    else if(per_href_ff1)begin5 A/ W$ t* ?" u2 D+ r7 i
        mean_value_add1<=p_11+p_12+p_13;
- }! r* h, v) R7 }. F        mean_value_add2<=p_21+   0   +p_23;
; v7 w* e5 v6 V, M$ u2 A) I/ n0 |        mean_value_add3<=p_31+p_32+p_33;
) B- s6 c' V5 \5 n% r    end
9 k& J, o) H3 S! C6 }7 Jend, P" N9 c- H- a* _+ t& A3 p

& X1 |& L5 l8 i

4 F4 i2 Q) o& q0 N1 b
* c4 R. q8 m  M" F) a  F6 X3 Nwire [8:0]mean_value;//8位数之和

2 h. a. V6 t- Z1 Rwire [5:0]fin_y_data; //平均数,除以8,相当于左移三位。
* G! P4 M5 }: R1 M
# A0 p/ j; ?5 F

2 i! ?) k" K4 b$ [8 R9 R/ C. T) R8 h9 g
assign mean_value=mean_value_add1+mean_value_add2+mean_value_add3;

  H# w& P, V, a4 {/ L  eassign fin_y_data=mean_value[8:3];
$ G, _* a1 V8 Q! v+ H6 R7 e. d
五、sobel 边缘检测

- ?5 o$ [  G2 y  b9 X1 I# |# s7 R- E" W
边缘检测的原理
/ t$ X; p' M! Y2 F: B+ i5 M7 e" X6 T# c3 V0 t# O) x
. u) J( q2 Y+ k0 [7 g5 G, E
该算子包含两组 3x3 的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。A代表原始图像的 3*3 像素阵列,Gx及Gy分别代表经横向及纵向边缘检测的图像,其公式如下:
) l! h# S8 W1 J' N1 e* O7 o1 {" C* e) V, `" U  I1 |

# y0 }- m" g% E4 P, I; v$ F; \; W
  ^7 X7 u  C. y) {; Z) @6 [* P! {图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小。
/ I, S' f& ?, [/ r$ V& Q2 t1 ]
# J) F, o: R  @5 d, o# n
/ p! D: Y; a1 Z* _" Y" c* e8 [  u
如果梯度G大于某一阀值则认为该点(x,y)为边缘点。

# P7 e4 K- t! ]; T1 n
/ g5 W- H  x1 X  m% ^5 w& ^

1 W, j+ r. W. _' H用的是边缘检测算法。
& y9 n8 c6 {$ W, H- {" _+ G0 j5 v) {7 K8 f- M5 v, a" O3 V0 L4 V* ~$ y
/ i( v3 d# e# X! s2 m9 e
难点:9 H  G) F8 U8 E: f8 y- J

1 T  R; n1 R0 [' F! T
; P; d  S! ?8 D2 T( m* ~+ l" P/ O
(1)掌握了 3*3 像素阵列,Gx 与 Gy 就很好计算了。
- Y1 A$ C0 d0 H! \. L/ F  a8 ?5 p9 ^5 i, P. k5 \( E0 s
2 |# `' D) l8 R: X
注意问题:为了避免计算过程中出现负值,所以将正负值分开单独计算,具体见代码)1 J5 ?3 X2 Y& C5 s: W: P3 q
- M. L6 t5 {: S% a
; N, v5 X  e  {* i9 ?
(2)G的计算需要开平方,如何进行开平方运算Quartus ii 提供了开平方 ip 核,因此我们直接调用就好了 。
* ]8 R6 A2 }' @+ L; r8 ^: U% ~! j6 }% S- ?9 U, M" F# Z% ]* q! R/ L* s: g
) [% H8 l  S; K2 ~, B  d; \7 q
  k8 A9 U- F5 ]: Z* u& M. R
代码如下:
( b" i4 J5 e. z  I: {  H; k. D/ [6 \  W) `, h5 n
) y4 G% m6 O6 V" c7 H7 ?; N5 E( w  i
reg [8:0] p_x_data ,p_y_data ;  // x 和 y 的正值之和
, G( s/ |1 C0 C. }8 T5 M$ k
reg [8:0] n_x_data ,n_y_data ; // x 和 y 的负值之和
+ t/ _5 H$ L( }- I% o- _3 j' Xreg [8:0] gx_data  ,gy_data  ; //最终结果9 H9 H5 U9 W# t

- F) _% s4 D; e: F, Halways  @(posedge clk or negedge rst_n)begin
2 ]* a" [4 g" Z! [7 |" O  {
! j) l3 I6 U1 C2 v
+ H: l3 \5 H& D5 Q$ D$ {
    if(rst_n==1'b0)begin  e# W+ m  W( Z4 O
       p_x_data <=0;
& D* q6 u( j/ y% d( J" }6 t/ r       n_x_data <=0;
/ f2 f( C/ t3 ^3 \$ P- n) ~) t- [       gx_data   <=0;
& N* @, w2 m. P6 D8 L, ]9 [' K# j

7 {4 i& ?/ b2 o# d0 J# ]    end2 l8 k  F8 B  G! {: f/ ?

0 t4 D2 B' e+ Z" `. |/ r7 S7 [

; d, R% O# I5 {  Y( D    else if(per_href_ff1==1) begin
# ^' B& Y! C# j0 J6 N" F
9 h6 N; B) M! |1 q8 f
7 y  n4 P, H  y' X
         p_x_data <= p_13 + (p_23<<1) + p_33 ;
5 h8 F( J! x3 X0 a3 A        n_x_data <= p_11 + (p_12<<1 )+ p_13 ;
: F" t- M& T0 c- k7 @        gx_data   <= (p_x_data >=n_x_data)? p_x_data - n_x_data : n_x_data - p_x_data ;5 j4 H& f- D, H4 [$ A- A+ p

  g# g" U, _; R8 C3 ?1 b* C
8 _* ?/ s. X, e& H1 s1 o3 n
     end' G5 c$ |3 p: l1 _/ W! j
& n* x0 W& ^4 w/ ~; [, W) b

  v1 r8 L( c+ V4 k& a2 ~) x& |    else begin
+ q: S0 J- s  p- Q2 |) _. ?         p_x_data<=0;
9 j# G# o) [# J% Y4 h         n_x_data<=0;$ O; m! |8 i, Y( m
         gx_data <=0;
' z' }2 T& a5 E/ I; P) [. s    end
* C% L- r1 A! }2 rend) w, _; B/ T& T9 U4 O$ ]( }$ V
  J  T  n$ {. {3 j9 y& W
always  @(posedge clk or negedge rst_n)begin
5 v' e6 T+ u* z3 }& H3 v" E4 {
    if(rst_n==1'b0)begin
' x3 `  ?: J# N; j+ R; o3 E8 {       p_y_data <=0;
6 I+ c+ M! O, F& I! r; `) t       n_y_data <=0;
# y  R  A# Z6 X. `2 y: U# B       gy_data   <=0;
, ^$ r0 w; ]" f
& S& p+ w& c. n8 h
, v8 Y1 s' ^4 {2 v3 d7 V8 {
    end
0 M$ q! J# Q$ X6 f. K. C8 Q/ R* m   8 X7 a: }7 P  k
    else if(per_href_ff1==1) begin
4 }' \6 V+ j& D6 o- H        p_y_data <= p_11 + (p_12<<1) + p_13 ;6 l: ~6 P& Q7 O0 V: h3 W
        n_y_data <= p_31 + (p_32<<1) + p_33 ;
/ P( h" T# v9 C- }+ s" J& G        gy_data   <= (p_y_data >=n_y_data)? p_y_data - n_y_data : n_y_data - p_y_data ;     
0 k/ l3 r8 @* |
* b# k& G( Y- E% ]

1 p6 G. W' Z/ d0 a. ?1 W3 n) G       end   
' f; B& J  }6 t& F# ]0 q
# ^# s9 T4 h: ^! W% x
, S4 K5 s; e: a2 D
       else begin5 n5 J: j6 M" R8 T) m
        p_y_data <=0;/ [7 q7 [' L& B0 z0 L
        n_y_data <=0;
' Q  V7 f# @. \' O        gy_data   <=0;# _! a" |# g; \8 D4 x
       end
7 R3 b' k) i  H) Z. c$ _end2 ^& B( A5 a( y4 d2 R: v5 b* C" b

& z5 S% G% ^, q2 g//求平方和,调用ip核开平方
/ N* \: |; T- P* H) P% l
reg [16:0] gxy; // Gx 与 Gy 的平方和  l4 W# F; g0 @$ I* C
always  @(posedge clk or negedge rst_n)begin
" K5 }. H3 z5 }: ?7 o2 m    if(rst_n==1'b0)begin
* b. X' ^( U# ~+ W! x) S        gxy<=0;
% i, }+ n: Q" J7 M! j+ n, Y1 X' Q* `/ Y* y    end7 a* d  Y7 |5 P% K
    else begin: ]7 |' ~+ E- u& t. B9 l
        gxy<= gy_data* gy_data + gx_data* gx_data ;
8 k' _5 B# c: E9 X% s6 T    end0 [5 t. k8 ~! w4 m) t% i6 ^( l
end
& N4 |$ @1 ^1 S' a9 P3 _# C2 P8 ~& w- q: p% X6 w. B7 a% w
wire [8:0] squart_out ;
8 {! O3 l9 l* H% S
altsquart  u1_altsquart (     //例化开平方的ip核
$ w( @) O. L" m+ `3 A5 K    .radical (gxy),2 j0 a' t6 \& D
    .q       (squart_out),  //输出的结果' i! s6 n2 m* e$ c. R
    .remainder()
% f! C4 R; N% d1 `. i                       );# u  E8 |$ y  _' V+ ^2 M. [
* s# }8 D$ a- f/ `& [6 V' c

) Z+ e7 C4 I! m; F+ h# @# N
7 `! a- _" @0 S! d3 T0 g/ \//与阈值进行比较
) o6 Y: T* `3 g8 Y

0 R& ^* i$ n; p# q
. L4 t: ]$ [/ l* A5 U% g  C
reg [15:0] post_y_data_r;; ?% U1 z4 ^3 I; s: k2 r
always  @(posedge clk or negedge rst_n)begin- z. J, l* Q' t2 @
    if(rst_n==1'b0)begin
; u0 {3 i3 Q/ t7 a0 m/ ]8 }        post_y_data_r<=16'h00;
; L* s1 W& K2 \. q    end( @6 @. [- A6 {, X
    else if(squart_out>=threshold)
; o. o4 l7 e* [+ t# @! V         post_y_data_r<=16'h00  ;& E/ U% k: X3 D0 H
    else0 e# z8 v6 I8 u$ f9 M  [
         post_y_data_r<=16'hffff  ;! c, k4 U& \7 i
   - {7 F3 D3 Z9 [+ V, t! T$ |
end) g4 Z0 z7 o  B( K" _3 G" O
  k4 T% t2 T: a$ E
六、图片的显示

9 m0 U  \7 r/ }5 k; l& x; _/ q% N
) J# O; |5 u2 D3 k/ b/ r
       本来是想用 VGA 来显示图片的,由于条件的限制没能实现,最终只能将处理完的数据输出保存在 .txt 文件中,然后借助网页进行显示。: ?) q1 d* B' E9 N

% l0 s* |) O4 [9 v/ D

& u- a' N1 T/ y# @7 a4 e. j难点:
1 F2 C/ i3 Y4 @4 L) g" W) ^- D2 o' k8 o& m1 U2 b) ^9 y

* p+ r2 j2 n  ?(1) 如何将数据流输出保存到 .txt 文件中。
/ `: R* G- F; t) m6 v% z* N0 d  F2 C5 K' m# b
! ?" e; c: N* V
(2) 网页的使用及注意事项。在testbench里加入下面所示代码即可将图片数据保存到 .txt 文本。
8 W6 m# O" J. f# E; s4 b. v
5 J) t* }1 a/ T; K# u' y, f9 M5 {
# @; Q" q" O$ ~# t7 K

代码如下:


, B0 q4 @+ w9 M+ P$ H% z8 ~) w
9 f0 u9 N: d9 H6 ^

  integer w_file;  

     initial

     w_file = $fopen("data_out_3.txt");   //保存数据的文件名

2 K) z# {* Y; V1 J; B, Y. D

     always @(posedge clk or negedge rst_n)  

     begin  

      if(flag_write==1&&post_href==1)//根据自己的需求定义

        $fdisplay(w_file,"%b",post_y_data);   


, |: q$ p8 s; g/ E# \3 P

      end      


1 ?" s* J! @7 i6 W4 k3 ]( x) N6 a; w" G  Z& w

网页的界面如下,将参数设置好以后就可以显示图片。

0 Z2 R  U: ]$ a5 p

下载链接:


+ {2 h7 S! {1 ~  q3 c% y+ ]/ R# Y
提取码:e87j

3 B1 n1 d$ s6 U: `- n* c$ m2 n; X' \
! w/ r5 _$ n+ d/ k2 ~" y
5 |% E) w  n( v0 B" K
        注意:由于此网站是量身定做的,所以只能显示数据格式为RGB565的16位二进制的数才能正确显示,注意不能有分号,正确格式示例如下,必须严格遵守。
6 j9 ~; b5 A2 x6 c

0 Q6 ?! c0 A) U3 f% y6 J七、结果展示' Q' c* P. {' s

% Z+ n8 p* i& e/ r' I' B, }5 `
+ Z0 c2 x& F, ?0 ]

" t, G1 _+ w& o" U& r+ a7 X0 q; n' J* i7 j' a
: T! ?* q1 u0 `! [5 ]$ U" v
        小结:均值滤波处理后的图片有明显的黑边,产生这一现象的原因就是生成 3*3 像素矩阵和取像素值时数据有损失造成的,但是这也是可以优化的,后续我会继续努力不断完善。本次只是简单对一幅图像进行边缘检测,我的后续目标是实现图片的实时处理,这又需要学习很多东西了,SDRAM、摄像头驱动等等等,越学习越发现自己知道的实在是太少了,永远在路上,学无止境。希望我的分享能够帮助一些和我一样热爱 FPGA 图像处理的朋友。

# O; b& K7 z4 p) ~6 G0 V: ]
- THE END -
. c7 q; K# j) I) W5 }

! l7 w8 |6 r- h$ s- ~

该用户从未签到

2#
 楼主| 发表于 2024-7-22 16:47 | 只看该作者
              
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-7-15 20:59 , Processed in 0.203125 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表