The goal of this project was to create a colorized image given a .jpg or .tif file from the Prokudin-Gorskii Photo Collection. We were to do this by extracting the RGB color channels from each raw image and applying our algorithm to colorize the photo.
For low-resolution photos (hundreds of pixels), we can apply a naive brute-force approach. First, I cropped each color channel border by 35 pixels. Then, for each non-blue color channel, I iterated over all possible (x, y) offsets with in the range -15 < x < 15 and -15 < y < 15 and chose the one which minimized the sum of squared differences (SSD) between itself and the blue channel. I then stacked all three color channels to generate a colorized image.
For high-resolution photos (thousands of pixels), we want to change our approach to be more efficient. The method I chose was to implement an image pyramid recursively. An image pyramid works by first searching for the best offset for the same image at a lower scale (resolution), then propagating that offset upwards recursively reducing the offset search range at for itself at a higher scale. I chose a scaling factor of .25 with a maximum depth of 5 or when the images were scaled down to a 400 pixel count or less. I cropped each channel border by 800 pixels before processing and kept SSD as my cost function.
To combat variations in brightness, I applied first-order derivative edge detection to my channels through Sobel edge detection using the skimages filters. This feature improvement helped greatly with colorizing and refining images, especially the Emir image, as seen in the before and after below.
before Sobel edge detection after Sobel edge detection (observe Emir no longer has color shadows)
before Sobel edge detection after Sobel edge detection (harder to see, but observe the table leg edges no longer have color shadows)
It was difficult finding the right scaling factor for the pyramid base case. I went though a lot of manual trial and error when searching for the one I thought worked best. I also noticed in the output, there were mismatched borders at times and color flares. I resolved this by cropping the edges of the photos.
Including offsets for examples and other photos. Offsets are in the for of (dx, dy)
required | g: (5, 2), r: (12, 3) required | g: (-3, 2), r: (3, 2)
required | g: (3, 3), r: (6, 3) extra | g: (3, 0), g: (11, 1)
extra | g: (5, 0), r: (14, 1) extra | g: (3, -1), r: (12, -2)
required | g: (43, 23), r: (106, 41) required | g: (33, 2), r: (97, 5)
required | g: (59, 29), r: (123, 18) required | g: (40, 18), r: (89, 24)
required | g: (48, 7), r: (108, 11) required | g: (83, 10), r: (179, 13)
required | g: (49, 26), r: (107, 37) required | g: (77, 29), r: (175, 37)
required | g: (49, 15), r: (108, 12) required | g: (42, 6), r: (85, 32)
required | g: (53, 0), r: (105, -12) extra | g: (34, 7), r: (116, 9)
extra | g: (31, -1), r: (111, -2)