Skip to content

Commit 752587e

Browse files
committed
prettify everything
1 parent ab64bb3 commit 752587e

1 file changed

Lines changed: 218 additions & 80 deletions

File tree

1/index.html

Lines changed: 218 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,225 @@
1-
Hello, this blog is aims to talk about how to use OpenCV to colorize a grayscale image. Before the advent of color cameras, a lot of cameras took images of each of the r,g,b channels separately in order to get the actual color back based on this.
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Image Colorization with OpenCV</title>
7+
<style>
8+
body {
9+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
10+
line-height: 1.6;
11+
max-width: 800px;
12+
margin: 0 auto;
13+
padding: 20px;
14+
background-color: #f9f9f9;
15+
color: #333;
16+
}
17+
18+
h1 {
19+
color: #2c3e50;
20+
border-bottom: 3px solid #3498db;
21+
padding-bottom: 10px;
22+
}
23+
24+
h2 {
25+
color: #34495e;
26+
margin-top: 40px;
27+
margin-bottom: 20px;
28+
}
29+
30+
p {
31+
margin-bottom: 15px;
32+
text-align: justify;
33+
}
34+
35+
.image-container {
36+
text-align: center;
37+
margin: 30px 0;
38+
padding: 20px;
39+
background-color: white;
40+
border-radius: 8px;
41+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
42+
}
43+
44+
.image-container img {
45+
max-width: 100%;
46+
height: auto;
47+
border-radius: 5px;
48+
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
49+
}
50+
51+
.image-caption {
52+
margin-top: 10px;
53+
font-style: italic;
54+
color: #666;
55+
font-size: 14px;
56+
}
57+
58+
.gallery {
59+
display: grid;
60+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
61+
gap: 20px;
62+
margin-top: 30px;
63+
}
64+
65+
.gallery-item {
66+
background-color: white;
67+
padding: 15px;
68+
border-radius: 8px;
69+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
70+
text-align: center;
71+
}
72+
73+
.gallery-item img {
74+
width: 100%;
75+
height: auto;
76+
border-radius: 5px;
77+
}
78+
79+
.intro {
80+
background-color: white;
81+
padding: 25px;
82+
border-radius: 8px;
83+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
84+
margin-bottom: 30px;
85+
}
86+
</style>
87+
</head>
88+
<body>
89+
<h1>Image Colorization with OpenCV</h1>
90+
91+
<div class="intro">
92+
<p>This blog explores how to use OpenCV to colorize grayscale images. Before the advent of color cameras, photographers captured images of each RGB channel separately to reconstruct the final color image.</p>
93+
</div>
94+
95+
<p>I will use the following image as an example:</p>
96+
97+
<div class="image-container">
98+
<img src="media/cathedral.jpg" alt="Cathedral original grayscale channels">
99+
<div class="image-caption">Original Cathedral image with separate R, G, B channels</div>
100+
</div>
101+
102+
<p>This image is a grayscale image (only one channel instead of RGB), with each of the 3 sections representing the blue, green, and red channels in grayscale. Our job is to combine these three grayscales to create a color image.</p>
103+
104+
<p>A naive attempt at this will look something like this:</p>
105+
106+
<div class="image-container">
107+
<img src="media/cathedral_0.jpg" alt="Cathedral naive alignment">
108+
<div class="image-caption">Naive alignment - simply stacking the channels without proper alignment</div>
109+
</div>
110+
111+
<p>What we do here is naively chunk the original image into thirds by height and assign the colors respectively. We can see that the images do not align properly.</p>
112+
113+
<p>Thus, we need to align the three images together to get the correct color image. An easy way to start is to find the alignment that reduces the L2 loss, since we know that these colors will generally have high correlation.</p>
114+
115+
<p>Of course, a natural problem that arises here is that after adding some sort of offset, the image dimensions will no longer match up. Thus, we need to find a way to account for this in our norm. One way to do this is to apply the L2 norm on a smaller patch of the image such that both the original and shifted dimensions include the entirety of this smaller patch. I arbitrarily chose the middle 40% of each dimension (meaning we only use 16% total).</p>
116+
117+
<p>Applying this technique to our image, we get the following output:</p>
118+
119+
<div class="image-container">
120+
<img src="media/cathedral_1_L2.jpg" alt="Cathedral L2 alignment">
121+
<div class="image-caption">L2 loss alignment result</div>
122+
</div>
123+
124+
<p>Another way to do this is to use the Normalized Cross Correlation (NCC) loss. The output looks as follows:</p>
125+
126+
<div class="image-container">
127+
<img src="media/cathedral_1_ncc.jpg" alt="Cathedral NCC alignment">
128+
<div class="image-caption">Normalized Cross Correlation (NCC) alignment result</div>
129+
</div>
130+
131+
<h2>Pyramid Search Algorithm</h2>
132+
133+
<p>The problem here is that although this works on a smaller image like this (~300 x 300 pixels), trying to brute force search this on every pixel will take too much time. Thus, we want to implement a pyramid-based search to find the best alignment.</p>
134+
135+
<p>A pyramid-based search starts with a much lower resolution version of the image (downsampled) and finds the best offset for this smaller version. Then, we look at a larger version of it, find an offset (based on the offset of the smaller version) and repeat this process until we reach the original resolution.</p>
136+
137+
<p>In this particular case, the pyramid search results in the same output without any significant speed up. However, consider a different image such as this image of 3 generations:</p>
138+
139+
<div class="image-container">
140+
<img src="media/three_generations.tif" alt="3 Generations original">
141+
<div class="image-caption">Three Generations - original grayscale channels (9629 x 3714 pixels)</div>
142+
</div>
143+
144+
<p>This image is 9629 x 3714 pixels. If we were to use the brute force approach, we would have to search tens of millions of possible alignments, taking minutes if not hours. On the other hand, the pyramid search only takes a few seconds under the right conditions.</p>
145+
146+
<p>Here is the output of the pyramid search:</p>
147+
148+
<div class="image-container">
149+
<img src="media/three_generations_aligned_pyramid.jpg" alt="3 Generations pyramid result">
150+
<div class="image-caption">Three Generations - pyramid search result</div>
151+
</div>
152+
153+
<h2>Gallery of Pyramid Search Results</h2>
154+
155+
<p>Here are the results of the pyramid search algorithm applied to various other images:</p>
156+
157+
<div class="gallery">
158+
<div class="gallery-item">
159+
<img src="media/monastery_aligned_pyramid.jpg" alt="Monastery">
160+
<div class="image-caption">Monastery</div>
161+
</div>
162+
163+
<div class="gallery-item">
164+
<img src="media/tobolsk_aligned_pyramid.jpg" alt="Tobolsk">
165+
<div class="image-caption">Tobolsk</div>
166+
</div>
167+
168+
<div class="gallery-item">
169+
<img src="media/cathedral_aligned_pyramid.jpg" alt="Cathedral">
170+
<div class="image-caption">Cathedral</div>
171+
</div>
172+
173+
<div class="gallery-item">
174+
<img src="media/emir_aligned_pyramid.jpg" alt="Emir">
175+
<div class="image-caption">Emir</div>
176+
</div>
177+
178+
<div class="gallery-item">
179+
<img src="media/italil_aligned_pyramid.jpg" alt="Italil">
180+
<div class="image-caption">Italil</div>
181+
</div>
182+
183+
<div class="gallery-item">
184+
<img src="media/church_aligned_pyramid.jpg" alt="Church">
185+
<div class="image-caption">Church</div>
186+
</div>
2187

