Commit c5536534 authored by Maksim Shabunin's avatar Maksim Shabunin

Doxygen tutorials: warnings cleared

parent 8375182e
......@@ -199,7 +199,7 @@ if(BUILD_DOCS AND HAVE_DOXYGEN)
set(tutorial_path "${CMAKE_CURRENT_SOURCE_DIR}/tutorials")
string(REPLACE ";" " \\\n" CMAKE_DOXYGEN_INPUT_LIST "${rootfile} ; ${paths_include} ; ${paths_doc} ; ${tutorial_path}")
string(REPLACE ";" " \\\n" CMAKE_DOXYGEN_IMAGE_PATH "${paths_doc} ; ${tutorial_path}")
string(REPLACE ";" " \\\n" CMAKE_DOXYGEN_EXAMPLE_PATH "${CMAKE_SOURCE_DIR}/samples/cpp ; ${paths_doc}")
string(REPLACE ";" " \\\n" CMAKE_DOXYGEN_EXAMPLE_PATH "${CMAKE_SOURCE_DIR}/samples ; ${paths_doc}")
set(CMAKE_DOXYGEN_LAYOUT "${CMAKE_CURRENT_SOURCE_DIR}/DoxygenLayout.xml")
set(CMAKE_DOXYGEN_OUTPUT_PATH "doxygen")
set(CMAKE_EXTRA_BIB_FILES "${bibfile} ${paths_bib}")
......
......@@ -91,7 +91,7 @@ directory mentioned above.
The application starts up with reading the settings from the configuration file. Although, this is
an important part of it, it has nothing to do with the subject of this tutorial: *camera
calibration*. Therefore, I've chosen not to post the code for that part here. Technical background
on how to do this you can find in the @ref fileInputOutputXMLYAML tutorial.
on how to do this you can find in the @ref tutorial_file_input_output_with_xml_yml tutorial.
Explanation
-----------
......@@ -486,4 +486,3 @@ here](https://www.youtube.com/watch?v=ViPN810E0SU).
<iframe title=" Camera calibration With OpenCV - Chessboard or asymmetrical circle pattern." width="560" height="349" src="http://www.youtube.com/embed/ViPN810E0SU?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>
\endhtmlonly
......@@ -51,8 +51,7 @@ plane:
\f[s\ \left [ \begin{matrix} u \\ v \\ 1 \end{matrix} \right ] = \left [ \begin{matrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{matrix} \right ] \left [ \begin{matrix} r_{11} & r_{12} & r_{13} & t_1 \\ r_{21} & r_{22} & r_{23} & t_2 \\ r_{31} & r_{32} & r_{33} & t_3 \end{matrix} \right ] \left [ \begin{matrix} X \\ Y \\ Z\\ 1 \end{matrix} \right ]\f]
The complete documentation of how to manage with this equations is in @ref cv::Camera Calibration
and 3D Reconstruction .
The complete documentation of how to manage with this equations is in @ref calib3d .
Source code
-----------
......@@ -80,7 +79,7 @@ then uses the mesh along with the [Möller–Trumbore intersection
algorithm](http://http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm/)
to compute the 3D coordinates of the found features. Finally, the 3D points and the descriptors
are stored in different lists in a file with YAML format which each row is a different point. The
technical background on how to store the files can be found in the @ref fileInputOutputXMLYAML
technical background on how to store the files can be found in the @ref tutorial_file_input_output_with_xml_yml
tutorial.
![image](images/registration.png)
......@@ -91,9 +90,9 @@ The aim of this application is estimate in real time the object pose given its 3
The application starts up loading the 3D textured model in YAML file format with the same
structure explained in the model registration program. From the scene, the ORB features and
descriptors are detected and extracted. Then, is used @ref cv::FlannBasedMatcher with @ref
cv::LshIndexParams to do the matching between the scene descriptors and the model descriptors.
Using the found matches along with @ref cv::solvePnPRansac function the @ref cv::R\` and \f$t\f$ of
descriptors are detected and extracted. Then, is used @ref cv::FlannBasedMatcher with
@ref cv::flann::GenericIndex to do the matching between the scene descriptors and the model descriptors.
Using the found matches along with @ref cv::solvePnPRansac function the `R` and `t` of
the camera are computed. Finally, a KalmanFilter is applied in order to reject bad poses.
In the case that you compiled OpenCV with the samples, you can find it in opencv/build/bin/cpp-tutorial-pnp_detection\`.
......@@ -242,7 +241,7 @@ implemented a *class* **RobustMatcher** which has a function for keypoints detec
extraction. You can find it in
`samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/RobusMatcher.cpp`. In your
*RobusMatch* object you can use any of the 2D features detectors of OpenCV. In this case I used
@ref cv::ORB features because is based on @ref cv::FAST to detect the keypoints and @ref cv::BRIEF
@ref cv::ORB features because is based on @ref cv::FAST to detect the keypoints and @ref cv::xfeatures2d::BriefDescriptorExtractor
to extract the descriptors which means that is fast and robust to rotations. You can find more
detailed information about *ORB* in the documentation.
......@@ -265,9 +264,9 @@ It is the first step in our detection algorithm. The main idea is to match the s
with our model descriptors in order to know the 3D coordinates of the found features into the
current scene.
Firstly, we have to set which matcher we want to use. In this case is used @ref
cv::FlannBasedMatcher matcher which in terms of computational cost is faster than the @ref
cv::BruteForceMatcher matcher as we increase the trained collectction of features. Then, for
Firstly, we have to set which matcher we want to use. In this case is used
@ref cv::FlannBasedMatcher matcher which in terms of computational cost is faster than the
@ref cv::BFMatcher matcher as we increase the trained collectction of features. Then, for
FlannBased matcher the index created is *Multi-Probe LSH: Efficient Indexing for High-Dimensional
Similarity Search* due to *ORB* descriptors are binary.
......@@ -349,8 +348,8 @@ void RobustMatcher::robustMatch( const cv::Mat& frame, std::vector<cv::DMatch>&
}
@endcode
After the matches filtering we have to subtract the 2D and 3D correspondences from the found scene
keypoints and our 3D model using the obtained *DMatches* vector. For more information about @ref
cv::DMatch check the documentation.
keypoints and our 3D model using the obtained *DMatches* vector. For more information about
@ref cv::DMatch check the documentation.
@code{.cpp}
// -- Step 2: Find out the 2D/3D correspondences
......@@ -385,8 +384,8 @@ solution.
For the camera pose estimation I have implemented a *class* **PnPProblem**. This *class* has 4
atributes: a given calibration matrix, the rotation matrix, the translation matrix and the
rotation-translation matrix. The intrinsic calibration parameters of the camera which you are
using to estimate the pose are necessary. In order to obtain the parameters you can check @ref
CameraCalibrationSquareChessBoardTutorial and @ref cameraCalibrationOpenCV tutorials.
using to estimate the pose are necessary. In order to obtain the parameters you can check
@ref tutorial_camera_calibration_square_chess and @ref tutorial_camera_calibration tutorials.
The following code is how to declare the *PnPProblem class* in the main program:
@code{.cpp}
......@@ -543,9 +542,9 @@ Filter will be applied after detected a given number of inliers.
You can find more information about what [Kalman
Filter](http://en.wikipedia.org/wiki/Kalman_filter) is. In this tutorial it's used the OpenCV
implementation of the @ref cv::Kalman Filter based on [Linear Kalman Filter for position and
orientation tracking](http://campar.in.tum.de/Chair/KalmanFilter) to set the dynamics and
measurement models.
implementation of the @ref cv::KalmanFilter based on
[Linear Kalman Filter for position and orientation tracking](http://campar.in.tum.de/Chair/KalmanFilter)
to set the dynamics and measurement models.
Firstly, we have to define our state vector which will have 18 states: the positional data (x,y,z)
with its first and second derivatives (velocity and acceleration), then rotation is added in form
......@@ -796,4 +795,3 @@ here](http://www.youtube.com/user/opencvdev/videos).
<iframe title="Pose estimation of textured object using OpenCV in cluttered background" width="560" height="349" src="http://www.youtube.com/embed/YLS9bWek78k?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>
\endhtmlonly
......@@ -87,25 +87,18 @@ Explanation
Since we are *adding* *src1* and *src2*, they both have to be of the same size (width and
height) and type.
2. Now we need to generate the @ref cv::g(x)\` image. For this, the function
add_weighted:addWeighted comes quite handy:
.. code-block:: cpp
2. Now we need to generate the `g(x)` image. For this, the function add_weighted:addWeighted comes quite handy:
@code{.cpp}
beta = ( 1.0 - alpha );
addWeighted( src1, alpha, src2, beta, 0.0, dst);
@endcode
since @ref cv::addWeighted produces:
\f[dst = \alpha \cdot src1 + \beta \cdot src2 + \gamma\f]
In this case, `gamma` is the argument \f$0.0\f$ in the code above.
.. math::
dst = \\alpha \\cdot src1 + \\beta \\cdot src2 + \\gamma
In this case, :math:gamma\` is the argument \f$0.0\f$ in the code above.
3. Create windows, show the images and wait for the user to end the program.
Result
------
![image](images/Adding_Images_Tutorial_Result_0.jpg)
![image](images/Adding_Images_Tutorial_Result_Big.jpg)
......@@ -115,6 +115,6 @@ Explanation
Result
=======
.. image:: images/Adding_Images_Tutorial_Result_0.jpg
.. image:: images/Adding_Images_Tutorial_Result_Big.jpg
:alt: Blending Images Tutorial - Final Result
:align: center
......@@ -97,6 +97,7 @@ int main( int argc, char** argv )
return 0;
}
@endcode
Explanation
-----------
......@@ -134,11 +135,10 @@ Explanation
}
@endcode
Notice the following:
- To access each pixel in the images we are using this syntax: *image.at\<Vec3b\>(y,x)[c]*
where *y* is the row, *x* is the column and *c* is R, G or B (0, 1 or 2).
- Since the operation @ref cv::alpha cdot p(i,j) + beta\` can give values out of range or not
integers (if \f$\alpha\f$ is float), we use :saturate_cast:\`saturate_cast to make sure the
- Since the operation \f$\alpha \cdot p(i,j) + \beta\f$ can give values out of range or not
integers (if \f$\alpha\f$ is float), we use cv::saturate_cast to make sure the
values are valid.
5. Finally, we create windows and show the images, the usual way.
......@@ -151,12 +151,13 @@ Explanation
waitKey(0);
@endcode
@note
Instead of using the **for** loops to access each pixel, we could have simply used this command:
@code{.cpp}
image.convertTo(new_image, -1, alpha, beta);
@endcode
where @ref cv::convertTo would effectively perform *new_image = a*image + beta\*. However, we
where @ref cv::Mat::convertTo would effectively perform *new_image = a*image + beta\*. However, we
wanted to show you how to access each pixel. In any case, both methods give the same result but
convertTo is more optimized and works a lot faster.
......@@ -171,8 +172,7 @@ Result
* Enter the alpha value [1.0-3.0]: 2.2
* Enter the beta value [0-100]: 50
@endcode
- We get this:
![image](images/Basic_Linear_Transform_Tutorial_Result_0.jpg)
- We get this:
![image](images/Basic_Linear_Transform_Tutorial_Result_big.jpg)
......@@ -204,6 +204,6 @@ Result
* We get this:
.. image:: images/Basic_Linear_Transform_Tutorial_Result_0.jpg
.. image:: images/Basic_Linear_Transform_Tutorial_Result_big.jpg
:alt: Basic Linear Transform - Final Result
:align: center
......@@ -79,10 +79,12 @@ double t = (double)getTickCount();
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Times passed in seconds: " << t << endl;
@endcode
@anchor tutorial_how_to_scan_images_storing
How the image matrix is stored in the memory?
---------------------------------------------
As you could already read in my @ref matTheBasicImageContainer tutorial the size of the matrix
As you could already read in my @ref tutorial_mat_the_basic_image_container tutorial the size of the matrix
depends of the color system used. More accurately, it depends from the number of channels used. In
case of a gray scale image we have something like:
......@@ -110,7 +112,7 @@ Row n & \tabIt{n,0} & \tabIt{n,1} & \tabIt{n,...} & \tabIt{n, m} \\
Note that the order of the channels is inverse: BGR instead of RGB. Because in many cases the memory
is large enough to store the rows in a successive fashion the rows may follow one after another,
creating a single long row. Because everything is in a single place following one after another this
may help to speed up the scanning process. We can use the @ref cv::isContinuous() function to *ask*
may help to speed up the scanning process. We can use the @ref cv::Mat::isContinuous() function to *ask*
the matrix if this is the case. Continue on to the next section to find an example.
The efficient way
......@@ -227,12 +229,12 @@ differences I've used a quite large (2560 X 1600) image. The performance present
color images. For a more accurate value I've averaged the value I got from the call of the function
for hundred times.
--------------- ----------------------
Efficient Way 79.4717 milliseconds
Iterator 83.7201 milliseconds
On-The-Fly RA 93.7878 milliseconds
LUT function 32.5759 milliseconds
--------------- ----------------------
Method | Time
--------------- | ----------------------
Efficient Way | 79.4717 milliseconds
Iterator | 83.7201 milliseconds
On-The-Fly RA | 93.7878 milliseconds
LUT function | 32.5759 milliseconds
We can conclude a couple of things. If possible, use the already made functions of OpenCV (instead
reinventing these). The fastest method turns out to be the LUT function. This is because the OpenCV
......@@ -242,12 +244,10 @@ Using the on-the-fly reference access method for full image scan is the most cos
In the release mode it may beat the iterator approach or not, however it surely sacrifices for this
the safety trait of iterators.
Finally, you may watch a sample run of the program on the [video
posted](https://www.youtube.com/watch?v=fB3AN5fjgwc) on our YouTube channel.
Finally, you may watch a sample run of the program on the [video posted](https://www.youtube.com/watch?v=fB3AN5fjgwc) on our YouTube channel.
\htmlonly
<div align="center">
<iframe title="How to scan images in OpenCV?" width="560" height="349" src="http://www.youtube.com/embed/fB3AN5fjgwc?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>
\endhtmlonly
......@@ -16,8 +16,7 @@ Code
You may also find the source code in the
`samples/cpp/tutorial_code/core/ippasync/ippasync_sample.cpp` file of the OpenCV source library or
download it from here
\<../../../../samples/cpp/tutorial_code/core/ippasync/ippasync_sample.cpp\>.
download it from [here](samples/cpp/tutorial_code/core/ippasync/ippasync_sample.cpp).
@includelineno cpp/tutorial_code/core/ippasync/ippasync_sample.cpp
......@@ -37,8 +36,8 @@ Explanation
hppStatus sts;
hppiVirtualMatrix * virtMatrix;
@endcode
2. Load input image or video. How to open and read video stream you can see in the @ref
videoInputPSNRMSSIM tutorial.
2. Load input image or video. How to open and read video stream you can see in the
@ref tutorial_video_input_psnr_ssim tutorial.
@code{.cpp}
if( useCamera )
{
......@@ -83,7 +82,7 @@ Explanation
result.create( image.rows, image.cols, CV_8U);
@endcode
6. Convert Mat to [hppiMatrix](http://software.intel.com/en-us/node/501660) using @ref cv::getHpp
6. Convert Mat to [hppiMatrix](http://software.intel.com/en-us/node/501660) using @ref cv::hpp::getHpp
and call [hppiSobel](http://software.intel.com/en-us/node/474701) function.
@code{.cpp}
//convert Mat to hppiMatrix
......@@ -134,6 +133,7 @@ Explanation
CHECK_DEL_STATUS(sts, "hppDeleteInstance");
}
@endcode
Result
------
......@@ -141,4 +141,3 @@ After compiling the code above we can execute it giving an image or video path a
as an argument. For this tutorial we use baboon.png image as input. The result is below.
![image](images/How_To_Use_IPPA_Result.jpg)
......@@ -19,8 +19,8 @@ this. In the following you'll learn:
General
-------
When making the switch you first need to learn some about the new data structure for images: @ref
matTheBasicImageContainer, this replaces the old *CvMat* and *IplImage* ones. Switching to the new
When making the switch you first need to learn some about the new data structure for images:
@ref tutorial_mat_the_basic_image_container, this replaces the old *CvMat* and *IplImage* ones. Switching to the new
functions is easier. You just need to remember a couple of new things.
OpenCV 2 received reorganization. No longer are all the functions crammed into a single library. We
......@@ -46,8 +46,8 @@ and the subsequent words start with a capital letter (like *copyMakeBorder*).
Now, remember that you need to link to your application all the modules you use, and in case you are
on Windows using the *DLL* system you will need to add, again, to the path all the binaries. For
more in-depth information if you're on Windows read @ref Windows_Visual_Studio_How_To and for
Linux an example usage is explained in @ref Linux_Eclipse_Usage.
more in-depth information if you're on Windows read @ref tutorial_windows_visual_studio_Opencv and for
Linux an example usage is explained in @ref tutorial_linux_eclipse.
Now for converting the *Mat* object you can use either the *IplImage* or the *CvMat* operators.
While in the C interface you used to work with pointers here it's no longer the case. In the C++
......@@ -81,11 +81,11 @@ For example:
Mat K(piL), L;
L = Mat(pI);
@endcode
A case study
------------
Now that you have the basics done [here's
](samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp)
Now that you have the basics done [here's](samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp)
an example that mixes the usage of the C interface with the C++ one. You will also find it in the
sample directory of the OpenCV source code library at the
`samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp` .
......@@ -124,7 +124,7 @@ lines
Here you can observe that we may go through all the pixels of an image in three fashions: an
iterator, a C pointer and an individual element access style. You can read a more in-depth
description of these in the @ref howToScanImagesOpenCV tutorial. Converting from the old function
description of these in the @ref tutorial_how_to_scan_images tutorial. Converting from the old function
names is easy. Just remove the cv prefix and use the new *Mat* data structure. Here's an example of
this by using the weighted addition function:
......@@ -161,4 +161,3 @@ of the OpenCV source code library.
<iframe title="Interoperability with OpenCV 1" width="560" height="349" src="http://www.youtube.com/embed/qckm-zvo31w?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>
\endhtmlonly
......@@ -67,7 +67,7 @@ At first we make sure that the input images data is in unsigned char format. For
CV_Assert(myImage.depth() == CV_8U); // accept only uchar images
@endcode
We create an output image with the same size and the same type as our input. As you can see in the
@ref How_Image_Stored_Memory section, depending on the number of channels we may have one or more
@ref tutorial_how_to_scan_images_storing "storing" section, depending on the number of channels we may have one or more
subcolumns. We will iterate through them via pointers so the total number of elements depends from
this number.
@code{.cpp}
......@@ -104,6 +104,7 @@ Result.row(Result.rows - 1).setTo(Scalar(0)); // The bottom row
Result.col(0).setTo(Scalar(0)); // The left column
Result.col(Result.cols - 1).setTo(Scalar(0)); // The right column
@endcode
The filter2D function
---------------------
......
......@@ -18,8 +18,8 @@ numerical matrices and other information describing the matrix itself. *OpenCV*
library whose main focus is to process and manipulate this information. Therefore, the first thing
you need to be familiar with is how OpenCV stores and handles images.
*Mat*
-----
Mat
---
OpenCV has been around since 2001. In those days the library was built around a *C* interface and to
store the image in the memory they used a C structure called *IplImage*. This is the one you'll see
......@@ -62,6 +62,7 @@ To tackle this issue OpenCV uses a reference counting system. The idea is that e
its own header, however the matrix may be shared between two instance of them by having their matrix
pointers point to the same address. Moreover, the copy operators **will only copy the headers** and
the pointer to the large matrix, not the data itself.
@code{.cpp}
Mat A, C; // creates just the header parts
A = imread(argv[1], IMREAD_COLOR); // here we'll know the method used (allocate matrix)
......@@ -70,6 +71,7 @@ Mat B(A); // Use the copy constructor
C = A; // Assignment operator
@endcode
All the above objects, in the end, point to the same single data matrix. Their headers are
different, however, and making a modification using any of them will affect all the other ones as
well. In practice the different objects just provide different access method to the same underlying
......@@ -85,7 +87,7 @@ for cleaning it up when it's no longer needed. The short answer is: the last obj
This is handled by using a reference counting mechanism. Whenever somebody copies a header of a
*Mat* object, a counter is increased for the matrix. Whenever a header is cleaned this counter is
decreased. When the counter reaches zero the matrix too is freed. Sometimes you will want to copy
the matrix itself too, so OpenCV provides the @ref cv::clone() and @ref cv::copyTo() functions.
the matrix itself too, so OpenCV provides the @ref cv::Mat::clone() and @ref cv::Mat::copyTo() functions.
@code{.cpp}
Mat F = A.clone();
Mat G;
......@@ -97,10 +99,10 @@ remember from all this is that:
- Output image allocation for OpenCV functions is automatic (unless specified otherwise).
- You do not need to think about memory management with OpenCVs C++ interface.
- The assignment operator and the copy constructor only copies the header.
- The underlying matrix of an image may be copied using the @ref cv::clone() and @ref cv::copyTo()
- The underlying matrix of an image may be copied using the @ref cv::Mat::clone() and @ref cv::Mat::copyTo()
functions.
*Storing* methods
Storing methods
-----------------
This is about how you store the pixel values. You can select the color space and the data type used.
......@@ -134,10 +136,10 @@ using the float (4 byte = 32 bit) or double (8 byte = 64 bit) data types for eac
Nevertheless, remember that increasing the size of a component also increases the size of the whole
picture in the memory.
Creating a *Mat* object explicitly
Creating a Mat object explicitly
----------------------------------
In the @ref Load_Save_Image tutorial you have already learned how to write a matrix to an image
In the @ref tutorial_load_save_image tutorial you have already learned how to write a matrix to an image
file by using the @ref cv::imwrite() function. However, for debugging purposes it's much more
convenient to see the actual values. You can do this using the \<\< operator of *Mat*. Be aware that
this only works for two dimensional matrices.
......@@ -146,29 +148,28 @@ Although *Mat* works really well as an image container, it is also a general mat
Therefore, it is possible to create and manipulate multidimensional matrices. You can create a Mat
object in multiple ways:
- @ref cv::Mat() Constructor
- @ref cv::Mat::Mat Constructor
@includelineno
cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp
lines
27-28
lines 27-28
![image](images/MatBasicContainerOut1.png)
![image](images/MatBasicContainerOut1.png)
For two dimensional and multichannel images we first define their size: row and column count wise.
For two dimensional and multichannel images we first define their size: row and column count wise.
Then we need to specify the data type to use for storing the elements and the number of channels
per matrix point. To do this we have multiple definitions constructed according to the following
convention:
@code{.cpp}
CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
@endcode
For instance, *CV_8UC3* means we use unsigned char types that are 8 bit long and each pixel has
three of these to form the three channels. This are predefined for up to four channel numbers. The
@ref cv::Scalar is four element short vector. Specify this and you can initialize all matrix
points with a custom value. If you need more you can create the type with the upper macro, setting
the channel number in parenthesis as you can see below.
Then we need to specify the data type to use for storing the elements and the number of channels
per matrix point. To do this we have multiple definitions constructed according to the following
convention:
@code{.cpp}
CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
@endcode
For instance, *CV_8UC3* means we use unsigned char types that are 8 bit long and each pixel has
three of these to form the three channels. This are predefined for up to four channel numbers. The
@ref cv::Scalar is four element short vector. Specify this and you can initialize all matrix
points with a custom value. If you need more you can create the type with the upper macro, setting
the channel number in parenthesis as you can see below.
- Use C/C++ arrays and initialize via constructor
......@@ -187,20 +188,19 @@ the channel number in parenthesis as you can see below.
IplImage* img = cvLoadImage("greatwave.png", 1);
Mat mtx(img); // convert IplImage* -> Mat
@endcode
- @ref cv::Create() function:
- @ref cv::Mat::create function:
@includelineno
cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp
lines
31-32
lines 31-32
![image](images/MatBasicContainerOut2.png)
![image](images/MatBasicContainerOut2.png)
You cannot initialize the matrix values with this construction. It will only reallocate its matrix
data memory if the new size will not fit into the old one.
You cannot initialize the matrix values with this construction. It will only reallocate its matrix
data memory if the new size will not fit into the old one.
- MATLAB style initializer: @ref cv::zeros() , @ref cv::ones() , @ref cv::eye() . Specify size and
- MATLAB style initializer: @ref cv::Mat::zeros , @ref cv::Mat::ones , @ref cv::Mat::eye . Specify size and
data type to use:
@includelineno
......@@ -209,29 +209,27 @@ data memory if the new size will not fit into the old one.
lines
40-47
![image](images/MatBasicContainerOut3.png)
![image](images/MatBasicContainerOut3.png)
- For small matrices you may use comma separated initializers:
@includelineno
cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp
lines
50-51
lines 50-51
![image](images/MatBasicContainerOut6.png)
![image](images/MatBasicContainerOut6.png)
- Create a new header for an existing *Mat* object and @ref cv::clone() or @ref cv::copyTo() it.
- Create a new header for an existing *Mat* object and @ref cv::Mat::clone or @ref cv::Mat::copyTo it.
@includelineno
cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp
lines
53-54
lines 53-54
![image](images/MatBasicContainerOut7.png)
@note
@note
You can fill out a matrix with random values using the @ref cv::randu() function. You need to
give the lower and upper value for the random values:
......@@ -343,8 +341,7 @@ OpenCV offers support for output of other common OpenCV data structures too via
![image](images/MatBasicContainerOut15.png)
Most of the samples here have been included in a small console application. You can download it from
[here
](samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp)
[here](samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp)
or in the core section of the cpp samples.
You can also find a quick video demonstration of this on
......@@ -355,4 +352,3 @@ You can also find a quick video demonstration of this on
<iframe title="Install OpenCV by using its source files - Part 1" width="560" height="349" src="http://www.youtube.com/embed/1tibU7vGWpk?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>
\endhtmlonly
......@@ -13,15 +13,14 @@ In this tutorial you will learn how to:
Code
----
- In the previous tutorial (@ref Drawing_1) we drew diverse geometric figures, giving as input
parameters such as coordinates (in the form of @ref cv::Points ), color, thickness, etc. You
- In the previous tutorial (@ref tutorial_basic_geometric_drawing) we drew diverse geometric figures, giving as input
parameters such as coordinates (in the form of @ref cv::Point), 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](http://code.opencv.org/projects/opencv/repository/revisions/master/raw/samples/cpp/tutorial_code/core/Matrix/Drawing_2.cpp)
.
Explanation
-----------
......@@ -213,9 +212,9 @@ Explanation
**image** minus the value of **i** (remember that for each pixel we are considering three values
such as R, G and B, so each of them will be affected)
Also remember that the substraction operation *always* performs internally a **saturate**
operation, which means that the result obtained will always be inside the allowed range (no
negative and between 0 and 255 for our example).
Also remember that the substraction operation *always* performs internally a **saturate**
operation, which means that the result obtained will always be inside the allowed range (no
negative and between 0 and 255 for our example).
Result
------
......@@ -247,6 +246,4 @@ functions, which will produce:
colors and positions.
8. And the big end (which by the way expresses a big truth too):
![image](images/Drawing_2_Tutorial_Result_7.jpg)
![image](images/Drawing_2_Tutorial_Result_big.jpg)
......@@ -262,6 +262,6 @@ As you just saw in the Code section, the program will sequentially execute diver
#. And the big end (which by the way expresses a big truth too):
.. image:: images/Drawing_2_Tutorial_Result_7.jpg
.. image:: images/Drawing_2_Tutorial_Result_big.jpg
:alt: Drawing Tutorial 2 - Final Result 7
:align: center
......@@ -8,7 +8,7 @@ In this tutorial you will learn how to:
- Use the @ref cv::DescriptorExtractor interface in order to find the feature vector correspondent
to the keypoints. Specifically:
- Use @ref cv::SurfDescriptorExtractor and its function @ref cv::compute to perform the
- Use @ref cv::xfeatures2d::SURF and its function @ref cv::xfeatures2d::SURF::compute to perform the
required calculations.
- Use a @ref cv::BFMatcher to match the features vector
- Use the function @ref cv::drawMatches to draw the detected matches.
......@@ -78,14 +78,13 @@ int main( int argc, char** argv )
void readme()
{ std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; }
@endcode
Explanation
-----------
Result
------
1. Here is the result after applying the BruteForce matcher between the two original images:
![image](images/Feature_Description_BruteForce_Result.jpg)
Here is the result after applying the BruteForce matcher between the two original images:
![image](images/Feature_Description_BruteForce_Result.jpg)
......@@ -7,7 +7,7 @@ Goal
In this tutorial you will learn how to:
- Use the @ref cv::FeatureDetector interface in order to find interest points. Specifically:
- Use the @ref cv::SurfFeatureDetector and its function @ref cv::detect to perform the
- Use the @ref cv::xfeatures2d::SURF and its function @ref cv::xfeatures2d::SURF::detect to perform the
detection process
- Use the function @ref cv::drawKeypoints to draw the detected keypoints
......@@ -72,6 +72,7 @@ int main( int argc, char** argv )
void readme()
{ std::cout << " Usage: ./SURF_detector <img1> <img2>" << std::endl; }
@endcode
Explanation
-----------
......@@ -85,5 +86,3 @@ Result
2. And here is the result for the second image:
![image](images/Feature_Detection_Result_b.jpg)
......@@ -7,7 +7,7 @@ Goal
In this tutorial you will learn how to:
- Use the @ref cv::FlannBasedMatcher interface in order to perform a quick and efficient matching
by using the @ref cv::FLANN ( *Fast Approximate Nearest Neighbor Search Library* )
by using the @ref flann module
Theory
------
......@@ -123,6 +123,7 @@ int main( int argc, char** argv )
void readme()
{ std::cout << " Usage: ./SURF_FlannMatcher <img1> <img2>" << std::endl; }
@endcode
Explanation
-----------
......@@ -136,5 +137,3 @@ Result
2. Additionally, we get as console output the keypoints filtered:
![image](images/Feature_FlannMatcher_Keypoints_Result.jpg)
Similarity check (PNSR and SSIM) on the GPU {#tutorial_gpu_basics_similarity}
===========================================
@todo update this tutorial
Goal
----
In the @ref videoInputPSNRMSSIM tutorial I already presented the PSNR and SSIM methods for checking
In the @ref tutorial_video_input_psnr_ssim tutorial I already presented the PSNR and SSIM methods for checking
the similarity between the two images. And as you could see there performing these takes quite some
time, especially in the case of the SSIM. However, if the performance numbers of an OpenCV
implementation for the CPU do not satisfy you and you happen to have an NVidia CUDA GPU device in
......@@ -32,7 +33,7 @@ you'll find here only the functions itself.
The PSNR returns a float number, that if the two inputs are similar between 30 and 50 (higher is
better).
@includelineno cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp
@includelineno samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp
lines
165-210, 18-23, 210-235
......@@ -41,7 +42,7 @@ The SSIM returns the MSSIM of the images. This is too a float number between zer
better), however we have one for each channel. Therefore, we return a *Scalar* OpenCV data
structure:
@includelineno cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp
@includelineno samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp
lines
235-355, 26-42, 357-
......@@ -63,7 +64,8 @@ the cv:: to avoid confusion. I'll do the later.
@code{.cpp}
#include <opencv2/gpu.hpp> // GPU structures and methods
@endcode
GPU stands for **g**raphics **p**rocessing **u**nit. It was originally build to render graphical
GPU stands for "graphics processing unit". It was originally build to render graphical
scenes. These scenes somehow build on a lot of data. Nevertheless, these aren't all dependent one
from another in a sequential way and as it is possible a parallel processing of them. Due to this a
GPU will contain multiple smaller processing units. These aren't the state of the art processors and
......@@ -81,7 +83,7 @@ small functions to GPU is not recommended as the upload/download time will be la
you gain by a parallel execution.
Mat objects are stored only in the system memory (or the CPU cache). For getting an OpenCV matrix to
the GPU you'll need to use its GPU counterpart @ref cv::GpuMat . It works similar to the Mat with a
the GPU you'll need to use its GPU counterpart @ref cv::cuda::GpuMat . It works similar to the Mat with a
2D only limitation and no reference returning for its functions (cannot mix GPU references with CPU
ones). To upload a Mat object to the GPU you need to call the upload function after creating an
instance of the class. To download you may use simple assignment to a Mat object or use the download
......@@ -120,7 +122,7 @@ Optimization
The reason for this is that you're throwing out on the window the price for memory allocation and
data transfer. And on the GPU this is damn high. Another possibility for optimization is to
introduce asynchronous OpenCV GPU calls too with the help of the @ref cv::gpu::Stream.
introduce asynchronous OpenCV GPU calls too with the help of the @ref cv::cuda::Stream.
1. Memory allocation on the GPU is considerable. Therefore, if it’s possible allocate new memory as
few times as possible. If you create a function what you intend to call multiple times it is a
......@@ -162,7 +164,7 @@ introduce asynchronous OpenCV GPU calls too with the help of the @ref cv::gpu::S
gpu::multiply(b.mu1_mu2, 2, b.t1); //b.t1 = 2 * b.mu1_mu2 + C1;
gpu::add(b.t1, C1, b.t1);
@endcode
3. Use asynchronous calls (the @ref cv::gpu::Stream ). By default whenever you call a gpu function
3. Use asynchronous calls (the @ref cv::cuda::Stream ). By default whenever you call a gpu function
it will wait for the call to finish and return with the result afterwards. However, it is
possible to make asynchronous calls, meaning it will call for the operation execution, make the
costly data allocations for the algorithm and return back right away. Now you can call another
......@@ -182,6 +184,7 @@ introduce asynchronous OpenCV GPU calls too with the help of the @ref cv::gpu::S
gpu::split(b.t1, b.vI1, stream); // Methods (pass the stream as final parameter).
gpu::multiply(b.vI1[i], b.vI1[i], b.I1_2, stream); // I1^2
@endcode
Result and conclusion
---------------------
......
......@@ -22,7 +22,7 @@ In this tutorial you will learn how to:
Code
----
Let's modify the program made in the tutorial @ref Adding_Images. We will let the user enter the
Let's modify the program made in the tutorial @ref tutorial_adding_images. We will let the user enter the
\f$\alpha\f$ value by using the Trackbar.
@code{.cpp}
#include <opencv2/opencv.hpp>
......@@ -82,6 +82,7 @@ int main( int argc, char** argv )
return 0;
}
@endcode
Explanation
-----------
......@@ -122,7 +123,6 @@ We only analyze the code that is related to Trackbar:
}
@endcode
Note that:
- We use the value of **alpha_slider** (integer) to get a double value for **alpha**.
- **alpha_slider** is updated each time the trackbar is displaced by the user.
- We define *src1*, *src2*, *dist*, *alpha*, *alpha_slider* and *beta* as global variables,
......@@ -135,10 +135,8 @@ Result
![image](images/Adding_Trackbars_Tutorial_Result_0.jpg)
- As a manner of practice, you can also add 02 trackbars for the program made in @ref
Basic_Linear_Transform. One trackbar to set \f$\alpha\f$ and another for \f$\beta\f$. The output might
- As a manner of practice, you can also add 02 trackbars for the program made in
@ref tutorial_basic_linear_transform. One trackbar to set \f$\alpha\f$ and another for \f$\beta\f$. The output might
look like:
![image](images/Adding_Trackbars_Tutorial_Result_1.jpg)
......@@ -33,8 +33,8 @@ lines
How to read a video stream (online-camera or offline-file)?
-----------------------------------------------------------
Essentially, all the functionalities required for video manipulation is integrated in the @ref
cv::VideoCapture C++ class. This on itself builds on the FFmpeg open source library. This is a basic
Essentially, all the functionalities required for video manipulation is integrated in the @ref cv::VideoCapture
C++ class. This on itself builds on the FFmpeg open source library. This is a basic
dependency of OpenCV so you shouldn't need to worry about this. A video is composed of a succession
of images, we refer to these in the literature as frames. In case of a video file there is a *frame
rate* specifying just how long is between two frames. While for the video cameras usually there is a
......@@ -42,7 +42,7 @@ limit of just how many frames they can digitalize per second, this property is l
any time the camera sees the current snapshot of the world.
The first task you need to do is to assign to a @ref cv::VideoCapture class its source. You can do
this either via the @ref cv::constructor or its @ref cv::open function. If this argument is an
this either via the @ref cv::VideoCapture::VideoCapture or its @ref cv::VideoCapture::open function. If this argument is an
integer then you will bind the class to a camera, a device. The number passed here is the ID of the
device, assigned by the operating system. If you have a single camera attached to your system its ID
will probably be zero and further ones increasing from there. If the parameter passed to these is a
......@@ -63,8 +63,8 @@ VideoCapture captRefrnc(sourceReference);
VideoCapture captUndTst;
captUndTst.open(sourceCompareWith);
@endcode
To check if the binding of the class to a video source was successful or not use the @ref
cv::isOpened function:
To check if the binding of the class to a video source was successful or not use the @ref cv::VideoCapture::isOpened
function:
@code{.cpp}
if ( !captRefrnc.isOpened())
{
......@@ -73,10 +73,10 @@ if ( !captRefrnc.isOpened())
}
@endcode
Closing the video is automatic when the objects destructor is called. However, if you want to close
it before this you need to call its @ref cv::release function. The frames of the video are just
it before this you need to call its @ref cv::VideoCapture::release function. The frames of the video are just
simple images. Therefore, we just need to extract them from the @ref cv::VideoCapture object and put
them inside a *Mat* one. The video streams are sequential. You may get the frames one after another
by the @ref cv::read or the overloaded \>\> operator:
by the @ref cv::VideoCapture::read or the overloaded \>\> operator:
@code{.cpp}
Mat frameReference, frameUnderTest;
captRefrnc >> frameReference;
......@@ -92,11 +92,11 @@ if( frameReference.empty() || frameUnderTest.empty())
}
@endcode
A read method is made of a frame grab and a decoding applied on that. You may call explicitly these
two by using the @ref cv::grab and then the @ref cv::retrieve functions.
two by using the @ref cv::VideoCapture::grab and then the @ref cv::VideoCapture::retrieve functions.
Videos have many-many information attached to them besides the content of the frames. These are
usually numbers, however in some case it may be short character sequences (4 bytes or less). Due to
this to acquire these information there is a general function named @ref cv::get that returns double
this to acquire these information there is a general function named @ref cv::VideoCapture::get that returns double
values containing these properties. Use bitwise operations to decode the characters from a double
type and conversions where valid values are only integers. Its single argument is the ID of the
queried property. For example, here we get the size of the frames in the reference and test case
......@@ -109,7 +109,7 @@ cout << "Reference frame resolution: Width=" << refS.width << " Height=" << ref
<< " of nr#: " << captRefrnc.get(CAP_PROP_FRAME_COUNT) << endl;
@endcode
When you are working with videos you may often want to control these values yourself. To do this
there is a @ref cv::set function. Its first argument remains the name of the property you want to
there is a @ref cv::VideoCapture::set function. Its first argument remains the name of the property you want to
change and there is a second of double type containing the value to be set. It will return true if
it succeeds and false otherwise. Good examples for this is seeking in a video file to a given time
or frame:
......@@ -118,8 +118,8 @@ captRefrnc.set(CAP_PROP_POS_MSEC, 1.2); // go to the 1.2 second in the video
captRefrnc.set(CAP_PROP_POS_FRAMES, 10); // go to the 10th frame of the video
// now a read operation would read the frame at the set position
@endcode
For properties you can read and change look into the documentation of the @ref cv::get and @ref
cv::set functions.
For properties you can read and change look into the documentation of the @ref cv::VideoCapture::get and
@ref cv::VideoCapture::set functions.
Image similarity - PSNR and SSIM
--------------------------------
......@@ -178,6 +178,7 @@ implementation below.
SSIM is described more in-depth in the: "Z. Wang, A. C. Bovik, H. R. Sheikh and E. P.
Simoncelli, "Image quality assessment: From error visibility to structural similarity," IEEE
Transactions on Image Processing, vol. 13, no. 4, pp. 600-612, Apr. 2004." article.
@code{.cpp}
Scalar getMSSIM( const Mat& i1, const Mat& i2)
{
......
......@@ -5,8 +5,8 @@ Goal
----
Whenever you work with video feeds you may eventually want to save your image processing result in a
form of a new video file. For simple video outputs you can use the OpenCV built-in @ref
cv::VideoWriter class, designed for this.
form of a new video file. For simple video outputs you can use the OpenCV built-in @ref cv::VideoWriter
class, designed for this.
- How to create a video file with OpenCV
- What type of video files you can create with OpenCV
......@@ -58,11 +58,15 @@ container. No audio or other track editing support here. Nevertheless, any video
your system might work. If you encounter some of these limitations you will need to look into more
specialized video writing libraries such as *FFMpeg* or codecs as *HuffYUV*, *CorePNG* and *LCL*. As
an alternative, create the video track with OpenCV and expand it with sound tracks or convert it to
other formats by using video manipulation programs such as *VirtualDub* or *AviSynth*. The
*VideoWriter* class ======================= The content written here builds on the assumption you
already read the @ref videoInputPSNRMSSIM tutorial and you know how to read video files. To create a
other formats by using video manipulation programs such as *VirtualDub* or *AviSynth*.
The *VideoWriter* class
-----------------------
The content written here builds on the assumption you
already read the @ref tutorial_video_input_psnr_ssim tutorial and you know how to read video files. To create a
video file you just need to create an instance of the @ref cv::VideoWriter class. You can specify
its properties either via parameters in the constructor or later on via the @ref cv::open function.
its properties either via parameters in the constructor or later on via the @ref cv::VideoWriter::open function.
Either way, the parameters are the same: 1. The name of the output that contains the container type
in its extension. At the moment only *avi* is supported. We construct this from the input file, add
to this the name of the channel to use, and finish it off with the container extension.
......@@ -122,10 +126,10 @@ Size S = Size((int) inputVideo.get(CAP_PROP_FRAME_WIDTH), //Acquire input siz
(int) inputVideo.get(CAP_PROP_FRAME_HEIGHT));
outputVideo.open(NAME , ex, inputVideo.get(CAP_PROP_FPS),S, true);
@endcode
Afterwards, you use the @ref cv::isOpened() function to find out if the open operation succeeded or
Afterwards, you use the @ref cv::VideoWriter::isOpened() function to find out if the open operation succeeded or
not. The video file automatically closes when the *VideoWriter* object is destroyed. After you open
the object with success you can send the frames of the video in a sequential order by using the @ref
cv::write function of the class. Alternatively, you can use its overloaded operator \<\< :
the object with success you can send the frames of the video in a sequential order by using the
@ref cv::VideoWriter::write function of the class. Alternatively, you can use its overloaded operator \<\< :
@code{.cpp}
outputVideo.write(res); //or
outputVideo << res;
......
......@@ -15,7 +15,9 @@ Cool Theory
-----------
@note The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.
Morphological Operations --------------------------
Morphological Operations
------------------------
- In short: A set of operations that process images based on shapes. Morphological operations
apply a *structuring element* to an input image and generate an output image.
......@@ -59,102 +61,8 @@ Code
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp)
@code{.cpp}
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "highgui.h"
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
/// Global variables
Mat src, erosion_dst, dilation_dst;
int erosion_elem = 0;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;
/* Function Headers */
void Erosion( int, void* );
void Dilation( int, void* );
/* @function main */
int main( int argc, char** argv )
{
/// Load an image
src = imread( argv[1] );
if( !src.data )
{ return -1; }
/// Create windows
namedWindow( "Erosion Demo", WINDOW_AUTOSIZE );
namedWindow( "Dilation Demo", WINDOW_AUTOSIZE );
cvMoveWindow( "Dilation Demo", src.cols, 0 );
/// Create Erosion Trackbar
createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",
&erosion_elem, max_elem,
Erosion );
createTrackbar( "Kernel size:\n 2n +1", "Erosion Demo",
&erosion_size, max_kernel_size,
Erosion );
/// Create Dilation Trackbar
createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
&dilation_elem, max_elem,
Dilation );
createTrackbar( "Kernel size:\n 2n +1", "Dilation Demo",
&dilation_size, max_kernel_size,
Dilation );
/// Default start
Erosion( 0, 0 );
Dilation( 0, 0 );
waitKey(0);
return 0;
}
/* @function Erosion */
void Erosion( int, void* )
{
int erosion_type;
if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }
else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }
else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }
Mat element = getStructuringElement( erosion_type,
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
Point( erosion_size, erosion_size ) );
/// Apply the erosion operation
erode( src, erosion_dst, element );
imshow( "Erosion Demo", erosion_dst );
}
/* @function Dilation */
void Dilation( int, void* )
{
int dilation_type;
if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }
else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }
else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }
@includelineno samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp
Mat element = getStructuringElement( dilation_type,
Size( 2*dilation_size + 1, 2*dilation_size+1 ),
Point( dilation_size, dilation_size ) );
/// Apply the dilation operation
dilate( src, dilation_dst, element );
imshow( "Dilation Demo", dilation_dst );
}
@endcode
Explanation
-----------
......@@ -195,9 +103,8 @@ Explanation
- *src*: The source image
- *erosion_dst*: The output image
- *element*: This is the kernel we will use to perform the operation. If we do not
specify, the default is a simple @ref cv::3x3\` matrix. Otherwise, we can specify its
shape. For this, we need to use the function
get_structuring_element:\`getStructuringElement :
specify, the default is a simple `3x3` matrix. Otherwise, we can specify its
shape. For this, we need to use the function cv::getStructuringElement :
@code{.cpp}
Mat element = getStructuringElement( erosion_type,
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
......@@ -213,20 +120,19 @@ get_structuring_element:\`getStructuringElement :
specified, it is assumed to be in the center.
- That is all. We are ready to perform the erosion of our image.
@note Additionally, there is another parameter that allows you to perform multiple erosions
(iterations) at once. We are not using it in this simple tutorial, though. You can check out the
Reference for more details.
1. **dilation:**
3. **dilation:**
The code is below. As you can see, it is completely similar to the snippet of code for **erosion**.
Here we also have the option of defining our kernel, its anchor point and the size of the operator
to be used.
@code{.cpp}
/* @function Dilation */
void Dilation( int, void* )
{
The code is below. As you can see, it is completely similar to the snippet of code for **erosion**.
Here we also have the option of defining our kernel, its anchor point and the size of the operator
to be used.
@code{.cpp}
/* @function Dilation */
void Dilation( int, void* )
{
int dilation_type;
if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }
else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }
......@@ -238,19 +144,18 @@ void Dilation( int, void* )
/// Apply the dilation operation
dilate( src, dilation_dst, element );
imshow( "Dilation Demo", dilation_dst );
}
@endcode
}
@endcode
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.jpg)
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.
Compile the code above and execute it with an image as argument. For instance, using this image:
![image](images/Morphology_1_Tutorial_Cover.jpg)
![image](images/Morphology_1_Tutorial_Original_Image.jpg)
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_Result.jpg)
......@@ -271,6 +271,6 @@ Results
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.jpg
.. image:: images/Morphology_1_Result.jpg
:alt: Dilation and Erosion application
:align: center
......@@ -42,17 +42,17 @@ Theory
- What we want to do is to use our *model histogram* (that we know represents a skin tonality) to
detect skin areas in our Test Image. Here are the steps
a. In each pixel of our Test Image (i.e. \f$p(i,j)\f$ ), collect the data and find the
-# In each pixel of our Test Image (i.e. \f$p(i,j)\f$ ), collect the data and find the
correspondent bin location for that pixel (i.e. \f$( h_{i,j}, s_{i,j} )\f$ ).
b. Lookup the *model histogram* in the correspondent bin - \f$( h_{i,j}, s_{i,j} )\f$ - and read
-# Lookup the *model histogram* in the correspondent bin - \f$( h_{i,j}, s_{i,j} )\f$ - and read
the bin value.
c. Store this bin value in a new image (*BackProjection*). Also, you may consider to normalize
-# Store this bin value in a new image (*BackProjection*). Also, you may consider to normalize
the *model histogram* first, so the output for the Test Image can be visible for you.
d. Applying the steps above, we get the following BackProjection image for our Test Image:
-# Applying the steps above, we get the following BackProjection image for our Test Image:
![image](images/Back_Projection_Theory4.jpg)
e. In terms of statistics, the values stored in *BackProjection* represent the *probability*
-# In terms of statistics, the values stored in *BackProjection* represent the *probability*
that a pixel in *Test Image* belongs to a skin area, based on the *model histogram* that we
use. For instance in our Test image, the brighter areas are more probable to be skin area
(as they actually are), whereas the darker areas have less probability (notice that these
......@@ -72,13 +72,13 @@ Code
- Display the backprojection and the histogram in windows.
- **Downloadable code**:
a. Click
-# Click
[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp)
for the basic version (explained in this tutorial).
b. For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the
-# For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the
skin area) you can check the [improved
demo](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp)
c. ...or you can always check out the classical
-# ...or you can always check out the classical
[camshiftdemo](https://github.com/Itseez/opencv/tree/master/samples/cpp/camshiftdemo.cpp)
in samples.
......@@ -255,5 +255,3 @@ Results
------ ------ ------
|R0| |R1| |R2|
------ ------ ------
......@@ -10,7 +10,7 @@ In this tutorial you will learn how to:
- To calculate histograms of arrays of images by using the OpenCV function @ref cv::calcHist
- To normalize an array by using the function @ref cv::normalize
@note In the last tutorial (@ref histogram_equalization) we talked about a particular kind of
@note In the last tutorial (@ref tutorial_histogram_equalization) we talked about a particular kind of
histogram called *Image histogram*. Now we will considerate it in its more general concept. Read on!
### What are histograms?
......@@ -42,10 +42,10 @@ histogram called *Image histogram*. Now we will considerate it in its more gener
keep count not only of color intensities, but of whatever image features that we want to measure
(i.e. gradients, directions, etc).
- Let's identify some parts of the histogram:
a. **dims**: The number of parameters you want to collect data of. In our example, **dims = 1**
-# **dims**: The number of parameters you want to collect data of. In our example, **dims = 1**
because we are only counting the intensity values of each pixel (in a greyscale image).
b. **bins**: It is the number of **subdivisions** in each dim. In our example, **bins = 16**
c. **range**: The limits for the values to be measured. In this case: **range = [0,255]**
-# **bins**: It is the number of **subdivisions** in each dim. In our example, **bins = 16**
-# **range**: The limits for the values to be measured. In this case: **range = [0,255]**
- What if you want to count two features? In this case your resulting histogram would be a 3D plot
(in which x and y would be \f$bin_{x}\f$ and \f$bin_{y}\f$ for each feature and z would be the number of
counts for each combination of \f$(bin_{x}, bin_{y})\f$. The same would apply for more features (of
......@@ -68,82 +68,8 @@ Code
- **Downloadable code**: Click
[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp)
- **Code at glance:**
@code{.cpp}
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
/*
* @function main
*/
int main( int argc, char** argv )
{
Mat src, dst;
/// Load image
src = imread( argv[1], 1 );
if( !src.data )
{ return -1; }
/// Separate the image in 3 places ( B, G and R )
vector<Mat> bgr_planes;
split( src, bgr_planes );
/// Establish the number of bins
int histSize = 256;
/// Set the ranges ( for B,G,R) )
float range[] = { 0, 256 } ;
const float* histRange = { range };
bool uniform = true; bool accumulate = false;
Mat b_hist, g_hist, r_hist;
/// Compute the histograms:
calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
// Draw the histograms for B, G and R
int hist_w = 512; int hist_h = 400;
int bin_w = cvRound( (double) hist_w/histSize );
Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );
/// Normalize the result to [ 0, histImage.rows ]
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
/// Draw for each channel
for( int i = 1; i < histSize; i++ )
{
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
Scalar( 255, 0, 0), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
Scalar( 0, 255, 0), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
Scalar( 0, 0, 255), 2, 8, 0 );
}
/// Display
namedWindow("calcHist Demo", WINDOW_AUTOSIZE );
imshow("calcHist Demo", histImage );
@includelineno samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp
waitKey(0);
return 0;
}
@endcode
Explanation
-----------
......@@ -169,26 +95,26 @@ Explanation
4. Now we are ready to start configuring the **histograms** for each plane. Since we are working
with the B, G and R planes, we know that our values will range in the interval \f$[0,255]\f$
a. Establish number of bins (5, 10...):
-# Establish number of bins (5, 10...):
@code{.cpp}
int histSize = 256; //from 0 to 255
@endcode
b. Set the range of values (as we said, between 0 and 255 )
-# Set the range of values (as we said, between 0 and 255 )
@code{.cpp}
/// Set the ranges ( for B,G,R) )
float range[] = { 0, 256 } ; //the upper boundary is exclusive
const float* histRange = { range };
@endcode
c. We want our bins to have the same size (uniform) and to clear the histograms in the
-# We want our bins to have the same size (uniform) and to clear the histograms in the
beginning, so:
@code{.cpp}
bool uniform = true; bool accumulate = false;
@endcode
d. Finally, we create the Mat objects to save our histograms. Creating 3 (one for each plane):
-# Finally, we create the Mat objects to save our histograms. Creating 3 (one for each plane):
@code{.cpp}
Mat b_hist, g_hist, r_hist;
@endcode
e. We proceed to calculate the histograms by using the OpenCV function @ref cv::calcHist :
-# We proceed to calculate the histograms by using the OpenCV function @ref cv::calcHist :
@code{.cpp}
/// Compute the histograms:
calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
......@@ -254,18 +180,15 @@ Explanation
Scalar( 0, 0, 255), 2, 8, 0 );
}
@endcode
we use the expression:
@code{.cpp}
b_hist.at<float>(i)
@endcode
where \f$i\f$ indicates the dimension. If it were a 2D-histogram we would use something like:
@code{.cpp}
b_hist.at<float>( i, j )
@endcode
8. Finally we display our histograms and wait for the user to exit:
@code{.cpp}
namedWindow("calcHist Demo", WINDOW_AUTOSIZE );
......@@ -275,6 +198,7 @@ Explanation
return 0;
@endcode
Result
------
......@@ -285,5 +209,3 @@ Result
2. Produces the following histogram:
![image](images/Histogram_Calculation_Result.jpg)
......@@ -17,7 +17,7 @@ Theory
(\f$d(H_{1}, H_{2})\f$) to express how well both histograms match.
- OpenCV implements the function @ref cv::compareHist to perform a comparison. It also offers 4
different metrics to compute the matching:
a. **Correlation ( CV_COMP_CORREL )**
-# **Correlation ( CV_COMP_CORREL )**
\f[d(H_1,H_2) = \frac{\sum_I (H_1(I) - \bar{H_1}) (H_2(I) - \bar{H_2})}{\sqrt{\sum_I(H_1(I) - \bar{H_1})^2 \sum_I(H_2(I) - \bar{H_2})^2}}\f]
......@@ -27,15 +27,15 @@ Theory
and \f$N\f$ is the total number of histogram bins.
b. **Chi-Square ( CV_COMP_CHISQR )**
-# **Chi-Square ( CV_COMP_CHISQR )**
\f[d(H_1,H_2) = \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)}\f]
c. **Intersection ( method=CV_COMP_INTERSECT )**
-# **Intersection ( method=CV_COMP_INTERSECT )**
\f[d(H_1,H_2) = \sum _I \min (H_1(I), H_2(I))\f]
d. **Bhattacharyya distance ( CV_COMP_BHATTACHARYYA )**
-# **Bhattacharyya distance ( CV_COMP_BHATTACHARYYA )**
\f[d(H_1,H_2) = \sqrt{1 - \frac{1}{\sqrt{\bar{H_1} \bar{H_2} N^2}} \sum_I \sqrt{H_1(I) \cdot H_2(I)}}\f]
......@@ -165,4 +165,3 @@ match. As we can see, the match *base-base* is the highest of all as expected. A
that the match *base-half* is the second best match (as we predicted). For the other two metrics,
the less the result, the better the match. We can observe that the matches between the test 1 and
test 2 with respect to the base are worse, which again, was expected.
......@@ -7,7 +7,7 @@ Goal
In this tutorial you will learn:
- What an image histogram is and why it is useful
- To equalize histograms of images by using the OpenCV <function@ref> cv::equalizeHist
- To equalize histograms of images by using the OpenCV function @ref cv::equalizeHist
Theory
------
......@@ -59,54 +59,13 @@ Code
- **What does this program do?**
- Loads an image
- Convert the original image to grayscale
- Equalize the Histogram by using the OpenCV function @ref cv::EqualizeHist
- Equalize the Histogram by using the OpenCV function @ref cv::equalizeHist
- Display the source and equalized images in a window.
- **Downloadable code**: Click
[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp)
- **Code at glance:**
@code{.cpp}
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
/* @function main */
int main( int argc, char** argv )
{
Mat src, dst;
char* source_window = "Source image";
char* equalized_window = "Equalized Image";
/// Load image
src = imread( argv[1], 1 );
if( !src.data )
{ cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;
return -1;}
/// Convert to grayscale
cvtColor( src, src, COLOR_BGR2GRAY );
/// Apply Histogram Equalization
equalizeHist( src, dst );
/// Display results
namedWindow( source_window, WINDOW_AUTOSIZE );
namedWindow( equalized_window, WINDOW_AUTOSIZE );
imshow( source_window, src );
imshow( equalized_window, dst );
@includelineno samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp
/// Wait until user exits the program
waitKey(0);
return 0;
}
@endcode
Explanation
-----------
......@@ -149,6 +108,7 @@ Explanation
waitKey(0);
return 0;
@endcode
Results
-------
......@@ -173,8 +133,6 @@ Results
Notice how the number of pixels is more distributed through the intensity range.
**note**
@note
Are you wondering how did we draw the Histogram figures shown above? Check out the following
tutorial!
......@@ -23,8 +23,8 @@ template image (patch).
- We need two primary components:
a. **Source image (I):** The image in which we expect to find a match to the template image
b. **Template image (T):** The patch image which will be compared to the template image
-# **Source image (I):** The image in which we expect to find a match to the template image
-# **Template image (T):** The patch image which will be compared to the template image
our goal is to detect the highest matching area:
......@@ -300,5 +300,3 @@ Results
other possible high matches.
![image](images/Template_Matching_Image_Result.jpg)
......@@ -11,12 +11,12 @@ In this tutorial you will learn how to:
Theory
------
1. The *Canny Edge detector* was developed by John F. Canny in 1986. Also known to many as the
*optimal detector*, Canny algorithm aims to satisfy three main criteria:
- **Low error rate:** Meaning a good detection of only existent edges.
- **Good localization:** The distance between edge pixels detected and real edge pixels have
The *Canny Edge detector* was developed by John F. Canny in 1986. Also known to many as the
*optimal detector*, Canny algorithm aims to satisfy three main criteria:
- **Low error rate:** Meaning a good detection of only existent edges.
- **Good localization:** The distance between edge pixels detected and real edge pixels have
to be minimized.
- **Minimal response:** Only one detector response per edge.
- **Minimal response:** Only one detector response per edge.
### Steps
......@@ -32,8 +32,7 @@ Theory
\end{bmatrix}\f]
2. Find the intensity gradient of the image. For this, we follow a procedure analogous to Sobel:
a. Apply a pair of convolution masks (in \f$x\f$ and \f$y\f$ directions:
1. Apply a pair of convolution masks (in \f$x\f$ and \f$y\f$ directions:
\f[G_{x} = \begin{bmatrix}
-1 & 0 & +1 \\
-2 & 0 & +2 \\
......@@ -44,22 +43,20 @@ Theory
+1 & +2 & +1
\end{bmatrix}\f]
b. Find the gradient strength and direction with:
2. Find the gradient strength and direction with:
\f[\begin{array}{l}
G = \sqrt{ G_{x}^{2} + G_{y}^{2} } \\
\theta = \arctan(\dfrac{ G_{y} }{ G_{x} })
\end{array}\f]
The direction is rounded to one of four possible angles (namely 0, 45, 90 or 135)
3. *Non-maximum* suppression is applied. This removes pixels that are not considered to be part of
an edge. Hence, only thin lines (candidate edges) will remain.
4. *Hysteresis*: The final step. Canny does use two thresholds (upper and lower):
a. If a pixel gradient is higher than the *upper* threshold, the pixel is accepted as an edge
b. If a pixel gradient value is below the *lower* threshold, then it is rejected.
c. If the pixel gradient is between the two thresholds, then it will be accepted only if it is
1. If a pixel gradient is higher than the *upper* threshold, the pixel is accepted as an edge
2. If a pixel gradient value is below the *lower* threshold, then it is rejected.
3. If the pixel gradient is between the two thresholds, then it will be accepted only if it is
connected to a pixel that is above the *upper* threshold.
Canny recommended a *upper*:*lower* ratio between 2:1 and 3:1.
......@@ -78,76 +75,8 @@ Code
2. The tutorial code's is shown lines below. You can also download it from
[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp)
@code{.cpp}
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
/// Global variables
Mat src, src_gray;
Mat dst, detected_edges;
int edgeThresh = 1;
int lowThreshold;
int const max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
char* window_name = "Edge Map";
/*
* @function CannyThreshold
* @brief Trackbar callback - Canny thresholds input with a ratio 1:3
*/
void CannyThreshold(int, void*)
{
/// Reduce noise with a kernel 3x3
blur( src_gray, detected_edges, Size(3,3) );
/// Canny detector
Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );
/// Using Canny's output as a mask, we display our result
dst = Scalar::all(0);
src.copyTo( dst, detected_edges);
imshow( window_name, dst );
}
/* @function main */
int main( int argc, char** argv )
{
/// Load an image
src = imread( argv[1] );
@includelineno samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp
if( !src.data )
{ return -1; }
/// Create a matrix of the same type and size as src (for dst)
dst.create( src.size(), src.type() );
/// Convert the image to grayscale
cvtColor( src, src_gray, COLOR_BGR2GRAY );
/// Create a window
namedWindow( window_name, WINDOW_AUTOSIZE );
/// Create a Trackbar for user to enter threshold
createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold );
/// Show the image
CannyThreshold(0, 0);
/// Wait until user exit program by pressing a key
waitKey(0);
return 0;
}
@endcode
Explanation
-----------
......@@ -165,10 +94,10 @@ Explanation
@endcode
Note the following:
a. We establish a ratio of lower:upper threshold of 3:1 (with the variable *ratio*)
b. We set the kernel size of \f$3\f$ (for the Sobel operations to be performed internally by the
1. We establish a ratio of lower:upper threshold of 3:1 (with the variable *ratio*)
2. We set the kernel size of \f$3\f$ (for the Sobel operations to be performed internally by the
Canny function)
c. We set a maximum value for the lower Threshold of \f$100\f$.
3. We set a maximum value for the lower Threshold of \f$100\f$.
2. Loads the source image:
@code{.cpp}
......@@ -196,17 +125,17 @@ Explanation
@endcode
Observe the following:
a. The variable to be controlled by the Trackbar is *lowThreshold* with a limit of
1. The variable to be controlled by the Trackbar is *lowThreshold* with a limit of
*max_lowThreshold* (which we set to 100 previously)
b. Each time the Trackbar registers an action, the callback function *CannyThreshold* will be
2. Each time the Trackbar registers an action, the callback function *CannyThreshold* will be
invoked.
7. Let's check the *CannyThreshold* function, step by step:
a. First, we blur the image with a filter of kernel size 3:
1. First, we blur the image with a filter of kernel size 3:
@code{.cpp}
blur( src_gray, detected_edges, Size(3,3) );
@endcode
b. Second, we apply the OpenCV function @ref cv::Canny :
2. Second, we apply the OpenCV function @ref cv::Canny :
@code{.cpp}
Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );
@endcode
......@@ -224,12 +153,12 @@ Explanation
@code{.cpp}
dst = Scalar::all(0);
@endcode
9. Finally, we will use the function @ref cv::copyTo to map only the areas of the image that are
9. Finally, we will use the function @ref cv::Mat::copyTo to map only the areas of the image that are
identified as edges (on a black background).
@code{.cpp}
src.copyTo( dst, detected_edges);
@endcode
@ref cv::copyTo copy the *src* image onto *dst*. However, it will only copy the pixels in the
@ref cv::Mat::copyTo copy the *src* image onto *dst*. However, it will only copy the pixels in the
locations where they have non-zero values. Since the output of the Canny detector is the edge
contours on a black background, the resulting *dst* will be black in all the area but the
detected edges.
......@@ -251,4 +180,3 @@ Result
![image](images/Canny_Detector_Tutorial_Result.jpg)
- Notice how the image is superposed to the black background on the edge regions.
......@@ -24,8 +24,8 @@ Theory
3. In this tutorial, we will briefly explore two ways of defining the extra padding (border) for an
image:
a. **BORDER_CONSTANT**: Pad the image with a constant value (i.e. black or \f$0\f$
b. **BORDER_REPLICATE**: The row or column at the very edge of the original is replicated to
-# **BORDER_CONSTANT**: Pad the image with a constant value (i.e. black or \f$0\f$
-# **BORDER_REPLICATE**: The row or column at the very edge of the original is replicated to
the extra border.
This will be seen more clearly in the Code section.
......@@ -175,13 +175,13 @@ Explanation
@endcode
The arguments are:
a. *src*: Source image
b. *dst*: Destination image
c. *top*, *bottom*, *left*, *right*: Length in pixels of the borders at each side of the image.
-# *src*: Source image
-# *dst*: Destination image
-# *top*, *bottom*, *left*, *right*: Length in pixels of the borders at each side of the image.
We define them as being 5% of the original size of the image.
d. *borderType*: Define what type of border is applied. It can be constant or replicate for
-# *borderType*: Define what type of border is applied. It can be constant or replicate for
this example.
e. *value*: If *borderType* is *BORDER_CONSTANT*, this is the value used to fill the border
-# *value*: If *borderType* is *BORDER_CONSTANT*, this is the value used to fill the border
pixels.
8. We display our output image in the image created previously
......@@ -204,5 +204,3 @@ Results
option looks:
![image](images/CopyMakeBorder_Tutorial_Results.jpg)
......@@ -159,15 +159,15 @@ Explanation
@endcode
The arguments denote:
a. *src*: Source image
b. *dst*: Destination image
c. *ddepth*: The depth of *dst*. A negative value (such as \f$-1\f$) indicates that the depth is
-# *src*: Source image
-# *dst*: Destination image
-# *ddepth*: The depth of *dst*. A negative value (such as \f$-1\f$) indicates that the depth is
the same as the source.
d. *kernel*: The kernel to be scanned through the image
e. *anchor*: The position of the anchor relative to its kernel. The location *Point(-1, -1)*
-# *kernel*: The kernel to be scanned through the image
-# *anchor*: The position of the anchor relative to its kernel. The location *Point(-1, -1)*
indicates the center by default.
f. *delta*: A value to be added to each pixel during the convolution. By default it is \f$0\f$
g. *BORDER_DEFAULT*: We let this value by default (more details in the following tutorial)
-# *delta*: A value to be added to each pixel during the convolution. By default it is \f$0\f$
-# *BORDER_DEFAULT*: We let this value by default (more details in the following tutorial)
7. Our program will effectuate a *while* loop, each 500 ms the kernel size of our filter will be
updated in the range indicated.
......@@ -180,5 +180,3 @@ Results
the kernel size should change, as can be seen in the series of snapshots below:
![image](images/filter_2d_tutorial_result.jpg)
......@@ -20,8 +20,8 @@ straight lines. \#. To apply the Transform, first an edge detection pre-processi
1. As you know, a line in the image space can be expressed with two variables. For example:
a. In the **Cartesian coordinate system:** Parameters: \f$(m,b)\f$.
b. In the **Polar coordinate system:** Parameters: \f$(r,\theta)\f$
-# In the **Cartesian coordinate system:** Parameters: \f$(m,b)\f$.
-# In the **Polar coordinate system:** Parameters: \f$(r,\theta)\f$
![image](images/Hough_Lines_Tutorial_Theory_0.jpg)
......@@ -180,7 +180,7 @@ Explanation
available for this purpose:
3. **Standard Hough Line Transform**
a. First, you apply the Transform:
-# First, you apply the Transform:
@code{.cpp}
vector<Vec2f> lines;
HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );
......@@ -196,7 +196,7 @@ Explanation
- *threshold*: The minimum number of intersections to "*detect*" a line
- *srn* and *stn*: Default parameters to zero. Check OpenCV reference for more info.
b. And then you display the result by drawing the lines.
-# And then you display the result by drawing the lines.
@code{.cpp}
for( size_t i = 0; i < lines.size(); i++ )
{
......@@ -212,7 +212,7 @@ Explanation
}
@endcode
4. **Probabilistic Hough Line Transform**
a. First you apply the transform:
-# First you apply the transform:
@code{.cpp}
vector<Vec4i> lines;
HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 );
......@@ -231,7 +231,7 @@ Explanation
this number of points are disregarded.
- *maxLineGap*: The maximum gap between two points to be considered in the same line.
b. And then you display the result by drawing the lines.
-# And then you display the result by drawing the lines.
@code{.cpp}
for( size_t i = 0; i < lines.size(); i++ )
{
......@@ -267,4 +267,3 @@ We get the following result by using the Probabilistic Hough Line Transform:
You may observe that the number of lines detected vary while you change the *threshold*. The
explanation is sort of evident: If you establish a higher threshold, fewer lines will be detected
(since you will need more points to declare a line detected).
......@@ -206,16 +206,16 @@ Explanation
How do we update our mapping matrices *mat_x* and *mat_y*? Go on reading:
6. **Updating the mapping matrices:** We are going to perform 4 different mappings:
a. Reduce the picture to half its size and will display it in the middle:
-# Reduce the picture to half its size and will display it in the middle:
\f[h(i,j) = ( 2*i - src.cols/2 + 0.5, 2*j - src.rows/2 + 0.5)\f]
for all pairs \f$(i,j)\f$ such that: \f$\dfrac{src.cols}{4}<i<\dfrac{3 \cdot src.cols}{4}\f$ and
\f$\dfrac{src.rows}{4}<j<\dfrac{3 \cdot src.rows}{4}\f$
b. Turn the image upside down: \f$h( i, j ) = (i, src.rows - j)\f$
c. Reflect the image from left to right: \f$h(i,j) = ( src.cols - i, j )\f$
d. Combination of b and c: \f$h(i,j) = ( src.cols - i, src.rows - j )\f$
-# Turn the image upside down: \f$h( i, j ) = (i, src.rows - j)\f$
-# Reflect the image from left to right: \f$h(i,j) = ( src.cols - i, j )\f$
-# Combination of b and c: \f$h(i,j) = ( src.cols - i, src.rows - j )\f$
This is expressed in the following snippet. Here, *map_x* represents the first coordinate of
*h(i,j)* and *map_y* the second coordinate.
......@@ -277,4 +277,3 @@ Result
5. Reflecting it in both directions:
![image](images/Remap_Tutorial_Result_3.jpg)
......@@ -53,7 +53,7 @@ Theory
Assuming that the image to be operated is \f$I\f$:
1. We calculate two derivatives:
a. **Horizontal changes**: This is computed by convolving \f$I\f$ with a kernel \f$G_{x}\f$ with odd
1. **Horizontal changes**: This is computed by convolving \f$I\f$ with a kernel \f$G_{x}\f$ with odd
size. For example for a kernel size of 3, \f$G_{x}\f$ would be computed as:
\f[G_{x} = \begin{bmatrix}
......@@ -62,7 +62,7 @@ Assuming that the image to be operated is \f$I\f$:
-1 & 0 & +1
\end{bmatrix} * I\f]
b. **Vertical changes**: This is computed by convolving \f$I\f$ with a kernel \f$G_{y}\f$ with odd
2. **Vertical changes**: This is computed by convolving \f$I\f$ with a kernel \f$G_{y}\f$ with odd
size. For example for a kernel size of 3, \f$G_{y}\f$ would be computed as:
\f[G_{y} = \begin{bmatrix}
......@@ -81,11 +81,10 @@ Assuming that the image to be operated is \f$I\f$:
\f[G = |G_{x}| + |G_{y}|\f]
@note
When the size of the kernel is @ref cv::3\`, the Sobel kernel shown above may produce noticeable
When the size of the kernel is `3`, the Sobel kernel shown above may produce noticeable
inaccuracies (after all, Sobel is only an approximation of the derivative). OpenCV addresses
this inaccuracy for kernels of size 3 by using the :scharr:\`Scharr function. This is as fast
but more accurate than the standar Sobel function. It implements the following kernels:
\f[G_{x} = \begin{bmatrix}
-3 & 0 & +3 \\
-10 & 0 & +10 \\
......@@ -95,11 +94,11 @@ Assuming that the image to be operated is \f$I\f$:
0 & 0 & 0 \\
+3 & +10 & +3
\end{bmatrix}\f]
You can check out more information of this function in the OpenCV reference (@ref cv::Scharr ).
Also, in the sample code below, you will notice that above the code for @ref cv::Sobel function
there is also code for the @ref cv::Scharr function commented. Uncommenting it (and obviously
commenting the Sobel stuff) should give you an idea of how this function works.
@note
You can check out more information of this function in the OpenCV reference (@ref cv::Scharr ).
Also, in the sample code below, you will notice that above the code for @ref cv::Sobel function
there is also code for the @ref cv::Scharr function commented. Uncommenting it (and obviously
commenting the Sobel stuff) should give you an idea of how this function works.
Code
----
......@@ -110,65 +109,8 @@ Code
2. The tutorial code's is shown lines below. You can also download it from
[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp)
@code{.cpp}
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
@includelineno samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp
using namespace cv;
/* @function main */
int main( int argc, char** argv )
{
Mat src, src_gray;
Mat grad;
char* window_name = "Sobel Demo - Simple Edge Detector";
int scale = 1;
int delta = 0;
int ddepth = CV_16S;
int c;
/// Load an image
src = imread( argv[1] );
if( !src.data )
{ return -1; }
GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
/// Convert it to gray
cvtColor( src, src_gray, COLOR_RGB2GRAY );
/// Create window
namedWindow( window_name, WINDOW_AUTOSIZE );
/// Generate grad_x and grad_y
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
/// Gradient X
//Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT );
Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_x, abs_grad_x );
/// Gradient Y
//Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT );
Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_y, abs_grad_y );
/// Total Gradient (approximate)
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
imshow( window_name, grad );
waitKey(0);
return 0;
}
@endcode
Explanation
-----------
......@@ -239,5 +181,3 @@ Results
1. Here is the output of applying our basic detector to *lena.jpg*:
![image](images/Sobel_Derivatives_Tutorial_Result.jpg)
......@@ -18,9 +18,9 @@ Theory
transformation) followed by a *vector addition* (translation).
2. From the above, We can use an Affine Transformation to express:
a. Rotations (linear transformation)
b. Translations (vector addition)
c. Scale operations (linear transformation)
-# Rotations (linear transformation)
-# Translations (vector addition)
-# Scale operations (linear transformation)
you can see that, in essence, an Affine Transformation represents a **relation** between two
images.
......@@ -58,8 +58,8 @@ Theory
1. Excellent question. We mentioned that an Affine Transformation is basically a **relation**
between two images. The information about this relation can come, roughly, in two ways:
a. We know both \f$X\f$ and T and we also know that they are related. Then our job is to find \f$M\f$
b. We know \f$M\f$ and \f$X\f$. To obtain \f$T\f$ we only need to apply \f$T = M \cdot X\f$. Our information
-# We know both \f$X\f$ and T and we also know that they are related. Then our job is to find \f$M\f$
-# We know \f$M\f$ and \f$X\f$. To obtain \f$T\f$ we only need to apply \f$T = M \cdot X\f$. Our information
for \f$M\f$ may be explicit (i.e. have the 2-by-3 matrix) or it can come as a geometric relation
between points.
......@@ -219,9 +219,9 @@ Explanation
7. **Rotate:** To rotate an image, we need to know two things:
a. The center with respect to which the image will rotate
b. The angle to be rotated. In OpenCV a positive angle is counter-clockwise
c. *Optional:* A scale factor
-# The center with respect to which the image will rotate
-# The angle to be rotated. In OpenCV a positive angle is counter-clockwise
-# *Optional:* A scale factor
We define these parameters with the following snippet:
@code{.cpp}
......@@ -269,5 +269,3 @@ Result
factor, we get:
![image](images/Warp_Affine_Tutorial_Result_Warp_Rotate.jpg)
......@@ -12,8 +12,7 @@ In this tutorial you will learn how to:
Theory
------
@note The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler. ..
container:: enumeratevisibleitemswithsquare
@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:
......@@ -53,86 +52,30 @@ container:: enumeratevisibleitemswithsquare
predecessor. Iterating this process on the input image \f$G_{0}\f$ (original image) produces the
entire pyramid.
- The procedure above was useful to downsample an image. What if we want to make it bigger?:
- First, upsize the image to twice the original in each dimension, wit the new even rows and
columns filled with zeros (\f$0\f$)
- First, upsize the image to twice the original in each dimension, wit the new even rows and
- Perform a convolution with the same kernel shown above (multiplied by 4) to approximate the
values of the "missing pixels"
- These two procedures (downsampling and upsampling as explained above) are implemented by the
OpenCV functions @ref cv::pyrUp and @ref cv::pyrDown , as we will see in an example with the
code below:
@note When we reduce the size of an image, we are actually *losing* information of the image. Code
======
@note When we reduce the size of an image, we are actually *losing* information of the image.
Code
----
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp)
@code{.cpp}
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
/// Global variables
Mat src, dst, tmp;
char* window_name = "Pyramids Demo";
/*
* @function main
*/
int main( int argc, char** argv )
{
/// General instructions
printf( "\n Zoom In-Out demo \n " );
printf( "------------------ \n" );
printf( " * [u] -> Zoom in \n" );
printf( " * [d] -> Zoom out \n" );
printf( " * [ESC] -> Close program \n \n" );
/// Test image - Make sure it s divisible by 2^{n}
src = imread( "../images/chicky_512.jpg" );
if( !src.data )
{ printf(" No data! -- Exiting the program \n");
return -1; }
@includelineno samples/cpp/tutorial_code/ImgProc/Pyramids.cpp
tmp = src;
dst = tmp;
/// Create window
namedWindow( window_name, WINDOW_AUTOSIZE );
imshow( window_name, dst );
/// Loop
while( true )
{
int c;
c = waitKey(10);
if( (char)c == 27 )
{ break; }
if( (char)c == 'u' )
{ pyrUp( tmp, dst, Size( tmp.cols*2, tmp.rows*2 ) );
printf( "** Zoom In: Image x 2 \n" );
}
else if( (char)c == 'd' )
{ pyrDown( tmp, dst, Size( tmp.cols/2, tmp.rows/2 ) );
printf( "** Zoom Out: Image / 2 \n" );
}
imshow( window_name, dst );
tmp = dst;
}
return 0;
}
@endcode
Explanation
-----------
1. Let's check the general structure of the program:
- Load an image (in this case it is defined in the program, the user does not have to enter it
Let's check the general structure of the program:
- Load an image (in this case it is defined in the program, the user does not have to enter it
as an argument)
@code{.cpp}
/// Test image - Make sure it s divisible by 2^{n}
......@@ -141,7 +84,8 @@ Explanation
{ printf(" No data! -- Exiting the program \n");
return -1; }
@endcode
- Create a Mat object to store the result of the operations (*dst*) and one to save temporal
- Create a Mat object to store the result of the operations (*dst*) and one to save temporal
results (*tmp*).
@code{.cpp}
Mat src, dst, tmp;
......@@ -149,12 +93,14 @@ Explanation
tmp = src;
dst = tmp;
@endcode
- Create a window to display the result
- Create a window to display the result
@code{.cpp}
namedWindow( window_name, WINDOW_AUTOSIZE );
imshow( window_name, dst );
@endcode
- Perform an infinite loop waiting for user input.
- Perform an infinite loop waiting for user input.
@code{.cpp}
while( true )
{
......@@ -208,6 +154,7 @@ Explanation
@code{.cpp}
tmp = dst;
@endcode
Results
-------
......@@ -226,5 +173,3 @@ Results
is now:
![image](images/Pyramids_Tutorial_PyrUp_Result.jpg)
......@@ -16,67 +16,8 @@ Code
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp)
@code{.cpp}
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
/// Function header
void thresh_callback(int, void* );
@endcode
/\* @function main */ int main( int argc, char*\* argv )
{
/// Load source image and convert it to gray src = imread( argv[1], 1 );
/// Convert image to gray and blur it cvtColor( src, src_gray, COLOR_BGR2GRAY ); blur(
src_gray, src_gray, Size(3,3) );
/// Create Window char\* source_window = "Source"; namedWindow( source_window,
WINDOW_AUTOSIZE ); imshow( source_window, src );
createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );
thresh_callback( 0, 0 );
waitKey(0); return(0);
}
/\* @function thresh_callback */ void thresh_callback(int, void* ) { Mat src_copy =
src.clone(); Mat threshold_output; vector\<vector\<Point\> \> contours; vector\<Vec4i\>
hierarchy;
/// Detect edges using Threshold threshold( src_gray, threshold_output, thresh, 255,
THRESH_BINARY );
/// Find contours findContours( threshold_output, contours, hierarchy, RETR_TREE,
CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Find the convex hull object for each contour vector\<vector\<Point\> \>hull(
contours.size() ); for( int i = 0; i \< contours.size(); i++ ) { convexHull(
Mat(contours[i]), hull[i], false ); }
/// Draw contours + hull results Mat drawing = Mat::zeros( threshold_output.size(),
CV_8UC3 ); for( int i = 0; i\< contours.size(); i++ ) { Scalar color = Scalar(
rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) ); drawContours( drawing,
contours, i, color, 1, 8, vector\<Vec4i\>(), 0, Point() ); drawContours( drawing, hull, i,
color, 1, 8, vector\<Vec4i\>(), 0, Point() ); }
/// Show in a window namedWindow( "Hull demo", WINDOW_AUTOSIZE ); imshow( "Hull demo",
drawing );
}
@includelineno samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp
Explanation
-----------
......@@ -84,10 +25,7 @@ Explanation
Result
------
1. Here it is:
----------- -----------
|Hull_0| |Hull_1|
----------- -----------
Here it is:
![Original](images/Hull_Original_Image.jpg)
![Result](images/Hull_Result.jpg)
......@@ -13,7 +13,7 @@ This tutorial assumes you have the following software installed and configured:
- Eclipse IDE
- ADT and CDT plugins for Eclipse
If you need help with anything of the above, you may refer to our @ref android_dev_intro guide.
If you need help with anything of the above, you may refer to our @ref tutorial_android_dev_intro guide.
If you encounter any error after thoroughly following these steps, feel free to contact us via
[OpenCV4Android](https://groups.google.com/group/android-opencv/) discussion group or OpenCV [Q&A
......@@ -27,9 +27,9 @@ Pack](http://developer.nvidia.com/tegra-android-development-pack) (**TADP**) rel
for Android development environment setup.
Beside Android development tools the TADP 2.0 includes OpenCV4Android SDK, so it can be already
installed in your system and you can skip to @ref Running_OpenCV_Samples section of this tutorial.
installed in your system and you can skip to @ref tutorial_O4A_SDK_samples "samples" section of this tutorial.
More details regarding TADP can be found in the @ref android_dev_intro guide.
More details regarding TADP can be found in the @ref tutorial_android_dev_intro guide.
General info
------------
......@@ -71,20 +71,21 @@ The structure of package contents looks as follows:
On production devices that have access to Google Play Market (and Internet) these packages will
be installed from Market on the first start of an application using OpenCV Manager API. But
devkits without Market or Internet connection require this packages to be installed manually.
Install the Manager.apk and optional binary_pack.apk if it needed. See @ref manager_selection
Install the Manager.apk and optional binary_pack.apk if it needed. See `Manager Selection`
for details.
@note Installation from Internet is the preferable way since OpenCV team may publish updated
versions of this packages on the Market. \* `samples` folder contains sample applications projects
and their prebuilt packages (APK). Import them into Eclipse workspace (like described below) and
browse the code to learn possible ways of OpenCV use on Android.
@note Installation from Internet is the preferable way since OpenCV team may publish updated
versions of this packages on the Market.
- `samples` folder contains sample applications projects
and their prebuilt packages (APK). Import them into Eclipse workspace (like described below) and
browse the code to learn possible ways of OpenCV use on Android.
- `doc` folder contains various OpenCV documentation in PDF format. It's also available online at
<http://docs.opencv.org>.
@note The most recent docs (nightly build) are at <http://docs.opencv.org/2.4>. Generally, it's more
up-to-date, but can refer to not-yet-released functionality. .. TODO: I'm not sure that this is the
best place to talk about OpenCV Manager
@note The most recent docs (nightly build) are at <http://docs.opencv.org/2.4>. Generally, it's more
up-to-date, but can refer to not-yet-released functionality.
@todo I'm not sure that this is the best place to talk about OpenCV Manager
Starting from version 2.4.3 OpenCV4Android SDK uses OpenCV Manager API for library initialization.
OpenCV Manager is an Android service based solution providing the following benefits for OpenCV
......@@ -98,8 +99,8 @@ applications developers:
For additional information on OpenCV Manager see the:
- Slides_
- Reference Manual_
- [Slides](https://docs.google.com/a/itseez.com/presentation/d/1EO_1kijgBg_BsjNp2ymk-aarg-0K279_1VZRcPplSuk/present#slide=id.p)
- [Reference Manual](http://docs.opencv.org/android/refman.html)
Manual OpenCV4Android SDK setup
-------------------------------
......@@ -108,21 +109,23 @@ Manual OpenCV4Android SDK setup
1. Go to the [OpenCV download page on
SourceForge](http://sourceforge.net/projects/opencvlibrary/files/opencv-android/) and download
the latest available version. Currently it's `OpenCV-2.4.9-android-sdk.zip`_.
the latest available version. Currently it's [OpenCV-2.4.9-android-sdk.zip](http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.4.9/OpenCV-2.4.9-android-sdk.zip/download).
2. Create a new folder for Android with OpenCV development. For this tutorial we have unpacked
OpenCV SDK to the `C:\\Work\\OpenCV4Android\\` directory.
OpenCV SDK to the `C:\Work\OpenCV4Android\` directory.
@note Better to use a path without spaces in it. Otherwise you may have problems with ndk-build.
@note Better to use a path without spaces in it. Otherwise you may have problems with ndk-build. \#.
Unpack the SDK archive into the chosen directory.
3. Unpack the SDK archive into the chosen directory.
You can unpack it using any popular archiver (e.g with 7-Zip_):
You can unpack it using any popular archiver (e.g with 7-Zip_):
![image](images/android_package_7zip.png)
![image](images/android_package_7zip.png)
On Unix you can use the following command:
@code{.bash}
unzip ~/Downloads/OpenCV-2.4.9-android-sdk.zip
@endcode
On Unix you can use the following command:
@code{.bash}
unzip ~/Downloads/OpenCV-2.4.9-android-sdk.zip
@endcode
### Import OpenCV library and samples to the Eclipse
1. Start Eclipse and choose your workspace location.
......@@ -143,7 +146,7 @@ unzip ~/Downloads/OpenCV-2.4.9-android-sdk.zip
already references OpenCV library. Follow the steps below to import OpenCV and samples into the
workspace:
@note OpenCV samples are indeed **dependent** on OpenCV library project so don't forget to import it to your workspace as well.
@note OpenCV samples are indeed **dependent** on OpenCV library project so don't forget to import it to your workspace as well.
- Right click on the Package Explorer window and choose Import... option from the context
menu:
......@@ -171,12 +174,13 @@ unzip ~/Downloads/OpenCV-2.4.9-android-sdk.zip
![image](images/eclipse_10_crystal_clean.png)
@anchor tutorial_O4A_SDK_samples
### Running OpenCV Samples
At this point you should be able to build and run the samples. Keep in mind, that face-detection and
Tutorial 2 - Mixed Processing include some native code and require Android NDK and NDK/CDT plugin
for Eclipse to build working applications. If you haven't installed these tools, see the
corresponding section of @ref Android_Dev_Intro.
corresponding section of @ref tutorial_android_dev_intro.
**warning**
......@@ -185,21 +189,23 @@ Please consider that some samples use Android Java Camera API, which is accessib
emulator.
@note Recent *Android SDK tools, revision 19+* can run ARM v7a OS images but they available not for
all Android versions. Well, running samples from Eclipse is very simple:
all Android versions.
Well, running samples from Eclipse is very simple:
- Connect your device with adb tool from Android SDK or create an emulator with camera support.
- See [Managing Virtual
Devices](http://developer.android.com/guide/developing/devices/index.html) document for help
- See [Managing Virtual Devices](http://developer.android.com/guide/developing/devices/index.html) document for help
with Android Emulator.
- See [Using Hardware Devices](http://developer.android.com/guide/developing/device.html) for
help with real devices (not emulators).
- Select project you want to start in Package Explorer and just press Ctrl + F11 or select option
Run --\> Run from the main menu, or click Run button on the toolbar.
@note Android Emulator can take several minutes to start. So, please, be patient. \* On the first
run Eclipse will ask you about the running mode for your application:
@note Android Emulator can take several minutes to start. So, please, be patient. \* On the first
run Eclipse will ask you about the running mode for your application:
![image](images/eclipse_11_run_as.png)
![image](images/eclipse_11_run_as.png)
- Select the Android Application option and click OK button. Eclipse will install and run the
sample.
......@@ -215,18 +221,17 @@ run Eclipse will ask you about the running mode for your application:
device/emulator. It will redirect you to the corresponding page on *Google Play Market*.
If you have no access to the *Market*, which is often the case with emulators - you will need to
install the packages from OpenCV4Android SDK folder manually. See @ref manager_selection for
install the packages from OpenCV4Android SDK folder manually. See `Manager Selection` for
details.
@code{.sh}
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.9_Manager_2.18_armv7a-neon.apk
@endcode
@note armeabi, armv7a-neon, arm7a-neon-android8, mips and x86 stand for platform targets:
@note armeabi, armv7a-neon, arm7a-neon-android8, mips and x86 stand for platform targets:
- armeabi is for ARM v5 and ARM v6 architectures with Android API 8+,
- armv7a-neon is for NEON-optimized ARM v7 with Android API 9+,
- arm7a-neon-android8 is for NEON-optimized ARM v7 with Android API 8,
- mips is for MIPS architecture with Android API 9+,
- x86 is for Intel x86 CPUs with Android API 9+.
If using hardware device for testing/debugging, run the following command to learn its CPU
architecture:
@code{.sh}
......@@ -236,9 +241,9 @@ run Eclipse will ask you about the running mode for your application:
Click Edit in the context menu of the selected device. In the window, which then pop-ups, find
the CPU field.
You may also see section @ref manager_selection for details.
You may also see section `Manager Selection` for details.
When done, you will be able to run OpenCV samples on your device/emulator seamlessly.
When done, you will be able to run OpenCV samples on your device/emulator seamlessly.
- Here is Sample - image-manipulations sample, running on top of stock camera-preview of the
emulator.
......@@ -249,6 +254,4 @@ What's next
-----------
Now, when you have your instance of OpenCV4Adroid SDK set up and configured, you may want to proceed
to using OpenCV in your own application. You can learn how to do that in a separate @ref
dev_with_OCV_on_Android tutorial.
to using OpenCV in your own application. You can learn how to do that in a separate @ref tutorial_dev_with_OCV_on_Android tutorial.
......@@ -247,6 +247,7 @@ APP_ABI := all
@note We recommend setting APP_ABI := all for all targets. If you want to specify the target
explicitly, use armeabi for ARMv5/ARMv6, armeabi-v7a for ARMv7, x86 for Intel Atom or mips for MIPS.
@anchor tutorial_android_dev_intro_ndk
Building application native part from command line
--------------------------------------------------
......@@ -284,6 +285,8 @@ build tool).
@code{.bash}
<path_where_NDK_is_placed>/ndk-build -B
@endcode
@anchor tutorial_android_dev_intro_eclipse
Building application native part from *Eclipse* (CDT Builder)
-------------------------------------------------------------
......@@ -331,9 +334,9 @@ to apply the changes.
4. Open Project Properties -\> C/C++ Build, uncheck Use default build command, replace "Build
command" text from "make" to
"\\f${NDKROOT}/ndk-build.cmd" on Windows,
"${NDKROOT}/ndk-build.cmd" on Windows,
"\\f${NDKROOT}/ndk-build" on Linux and MacOS.
"${NDKROOT}/ndk-build" on Linux and MacOS.
![image](images/eclipse_cdt_cfg4.png)
......@@ -514,5 +517,4 @@ What's next
-----------
Now, when you have your development environment set up and configured, you may want to proceed to
installing OpenCV4Android SDK. You can learn how to do that in a separate @ref O4A_SDK tutorial.
installing OpenCV4Android SDK. You can learn how to do that in a separate @ref tutorial_O4A_SDK tutorial.
......@@ -13,11 +13,11 @@ This tutorial assumes you have the following installed and configured:
- Eclipse IDE
- ADT and CDT plugins for Eclipse
If you need help with anything of the above, you may refer to our @ref android_dev_intro guide.
If you need help with anything of the above, you may refer to our @ref tutorial_android_dev_intro guide.
This tutorial also assumes you have OpenCV4Android SDK already installed on your development machine
and OpenCV Manager on your testing device correspondingly. If you need help with any of these, you
may consult our @ref O4A_SDK tutorial.
may consult our @ref tutorial_O4A_SDK tutorial.
If you encounter any error after thoroughly following these steps, feel free to contact us via
[OpenCV4Android](https://groups.google.com/group/android-opencv/) discussion group or OpenCV [Q&A
......@@ -28,7 +28,7 @@ Using OpenCV Library Within Your Android Project
In this section we will explain how to make some existing project to use OpenCV. Starting with 2.4.2
release for Android, *OpenCV Manager* is used to provide apps with the best available version of
OpenCV. You can get more information here: @ref Android_OpenCV_Manager and in these
OpenCV. You can get more information here: `Android OpenCV Manager` and in these
[slides](https://docs.google.com/a/itseez.com/presentation/d/1EO_1kijgBg_BsjNp2ymk-aarg-0K279_1VZRcPplSuk/present#slide=id.p).
### Java
......@@ -52,7 +52,7 @@ Manager to access OpenCV libraries externally installed in the target system.
In most cases OpenCV Manager may be installed automatically from Google Play. For the case, when
Google Play is not available, i.e. emulator, developer board, etc, you can install it manually using
adb tool. See @ref manager_selection for details.
adb tool. See `Manager Selection` for details.
There is a very base code snippet implementing the async initialization. It shows basic principles.
See the "15-puzzle" OpenCV sample for details.
......@@ -118,7 +118,7 @@ described above.
In case of the application project **with a JNI part**, instead of manual libraries copying you
need to modify your Android.mk file: add the following two code lines after the
"include \\f$(CLEAR_VARS)" and before
"include $(CLEAR_VARS)" and before
"include path_to_OpenCV-2.4.9-android-sdk/sdk/native/jni/OpenCV.mk"
@code{.make}
OPENCV_CAMERA_MODULES:=on
......@@ -160,6 +160,7 @@ described above.
}
}
@endcode
### Native/C++
To build your own Android application, using OpenCV as native part, the following steps should be
......@@ -184,11 +185,12 @@ taken:
4. Several variables can be used to customize OpenCV stuff, but you **don't need** to use them when
your application uses the async initialization via the OpenCV Manager API.
@note These variables should be set **before** the "include .../OpenCV.mk" line:
@note These variables should be set **before** the "include .../OpenCV.mk" line:
@code{.make}
OPENCV_INSTALL_MODULES:=on
@endcode
Copies necessary OpenCV dynamic libs to the project libs folder in order to include them
Copies necessary OpenCV dynamic libs to the project libs folder in order to include them
into the APK.
@code{.make}
OPENCV_CAMERA_MODULES:=off
......@@ -200,7 +202,7 @@ Copies necessary OpenCV dynamic libs to the project libs folder in order to incl
Perform static linking with OpenCV. By default dynamic link is used and the project JNI lib
depends on libopencv_java.so.
1. The file `Application.mk` should exist and should contain lines:
5. The file `Application.mk` should exist and should contain lines:
@code{.make}
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
......@@ -218,8 +220,10 @@ Copies necessary OpenCV dynamic libs to the project libs folder in order to incl
@code{.make}
APP_PLATFORM := android-9
@endcode
2. Either use @ref manual \<NDK_build_cli\> ndk-build invocation or @ref setup Eclipse CDT
Builder \<CDT_Builder\> to build native JNI lib before (re)building the Java part and creating
6. Either use @ref tutorial_android_dev_intro_ndk "manual" ndk-build invocation or
@ref tutorial_android_dev_intro_eclipse "setup Eclipse CDT Builder" to build native JNI lib
before (re)building the Java part and creating
an APK.
Hello OpenCV Sample
......@@ -365,7 +369,8 @@ function and it is called on retrieving frame from camera. The callback input is
CvCameraViewFrame class that represents frame from camera.
@note Do not save or use CvCameraViewFrame object out of onCameraFrame callback. This object does
not have its own state and its behavior out of callback is unpredictable! It has rgba() and gray()
not have its own state and its behavior out of callback is unpredictable!
It has rgba() and gray()
methods that allows to get frame as RGBA and one channel gray scale Mat respectively. It expects
that onCameraFrame function returns RGBA frame that will be drawn on the screen.
......@@ -61,7 +61,7 @@ The available [installation guide](https://github.com/technomancy/leiningen#inst
easy to be followed:
1. [Download the script](https://raw.github.com/technomancy/leiningen/stable/bin/lein)
2. Place it on your \\f$PATH (cf. \~/bin is a good choice if it is on your path.)
2. Place it on your $PATH (cf. \~/bin is a good choice if it is on your path.)
3. Set the script to be executable. (i.e. chmod 755 \~/bin/lein).
If you work on Windows, follow [this instruction](https://github.com/technomancy/leiningen#windows)
......
......@@ -6,8 +6,8 @@ Android development. This guide will help you to create your first Java (or Scal
OpenCV. We will use either [Apache Ant](http://ant.apache.org/) or [Simple Build Tool
(SBT)](http://www.scala-sbt.org/) to build the application.
If you want to use Eclipse head to @ref Java_Eclipse. For further reading after this guide, look at
the @ref Android_Dev_Intro tutorials.
If you want to use Eclipse head to @ref tutorial_java_eclipse. For further reading after this guide, look at
the @ref tutorial_android_dev_intro tutorials.
What we'll do in this guide
---------------------------
......@@ -58,19 +58,23 @@ or
@code{.bat}
cmake -DBUILD_SHARED_LIBS=OFF -G "Visual Studio 10" ..
@endcode
@note When OpenCV is built as a set of **static** libraries (-DBUILD_SHARED_LIBS=OFF option) the
Java bindings dynamic library is all-sufficient, i.e. doesn't depend on other OpenCV libs, but
includes all the OpenCV code inside. Examine the output of CMake and ensure java is one of the
includes all the OpenCV code inside.
Examine the output of CMake and ensure java is one of the
modules "To be built". If not, it's likely you're missing a dependency. You should troubleshoot by
looking through the CMake output for any Java-related tools that aren't found and installing them.
![image](images/cmake_output.png)
@note If CMake can't find Java in your system set the JAVA_HOME environment variable with the path to installed JDK before running it. E.g.:
@code{.bash}
export JAVA_HOME=/usr/lib/jvm/java-6-oracle
cmake -DBUILD_SHARED_LIBS=OFF ..
@endcode
@code{.bash}
export JAVA_HOME=/usr/lib/jvm/java-6-oracle
cmake -DBUILD_SHARED_LIBS=OFF ..
@endcode
Now start the build:
@code{.bash}
make -j8
......@@ -87,71 +91,22 @@ Java sample with Ant
--------------------
@note The described sample is provided with OpenCV library in the `opencv/samples/java/ant`
folder. \* Create a folder where you'll develop this sample application.
- In this folder create the `build.xml` file with the following content using any text editor:
@code{.xml}
<project name="SimpleSample" basedir="." default="rebuild-run">
<property name="src.dir" value="src"/>
<property name="lib.dir" value="\f${ocvJarDir}"/>
<path id="classpath">
<fileset dir="\f${lib.dir}" includes="**/*.jar"/>
</path>
folder.
<property name="build.dir" value="build"/>
<property name="classes.dir" value="\f${build.dir}/classes"/>
<property name="jar.dir" value="\f${build.dir}/jar"/>
- Create a folder where you'll develop this sample application.
<property name="main-class" value="\f${ant.project.name}"/>
<target name="clean">
<delete dir="\f${build.dir}"/>
</target>
<target name="compile">
<mkdir dir="\f${classes.dir}"/>
<javac includeantruntime="false" srcdir="\f${src.dir}" destdir="\f${classes.dir}" classpathref="classpath"/>
</target>
<target name="jar" depends="compile">
<mkdir dir="\f${jar.dir}"/>
<jar destfile="\f${jar.dir}/\f${ant.project.name}.jar" basedir="\f${classes.dir}">
<manifest>
<attribute name="Main-Class" value="\f${main-class}"/>
</manifest>
</jar>
</target>
<target name="run" depends="jar">
<java fork="true" classname="\f${main-class}">
<sysproperty key="java.library.path" path="\f${ocvLibDir}"/>
<classpath>
<path refid="classpath"/>
<path location="\f${jar.dir}/\f${ant.project.name}.jar"/>
</classpath>
</java>
</target>
<target name="rebuild" depends="clean,jar"/>
<target name="rebuild-run" depends="clean,run"/>
</project>
@endcode
@note This XML file can be reused for building other Java applications. It describes a common folder structure in the lines 3 - 12 and common targets for compiling and running the application.
- In this folder create the `build.xml` file with the following content using any text editor:
@include samples/java/ant/build.xml
@note This XML file can be reused for building other Java applications. It describes a common folder structure in the lines 3 - 12 and common targets for compiling and running the application.
When reusing this XML don't forget to modify the project name in the line 1, that is also the
name of the main class (line 14). The paths to OpenCV jar and jni lib are expected as parameters
("\\f${ocvJarDir}" in line 5 and "\\f${ocvLibDir}" in line 37), but you can hardcode these paths for
("${ocvJarDir}" in line 5 and "${ocvLibDir}" in line 37), but you can hardcode these paths for
your convenience. See [Ant documentation](http://ant.apache.org/manual/) for detailed
description of its build file format.
- Create an `src` folder next to the `build.xml` file and a `SimpleSample.java` file in it.
-
Put the following Java code into the `SimpleSample.java` file:
- Put the following Java code into the `SimpleSample.java` file:
@code{.java}
import org.opencv.core.Core;
import org.opencv.core.Mat;
......@@ -175,9 +130,7 @@ folder. \* Create a folder where you'll develop this sample application.
}
@endcode
-
Run the following command in console in the folder containing `build.xml`:
- Run the following command in console in the folder containing `build.xml`:
@code{.bash}
ant -DocvJarDir=path/to/dir/containing/opencv-244.jar -DocvLibDir=path/to/dir/containing/opencv_java244/native/library
@endcode
......@@ -370,4 +323,3 @@ It should also write the following image to `faceDetection.png`:
You're done! Now you have a sample Java application working with OpenCV, so you can start the work
on your own. We wish you good luck and many years of joyful life!
How to write a tutorial for OpenCV {#tutorial_how_to_write_a_tutorial}
==================================
Okay, so assume you have just finished a project of yours implementing something based on OpenCV and
you want to present/share it with the community. Luckily, OpenCV is an *open source project*. This
means that anyone has access to the full source code and may propose extensions. And a good tutorial
is a valuable addition to the library! Please read instructions on contribution process here:
<http://opencv.org/contribute.html>. You may also find this page helpful: @ref cv::How to contribute
.
While making a robust and practical library (like OpenCV) is great, the success of a library also
depends on how user friendly it is. To improve on this aspect, the OpenCV team has already been
listening to user feedback at :opencv_qa:OpenCV Q&A
forum \<\> and by making samples you can find in the source directories `samples` folder. The
addition of the tutorials (in both online and PDF format) is an extension of these efforts.
Goal
----
The tutorials are just as an important part of the library as the implementation of those crafty
data structures and algorithms you can find in OpenCV. Therefore, the source codes for the tutorials
are part of the library. And yes, I meant source codes. The reason for this formulation is that the
tutorials are written by using the Sphinx_ documentation generation system. This is based on the
popular Python documentation system called reStructuredText_ (reST). ReStructuredText is a really
neat language that by using a few simple conventions (indentation, directives) and emulating old
school email writing techniques (text only) tries to offer a simple way to create and edit
documents. Sphinx extends this with some new features and creates the resulting document in both
HTML (for web) and PDF (for offline usage) format.
Usually, an OpenCV tutorial has the following parts:
1. A source code demonstration of an OpenCV feature:
a. One or more CPP, Python, Java or other type of files depending for what OpenCV offers
support and for what language you make the tutorial.
b. Occasionaly, input resource files required for running your tutorials application.
2. A table of content entry (so people may easily find the tutorial):
a. Adding your stuff to the tutorials table of content (**reST** file).
b. Add an image file near the TOC entry.
3. The content of the tutorial itself:
a. The **reST** text of the tutorial
b. Images following the idea that "*A picture is worth a thousand words*".
c. For more complex demonstrations you may create a video.
As you can see you will need at least some basic knowledge of the *reST* system in order to complete
the task at hand with success. However, don't worry *reST* (and *Sphinx*) was made with simplicity
in mind. It is easy to grasp its basics. I found that the [OpenAlea documentations introduction on
this
subject](http://openalea.gforge.inria.fr/doc/openalea/doc/_build/html/source/tutorial/rest_syntax.html)
(or the [Thomas Cokelaer one](http://thomas-cokelaer.info/tutorials/sphinx/rest_syntax.html) )
should enough for this. If for some directive or feature you need a more in-depth description look
it up in the official reStructuredText_ help files or at the Sphinx_ documentation.
In our world achieving some tasks is possible in multiple ways. However, some of the roads to take
may have obvious or hidden advantages over others. Then again, in some other cases it may come down
to just simple user preference. Here, I'll present how I decided to write the tutorials, based on my
personal experience. If for some of them you know a better solution and you can back it up feel free
to use that. I've nothing against it, as long as it gets the job done in an elegant fashion.
Now the best would be if you could make the integration yourself. For this you need first to have
the source code. I recommend following the guides for your operating system on acquiring OpenCV
sources. For Linux users look @ref here \<Linux-Installation\> and for @ref Windows here
\<Windows_Installation\>. You must also install python and sphinx with its dependencies in order to
be able to build the documentation.
Once you have downloaded the repository to your hard drive you can take a look in the OpenCV
directory to make sure you have both the samples and doc folder present. Anyone may download the
latest source files from `git://github.com/Itseez/opencv.git` . Nevertheless, not everyone has
upload (commit/submit) rights. This is to protect the integrity of the library. If you plan doing
more than one tutorial, and would like to have an account with commit user rights you should first
register an account at <http://code.opencv.org/> and then contact OpenCV administrator
<-delete-admin@-delete-opencv.org>. Otherwise, you can just send the resulting files to us at
<-delete-admin@-delete-opencv.org> and we'll add it.
Format the Source Code
----------------------
Before I start this let it be clear: the main goal is to have a working sample code. However, for
your tutorial to be of a top notch quality you should follow a few guide lines I am going to present
here. In case you have an application by using the older interface (with *IplImage*, *cvMat*,
*cvLoadImage* and such) consider migrating it to the new C++ interface. The tutorials are intended
to be an up to date help for our users. And as of OpenCV 2 the OpenCV emphasis on using the less
error prone and clearer C++ interface. Therefore, if possible please convert your code to the C++
interface. For this it may help to read the @ref InteroperabilityWithOpenCV1 tutorial. However, once
you have an OpenCV 2 working code, then you should make your source code snippet as easy to read as
possible. Here're a couple of advices for this:
- Add a standard output with the description of what your program does. Keep it short and yet,
descriptive. This output is at the start of the program. In my example files this usually takes
the form of a *help* function containing the output. This way both the source file viewer and
application runner can see what all is about in your sample. Here's an instance of this:
@code{.cpp}
void help()
{
cout
<< "--------------------------------------------------------------------------" << endl
<< "This program shows how to write video files. You can extract the R or G or B color channel "
<< " of the input video. You can choose to use the source codec (Y) or select a custom one. (N)"<< endl
<< "Usage:" << endl
<< "./video-write inputvideoName [ R | G | B] [Y | N]" << endl
<< "--------------------------------------------------------------------------" << endl
<< endl;
}
// ...
int main(int argc, char *argv[], char *window_name)
{
help();
// here comes the actual source code
}
@endcode
Additionally, finalize the description with a short usage guide. This way the user will know how
to call your programs, what leads us to the next point.
- Prefer command line argument controlling instead of hard coded one. If your program has some
variables that may be changed use command line arguments for this. The tutorials, can be a
simple try-out ground for the user. If you offer command line controlling for the input image
(for example), then you offer the possibility for the user to try it out with his/her own
images, without the need to mess in the source code. In the upper example you can see that the
input image, channel and codec selection may all be changed from the command line. Just compile
the program and run it with your own input arguments.
- Be as verbose as possible. There is no shame in filling the source code with comments. This way
the more advanced user may figure out what's happening right from the sample code. This advice
goes for the output console too. Specify to the user what's happening. Never leave the user
hanging there and thinking on: "Is this program now crashing or just doing some computationally
intensive task?." So, if you do a training task that may take some time, make sure you print out
a message about this before starting and after finishing it.
- Throw out unnecessary stuff from your source code. This is a warning to not take the previous
point too seriously. Balance is the key. If it's something that can be done in a fewer lines or
simpler than that's the way you should do it. Nevertheless, if for some reason you have such
sections notify the user why you have chosen to do so. Keep the amount of information as low as
possible, while still getting the job done in an elegant way.
- Put your sample file into the `opencv/samples/cpp/tutorial_code/sectionName` folder. If you
write a tutorial for other languages than cpp, then change that part of the path. Before
completing this you need to decide that to what section (module) does your tutorial goes. Think
about on what module relies most heavily your code and that is the one to use. If the answer to
this question is more than one modules then the *general* section is the one to use. For finding
the *opencv* directory open up your file system and navigate where you downloaded our
repository.
- If the input resources are hard to acquire for the end user consider adding a few of them to the
`opencv/samples/cpp/tutorial_code/images`. Make sure that who reads your code can try it out!
Add the TOC entry
-----------------
For this you will need to know some reStructuredText_. There is no going around this.
reStructuredText_ files have **rst** extensions. However, these are simple text files. Use any text
editor you like. Finding a text editor that offers syntax highlighting for reStructuredText_ was
quite a challenge at the time of writing this tutorial. In my experience,
[Intype](http://intype.info/) is a solid option on Windows, although there is still place for
improvement.
Adding your source code to a table of content is important for multiple reasons. First and foremost
this will allow for the user base to find your tutorial from our websites tutorial table of content.
Secondly, if you omit this *Sphinx* will throw a warning that your tutorial file isn't part of any
TOC tree entry. And there is nothing more than the developer team hates than an ever increasing
warning/error list for their builds. *Sphinx* also uses this to build up the previous-back-up
buttons on the website. Finally, omitting this step will lead to that your tutorial will **not** be
added to the PDF version of the tutorials.
Navigate to the `opencv/doc/tutorials/section/table_of_content_section` folder (where the section is
the module to which you're adding the tutorial). Open the *table_of_content_section* file. Now
this may have two forms. If no prior tutorials are present in this section that there is a template
message about this and has the following form:
@code{.rst}
.. _Table-Of-Content-Section:
Section title
-----------------------------------------------------------
Description about the section.
.. include:: ../../definitions/noContent.rst
.. raw:: latex
@endcode
The first line is a reference to the section title in the reST system. The section title will be a
link and you may refer to it via the
`` @ref directive. The *include* directive imports the template text from the definitions directories *noContent.rst* file. *Sphinx* does not creates the PDF from scratch. It does this by first creating a latex file. Then creates the PDF from the latex file. With the *raw* directive you can directly add to this output commands. Its unique argument is for what kind of output to add the content of the directive. For the PDFs it may happen that multiple sections will overlap on a single page. To avoid this at the end of the TOC we add a *pagebreak* latex command, that hints to the LATEX system that the next line should be on a new page. If you have one of this, try to transform it to the following form: .. include:: ../../definitions/tocDefinitions.rst .. code-block:: rst .. _Table-Of-Content-Section: Section title ----------------------------------------------------------- .. include:: ../../definitions/tocDefinitions.rst + .. tabularcolumns:: m{100pt} m{300pt} .. cssclass:: toctableopencv |MatBasicIma| **Title:** @ref matTheBasicImageContainer *Compatibility:* > OpenCV 2.0 *Author:* Bernát Gábor You will learn how to store images in the memory and how to print out their content to the console. =============== ===================================================== .. |MatBasicIma| image:: images/matTheBasicImageStructure.jpg .. raw:: latex .. toctree:: :hidden: ../mat - the basic image container/mat - the basic image container If this is already present just add a new section of the content between the include and the raw directives (excluding those lines). Here you'll see a new include directive. This should be present only once in a TOC tree and the reST file contains the definitions of all the authors contributing to the OpenCV tutorials. We are a multicultural community and some of our name may contain some funky characters. However, reST **only supports** ANSI characters. Luckily we can specify Unicode characters with the *unicode* directive. Doing this for all of your tutorials is a troublesome procedure. Therefore, the tocDefinitions file contains the definition of your author name. Add it here once and afterwards just use the replace construction. For example here's the definition for my name: .. code-block:: rst .. Bernát Gábor unicode:: Bern U+00E1 t U+0020 G U+00E1 bor The `Bernát Gábor` is the text definitions alias. I can use later this to add the definition, like I've done in the TOCs *Author* part. After the `::` and a space you start the definition. If you want to add an UNICODE character (non-ASCI) leave an empty space and specify it in the format U+(UNICODE code). To find the UNICODE code of a character I recommend using the `FileFormat <http://www.fileformat.info>`_ websites service. Spaces are trimmed from the definition, therefore we add a space by its UNICODE character (U+0020). Until the *raw* directive what you can see is a TOC tree entry. Here's how a TOC entry will look like: + .. tabularcolumns:: m{100pt} m{300pt} .. cssclass:: toctableopencv |MatBasicIma| **Title:** @ref matTheBasicImageContainer *Compatibility:* > OpenCV 2.0 *Author:* Bernát Gábor You will learn how to store images in the memory and how to print out their content to the console. .. |MatBasicIma| image:: images/matTheBasicImageStructure.jpg As you can see we have an image to the left and a description box to the right. To create two boxes we use a table with two columns and a single row. In the left column is the image and in the right one the description. However, the image directive is way too long to fit in a column. Therefore, we need to use the substitution definition system. We add this definition after the TOC tree. All images for the TOC tree are to be put in the images folder near its |reST|_ file. We use the point measurement system because we are also creating PDFs. PDFs are printable documents, where there is no such thing that pixels (px), just points (pt). And while generally space is no problem for web pages (we have monitors with **huge** resolutions) the size of the paper (A4 or letter) is constant and will be for a long time in the future. Therefore, size constrains come in play more like for the PDF, than the generated HTML code. Now your images should be as small as possible, while still offering the intended information for the user. Remember that the tutorial will become part of the OpenCV source code. If you add large images (that manifest in form of large image size) it will just increase the size of the repository pointlessly. If someone wants to download it later, its download time will be that much longer. Not to mention the larger PDF size for the tutorials and the longer load time for the web pages. In terms of pixels a TOC image should not be larger than 120 X 120 pixels. Resize your images if they are larger! @note If you add a larger image and specify a smaller image size, *Sphinx* will not resize that. At build time will add the full size image and the resize will be done by your browser after the image is loaded. A 120 X 120 image is somewhere below 10KB. If you add a 110KB image, you have just pointlessly added a 100KB extra data to transfer over the internet for every user! Generally speaking you shouldn't need to specify your images size (excluding the TOC entries). If no such is found *Sphinx* will use the size of the image itself (so no resize occurs). Then again if for some reason you decide to specify a size that should be the **width** of the image rather than its height. The reason for this again goes back to the PDFs. On a PDF page the height is larger than the width. In the PDF the images will not be resized. If you specify a size that does not fit in the page, then what does not fits in **will be cut off**. When creating your images for your tutorial you should try to keep the image widths below 500 pixels, and calculate with around 400 point page width when specifying image widths. The image format depends on the content of the image. If you have some complex scene (many random like colors) then use *jpg*. Otherwise, prefer using *png*. They are even some tools out there that optimize the size of *PNG* images, such as `PNGGauntlet <http://pnggauntlet.com/>`_. Use them to make your images as small as possible in size. Now on the right side column of the table we add the information about the tutorial: .. container:: enumeratevisibleitemswithsquare + In the first line it is the title of the tutorial. However, there is no need to specify it explicitly. We use the reference system. We'll start up our tutorial with a reference specification, just like in case of this TOC entry with its ` .. _Table-Of-Content-Section:` . If after this you have a title (pointed out by the following line of -), then Sphinx will replace the `@ref Table-Of-Content-Section` directive with the tile of the section in reference form (creates a link in web page). Here's how the definition looks in my case: .. code-block:: rst .. _matTheBasicImageContainer: Mat - The Basic Image Container ******************************* Note, that according to the |reST|_ rules the * should be as long as your title. + Compatibility. What version of OpenCV is required to run your sample code. + Author. Use the substitution markup of |reST|_. + A short sentence describing the essence of your tutorial. Now before each TOC entry you need to add the three lines of: .. code-block:: cpp + .. tabularcolumns:: m{100pt} m{300pt} .. cssclass:: toctableopencv The plus sign (+) is to enumerate tutorials by using bullet points. So for every TOC entry we have a corresponding bullet point represented by the +. Sphinx is highly indenting sensitive. Indentation is used to express from which point until to which point does a construction last. Un-indentation means end of that construction. So to keep all the bullet points to the same group the following TOC entries (until the next +) should be indented by two spaces. Here, I should also mention that **always** prefer using spaces instead of tabs. Working with only spaces makes possible that if we both use monotype fonts we will see the same thing. Tab size is text editor dependent and as should be avoided. *Sphinx* translates all tabs into 8 spaces before interpreting it. It turns out that the automatic formatting of both the HTML and PDF(LATEX) system messes up our tables. Therefore, we need to help them out a little. For the PDF generation we add the `.. tabularcolumns:: m{100pt} m{300pt}` directive. This means that the first column should be 100 points wide and middle aligned. For the HTML look we simply name the following table of a *toctableopencv* class type. Then, we can modify the look of the table by modifying the CSS of our web page. The CSS definitions go into the ``opencv/doc/_themes/blue/static/default.css_t`file. .. code-block:: css .toctableopencv { width: 100% ; table-layout: fixed; } .toctableopencv colgroup col:first-child { width: 100pt !important; max-width: 100pt !important; min-width: 100pt !important; } .toctableopencv colgroup col:nth-child(2) { width: 100% !important; } However, you should not need to modify this. Just add these three lines (plus keep the two space indentation) for all TOC entries you add. At the end of the TOC file you'll find: .. code-block:: rst .. raw:: latex .. toctree:: :hidden: ../mat - the basic image container/mat - the basic image container The page break entry comes for separating sections and should be only one in a TOC tree |reST|_ file. Finally, at the end of the TOC tree we need to add our tutorial to the *Sphinx* TOC tree system. *Sphinx* will generate from this the previous-next-up information for the HTML file and add items to the PDF according to the order here. By default this TOC tree directive generates a simple table of contents. However, we already created a fancy looking one so we no longer need this basic one. Therefore, we add the *hidden* option to do not show it. The path is of a relative type. We step back in the file system and then go into the`mat -
the basic image container`directory for the`mat - the basic image
container.rst`file. Putting out the *rst* extension for the file is optional. Write the tutorial ================== Create a folder with the name of your tutorial. Preferably, use small letters only. Then create a text file in this folder with *rst* extension and the same name. If you have images for the tutorial create an`images`` folder and add your images there. When creating your images follow the guidelines described in the previous part! Now here's our recommendation for the structure of the tutorial (although, remember that this is not carved in the stone; if you have a better idea, use it!): .. container:: enumeratevisibleitemswithsquare + Create the reference point and the title. .. code-block:: rst .. _matTheBasicImageContainer: Mat - The Basic Image Container ******************************* You start the tutorial by specifying a reference point by the `.. _matTheBasicImageContainer:` and then its title. The name of the reference point should be a unique one over the whole documentation. Therefore, do not use general names like *tutorial1*. Use the * character to underline the title for its full width. The subtitles of the tutorial should be underlined with = charachter. + Goals. You start your tutorial by specifying what you will present. You can also enumerate the sub jobs to be done. For this you can use a bullet point construction. There is a single configuration file for both the reference manual and the tutorial documentation. In the reference manuals at the argument enumeration we do not want any kind of bullet point style enumeration. Therefore, by default all the bullet points at this level are set to do not show the dot before the entries in the HTML. You can override this by putting the bullet point in a container. I've defined a square type bullet point view under the name *enumeratevisibleitemswithsquare*. The CSS style definition for this is again in the ``opencvdoc_themesbluestaticdefault.css_t`file. Here's a quick example of using it: .. code-block:: rst .. container:: enumeratevisibleitemswithsquare + Create the reference point and the title. + Second entry + Third entry Note that you need the keep the indentation of the container directive. Directive indentations are always three (3) spaces. Here you may even give usage tips for your sample code. + Source code. Present your samples code to the user. It's a good idea to offer a quick download link for the HTML page by using the *download* directive and pointing out where the user may find your source code in the file system by using the *file* directive: .. code-block:: rst Text`samples/cpp/tutorial_code/highgui/video-write/`` folder of the OpenCV source library or :download:`text to appear in the webpage <../../../../samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp>`. For the download link the path is a relative one, hence the multiple back stepping operations (..). Then you can add the source code either by using the *code block* directive or the *literal include* one. In case of the code block you will need to actually add all the source code text into your |reST|_ text and also apply the required indentation: .. code-block:: rst .. code-block:: cpp int i = 0; l = ++j; The only argument of the directive is the language used (here CPP). Then you add the source code into its content (meaning one empty line after the directive) by keeping the indentation of the directive (3 spaces). With the *literal include* directive you do not need to add the source code of the sample. You just specify the sample and *Sphinx* will load it for you, during build time. Here's an example usage: .. code-block:: rst @includelineno cpp/tutorial_code/HighGUI/video-write/video-write.cpp :lines: 1-8, 21-23, 25- After the directive you specify a relative path to the file from what to import. It has four options: the language to use, if you add the ` + The tutorial. Well here goes the explanation for why and what have you used. Try to be short, clear, concise and yet a thorough one. There's no magic formula. Look into a few already made tutorials and start out from there. Try to mix sample OpenCV code with your explanations. If with words is hard to describe something do not hesitate to add in a reasonable size image, to overcome this issue. When you present OpenCV functionality it's a good idea to give a link to the used OpenCV data structure or function. Because the OpenCV tutorials and reference manual are in separate PDF files it is not possible to make this link work for the PDF format. Therefore, we use here only web page links to the http://docs.opencv.org website. The OpenCV functions and data structures may be used for multiple tasks. Nevertheless, we want to avoid that every users creates its own reference to a commonly used function. So for this we use the global link collection of *Sphinx*. This is defined in the file:`opencv/doc/conf.py` configuration file. Open it and go all the way down to the last entry: .. code-block:: py # ---- External links for tutorials ----------------- extlinks = { 'rwimg' : ('http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html#%s', None) } In short here we defined a new **rwimg** directive that refers to an external webpage link. Its usage is: .. code-block:: rst A sample function of the highgui modules image write and read page is the @ref cv::imread() function . Which turns to: A sample function of the highgui modules image write and read page is the @ref cv::imread() function . The argument you give between the <> will be put in place of the `%s` in the upper definition, and as the link will anchor to the correct function. To find out the anchor of a given function just open up a web page, search for the function and click on it. In the address bar it should appear like: `http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images.html#imread` . Look here for the name of the directives for each page of the OpenCV reference manual. If none present for one of them feel free to add one for it. For formulas you can add LATEX code that will translate in the web pages into images. You do this by using the *math* directive. A usage tip: .. code-block:: latex .. math:: MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2} That after build turns into: .. math:: MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2} You can even use it inline as `:math:` MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2} ``
that turns into \f$MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}\f$.
If you use some crazy LATEX library extension you need to add those to the ones to use at build
time. Look into the [file:\`opencv/doc/conf.py](file:`opencv/doc/conf.py)\` configuration file for
more information on this.
- Results. Well, here depending on your program show one of more of the following:
- Console outputs by using the code block directive.
- Output images.
- Runtime videos, visualization. For this use your favorite screens capture software.
[Camtasia Studio](http://www.techsmith.com/camtasia/) certainly is one of the better
choices, however their prices are out of this world. [CamStudio](http://camstudio.org/) is
a free alternative, but less powerful. If you do a video you can upload it to YouTube and
then use the raw directive with HTML option to embed it into the generated web page:
@code{.rst}
You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=jpBwHxsl1_0>`_.
.. raw:: html
\htmlonly
<div align="center">
<iframe title="Creating a video with OpenCV" width="560" height="349" src="http://www.youtube.com/embed/jpBwHxsl1_0?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>
\endhtmlonly
@endcode
This results in the text and video: You may observe a runtime instance of this on the
[YouTube here](https://www.youtube.com/watch?v=jpBwHxsl1_0).
\htmlonly
<div align="center">
<iframe title="Creating a video with OpenCV" width="560" height="349" src="http://www.youtube.com/embed/jpBwHxsl1_0?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>
\endhtmlonly
When these aren't self-explanatory make sure to throw in a few guiding lines about what and
why we can see.
- Build the documentation and check for errors or warnings. In the CMake make sure you check or
pass the option for building documentation. Then simply build the **docs** project for the PDF
file and the **docs_html** project for the web page. Read the output of the build and check
for errors/warnings for what you have added. This is also the time to observe and correct any
kind of *not so good looking* parts. Remember to keep clean our build logs.
- Read again your tutorial and check for both programming and spelling errors. If found any,
please correct them.
Take home the pride and joy of a job well done!
-----------------------------------------------
Once you are done please make a GitHub pull request with the tutorial. Now, to see your work
**live** you may need to wait some time. The PDFs are updated usually at the launch of a new OpenCV
version. The web pages are a little more diverse. They are automatically rebuilt nightly. Currently
we use 2.4 and master branches for daily builds. So, if your pull request was merged to any of these
branches, your material will be published at [docs.opencv.org/2.4](http:/docs.opencv.org/2.4) or
[docs.opencv.org/master](http:/docs.opencv.org/master) correspondingly. Everything that was added to
2.4 is merged to master branch every week. Although, we try to make a build every night,
occasionally we might freeze any of the branches to fix upcoming issues. During this it may take a
little longer to see your work online, however if you submitted it, be sure that eventually it will
show up.
If you have any questions or advices relating to this tutorial you can contact us at
<-delete-admin@-delete-opencv.org> (delete the -delete- parts of that email address).
@todo new tutorial guide needed
......@@ -12,10 +12,12 @@ Required Packages
Launch GIT client and clone OpenCV repository from [here](http://github.com/itseez/opencv)
In MacOS it can be done using the following command in Terminal:
@code{.bash}
cd ~/<my_working _directory>
git clone https://github.com/Itseez/opencv.git
@endcode
Building OpenCV from Source, using CMake and Command Line
---------------------------------------------------------
......@@ -24,11 +26,13 @@ Building OpenCV from Source, using CMake and Command Line
cd /
sudo ln -s /Applications/Xcode.app/Contents/Developer Developer
@endcode
2. Build OpenCV framework:
@code{.bash}
cd ~/<my_working_directory>
python opencv/platforms/ios/build_framework.py ios
@endcode
If everything's fine, a few minutes later you will get
\~/\<my_working_directory\>/ios/opencv2.framework. You can add this framework to your Xcode
projects.
......@@ -36,5 +40,4 @@ projects.
Further Reading
---------------
You can find several OpenCV+iOS tutorials here @ref Table-Of-Content-iOS.
You can find several OpenCV+iOS tutorials here @ref tutorial_table_of_content_ios.
......@@ -11,7 +11,7 @@ Configuring Eclipse
-------------------
First, obtain a fresh release of OpenCV [from download page](http://opencv.org/downloads.html) and
extract it under a simple location like C:\\OpenCV-2.4.6\\. I am using version 2.4.6, but the steps
extract it under a simple location like `C:\OpenCV-2.4.6\`. I am using version 2.4.6, but the steps
are more or less the same for other versions.
Now, we will define OpenCV as a user library in Eclipse, so we can reuse the configuration for any
......@@ -31,12 +31,12 @@ Now select your new user library and click Add External JARs....
![image](images/4-add-external-jars.png)
Browse through C:\\OpenCV-2.4.6\\build\\java\\ and select opencv-246.jar. After adding the jar,
Browse through `C:\OpenCV-2.4.6\build\java\` and select opencv-246.jar. After adding the jar,
extend the opencv-246.jar and select Native library location and press Edit....
![image](images/5-native-library.png)
Select External Folder... and browse to select the folder C:\\OpenCV-2.4.6\\build\\java\\x64. If you
Select External Folder... and browse to select the folder `C:\OpenCV-2.4.6\build\java\x64`. If you
have a 32-bit system you need to select the x86 folder instead of x64.
![image](images/6-external-folder.png)
......@@ -86,4 +86,3 @@ When you run the code you should see 3x3 identity matrix as output.
That is it, whenever you start a new project just add the OpenCV user library that you have defined
to your project and you are good to go. Enjoy your powerful, less painful development environment :)
Using OpenCV with Eclipse (plugin CDT) {#tutorial_linux_eclipse}
======================================
@note Two ways, one by forming a project directly, and another by CMake Prerequisites
===============
Prerequisites
-------------
Two ways, one by forming a project directly, and another by CMake Prerequisites
1. Having installed [Eclipse](http://www.eclipse.org/) in your workstation (only the CDT plugin for
C/C++ is needed). You can follow the following steps:
- Go to the Eclipse site
- Download [Eclipse IDE for C/C++
Developers](http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/heliossr2) .
Choose the link according to your workstation.
2. Having installed OpenCV. If not yet, go @ref here \<Linux-Installation\>.
2. Having installed OpenCV. If not yet, go @ref tutorial_linux_install "here".
Making a project
----------------
......@@ -75,13 +74,13 @@ Making a project
- Go to **Project--\>Properties**
- In **C/C++ Build**, click on **Settings**. At the right, choose the **Tool Settings** Tab.
Here we will enter the headers and libraries info:
a. In **GCC C++ Compiler**, go to **Includes**. In **Include paths(-l)** you should
-# In **GCC C++ Compiler**, go to **Includes**. In **Include paths(-l)** you should
include the path of the folder where opencv was installed. In our example, this is
/usr/local/include/opencv.
![image](images/a9.png)
@note If you do not know where your opencv files are, open the **Terminal** and type:
@note If you do not know where your opencv files are, open the **Terminal** and type:
@code{.bash}
pkg-config --cflags opencv
@endcode
......@@ -89,7 +88,8 @@ Making a project
@code{.bash}
-I/usr/local/include/opencv -I/usr/local/include
@endcode
b. Now go to **GCC C++ Linker**,there you have to fill two spaces:
-# Now go to **GCC C++ Linker**,there you have to fill two spaces:
First in **Library search path (-L)** you have to write the path to where the opencv libraries
reside, in my case the path is: :
......@@ -110,10 +110,10 @@ b. Now go to **GCC C++ Linker**,there you have to fill two spaces:
@code{.bash}
pkg-config --libs opencv
@endcode
My output (in case you want to check) was: .. code-block:: bash
My output (in case you want to check) was:
@code{.bash}
-L/usr/local/lib -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_flann
@endcode
Now you are done. Click **OK**
- Your project should be ready to be built. For this, go to **Project-\>Build all**
......@@ -171,7 +171,7 @@ int main ( int argc, char **argv )
}
@endcode
1. Create a build directory, say, under *foo*: mkdir /build. Then cd build.
2. Put a *CmakeLists.txt* file in build:
2. Put a `CmakeLists.txt` file in build:
@code{.bash}
PROJECT( helloworld_proj )
FIND_PACKAGE( OpenCV REQUIRED )
......@@ -180,21 +180,20 @@ TARGET_LINK_LIBRARIES( helloworld \f${OpenCV_LIBS} )
@endcode
1. Run: cmake-gui .. and make sure you fill in where opencv was built.
2. Then click configure and then generate. If it's OK, **quit cmake-gui**
3. Run make -j4 *(the -j4 is optional, it just tells the compiler to build in 4 threads)*. Make
3. Run `make -j4` (the -j4 is optional, it just tells the compiler to build in 4 threads). Make
sure it builds.
4. Start eclipse . Put the workspace in some directory but **not** in foo or foo\\\\build
4. Start eclipse. Put the workspace in some directory but **not** in foo or `foo\build`
5. Right click in the Project Explorer section. Select Import And then open the C/C++ filter.
Choose *Existing Code* as a Makefile Project\`\`
6. Name your project, say *helloworld*. Browse to the Existing Code location foo\\\\build (where
Choose *Existing Code* as a Makefile Project.
6. Name your project, say *helloworld*. Browse to the Existing Code location `foo\build` (where
you ran your cmake-gui from). Select *Linux GCC* in the *"Toolchain for Indexer Settings"* and
press *Finish*.
7. Right click in the Project Explorer section. Select Properties. Under C/C++ Build, set the
*build directory:* from something like \\f${workspace_loc:/helloworld} to
\\f${workspace_loc:/helloworld}/build since that's where you are building to.
*build directory:* from something like `${workspace_loc:/helloworld}` to
`${workspace_loc:/helloworld}/build` since that's where you are building to.
a. You can also optionally modify the Build command: from make to something like
make VERBOSE=1 -j4 which tells the compiler to produce detailed symbol files for debugging and
-# You can also optionally modify the Build command: from make to something like
`make VERBOSE=1 -j4` which tells the compiler to produce detailed symbol files for debugging and
also to compile in 4 parallel threads.
1. Done!
8. Done!
......@@ -127,10 +127,9 @@ Building OpenCV from Source Using CMake
@code{.bash}
<cmake_build_dir>/bin/opencv_test_core
@endcode
@note
If the size of the created library is a critical issue (like in case of an Android build) you
can use the install/strip command to get the smallest size as possible. The *stripped* version
appears to be twice as small. However, we do not recommend using this unless those extra
megabytes do really matter.
......@@ -3,7 +3,7 @@ Load, Modify, and Save an Image {#tutorial_load_save_image}
@note
We assume that by now you know how to load an image using @ref cv::imread and to display it in a
window (using @ref cv::imshow ). Read the @ref Display_Image tutorial otherwise.
window (using @ref cv::imshow ). Read the @ref tutorial_display_image tutorial otherwise.
Goals
-----
......@@ -103,4 +103,3 @@ And if you check in your folder (in my case *images*), you should have a newly .
![image](images/Load_Save_Image_Result_2.jpg)
Congratulations, you are done with this tutorial!
......@@ -6,13 +6,13 @@ relatively modern version of Windows OS. If you encounter errors after following
below, feel free to contact us via our [OpenCV Q&A forum](http://answers.opencv.org). We'll do our
best to help you out.
@note To use the OpenCV library you have two options: @ref Windows_Install_Prebuild or @ref
CppTutWindowsMakeOwn. While the first one is easier to complete, it only works if you are coding
@note To use the OpenCV library you have two options: @ref tutorial_windows_install_prebuilt or
@ref tutorial_windows_install_build. While the first one is easier to complete, it only works if you are coding
with the latest Microsoft Visual Studio IDE and doesn't take advantage of the most advanced
technologies we integrate into our library. .. _Windows_Install_Prebuild:
Installation by Using the Pre-built Libraries
---------------------------------------------
Installation by Using the Pre-built Libraries {#tutorial_windows_install_prebuilt}
=============================================
1. Launch a web browser of choice and go to our [page on
Sourceforge](http://sourceforge.net/projects/opencvlibrary/files/opencv-win/).
......@@ -22,14 +22,13 @@ Installation by Using the Pre-built Libraries
![image](images/OpenCV_Install_Directory.png)
5. To finalize the installation go to the @ref WindowsSetPathAndEnviromentVariable section.
5. To finalize the installation go to the @ref tutorial_windows_install_path section.
Installation by Making Your Own Libraries from the Source Files
---------------------------------------------------------------
Installation by Making Your Own Libraries from the Source Files {#tutorial_windows_install_build}
===============================================================
You may find the content of this tutorial also inside the following videos: [Part
1](https://www.youtube.com/watch?v=NnovZ1cTlMs) and [Part
2](https://www.youtube.com/watch?v=qGNWMcfWwPU), hosted on YouTube.
You may find the content of this tutorial also inside the following videos:
[Part 1](https://www.youtube.com/watch?v=NnovZ1cTlMs) and [Part 2](https://www.youtube.com/watch?v=qGNWMcfWwPU), hosted on YouTube.
\htmlonly
<div align="center">
......@@ -37,6 +36,7 @@ You may find the content of this tutorial also inside the following videos: [Par
<iframe title="Install OpenCV by using its source files - Part 2" width="560" height="349" src="http://www.youtube.com/embed/qGNWMcfWwPU?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>
\endhtmlonly
**warning**
These videos above are long-obsolete and contain inaccurate information. Be careful, since
......@@ -50,10 +50,10 @@ Building the OpenCV library from scratch requires a couple of tools installed be
- An IDE of choice (preferably), or just a CC++ compiler that will actually make the binary files.
Here we will use the [Microsoft Visual Studio](https://www.microsoft.com/visualstudio/en-us).
However, you can use any other IDE that has a valid CC++ compiler.
- CMake_, which is a neat tool to make the project files (for your chosen IDE) from the OpenCV
- [CMake](http://www.cmake.org/cmake/resources/software.html), which is a neat tool to make the project files (for your chosen IDE) from the OpenCV
source files. It will also allow an easy configuration of the OpenCV build files, in order to
make binary files that fits exactly to your needs.
- Git to acquire the OpenCV source files. A good tool for this is TortoiseGit_. Alternatively,
- Git to acquire the OpenCV source files. A good tool for this is [TortoiseGit](http://code.google.com/p/tortoisegit/wiki/Download). Alternatively,
you can just download an archived version of the source files from our [page on
Sourceforge](http://sourceforge.net/projects/opencvlibrary/files/opencv-win/)
......@@ -62,35 +62,35 @@ Nevertheless, there is a couple of tools, libraries made by 3rd parties that off
the OpenCV may take advantage. These will improve its capabilities in many ways. In order to use any
of them, you need to download and install them on your system.
- The Python libraries_ are required to build the *Python interface* of OpenCV. For now use the
- The [Python libraries](http://www.python.org/downloads/) are required to build the *Python interface* of OpenCV. For now use the
version `2.7.{x}`. This is also a must if you want to build the *OpenCV documentation*.
- Numpy_ is a scientific computing package for Python. Required for the *Python interface*.
- Intel |copy| Threading Building Blocks (*TBB*)_ is used inside OpenCV for parallel code
- [Numpy](http://numpy.scipy.org/) is a scientific computing package for Python. Required for the *Python interface*.
- [Intel Threading Building Blocks (*TBB*)](http://threadingbuildingblocks.org/file.php?fid=77) is used inside OpenCV for parallel code
snippets. Using this will make sure that the OpenCV library will take advantage of all the cores
you have in your systems CPU.
- Intel |copy| Integrated Performance Primitives (*IPP*)_ may be used to improve the performance
- [Intel Integrated Performance Primitives (*IPP*)](http://software.intel.com/en-us/articles/intel-ipp/) may be used to improve the performance
of color conversion, Haar training and DFT functions of the OpenCV library. Watch out, since
this isn't a free service.
- Intel |copy| IPP Asynchronous C/C++_ is currently focused delivering Intel |copy| Graphics
- [Intel IPP Asynchronous C/C++](http://software.intel.com/en-us/intel-ipp-preview) is currently focused delivering Intel Graphics
support for advanced image processing and computer vision functions.
- OpenCV offers a somewhat fancier and more useful graphical user interface, than the default one
by using the Qt framework_. For a quick overview of what this has to offer look into the
by using the [Qt framework](http://qt.nokia.com/downloads). For a quick overview of what this has to offer look into the
documentations *highgui* module, under the *Qt New Functions* section. Version 4.6 or later of
the framework is required.
- Eigen_ is a C++ template library for linear algebra.
- The latest CUDA Toolkit_ will allow you to use the power lying inside your GPU. This will
- [Eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page#Download) is a C++ template library for linear algebra.
- The latest [CUDA Toolkit](http://developer.nvidia.com/cuda-downloads) will allow you to use the power lying inside your GPU. This will
drastically improve performance for some algorithms (e.g the HOG descriptor). Getting more and
more of our algorithms to work on the GPUs is a constant effort of the OpenCV team.
- OpenEXR_ source files are required for the library to work with this high dynamic range (HDR)
- [OpenEXR](http://www.openexr.com/downloads.html) source files are required for the library to work with this high dynamic range (HDR)
image file format.
- The OpenNI Framework_ contains a set of open source APIs that provide support for natural
- The [OpenNI Framework](http://www.openni.org/) contains a set of open source APIs that provide support for natural
interaction with devices via methods such as voice command recognition, hand gestures and body
motion tracking.
- Miktex_ is the best [TEX](https://secure.wikimedia.org/wikipedia/en/wiki/TeX) implementation on
- [Miktex]( http://miktex.org/2.9/setup) is the best [TEX](https://secure.wikimedia.org/wikipedia/en/wiki/TeX) implementation on
the Windows OS. It is required to build the *OpenCV documentation*.
- Sphinx_ is a python documentation generator and is the tool that will actually create the
- [Sphinx](http://sphinx.pocoo.org/) is a python documentation generator and is the tool that will actually create the
*OpenCV documentation*. This on its own requires a couple of tools installed, We will cover this
in depth at the @ref How to Install Sphinx \<HereInstallSphinx\> section.
in depth at the @ref tutorial_windows_install_sphinx "How to Install Sphinx" section.
Now we will describe the steps to follow for a full build (using all the above frameworks, tools and
libraries). If you do not need the support for some of these you can just freely skip this section.
......@@ -99,31 +99,32 @@ libraries). If you do not need the support for some of these you can just freely
1. Make sure you have a working IDE with a valid compiler. In case of the Microsoft Visual Studio
just install it and make sure it starts up.
2. Install CMake_. Simply follow the wizard, no need to add it to the path. The default install
2. Install [CMake](http://www.cmake.org/cmake/resources/software.html). Simply follow the wizard, no need to add it to the path. The default install
options are OK.
3. Download and install an up-to-date version of msysgit from its [official
site](http://code.google.com/p/msysgit/downloads/list). There is also the portable version,
which you need only to unpack to get access to the console version of Git. Supposing that for
some of us it could be quite enough.
4. Install TortoiseGit_. Choose the 32 or 64 bit version according to the type of OS you work in.
4. Install [TortoiseGit](http://code.google.com/p/tortoisegit/wiki/Download). Choose the 32 or 64 bit version according to the type of OS you work in.
While installing, locate your msysgit (if it doesn't do that automatically). Follow the
wizard -- the default options are OK for the most part.
5. Choose a directory in your file system, where you will download the OpenCV libraries to. I
recommend creating a new one that has short path and no special charachters in it, for example
`D:/OpenCV`. For this tutorial I'll suggest you do so. If you use your own path and know, what
you're doing -- it's OK.
a) Clone the repository to the selected directory. After clicking *Clone* button, a window will
-# Clone the repository to the selected directory. After clicking *Clone* button, a window will
appear where you can select from what repository you want to download source files
(<https://github.com/Itseez/opencv.git>) and to what directory (`D:/OpenCV`).
b) Push the OK button and be patient as the repository is quite a heavy download. It will take
-# Push the OK button and be patient as the repository is quite a heavy download. It will take
some time depending on your Internet connection.
6. In this section I will cover installing the 3rd party libraries.
a) Download the Python libraries_ and install it with the default options. You will need a
-# Download the [Python libraries](http://www.python.org/downloads/) and install it with the default options. You will need a
couple other python extensions. Luckily installing all these may be automated by a nice tool
called [Setuptools](http://pypi.python.org/pypi/setuptools#downloads). Download and install
again.
b) Installing Sphinx is easy once you have installed *Setuptools*. This contains a little
@anchor tutorial_windows_install_sphinx
-# Installing Sphinx is easy once you have installed *Setuptools*. This contains a little
application that will automatically connect to the python databases and download the latest
version of many python scripts. Start up a command window (enter *cmd* into the windows
start menu and press enter) and use the *CD* command to navigate to your Python folders
......@@ -134,47 +135,49 @@ libraries). If you do not need the support for some of these you can just freely
![image](images/Sphinx_Install.png)
@note
@note
The *CD* navigation command works only inside a drive. For example if you are somewhere in the
*C:* drive you cannot use it this to go to another drive (like for example *D:*). To do so you
first need to change drives letters. For this simply enter the command *D:*. Then you can use
the *CD* to navigate to specific folder inside the drive. Bonus tip: you can clear the screen by
using the *CLS* command.
This will also install its prerequisites [Jinja2](http://jinja.pocoo.org/docs/) and
[Pygments](http://pygments.org/).
This will also install its prerequisites [Jinja2](http://jinja.pocoo.org/docs/) and
[Pygments](http://pygments.org/).
1) The easiest way to install Numpy_ is to just download its binaries from the [sourceforga
page](http://sourceforge.net/projects/numpy/files/NumPy/). Make sure your download and install
-# The easiest way to install Numpy is to just download its binaries from the [sourceforge page](http://sourceforge.net/projects/numpy/files/NumPy/).
Make sure your download and install
exactly the binary for your python version (so for version `2.7`).
2) Download the Miktex_ and install it. Again just follow the wizard. At the fourth step make
-# Download the [Miktex](http://miktex.org/2.9/setup) and install it. Again just follow the wizard. At the fourth step make
sure you select for the *"Install missing packages on-the-fly"* the *Yes* option, as you can
see on the image below. Again this will take quite some time so be patient.
![image](images/MiktexInstall.png)
3) For the Intel |copy| Threading Building Blocks (*TBB*)_ download the source files and extract
-# For the [Intel Threading Building Blocks (*TBB*)](http://threadingbuildingblocks.org/file.php?fid=77)
download the source files and extract
it inside a directory on your system. For example let there be `D:/OpenCV/dep`. For installing
the Intel |copy| Integrated Performance Primitives (*IPP*)_ the story is the same. For
the [Intel Integrated Performance Primitives (*IPP*)](http://software.intel.com/en-us/articles/intel-ipp/)
the story is the same. For
exctracting the archives I recommend using the [7-Zip](http://www.7-zip.org/) application.
![image](images/IntelTBB.png)
4) For the Intel |copy| IPP Asynchronous C/C++_ download the source files and set environment
-# For the [Intel IPP Asynchronous C/C++](http://software.intel.com/en-us/intel-ipp-preview) download the source files and set environment
variable **IPP_ASYNC_ROOT**. It should point to
`<your Program Files(x86) directory>/Intel/IPP Preview */ipp directory`. Here \* denotes the
particular preview name.
5) In case of the Eigen_ library it is again a case of download and extract to the
-# In case of the [Eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page#Download) library it is again a case of download and extract to the
`D:/OpenCV/dep` directory.
6) Same as above with OpenEXR_.
7) For the OpenNI Framework_ you need to install both the [development
-# Same as above with [OpenEXR](http://www.openexr.com/downloads.html).
-# For the [OpenNI Framework](http://www.openni.org/) you need to install both the [development
build](http://www.openni.org/downloadfiles/opennimodules/openni-binaries/21-stable) and the
[PrimeSensor
Module](http://www.openni.org/downloadfiles/opennimodules/openni-compliant-hardware-binaries/32-stable).
8) For the CUDA you need again two modules: the latest CUDA Toolkit_ and the *CUDA Tools SDK*.
-# For the CUDA you need again two modules: the latest [CUDA Toolkit](http://developer.nvidia.com/cuda-downloads) and the *CUDA Tools SDK*.
Download and install both of them with a *complete* option by using the 32 or 64 bit setups
according to your OS.
9) In case of the Qt framework_ you need to build yourself the binary files (unless you use the
-# In case of the Qt framework you need to build yourself the binary files (unless you use the
Microsoft Visual Studio 2008 with 32 bit compiler). To do this go to the [Qt
Downloads](http://qt.nokia.com/downloads) page. Download the source files (not the
installers!!!):
......@@ -205,15 +208,15 @@ This will also install its prerequisites [Jinja2](http://jinja.pocoo.org/docs/)
@code{.bash}
setx -m QTDIR D:/OpenCV/dep/qt/qt-everywhere-opensource-src-4.7.3
@endcode
Also, add the built binary files path to the system path by using the |PathEditor|_. In our
Also, add the built binary files path to the system path by using the [PathEditor](http://www.redfernplace.com/software-projects/patheditor/). In our
case this is `D:/OpenCV/dep/qt/qt-everywhere-opensource-src-4.7.3/bin`.
@note
@note
If you plan on doing Qt application development you can also install at this point the *Qt
Visual Studio Add-in*. After this you can make and build Qt applications without using the *Qt
Creator*. Everything is nicely integrated into Visual Studio.
1. Now start the *CMake (cmake-gui)*. You may again enter it in the start menu search or get it
7. Now start the *CMake (cmake-gui)*. You may again enter it in the start menu search or get it
from the All Programs --\> CMake 2.8 --\> CMake (cmake-gui). First, select the directory for the
source files of the OpenCV library (1). Then, specify a directory where you will build the
binary files for OpenCV (2).
......@@ -307,8 +310,8 @@ This will also install its prerequisites [Jinja2](http://jinja.pocoo.org/docs/)
To test your build just go into the `Build/bin/Debug` or `Build/bin/Release` directory and start
a couple of applications like the *contours.exe*. If they run, you are done. Otherwise,
something definitely went awfully wrong. In this case you should contact us at our @ref cv::Q&A
forum . If everything is okay the *contours.exe* output should resemble the following image (if
something definitely went awfully wrong. In this case you should contact us at our [Q&A forum](http://answers.opencv.org/).
If everything is okay the *contours.exe* output should resemble the following image (if
built with Qt support):
![image](images/WindowsQtContoursOutput.png)
......@@ -319,18 +322,18 @@ This will also install its prerequisites [Jinja2](http://jinja.pocoo.org/docs/)
caused mostly by old video card drivers. For testing the GPU (if built) run the
*performance_gpu.exe* sample application.
Set the OpenCV enviroment variable and add it to the systems path
-----------------------------------------------------------------
Set the OpenCV enviroment variable and add it to the systems path {#tutorial_windows_install_path}
=================================================================
First we set an enviroment variable to make easier our work. This will hold the build directory of
our OpenCV library that we use in our projects. Start up a command window and enter:
@code
setx -m OPENCV_DIR D:\OpenCV\Build\x86\vc10 (suggested for Visual Studio 2010 - 32 bit Windows)
setx -m OPENCV_DIR D:\OpenCV\Build\x64\vc10 (suggested for Visual Studio 2010 - 64 bit Windows)
setx -m OPENCV_DIR D:\OpenCV\Build\x86\vc11 (suggested for Visual Studio 2012 - 32 bit Windows)
setx -m OPENCV_DIR D:\OpenCV\Build\x64\vc11 (suggested for Visual Studio 2012 - 64 bit Windows)
@endcode
Here the directory is where you have your OpenCV binaries (*extracted* or *built*). You can have
different platform (e.g. x64 instead of x86) or compiler type, so substitute appropriate value.
Inside this you should have two folders called *lib* and *bin*. The -m should be added if you wish
......@@ -344,10 +347,11 @@ However, to do this the operating system needs to know where they are. The syste
a list of folders where DLLs can be found. Add the OpenCV library path to this and the OS will know
where to look if he ever needs the OpenCV binaries. Otherwise, you will need to copy the used DLLs
right beside the applications executable file (*exe*) for the OS to find it, which is highly
unpleasent if you work on many projects. To do this start up again the |PathEditor|_ and add the
unpleasent if you work on many projects. To do this start up again the [PathEditor](http://www.redfernplace.com/software-projects/patheditor/) and add the
following new entry (right click in the application to bring up the menu):
@code
%OPENCV_DIR%\bin
@endcode
![image](images/PathEditorOpenCVInsertNew.png)
......@@ -357,7 +361,6 @@ Save it to the registry and you are done. If you ever change the location of you
or want to try out your applicaton with a different build all you will need to do is to update the
OPENCV_DIR variable via the *setx* command inside a command window.
Now you can continue reading the tutorials with the @ref Windows_Visual_Studio_How_To section.
Now you can continue reading the tutorials with the @ref tutorial_windows_visual_studio_Opencv section.
There you will find out how to use the OpenCV library in your own projects with the help of the
Microsoft Visual Studio IDE.
How to build applications with OpenCV inside the *Microsoft Visual Studio* {#tutorial_windows_visual_studio_Opencv}
How to build applications with OpenCV inside the "Microsoft Visual Studio" {#tutorial_windows_visual_studio_Opencv}
==========================================================================
Everything I describe here will apply to the C\\C++ interface of OpenCV. I start out from the
assumption that you have read and completed with success the @ref Windows_Installation tutorial.
assumption that you have read and completed with success the @ref tutorial_windows_install tutorial.
Therefore, before you go any further make sure you have an OpenCV directory that contains the OpenCV
header files plus binaries and you have set the environment variables as @ref described here
\<WindowsSetPathAndEnviromentVariable\>.
header files plus binaries and you have set the environment variables as described here
@ref tutorial_windows_install_path.
![image](images/OpenCV_Install_Directory.jpg)
The OpenCV libraries, distributed by us, on the Microsoft Windows operating system are in a
**D**ynamic **L**inked **L**ibraries (*DLL*). These have the advantage that all the content of the
Dynamic Linked Libraries (*DLL*). These have the advantage that all the content of the
library are loaded only at runtime, on demand, and that countless programs may use the same library
file. This means that if you have ten applications using the OpenCV library, no need to have around
a version for each one of them. Of course you need to have the *dll* of the OpenCV on all systems
where you want to run your application.
Another approach is to use static libraries that have *lib* extensions. You may build these by using
our source files as described in the @ref Windows_Installation tutorial. When you use this the
our source files as described in the @ref tutorial_windows_install tutorial. When you use this the
library will be built-in inside your *exe* file. So there is no chance that the user deletes them,
for some reason. As a drawback your application will be larger one and as, it will take more time to
load it during its startup.
......@@ -103,13 +103,14 @@ further to someone else who has a different OpenCV install path. Moreover, fixin
to manually modifying every explicit path. A more elegant solution is to use the environment
variables. Anything that you put inside a parenthesis started with a dollar sign will be replaced at
runtime with the current environment variables value. Here comes in play the environment variable
setting we already made in our @ref previous tutorial \<WindowsSetPathAndEnviromentVariable\>.
setting we already made in our previous tutorial @ref tutorial_windows_install_path.
Next go to the Linker --\> General and under the *"Additional Library Directories"* add the libs
directory:
@code{.bash}
\f$(OPENCV_DIR)\lib
$(OPENCV_DIR)\lib
@endcode
![image](images/PropertySheetOpenCVLib.jpg)
Then you need to specify the libraries in which the linker should look into. To do this go to the
......@@ -233,5 +234,4 @@ cumbersome task. Luckily, in the Visual Studio there is a menu to automate all t
Specify here the name of the inputs and while you start your application from the Visual Studio
enviroment you have automatic argument passing. In the next introductionary tutorial you'll see an
in-depth explanation of the upper source code: @ref Display_Image.
in-depth explanation of the upper source code: @ref tutorial_display_image.
......@@ -12,9 +12,8 @@ This tutorial assumes that you have the following available:
1. Visual Studio 2012 Professional (or better) with Update 1 installed. Update 1 can be downloaded
[here](http://www.microsoft.com/en-us/download/details.aspx?id=35774).
2. An OpenCV installation on your Windows machine (Tutorial: @ref Windows_Installation).
3. Ability to create and build OpenCV projects in Visual Studio (Tutorial: @ref
Windows_Visual_Studio_How_To).
2. An OpenCV installation on your Windows machine (Tutorial: @ref tutorial_windows_install).
3. Ability to create and build OpenCV projects in Visual Studio (Tutorial: @ref tutorial_windows_visual_studio_Opencv).
Installation
------------
......@@ -178,4 +177,3 @@ Documentation](http://go.microsoft.com/fwlink/?LinkId=285461) for details--you a
documentation page by clicking on the *Help* link in the Image Watch window:
![image](images/help_button.jpg)
......@@ -15,7 +15,7 @@ Including OpenCV library in your iOS project
The OpenCV library comes as a so-called framework, which you can directly drag-and-drop into your
XCode project. Download the latest binary from
\<<http://sourceforge.net/projects/opencvlibrary/files/opencv-ios/>\>. Alternatively follow this
guide @ref iOS-Installation to compile the framework manually. Once you have the framework, just
guide @ref tutorial_ios_install to compile the framework manually. Once you have the framework, just
drag-and-drop into XCode:
![image](images/xcode_hello_ios_framework_drag_and_drop.png)
......@@ -203,4 +203,3 @@ When you are working on grayscale data, turn set grayscale = YES as the YUV colo
directly access the luminance plane.
The Accelerate framework provides some CPU-accelerated DSP filters, which come handy in your case.
Introduction to Support Vector Machines {#tutorial_introduction_to_svm}
=======================================
@todo update this tutorial
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV functions @ref cv::CvSVM::train to build a classifier based on SVMs and @ref
cv::CvSVM::predict to test its performance.
- Use the OpenCV functions @ref cv::ml::SVM::train to build a classifier based on SVMs and @ref
cv::ml::SVM::predict to test its performance.
What is a SVM?
--------------
......@@ -47,7 +49,7 @@ How is the optimal hyperplane computed?
Let's introduce the notation used to define formally a hyperplane:
f(x) = beta_{0} + beta\^{T} x,
\f[f(x) = \beta_{0} + \beta^{T} x,\f]
where \f$\beta\f$ is known as the *weight vector* and \f$\beta_{0}\f$ as the *bias*.
......@@ -57,7 +59,7 @@ Friedman. The optimal hyperplane can be represented in an infinite number of dif
scaling of \f$\beta\f$ and \f$\beta_{0}\f$. As a matter of convention, among all the possible
representations of the hyperplane, the one chosen is
|beta_{0} + beta\^{T} x| = 1
\f[|\beta_{0} + \beta^{T} x| = 1\f]
where \f$x\f$ symbolizes the training examples closest to the hyperplane. In general, the training
examples that are closest to the hyperplane are called **support vectors**. This representation is
......@@ -71,20 +73,18 @@ Now, we use the result of geometry that gives the distance between a point \f$x\
In particular, for the canonical hyperplane, the numerator is equal to one and the distance to the
support vectors is
mathrm{distance}_{text{ support vectors}} = frac{|beta_{0} + beta\^{T} x|}{||beta||} =
frac{1}{||beta||}.
\f[\mathrm{distance}_{\text{ support vectors}} = \frac{|\beta_{0} + \beta^{T} x|}{||\beta||} = \frac{1}{||\beta||}.\f]
Recall that the margin introduced in the previous section, here denoted as \f$M\f$, is twice the
distance to the closest examples:
M = frac{2}{||beta||}
\f[M = \frac{2}{||\beta||}\f]
Finally, the problem of maximizing \f$M\f$ is equivalent to the problem of minimizing a function
\f$L(\beta)\f$ subject to some constraints. The constraints model the requirement for the hyperplane to
classify correctly all the training examples \f$x_{i}\f$. Formally,
min_{beta, beta_{0}} L(beta) = frac{1}{2}||beta||\^{2} text{ subject to } y_{i}(beta\^{T}
x_{i} + beta_{0}) geq 1 text{ } forall i,
\f[\min_{\beta, \beta_{0}} L(\beta) = \frac{1}{2}||\beta||^{2} \text{ subject to } y_{i}(\beta^{T} x_{i} + \beta_{0}) \geq 1 \text{ } \forall i,\f]
where \f$y_{i}\f$ represents each of the labels of the training examples.
......@@ -101,19 +101,20 @@ Explanation
1. **Set up the training data**
The training data of this exercise is formed by a set of labeled 2D-points that belong to one of
two different classes; one of the classes consists of one point and the other of three points.
@code{.cpp}
float labels[4] = {1.0, -1.0, -1.0, -1.0};
float trainingData[4][2] = {{501, 10}, {255, 10}, {501, 255}, {10, 501}};
@endcode
The function @ref cv::CvSVM::train that will be used afterwards requires the training data to be
stored as @ref cv::Mat objects of floats. Therefore, we create these objects from the arrays
defined above:
@code{.cpp}
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);
Mat labelsMat (4, 1, CV_32FC1, labels);
@endcode
The training data of this exercise is formed by a set of labeled 2D-points that belong to one of
two different classes; one of the classes consists of one point and the other of three points.
@code{.cpp}
float labels[4] = {1.0, -1.0, -1.0, -1.0};
float trainingData[4][2] = {{501, 10}, {255, 10}, {501, 255}, {10, 501}};
@endcode
The function @ref cv::ml::SVM::train that will be used afterwards requires the training data to be
stored as @ref cv::Mat objects of floats. Therefore, we create these objects from the arrays
defined above:
@code{.cpp}
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);
Mat labelsMat (4, 1, CV_32FC1, labels);
@endcode
2. **Set up SVM's parameters**
In this tutorial we have introduced the theory of SVMs in the most simple case, when the
......@@ -121,7 +122,7 @@ Mat labelsMat (4, 1, CV_32FC1, labels);
used in a wide variety of problems (e.g. problems with non-linearly separable data, a SVM using
a kernel function to raise the dimensionality of the examples, etc). As a consequence of this,
we have to define some parameters before training the SVM. These parameters are stored in an
object of the class @ref cv::CvSVMParams .
object of the class @ref cv::ml::SVM::Params .
@code{.cpp}
ml::SVM::Params params;
params.svmType = ml::SVM::C_SVC;
......@@ -132,7 +133,8 @@ Mat labelsMat (4, 1, CV_32FC1, labels);
classification (n \f$\geq\f$ 2). This parameter is defined in the attribute
*ml::SVM::Params.svmType*.
@note The important feature of the type of SVM **CvSVM::C_SVC** deals with imperfect separation of classes (i.e. when the training data is non-linearly separable). This feature is not important here since the data is linearly separable and we chose this SVM type only for being the most commonly used.
The important feature of the type of SVM **CvSVM::C_SVC** deals with imperfect separation of classes (i.e. when the training data is non-linearly separable). This feature is not important here since the data is linearly separable and we chose this SVM type only for being the most commonly used.
- *Type of SVM kernel*. We have not talked about kernel functions since they are not
interesting for the training data we are dealing with. Nevertheless, let's explain briefly
now the main idea behind a kernel function. It is a mapping done to the training data to
......@@ -140,6 +142,7 @@ Mat labelsMat (4, 1, CV_32FC1, labels);
increasing the dimensionality of the data and is done efficiently using a kernel function.
We choose here the type **ml::SVM::LINEAR** which means that no mapping is done. This
parameter is defined in the attribute *ml::SVMParams.kernel_type*.
- *Termination criteria of the algorithm*. The SVM training procedure is implemented solving a
constrained quadratic optimization problem in an **iterative** fashion. Here we specify a
maximum number of iterations and a tolerance error so we allow the algorithm to finish in
......@@ -155,17 +158,18 @@ Mat labelsMat (4, 1, CV_32FC1, labels);
CvSVM SVM;
SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
@endcode
4. **Regions classified by the SVM**
The method @ref cv::CvSVM::predict is used to classify an input sample using a trained SVM. In
this example we have used this method in order to color the space depending on the prediction done
by the SVM. In other words, an image is traversed interpreting its pixels as points of the
Cartesian plane. Each of the points is colored depending on the class predicted by the SVM; in
green if it is the class with label 1 and in blue if it is the class with label -1.
@code{.cpp}
Vec3b green(0,255,0), blue (255,0,0);
The method @ref cv::ml::SVM::predict is used to classify an input sample using a trained SVM. In
this example we have used this method in order to color the space depending on the prediction done
by the SVM. In other words, an image is traversed interpreting its pixels as points of the
Cartesian plane. Each of the points is colored depending on the class predicted by the SVM; in
green if it is the class with label 1 and in blue if it is the class with label -1.
@code{.cpp}
Vec3b green(0,255,0), blue (255,0,0);
for (int i = 0; i < image.rows; ++i)
for (int i = 0; i < image.rows; ++i)
for (int j = 0; j < image.cols; ++j)
{
Mat sampleMat = (Mat_<float>(1,2) << i,j);
......@@ -177,13 +181,13 @@ for (int i = 0; i < image.rows; ++i)
if (response == -1)
image.at<Vec3b>(j, i) = blue;
}
@endcode
@endcode
5. **Support vectors**
We use here a couple of methods to obtain information about the support vectors. The method @ref
cv::CvSVM::get_support_vector_count outputs the total number of support vectors used in the
problem and with the method @ref cv::CvSVM::get_support_vector we obtain each of the support
vectors using an index. We have used this methods here to find the training examples that are
We use here a couple of methods to obtain information about the support vectors.
The method @ref cv::ml::SVM::getSupportVectors obtain all of the support
vectors. We have used this methods here to find the training examples that are
support vectors and highlight them.
@code{.cpp}
int c = SVM.get_support_vector_count();
......@@ -194,6 +198,7 @@ for (int i = 0; i < image.rows; ++i)
circle( image, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thickness, lineType);
}
@endcode
Results
-------
......@@ -204,5 +209,4 @@ Results
optimal separating hyperplane.
- Finally the support vectors are shown using gray rings around the training examples.
![image](images/result.png)
![image](images/svm_intro_result.png)
......@@ -182,6 +182,6 @@ Results
* Finally the support vectors are shown using gray rings around the training examples.
.. image:: images/result.png
.. image:: images/svm_intro_result.png
:alt: The seperated planes
:align: center
Support Vector Machines for Non-Linearly Separable Data {#tutorial_non_linear_svms}
=======================================================
@todo update this tutorial
Goal
----
......@@ -8,7 +10,7 @@ In this tutorial you will learn how to:
- Define the optimization problem for SVMs when it is not possible to separate linearly the
training data.
- How to configure the parameters in @ref cv::CvSVMParams to adapt your SVM for this class of
- How to configure the parameters in @ref cv::ml::SVM::Params to adapt your SVM for this class of
problems.
Motivation
......@@ -36,23 +38,22 @@ the biggest margin and the new one of generalizing the training data correctly b
many classification errors.
We start here from the formulation of the optimization problem of finding the hyperplane which
maximizes the **margin** (this is explained in the @ref previous tutorial \<introductiontosvms\>):
maximizes the **margin** (this is explained in the previous tutorial (@ref tutorial_introduction_to_svm):
min_{beta, beta_{0}} L(beta) = frac{1}{2}||beta||\^{2} text{ subject to } y_{i}(beta\^{T}
x_{i} + beta_{0}) geq 1 text{ } forall i
\f[\min_{\beta, \beta_{0}} L(\beta) = \frac{1}{2}||\beta||^{2} \text{ subject to } y_{i}(\beta^{T} x_{i} + \beta_{0}) \geq 1 \text{ } \forall i\f]
There are multiple ways in which this model can be modified so it takes into account the
misclassification errors. For example, one could think of minimizing the same quantity plus a
constant times the number of misclassification errors in the training data, i.e.:
min ||beta||\^{2} + C text{(\# misclassication errors)}
\f[\min ||\beta||^{2} + C \text{(\# misclassication errors)}\f]
However, this one is not a very good solution since, among some other reasons, we do not distinguish
between samples that are misclassified with a small distance to their appropriate decision region or
samples that are not. Therefore, a better solution will take into account the *distance of the
misclassified samples to their correct decision regions*, i.e.:
min ||beta||\^{2} + C text{(distance of misclassified samples to their correct regions)}
\f[\min ||\beta||^{2} + C \text{(distance of misclassified samples to their correct regions)}\f]
For each sample of the training data a new parameter \f$\xi_{i}\f$ is defined. Each one of these
parameters contains the distance from its corresponding training sample to their correct decision
......@@ -70,8 +71,7 @@ misclassified training sample to the margin of its appropriate region.
Finally, the new formulation for the optimization problem is:
min_{beta, beta_{0}} L(beta) = ||beta||\^{2} + C sum_{i} {xi_{i}} text{ subject to }
y_{i}(beta\^{T} x_{i} + beta_{0}) geq 1 - xi_{i} text{ and } xi_{i} geq 0 text{ } forall i
\f[\min_{\beta, \beta_{0}} L(\beta) = ||\beta||^{2} + C \sum_{i} {\xi_{i}} \text{ subject to } y_{i}(\beta^{T} x_{i} + \beta_{0}) \geq 1 - \xi_{i} \text{ and } \xi_{i} \geq 0 \text{ } \forall i\f]
How should the parameter C be chosen? It is obvious that the answer to this question depends on how
the training data is distributed. Although there is no general answer, it is useful to take into
......@@ -101,87 +101,90 @@ Explanation
1. **Set up the training data**
The training data of this exercise is formed by a set of labeled 2D-points that belong to one of
two different classes. To make the exercise more appealing, the training data is generated
randomly using a uniform probability density functions (PDFs).
We have divided the generation of the training data into two main parts.
In the first part we generate data for both classes that is linearly separable.
@code{.cpp}
// Generate random points for the class 1
Mat trainClass = trainData.rowRange(0, nLinearSamples);
// The x coordinate of the points is in [0, 0.4)
Mat c = trainClass.colRange(0, 1);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(0.4 * WIDTH));
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));
// Generate random points for the class 2
trainClass = trainData.rowRange(2*NTRAINING_SAMPLES-nLinearSamples, 2*NTRAINING_SAMPLES);
// The x coordinate of the points is in [0.6, 1]
c = trainClass.colRange(0 , 1);
rng.fill(c, RNG::UNIFORM, Scalar(0.6*WIDTH), Scalar(WIDTH));
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));
@endcode
In the second part we create data for both classes that is non-linearly separable, data that
overlaps.
@code{.cpp}
// Generate random points for the classes 1 and 2
trainClass = trainData.rowRange( nLinearSamples, 2*NTRAINING_SAMPLES-nLinearSamples);
// The x coordinate of the points is in [0.4, 0.6)
c = trainClass.colRange(0,1);
rng.fill(c, RNG::UNIFORM, Scalar(0.4*WIDTH), Scalar(0.6*WIDTH));
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));
@endcode
The training data of this exercise is formed by a set of labeled 2D-points that belong to one of
two different classes. To make the exercise more appealing, the training data is generated
randomly using a uniform probability density functions (PDFs).
We have divided the generation of the training data into two main parts.
In the first part we generate data for both classes that is linearly separable.
@code{.cpp}
// Generate random points for the class 1
Mat trainClass = trainData.rowRange(0, nLinearSamples);
// The x coordinate of the points is in [0, 0.4)
Mat c = trainClass.colRange(0, 1);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(0.4 * WIDTH));
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));
// Generate random points for the class 2
trainClass = trainData.rowRange(2*NTRAINING_SAMPLES-nLinearSamples, 2*NTRAINING_SAMPLES);
// The x coordinate of the points is in [0.6, 1]
c = trainClass.colRange(0 , 1);
rng.fill(c, RNG::UNIFORM, Scalar(0.6*WIDTH), Scalar(WIDTH));
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));
@endcode
In the second part we create data for both classes that is non-linearly separable, data that
overlaps.
@code{.cpp}
// Generate random points for the classes 1 and 2
trainClass = trainData.rowRange( nLinearSamples, 2*NTRAINING_SAMPLES-nLinearSamples);
// The x coordinate of the points is in [0.4, 0.6)
c = trainClass.colRange(0,1);
rng.fill(c, RNG::UNIFORM, Scalar(0.4*WIDTH), Scalar(0.6*WIDTH));
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));
@endcode
2. **Set up SVM's parameters**
@sa
In the previous tutorial @ref introductiontosvms there is an explanation of the atributes of the
class @ref cv::CvSVMParams that we configure here before training the SVM.
@code{.cpp}
CvSVMParams params;
params.svm_type = SVM::C_SVC;
params.C = 0.1;
params.kernel_type = SVM::LINEAR;
params.term_crit = TermCriteria(TermCriteria::ITER, (int)1e7, 1e-6);
@endcode
There are just two differences between the configuration we do here and the one that was done in
the @ref previous tutorial \<introductiontosvms\> that we use as reference.
- *CvSVM::C_SVC*. We chose here a small value of this parameter in order not to punish too much
@sa
In the previous tutorial @ref tutorial_introduction_to_svm there is an explanation of the atributes of the
class @ref cv::ml::SVM::Params that we configure here before training the SVM.
@code{.cpp}
CvSVMParams params;
params.svm_type = SVM::C_SVC;
params.C = 0.1;
params.kernel_type = SVM::LINEAR;
params.term_crit = TermCriteria(TermCriteria::ITER, (int)1e7, 1e-6);
@endcode
There are just two differences between the configuration we do here and the one that was done in
the previous tutorial (tutorial_introduction_to_svm) that we use as reference.
- *CvSVM::C_SVC*. We chose here a small value of this parameter in order not to punish too much
the misclassification errors in the optimization. The idea of doing this stems from the will
of obtaining a solution close to the one intuitively expected. However, we recommend to get a
better insight of the problem by making adjustments to this parameter.
@note Here there are just very few points in the overlapping region between classes, giving a smaller value to **FRAC_LINEAR_SEP** the density of points can be incremented and the impact of the parameter **CvSVM::C_SVC** explored deeply.
@note Here there are just very few points in the overlapping region between classes, giving a smaller value to **FRAC_LINEAR_SEP** the density of points can be incremented and the impact of the parameter **CvSVM::C_SVC** explored deeply.
- *Termination Criteria of the algorithm*. The maximum number of iterations has to be
increased considerably in order to solve correctly a problem with non-linearly separable
training data. In particular, we have increased in five orders of magnitude this value.
3. **Train the SVM**
We call the method @ref cv::CvSVM::train to build the SVM model. Watch out that the training
process may take a quite long time. Have patiance when your run the program.
@code{.cpp}
CvSVM svm;
svm.train(trainData, labels, Mat(), Mat(), params);
@endcode
We call the method @ref cv::ml::SVM::train to build the SVM model. Watch out that the training
process may take a quite long time. Have patiance when your run the program.
@code{.cpp}
CvSVM svm;
svm.train(trainData, labels, Mat(), Mat(), params);
@endcode
4. **Show the Decision Regions**
The method @ref cv::CvSVM::predict is used to classify an input sample using a trained SVM. In
this example we have used this method in order to color the space depending on the prediction done
by the SVM. In other words, an image is traversed interpreting its pixels as points of the
Cartesian plane. Each of the points is colored depending on the class predicted by the SVM; in
dark green if it is the class with label 1 and in dark blue if it is the class with label 2.
@code{.cpp}
Vec3b green(0,100,0), blue (100,0,0);
for (int i = 0; i < I.rows; ++i)
The method @ref cv::ml::SVM::predict is used to classify an input sample using a trained SVM. In
this example we have used this method in order to color the space depending on the prediction done
by the SVM. In other words, an image is traversed interpreting its pixels as points of the
Cartesian plane. Each of the points is colored depending on the class predicted by the SVM; in
dark green if it is the class with label 1 and in dark blue if it is the class with label 2.
@code{.cpp}
Vec3b green(0,100,0), blue (100,0,0);
for (int i = 0; i < I.rows; ++i)
for (int j = 0; j < I.cols; ++j)
{
Mat sampleMat = (Mat_<float>(1,2) << i, j);
......@@ -190,49 +193,51 @@ for (int i = 0; i < I.rows; ++i)
if (response == 1) I.at<Vec3b>(j, i) = green;
else if (response == 2) I.at<Vec3b>(j, i) = blue;
}
@endcode
@endcode
5. **Show the training data**
The method @ref cv::circle is used to show the samples that compose the training data. The samples
of the class labeled with 1 are shown in light green and in light blue the samples of the class
labeled with 2.
@code{.cpp}
int thick = -1;
int lineType = 8;
float px, py;
// Class 1
for (int i = 0; i < NTRAINING_SAMPLES; ++i)
{
The method @ref cv::circle is used to show the samples that compose the training data. The samples
of the class labeled with 1 are shown in light green and in light blue the samples of the class
labeled with 2.
@code{.cpp}
int thick = -1;
int lineType = 8;
float px, py;
// Class 1
for (int i = 0; i < NTRAINING_SAMPLES; ++i)
{
px = trainData.at<float>(i,0);
py = trainData.at<float>(i,1);
circle(I, Point( (int) px, (int) py ), 3, Scalar(0, 255, 0), thick, lineType);
}
// Class 2
for (int i = NTRAINING_SAMPLES; i <2*NTRAINING_SAMPLES; ++i)
{
}
// Class 2
for (int i = NTRAINING_SAMPLES; i <2*NTRAINING_SAMPLES; ++i)
{
px = trainData.at<float>(i,0);
py = trainData.at<float>(i,1);
circle(I, Point( (int) px, (int) py ), 3, Scalar(255, 0, 0), thick, lineType);
}
@endcode
}
@endcode
6. **Support vectors**
We use here a couple of methods to obtain information about the support vectors. The method @ref
cv::CvSVM::get_support_vector_count outputs the total number of support vectors used in the
problem and with the method @ref cv::CvSVM::get_support_vector we obtain each of the support
vectors using an index. We have used this methods here to find the training examples that are
support vectors and highlight them.
@code{.cpp}
thick = 2;
lineType = 8;
int x = svm.get_support_vector_count();
for (int i = 0; i < x; ++i)
{
We use here a couple of methods to obtain information about the support vectors. The method
@ref cv::ml::SVM::getSupportVectors obtain all support vectors.
We have used this methods here to find the training examples that are
support vectors and highlight them.
@code{.cpp}
thick = 2;
lineType = 8;
int x = svm.get_support_vector_count();
for (int i = 0; i < x; ++i)
{
const float* v = svm.get_support_vector(i);
circle( I, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thick, lineType);
}
@endcode
}
@endcode
Results
-------
......@@ -245,14 +250,12 @@ Results
and some blue points lay on the green one.
- Finally the support vectors are shown using gray rings around the training examples.
![image](images/result.png)
![image](images/svm_non_linear_result.png)
You may observe a runtime instance of this on the [YouTube
here](https://www.youtube.com/watch?v=vFv2yPcSo-Q).
You may observe a runtime instance of this on the [YouTube here](https://www.youtube.com/watch?v=vFv2yPcSo-Q).
\htmlonly
<div align="center">
<iframe title="Support Vector Machines for Non-Linearly Separable Data" width="560" height="349" src="http://www.youtube.com/embed/vFv2yPcSo-Q?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>
\endhtmlonly
......@@ -218,7 +218,7 @@ Results
* Finally the support vectors are shown using gray rings around the training examples.
.. image:: images/result.png
.. image:: images/svm_non_linear_result.png
:alt: Training data and decision regions given by the SVM
:width: 300pt
:align: center
......
......@@ -8,8 +8,8 @@ In this tutorial you will learn how to:
- Use the @ref cv::CascadeClassifier class to detect objects in a video stream. Particularly, we
will use the functions:
- @ref cv::load to load a .xml classifier file. It can be either a Haar or a LBP classifer
- @ref cv::detectMultiScale to perform the detection.
- @ref cv::CascadeClassifier::load to load a .xml classifier file. It can be either a Haar or a LBP classifer
- @ref cv::CascadeClassifier::detectMultiScale to perform the detection.
Theory
------
......@@ -126,5 +126,3 @@ Result
detection. For the eyes we keep using the file used in the tutorial.
![image](images/Cascade_Classifier_Tutorial_Result_LBP.jpg)
......@@ -43,8 +43,8 @@ file or a sequence of images.
-
Two different methods are used to generate two foreground masks:
1. @ref cv::MOG
2. @ref cv::MOG2
1. @ref cv::bgsegm::BackgroundSubtractorMOG
2. @ref cv::bgsegm::BackgroundSubtractorMOG2
The results as well as the input data are shown on the screen.
@code{.cpp}
......@@ -389,4 +389,3 @@ References
- Antoine Vacavant, Thierry Chateau, Alexis Wilhelm and Laurent Lequievre. A Benchmark Dataset for
Foreground/Background Extraction. In ACCV 2012, Workshop: Background Models Challenge, LNCS
7728, 291-300. November 2012, Daejeon, Korea.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment