Lab 10: Panorama

You may work with a partner

Files to copy

cp ~cs102/robot_labs/Lab_Skeletons/Lab10a/makefile .
cp ~cs102/robot_labs/Lab_Skeletons/Lab10a/panoramic.o .
cp ~cs102/robot_labs/Lab_Skeletons/Lab10a/panoramic.h .
cp ~cs102/robot_labs/Lab_Skeletons/Lab10a/panoramic_example .

Example Program

/home/cs102/robot_labs/Lab_Skeletons/Lab10a/panoramic

In this lab you'll take a series of pictures with your robot, analyze the pictures for overlapping areas, then stitch them together and display them as a panorama. This lab will not be part of the Navigator class.

There are several ways to solve this problem, and you may already be familiar with photo editing software that constructs panoramas. For this lab, you'll be instructed through one of the simpler, yet effective, methods of solving this problem.

Before You Begin

Remember that the data for a picture is stored in a Picture objected. More percisely for this lab each picture is stored in a ColorPicture object. The following, code snipets cover creating ColorPicture objects, and their respective member functions. (Note: You will only need to create one ColorPicture, and that will be the panoramic Picture that you are returning from buildImage)

ColorPicture Memember Functions and Examples

  1. Constructor:
    ColorPicture(int width, int height)

    Example:
    ColorPicture * picture = new ColorPicture(width,height); //width and height are variables!
  2. Picture Height Accessor:
    int ColorPicture::getHeight()

    Example:
    picture->getHeight(); //returns picture's height
  3. Picture Width Accessor:
    int ColorPicture::getWidth()

    Example:
    picture->getWidth(); //returns picture's width
  4. Pixel Accessor:
    Pixel ColorPicture::getPixel(int x, int y)

    Example:
    Pixel pix = picture->getPixel(0,0); //returns the Pixel structure at the top left corner in the picture and stores the Pixel in pix
  5. Pixel Mutator:
    void ColorPicture::setPixel(int x, int y, Pixel pix)

    Example:
    int width = picture->getWidth();
    int height = picture->getHeight();
    Pixel pix = picture->getPixel(width-1,height-1));
    picture->setPixel(0,0,pix); //changes the top left pixel to be the same as the bottom right pixel

Pair Class Usuage Information

  1. Pair Constructor:
    pair<int,int> pr = pair<int,int>(int x, int y);

    Example:
    pair<int,int> pr = pair<int,int>(9,8);
  2. First Element Accessor Example:
    pair<int,int> pr = pair<int,int>(9,8);
    int first = pr.first;
  3. Second Element Accessor Example:
    pair<int,int> pr = pair<int,int>(9,8);
    int first = pr.second;

Part A: Image Stitching

You will write the function, buildImage, to stitch the images together. You will be given an array of pictures and the points where they best overlap. The function prototype looks like below and can also be found in panoramic.h . Implement this code into a new file named panermaic_buildimage.cpp

Picture * buildImage(vector<Picture*> imageArray, vector< pair<int,int> > overLap, int& final_width);

The first argument is a pointer pointer--this acts as an array of pointers, where each pointer points to an image(Picture) that will be used to construct the panorama. The second, third, and forth arguments are the number of pictures in the array, the width of each picture in the panorama, and the height of each picture in the panorama, respectively. The fifth argument is a vector of pairs. In each pair, the first integer represents the column number of the left hand picture that matches up with the column number indicated by the second integer in the right hand picture. There is a pair for each seam in the panorama. The last argument is the address of the final_width variable. The final_width will be calculated in this function, and will be used outside this function. This means that we either pass the final_width variable by pointer or by reference. To make life easier the final_width variable is passed by reference. If you don't remember pass by reference, consult your cs102 class notes.

The buildImage function should:

  1. compute the final width of the image based on the column-coordinate pairs you are given.
  2. initialize a Color Picture of the proper size for the panorama (use the calculated final width).
  3. copy the correct portions of the pictures into the panorama color image.
  4. return a pointer to the image.

Consider the diagram below to help you figure out how to build the image. This example picture array has four pictures, each with a width of 5 "pixels". The pairs are found in such a way that it is possible that any column in one picture can match with any column in another. An example of this case is illustrated with seam 2 of the figure. Column zero of Picture C contains a "Picture Anomaly," possibly a trick of light makes the two columns different, so the columns with the best intensity match are <4,1>. A similar thing happens over seam 1. Next week you'll deal with how to find the "right" matches, but for now consider that work already done.

Do This: Create the buildImage function according to the descriptions above in panoramic_buildimage.cpp . Also, only write the function, all the other code has already been written for you.