Vous êtes sur la page 1sur 13

9/13/2018 2D Convolution in Hardware

2D Convolution in Hardware
SystemVerilog implementation of Edge Detection

Posted by Nelson Campos (about.html) on December 27, 2016

The Sobel operator is one of the most widely known methods for edge
detection in image processing. The edges in an image are the points where
the pixel intensity have the maximum variation in the spatial distribution. In
the frequency domain, the edges are obtained ltering out the low
frequencies in the spatial distribution [1].

To obtain the edges of an image I, a 2D convolution with two kernels of


dimension 3x3 are calculated to obtain the gradients (Gx: frequency
variations in horizontal direction and Gy: frequency variations in vertical
direction) according to equation (1):

https://sistenix.com/sobel.html 1/13
9/13/2018 2D Convolution in Hardware

(img/grad_eq1.svg)
Equation (1)

The resultant gradient with its direction is de ned in equation (2):

(img/grad_eq2.svg)
Equation (2)

A practical example
To understand the effect of the Solbel lter, we will use the Figure (1).

https://sistenix.com/sobel.html 2/13
9/13/2018 2D Convolution in Hardware

(img/lena.bmp)
Figure (1): The classic picture of Lena

Using MATLAB (or its open source version Octave with Image Processing
package) we can do the Sobel Operation with the following lines of code:

//Figure (1): the classic picture of Lena


img = imread("lena.bmp");
figure(1), imshow(img);

The rst step for edge detection using Octave is to convert the image to gray
scale. It can be achieved with the following lines of code:

https://sistenix.com/sobel.html 3/13
9/13/2018 2D Convolution in Hardware

//Figure (2): Lena's picture in gray scale


pkg load image;
img_gray = rgb2gray(img);
figure(2), imshow(img_gray);

The Lena's picture in gray scale can be seen in Figure (2):

(img/img_gray.jpg)
Figure (2): Lena's picture in gray scale

To detect the edges of the image using Octave just use this lines of code:

https://sistenix.com/sobel.html 4/13
9/13/2018 2D Convolution in Hardware

//Figure (3): Edges of the classic picture of Lena


edge_img = edge(img_gray, "Sobel");
figure(3), imshow(edge_img)

The edges of the classic picture of Lena can be seen in Figure (3):

(img/edge_img.jpg)
Figure (3): Edges of the classic picture of Lena

Hardware implementation

https://sistenix.com/sobel.html 5/13
9/13/2018 2D Convolution in Hardware

An image is de ned with a 2D matrix in which its elements represent the


pixel intensity of its content. However, hardware devices such digital
cameras transfer images in 1D stream of bits. So, to perform a kernel
convolution of 3x3 dimension, the minimum amount of bits required is 2 lines
of the the image, as can be seen in Figure (4), where 2 buffers of lenght 9 are
being used for convolve a 3x3 kernel [2][3][4].

(img/sliding_window.svg)
Figure (4): Convolution of a 3x3 kernel with a image with WIDTH=9 pixels per line

The pixel's datapath in the convolution can ben seen in Figure (5) and it can
be represented mathematically as a function of the BUFFER_SIZE acccording
to equation (3), where the matrix SLIDING_WINDOW3x3(pixel(t)), represents
the 3x3 kernel that convolves the pixels in function of the time t and as a
function of BUFFER_SIZE.

(img/grad_eq3.svg)

https://sistenix.com/sobel.html 6/13
9/13/2018 2D Convolution in Hardware

Equation (3)

input

(img/circular_buffer.svg)
Figure (5): The pixel's datapath in the convolution

The SystemVerilog code of the Sliding Window for the pixel streams can be
seen below:

https://sistenix.com/sobel.html 7/13
9/13/2018 2D Convolution in Hardware

parameter WORD_SIZE = 8;
parameter ROW_SIZE = 10;
parameter BUFFER_SIZE = 3;

module sliding_window #(parameter WORD_SIZE=8, BUFFER_SIZE=3)


(input logic clock, reset,
input logic [WORD_SIZE-1:0] inputPixel,
output logic [BUFFER_SIZE-1:0][WORD_SIZE-1:0]sliding[BUFFER_SIZE-1:0]);

logic [(BUFFER_SIZE-1)*WORD_SIZE-1:0] buffer[ROW_SIZE-1:0];


logic [$clog2(ROW_SIZE)-1:0] ptr;

always_ff @(posedge clock)


if(reset) begin
ptr <=0;
sliding[0][0] <= 0;
sliding[0][1] <= 0;
sliding[0][2] <= 0;
sliding[1][0] <= 0;
sliding[1][1] <= 0;
sliding[1][2] <= 0;
sliding[2][0] <= 0;
sliding[2][1] <= 0;
sliding[2][2] <= 0;
end
else begin
sliding[0][0] <= inputPixel;
sliding[1][0] <= sliding[0][0];
sliding[1][1] <= sliding[0][1];
sliding[1][2] <= sliding[0][2];
sliding[2][0] <= sliding[1][0];
sliding[2][1] <= sliding[1][1];
sliding[2][2] <= sliding[1][2];

