ES 314 Advanced Programming, Modeling and Simulation                                                                                Fall 2008

 

Project # 1

 

Due: September 29, 2008

 

Problem Statement: Write a C++ program to perform the following operations on an image: (a) add a text label at the North-East corner as foreground and (b) perform an image filtering operation. The filtering operation we are interested in called the median-filtering operation and its removes random noise in the image.

 

The following figure illustrates the input and the output files for operation (a):

 

                       

 

 

The next pair of images show the input and output of the median-filter.

 

                       

 

Goals of the project:

 

EasyBMP library:

EasyBMP is a library written in C++ that provides support for opening an image (in the BMP format), and manipulate the individual pixels of the image. You don’t have to know the details of how a BMP image is stored in a file. It is enough to know how to make calls to EasyBMP functions. The following are some useful classes and functions from the EasyBMP library:

If you are unclear about any of these functions, the manual EasyBMP_UserManual.pdf may be useful and can be found in http://easybmp.sourceforge.net/documentation.html. The manual also contains some examples with source code.

In the following, a simple example is presented to illustrate how to use EasyBMP.

Suppose we want to convert a color image or a gray scale image into black and white. This is a tricky process, but a very important one – for example when we want to print a color photo on a black and white printer, we need such an algorithm. We will use a very simple-minded algorithm called thresholding. Recall that each color pixel is defined by three color components (R, G, B), each taking a value between 0 and 255. R = G  = B = 255 is white, R = G = B = 0 is black. In thresholding, the average the color components of a pixel (i.e., compute (R + G + B)/3) is computed and if this average exceeds 127, this pixel to mapped to white, otherwise it is mapped to black. In the code below, we take a weighted average by weighting the colors by 0.3, 0.6 and 0.1 (since green is the most sensitive and blue is the least sensitive.) We present the code to implement this algorithm below.

An example of input/output is shown below.

          

The code is as follows:

 

#include "EasyBMP.h"

using namespace std;

 

int main( int argc, char* argv[] )

{

 BMP Background;

 Background.ReadFromFile(argv[1]);

 BMP Output;

 int picWidth = Background.TellWidth();

 int picHeight = Background.TellHeight();

 Output.SetSize(picWidth, picHeight);

 Output.SetBitDepth(1);

 

 for (int i = 1; i < picWidth-1; ++i)

    for (int j = 1; j < picHeight-1; ++j) {

          Output(i,j)->Red = 0;

          Output(i,j)->Blue = 0;

          Output(i,j)->Green = 0;

    }

 

 for (int i = 1; i < picWidth-1; ++i)

   for (int j = 1; j < picHeight-1; ++j) {

         int col = 0.1* Background(i, j)->Blue +

           0.6*Background(i,j)->Green +0.3* Background(i,j)->Red;

         if (col > 127) {

          Output(i,j)->Red = 255;

          Output(i,j)->Blue = 255;

          Output(i,j)->Green = 255;

          }

        }

 Output.WriteToFile(argv[2]);

 return 0;

}

The resulting b/w image is smaller in size. It also looks like hand-drawn.

Solution to the two problems:

Problem (1)

To label the given image with a given text, you need access to a bit-map image of each letter. For the purpose of this lab, you can assume that the font size of the letters in the label is fixed. (i.e., you will not be required to rescale the font files.) We will assume that the label consists of an alphabetical symbol or a blank space. Also assume that the font images are black in color with black background. The font images will be provided to you. The basic idea is to first copy the background image onto a buffer. Then, your program should overwrite the pixels on the upper-right corner by copying the bit-map images corresponding to the label. For example, if the label is the word “text”, your program will calculate the position in which each of the letters t, e, x and t should be written. It should then copy the image t.bmp, e.bmp etc. in the appropriate position. Note that when your write a letter, only the letter (not the background) should be copied. You can assume that the heights of all the font images are the same. However, they have varying widths so your program should use the width information to ensure a uniform spacing between letters. If the space needed to typeset the label exceeds the width of the image, your program should display an error message and terminate without adding any text to the image.

Problem (2)

   The idea behind median-filter is simple. Assume that only a small number of pixels have been affected by the random noise. Consider a pixel p that has been changed by the noise. A reasonable choice for the correct value of this pixel is the median of 9 pixels – itself and the 8 neighboring pixels. This guess will be incorrect only under the following situations: (a) the pixel was actually not affected by noise, and its color value is significantly different from that of its neighbors, (b) more than half of the pixels surrounding the current pixel have been corrupted by noise. Since both these events are low probability events, the algorithm is likely to replace most of the noisy pixel values by a value that is close to the correct one.

 The algorithm is described below:

I = input image; O = output image;

w = width of the image;

 h = height of the image;

 for j from 0 to w-1 do

   O(0,j)->Blue = I(0,j)->Blue; // etc. for all colors

 end for;

 for k from 0 to h-1 do

   O(k,0)->Blue = I(k,0)->Blue; // etc. for all colors

 end for;

 for j from 1 to w-2 do

  for k from 1 to h-2 do

   O(j,k)->Blue =

    (I(j,k)->Blue + I(j-1,k)->Blue + I(j+1,k)->Blue

   + I(j,k-1)->Blue + I(j-1,k-1)->Blue+ I(j+1,k-1)->Blue

   +I(j,k+1)->Blue + I(j-1,k+1)->Blue+ I(j+k+1)->Blue)/9;

             . . . . // similarly for other colors

  end for;

 end for;

What should be submitted?

When your program is run (after compiling it through the makefile you submit), it should take as input several image files, and produce as output three image files. The names of the main image files are in1.bmp and in2.bmp; in addition, your program will use a.bmp, b.bmp, … , z.bmp and space.bmp – all stored in the current directory.

After compiling, suppose the object code is named proj1. If proj1 is run with 5 inputs (in1.bmp, in2.bmp, str, out1.bmp, out2.bmp), it should read the files in1.bmp and in2.bmp and a string str, and produce images out1.bmp (by adding the label str to image in1.bmp) and out2.bmp (by applying median filtering on in2.bmp). The two image files should be created in the same directory.

Grading:

Both problems will be weighted equally. Your program will be tested with at least one input pair and its correctness will be determined by visual inspection. Full credit will be given for correct output. Partial credit will be given based on part of the work completed. You should demonstrate working functions/procedures with appropriate test cases to get partial credit.