phase 1:
Fractals and Composite Images
cs40 assignment 1 web page
Task 1 -- Composite Images:
For the first task, the assignment was, using a photograph of myself against a bluescreen, create composite images with myself against different backgrounds. In one of the images I was to insert myself multiple times.
The basic algorithm:
- crop a blue region of the foreground image and scan this region for min/max values of blue hue (b=B/(R+G+B))
- scale the foreground image to the desired size
- transform the foreground image as desired
- determine corresponding regions of the foreground and background images
- traverse the background region, replacing pixels with pixels from the foreground image if the corresponding foreground pixel does not fall in the min/max blue hue range
- repeat as desired
Discussion inspired by lab questions:The picture of myself is 2560 pixels wide and 1920 pixels high, as determined by reading the image in using
readPPM()
and then making aprintf("%d,%d\n", image->cols, image->rows)
call. Location (0,0) in the image varies depending on how it is accessed. When accessed from within my code, it is in the lower-left (as determined by coloring pixels in that region bright red), but when running xv, it is in the upper- left (as determined by middle-clicking).To do the blue-pixel replacement, I thresholded using blue hue (B/(R+G+B)) values, which worked pretty well (I never got any blue spill, for instance). The only problem occurred with images many-times shrunk (my image-shrinking algorithm hasn't been perfected yet, and it tends to wash out). So to improve things I would mostly need to fix my image shrinker.
My method for inserting myself into the image was to first choose a desirable scale and transformation (gotten through trial and error), then I would eyeball the background and transformed foreground images and see where they should line up. Clicking in xv, I would figure out the coordinates of a desirable rectangular insertion-region in the background image (call this (x1,y1,x2,y2)), and the coordinates of the lower-left corner of the desired region in the foreground image (call it (x3,y3)). The blending function aligns the lower-left corner of the background region to the specified lower-left corner of the foreground region. We can then iterate in (x,y) pixel coordinates of the background image, going from x1 to x2 and y1 to y2, and we get the corresponding foreground pixel for comparison by x' = x - x1 + x3, y' = y - y1 + y3.
Extensions:I implemented basic feathering in the bluescreen-composite images. In short, the alpha channel for the pixel being replaced was set to 0.0 if it was completely in the min/max region, but if it was only a little bit outside the specified region, its alpha channel was set to some value between 0.0 and 1.0, resulting in blending at the edges.
a little taste test:
no feathering feathering
Task 2 -- Fractals:
For the second task, I was to create some images of mandelbrot and julia sets. The mandelbrot attractor is given by z_k+1 = (z_k)^2 - c, where z and c are complex numbers. Depending on c and the initial value of z, z will either approach zero or approach infinity.
A julia set is associated with a particular value of c (there an infinite number of julia sets), and is defined to be those initial values of z such that z goes to zero. The mandelbrot set is those values of c for which z goes to zero when the initial value of z is 0+0i. In either case, because the set memebers are complex numbers, we can associate the real and imaginary parts of these numbers to x,y coordinates and thus end up with pretty pictures.
The basic algorithm involves establishing a region of equation space, and establishing a mapping from an image of pre-defined dimensions to the equation space. We then iterate over the image pixels, and pixel x,y will map to equation space x',y', which corresponds to either z_0 (for a julia set) or to c (for the mandelbrot set). We then test the point associated with that pixel for set membership by following the update rule for z, and seeing if z exceeds a threshold value within a specified limit of iterations -- if so, it is not in the set, if not, we assume it to be in the set.
Coloring schemes:Beyond simply using on/off pixel colors for set exclusion/inclusion, various coloring schemes can be thought up to make more pretty pictures. One option is to create a striped effect for non-set pixels by alternating between two colors depending on whether the associated point exceeded the threshold on an even or an odd iteration. Another option is to use the magnitude of the break-out iteration number to blend between border- line set and non-set members. A third option is to use magnitude to blend from borderline non-set members to way-out-there non set members. In creating my images, I used either a combination of striping and blending across the borderline (what I call "striping", or blending from near to far (what I call "blending").
I really like what I call the "zipper" region of the mandelbrot set (0.63,0.0 to 0.92,0.39), which does a good job of revealing all the tiny little mandelbrots which sit in the border region of the mandelbrot set. My favorite image, of the above, though, is probably the final julia set one, for the which the blended color scheme works particularly well. The particular characteristics of each set/region can be best brought out by different color schemes, though.
More extensions:
I composited an image of a fractal with a scary image of myself from freshman-year halloween, thresholding in intensity in the fractal image, then changed the apparent light color of the image.
dear lord... (click to enlarge)
before... and after