buffer[ptr] <= sliding[BUFFER_SIZE-1][BUFFER_SIZE-2:0];


sliding[0][BUFFER_SIZE-1:1] <= buffer[ptr];
if(ptr < ROW_SIZE-BUFFER_SIZE) ptr <= ptr + 1;
else ptr <= 0;
end
endmodule: sliding_window

SystemVerilog code of the Sliding Window

https://sistenix.com/sobel.html 8/13
9/13/2018 2D Convolution in Hardware

The SystemVerilog code of the 3x3 kernel for Sobel Operation and its
testbench can be seen below:

https://sistenix.com/sobel.html 9/13
9/13/2018 2D Convolution in Hardware

module sobel #(parameter WORD_SIZE=8)


(input logic clock,reset,
input logic [WORD_SIZE-1:0] inputPixel,
output logic [WORD_SIZE-1:0] outputPixel);

localparam BUFFER_SIZE=3;

logic [BUFFER_SIZE-1:0] [WORD_SIZE-1:0] sliding [BUFFER_SIZE-1:0];


sliding_window #(WORD_SIZE,BUFFER_SIZE) my_window(.*);

logic [WORD_SIZE+1:0] gx1, gx2, gy1, gy2;

always_ff @(posedge clock)


if (reset) begin
gx1 <= 0;
gx2 <= 0;
gy1 <= 0;
gy2 <= 0;
end
else begin
gx1 <= sliding[0][0] + sliding[2][0] + (sliding[1][0]<<1);
gx2 <= sliding[0][2] + sliding[2][2] + (sliding[1][2]<<1);
gy1 <= sliding[0][0] + sliding[0][2] + (sliding[2][1]<<1);
gy2 <= sliding[2][0] + sliding[2][2] + (sliding[0][1]<<1);
end

logic [WORD_SIZE+1:0] gx, gy;


always_comb begin
if (gx1 > gx2) gx <= gx1-gx2;
else gx <= gx2 - gx1;
if (gy1 > gy2) gy <= gy1-gy2;
else gy <= gy2-gy1;
end

logic [WORD_SIZE+2:0] g;

always_comb g <= gy+gx;


always_ff @(posedge clock)
if (reset)
outputPixel <= 0;
else
if (g[WORD_SIZE+2]) outputPixel <= {WORD_SIZE{1'b1}};

https://sistenix.com/sobel.html 10/13
9/13/2018 2D Convolution in Hardware

else outputPixel <= g[WORD_SIZE+1:2];

endmodule

SystemVerilog code of the 3x3 kernel for Sobel Operation

`include "sobel.sv"
module top();
logic clock, reset;
logic [4:0] i, k;
logic [WORD_SIZE-1:0] inputPixel;
logic [WORD_SIZE-1:0] outputPixel;

initial begin
$display("testing ...");
clock = 0;
$monitor("%d %d %d", i, inputPixel, outputPixel);
for(i=0; i<31; i++)begin
#0 @(posedge clock)
inputPixel=$random;
end
#100;
$finish;
end
always #5 clock = !clock;

sobel filter(.clock(clock), .reset(1'b0), .inputPixel(inputPixel),


.outputPixel(outputPixel));
endmodule: top

SystemVerilog code of the Sobel Filter testbench

Also available in GitHub


(https://github.com/nelsoncsc/sv_image/tree/master/SOBEL).

https://sistenix.com/sobel.html 11/13
9/13/2018 2D Convolution in Hardware

References:
[1] http://homepages.inf.ed.ac.uk/rbf/HIPR2/sobel.htm
(http://homepages.inf.ed.ac.uk/rbf/HIPR2/sobel.htm)
[2] Gradient Filter implementation on FPGA : Part 2 Implementing gradient
Filter (https://www.element14.com/community/groups/fpga-
group/blog/2015/05/27/gradient- lter-implementation-on-fpga-part2-
rst-modules)
[3] VIVADO HLS 2D Convolution on hardware - part 1
(https://www.youtube.com/watch?v=38lj0VQci7E&t=44s)
[4] LAD Projetos (http://lad.dsc.ufcg.edu.br/lad/pmwiki.php?n=Lad.Projetos)

 (mailto:nelsoncscampos@gmail.com)


 (https://twitter.com/ne1_50n)


 (https://br.linkedin.com/in/nelsoncsc)


 (https://github.com/nelsoncsc)

Copyright © sistenix.com 2016

https://sistenix.com/sobel.html 12/13
9/13/2018 2D Convolution in Hardware

https://sistenix.com/sobel.html 13/13

Vous aimerez peut-être aussi