3-
I will use the following image as an example:
188+
<div class="gallery-item">
189+
<img src="media/lugano_aligned_pyramid.jpg" alt="Lugano">
190+
<div class="image-caption">Lugano</div>
191+
</div>
4192

5-
<img src="media/cathedral.jpg" alt="Cathedral" width="500">
193+
<div class="gallery-item">
194+
<img src="media/melons_aligned_pyramid.jpg" alt="Melons">
195+
<div class="image-caption">Melons</div>
196+
</div>
6197

7-
This image is a grayscale image (only one channel instead of rgb), with each of the 3 images
8-
representing the blue, green, and red channels in a gray scale. Our job is to get all of these there grayscales and put them together to have a color image.
198+
<div class="gallery-item">
199+
<img src="media/lastochikino_aligned_pyramid.jpg" alt="Lastochikino">
200+
<div class="image-caption">Lastochikino</div>
201+
</div>
9202

10-
A naive attempt at this will look something like this:
203+
<div class="gallery-item">
204+
<img src="media/icon_aligned_pyramid.jpg" alt="Icon">
205+
<div class="image-caption">Icon</div>
206+
</div>
11207

12-
<img src="media/cathedral_0.jpg" alt="Cathedral" width="500">
208+
<div class="gallery-item">
209+
<img src="media/siren_aligned_pyramid.jpg" alt="Siren">
210+
<div class="image-caption">Siren</div>
211+
</div>
13212

