Normalize image brightness

Execution environment

Ubuntu 18.04 Python 3.6.9 OpenCV 3.3.0

Overview

When processing a large number of images, bright and dark photos are mixed, It will affect the processing result, so I want to unify the brightness!

From that thought Since I had the opportunity to adjust the brightness of the image in the pre-processing of learning, I will summarize the method. The purpose is to normalize the input color image to uniform brightness. There are three types of methods I tried.

** ① Histogram flattening ② Adaptive histogram flattening ③ Specify the average and standard deviation of the brightness values **

Click here for a photo for verification. Taj Mahal with haze taj-mahal-1209004_1280.jpg The luminance histogram of this image is distributed as follows. It can be seen that the pixel values are concentrated around 100 to 230. original.png

Library to use

import cv2
import numpy as np
from matplotlib import pyplot as plt

Preprocessing

To handle the brightness value, first acquire a grayscale image. If you specify an argument with imread of OpenCV, you can get a grayscale image in one shot, Since the purpose of this time is to change only the brightness of the color image, color information is also acquired. Therefore, the image is read and converted from RGB (BGR in OpenCV) to HSV.

HSV images ・ Hue (hue) ・ Saturation ・ Value (brightness) It is represented by, and the value of brightness is used in this.

The code to get the Value is as follows.

img=cv2.imread(str(file)) #Image loading
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #Convert to hsv color system
h,s,v = cv2.split(hsv) #Divided into each component

Among h, s, v, v is Value, which is treated as a grayscale image.

The image histogram can be easily displayed with the matplotlib function.

plt.hist(v.ravel(),256,[0,256]);plt.show()

Post-processing

If you mention the post-processing first, Since the variable result, which stores the results of (1) to (3), is a grayscale image that represents the brightness value, Finally, the reverse processing of the preprocessing is performed to return to the color image.

hsv = cv2.merge((h,s,result))
rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite("result.jpg ", rgb) #When outputting

** ① Histogram flattening **

The first method is to flatten the histogram (brightness distribution) of the image. The image of flattening the histogram is as follows.

Histogrammeinebnung.png The word "flattening" gives the impression that the image is smooth, Actually, in order to adjust the pixel value so that it appears evenly from pure black pixels to pure white pixels, The contrast is emphasized and the image becomes clear.

This technique can be confirmed with OpenCV functions. The code is as follows.

result = cv2.equalizeHist(v)

Click here for the resulting image and histogram. result.jpg

equal.png

Looking at the histogram, the pixels around 250 are discrete. This appears in the light gradation part on the upper right of the result image, and the tone jump occurs due to the effect of the contrast being emphasized. jagi.jpg It seems to occur because the histogram distribution of the brightness value of the original image is not uniform. The next adaptive histogram flattening method is to flatten the histogram a little more carefully.

** ② Adaptive histogram flattening **

The second method is to flatten the histogram in (1) for each small area. For detailed mechanism and parameters, refer to Reference. This enables more accurate flattening than ①, but be careful because it will be overemphasized if the parameters are incorrect.

The implementation of adaptive histogram flattening is as follows.

clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(3, 3))
result = clahe.apply(v)

clipLimit is a parameter to limit the contrast. tileGridSize is the size of a small area, this time it is done in a 3x3 area.

Here are the results. adaptive.jpg adaptive.png From the histogram, it can be seen that the pixel values are distributed continuously from ①. The tone jump that occurred in (1) has been alleviated, resulting in a balanced histogram.

** ③ Specify the average and standard deviation of brightness **

The third was based on the here site. A method of obtaining the average value and standard deviation of the brightness of an image and changing them to arbitrary values.

v = (v-np.mean(v)) / np.std(v) * s + m
result = np.array(v, dtype=np.uint8) #Return dtype of array to unit8

--np.mean (v): Average brightness --np.std (v): Standard deviation of brightness

First, an image having an average brightness of 0 and a standard deviation of 1 is generated by subtracting the average value of the brightness from the original image and dividing by the standard deviation. The standard deviation is set by multiplying it by an arbitrary value s, and the brightness average is set by adding an arbitrary value m. This time, s = 32 and m = 128 are set.

Click here for the results. mean32.jpg mean32.png

From the histogram, it can be confirmed that the pixels are aggregated around the average brightness of 128. This time, when returning to a color image, it will be converted to an integer type, so If the brightness is out of the range of 0 to 255 in the calculation result, the result will be incorrect and adjustment is required.

in conclusion

Finally, each result is posted together. Since the conditions after flattening the histogram are different, it is not a performance comparison experiment, but for reference. From the left Original image-①Result-②Result-③Result marge1.jpg marge2.jpg With each method, images taken in various environments can be matched to a certain standard.

This time, only the brightness was normalized, but by normalizing the contrast and saturation as well, You will be able to create a more uniform image.

References

・ Http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_histograms/py_histogram_equalization/py_histogram_equalization.html ・ Https://cvtech.cc/std/

Recommended Posts

Normalize image brightness
Image denoising
Image recognition
Image crawler