Image processing operations in System Verilog and C. Functional.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Image Processing with Convolution

Jenner Hanni

Released under the 3-clause BSD License.



Getpixels converts a color input image into a text file of its pixel values separated by spaces:

164 165 165 165 165 164 165 165 165 164 165 166

It also converts a text file of pixel values back to an image.

  1. ./GetPixels.o 1 brokentop.png brokentop.txt 240 320
  2. use SystemVerilog or C program to modify pixels
  3. ./GetPixels.o 2 brokentop.png brokentop.txt 240 320


This project performs pixel-by-pixel convolution on a 2-dimensional image of any height and width. A user-defined type pixel_t is a three-channel struct which is passed onto the data bus and through the decoder, blur, edges, emboss, flip, invert, and encoder modules. The only modules which perform operations are blur, edges, and emboss. Download the files and run the script.

Compiled using Mentor Questa.


The convolution program works by shoving an image's pixel values into an array and iterating over them with a convolution kernel matrix. The program takes arguments to specify input and output file names along with the number of kernels (1 or 2), kernel size (odd numbers between 1 and 17), and kernel coefficients (integers).

Usage: ./main.o <input.txt> <width> <height> <op> <kernel> <norm> <output.txt>

input.txt is the text file containing grayscale image pixel values.

width in pixels, same as number of columns in image.

height in pixels, same as number of rows in image.

op is (1) a horizontal 1d, (2) a vertical 1d, or (3) custom kernel to be entered by the user.

kernel is the N in the NxN kernel matrix that must be an odd number between 1 and 17.

norm is (0) no or (1) yes to normalize (divide by number of coefficients) the image.

output.txt is the text file to store resulting grayscale image pixel values.

To perform a custom 2D operation on a 240x320 image with a 5x5 filter kernel that will be normalized:

./main.o input.txt 240 320 3 5 1 output.txt

To perform a 1D horizontal operation on the same 240x320 image with a 3x3 filter kernel that will not be normalized:

./main.o input.txt 240 320 1 3 0 output.txt

Scripting Example

I put the following in a script to run a bunch of kernels all in a row. I used the same input image (brokentop.txt) but saved the outputs to their own files so I could reconstruct them with GetPixels at the end. The image is a portrait size of 240x320. I chose to do a single custom 3x3 operation and none of them are to be normalized.

First, I turned the brokentop.png image into a text file.

./GetPixels.o 1 brokentop.png brokentop.txt 240 320

Then I performed the operations, creating six output text files with the results.

./main.o brokentop.txt 240 320 3 3 0 output-horz.txt
./main.o brokentop.txt 240 320 3 3 0 output-sobel-h.txt  
./main.o brokentop.txt 240 320 3 3 0 output-vert.txt 
./main.o brokentop.txt 240 320 3 3 0 output-sobel-v.txt 
./main.o brokentop.txt 240 320 3 3 0 output-45deg.txt 
./main.o brokentop.txt 240 320 3 3 0 output-135deg.txt 

Finally, I reconstructed images from the output files so I could look at them in an image viewer.

./GetPixels.o 2 output-horz.png output-horz.txt 240 320
./GetPixels.o 2 output-sobel-h.png output-sobel-h.txt 240 320
./GetPixels.o 2 output-vert.png output-vert.txt 240 320
./GetPixels.o 2 output-sobel-v.png output-sobel-v.txt 240 320
./GetPixels.o 2 output-45deg.png output-45deg.txt 240 320
./GetPixels.o 2 output-135deg.png output-135deg.txt 240 320

For each operation, the program prompted me to enter the coefficients from left to right by hand but I have a couple options for how to enter them. Using the kernel for a Sobel horizontal operator, I can enter the coefficients all on one line like this,

+1 +2 +1 0 0 0 -1 -2 -1

or I can enter them by lines like this,

+1 +2 +1
0 0 0 
-1 -2 -1

which can be easier to read. Finally, I can enter them all like this,


so it really doesn't matter. I ended up writing them in the second form in a text file and copying/pasting. That way the test is built before I start and the results come out without needing editing.