CSE/EE 486:  Fundamentals of Computer Vision


      Computer Project Report #3:

      Imaging Geometry

      Group #11: Howard Elikan, Jim Geis and Anirudh Modi

      April 1, 1999


      1. Objectives:
        To apply the concepts of geometry transformation to mapping 3-D polyhedra onto a 2-D image plane.

      2. Methods:
        A program was implemented in C++ code to accomplish the project's objectives. First, a routine reads in the object data as input, and stores all the information. The data file provides the camera's initial position, the point towards which it points, the focal length, the position of each vertex, and a table listing which vertices connect to form edges. The world points are put through a series of geometric transformations in mapping them to a 2-D plane. The exact transformations are determined from the data in the input file. In general, five transformations are required:
        1. a translation to account for displacing the camera
        2. a rotation about the z-axis to account for the camera panning around (theta)
        3. a rotation about the x-axis to account for the tilt of the camera (alpha)
        4. a translation to account for displacing the image plane
        5. a perspective transformation
        These transformations were all done using matrices and then multiplied together to form one matrix. With the transformed vertices and the edge connections known, the points were plotted on a 2-D image plane. Clipping with the view plane was done while drawing the edges to improve efficiency of the pixel painting algorithm. Finally, the finished image was written as a binary PPM file for viewing. The program code, relevant scripts and sample data files can be found in a single tar-ball in the Appendix below.

      3. Results:

        To test the functionality of our image mapping program, we first created an image of the unit cube given in the handout. Supplying data for the cube to our program yields the following output:
        ------------------------------------------------------------------------------
        Reading object from file "objects/cube.off" ->
        ------------------------------------------------------------------------------
        Camera Origin  = [10,10,10]
        Camera facing towards [0,0,0]
        Focal length of camera = 3
        Number of vertices = 8
        Number of edges = 12
        ------------------------------------------------------------------------------
        ------------------------------------------------------------------------------
        Mapping from World co-ordinates to Image plane co-ordinates:
        ------------------------------------------------------------------------------
        (0,0,0) => [128,128]
        (0,0,1) => [128,105]
        (0,1,0) => [147,139]
        (1,0,0) => [108,139]
        (1,1,1) => [128,128]
        (1,1,0) => [128,151]
        (1,0,1) => [107,116]
        (0,1,1) => [148,116]
        ------------------------------------------------------------------------------
        Writing 256x256 image to file "view.ppm"...done!
        

        As you can see, the program first reads in the parameters for the camera's position, orientation, and focal length. Then it reads in the number of vertices and edges. Next, the program maps each world coordinate to its corresponding image coordinate. Then the edges are connected and the output image file is written. The output of the unit cube given in the handout appears in Figure 1. The output image looks like a hexagon shaped pie. This makes sense because the corners of the image lie at [0,0,0] and [1,1,1], while the camera is positioned at [10,10,10] looking towards the origin. These three points are co-linear, so the corners are mapped to the same image point.

        To mix things up, we altered the camera's position by moving it to the point [7,5,3], keeping it pointing towards the origin and leaving its focal length fixed. The output image for this configuration is shown in Figure 2. Here the corners no longer line up, so the shape of the cube is easily seen. The cube appears larger in this image because we've moved the camera closer.

        Then we decided to push the image mapping program to the max. It turns out that the format we're using to input the 3D objects into our program is very similar to another standard for objects, Object File Format, or OFF. We happened to have a few of these files handy, so we tried them out on our program. We had to modify the header for setting up the camera position and angle. Then we tried several of the OFF files in our program, and the results are amazing. For each of the following models, we positioned the camera in a postion so it could clearly show the whole object.

          Figure 3 - a mushroom with 226 nodes and 928 edges.
          Figure 4 - a pear with 8981 nodes and 3504 edges.
          Figure 5 - a tea pot with 1976 nodes and 11273 edges.
          Figure 6 - a space station with 5749 nodes and 20203 edges.

        The results of the four OFF objects show the potential of the 3D image mapping program. For the purpose of the assignment, we only had to display a simple cube, but the idea can be easily extended to include very complex objects as well.

      4. Conclusion:
        In this project, we learned the basics of mapping 3D world points onto a 2D image plane. By running the program with different parameters for the camera position and direction, we could see what effects these had on the output image. For example, increasing the focal length made the resulting image appear larger. Making the optical axis collinear with real world vertices make them appear at the same point on the image plane. Finally, using complex objects such as the teapot, we showed that simple image mapping techniques used here could be extended to include much more complex models as well.

      5. Appendix:
        All images are 256 x 256.

        Figure 1: Original object (cube.off)
        with camera origin at [10,10,10]
        Figure 2: Same object (cube2.off) with
        camera origin shifted to [7,5,3]

        Figure 3: Example object: mushroom.off Figure 4: Example object: pear.off

        Figure 5: Example object: teapot.off Figure 6: Example object: space_station.off

        Source code:

          The file offobject.h is the header file for the class of functions for reading, writing and manipulating the 3D object data (C++).

          The file offobject.cc is the implementation file for the class of functions for reading, writing and manipulating the 3D object data (C++).

          The file matrix.h is the header file for the class of functions for matrix operations (C++).

          The file matrix.cc is the implementation file for the class of functions for matrix operations (C++).

          The file image.h is the header file for the class of functions for image manipulation (C++).

          The file image.cc is the implementation file for the class of functions for image manipulation (C++).

          The file main.cc is the main driving routine for this project (C++).

        Note: Special run scripts are necessary to execute the code.   For a complete copy of the code, scripts, and objects, click here.   After you have downloaded the file:

        1. Type "gunzip -c project3.tar.gz | tar -xvf -"
        2. Type "./run objects/[object-data]" to execute the code

        Binary:

          Binary for SunOS: proj3sunOS
          Binary for Linux: proj3linux