copied the latest tutorials & find_obj.py sample from trunk to 2.3 branch
@@ -355,10 +355,32 @@ extlinks = {'cvt_color': ('http://opencv.willowgarage.com/documentation/cpp/imgp
|
||||
'utilitysystemfunctions':('http://opencv.itseez.com/modules/core/doc/utility_and_system_functions_and_macros.html#%s', None),
|
||||
'imgprocfilter':('http://opencv.itseez.com/modules/imgproc/doc/filtering.html#%s', None),
|
||||
'svms':('http://opencv.itseez.com/modules/ml/doc/support_vector_machines.html#%s', None),
|
||||
'drawingfunc':('http://opencv.itseez.com/modules/core/doc/drawing_functions.html#%s', None),
|
||||
'xmlymlpers':('http://opencv.itseez.com/modules/core/doc/xml_yaml_persistence.html#%s', None),
|
||||
'huivideo' : ('http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None),
|
||||
'filtering':('http://opencv.itseez.com/modules/imgproc/doc/filtering.html#%s', None),
|
||||
'point_polygon_test' : ('http://opencv.willowgarage.com/documentation/cpp/imgproc_structural_analysis_and_shape_descriptors.html#cv-pointpolygontest%s', None)
|
||||
'gpuinit' : ('http://opencv.itseez.com/modules/gpu/doc/initalization_and_information.html#%s', None),
|
||||
'gpudatastructure' : ('http://opencv.itseez.com/modules/gpu/doc/data_structures.html#%s', None),
|
||||
'gpuopmatrices' : ('http://opencv.itseez.com/modules/gpu/doc/operations_on_matrices.html#%s', None),
|
||||
'gpuperelement' : ('http://opencv.itseez.com/modules/gpu/doc/per_element_operations.html#%s', None),
|
||||
'gpuimgproc' : ('http://opencv.itseez.com/modules/gpu/doc/image_processing.html#%s', None),
|
||||
'gpumatrixreduct' : ('http://opencv.itseez.com/modules/gpu/doc/matrix_reductions.html#%s', None),'filtering':('http://opencv.itseez.com/modules/imgproc/doc/filtering.html#%s', None),
|
||||
'point_polygon_test' : ('http://opencv.willowgarage.com/documentation/cpp/imgproc_structural_analysis_and_shape_descriptors.html#cv-pointpolygontest%s', None),
|
||||
'feature_detector' : ( 'http://opencv.willowgarage.com/documentation/cpp/features2d_common_interfaces_of_feature_detectors.html#featuredetector%s', None),
|
||||
'feature_detector_detect' : ('http://opencv.willowgarage.com/documentation/cpp/features2d_common_interfaces_of_feature_detectors.html#cv-featuredetector-detect%s', None ),
|
||||
'surf_feature_detector' : ('http://opencv.willowgarage.com/documentation/cpp/features2d_common_interfaces_of_feature_detectors.html#surffeaturedetector%s', None ),
|
||||
'draw_keypoints' : ('http://opencv.willowgarage.com/documentation/cpp/features2d_drawing_function_of_keypoints_and_matches.html#cv-drawkeypoints%s', None ),
|
||||
'descriptor_extractor': ( 'http://opencv.willowgarage.com/documentation/cpp/features2d_common_interfaces_of_descriptor_extractors.html#descriptorextractor%s', None ),
|
||||
'descriptor_extractor_compute' : ( 'http://opencv.willowgarage.com/documentation/cpp/features2d_common_interfaces_of_descriptor_extractors.html#cv-descriptorextractor-compute%s', None ),
|
||||
'surf_descriptor_extractor' : ( 'http://opencv.willowgarage.com/documentation/cpp/features2d_common_interfaces_of_descriptor_extractors.html#surfdescriptorextractor%s', None ),
|
||||
'draw_matches' : ( 'http://opencv.willowgarage.com/documentation/cpp/features2d_drawing_function_of_keypoints_and_matches.html#cv-drawmatches%s', None ),
|
||||
'find_homography' : ('http://opencv.willowgarage.com/documentation/cpp/calib3d_camera_calibration_and_3d_reconstruction.html?#findHomography%s', None),
|
||||
'perspective_transform' : ('http://opencv.willowgarage.com/documentation/cpp/core_operations_on_arrays.html?#perspectiveTransform%s', None ),
|
||||
'flann_based_matcher' : ('http://opencv.willowgarage.com/documentation/cpp/features2d_common_interfaces_of_descriptor_matchers.html?#FlannBasedMatcher%s', None),
|
||||
'brute_force_matcher' : ('http://opencv.willowgarage.com/documentation/cpp/features2d_common_interfaces_of_descriptor_matchers.html?#BruteForceMatcher%s', None ),
|
||||
'flann' : ('http://opencv.willowgarage.com/documentation/cpp/flann_fast_approximate_nearest_neighbor_search.html?%s', None ),
|
||||
'cascade_classifier' : ('http://opencv.willowgarage.com/documentation/cpp/objdetect_cascade_classification.html#cascadeclassifier%s', None ),
|
||||
'cascade_classifier_load' : ('http://opencv.willowgarage.com/documentation/cpp/objdetect_cascade_classification.html#cv-cascadeclassifier-load%s', None ),
|
||||
'cascade_classifier_detect_multiscale' : ('http://opencv.willowgarage.com/documentation/cpp/objdetect_cascade_classification.html#cv-cascadeclassifier-detectmultiscale%s', None )
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,11 +8,13 @@ Goal
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
* What is *linear blending* and why it is useful.
|
||||
* Add two images using :add_weighted:`addWeighted <>`
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
Cool Theory
|
||||
=================
|
||||
* What is *linear blending* and why it is useful.
|
||||
* Add two images using :add_weighted:`addWeighted <>`
|
||||
|
||||
Theory
|
||||
=======
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -24,12 +26,12 @@ From our previous tutorial, we know already a bit of *Pixel operators*. An inter
|
||||
|
||||
g(x) = (1 - \alpha)f_{0}(x) + \alpha f_{1}(x)
|
||||
|
||||
By varying :math:`\alpha` from :math:`0 \rightarrow 1` this operator can be used to perform a temporal *cross-disolve* between two images or videos, as seen in slide shows and film production (cool, eh?)
|
||||
By varying :math:`\alpha` from :math:`0 \rightarrow 1` this operator can be used to perform a temporal *cross-disolve* between two images or videos, as seen in slide shows and film productions (cool, eh?)
|
||||
|
||||
Code
|
||||
=====
|
||||
|
||||
As usual, after the not-so-lengthy explanation, let's go to the code. Here it is:
|
||||
As usual, after the not-so-lengthy explanation, let's go to the code:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -116,4 +118,4 @@ Result
|
||||
|
||||
.. image:: images/Adding_Images_Tutorial_Result_0.jpg
|
||||
:alt: Blending Images Tutorial - Final Result
|
||||
:align: center
|
||||
:align: center
|
||||
|
||||
@@ -7,13 +7,15 @@ Goals
|
||||
======
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
* Use :point:`Point <>` to define 2D points in an image.
|
||||
* Use :scalar:`Scalar <>` and why it is useful
|
||||
* Draw a **line** by using the OpenCV function :line:`line <>`
|
||||
* Draw an **ellipse** by using the OpenCV function :ellipse:`ellipse <>`
|
||||
* Draw a **rectangle** by using the OpenCV function :rectangle:`rectangle <>`
|
||||
* Draw a **circle** by using the OpenCV function :circle:`circle <>`
|
||||
* Draw a **filled polygon** by using the OpenCV function :fill_poly:`fillPoly <>`
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use :point:`Point <>` to define 2D points in an image.
|
||||
* Use :scalar:`Scalar <>` and why it is useful
|
||||
* Draw a **line** by using the OpenCV function :line:`line <>`
|
||||
* Draw an **ellipse** by using the OpenCV function :ellipse:`ellipse <>`
|
||||
* Draw a **rectangle** by using the OpenCV function :rectangle:`rectangle <>`
|
||||
* Draw a **circle** by using the OpenCV function :circle:`circle <>`
|
||||
* Draw a **filled polygon** by using the OpenCV function :fill_poly:`fillPoly <>`
|
||||
|
||||
OpenCV Theory
|
||||
===============
|
||||
@@ -22,7 +24,10 @@ For this tutorial, we will heavily use two structures: :point:`Point <>` and :sc
|
||||
|
||||
Point
|
||||
-------
|
||||
It represents a 2D point, specified by its image coordinates :math:`x` and :math:`y`. We can define it as:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
It represents a 2D point, specified by its image coordinates :math:`x` and :math:`y`. We can define it as:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -51,7 +56,7 @@ Scalar
|
||||
|
||||
Code
|
||||
=====
|
||||
* This code is in your OpenCV sample folder. Otherwise you can grab it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/Basic/Drawing_1.cpp>`_
|
||||
* This code is in your OpenCV sample folder. Otherwise you can grab it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp>`_
|
||||
|
||||
Explanation
|
||||
=============
|
||||
@@ -126,11 +131,13 @@ Explanation
|
||||
|
||||
As we can see, *MyLine* just call the function :line:`line <>`, which does the following:
|
||||
|
||||
* Draw a line from Point **start** to Point **end**
|
||||
* The line is displayed in the image **img**
|
||||
* The line color is defined by **Scalar( 0, 0, 0)** which is the RGB value correspondent to **Black**
|
||||
* The line thickness is set to **thickness** (in this case 2)
|
||||
* The line is a 8-connected one (**lineType** = 8)
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Draw a line from Point **start** to Point **end**
|
||||
* The line is displayed in the image **img**
|
||||
* The line color is defined by **Scalar( 0, 0, 0)** which is the RGB value correspondent to **Black**
|
||||
* The line thickness is set to **thickness** (in this case 2)
|
||||
* The line is a 8-connected one (**lineType** = 8)
|
||||
|
||||
* *MyEllipse*
|
||||
|
||||
@@ -153,13 +160,15 @@ Explanation
|
||||
}
|
||||
|
||||
From the code above, we can observe that the function :ellipse:`ellipse <>` draws an ellipse such that:
|
||||
|
||||
* The ellipse is displayed in the image **img**
|
||||
* The ellipse center is located in the point **(w/2.0, w/2.0)** and is enclosed in a box of size **(w/4.0, w/16.0)**
|
||||
* The ellipse is rotated **angle** degrees
|
||||
* The ellipse extends an arc between **0** and **360** degrees
|
||||
* The color of the figure will be **Scalar( 255, 255, 0)** which means blue in RGB value.
|
||||
* The ellipse's **thickness** is 2.
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* The ellipse is displayed in the image **img**
|
||||
* The ellipse center is located in the point **(w/2.0, w/2.0)** and is enclosed in a box of size **(w/4.0, w/16.0)**
|
||||
* The ellipse is rotated **angle** degrees
|
||||
* The ellipse extends an arc between **0** and **360** degrees
|
||||
* The color of the figure will be **Scalar( 255, 255, 0)** which means blue in RGB value.
|
||||
* The ellipse's **thickness** is 2.
|
||||
|
||||
|
||||
* *MyFilledCircle*
|
||||
@@ -181,11 +190,13 @@ Explanation
|
||||
|
||||
Similar to the ellipse function, we can observe that *circle* receives as arguments:
|
||||
|
||||
* The image where the circle will be displayed (**img**)
|
||||
* The center of the circle denoted as the Point **center**
|
||||
* The radius of the circle: **w/32.0**
|
||||
* The color of the circle: **Scalar(0, 0, 255)** which means *Red* in RGB
|
||||
* Since **thickness** = -1, the circle will be drawn filled.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* The image where the circle will be displayed (**img**)
|
||||
* The center of the circle denoted as the Point **center**
|
||||
* The radius of the circle: **w/32.0**
|
||||
* The color of the circle: **Scalar(0, 0, 255)** which means *Red* in BGR
|
||||
* Since **thickness** = -1, the circle will be drawn filled.
|
||||
|
||||
* *MyPolygon*
|
||||
|
||||
@@ -230,12 +241,14 @@ Explanation
|
||||
}
|
||||
|
||||
To draw a filled polygon we use the function :fill_poly:`fillPoly <>`. We note that:
|
||||
|
||||
* The polygon will be drawn on **img**
|
||||
* The vertices of the polygon are the set of points in **ppt**
|
||||
* The total number of vertices to be drawn are **npt**
|
||||
* The number of polygons to be drawn is only **1**
|
||||
* The color of the polygon is defined by **Scalar( 255, 255, 255)**, which is the RGB value for *white*
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* The polygon will be drawn on **img**
|
||||
* The vertices of the polygon are the set of points in **ppt**
|
||||
* The total number of vertices to be drawn are **npt**
|
||||
* The number of polygons to be drawn is only **1**
|
||||
* The color of the polygon is defined by **Scalar( 255, 255, 255)**, which is the BGR value for *white*
|
||||
|
||||
* *rectangle*
|
||||
|
||||
@@ -250,10 +263,12 @@ Explanation
|
||||
|
||||
Finally we have the :rectangle:`rectangle <>` function (we did not create a special function for this guy). We note that:
|
||||
|
||||
* The rectangle will be drawn on **rook_image**
|
||||
* Two opposite vertices of the rectangle are defined by ** Point( 0, 7*w/8.0 )** and **Point( w, w)**
|
||||
* The color of the rectangle is given by **Scalar(0, 255, 255)** which is the RGB value for *yellow*
|
||||
* Since the thickness value is given by **-1**, the rectangle will be filled.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* The rectangle will be drawn on **rook_image**
|
||||
* Two opposite vertices of the rectangle are defined by ** Point( 0, 7*w/8.0 )** and **Point( w, w)**
|
||||
* The color of the rectangle is given by **Scalar(0, 255, 255)** which is the BGR value for *yellow*
|
||||
* Since the thickness value is given by **-1**, the rectangle will be filled.
|
||||
|
||||
Result
|
||||
=======
|
||||
|
||||
@@ -18,8 +18,8 @@ In this tutorial you will learn how to:
|
||||
|
||||
+ Get some cool info about pixel transformations
|
||||
|
||||
Cool Theory
|
||||
=================
|
||||
Theory
|
||||
=======
|
||||
|
||||
.. note::
|
||||
The explanation below belongs to the book `Computer Vision: Algorithms and Applications <http://szeliski.org/Book/>`_ by Richard Szeliski
|
||||
@@ -27,44 +27,52 @@ Cool Theory
|
||||
Image Processing
|
||||
--------------------
|
||||
|
||||
* A general image processing operator is a function that takes one or more input images and produces an output image.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Image transforms can be seen as:
|
||||
* A general image processing operator is a function that takes one or more input images and produces an output image.
|
||||
|
||||
* Point operators (pixel transforms)
|
||||
* Neighborhood (area-based) operators
|
||||
* 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).
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Examples of such operators include *brightness and contrast adjustments* as well as color correction and transformations.
|
||||
* 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::
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
g(x) = \alpha f(x) + \beta
|
||||
* Two commonly used point processes are *multiplication* and *addition* with a constant:
|
||||
|
||||
* 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
|
||||
.. math::
|
||||
|
||||
g(x) = \alpha f(x) + \beta
|
||||
|
||||
where :math:`i` and :math:`j` indicates that the pixel is located in the *i-th* row and *j-th* column.
|
||||
* 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:
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* The following code performs the operation :math:`g(i,j) = \alpha \cdot f(i,j) + \beta` :
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -132,8 +140,10 @@ Explanation
|
||||
|
||||
#. 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
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Initial pixel values equal to zero
|
||||
* Same size and type as the original image
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -155,9 +165,11 @@ Explanation
|
||||
|
||||
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).
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* 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.
|
||||
* 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.
|
||||
@@ -199,4 +211,4 @@ Result
|
||||
|
||||
.. image:: images/Basic_Linear_Transform_Tutorial_Result_0.jpg
|
||||
:alt: Basic Linear Transform - Final Result
|
||||
:align: center
|
||||
:align: center
|
||||
|
||||
@@ -8,16 +8,21 @@ Goals
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
* Use the *Random Number generator class* (:rng:`RNG <>`) and how to get a random number from a uniform distribution.
|
||||
* Display text on an OpenCV window by using the function :put_text:`putText <>`
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the *Random Number generator class* (:rng:`RNG <>`) and how to get a random number from a uniform distribution.
|
||||
* Display text on an OpenCV window by using the function :put_text:`putText <>`
|
||||
|
||||
Code
|
||||
=====
|
||||
* In the previous tutorial (:ref:`Drawing_1`) we drew diverse geometric figures, giving as input parameters such as coordinates (in the form of :point:`Points <>`), color, thickness, etc. You might have noticed that we gave specific values for these arguments.
|
||||
|
||||
* In this tutorial, we intend to use *random* values for the drawing parameters. Also, we intend to populate our image with a big number of geometric figures. Since we will be initializing them in a random fashion, this process will be automatic and made by using *loops* .
|
||||
|
||||
* This code is in your OpenCV sample folder. Otherwise you can grab it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/Basic/Drawing_2.cpp>`_ .
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* In the previous tutorial (:ref:`Drawing_1`) we drew diverse geometric figures, giving as input parameters such as coordinates (in the form of :point:`Points <>`), color, thickness, etc. You might have noticed that we gave specific values for these arguments.
|
||||
|
||||
* In this tutorial, we intend to use *random* values for the drawing parameters. Also, we intend to populate our image with a big number of geometric figures. Since we will be initializing them in a random fashion, this process will be automatic and made by using *loops* .
|
||||
|
||||
* This code is in your OpenCV sample folder. Otherwise you can grab it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/core/Matrix/Drawing_2.cpp>`_ .
|
||||
|
||||
Explanation
|
||||
============
|
||||
@@ -172,12 +177,14 @@ Explanation
|
||||
|
||||
So, what does the function :put_text:`putText <>` do? In our example:
|
||||
|
||||
* Draws the text **"Testing text rendering"** in **image**
|
||||
* The bottom-left corner of the text will be located in the Point **org**
|
||||
* The font type is a random integer value in the range: :math:`[0, 8>`.
|
||||
* The scale of the font is denoted by the expression **rng.uniform(0, 100)x0.05 + 0.1** (meaning its range is: :math:`[0.1, 5.1>`)
|
||||
* The text color is random (denoted by **randomColor(rng)**)
|
||||
* The text thickness ranges between 1 and 10, as specified by **rng.uniform(1,10)**
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Draws the text **"Testing text rendering"** in **image**
|
||||
* The bottom-left corner of the text will be located in the Point **org**
|
||||
* The font type is a random integer value in the range: :math:`[0, 8>`.
|
||||
* The scale of the font is denoted by the expression **rng.uniform(0, 100)x0.05 + 0.1** (meaning its range is: :math:`[0.1, 5.1>`)
|
||||
* The text color is random (denoted by **randomColor(rng)**)
|
||||
* The text thickness ranges between 1 and 10, as specified by **rng.uniform(1,10)**
|
||||
|
||||
As a result, we will get (analagously to the other drawing functions) **NUMBER** texts over our image, in random locations.
|
||||
|
||||
@@ -257,4 +264,4 @@ As you just saw in the Code section, the program will sequentially execute diver
|
||||
|
||||
.. image:: images/Drawing_2_Tutorial_Result_7.jpg
|
||||
:alt: Drawing Tutorial 2 - Final Result 7
|
||||
:align: center
|
||||
:align: center
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
.. _feature_description:
|
||||
|
||||
Feature Description
|
||||
*******************
|
||||
|
||||
Goal
|
||||
=====
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the :descriptor_extractor:`DescriptorExtractor<>` interface in order to find the feature vector correspondent to the keypoints. Specifically:
|
||||
|
||||
* Use :surf_descriptor_extractor:`SurfDescriptorExtractor<>` and its function :descriptor_extractor:`compute<>` to perform the required calculations.
|
||||
* Use a :brute_force_matcher:`BruteForceMatcher<>` to match the features vector
|
||||
* Use the function :draw_matches:`drawMatches<>` to draw the detected matches.
|
||||
|
||||
|
||||
Theory
|
||||
======
|
||||
|
||||
Code
|
||||
====
|
||||
|
||||
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/features2D/SURF_descriptor.cpp>`_
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
void readme();
|
||||
|
||||
/** @function main */
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
if( argc != 3 )
|
||||
{ return -1; }
|
||||
|
||||
Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
|
||||
Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );
|
||||
|
||||
if( !img_1.data || !img_2.data )
|
||||
{ return -1; }
|
||||
|
||||
//-- Step 1: Detect the keypoints using SURF Detector
|
||||
int minHessian = 400;
|
||||
|
||||
SurfFeatureDetector detector( minHessian );
|
||||
|
||||
std::vector<KeyPoint> keypoints_1, keypoints_2;
|
||||
|
||||
detector.detect( img_1, keypoints_1 );
|
||||
detector.detect( img_2, keypoints_2 );
|
||||
|
||||
//-- Step 2: Calculate descriptors (feature vectors)
|
||||
SurfDescriptorExtractor extractor;
|
||||
|
||||
Mat descriptors_1, descriptors_2;
|
||||
|
||||
extractor.compute( img_1, keypoints_1, descriptors_1 );
|
||||
extractor.compute( img_2, keypoints_2, descriptors_2 );
|
||||
|
||||
//-- Step 3: Matching descriptor vectors with a brute force matcher
|
||||
BruteForceMatcher< L2<float> > matcher;
|
||||
std::vector< DMatch > matches;
|
||||
matcher.match( descriptors_1, descriptors_2, matches );
|
||||
|
||||
//-- Draw matches
|
||||
Mat img_matches;
|
||||
drawMatches( img_1, keypoints_1, img_2, keypoints_2, matches, img_matches );
|
||||
|
||||
//-- Show detected matches
|
||||
imshow("Matches", img_matches );
|
||||
|
||||
waitKey(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @function readme */
|
||||
void readme()
|
||||
{ std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; }
|
||||
|
||||
Explanation
|
||||
============
|
||||
|
||||
Result
|
||||
======
|
||||
|
||||
#. Here is the result after applying the BruteForce matcher between the two original images:
|
||||
|
||||
.. image:: images/Feature_Description_BruteForce_Result.jpg
|
||||
:align: center
|
||||
:height: 200pt
|
||||
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 117 KiB |
@@ -0,0 +1,97 @@
|
||||
.. _feature_detection:
|
||||
|
||||
Feature Detection
|
||||
******************
|
||||
|
||||
Goal
|
||||
=====
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the :feature_detector:`FeatureDetector<>` interface in order to find interest points. Specifically:
|
||||
|
||||
* Use the :surf_feature_detector:`SurfFeatureDetector<>` and its function :feature_detector_detect:`detect<>` to perform the detection process
|
||||
* Use the function :draw_keypoints:`drawKeypoints<>` to draw the detected keypoints
|
||||
|
||||
|
||||
Theory
|
||||
======
|
||||
|
||||
Code
|
||||
====
|
||||
|
||||
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/features2D/SURF_detector.cpp>`_
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
void readme();
|
||||
|
||||
/** @function main */
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
if( argc != 3 )
|
||||
{ readme(); return -1; }
|
||||
|
||||
Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
|
||||
Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );
|
||||
|
||||
if( !img_1.data || !img_2.data )
|
||||
{ std::cout<< " --(!) Error reading images " << std::endl; return -1; }
|
||||
|
||||
//-- Step 1: Detect the keypoints using SURF Detector
|
||||
int minHessian = 400;
|
||||
|
||||
SurfFeatureDetector detector( minHessian );
|
||||
|
||||
std::vector<KeyPoint> keypoints_1, keypoints_2;
|
||||
|
||||
detector.detect( img_1, keypoints_1 );
|
||||
detector.detect( img_2, keypoints_2 );
|
||||
|
||||
//-- Draw keypoints
|
||||
Mat img_keypoints_1; Mat img_keypoints_2;
|
||||
|
||||
drawKeypoints( img_1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
|
||||
drawKeypoints( img_2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
|
||||
|
||||
//-- Show detected (drawn) keypoints
|
||||
imshow("Keypoints 1", img_keypoints_1 );
|
||||
imshow("Keypoints 2", img_keypoints_2 );
|
||||
|
||||
waitKey(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @function readme */
|
||||
void readme()
|
||||
{ std::cout << " Usage: ./SURF_detector <img1> <img2>" << std::endl; }
|
||||
|
||||
Explanation
|
||||
============
|
||||
|
||||
Result
|
||||
======
|
||||
|
||||
#. Here is the result of the feature detection applied to the first image:
|
||||
|
||||
.. image:: images/Feature_Detection_Result_a.jpg
|
||||
:align: center
|
||||
:height: 125pt
|
||||
|
||||
#. And here is the result for the second image:
|
||||
|
||||
.. image:: images/Feature_Detection_Result_b.jpg
|
||||
:align: center
|
||||
:height: 200pt
|
||||
|
||||
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 66 KiB |
@@ -0,0 +1,132 @@
|
||||
.. _feature_flann_matcher:
|
||||
|
||||
Feature Matching with FLANN
|
||||
****************************
|
||||
|
||||
Goal
|
||||
=====
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the :flann_based_matcher:`FlannBasedMatcher<>` interface in order to perform a quick and efficient matching by using the :flann:`FLANN<>` ( *Fast Approximate Nearest Neighbor Search Library* )
|
||||
|
||||
|
||||
Theory
|
||||
======
|
||||
|
||||
Code
|
||||
====
|
||||
|
||||
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/features2D/SURF_FlannMatcher.cpp>`_
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
void readme();
|
||||
|
||||
/** @function main */
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
if( argc != 3 )
|
||||
{ readme(); return -1; }
|
||||
|
||||
Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
|
||||
Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );
|
||||
|
||||
if( !img_1.data || !img_2.data )
|
||||
{ std::cout<< " --(!) Error reading images " << std::endl; return -1; }
|
||||
|
||||
//-- Step 1: Detect the keypoints using SURF Detector
|
||||
int minHessian = 400;
|
||||
|
||||
SurfFeatureDetector detector( minHessian );
|
||||
|
||||
std::vector<KeyPoint> keypoints_1, keypoints_2;
|
||||
|
||||
detector.detect( img_1, keypoints_1 );
|
||||
detector.detect( img_2, keypoints_2 );
|
||||
|
||||
//-- Step 2: Calculate descriptors (feature vectors)
|
||||
SurfDescriptorExtractor extractor;
|
||||
|
||||
Mat descriptors_1, descriptors_2;
|
||||
|
||||
extractor.compute( img_1, keypoints_1, descriptors_1 );
|
||||
extractor.compute( img_2, keypoints_2, descriptors_2 );
|
||||
|
||||
//-- Step 3: Matching descriptor vectors using FLANN matcher
|
||||
FlannBasedMatcher matcher;
|
||||
std::vector< DMatch > matches;
|
||||
matcher.match( descriptors_1, descriptors_2, matches );
|
||||
|
||||
double max_dist = 0; double min_dist = 100;
|
||||
|
||||
//-- Quick calculation of max and min distances between keypoints
|
||||
for( int i = 0; i < descriptors_1.rows; i++ )
|
||||
{ double dist = matches[i].distance;
|
||||
if( dist < min_dist ) min_dist = dist;
|
||||
if( dist > max_dist ) max_dist = dist;
|
||||
}
|
||||
|
||||
printf("-- Max dist : %f \n", max_dist );
|
||||
printf("-- Min dist : %f \n", min_dist );
|
||||
|
||||
//-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist )
|
||||
//-- PS.- radiusMatch can also be used here.
|
||||
std::vector< DMatch > good_matches;
|
||||
|
||||
for( int i = 0; i < descriptors_1.rows; i++ )
|
||||
{ if( matches[i].distance < 2*min_dist )
|
||||
{ good_matches.push_back( matches[i]); }
|
||||
}
|
||||
|
||||
//-- Draw only "good" matches
|
||||
Mat img_matches;
|
||||
drawMatches( img_1, keypoints_1, img_2, keypoints_2,
|
||||
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
|
||||
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
|
||||
|
||||
//-- Show detected matches
|
||||
imshow( "Good Matches", img_matches );
|
||||
|
||||
for( int i = 0; i < good_matches.size(); i++ )
|
||||
{ printf( "-- Good Match [%d] Keypoint 1: %d -- Keypoint 2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); }
|
||||
|
||||
waitKey(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @function readme */
|
||||
void readme()
|
||||
{ std::cout << " Usage: ./SURF_FlannMatcher <img1> <img2>" << std::endl; }
|
||||
|
||||
Explanation
|
||||
============
|
||||
|
||||
Result
|
||||
======
|
||||
|
||||
#. Here is the result of the feature detection applied to the first image:
|
||||
|
||||
.. image:: images/Featur_FlannMatcher_Result.jpg
|
||||
:align: center
|
||||
:height: 250pt
|
||||
|
||||
#. Additionally, we get as console output the keypoints filtered:
|
||||
|
||||
.. image:: images/Feature_FlannMatcher_Keypoints_Result.jpg
|
||||
:align: center
|
||||
:height: 250pt
|
||||
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 77 KiB |
@@ -0,0 +1,148 @@
|
||||
.. _feature_homography:
|
||||
|
||||
Features2D + Homography to find a known object
|
||||
**********************************************
|
||||
|
||||
Goal
|
||||
=====
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the function :find_homography:`findHomography<>` to find the transform between matched keypoints.
|
||||
* Use the function :perspective_transform:`perspectiveTransform<>` to map the points.
|
||||
|
||||
|
||||
Theory
|
||||
======
|
||||
|
||||
Code
|
||||
====
|
||||
|
||||
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/features2D/SURF_Homography.cpp>`_
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
void readme();
|
||||
|
||||
/** @function main */
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
if( argc != 3 )
|
||||
{ readme(); return -1; }
|
||||
|
||||
Mat img_object = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
|
||||
Mat img_scene = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );
|
||||
|
||||
if( !img_object.data || !img_scene.data )
|
||||
{ std::cout<< " --(!) Error reading images " << std::endl; return -1; }
|
||||
|
||||
//-- Step 1: Detect the keypoints using SURF Detector
|
||||
int minHessian = 400;
|
||||
|
||||
SurfFeatureDetector detector( minHessian );
|
||||
|
||||
std::vector<KeyPoint> keypoints_object, keypoints_scene;
|
||||
|
||||
detector.detect( img_object, keypoints_object );
|
||||
detector.detect( img_scene, keypoints_scene );
|
||||
|
||||
//-- Step 2: Calculate descriptors (feature vectors)
|
||||
SurfDescriptorExtractor extractor;
|
||||
|
||||
Mat descriptors_object, descriptors_scene;
|
||||
|
||||
extractor.compute( img_object, keypoints_object, descriptors_object );
|
||||
extractor.compute( img_scene, keypoints_scene, descriptors_scene );
|
||||
|
||||
//-- Step 3: Matching descriptor vectors using FLANN matcher
|
||||
FlannBasedMatcher matcher;
|
||||
std::vector< DMatch > matches;
|
||||
matcher.match( descriptors_object, descriptors_scene, matches );
|
||||
|
||||
double max_dist = 0; double min_dist = 100;
|
||||
|
||||
//-- Quick calculation of max and min distances between keypoints
|
||||
for( int i = 0; i < descriptors_object.rows; i++ )
|
||||
{ double dist = matches[i].distance;
|
||||
if( dist < min_dist ) min_dist = dist;
|
||||
if( dist > max_dist ) max_dist = dist;
|
||||
}
|
||||
|
||||
printf("-- Max dist : %f \n", max_dist );
|
||||
printf("-- Min dist : %f \n", min_dist );
|
||||
|
||||
//-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
|
||||
std::vector< DMatch > good_matches;
|
||||
|
||||
for( int i = 0; i < descriptors_object.rows; i++ )
|
||||
{ if( matches[i].distance < 3*min_dist )
|
||||
{ good_matches.push_back( matches[i]); }
|
||||
}
|
||||
|
||||
Mat img_matches;
|
||||
drawMatches( img_object, keypoints_object, img_scene, keypoints_scene,
|
||||
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
|
||||
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
|
||||
|
||||
//-- Localize the object
|
||||
std::vector<Point2f> obj;
|
||||
std::vector<Point2f> scene;
|
||||
|
||||
for( int i = 0; i < good_matches.size(); i++ )
|
||||
{
|
||||
//-- Get the keypoints from the good matches
|
||||
obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
|
||||
scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
|
||||
}
|
||||
|
||||
Mat H = findHomography( obj, scene, CV_RANSAC );
|
||||
|
||||
//-- Get the corners from the image_1 ( the object to be "detected" )
|
||||
std::vector<Point2f> obj_corners(4);
|
||||
obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( img_object.cols, 0 );
|
||||
obj_corners[2] = cvPoint( img_object.cols, img_object.rows ); obj_corners[3] = cvPoint( 0, img_object.rows );
|
||||
std::vector<Point2f> scene_corners(4);
|
||||
|
||||
perspectiveTransform( obj_corners, scene_corners, H);
|
||||
|
||||
//-- Draw lines between the corners (the mapped object in the scene - image_2 )
|
||||
line( img_matches, scene_corners[0] + Point2f( img_object.cols, 0), scene_corners[1] + Point2f( img_object.cols, 0), Scalar(0, 255, 0), 4 );
|
||||
line( img_matches, scene_corners[1] + Point2f( img_object.cols, 0), scene_corners[2] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
|
||||
line( img_matches, scene_corners[2] + Point2f( img_object.cols, 0), scene_corners[3] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
|
||||
line( img_matches, scene_corners[3] + Point2f( img_object.cols, 0), scene_corners[0] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
|
||||
|
||||
//-- Show detected matches
|
||||
imshow( "Good Matches & Object detection", img_matches );
|
||||
|
||||
waitKey(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @function readme */
|
||||
void readme()
|
||||
{ std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; }
|
||||
|
||||
Explanation
|
||||
============
|
||||
|
||||
Result
|
||||
======
|
||||
|
||||
|
||||
#. And here is the result for the detected object (highlighted in green)
|
||||
|
||||
.. image:: images/Feature_Homography_Result.jpg
|
||||
:align: center
|
||||
:height: 200pt
|
||||
|
||||
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 51 KiB |
@@ -72,7 +72,7 @@ Learn about how to use the feature points detectors, descriptors and matching f
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
===================== ==============================================
|
||||
|Subpixel| **Title:** :ref:`corner_subpixeles`
|
||||
|Subpixel| **Title:** :ref:`corner_subpixeles`
|
||||
|
||||
*Compatibility:* > OpenCV 2.0
|
||||
|
||||
@@ -86,6 +86,84 @@ Learn about how to use the feature points detectors, descriptors and matching f
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
+
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
===================== ==============================================
|
||||
|FeatureDetect| **Title:** :ref:`feature_detection`
|
||||
|
||||
*Compatibility:* > OpenCV 2.0
|
||||
|
||||
*Author:* |Author_AnaH|
|
||||
|
||||
In this tutorial, you will use *features2d* to detect interest points.
|
||||
|
||||
===================== ==============================================
|
||||
|
||||
.. |FeatureDetect| image:: images/Feature_Detection_Tutorial_Cover.jpg
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
|
||||
+
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
===================== ==============================================
|
||||
|FeatureDescript| **Title:** :ref:`feature_description`
|
||||
|
||||
*Compatibility:* > OpenCV 2.0
|
||||
|
||||
*Author:* |Author_AnaH|
|
||||
|
||||
In this tutorial, you will use *features2d* to calculate feature vectors.
|
||||
|
||||
===================== ==============================================
|
||||
|
||||
.. |FeatureDescript| image:: images/Feature_Description_Tutorial_Cover.jpg
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
+
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
===================== ==============================================
|
||||
|FeatureFlann| **Title:** :ref:`feature_flann_matcher`
|
||||
|
||||
*Compatibility:* > OpenCV 2.0
|
||||
|
||||
*Author:* |Author_AnaH|
|
||||
|
||||
In this tutorial, you will use the FLANN library to make a fast matching.
|
||||
|
||||
===================== ==============================================
|
||||
|
||||
.. |FeatureFlann| image:: images/Feature_Flann_Matcher_Tutorial_Cover.jpg
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
+
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
===================== ==============================================
|
||||
|FeatureHomo| **Title:** :ref:`feature_homography`
|
||||
|
||||
*Compatibility:* > OpenCV 2.0
|
||||
|
||||
*Author:* |Author_AnaH|
|
||||
|
||||
In this tutorial, you will use *features2d* and *calib3d* to detect an object in a scene.
|
||||
|
||||
===================== ==============================================
|
||||
|
||||
.. |FeatureHomo| image:: images/Feature_Homography_Tutorial_Cover.jpg
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
|
||||
+
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
@@ -112,8 +190,17 @@ Learn about how to use the feature points detectors, descriptors and matching f
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
../feature_description/feature_description
|
||||
../feature_detection/feature_detection
|
||||
../trackingmotion/harris_detector/harris_detector
|
||||
../feature_flann_matcher/feature_flann_matcher
|
||||
../feature_homography/feature_homography
|
||||
../trackingmotion/good_features_to_track/good_features_to_track.rst
|
||||
../trackingmotion/generic_corner_detector/generic_corner_detector
|
||||
../trackingmotion/corner_subpixeles/corner_subpixeles
|
||||
../detection_of_planar_objects/detection_of_planar_objects
|
||||
../feature_detection/feature_detection
|
||||
../feature_detection/feature_description
|
||||
../feature_flann_matcher/feature_flann_matcher
|
||||
../feature_homography/feature_homography
|
||||
../detection_of_planar_objects/detection_of_planar_objects
|
||||
|
||||
|
||||
@@ -88,14 +88,14 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
/// Apply corner detection
|
||||
goodFeaturesToTrack( src_gray,
|
||||
corners,
|
||||
maxCorners,
|
||||
qualityLevel,
|
||||
minDistance,
|
||||
Mat(),
|
||||
blockSize,
|
||||
useHarrisDetector,
|
||||
k );
|
||||
corners,
|
||||
maxCorners,
|
||||
qualityLevel,
|
||||
minDistance,
|
||||
Mat(),
|
||||
blockSize,
|
||||
useHarrisDetector,
|
||||
k );
|
||||
|
||||
|
||||
/// Draw corners detected
|
||||
@@ -116,7 +116,7 @@ Explanation
|
||||
Result
|
||||
======
|
||||
|
||||
.. image:: images/Shi_Tomasi_Detector_Result.jpg
|
||||
.. image:: images/Feature_Detection_Result_a.jpg
|
||||
:align: center
|
||||
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 32 KiB |
@@ -6,15 +6,46 @@ Harris corner detector
|
||||
Goal
|
||||
=====
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
In this tutorial you will learn:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* What features are and why they are important
|
||||
* Use the function :corner_harris:`cornerHarris <>` to detect corners using the Harris-Stephens method.
|
||||
|
||||
Theory
|
||||
======
|
||||
|
||||
What is a feature?
|
||||
-------------------
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* In computer vision, usually we need to find matching points between different frames of an environment. Why? If we know how two images relate to each other, we can use *both* images to extract information of them.
|
||||
|
||||
* When we say **matching points** we are referring, in a general sense, to *characteristics* in the scene that we can recognize easily. We call these characteristics **features**.
|
||||
|
||||
* **So, what characteristics should a feature have?**
|
||||
|
||||
* It must be *uniquely recognizable*
|
||||
|
||||
|
||||
Types of Image Features
|
||||
------------------------
|
||||
|
||||
To mention a few:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Edges
|
||||
* Corner (also known as interest points)
|
||||
* Blobs (also known as regions of interest )
|
||||
|
||||
In this tutorial we will study the *corner* features, specifically.
|
||||
|
||||
Why is a corner so special?
|
||||
----------------------------
|
||||
|
||||
Code
|
||||
====
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -1,12 +1,36 @@
|
||||
.. _Table-Of-Content-GPU:
|
||||
|
||||
*gpu* module. GPU-Accelerated Computer Vision
|
||||
-----------------------------------------------------------
|
||||
---------------------------------------------
|
||||
|
||||
Squeeze out every little computation power from your system by using the power of your video card to run the OpenCV algorithms.
|
||||
|
||||
.. include:: ../../definitions/noContent.rst
|
||||
.. include:: ../../definitions/tocDefinitions.rst
|
||||
|
||||
+
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
=============== ======================================================
|
||||
|hVideoWrite| *Title:* :ref:`gpuBasicsSimilarity`
|
||||
|
||||
*Compatibility:* > OpenCV 2.0
|
||||
|
||||
*Author:* |Author_BernatG|
|
||||
|
||||
This will give a good grasp on how to approach coding on the GPU module, once you already know how to handle the other modules. As a test case it will port the similarity methods from the tutorial :ref:`videoInputPSNRMSSIM` to the GPU.
|
||||
|
||||
=============== ======================================================
|
||||
|
||||
.. |hVideoWrite| image:: images/gpu-basics-similarity.png
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\pagebreak
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
../gpu-basics-similarity/gpu-basics-similarity
|
||||
|
||||
|
After Width: | Height: | Size: 7.2 KiB |
@@ -1,7 +1,7 @@
|
||||
.. _Table-Of-Content-HighGui:
|
||||
|
||||
*highgui* module. High Level GUI and Media
|
||||
-----------------------------------------------------------
|
||||
------------------------------------------
|
||||
|
||||
This section contains valuable tutorials about how to read/save your image/video files and how to use the built-in graphical user interface of the library.
|
||||
|
||||
@@ -45,6 +45,26 @@ This section contains valuable tutorials about how to read/save your image/video
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
+
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
=============== ======================================================
|
||||
|hVideoWrite| *Title:* :ref:`videoWriteHighGui`
|
||||
|
||||
*Compatibility:* > OpenCV 2.0
|
||||
|
||||
*Author:* |Author_BernatG|
|
||||
|
||||
Whenever you work with video feeds you may eventually want to save your image processing result in a form of a new video file. Here's how to do it.
|
||||
|
||||
=============== ======================================================
|
||||
|
||||
.. |hVideoWrite| image:: images/video-write.png
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\pagebreak
|
||||
@@ -54,3 +74,4 @@ This section contains valuable tutorials about how to read/save your image/video
|
||||
|
||||
../trackbar/trackbar
|
||||
../video-input-psnr-ssim/video-input-psnr-ssim
|
||||
../video-write/video-write
|
||||
@@ -18,7 +18,7 @@ The source code
|
||||
|
||||
As a test case where to show off these using OpenCV I've created a small program that reads in two video files and performs a similarity check between them. This is something you could use to check just how well a new video compressing algorithms works. Let there be a reference (original) video like :download:`this small Megamind clip <../../../../samples/cpp/tutorial_code/highgui/video-input-psnr-ssim/video/Megamind.avi>` and :download:`a compressed version of it <../../../../samples/cpp/tutorial_code/highgui/video-input-psnr-ssim/video/Megamind_bugy.avi>`. You may also find the source code and these video file in the :file:`samples/cpp/tutorial_code/highgui/video-input-psnr-ssim/` folder of the OpenCV source library.
|
||||
|
||||
.. literalinclude:: ../../../../samples/cpp/tutorial_code/HighGUI\video-input-psnr-ssim\video-input-psnr-ssim.cpp
|
||||
.. literalinclude:: ../../../../samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video-input-psnr-ssim.cpp
|
||||
:language: cpp
|
||||
:linenos:
|
||||
:tab-width: 4
|
||||
|
||||
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 12 KiB |
@@ -70,7 +70,7 @@ Erosion
|
||||
Code
|
||||
======
|
||||
|
||||
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/Image_Processing/Morphology_1.cpp>`_
|
||||
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp>`_
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -175,16 +175,16 @@ Explanation
|
||||
|
||||
#. Most of the stuff shown is known by you (if you have any doubt, please refer to the tutorials in previous sections). Let's check the general structure of the program:
|
||||
|
||||
* Load an image (can be RGB or grayscale)
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Create two windows (one for dilation output, the other for erosion)
|
||||
* Load an image (can be RGB or grayscale)
|
||||
* Create two windows (one for dilation output, the other for erosion)
|
||||
* Create a set of 02 Trackbars for each operation:
|
||||
|
||||
* Create a set of 02 Trackbars for each operation:
|
||||
* The first trackbar "Element" returns either **erosion_elem** or **dilation_elem**
|
||||
* The second trackbar "Kernel size" return **erosion_size** or **dilation_size** for the corresponding operation.
|
||||
|
||||
* The first trackbar "Element" returns either **erosion_elem** or **dilation_elem**
|
||||
* The second trackbar "Kernel size" return **erosion_size** or **dilation_size** for the corresponding operation.
|
||||
|
||||
* Every time we move any slider, the user's function **Erosion** or **Dilation** will be called and it will update the output image based on the current trackbar values.
|
||||
* Every time we move any slider, the user's function **Erosion** or **Dilation** will be called and it will update the output image based on the current trackbar values.
|
||||
|
||||
Let's analyze these two functions:
|
||||
|
||||
@@ -220,13 +220,15 @@ Explanation
|
||||
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
|
||||
Point( erosion_size, erosion_size ) );
|
||||
|
||||
We can choose any of three shapes for our kernel:
|
||||
We can choose any of three shapes for our kernel:
|
||||
|
||||
* Rectangular box: MORPH_RECT
|
||||
* Cross: MORPH_CROSS
|
||||
* Ellipse: MORPH_ELLIPSE
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
Then, we just have to specify the size of our kernel and the *anchor point*. If not specified, it is assumed to be in the center.
|
||||
+ Rectangular box: MORPH_RECT
|
||||
+ Cross: MORPH_CROSS
|
||||
+ Ellipse: MORPH_ELLIPSE
|
||||
|
||||
Then, we just have to specify the size of our kernel and the *anchor point*. If not specified, it is assumed to be in the center.
|
||||
|
||||
* That is all. We are ready to perform the erosion of our image.
|
||||
|
||||
@@ -271,4 +273,4 @@ Results
|
||||
|
||||
.. image:: images/Morphology_1_Tutorial_Cover.jpg
|
||||
:alt: Dilation and Erosion application
|
||||
:align: center
|
||||
:align: center
|
||||
|
||||
@@ -8,7 +8,9 @@ Goal
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
a. Use the OpenCV function :canny:`Canny <>` to implement the Canny Edge Detector.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the OpenCV function :canny:`Canny <>` to implement the Canny Edge Detector.
|
||||
|
||||
Theory
|
||||
=======
|
||||
@@ -265,21 +267,21 @@ Explanation
|
||||
Result
|
||||
=======
|
||||
|
||||
#. After compiling the code above, we can run it giving as argument the path to an image. For example, using as an input the following image:
|
||||
* After compiling the code above, we can run it giving as argument the path to an image. For example, using as an input the following image:
|
||||
|
||||
.. image:: images/Canny_Detector_Tutorial_Original_Image.jpg
|
||||
:alt: Original test image
|
||||
:width: 200pt
|
||||
:align: center
|
||||
|
||||
and moving the slider, trying different threshold, we obtain the following result:
|
||||
* Moving the slider, trying different threshold, we obtain the following result:
|
||||
|
||||
.. image:: images/Canny_Detector_Tutorial_Result.jpg
|
||||
:alt: Result after running Canny
|
||||
:width: 200pt
|
||||
:align: center
|
||||
|
||||
Notice how the image is superposed to the black background on the edge regions.
|
||||
* Notice how the image is superposed to the black background on the edge regions.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,10 +8,12 @@ Goal
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
#. Use the OpenCV function :copy_make_border:`copyMakeBorder <>` to set the borders (extra padding to your image).
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the OpenCV function :copy_make_border:`copyMakeBorder <>` to set the borders (extra padding to your image).
|
||||
|
||||
Theory
|
||||
============
|
||||
========
|
||||
|
||||
.. note::
|
||||
The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.
|
||||
@@ -208,10 +210,12 @@ Results
|
||||
|
||||
#. After compiling the code above, you can execute it giving as argument the path of an image. The result should be:
|
||||
|
||||
* By default, it begins with the border set to BORDER_CONSTANT. Hence, a succession of random colored borders will be shown.
|
||||
* If you press 'r', the border will become a replica of the edge pixels.
|
||||
* If you press 'c', the random colored borders will appear again
|
||||
* If you press 'ESC' the program will exit.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* By default, it begins with the border set to BORDER_CONSTANT. Hence, a succession of random colored borders will be shown.
|
||||
* If you press 'r', the border will become a replica of the edge pixels.
|
||||
* If you press 'c', the random colored borders will appear again
|
||||
* If you press 'ESC' the program will exit.
|
||||
|
||||
Below some screenshot showing how the border changes color and how the *BORDER_REPLICATE* option looks:
|
||||
|
||||
|
||||
@@ -8,10 +8,12 @@ Goal
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
* Use the OpenCV function :filter2d:`filter2D <>` to create your own linear filters.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the OpenCV function :filter2d:`filter2D <>` to create your own linear filters.
|
||||
|
||||
Theory
|
||||
============
|
||||
=======
|
||||
|
||||
.. note::
|
||||
The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.
|
||||
|
||||
@@ -9,7 +9,9 @@ Goal
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
a. Use the OpenCV function :laplacian:`Laplacian <>` to implement a discrete analog of the *Laplacian operator*.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the OpenCV function :laplacian:`Laplacian <>` to implement a discrete analog of the *Laplacian operator*.
|
||||
|
||||
|
||||
Theory
|
||||
|
||||
@@ -9,8 +9,10 @@ Goal
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
#. Use the OpenCV function :sobel:`Sobel <>` to calculate the derivatives from an image.
|
||||
#. Use the OpenCV function :scharr:`Scharr <>` to calculate a more accurate derivative for a kernel of size :math:`3 \cdot 3`
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the OpenCV function :sobel:`Sobel <>` to calculate the derivatives from an image.
|
||||
* Use the OpenCV function :scharr:`Scharr <>` to calculate a more accurate derivative for a kernel of size :math:`3 \cdot 3`
|
||||
|
||||
Theory
|
||||
========
|
||||
|
||||
@@ -8,25 +8,28 @@ Goal
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
* Use the OpenCV function :morphology_ex:`morphologyEx <>` to apply Morphological Transformation such as:
|
||||
|
||||
* Opening
|
||||
* Closing
|
||||
* Morphological Gradient
|
||||
* Top Hat
|
||||
* Black Hat
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
Cool Theory
|
||||
============
|
||||
* Use the OpenCV function :morphology_ex:`morphologyEx <>` to apply Morphological Transformation such as:
|
||||
|
||||
+ Opening
|
||||
+ Closing
|
||||
+ Morphological Gradient
|
||||
+ Top Hat
|
||||
+ Black Hat
|
||||
|
||||
Theory
|
||||
=======
|
||||
|
||||
.. note::
|
||||
The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.
|
||||
|
||||
In the previous tutorial we covered two basic Morphology operations:
|
||||
|
||||
* Erosion
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Dilation.
|
||||
* Erosion
|
||||
* Dilation.
|
||||
|
||||
Based on these two we can effectuate more sophisticated transformations to our images. Here we discuss briefly 05 operations offered by OpenCV:
|
||||
|
||||
@@ -246,11 +249,11 @@ Explanation
|
||||
* **dst**: Output image
|
||||
* **operation**: The kind of morphology transformation to be performed. Note that we have 5 alternatives:
|
||||
|
||||
* *Opening*: MORPH_OPEN : 2
|
||||
* *Closing*: MORPH_CLOSE: 3
|
||||
* *Gradient*: MORPH_GRADIENT: 4
|
||||
* *Top Hat*: MORPH_TOPHAT: 5
|
||||
* *Black Hat*: MORPH_BLACKHAT: 6
|
||||
+ *Opening*: MORPH_OPEN : 2
|
||||
+ *Closing*: MORPH_CLOSE: 3
|
||||
+ *Gradient*: MORPH_GRADIENT: 4
|
||||
+ *Top Hat*: MORPH_TOPHAT: 5
|
||||
+ *Black Hat*: MORPH_BLACKHAT: 6
|
||||
|
||||
As you can see the values range from <2-6>, that is why we add (+2) to the values entered by the Trackbar:
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@ Goal
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
* Use the OpenCV functions :pyr_up:`pyrUp <>` and :pyr_down:`pyrDown <>` to downsample or upsample a given image.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the OpenCV functions :pyr_up:`pyrUp <>` and :pyr_down:`pyrDown <>` to downsample or upsample a given image.
|
||||
|
||||
Theory
|
||||
=======
|
||||
@@ -16,25 +18,30 @@ Theory
|
||||
.. note::
|
||||
The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.
|
||||
|
||||
* Usually we need to convert an image to a size different than its original. For this, there are two possible options:
|
||||
|
||||
* *Upsize* the image (zoom in) or
|
||||
* *Downsize* it (zoom out).
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Usually we need to convert an image to a size different than its original. For this, there are two possible options:
|
||||
|
||||
#. *Upsize* the image (zoom in) or
|
||||
#. *Downsize* it (zoom out).
|
||||
|
||||
* Although there is a *geometric transformation* function in OpenCV that -literally- resize an image (:resize:`resize <>`, which we will show in a future tutorial), in this section we analyze first the use of **Image Pyramids**, which are widely applied in a huge range of vision applications.
|
||||
|
||||
* Although there is a *geometric transformation* function in OpenCV that -literally- resize an image (:resize:`resize <>`, which we will show in a future tutorial), in this section we analyze first the use of **Image Pyramids**, which are widely applied in a huge range of vision applications.
|
||||
|
||||
Image Pyramid
|
||||
--------------
|
||||
|
||||
* An image pyramid is a collection of images - all arising from a single original image - that are successively downsampled until some desired stopping point is reached.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* There are two common kinds of image pyramids:
|
||||
* An image pyramid is a collection of images - all arising from a single original image - that are successively downsampled until some desired stopping point is reached.
|
||||
|
||||
* **Gaussian pyramid:** Used to downsample images
|
||||
* There are two common kinds of image pyramids:
|
||||
|
||||
* **Laplacian pyramid:** Used to reconstruct an upsampled image from an image lower in the pyramid (with less resolution)
|
||||
* **Gaussian pyramid:** Used to downsample images
|
||||
|
||||
* In this tutorial we'll use the *Gaussian pyramid*.
|
||||
* **Laplacian pyramid:** Used to reconstruct an upsampled image from an image lower in the pyramid (with less resolution)
|
||||
|
||||
* In this tutorial we'll use the *Gaussian pyramid*.
|
||||
|
||||
Gaussian Pyramid
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -8,7 +8,9 @@ Goal
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
* Perform basic thresholding operations using OpenCV function :threshold:`threshold <>`
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Perform basic thresholding operations using OpenCV function :threshold:`threshold <>`
|
||||
|
||||
|
||||
Cool Theory
|
||||
@@ -305,4 +307,4 @@ Results
|
||||
|
||||
.. image:: images/Threshold_Tutorial_Result_Zero.jpg
|
||||
:alt: Threshold Result Zero
|
||||
:align: center
|
||||
:align: center
|
||||
|
||||
@@ -17,7 +17,7 @@ In this tutorial you will learn how to:
|
||||
Source Code
|
||||
===========
|
||||
|
||||
Download the :download:`source code from here <../../../../samples/cpp/tutorial_code/introduction/display_image/display_image.cpp>` or look it up in our library at :file:`samples/cpp/tutorial_code/introduction/display_image/display_image.cpp`.
|
||||
Download the source code from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/introduction/display_image/display_image.cpp>`_.
|
||||
|
||||
.. literalinclude:: ../../../../samples/cpp/tutorial_code/introduction/display_image/display_image.cpp
|
||||
:language: cpp
|
||||
@@ -108,20 +108,22 @@ Because we want our window to be displayed until the user presses a key (otherwi
|
||||
Result
|
||||
=======
|
||||
|
||||
* Compile your code and then run the executable giving an image path as argument. If you're on Windows the executable will of course contain an *exe* extension too. Of course assure the image file is near your program file.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
.. code-block:: bash
|
||||
* Compile your code and then run the executable giving an image path as argument. If you're on Windows the executable will of course contain an *exe* extension too. Of course assure the image file is near your program file.
|
||||
|
||||
./DisplayImage HappyFish.jpg
|
||||
.. code-block:: bash
|
||||
|
||||
* You should get a nice window as the one shown below:
|
||||
./DisplayImage HappyFish.jpg
|
||||
|
||||
.. image:: images/Display_Image_Tutorial_Result.jpg
|
||||
:alt: Display Image Tutorial - Final Result
|
||||
:align: center
|
||||
* You should get a nice window as the one shown below:
|
||||
|
||||
.. raw:: html
|
||||
.. image:: images/Display_Image_Tutorial_Result.jpg
|
||||
:alt: Display Image Tutorial - Final Result
|
||||
:align: center
|
||||
|
||||
<div align="center">
|
||||
<iframe title="Introduction - Display an Image" width="560" height="349" src="http://www.youtube.com/embed/1OJEqpuaGc4?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
|
||||
</div>
|
||||
.. raw:: html
|
||||
|
||||
<div align="center">
|
||||
<iframe title="Introduction - Display an Image" width="560" height="349" src="http://www.youtube.com/embed/1OJEqpuaGc4?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
|
||||
</div>
|
||||
|
||||
@@ -6,12 +6,14 @@ Using OpenCV with gcc and CMake
|
||||
.. note::
|
||||
We assume that you have successfully installed OpenCV in your workstation.
|
||||
|
||||
The easiest way of using OpenCV in your code is to use `CMake <http://www.cmake.org/>`_. A few advantages (taken from the Wiki):
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* No need to change anything when porting between Linux and Windows
|
||||
* Can easily be combined with other tools by CMake( i.e. Qt, ITK and VTK )
|
||||
* The easiest way of using OpenCV in your code is to use `CMake <http://www.cmake.org/>`_. A few advantages (taken from the Wiki):
|
||||
|
||||
If you are not familiar with CMake, checkout the `tutorial <http://www.cmake.org/cmake/help/cmake_tutorial.html>`_ on its website.
|
||||
#. No need to change anything when porting between Linux and Windows
|
||||
#. Can easily be combined with other tools by CMake( i.e. Qt, ITK and VTK )
|
||||
|
||||
* If you are not familiar with CMake, checkout the `tutorial <http://www.cmake.org/cmake/help/cmake_tutorial.html>`_ on its website.
|
||||
|
||||
Steps
|
||||
======
|
||||
|
||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
@@ -26,6 +26,25 @@ Use the powerfull machine learning classes for statistical classification, regre
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
+
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
============ ==============================================
|
||||
|NonLinSVM| **Title:** :ref:`nonLinearSvmS`
|
||||
|
||||
*Compatibility:* > OpenCV 2.0
|
||||
|
||||
*Author:* |Author_FernandoI|
|
||||
|
||||
Here you will learn how to define the optimization problem for SVMs when it is not possible to separate linearly the training data.
|
||||
|
||||
============ ==============================================
|
||||
|
||||
.. |NonLinSVM| image:: images/non_linear_svms.png
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\pagebreak
|
||||
@@ -34,3 +53,4 @@ Use the powerfull machine learning classes for statistical classification, regre
|
||||
:hidden:
|
||||
|
||||
../introduction_to_svm/introduction_to_svm
|
||||
../non_linear_svms/non_linear_svms
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
.. _cascade_classifier:
|
||||
|
||||
Cascade Classifier
|
||||
*******************
|
||||
|
||||
Goal
|
||||
=====
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Use the :cascade_classifier:`CascadeClassifier <>` class to detect objects in a video stream. Particularly, we will use the functions:
|
||||
|
||||
* :cascade_classifier_load:`load <>` to load a .xml classifier file. It can be either a Haar or a LBP classifer
|
||||
* :cascade_classifier_detect_multiscale:`detectMultiScale <>` to perform the detection.
|
||||
|
||||
|
||||
Theory
|
||||
======
|
||||
|
||||
Code
|
||||
====
|
||||
|
||||
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp>`_ . The second version (using LBP for face detection) can be found `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/objectDetection/objectDetection2.cpp>`_
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/objdetect/objdetect.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
/** Function Headers */
|
||||
void detectAndDisplay( Mat frame );
|
||||
|
||||
/** Global variables */
|
||||
String face_cascade_name = "haarcascade_frontalface_alt.xml";
|
||||
String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
|
||||
CascadeClassifier face_cascade;
|
||||
CascadeClassifier eyes_cascade;
|
||||
string window_name = "Capture - Face detection";
|
||||
RNG rng(12345);
|
||||
|
||||
/** @function main */
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
CvCapture* capture;
|
||||
Mat frame;
|
||||
|
||||
//-- 1. Load the cascades
|
||||
if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
|
||||
if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
|
||||
|
||||
//-- 2. Read the video stream
|
||||
capture = cvCaptureFromCAM( -1 );
|
||||
if( capture )
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
frame = cvQueryFrame( capture );
|
||||
|
||||
//-- 3. Apply the classifier to the frame
|
||||
if( !frame.empty() )
|
||||
{ detectAndDisplay( frame ); }
|
||||
else
|
||||
{ printf(" --(!) No captured frame -- Break!"); break; }
|
||||
|
||||
int c = waitKey(10);
|
||||
if( (char)c == 'c' ) { break; }
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @function detectAndDisplay */
|
||||
void detectAndDisplay( Mat frame )
|
||||
{
|
||||
std::vector<Rect> faces;
|
||||
Mat frame_gray;
|
||||
|
||||
cvtColor( frame, frame_gray, CV_BGR2GRAY );
|
||||
equalizeHist( frame_gray, frame_gray );
|
||||
|
||||
//-- Detect faces
|
||||
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
|
||||
|
||||
for( int i = 0; i < faces.size(); i++ )
|
||||
{
|
||||
Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
|
||||
ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
|
||||
|
||||
Mat faceROI = frame_gray( faces[i] );
|
||||
std::vector<Rect> eyes;
|
||||
|
||||
//-- In each face, detect eyes
|
||||
eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );
|
||||
|
||||
for( int j = 0; j < eyes.size(); j++ )
|
||||
{
|
||||
Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );
|
||||
int radius = cvRound( (eyes[j].width + eyes[i].height)*0.25 );
|
||||
circle( frame, center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 );
|
||||
}
|
||||
}
|
||||
//-- Show what you got
|
||||
imshow( window_name, frame );
|
||||
}
|
||||
|
||||
Explanation
|
||||
============
|
||||
|
||||
Result
|
||||
======
|
||||
|
||||
#. Here is the result of running the code above and using as input the video stream of a build-in webcam:
|
||||
|
||||
.. image:: images/Cascade_Classifier_Tutorial_Result_Haar.jpg
|
||||
:align: center
|
||||
:height: 300pt
|
||||
|
||||
Remember to copy the files *haarcascade_frontalface_alt.xml* and *haarcascade_eye_tree_eyeglasses.xml* in your current directory. They are located in *opencv/data/haarcascades*
|
||||
|
||||
#. This is the result of using the file *lbpcascade_frontalface.xml* (LBP trained) for the face detection. For the eyes we keep using the file used in the tutorial.
|
||||
|
||||
.. image:: images/Cascade_Classifier_Tutorial_Result_LBP.jpg
|
||||
:align: center
|
||||
:height: 300pt
|
||||
|
||||
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 39 KiB |
@@ -5,4 +5,32 @@
|
||||
|
||||
Ever wondered how your digital camera detects peoples and faces? Look here to find out!
|
||||
|
||||
.. include:: ../../definitions/noContent.rst
|
||||
.. include:: ../../definitions/tocDefinitions.rst
|
||||
|
||||
+
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
===================== ==============================================
|
||||
|CascadeClassif| **Title:** :ref:`cascade_classifier`
|
||||
|
||||
*Compatibility:* > OpenCV 2.0
|
||||
|
||||
*Author:* |Author_AnaH|
|
||||
|
||||
Here we learn how to use *objdetect* to find objects in our images or videos
|
||||
|
||||
===================== ==============================================
|
||||
|
||||
.. |CascadeClassif| image:: images/Cascade_Classifier_Tutorial_Cover.jpg
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\pagebreak
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
../cascade_classifier/cascade_classifier
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
import numpy as np
|
||||
import cv2
|
||||
from common import anorm
|
||||
from functools import partial
|
||||
|
||||
help_message = '''SURF image match
|
||||
|
||||
USAGE: findobj.py [ <image1> <image2> ]
|
||||
'''
|
||||
|
||||
FLANN_INDEX_KDTREE = 1 # bug: flann enums are missing
|
||||
|
||||
def match(desc1, desc2, r_threshold = 0.75):
|
||||
flann_params = dict(algorithm = FLANN_INDEX_KDTREE,
|
||||
trees = 4)
|
||||
|
||||
def match_bruteforce(desc1, desc2, r_threshold = 0.75):
|
||||
res = []
|
||||
for i in xrange(len(desc1)):
|
||||
dist = anorm( desc2 - desc1[i] )
|
||||
@@ -18,6 +23,14 @@ def match(desc1, desc2, r_threshold = 0.75):
|
||||
res.append((i, n1))
|
||||
return np.array(res)
|
||||
|
||||
def match_flann(desc1, desc2, r_threshold = 0.6):
|
||||
flann = cv2.flann_Index(desc2, flann_params)
|
||||
idx2, dist = flann.knnSearch(desc1, 2, params = {}) # bug: need to provide empty dict
|
||||
mask = dist[:,0] / dist[:,1] < r_threshold
|
||||
idx1 = np.arange(len(desc1))
|
||||
pairs = np.int32( zip(idx1, idx2[:,0]) )
|
||||
return pairs[mask]
|
||||
|
||||
def draw_match(img1, img2, p1, p2, status = None, H = None):
|
||||
h1, w1 = img1.shape[:2]
|
||||
h2, w2 = img2.shape[:2]
|
||||
@@ -50,6 +63,7 @@ def draw_match(img1, img2, p1, p2, status = None, H = None):
|
||||
cv2.line(vis, (x2+w1-r, y2+r), (x2+w1+r, y2-r), col, thickness)
|
||||
return vis
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
try: fn1, fn2 = sys.argv[1:3]
|
||||
@@ -68,12 +82,21 @@ if __name__ == '__main__':
|
||||
desc2.shape = (-1, surf.descriptorSize())
|
||||
print 'img1 - %d features, img2 - %d features' % (len(kp1), len(kp2))
|
||||
|
||||
m = match(desc1, desc2)
|
||||
matched_p1 = np.array([kp1[i].pt for i, j in m])
|
||||
matched_p2 = np.array([kp2[j].pt for i, j in m])
|
||||
H, status = cv2.findHomography(matched_p1, matched_p2, cv2.RANSAC, 10.0)
|
||||
print '%d / %d inliers/matched' % (np.sum(status), len(status))
|
||||
def match_and_draw(match, r_threshold):
|
||||
m = match(desc1, desc2, r_threshold)
|
||||
matched_p1 = np.array([kp1[i].pt for i, j in m])
|
||||
matched_p2 = np.array([kp2[j].pt for i, j in m])
|
||||
H, status = cv2.findHomography(matched_p1, matched_p2, cv2.RANSAC, 5.0)
|
||||
print '%d / %d inliers/matched' % (np.sum(status), len(status))
|
||||
|
||||
vis = draw_match(img1, img2, matched_p1, matched_p2, status, H)
|
||||
cv2.imshow('find_obj SURF', vis)
|
||||
vis = draw_match(img1, img2, matched_p1, matched_p2, status, H)
|
||||
return vis
|
||||
|
||||
print 'bruteforce match:',
|
||||
vis_brute = match_and_draw( match_bruteforce, 0.75 )
|
||||
print 'flann match:',
|
||||
vis_flann = match_and_draw( match_flann, 0.6 ) # flann tends to find more distant second
|
||||
# neighbours, so r_threshold is decreased
|
||||
cv2.imshow('find_obj SURF', vis_brute)
|
||||
cv2.imshow('find_obj SURF flann', vis_flann)
|
||||
cv2.waitKey()
|
||||