Lab 1: Image Manipulations & Fractals
Andrew Cantino & Will Moss

In this, our first lab for Computer Graphics, we develop an image class and use it as a framework for performing both blue-screening and fractal generation.

Sections:

The Image Class

We decided to code this lab (and presumably subsequent labs) in C++ because we wanted access to the object-oriented features of C++. We started by writing an image class for the storage and manipulation of RGB images. The class contains the following data:

Taking advantage of C++'s object-oriented structure, the image class additionally provides the following methods:

Bluescreening and Image Manipulation
In lab, we had two pictures taken of each of us in front of a bluescreen. Here are two examples:


Andrew looking ruminative.


Will looking infarcted.

We set out to extract the images of ourselves from the bluescreen images, as follows:

Getting the bluescreening to work correctly was difficult, but the Gaussian sphere in RGB space worked quite well. Sometimes we would have to fiddle with thresholding values or apply a shrink before the bluescreening looked good, but it generally worked well. In the process of working on the bluescreening, we also tried running a median filter over the alpha channel to remove noise, but we didn't see much improvement and shrink worked as well.

Here are our example (portfolio) images, along with samples of the C++ calls used to make them:

Mandelbrot and Julia Sets

In this lab we used a simple attractor function to generate Mandelbrot and Julia sets. The function is defined by the iteration, z[n + 1] = z[n]^2 - c, where both z and c can be complex numbers. A Mandelbrot set was generated when the initial value of z[0] = 0, and c was varied over the complex plain. A julia set was generated by setting c to a specific value, and then varying the initial value of z over the complex plane. Our algorithm for visualizing these sets, and generating images of them, took as a parameter the size of the rectangle in the complex plane, and for the julia sets, it took the value for c as well. The value of z[n + 1] was then calculated using the above iteration, and checked to see whether z had gone above the given threshold. Both sets used a threshold of 100 (the threshold does not effect the outcome very strongly because the sets diverge so quickly). The number of times the iteration was run was plotted as an intensity in the red channel. For the Mandelbrot set, we found that the best resolution was achieved when we iterated 32 times (then multiplying the output by 8, to fill the entire available color space). For the Julia set, the best resolution was achieved when we iterated for 256 times, and plotted the resulting iteration value directly to the red channel.

Example images (click for larger version):


Julia Set from (-1.55, 1) to (1.55, 1)


Mandelbrot Set from (-.6, -1.2) to (1.8, 1.2)

 

Portfolio images (click for larger version):


Julia Set from (.8, -.2) to (1.2, .2) (Will)


Mandelbrot Set from (-.1, -1.1) to (.3, -.7) (Will)


Mandelbrot Set from (1.2, -.5) to (2.2, .5) (Andrew)


Julia Set from (-.1, -.5) to (1, .1) (Andrew)

Answers (to Questions)
  1. The images have height 1920 and width 2560. We determined this by accessing the rows and cols parameters from readPPM (or from our image class that wraps around readPPM).
  2. The origin is located at the upper left-hand corner of the image. We determined this by writing a small square of white pixels near (0,0).
  3. We didn't have X access to engin, and we didn't have xv on our own systems, so we don't know. Presumably it's either the upper left-hand or lower left-hand corner of the image.
  4. We didn't replace the blue pixels. Instead, we modified the alpha channel of the image. This is explained in the section Bluescreening and Image Manipulation. Our replacement worked well. Occasionally there was blue-spill in our images, but we could usually control it by varying the Euclidean distance threshold and playing with feathering. Sometimes a small bit of blue-spill does appear. We could control this further by using more advanced blue-screening techniques that try to adjust for backlighting off of the blue background. We also considered modeling 'blue' as multiple Gaussian spheres instead of one in color space. We could do this by some kind of k-means clustering in RGB space.
  5. For the portfolio images where we inserted ourselves into backgrounds, we used our image class and it's methods plus the bluescreening code. Please see the portfolio images at the end of Bluescreening and Image Manipulation.
  6. The edges around the central empty void in the Mandelbrot set were clearly the most interesting and we each picked a part to explore for our portfolio images.
  7. We played with various coloring schemes and ended up liking simple blues and reds. We also tried various vomit colored renditions of the fractals by mixing colors.

Extensions

Bilinear Interpolation
For both the rotate and scale down functions, we used a bilinear interpolation to achieve better quality images. For the case of scaling down, we found the location in the old image of the center of the pixel from the new image. Then, for each pixel that the new pixel "touched" we found the distance to the center of that pixel, and used it to do a weighted average of the color values. This made boarders and other areas of high contrast look much less jagged when they were scaled down. For the rotate, we used a similar technique and found where the center of the new pixel falls in the old image. Then we took the same weighted average as before, this time using the eight pixels that surrounded the pixel where the center fell.


Comparison of bilinear interpolation (on the left) and non-bilinear interpolation (on the right) scaling.

 

Feathering
As an extension, we did feathering, or blurring of the edges of the bluescreened image with the background. Having an alpha channel made this quite simple. We applied a mean filter to the alpha mask, so that every alpha value became the average of it's surrounding alpha values. This tends to blur the edges of the alpha channel, which means that when we overlay the image, it's edges get feathered, or blurred with the background. We experimented with some different values of blurring on the alpha channel, and found that averaging 2 alpha values in every direction worked well. All of the included images in Bluescreening and Image Manipulation use our feathering technique.

[Back to Lab Index]