Lab (2) - Image Processing

Representation of an image as a matrix
Sampling and Quantization
Effect of pixel reduction on image quality
Effect of gray-level reduction on image quality

In this lab you will learn to represent an image as a matrix of pixel intesities.  You will get a chance to make a beast out of a beauty or a beauty of a beast.

Viewing an image as a matrix
Perhaps the most common image format used to view an image as a matrix is Portable GreyMap (PGM) format.  You can learn more about this image format by using the man command on UNIX.  For the purpose of this lab, I will only refer to the most common 2-D format.  A PGM file contains the following information:

P2  (This is the tag, marking the 2-D nature of the image)
Gray_level  (This is the gray level or the intensity value (white in gray scale). In an 8-bit image, that is 255.
nx  ny (These numbers represent number of rows and columns respectively).
x(i,j) (This is the intensity values, you can list them row-by-row or all numbers at once, as long as they are separated by a blank space)

An example of a 4x4, 32 bit image:  sample.pgm
P2
#
4 4
255
12 124 214 255
123 14 200 120
12 8 112 245
112 124 254 255

If you save this in a file with .pgm extension, you have gotten yourself a 4x4 8-bit image and you can view it using xv.   Note that an image has NxM pixels which are represented in 2m gray levels.  Thus, the image size is:
b = NxMxm bits.  In the case that M = N, then we will have, b = N2m.

In order to read a PGM image, we will use a C++ code.  Matlab does not read PGM files but we can remove the header and read the remaining part of the image, the intensity values, as a matrix.  I have prepared a C++ code that helps you read PGM images.  Please create the ImgProc directory and copy the ReadPGM.C file from my directory using the following command:
% cp ~rt/3531_s01/codes/ReadPGM.C .    (don't forget the .)

This code is not very flexible, a quick and dirty one, but it works.  For images with different sizes, you need to set the image size, nx and ny (ncloumns and nrows), at the top of the code and compile it.  The best way to write the code is to read nx and ny from the input image, then dynamically create the matrix with the exact size.  This code will ask you for an input image and an output file.  Note that if you are creating a PGM file, then your output has to have .pgm extension.  The current version of the code reads the input image and prints the same image to the output file.  I advise you to keep a clean copy of this code.  You need to read many images in the lab and write them in different ways.  This code is a good place to start.

To start the lab you need some images.  Copy two sample images from my directory.  These two images are mona.pgm and sl00.pgm.  The first one is the picture of a model, was famous at the time before you were born, and the second is a CT spleen image.

Sampling
As we discussed in class, an image is denoted by f(x,y), where f represent the intensity and (x,y) represents the spatial coordinate.  Image sampling is the process of digitization of the spatial coordinates (x,y). An image is a continuous function in spatial coordinate.  We use a discrete sample with MxN points to represent the image digitally.  Selection of M and N is one of the factors that determines the digital image quality.  It is the factor for determining the image resolution.  In this part we want to see the effect of sampling on image quality.

The above two images that you have copied from my directory, are both 256x256 images. You need to write a function that takes f(x,y) and returns the reduced image as f(x,y) again.  You will determine the amount of reduction using an integer value, factor, that will be passed to that function as a parameter. Thus your function should look like this;

void Reduce_spatial(int x[nrows][ncolumns], int factor)

Please choose the factor to be a power of, we reduce the image to 128x128, 64x64, 32x32, 16x16, 8x8, 4x4.  Please note that we want to keep the image size at 256x256.  In order to do this, we remove the pixels (as many as the factor says) by replacing them, for now, with the neighboring pixel.  This process is called pixel replication.

We will do this for both images.  Please take a note of the changes that you will see in the quality of the reduced images.

128x128
64 x 64
32 x 32
16x16
8x8
4x4

When do you start seeing checkerboard effect ?

Quantization
To represent an image in digital world, the intensity (amplitude) must be digitized too.  In order to do this, we will break the intensity to some levels called gray scale levels (for a gray scale image).  The quantization is commonly done based on the power of 2.  Thus, we represent the gray scale as a number that is a power of two.  A pixel in an 8 bit image ( 28 = 256 gray levels) has the value 255 for white and 0 for black.  Any intensity value between these two is considered gray.

To see the effect of gray scale reduction, we will write another function that reduces the pixel values by a factor.  Note that this time we divide the gray scale (intensity by a number).

void Reduce_gray(int x[nrows][ncolumns], int gfactor)

Take a note of your observations.

m = 7
m = 6
m = 5
m = 4
m = 3
m = 2