Monday, October 28, 2019

Image White Balancing with Python

Below is a photo I took in the viewing deck of Taipei 101. Taipei 101 has a glass wall which is green color. Thus, all photos taken inside the building through the wall has a green cast including this one.




















To remove the cast of green color, we use the technique of image white balancing. First, we need a reference object with known color. Fortunately this photo has clouds (pointed by the arrow). Clouds are good references since they are white. By averaging the pixels of cloud (mean(img_array[400,500:550,:])), the mean of R/G/B is [201.5, 254.9, 253.9]. Since white color has R/G/B channels roughly equal, to make it white, 52 needs to be added to R channel of the whole image. Like DC cancellation in communication, white balancing removes the bias of the signal.

Code below shows how to do white balancing


filename = 'IMG_9254.JPG'
img = image.load_img(filename)
img_array = np.array(image.img_to_array(img),dtype=np.uint8)
img_shape=img_array.shape
plt.figure()
plt.imshow(img_array)

img_array2 = img_array
img_array2 = np.array(img_array2, dtype=np.uint16)
img_array2[:,:,0] = img_array2[:,:,0] + 52 # white balancing
img_array2 = np.clip(img_array2, 0, 255)

The newly generated image after white balancing, img_array2,  is shown below. The color does look more natural. In case that you want to repeat this, code/image can be found here.


Wednesday, October 2, 2019

Note on Implementation of “Fast Noise Variance Estimation” by J. Immerkær

Noise variance estimation is a fundamental task of image processing. Among various approaches of noise variance estimate, fast noise variance estimation method proposed by J. Immerkær in [1] stands out because of its good balance between complexity and accuracy.

Based on J. Immerkær's method, to estimate the standard deviation of image noise \(\sigma\), we can use equations below:

\(F=
\begin{bmatrix}
1 & -2 & 1\\
-2 & 4 & -2\\
1 & -2 & 1\\
\end{bmatrix}
\)

\(\sigma=\frac{\sqrt{\pi/2}}{6(W-2)(H-2)}\sum_{I}|I(x,y)*F|\)

\(F\) is the high-pass filter. To estimate noise variance, filter \(F\) will be applied on the whole image \(I(x,y)\) with convolution. The sum of absolute value of convolution results is normalized by width of height of the image, which is \((W-2)(H-2)\). "-2" counts for the boundary effect. The summation is also scaled by \(\frac{\sqrt{\pi/2}}{6}\), which is explained next.

Assume a 3x3 block of \(I(x,y)\) with each element of \(x_{i}\) to be a Gaussian random variable with mean \(\mu\) and standard deviation \(\sigma\)
\(I=
\begin{bmatrix}
x_{1} & x_{2} & x_{3}\\
x_{4} & x_{5} & x_{6}\\
x_{7} & x_{8} & x_{9}\\
\end{bmatrix}
\)
Then \(|I*F|=|x_{1}-2*x_{2}+x_{3}-2*x_{4}+4*x_{5}-2*x_{6}+x_{7}-2*x_{8}+x_{9}|\)
Since \(E(|I*F|^2)=36\sigma^2\), \(|I*F|=6|s|\) where s is Gaussian random variable with mean 0 and standard deviation \(\sigma\). We can derive the distribution of \(y=|s|\) and it is \(\frac{2}{\sqrt{2\pi}\sigma}e^{-\frac{y^2}{2\sigma^2}}\)  for \(y>=0\) and 0 for \(y < 0\). <0 .="" br=""> 

Since \(E(|s|)=\sqrt{\frac{2}{\pi}}\sigma\), it explains why the summation is also scaled by \(\frac{\sqrt{\pi/2}}{6}\).


[1] J. Immerkær, “Fast Noise Variance Estimation”, Computer Vision and Image Understanding, Vol. 64, No. 2, pp. 300-302, Sep. 1996