https://aditimundra05.github.io/cs180/2/index.html

Colorizing the Prokudin-Gorskii Images

Introduction

This project takes the digitized Prokudin-Gorskii glass plate images and, using image processing techniques, automatically produces a color image with as few visual artifacts as possible. In order to do this, I extracted the three color channel images, placed them on top of each other, and aligned them so they formed a single RGB color image.

Intro Image
Best Shift: G(49, 23), R(107, 40)

Methodology

My program took a glass plate image as input and produced a single color image as output. First, I divided the image into three equal parts as each image was essentially the three channels stacked as images on top of each other. Then, I aligned the second and third parts (G and R channels) to the first (B) iteratively. I aligned the images by exhaustively searching over a window of possible displacements (I chose [-15, 15] pixels), scored all of the alignments using an image matching metric, and then taking the displacement with the best score for the final image output.

Alignment Metrics

There are different metrics to score how well the images match. In this case, I used Euclidean distance (L2 norm) and Normalized Cross-Correlation (NCC) on a cropped version of the images (so that the chromatic abberation on the boundaries of the image wouldn't affect the results).

The SSD Norm

This is the simplest metric to use on the images (formula shown below). It worked well on the smaller images, but performance worsened on larger image sizes. To compute the euclidean distance, you first compute the per-element difference for each index i. Square each difference and then sum up those squared values to obtain the Sum-of-Squared-Differences. Finally, take the square root to get the Euclidean distance.

d(u, v) = √(∑i=1n (uivi)2)
Result 3
Result 3
Result 3

The NCC Norm

The Normalized Cross-Correlation metric is simply a dot product between two normalized vectors. This metric performed slightly better than the L2 Norm, but the effect was most noticeable on the larger images combined with the pyramid speedup. To compute the normalized cross-correlation metric, you first subtract the mean intensity from each image so they have zero mean. This makes the measure invariant to brightness shifts and centers the data. Then, you compute the dot product of the zero-mean image vectors which measures how much the patterns align. Finally, you compute the magnitude of each vector using the L2 norm and divide the dot product by the product of the magnitudes to normalize. Then, the result is between -1 and 1 where 1 indicates perfect alignment. This adjusts for differences in brightness and contrast compared to simply using Euclidean distance.

i (uiū)(vi) √(∑i (uiū)2) × √(∑i (vi)2)
Result 3
Result 3
Result 3
Improves further with pyramid speedup as shown in gallery below.

Pyramid Search

For larger images, exhaustive search becomes too expensive since the pixel displacement I've set ([-15,15] pixels) is too large. In this case, I implemented a faster search procedure, namely an image pyramid, that represents the image at multiple scales and processes from the smallest image downwards while updating my estimate.

Algorithm Steps:

Images of Choice

I found a couple of images from the Prokudin-Gorskii collection online and ran my algorithm on them. They use the normalized cross-correlation metric without a coarse-to-fine pyramid speedup since they're smaller images.

Result 3
Best Shift: G(7, -1), R(14, 0)
Result 1
Best Shift: G(8, -2), R(16, -6)
Result 2
Best Shift: G(7, 0), R(14, 1)
Result 3
Result 1
Result 2

Image Gallery

Here is the gallery of my algorithm ran on all of the example images provided (other than Emir which is shown up top) using the NCC image metric and image pyramid speedup.

Result 1
Best Shift: G(1, -1), R(7, -1)
Result 2
Best Shift: G(-3, 0), R(3, 1)
Result 3
Best Shift: G(3, 2), R(6, 3)
Result 4
Best Shift: G(39, 22), R(76, 35)
Result 5
Best Shift: G(25, -2), R(61, -14)
Result 6
Best Shift: G(40, 16), R(90, 23)
Result 7
Best Shift: G(-3, -3), R(76, -8)
Result 8
Best Shift: G(41, -11), R(93, -29)
Result 9
Best Shift: G(83, 4), R(176, 7)
Result 10
Best Shift: G(-9703, -7622), R(-9623, -7625)
Result 11
Best Shift: G(-9702, -7641), R(-9654, -7655)
Result 12
Best Shift: G(-9575, -11137), R(-9519, -11135)
Result 13
Best Shift: G(71, -6), R(94, 3)