mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Deleting old tutorial files and put them in folders
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
.. _Basic_Linear_Transform:
|
||||
|
||||
Changing the contrast and brightness of an image!
|
||||
***************************************************
|
||||
|
||||
Goal
|
||||
=====
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
* Access pixel values
|
||||
|
||||
* Initialize a matrix with zeros
|
||||
|
||||
* Learn what :saturate_cast:`saturate_cast <>` does and why it is useful
|
||||
|
||||
* Get some cool info about pixel transformations
|
||||
|
||||
Cool Theory
|
||||
=================
|
||||
|
||||
.. note::
|
||||
The explanation below belongs to the book `Computer Vision: Algorithms and Applications <http://szeliski.org/Book/>`_ by Richard Szeliski
|
||||
|
||||
Image Processing
|
||||
--------------------
|
||||
|
||||
* A general image processing operator is a function that takes one or more input images and produces an output image.
|
||||
|
||||
* Image transforms can be seen as:
|
||||
|
||||
* Point operators (pixel transforms)
|
||||
* Neighborhood (area-based) operators
|
||||
|
||||
|
||||
Pixel Transforms
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
* In this kind of image processing transform, each output pixel's value depends on only the corresponding input pixel value (plus, potentially, some globally collected information or parameters).
|
||||
|
||||
* Examples of such operators include *brightness and contrast adjustments* as well as color correction and transformations.
|
||||
|
||||
Brightness and contrast adjustments
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Two commonly used point processes are *multiplication* and *addition* with a constant:
|
||||
|
||||
.. math::
|
||||
|
||||
g(x) = \alpha f(x) + \beta
|
||||
|
||||
* The parameters :math:`\alpha > 0` and :math:`\beta` are often called the *gain* and *bias* parameters; sometimes these parameters are said to control *contrast* and *brightness* respectively.
|
||||
|
||||
* You can think of :math:`f(x)` as the source image pixels and :math:`g(x)` as the output image pixels. Then, more conveniently we can write the expression as:
|
||||
|
||||
.. math::
|
||||
|
||||
g(i,j) = \alpha \cdot f(i,j) + \beta
|
||||
where :math:`i` and :math:`j` indicates that the pixel is located in the *i-th* row and *j-th* column.
|
||||
|
||||
Code
|
||||
=====
|
||||
|
||||
* The following code performs the operation :math:`g(i,j) = \alpha \cdot f(i,j) + \beta`
|
||||
* Here it is:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <cv.h>
|
||||
#include <highgui.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
double alpha; /**< Simple contrast control */
|
||||
int beta; /**< Simple brightness control */
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
/// Read image given by user
|
||||
Mat image = imread( argv[1] );
|
||||
Mat new_image = Mat::zeros( image.size(), image.type() );
|
||||
|
||||
/// Initialize values
|
||||
std::cout<<" Basic Linear Transforms "<<std::endl;
|
||||
std::cout<<"-------------------------"<<std::endl;
|
||||
std::cout<<"* Enter the alpha value [1.0-3.0]: ";std::cin>>alpha;
|
||||
std::cout<<"* Enter the beta value [0-100]: "; std::cin>>beta;
|
||||
|
||||
/// Do the operation new_image(i,j) = alpha*image(i,j) + beta
|
||||
for( int y = 0; y < image.rows; y++ )
|
||||
{ for( int x = 0; x < image.cols; x++ )
|
||||
{ for( int c = 0; c < 3; c++ )
|
||||
{
|
||||
new_image.at<Vec3b>(y,x)[c] = saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create Windows
|
||||
namedWindow("Original Image", 1);
|
||||
namedWindow("New Image", 1);
|
||||
|
||||
/// Show stuff
|
||||
imshow("Original Image", image);
|
||||
imshow("New Image", new_image);
|
||||
|
||||
/// Wait until user press some key
|
||||
waitKey();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Explanation
|
||||
============
|
||||
|
||||
#. We begin by creating parameters to save :math:`\alpha` and :math:`\beta` to be entered by the user:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
double alpha;
|
||||
int beta;
|
||||
|
||||
|
||||
#. We load an image using :imread:`imread <>` and save it in a Mat object:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
Mat image = imread( argv[1] );
|
||||
|
||||
#. Now, since we will make some transformations to this image, we need a new Mat object to store it. Also, we want this to have the following features:
|
||||
|
||||
* Initial pixel values equal to zero
|
||||
* Same size and type as the original image
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
Mat new_image = Mat::zeros( image.size(), image.type() );
|
||||
|
||||
We observe that :mat_zeros:`Mat::zeros <>` returns a Matlab-style zero initializer based on *image.size()* and *image.type()*
|
||||
|
||||
#. Now, to perform the operation :math:`g(i,j) = \alpha \cdot f(i,j) + \beta` we will access to each pixel in image. Since we are operating with RGB images, we will have three values per pixel (R, G and B), so we will also access them separately. Here is the piece of code:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
for( int y = 0; y < image.rows; y++ )
|
||||
{ for( int x = 0; x < image.cols; x++ )
|
||||
{ for( int c = 0; c < 3; c++ )
|
||||
{ new_image.at<Vec3b>(y,x)[c] = saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta ); }
|
||||
}
|
||||
}
|
||||
|
||||
Notice the following:
|
||||
|
||||
* To access each pixel in the images we are using this syntax: *image.at<Vec3b>(y,x)[c]* where *y* is the row, *x* is the column and *c* is R, G or B (0, 1 or 2).
|
||||
|
||||
* Since the operation :math:`\alpha \cdot p(i,j) + \beta` can give values out of range or not integers (if :math:`\alpha` is float), we use :saturate_cast:`saturate_cast <>` to make sure the values are valid.
|
||||
|
||||
|
||||
#. Finally, we create windows and show the images, the usual way.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
namedWindow("Original Image", 1);
|
||||
namedWindow("New Image", 1);
|
||||
|
||||
imshow("Original Image", image);
|
||||
imshow("New Image", new_image);
|
||||
|
||||
waitKey(0);
|
||||
|
||||
.. note::
|
||||
|
||||
Instead of using the **for** loops to access each pixel, we could have simply used this command:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
image.convertTo(new_image, -1, alpha, beta);
|
||||
|
||||
where :convert_to:`convertTo <>` would effectively perform *new_image = a*image + beta*. However, we wanted to show you how to access each pixel. In any case, both methods give the same result.
|
||||
|
||||
Result
|
||||
=======
|
||||
|
||||
* Running our code and using :math:`\alpha = 2.2` and :math:`\beta = 50`
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ./BasicLinearTransforms lena.png
|
||||
Basic Linear Transforms
|
||||
-------------------------
|
||||
* Enter the alpha value [1.0-3.0]: 2.2
|
||||
* Enter the beta value [0-100]: 50
|
||||
|
||||
* We get this:
|
||||
|
||||
.. image:: images/Basic_Linear_Transform_Tutorial_Result_0.png
|
||||
:height: 400px
|
||||
:alt: Basic Linear Transform - Final Result
|
||||
:align: center
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 860 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 472 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 251 KiB |
Reference in New Issue
Block a user