CS 194 Project1: Images of the Russian Empire

Jacob Holesinger



Overview

In this project we developed algorithms for compositing color chanels. The photos we used were those of Prokudin-Gorskii, a Russian photographer who was taking colored photographs with color gells even before the techniques to combine them had been conceived. In my approach, I first implemented a naive alignment algorithm that would align two images by exhausitvley searching over all up and down pixel displacements within a 20x20 window. As the algorithm looped through all possible alignments, I kept track of the best seen "score" which was given by the normalized corelation coefficient between the two images. Next, in order to make this method tractible for higher resolution images which were much more expensive to compare, I ustilized an image pyramid of succesivly resized versions of the two images to be aligned. I decided to make the pyamid image resize by a factor of 2 and continued it untill the lowest level reached was a hardcoded 200 pixel width. The number of pyramid levels then was the log base 2 of (original_width / 200). All together, the pyramid worked by looping through this many iterations and at each, resizing the image by the appropriate factor of 2, cropping its borders to get rid of chanell mismatch and np.roll artifacts, using the naive algorithm to compute the optimal shift and finally shifting the original image by that amount scaled by the factor of 2. The images that gave me the most trouble were emir and village. For emir, aligning to the green chanel instead of the blue allowed the algorithm to find the right shift and for the villiage I had to resort to aligning the image passed through a sobel edge detector filter.

Bells and Whistles

Automatic Cropping

I implemented automatic cropping using a sorbel horizontal edge detector filter to find the top edge, and then succesive rotations to get the other three. First I would pass the image through this filter before summing up all of the image rows into a 1d array. I would then iterate down this array, keeping track of the most recent index that had a value above the threshhold 0.2 * image width. Since in the sorbel filtered image, pixels along a horizontal edge were given a value of around 0.2 or greater, elements of the 1d array passing this threshold would corespond to an edge crossing the whole image width. I stopped the search a third of the way down the image and if no edges passing the threshold were found, I kept the border of the original image.


Before auto cropping
After
Before
After

White Balance

I did white balance in my post processing by taking an average over my cropped image and then reweighting pixel values by a matrix with 0.5/(average value for chanel) along the diagonal so that this average value became gray [0.5, 0.5, 0.5].


Before white balancing
After
Before
After

Autocontrast

My method for balancing contrast was done by first convering to hsv, finding the max and min of the value chanel, rescaling all of the values linearly so that they spread from [0,1] and then finally applying an s-curve transformation that ended up shmooshing the midtones and expanding the highlights and darks. I think that this gave an interesting effect which I ended up liking more than the straight linear adjustment. The S curve was given by (1-e^x) / (1-e) and amounted to two mini gamma curves, one smooshing the lighter darks and one smooshing the darker lights. I had a little debate over whether to white balance then constrast adjust or to contrast adjust then white balance. I ended up picking contrast balancing last to keep a nice spread of values.


Before contrast adjust
After
Contrast First
White Balance First

Example Image Results

Cathedral: blue to green: [-5, -2] red to green: [7, 1]
Turkmen: green to blue- [56,22] red to blue- [116, 28]



Nativity: green to blue- [3, 1] red to blue- [8, 0]
Settlers: blue to green- [-7,0] red to green- [8, -1]



Self Portrait: blue to green: [-78, -29] red to green: [98, 8]
Emir: blue to green: [-48, -24] red to green: [57, 17]



Harvesters: green to blue- [59, 17] red to blue- [123, 15]
Icon: green to blue- [41, 17] red to blue- [90, 23]



Lady: green to blue- [52,8] red to blue- [112, 12]
Monastery: green to blue- [-3, 2] red to blue- [3, 2]



Three_generations: green to blue- [50, 15] red to blue- [110, 13]
Train: green to blue- [42, 6] red to blue- [86, 33]



Village: blue to green- [-64, -11] red to green- [73, 10]

Others from the Gorski Archive

At work on the upper reaches of the Syr-Darya. Golodnaia Steppe: blue to green- [-7, 0] red to green- [8, -1]
Dagestani types: blue to green- [-3, -1] red to green- [9, 1]



Pond: blue to green- [-2, -3] red to green- [3, 1]
Tow rope bridge in the village of Lava: green to blue- [-1, -1] red to green- [0, 0]