1) Converted all images to JPG to reduce size.
2) Added a raw Latex page break directive after each TOC tree. (For the PDF tutorial look). 3) Two finished tutorials: a) one describing how the Mat data structure works and its output capabilities (format function) (demonstration YouTube video included). b) one describing image scanning operations plus the LUT function (demonstration YouTube video included). c) a basic filtering approach (plus multi row image scanning demonstration) in the work.
@@ -34,7 +34,7 @@ Morphological Operations
|
||||
|
||||
* We will explain dilation and erosion briefly, using the following image as an example:
|
||||
|
||||
.. image:: images/Morphology_1_Tutorial_Theory_Original_Image.png
|
||||
.. image:: images/Morphology_1_Tutorial_Theory_Original_Image.jpg
|
||||
:alt: Original image
|
||||
:height: 100px
|
||||
:align: center
|
||||
@@ -48,7 +48,7 @@ Dilation
|
||||
|
||||
* As the kernel :math:`B` is scanned over the image, we compute the maximal pixel value overlapped by :math:`B` and replace the image pixel in the anchor point position with that maximal value. As you can deduce, this maximizing operation causes bright regions within an image to "grow" (therefore the name *dilation*). Take as an example the image above. Applying dilation we can get:
|
||||
|
||||
.. image:: images/Morphology_1_Tutorial_Theory_Dilation.png
|
||||
.. image:: images/Morphology_1_Tutorial_Theory_Dilation.jpg
|
||||
:alt: Dilation result - Theory example
|
||||
:height: 100px
|
||||
:align: center
|
||||
@@ -64,7 +64,7 @@ Erosion
|
||||
|
||||
* Analagously to the example for dilation, we can apply the erosion operator to the original image (shown above). You can see in the result below that the bright areas of the image (the background, apparently), get thinner, whereas the dark zones (the "writing"( gets bigger.
|
||||
|
||||
.. image:: images/Morphology_1_Tutorial_Theory_Erosion.png
|
||||
.. image:: images/Morphology_1_Tutorial_Theory_Erosion.jpg
|
||||
:alt: Erosion result - Theory example
|
||||
:height: 100px
|
||||
:align: center
|
||||
@@ -266,14 +266,14 @@ Results
|
||||
|
||||
* Compile the code above and execute it with an image as argument. For instance, using this image:
|
||||
|
||||
.. image:: images/Morphology_1_Tutorial_Original_Image.png
|
||||
.. image:: images/Morphology_1_Tutorial_Original_Image.jpg
|
||||
:alt: Original image
|
||||
:height: 200px
|
||||
:align: center
|
||||
|
||||
We get the results below. Varying the indices in the Trackbars give different output images, naturally. Try them out! You can even try to add a third Trackbar to control the number of iterations.
|
||||
|
||||
.. image:: images/Morphology_1_Tutorial_Cover.png
|
||||
.. image:: images/Morphology_1_Tutorial_Cover.jpg
|
||||
:alt: Dilation and Erosion application
|
||||
:height: 400px
|
||||
:align: center
|
||||
|
||||
|
After Width: | Height: | Size: 220 KiB |
|
Before Width: | Height: | Size: 344 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 203 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 289 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 1020 B |
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -149,7 +149,7 @@ Code
|
||||
namedWindow( window_name, CV_WINDOW_AUTOSIZE );
|
||||
|
||||
/// Load the source image
|
||||
src = imread( "../images/lena.png", 1 );
|
||||
src = imread( "../images/lena.jpg", 1 );
|
||||
|
||||
if( display_caption( "Original Image" ) != 0 ) { return 0; }
|
||||
|
||||
@@ -318,7 +318,7 @@ Results
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* The code opens an image (in this case *lena.png*) and display it under the effects of the 4 filters explained.
|
||||
* The code opens an image (in this case *lena.jpg*) and display it under the effects of the 4 filters explained.
|
||||
|
||||
* Here is a snapshot of the image smoothed using *medianBlur*:
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ What is a kernel?
|
||||
------------------
|
||||
A kernel is essentially a fixed size array of numerical coefficeints along with an *anchor point* in that array, which is tipically located at the center.
|
||||
|
||||
.. image:: images/filter_2d_tutorial_kernel_theory.png
|
||||
.. image:: images/filter_2d_tutorial_kernel_theory.jpg
|
||||
:alt: kernel example
|
||||
:align: center
|
||||
|
||||
@@ -194,6 +194,6 @@ Results
|
||||
|
||||
#. After compiling the code above, you can execute it giving as argument the path of an image. The result should be a window that shows an image blurred by a normalized filter. Each 0.5 seconds the kernel size should change, as can be seen in the series of snapshots below:
|
||||
|
||||
.. image:: images/filter_2d_tutorial_result.png
|
||||
.. image:: images/filter_2d_tutorial_result.jpg
|
||||
:alt: kernel example
|
||||
:align: center
|
||||
|
||||
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 125 KiB |
@@ -1,183 +1,183 @@
|
||||
.. _hough_circle:
|
||||
|
||||
Hough Circle Transform
|
||||
***********************
|
||||
|
||||
Goal
|
||||
=====
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
* Use the OpenCV function :hough_circles:`HoughCircles <>` to detect circles in an image.
|
||||
|
||||
Theory
|
||||
=======
|
||||
|
||||
Hough Circle Transform
|
||||
------------------------
|
||||
|
||||
* The Hough Circle Transform works in a *roughly* analogous way to the Hough Line Transform explained in the previous tutorial.
|
||||
* In the line detection case, a line was defined by two parameters :math:`(r, \theta)`. In the circle case, we need three parameters to define a circle:
|
||||
|
||||
.. math::
|
||||
|
||||
C : ( x_{center}, y_{center}, r )
|
||||
|
||||
where :math:`(x_{center}, y_{center})` define the center position (gree point) and :math:`r` is the radius, which allows us to completely define a circle, as it can be seen below:
|
||||
|
||||
.. image:: images/Hough_Circle_Tutorial_Theory_0.jpg
|
||||
:alt: Result of detecting circles with Hough Transform
|
||||
:height: 200pt
|
||||
:align: center
|
||||
|
||||
* For sake of efficiency, OpenCV implements a detection method slightly trickier than the standard Hough Transform: *The Hough gradient method*. For more details, please check the book *Learning OpenCV* or your favorite Computer Vision bibliography
|
||||
|
||||
Code
|
||||
======
|
||||
|
||||
#. **What does this program do?**
|
||||
|
||||
* Loads an image and blur it to reduce the noise
|
||||
* Applies the *Hough Circle Transform* to the blurred image .
|
||||
* Display the detected circle in a window.
|
||||
|
||||
.. _hough_circle:
|
||||
|
||||
Hough Circle Transform
|
||||
***********************
|
||||
|
||||
Goal
|
||||
=====
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
* Use the OpenCV function :hough_circles:`HoughCircles <>` to detect circles in an image.
|
||||
|
||||
Theory
|
||||
=======
|
||||
|
||||
Hough Circle Transform
|
||||
------------------------
|
||||
|
||||
* The Hough Circle Transform works in a *roughly* analogous way to the Hough Line Transform explained in the previous tutorial.
|
||||
* In the line detection case, a line was defined by two parameters :math:`(r, \theta)`. In the circle case, we need three parameters to define a circle:
|
||||
|
||||
.. math::
|
||||
|
||||
C : ( x_{center}, y_{center}, r )
|
||||
|
||||
where :math:`(x_{center}, y_{center})` define the center position (gree point) and :math:`r` is the radius, which allows us to completely define a circle, as it can be seen below:
|
||||
|
||||
.. image:: images/Hough_Circle_Tutorial_Theory_0.jpg
|
||||
:alt: Result of detecting circles with Hough Transform
|
||||
:height: 200pt
|
||||
:align: center
|
||||
|
||||
* For sake of efficiency, OpenCV implements a detection method slightly trickier than the standard Hough Transform: *The Hough gradient method*. For more details, please check the book *Learning OpenCV* or your favorite Computer Vision bibliography
|
||||
|
||||
Code
|
||||
======
|
||||
|
||||
#. **What does this program do?**
|
||||
|
||||
* Loads an image and blur it to reduce the noise
|
||||
* Applies the *Hough Circle Transform* to the blurred image .
|
||||
* Display the detected circle in a window.
|
||||
|
||||
.. |TutorialHoughCirclesSimpleDownload| replace:: here
|
||||
.. _TutorialHoughCirclesSimpleDownload: https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/houghlines.cpp
|
||||
.. |TutorialHoughCirclesFancyDownload| replace:: here
|
||||
.. _TutorialHoughCirclesFancyDownload: https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp
|
||||
|
||||
#. The sample code that we will explain can be downloaded from |TutorialHoughCirclesSimpleDownload|_. A slightly fancier version (which shows both Hough standard and probabilistic with trackbars for changing the threshold values) can be found |TutorialHoughCirclesFancyDownload|_.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
/** @function main */
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Mat src, src_gray;
|
||||
|
||||
/// Read the image
|
||||
src = imread( argv[1], 1 );
|
||||
|
||||
if( !src.data )
|
||||
{ return -1; }
|
||||
|
||||
/// Convert it to gray
|
||||
cvtColor( src, src_gray, CV_BGR2GRAY );
|
||||
|
||||
/// Reduce the noise so we avoid false circle detection
|
||||
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
|
||||
|
||||
vector<Vec3f> circles;
|
||||
|
||||
/// Apply the Hough Transform to find the circles
|
||||
HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );
|
||||
|
||||
/// Draw the circles detected
|
||||
for( size_t i = 0; i < circles.size(); i++ )
|
||||
{
|
||||
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
|
||||
int radius = cvRound(circles[i][2]);
|
||||
// circle center
|
||||
circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );
|
||||
// circle outline
|
||||
circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 );
|
||||
}
|
||||
|
||||
/// Show your results
|
||||
namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
|
||||
imshow( "Hough Circle Transform Demo", src );
|
||||
|
||||
waitKey(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Explanation
|
||||
============
|
||||
|
||||
|
||||
#. Load an image
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
src = imread( argv[1], 1 );
|
||||
|
||||
if( !src.data )
|
||||
{ return -1; }
|
||||
|
||||
#. Convert it to grayscale:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
cvtColor( src, src_gray, CV_BGR2GRAY );
|
||||
|
||||
#. Apply a Gaussian blur to reduce noise and avoid false circle detection:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
|
||||
|
||||
#. Proceed to apply Hough Circle Transform:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
vector<Vec3f> circles;
|
||||
|
||||
HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );
|
||||
|
||||
with the arguments:
|
||||
|
||||
* *src_gray*: Input image (grayscale)
|
||||
* *circles*: A vector that stores sets of 3 values: :math:`x_{c}, y_{c}, r` for each detected circle.
|
||||
* *CV_HOUGH_GRADIENT*: Define the detection method. Currently this is the only one available in OpenCV
|
||||
* *dp = 1*: The inverse ratio of resolution
|
||||
* *min_dist = src_gray.rows/8*: Minimum distance between detected centers
|
||||
* *param_1 = 200*: Upper threshold for the internal Canny edge detector
|
||||
* *param_2* = 100*: Threshold for center detection.
|
||||
* *min_radius = 0*: Minimum radio to be detected. If unknown, put zero as default.
|
||||
* *max_radius = 0*: Maximum radius to be detected. If unknown, put zero as default
|
||||
|
||||
#. Draw the detected circles:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
for( size_t i = 0; i < circles.size(); i++ )
|
||||
{
|
||||
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
|
||||
int radius = cvRound(circles[i][2]);
|
||||
// circle center
|
||||
circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );
|
||||
// circle outline
|
||||
circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 );
|
||||
}
|
||||
|
||||
You can see that we will draw the circle(s) on red and the center(s) with a small green dot
|
||||
|
||||
#. Display the detected circle(s):
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
|
||||
imshow( "Hough Circle Transform Demo", src );
|
||||
|
||||
#. Wait for the user to exit the program
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
waitKey(0);
|
||||
|
||||
|
||||
Result
|
||||
=======
|
||||
|
||||
The result of running the code above with a test image is shown below:
|
||||
|
||||
.. image:: images/Hough_Circle_Tutorial_Result.jpg
|
||||
:alt: Result of detecting circles with Hough Transform
|
||||
:align: center
|
||||
|
||||
#. The sample code that we will explain can be downloaded from |TutorialHoughCirclesSimpleDownload|_. A slightly fancier version (which shows both Hough standard and probabilistic with trackbars for changing the threshold values) can be found |TutorialHoughCirclesFancyDownload|_.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
/** @function main */
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Mat src, src_gray;
|
||||
|
||||
/// Read the image
|
||||
src = imread( argv[1], 1 );
|
||||
|
||||
if( !src.data )
|
||||
{ return -1; }
|
||||
|
||||
/// Convert it to gray
|
||||
cvtColor( src, src_gray, CV_BGR2GRAY );
|
||||
|
||||
/// Reduce the noise so we avoid false circle detection
|
||||
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
|
||||
|
||||
vector<Vec3f> circles;
|
||||
|
||||
/// Apply the Hough Transform to find the circles
|
||||
HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );
|
||||
|
||||
/// Draw the circles detected
|
||||
for( size_t i = 0; i < circles.size(); i++ )
|
||||
{
|
||||
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
|
||||
int radius = cvRound(circles[i][2]);
|
||||
// circle center
|
||||
circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );
|
||||
// circle outline
|
||||
circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 );
|
||||
}
|
||||
|
||||
/// Show your results
|
||||
namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
|
||||
imshow( "Hough Circle Transform Demo", src );
|
||||
|
||||
waitKey(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Explanation
|
||||
============
|
||||
|
||||
|
||||
#. Load an image
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
src = imread( argv[1], 1 );
|
||||
|
||||
if( !src.data )
|
||||
{ return -1; }
|
||||
|
||||
#. Convert it to grayscale:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
cvtColor( src, src_gray, CV_BGR2GRAY );
|
||||
|
||||
#. Apply a Gaussian blur to reduce noise and avoid false circle detection:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
|
||||
|
||||
#. Proceed to apply Hough Circle Transform:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
vector<Vec3f> circles;
|
||||
|
||||
HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );
|
||||
|
||||
with the arguments:
|
||||
|
||||
* *src_gray*: Input image (grayscale)
|
||||
* *circles*: A vector that stores sets of 3 values: :math:`x_{c}, y_{c}, r` for each detected circle.
|
||||
* *CV_HOUGH_GRADIENT*: Define the detection method. Currently this is the only one available in OpenCV
|
||||
* *dp = 1*: The inverse ratio of resolution
|
||||
* *min_dist = src_gray.rows/8*: Minimum distance between detected centers
|
||||
* *param_1 = 200*: Upper threshold for the internal Canny edge detector
|
||||
* *param_2* = 100*: Threshold for center detection.
|
||||
* *min_radius = 0*: Minimum radio to be detected. If unknown, put zero as default.
|
||||
* *max_radius = 0*: Maximum radius to be detected. If unknown, put zero as default
|
||||
|
||||
#. Draw the detected circles:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
for( size_t i = 0; i < circles.size(); i++ )
|
||||
{
|
||||
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
|
||||
int radius = cvRound(circles[i][2]);
|
||||
// circle center
|
||||
circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );
|
||||
// circle outline
|
||||
circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 );
|
||||
}
|
||||
|
||||
You can see that we will draw the circle(s) on red and the center(s) with a small green dot
|
||||
|
||||
#. Display the detected circle(s):
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
|
||||
imshow( "Hough Circle Transform Demo", src );
|
||||
|
||||
#. Wait for the user to exit the program
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
waitKey(0);
|
||||
|
||||
|
||||
Result
|
||||
=======
|
||||
|
||||
The result of running the code above with a test image is shown below:
|
||||
|
||||
.. image:: images/Hough_Circle_Tutorial_Result.jpg
|
||||
:alt: Result of detecting circles with Hough Transform
|
||||
:align: center
|
||||
|
||||
@@ -91,13 +91,19 @@ b. **The Probabilistic Hough Line Transform**
|
||||
Code
|
||||
======
|
||||
|
||||
.. |TutorialHoughLinesSimpleDownload| replace:: here
|
||||
.. _TutorialHoughLinesSimpleDownload: https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/houghlines.cpp
|
||||
.. |TutorialHoughLinesFancyDownload| replace:: here
|
||||
.. _TutorialHoughLinesFancyDownload: https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp
|
||||
|
||||
|
||||
#. **What does this program do?**
|
||||
|
||||
* Loads an image
|
||||
* Applies either a *Standard Hough Line Transform* or a *Probabilistic Line Transform*.
|
||||
* Display the original image and the detected line in two windows.
|
||||
|
||||
#. The sample code that we will explain can be downloaded from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/houghlines.cpp>`_. A slightly fancier version (which shows both Hough standard and probabilistic with trackbars for changing the threshold values) can be found `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp>`_
|
||||
#. The sample code that we will explain can be downloaded from |TutorialHoughLinesSimpleDownload|_. A slightly fancier version (which shows both Hough standard and probabilistic with trackbars for changing the threshold values) can be found |TutorialHoughLinesFancyDownload|_.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -113,12 +119,12 @@ Code
|
||||
{
|
||||
cout << "\nThis program demonstrates line finding with the Hough transform.\n"
|
||||
"Usage:\n"
|
||||
"./houghlines <image_name>, Default is pic1.png\n" << endl;
|
||||
"./houghlines <image_name>, Default is pic1.jpg\n" << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const char* filename = argc >= 2 ? argv[1] : "pic1.png";
|
||||
const char* filename = argc >= 2 ? argv[1] : "pic1.jpg";
|
||||
|
||||
Mat src = imread(filename, 0);
|
||||
if(src.empty())
|
||||
|
||||
|
After Width: | Height: | Size: 507 KiB |
|
Before Width: | Height: | Size: 990 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -43,7 +43,7 @@ Opening
|
||||
|
||||
* For instance, check out the example below. The image at the left is the original and the image at the right is the result after applying the opening transformation. We can observe that the small spaces in the corners of the letter tend to dissapear.
|
||||
|
||||
.. image:: images/Morphology_2_Tutorial_Theory_Opening.png
|
||||
.. image:: images/Morphology_2_Tutorial_Theory_Opening.jpg
|
||||
:height: 150pt
|
||||
:alt: Opening
|
||||
:align: center
|
||||
@@ -59,7 +59,7 @@ Closing
|
||||
|
||||
* Useful to remove small holes (dark regions).
|
||||
|
||||
.. image:: images/Morphology_2_Tutorial_Theory_Closing.png
|
||||
.. image:: images/Morphology_2_Tutorial_Theory_Closing.jpg
|
||||
:height: 150pt
|
||||
:alt: Closing example
|
||||
:align: center
|
||||
@@ -76,7 +76,7 @@ Morphological Gradient
|
||||
|
||||
* It is useful for finding the outline of an object as can be seen below:
|
||||
|
||||
.. image:: images/Morphology_2_Tutorial_Theory_Gradient.png
|
||||
.. image:: images/Morphology_2_Tutorial_Theory_Gradient.jpg
|
||||
:height: 150pt
|
||||
:alt: Gradient
|
||||
:align: center
|
||||
@@ -91,7 +91,7 @@ Top Hat
|
||||
|
||||
dst = tophat( src, element ) = src - open( src, element )
|
||||
|
||||
.. image:: images/Morphology_2_Tutorial_Theory_TopHat.png
|
||||
.. image:: images/Morphology_2_Tutorial_Theory_TopHat.jpg
|
||||
:height: 150pt
|
||||
:alt: Top Hat
|
||||
:align: center
|
||||
@@ -105,7 +105,7 @@ Black Hat
|
||||
|
||||
dst = blackhat( src, element ) = close( src, element ) - src
|
||||
|
||||
.. image:: images/Morphology_2_Tutorial_Theory_BlackHat.png
|
||||
.. image:: images/Morphology_2_Tutorial_Theory_BlackHat.jpg
|
||||
:height: 150pt
|
||||
:alt: Black Hat
|
||||
:align: center
|
||||
@@ -279,7 +279,7 @@ Results
|
||||
|
||||
* And here are two snapshots of the display window. The first picture shows the output after using the operator **Opening** with a cross kernel. The second picture (right side, shows the result of using a **Blackhat** operator with an ellipse kernel.
|
||||
|
||||
.. image:: images/Morphology_2_Tutorial_Cover.png
|
||||
.. image:: images/Morphology_2_Tutorial_Cover.jpg
|
||||
:height: 300pt
|
||||
:alt: Morphology 2: Result sample
|
||||
:align: center
|
||||
|
||||
|
After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 242 KiB |
|
After Width: | Height: | Size: 215 KiB |
|
Before Width: | Height: | Size: 496 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 198 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 15 KiB |
@@ -41,7 +41,7 @@ Gaussian Pyramid
|
||||
|
||||
* Imagine the pyramid as a set of layers in which the higher the layer, the smaller the size.
|
||||
|
||||
.. image:: images/Pyramids_Tutorial_Pyramid_Theory.png
|
||||
.. image:: images/Pyramids_Tutorial_Pyramid_Theory.jpg
|
||||
:alt: Pyramid figure
|
||||
:align: center
|
||||
|
||||
@@ -103,7 +103,7 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
printf( " * [ESC] -> Close program \n \n" );
|
||||
|
||||
/// Test image - Make sure it s divisible by 2^{n}
|
||||
src = imread( "../images/chicky_512.png" );
|
||||
src = imread( "../images/chicky_512.jpg" );
|
||||
if( !src.data )
|
||||
{ printf(" No data! -- Exiting the program \n");
|
||||
return -1; }
|
||||
@@ -148,7 +148,7 @@ Explanation
|
||||
.. code-block:: cpp
|
||||
|
||||
/// Test image - Make sure it s divisible by 2^{n}
|
||||
src = imread( "../images/chicky_512.png" );
|
||||
src = imread( "../images/chicky_512.jpg" );
|
||||
if( !src.data )
|
||||
{ printf(" No data! -- Exiting the program \n");
|
||||
return -1; }
|
||||
@@ -235,21 +235,21 @@ Explanation
|
||||
Results
|
||||
========
|
||||
|
||||
* After compiling the code above we can test it. The program calls an image **chicky_512.png** that comes in the *tutorial_code/image* folder. Notice that this image is :math:`512 \times 512`, hence a downsample won't generate any error (:math:`512 = 2^{9}`). The original image is shown below:
|
||||
* After compiling the code above we can test it. The program calls an image **chicky_512.jpg** that comes in the *tutorial_code/image* folder. Notice that this image is :math:`512 \times 512`, hence a downsample won't generate any error (:math:`512 = 2^{9}`). The original image is shown below:
|
||||
|
||||
.. image:: images/Pyramids_Tutorial_Original_Image.png
|
||||
.. image:: images/Pyramids_Tutorial_Original_Image.jpg
|
||||
:alt: Pyramids: Original image
|
||||
:align: center
|
||||
|
||||
* First we apply two successive :pyr_down:`pyrDown <>` operations by pressing 'd'. Our output is:
|
||||
|
||||
.. image:: images/Pyramids_Tutorial_PyrDown_Result.png
|
||||
.. image:: images/Pyramids_Tutorial_PyrDown_Result.jpg
|
||||
:alt: Pyramids: PyrDown Result
|
||||
:align: center
|
||||
|
||||
* Note that we should have lost some resolution due to the fact that we are diminishing the size of the image. This is evident after we apply :pyr_up:`pyrUp <>` twice (by pressing 'u'). Our output is now:
|
||||
|
||||
.. image:: images/Pyramids_Tutorial_PyrUp_Result.png
|
||||
.. image:: images/Pyramids_Tutorial_PyrUp_Result.jpg
|
||||
:alt: Pyramids: PyrUp Result
|
||||
:align: center
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 22 KiB |
@@ -42,7 +42,7 @@ In this section you will learn about the image processing (manipulation) functio
|
||||
|
||||
===================== ==============================================
|
||||
|
||||
.. |ImageProcessing_2| image:: images/Morphology_1_Tutorial_Cover.png
|
||||
.. |ImageProcessing_2| image:: images/Morphology_1_Tutorial_Cover.jpg
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
@@ -61,7 +61,7 @@ In this section you will learn about the image processing (manipulation) functio
|
||||
|
||||
================= ==================================================
|
||||
|
||||
.. |Morphology_2| image:: images/Morphology_2_Tutorial_Cover.png
|
||||
.. |Morphology_2| image:: images/Morphology_2_Tutorial_Cover.jpg
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
@@ -81,7 +81,7 @@ In this section you will learn about the image processing (manipulation) functio
|
||||
|
||||
===================== ==============================================
|
||||
|
||||
.. |Pyramids| image:: images/Pyramids_Tutorial_Cover.png
|
||||
.. |Pyramids| image:: images/Pyramids_Tutorial_Cover.jpg
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
@@ -101,7 +101,7 @@ In this section you will learn about the image processing (manipulation) functio
|
||||
|
||||
===================== ==============================================
|
||||
|
||||
.. |Threshold| image:: images/Threshold_Tutorial_Cover.png
|
||||
.. |Threshold| image:: images/Threshold_Tutorial_Cover.jpg
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
@@ -507,7 +507,9 @@ In this section you will learn about the image processing (manipulation) functio
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\pagebreak
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
|
After Width: | Height: | Size: 214 KiB |
|
Before Width: | Height: | Size: 216 KiB |
|
After Width: | Height: | Size: 215 KiB |
|
Before Width: | Height: | Size: 496 KiB |
|
After Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
Before Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 949 B |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 278 B |
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 336 B |
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 706 B |
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 524 B |
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 706 B |
@@ -28,7 +28,7 @@ What is Thresholding?
|
||||
|
||||
* Once we have separated properly the important pixels, we can set them with a determined value to identify them (i.e. we can assign them a value of :math:`0` (black), :math:`255` (white) or any value that suits your needs).
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Theory_Example.png
|
||||
.. image:: images/Threshold_Tutorial_Theory_Example.jpg
|
||||
:alt: Threshold simple example
|
||||
:height: 150pt
|
||||
:align: center
|
||||
@@ -42,7 +42,7 @@ Types of Thresholding
|
||||
|
||||
* To illustrate how these thresholding processes work, let's consider that we have a source image with pixels with intensity values :math:`src(x,y)`. The plot below depicts this. The horizontal blue line represents the threshold :math:`thresh` (fixed).
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Theory_Base_Figure.png
|
||||
.. image:: images/Threshold_Tutorial_Theory_Base_Figure.jpg
|
||||
:alt: Threshold Binary
|
||||
:height: 100pt
|
||||
:align: center
|
||||
@@ -58,7 +58,7 @@ Threshold Binary
|
||||
|
||||
* So, if the intensity of the pixel :math:`src(x,y)` is higher than :math:`thresh`, then the new pixel intensity is set to a :math:`MaxVal`. Otherwise, the pixels are set to :math:`0`.
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Theory_Binary.png
|
||||
.. image:: images/Threshold_Tutorial_Theory_Binary.jpg
|
||||
:alt: Threshold Binary
|
||||
:height: 100pt
|
||||
:align: center
|
||||
@@ -75,7 +75,7 @@ Threshold Binary, Inverted
|
||||
|
||||
* If the intensity of the pixel :math:`src(x,y)` is higher than :math:`thresh`, then the new pixel intensity is set to a :math:`0`. Otherwise, it is set to :math:`MaxVal`.
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Theory_Binary_Inverted.png
|
||||
.. image:: images/Threshold_Tutorial_Theory_Binary_Inverted.jpg
|
||||
:alt: Threshold Binary Inverted
|
||||
:height: 100pt
|
||||
:align: center
|
||||
@@ -91,7 +91,7 @@ Truncate
|
||||
|
||||
* The maximum intensity value for the pixels is :math:`thresh`, if :math:`src(x,y)` is greater, then its value is *truncated*. See figure below:
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Theory_Truncate.png
|
||||
.. image:: images/Threshold_Tutorial_Theory_Truncate.jpg
|
||||
:alt: Threshold Truncate
|
||||
:height: 100pt
|
||||
:align: center
|
||||
@@ -109,7 +109,7 @@ Threshold to Zero
|
||||
|
||||
* If :math:`src(x,y)` is lower than :math:`thresh`, the new pixel value will be set to :math:`0`.
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Theory_Zero.png
|
||||
.. image:: images/Threshold_Tutorial_Theory_Zero.jpg
|
||||
:alt: Threshold Zero
|
||||
:height: 100pt
|
||||
:align: center
|
||||
@@ -126,7 +126,7 @@ Threshold to Zero, Inverted
|
||||
|
||||
* If :math:`src(x,y)` is greater than :math:`thresh`, the new pixel value will be set to :math:`0`.
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Theory_Zero_Inverted.png
|
||||
.. image:: images/Threshold_Tutorial_Theory_Zero_Inverted.jpg
|
||||
:alt: Threshold Zero Inverted
|
||||
:height: 100pt
|
||||
:align: center
|
||||
@@ -296,7 +296,7 @@ Results
|
||||
#. After compiling this program, run it giving a path to an image as argument. For instance, for an input image as:
|
||||
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Original_Image.png
|
||||
.. image:: images/Threshold_Tutorial_Original_Image.jpg
|
||||
:alt: Threshold Original Image
|
||||
:height: 200pt
|
||||
:align: center
|
||||
@@ -304,7 +304,7 @@ Results
|
||||
#. First, we try to threshold our image with a *binary threhold inverted*. We expect that the pixels brighter than the :math:`thresh` will turn dark, which is what actually happens, as we can see in the snapshot below (notice from the original image, that the doggie's tongue and eyes are particularly bright in comparison with the image, this is reflected in the output image).
|
||||
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Result_Binary_Inverted.png
|
||||
.. image:: images/Threshold_Tutorial_Result_Binary_Inverted.jpg
|
||||
:alt: Threshold Result Binary Inverted
|
||||
:height: 200pt
|
||||
:align: center
|
||||
@@ -312,7 +312,7 @@ Results
|
||||
|
||||
#. Now we try with the *threshold to zero*. With this, we expect that the darkest pixels (below the threshold) will become completely black, whereas the pixels with value greater than the threshold will keep its original value. This is verified by the following snapshot of the output image:
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Result_Zero.png
|
||||
.. image:: images/Threshold_Tutorial_Result_Zero.jpg
|
||||
:alt: Threshold Result Zero
|
||||
:height: 200pt
|
||||
:align: center
|
||||
|
||||