14-
What we do here is to that we just naively chunk the original image into 1/3 of the height and assign the colors respectively. We see that the images do not seem to align properly.
15-
Thus, we need to align the three images together to get the correct color image. An easy way to start off would be to find the alignment that reduces the L2 loss since we know that
16-
these colors will generally have pretty high correlation.
213+
<div class="gallery-item">
214+
<img src="media/self_portrait_aligned_pyramid.jpg" alt="Self Portrait">
215+
<div class="image-caption">Self Portrait</div>
216+
</div>
217+
218+
<div class="gallery-item">
219+
<img src="media/harvesters_aligned_pyramid.jpg" alt="Harvesters">
220+
<div class="image-caption">Harvesters</div>
221+
</div>
222+
</div>
17223

18-
Of course, a natural problem that arises here is that after adding some sort of offset, the image dimensions will no longer match up. Thus, we need to find a way to account for this in our norm.
19-
One way to do this is the apply the L2 norm on a smaller patch of the image such that after both the original and shifted dimensions include the entirety of this smaller patch. I arbitrarily chose the middle 40% of each dimension (meaning we only use 16% total).
20-
21-
Applying this technique to our image, we get the following output:
22-
23-
<img src="media/cathedral_1_L2.jpg" alt="Cathedral" width="500">
24-
25-
Another way to do this is to use the Normalized Cross Correlation (NCC) loss. The output looks as follows:
26-
27-
<img src="media/cathedral_1_ncc.jpg" alt="Cathedral" width="500">
28-
29-
30-
The problem here is that although this works on a smaller image like this ~(300 x 300 pixels), trying to brute force search this on every pixel will take too much time. Thus, we want to implement a pyramid based search to find the best alignment.
31-
32-
A pyramid based search starts with a much lower resolution version of the image (downsampled) and finds the best offset for this smaller version.
33-
Then, we look at a larger version of it, finds an offset (based on the offset of the smaller version) and repeats this process until we reach the original resolution.
34-
35-
In this particular case, the pyramid search results in the same output without any significant speed up. However, consider a different image such as this image of 3 generations:
36-
37-
<img src="media/3_generations.tif" alt="3 Generations" width="500">
38-
39-
This image is 9629 x 3714 pixels. If we were to use the brute force approach, we would have to search tens of millions of possible aligments, taking minutes if not hours. On the other hand, the pyramid search only takes a few seconds under the right conditions.
40-
41-
Here is the output of the pyramid search, as well as the output of pyramid search for various images:
42-
43-
<img src="media/3_generations_pyramid.jpg" alt="3 Generations Pyramid" width="500">
44-
45-
<p>Here are the results of the pyramid search algorithm applied to various other images:</p>
46-
47-
<img src="media/monastery_aligned_pyramid.jpg" alt="Monastery" width="500">
48-
<p><em>Monastery</em></p>
49-
50-
<img src="media/tobolsk_aligned_pyramid.jpg" alt="Tobolsk" width="500">
51-
<p><em>Tobolsk</em></p>
52-
53-
<img src="media/cathedral_aligned_pyramid.jpg" alt="Cathedral" width="500">
54-
<p><em>Cathedral</em></p>
55-
56-
<img src="media/emir_aligned_pyramid.jpg" alt="Emir" width="500">
57-
<p><em>Emir</em></p>
58-
59-
<img src="media/italil_aligned_pyramid.jpg" alt="Italil" width="500">
60-
<p><em>Italil</em></p>
61-
62-
<img src="media/church_aligned_pyramid.jpg" alt="Church" width="500">
63-
<p><em>Church</em></p>
64-
65-
<img src="media/three_generations_aligned_pyramid.jpg" alt="Three Generations" width="500">
66-
<p><em>Three Generations</em></p>
67-
68-
<img src="media/lugano_aligned_pyramid.jpg" alt="Lugano" width="500">
69-
<p><em>Lugano</em></p>
70-
71-
<img src="media/melons_aligned_pyramid.jpg" alt="Melons" width="500">
72-
<p><em>Melons</em></p>
73-
74-
<img src="media/lastochikino_aligned_pyramid.jpg" alt="Lastochikino" width="500">
75-
<p><em>Lastochikino</em></p>
76-
77-
<img src="media/icon_aligned_pyramid.jpg" alt="Icon" width="500">
78-
<p><em>Icon</em></p>
79-
80-
<img src="media/siren_aligned_pyramid.jpg" alt="Siren" width="500">
81-
<p><em>Siren</em></p>
82-
83-
<img src="media/self_portrait_aligned_pyramid.jpg" alt="Self Portrait" width="500">
84-
<p><em>Self Portrait</em></p>
85-
86-
<img src="media/harvesters_aligned_pyramid.jpg" alt="Harvesters" width="500">
87-
<p><em>Harvesters</em></p>
224+
</body>
225+
</html>

0 commit comments

Comments
 (0)