58d37c8570d791d2bb2b24ce7eb5e493cdb46a1b
[platform/upstream/opencv.git] / doc / tutorials / core / basic_linear_transform / basic_linear_transform.markdown
1 Changing the contrast and brightness of an image! {#tutorial_basic_linear_transform}
2 =================================================
3
4 Goal
5 ----
6
7 In this tutorial you will learn how to:
8
9 -   Access pixel values
10 -   Initialize a matrix with zeros
11 -   Learn what @ref cv::saturate_cast does and why it is useful
12 -   Get some cool info about pixel transformations
13 -   Improve the brightness of an image on a practical example
14
15 Theory
16 ------
17
18 @note
19    The explanation below belongs to the book [Computer Vision: Algorithms and
20     Applications](http://szeliski.org/Book/) by Richard Szeliski
21
22 ### Image Processing
23
24 -   A general image processing operator is a function that takes one or more input images and
25     produces an output image.
26 -   Image transforms can be seen as:
27     -   Point operators (pixel transforms)
28     -   Neighborhood (area-based) operators
29
30 ### Pixel Transforms
31
32 -   In this kind of image processing transform, each output pixel's value depends on only the
33     corresponding input pixel value (plus, potentially, some globally collected information or
34     parameters).
35 -   Examples of such operators include *brightness and contrast adjustments* as well as color
36     correction and transformations.
37
38 ### Brightness and contrast adjustments
39
40 -   Two commonly used point processes are *multiplication* and *addition* with a constant:
41
42     \f[g(x) = \alpha f(x) + \beta\f]
43
44 -   The parameters \f$\alpha > 0\f$ and \f$\beta\f$ are often called the *gain* and *bias* parameters;
45     sometimes these parameters are said to control *contrast* and *brightness* respectively.
46 -   You can think of \f$f(x)\f$ as the source image pixels and \f$g(x)\f$ as the output image pixels. Then,
47     more conveniently we can write the expression as:
48
49     \f[g(i,j) = \alpha \cdot f(i,j) + \beta\f]
50
51     where \f$i\f$ and \f$j\f$ indicates that the pixel is located in the *i-th* row and *j-th* column.
52
53 Code
54 ----
55
56 -   The following code performs the operation \f$g(i,j) = \alpha \cdot f(i,j) + \beta\f$ :
57 @include BasicLinearTransforms.cpp
58
59 Explanation
60 -----------
61
62 -#  We begin by creating parameters to save \f$\alpha\f$ and \f$\beta\f$ to be entered by the user:
63     @snippet BasicLinearTransforms.cpp basic-linear-transform-parameters
64
65 -#  We load an image using @ref cv::imread and save it in a Mat object:
66     @snippet BasicLinearTransforms.cpp basic-linear-transform-load
67 -#  Now, since we will make some transformations to this image, we need a new Mat object to store
68     it. Also, we want this to have the following features:
69
70     -   Initial pixel values equal to zero
71     -   Same size and type as the original image
72     @snippet BasicLinearTransforms.cpp basic-linear-transform-output
73     We observe that @ref cv::Mat::zeros returns a Matlab-style zero initializer based on
74     *image.size()* and *image.type()*
75
76 -#  Now, to perform the operation \f$g(i,j) = \alpha \cdot f(i,j) + \beta\f$ we will access to each
77     pixel in image. Since we are operating with BGR images, we will have three values per pixel (B,
78     G and R), so we will also access them separately. Here is the piece of code:
79     @snippet BasicLinearTransforms.cpp basic-linear-transform-operation
80     Notice the following:
81     -   To access each pixel in the images we are using this syntax: *image.at\<Vec3b\>(y,x)[c]*
82         where *y* is the row, *x* is the column and *c* is R, G or B (0, 1 or 2).
83     -   Since the operation \f$\alpha \cdot p(i,j) + \beta\f$ can give values out of range or not
84         integers (if \f$\alpha\f$ is float), we use cv::saturate_cast to make sure the
85         values are valid.
86
87 -#  Finally, we create windows and show the images, the usual way.
88     @snippet BasicLinearTransforms.cpp basic-linear-transform-display
89
90 @note
91     Instead of using the **for** loops to access each pixel, we could have simply used this command:
92     @code{.cpp}
93     image.convertTo(new_image, -1, alpha, beta);
94     @endcode
95     where @ref cv::Mat::convertTo would effectively perform *new_image = a*image + beta\*. However, we
96     wanted to show you how to access each pixel. In any case, both methods give the same result but
97     convertTo is more optimized and works a lot faster.
98
99 Result
100 ------
101
102 -   Running our code and using \f$\alpha = 2.2\f$ and \f$\beta = 50\f$
103     @code{.bash}
104     $ ./BasicLinearTransforms lena.jpg
105     Basic Linear Transforms
106     -------------------------
107     * Enter the alpha value [1.0-3.0]: 2.2
108     * Enter the beta value [0-100]: 50
109     @endcode
110
111 -   We get this:
112
113     ![](images/Basic_Linear_Transform_Tutorial_Result_big.jpg)
114
115 Practical example
116 ----
117
118 In this paragraph, we will put into practice what we have learned to correct an underexposed image by adjusting the brightness
119 and the contrast of the image. We will also see another technique to correct the brightness of an image called
120 gamma correction.
121
122 ### Brightness and contrast adjustments
123
124 Increasing (/ decreasing) the \f$\beta\f$ value will add (/ subtract) a constant value to every pixel. Pixel values outside of the [0 ; 255]
125 range will be saturated (i.e. a pixel value higher (/ lesser) than 255 (/ 0) will be clamp to 255 (/ 0)).
126
127 ![In light gray, histogram of the original image, in dark gray when brightness = 80 in Gimp](images/Basic_Linear_Transform_Tutorial_hist_beta.png)
128
129 The histogram represents for each color level the number of pixels with that color level. A dark image will have many pixels with
130 low color value and thus the histogram will present a peak in his left part. When adding a constant bias, the histogram is shifted to the
131 right as we have added a constant bias to all the pixels.
132
133 The \f$\alpha\f$ parameter will modify how the levels spread. If \f$ \alpha < 1 \f$, the color levels will be compressed and the result
134 will be an image with less contrast.
135
136 ![In light gray, histogram of the original image, in dark gray when contrast < 0 in Gimp](images/Basic_Linear_Transform_Tutorial_hist_alpha.png)
137
138 Note that these histograms have been obtained using the Brightness-Contrast tool in the Gimp software. The brightness tool should be
139 identical to the \f$\beta\f$ bias parameters but the contrast tool seems to differ to the \f$\alpha\f$ gain where the output range
140 seems to be centered with Gimp (as you can notice in the previous histogram).
141
142 It can occur that playing with the \f$\beta\f$ bias will improve the brightness but in the same time the image will appear with a
143 slight veil as the contrast will be reduced. The \f$\alpha\f$ gain can be used to diminue this effect but due to the saturation,
144 we will lose some details in the original bright regions.
145
146 ### Gamma correction
147
148 [Gamma correction](https://en.wikipedia.org/wiki/Gamma_correction) can be used to correct the brightness of an image by using a non
149 linear transformation between the input values and the mapped output values:
150
151 \f[O = \left( \frac{I}{255} \right)^{\gamma} \times 255\f]
152
153 As this relation is non linear, the effect will not be the same for all the pixels and will depend to their original value.
154
155 ![Plot for different values of gamma](images/Basic_Linear_Transform_Tutorial_gamma.png)
156
157 When \f$ \gamma < 1 \f$, the original dark regions will be brighter and the histogram will be shifted to the right whereas it will
158 be the opposite with \f$ \gamma > 1 \f$.
159
160 ### Correct an underexposed image
161
162 The following image has been corrected with: \f$ \alpha = 1.3 \f$ and \f$ \beta = 40 \f$.
163
164 ![By Visem (Own work) [CC BY-SA 3.0], via Wikimedia Commons](images/Basic_Linear_Transform_Tutorial_linear_transform_correction.jpg)
165
166 The overall brightness has been improved but you can notice that the clouds are now greatly saturated due to the numerical saturation
167 of the implementation used ([highlight clipping](https://en.wikipedia.org/wiki/Clipping_(photography)) in photography).
168
169 The following image has been corrected with: \f$ \gamma = 0.4 \f$.
170
171 ![By Visem (Own work) [CC BY-SA 3.0], via Wikimedia Commons](images/Basic_Linear_Transform_Tutorial_gamma_correction.jpg)
172
173 The gamma correction should tend to add less saturation effect as the mapping is non linear and there is no numerical saturation possible as in the previous method.
174
175 ![Left: histogram after alpha, beta correction ; Center: histogram of the original image ; Right: histogram after the gamma correction](images/Basic_Linear_Transform_Tutorial_histogram_compare.png)
176
177 The previous figure compares the histograms for the three images (the y-ranges are not the same between the three histograms).
178 You can notice that most of the pixel values are in the lower part of the histogram for the original image. After \f$ \alpha \f$,
179 \f$ \beta \f$ correction, we can observe a big peak at 255 due to the saturation as well as a shift in the right.
180 After gamma correction, the histogram is shifted to the right but the pixels in the dark regions are more shifted
181 (see the gamma curves [figure](Basic_Linear_Transform_Tutorial_gamma.png)) than those in the bright regions.
182
183 In this tutorial, you have seen two simple methods to adjust the contrast and the brightness of an image. **They are basic techniques
184 and are not intended to be used as a replacement of a raster graphics editor!**
185
186 ### Code
187
188 Code for the tutorial is [here](https://github.com/opencv/opencv/blob/3.4/samples/cpp/tutorial_code/ImgProc/changing_contrast_brightness_image/changing_contrast_brightness_image.cpp).
189 Code for the gamma correction:
190
191 @snippet changing_contrast_brightness_image.cpp changing-contrast-brightness-gamma-correction
192
193 A look-up table is used to improve the performance of the computation as only 256 values needs to be calculated once.
194
195 ### Additional resources
196
197 -   [Gamma correction in graphics rendering](https://learnopengl.com/#!Advanced-Lighting/Gamma-Correction)
198 -   [Gamma correction and images displayed on CRT monitors](http://www.graphics.cornell.edu/~westin/gamma/gamma.html)
199 -   [Digital exposure techniques](http://www.cambridgeincolour.com/tutorials/digital-exposure-techniques.htm)