Final Project 1: Image Quilting

Comparison of Quilting Techniques

Original
Random Quilt
Overlapping Quilt
Seam-Finding Quilt

Seam Finding

Below are two patches that overlap for the brick wall. The cost image has the min-cost path shown in white. For this particular overlap, it happens to be so similar that the errors are very low and occur at the leftmost edge.
Overlap Region 1
Overlap Region 2
Cost image with min-cost path

The image quilting technique consists of first finding the patch that is most similar in the overlap region. Then instead of directly copying that patch onto the quilt, we find the min-cost path which provides the ragged boundary between the two overlapping patches that best stiches the two patches together. This min-cost path is found through dynamic programming, considering the cummulative error along all possible paths. In the case of vertical boundaries as shown in the example above, pixels left of the min-cost path are pixels from overlap region 1 and those right of the min-cost path are pixels from overlap region 2. This process is repeated until the entire quilt has been filled with patches.

A difficulty I encountered was writing the min-cost path algorithm on my own for the Bells & Whistles. It was also more difficult to get a synthesized texture that looked more natural for textures that were bigger, like the berries. A design decision I made was to make the patch sizes 25 by 25 with an overlap region of 5 pixels.

Seam Finding Results

Texture Transfer

To transfer the texture from a source image onto a target image, first construct correspondence maps. I used the luminosities as the correspondences. For each patch of the target image, look at the corresponding patch in the luminance correspondence map C1. Then find the best match for C1 in the luminance correspondence map for the source texture image, and say the best matching patch is C2. The patch corresponding to C2 in the source image is stiched into the target image using the seam-finding quilting technique illustrated above.

A difficulty I encountered was deciding on the correspondence map, but I ultimately settled on what the paper used which was just the luminance of the pixels. As a design decision, I chose to stick with the sketch texture, because there are enough differences in the texture to paint more details. However, without the iterative method described in the paper, the end result does not look as seamless.

Texture
Target Image
Result
Texture
Target Image
Result

Bells & Whistles

Create and use your own version of cut.m.

I created my own version of cut.m using dynamic programming in python. The code can be found in the function _min_error_cut of the main.py file in image_quilting. I implemented two versions depending on whether the seam was vertical or horizontal.

Face on toast

I used texture transfer to recreate the dog face with the toast texture. Then I used Laplacian pyramid blending to put that dog face onto toast.
Dog
Toast
Dog on Toast

Final Project 2: High Dynamic Range Images

Original Images

Below are the original images with different exposure times that are used to construct the HDR image.
Exposure: 32.0
Exposure: 16.0
Exposure: 8.0
Exposure: 4.0
Exposure: 2.0
Exposure: 1.0
Exposure: 0.5
Exposure: 0.25
Exposure: 0.125
Exposure: 0.0625
Exposure: 0.03125
Exposure: 0.015625
Exposure: 0.0078125
Exposure: 0.00390625
Exposure: 0.001953125
Exposure: 0.0009765625

Radiance Map Construction

Following the algorithm described in the paper by Debevec and Malik 1997, I solved for the log of irradiance values ln E_i and the function g in the system of equations
g(Z_ij) = ln(Ei) + ln(delta_t_j)
where Z_ij is the ith pixel from picture j, and delta_t_j is the exposure time for picture j. I sampled over 50 pixels from each of the images to construct the matrix Z. I also followed the paper to add weightings to emphasize the smoothness of the curve and to fit terms towards the middle.
Below is the result of using the solved information to get the radiance for each pixel.

Tone Mapping

Following the simplified version of the algorithm in Durand 2002, I used the radiance map to get the intensity of the pixels and the chrominance of each channel. Then I computed the log of the intensity and filtered it with a bilateral filter, which smooths the noise while preserving the edge details. Then I separated the details layer from the large scale structures (shown below), and applied an offset and scale to that base layer. Finally, I reconstructed the log intensity and put back the colors with the chrominance channels and applied gamma compression to the resulting image.
As shown below, the local tone mapping turned out better than the global tone mapping, which simply took a log of the ln(E_i) of each channel and normalized.
Detail Layer
Base Layer (Large Structures)
Global Tone Mapping
Local Tone Mapping