resolved conflicts, updated retina class interface and optimized a heavy retinacolor process
@@ -12,8 +12,8 @@ For the distortion OpenCV takes into account the radial and tangential factors.
|
||||
|
||||
.. math::
|
||||
|
||||
x_{corrected} = x( 1 + k_1 r^2 + k_2 r^4 + k^3 r^6) \\
|
||||
y_{corrected} = y( 1 + k_1 r^2 + k_2 r^4 + k^3 r^6)
|
||||
x_{corrected} = x( 1 + k_1 r^2 + k_2 r^4 + k_3 r^6) \\
|
||||
y_{corrected} = y( 1 + k_1 r^2 + k_2 r^4 + k_3 r^6)
|
||||
|
||||
So for an old pixel point at :math:`(x,y)` coordinate in the input image, for a corrected output image its position will be :math:`(x_{corrected} y_{corrected})` . The presence of the radial distortion manifests in form of the "barrel" or "fish-eye" effect.
|
||||
|
||||
|
@@ -31,7 +31,7 @@ The proposed model originates from Jeanny Herault's research at `Gipsa <http://w
|
||||
|
||||
The first two points are illustrated below :
|
||||
|
||||
In the figure below, the OpenEXR image sample *CrissyField.exr*, a High Dynamic Range image is shown. In order to make it visible on this web-page, the original input image is linearly rescaled to the classical image luminance range [0-255] and is converted to 8bit/channel format. Such strong conversion hides many details because of too strong local contrasts. Furthermore, noise energy is also strong and pollutes visual information.
|
||||
In the figure below, the OpenEXR image sample *CrissyField.exr*, a High Dynamic Range image is shown. In order to make it visible on this web-page, the original input image is linearly rescaled to the classical image luminance range [0-255] and is converted to 8bit/channel format. Such strong conversion hides many details because of too strong local contrasts. Furthermore, noise energy is also strong and pollutes visual information.
|
||||
|
||||
.. image:: images/retina_TreeHdr_small.jpg
|
||||
:alt: A High dynamic range image linearly rescaled within range [0-255].
|
||||
@@ -57,7 +57,7 @@ The retina model presents two outputs that benefit from the above cited behavior
|
||||
|
||||
**NOTE :** regarding the proposed model, contrary to the real retina, we apply these two channels on the entire input images using the same resolution. This allows enhanced visual details and motion information to be extracted on all the considered images... but remember, that these two channels are complementary. For example, if Magnocellular channel gives strong energy in an area, then, the Parvocellular channel is certainly blurred there since there is a transient event.
|
||||
|
||||
As an illustration, we apply in the following the retina model on a webcam video stream of a dark visual scene. In this visual scene, captured in an amphitheater of the university, some students are moving while talking to the teacher.
|
||||
As an illustration, we apply in the following the retina model on a webcam video stream of a dark visual scene. In this visual scene, captured in an amphitheater of the university, some students are moving while talking to the teacher.
|
||||
|
||||
In this video sequence, because of the dark ambiance, signal to noise ratio is low and color artifacts are present on visual features edges because of the low quality image capture tool-chain.
|
||||
|
||||
@@ -81,7 +81,7 @@ Retina use case
|
||||
===============
|
||||
|
||||
This model can be used basically for spatio-temporal video effects but also in the aim of :
|
||||
|
||||
|
||||
* performing texture analysis with enhanced signal to noise ratio and enhanced details robust against input images luminance ranges (check out the Parvocellular retina channel output)
|
||||
|
||||
* performing motion analysis also taking benefit of the previously cited properties.
|
||||
@@ -105,13 +105,13 @@ Code tutorial
|
||||
|
||||
Please refer to the original tutorial source code in file *opencv_folder/samples/cpp/tutorial_code/contrib/retina_tutorial.cpp*.
|
||||
|
||||
To compile it, assuming OpenCV is correctly installed, use the following command. It requires the opencv_core *(cv::Mat and friends objects management)*, opencv_highgui *(display and image/video read)* and opencv_contrib *(Retina description)* libraries to compile.
|
||||
To compile it, assuming OpenCV is correctly installed, use the following command. It requires the opencv_core *(cv::Mat and friends objects management)*, opencv_highgui *(display and image/video read)* and opencv_contrib *(Retina description)* libraries to compile.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
// compile
|
||||
gcc retina_tutorial.cpp -o Retina_tuto -lopencv_core -lopencv_highgui -lopencv_contrib
|
||||
|
||||
|
||||
// Run commands : add 'log' as a last parameter to apply a spatial log sampling (simulates retina sampling)
|
||||
// run on webcam
|
||||
./Retina_tuto -video
|
||||
@@ -228,7 +228,7 @@ Once all input parameters are processed, a first image should have been loaded,
|
||||
Now, everything is ready to run the retina model. I propose here to allocate a retina instance and to manage the eventual log sampling option. The Retina constructor expects at least a cv::Size object that shows the input data size that will have to be managed. One can activate other options such as color and its related color multiplexing strategy (here Bayer multiplexing is chosen using enum cv::RETINA_COLOR_BAYER). If using log sampling, the image reduction factor (smaller output images) and log sampling strengh can be adjusted.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
|
||||
// pointer to a retina object
|
||||
cv::Ptr<cv::Retina> myRetina;
|
||||
|
||||
@@ -240,7 +240,6 @@ Now, everything is ready to run the retina model. I propose here to allocate a r
|
||||
else// -> else allocate "classical" retina :
|
||||
myRetina = cv::createRetina(inputFrame.size());
|
||||
|
||||
|
||||
Once done, the proposed code writes a default xml file that contains the default parameters of the retina. This is useful to make your own config using this template. Here generated template xml file is called *RetinaDefaultParameters.xml*.
|
||||
|
||||
.. code-block:: cpp
|
||||
@@ -259,7 +258,7 @@ It is not required here but just to show it is possible, you can reset the retin
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
// reset all retina buffers (imagine you close your eyes for a long time)
|
||||
// reset all retina buffers (imagine you close your eyes for a long time)
|
||||
myRetina->clearBuffers();
|
||||
|
||||
Now, it is time to run the retina ! First create some output buffers ready to receive the two retina channels outputs
|
||||
@@ -292,7 +291,7 @@ Then, run retina in a loop, load new frames from video sequence if necessary and
|
||||
cv::waitKey(10);
|
||||
}
|
||||
|
||||
That's done ! But if you want to secure the system, take care and manage Exceptions. The retina can throw some when it sees irrelevant data (no input frame, wrong setup, etc.).
|
||||
That's done ! But if you want to secure the system, take care and manage Exceptions. The retina can throw some when it sees irrelevant data (no input frame, wrong setup, etc.).
|
||||
Then, i recommend to surround all the retina code by a try/catch system like this :
|
||||
|
||||
.. code-block:: cpp
|
||||
@@ -317,7 +316,7 @@ Retina parameters, what to do ?
|
||||
|
||||
First, it is recommended to read the reference paper :
|
||||
|
||||
* Benoit A., Caplier A., Durette B., Herault, J., *"Using Human Visual System Modeling For Bio-Inspired Low Level Image Processing"*, Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773. DOI <http://dx.doi.org/10.1016/j.cviu.2010.01.011>
|
||||
* Benoit A., Caplier A., Durette B., Herault, J., *"Using Human Visual System Modeling For Bio-Inspired Low Level Image Processing"*, Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773. DOI <http://dx.doi.org/10.1016/j.cviu.2010.01.011>
|
||||
|
||||
Once done open the configuration file *RetinaDefaultParameters.xml* generated by the demo and let's have a look at it.
|
||||
|
||||
@@ -346,7 +345,6 @@ Once done open the configuration file *RetinaDefaultParameters.xml* generated by
|
||||
<localAdaptintegration_k>7.</localAdaptintegration_k></IPLmagno>
|
||||
</opencv_storage>
|
||||
|
||||
|
||||
Here are some hints but actually, the best parameter setup depends more on what you want to do with the retina rather than the images input that you give to retina. Apart from the more specific case of High Dynamic Range images (HDR) that require more specific setup for specific luminance compression objective, the retina behaviors should be rather stable from content to content. Note that OpenCV is able to manage such HDR format thanks to the OpenEXR images compatibility.
|
||||
|
||||
Then, if the application target requires details enhancement prior to specific image processing, you need to know if mean luminance information is required or not. If not, the the retina can cancel or significantly reduce its energy thus giving more visibility to higher spatial frequency details.
|
||||
@@ -381,7 +379,7 @@ This parameter set tunes the neural network connected to the photo-receptors, th
|
||||
|
||||
* **horizontalCellsGain** here is a critical parameter ! If you are not interested by the mean luminance and focus on details enhancement, then, set to zero. But if you want to keep some environment luminance data, let some low spatial frequencies pass into the system and set a higher value (<1).
|
||||
|
||||
* **hcellsTemporalConstant** similar to photo-receptors, this acts on the temporal constant of a low pass temporal filter that smooths input data. Here, a high value generates a high retina after effect while a lower value makes the retina more reactive. this value should be lower than **photoreceptorsTemporalConstant** to limit strong retina after effects.
|
||||
* **hcellsTemporalConstant** similar to photo-receptors, this acts on the temporal constant of a low pass temporal filter that smooths input data. Here, a high value generates a high retina after effect while a lower value makes the retina more reactive. This value should be lower than **photoreceptorsTemporalConstant** to limit strong retina after effects.
|
||||
|
||||
* **hcellsSpatialConstant** is the spatial constant of the low pass filter of these cells filter. It specifies the lowest spatial frequency allowed in the following. Visually, a high value leads to very low spatial frequencies processing and leads to salient halo effects. Lower values reduce this effect but the limit is : do not go lower than the value of **photoreceptorsSpatialConstant**. Those 2 parameters actually specify the spatial band-pass of the retina.
|
||||
|
||||
@@ -405,7 +403,7 @@ Once image information is cleaned, this channel acts as a high pass temporal fil
|
||||
|
||||
* **parasolCells_k** the spatial constant of the spatial filtering effect, set it at a high value to favor low spatial frequency signals that are lower subject to residual noise.
|
||||
|
||||
* **amacrinCellsTemporalCutFrequency** specifies the temporal constant of the high pass filter. High values let slow transient events to be selected.
|
||||
* **amacrinCellsTemporalCutFrequency** specifies the temporal constant of the high pass filter. High values let slow transient events to be selected.
|
||||
|
||||
* **V0CompressionParameter** specifies the strength of the log compression. Similar behaviors to previous description but here it enforces sensitivity of transient events.
|
||||
|
||||
@@ -413,4 +411,3 @@ Once image information is cleaned, this channel acts as a high pass temporal fil
|
||||
|
||||
* **localAdaptintegration_k** specifies the size of the area on which local adaptation is performed. Low values lead to short range local adaptation (higher sensitivity to noise), high values secure log compression.
|
||||
|
||||
|
||||
|
@@ -35,8 +35,7 @@ As usual, after the not-so-lengthy explanation, let's go to the code:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <cv.h>
|
||||
#include <highgui.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
@@ -53,8 +52,8 @@ As usual, after the not-so-lengthy explanation, let's go to the code:
|
||||
std::cout<<"* Enter alpha [0-1]: ";
|
||||
std::cin>>input;
|
||||
|
||||
/// We use the alpha provided by the user iff it is between 0 and 1
|
||||
if( alpha >= 0 && alpha <= 1 )
|
||||
/// We use the alpha provided by the user if it is between 0 and 1
|
||||
if( input >= 0.0 && input <= 1.0 )
|
||||
{ alpha = input; }
|
||||
|
||||
/// Read image ( same size, same type )
|
||||
|
@@ -31,15 +31,15 @@ Point
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
Point pt;
|
||||
pt.x = 10;
|
||||
pt.y = 8;
|
||||
Point pt;
|
||||
pt.x = 10;
|
||||
pt.y = 8;
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
Point pt = Point(10, 8);
|
||||
Point pt = Point(10, 8);
|
||||
|
||||
Scalar
|
||||
-------
|
||||
@@ -49,7 +49,7 @@ Scalar
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
Scalar( a, b, c )
|
||||
Scalar( a, b, c )
|
||||
|
||||
We would be defining a RGB color such as: *Red = c*, *Green = b* and *Blue = a*
|
||||
|
||||
@@ -65,51 +65,51 @@ Explanation
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/// Windows names
|
||||
char atom_window[] = "Drawing 1: Atom";
|
||||
char rook_window[] = "Drawing 2: Rook";
|
||||
/// Windows names
|
||||
char atom_window[] = "Drawing 1: Atom";
|
||||
char rook_window[] = "Drawing 2: Rook";
|
||||
|
||||
/// Create black empty images
|
||||
Mat atom_image = Mat::zeros( w, w, CV_8UC3 );
|
||||
Mat rook_image = Mat::zeros( w, w, CV_8UC3 );
|
||||
/// Create black empty images
|
||||
Mat atom_image = Mat::zeros( w, w, CV_8UC3 );
|
||||
Mat rook_image = Mat::zeros( w, w, CV_8UC3 );
|
||||
|
||||
#. We created functions to draw different geometric shapes. For instance, to draw the atom we used *MyEllipse* and *MyFilledCircle*:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/// 1. Draw a simple atom:
|
||||
/// 1. Draw a simple atom:
|
||||
|
||||
/// 1.a. Creating ellipses
|
||||
MyEllipse( atom_image, 90 );
|
||||
MyEllipse( atom_image, 0 );
|
||||
MyEllipse( atom_image, 45 );
|
||||
MyEllipse( atom_image, -45 );
|
||||
/// 1.a. Creating ellipses
|
||||
MyEllipse( atom_image, 90 );
|
||||
MyEllipse( atom_image, 0 );
|
||||
MyEllipse( atom_image, 45 );
|
||||
MyEllipse( atom_image, -45 );
|
||||
|
||||
/// 1.b. Creating circles
|
||||
MyFilledCircle( atom_image, Point( w/2.0, w/2.0) );
|
||||
/// 1.b. Creating circles
|
||||
MyFilledCircle( atom_image, Point( w/2.0, w/2.0) );
|
||||
|
||||
#. And to draw the rook we employed *MyLine*, *rectangle* and a *MyPolygon*:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/// 2. Draw a rook
|
||||
/// 2. Draw a rook
|
||||
|
||||
/// 2.a. Create a convex polygon
|
||||
MyPolygon( rook_image );
|
||||
/// 2.a. Create a convex polygon
|
||||
MyPolygon( rook_image );
|
||||
|
||||
/// 2.b. Creating rectangles
|
||||
rectangle( rook_image,
|
||||
Point( 0, 7*w/8.0 ),
|
||||
Point( w, w),
|
||||
Scalar( 0, 255, 255 ),
|
||||
-1,
|
||||
8 );
|
||||
/// 2.b. Creating rectangles
|
||||
rectangle( rook_image,
|
||||
Point( 0, 7*w/8.0 ),
|
||||
Point( w, w),
|
||||
Scalar( 0, 255, 255 ),
|
||||
-1,
|
||||
8 );
|
||||
|
||||
/// 2.c. Create a few lines
|
||||
MyLine( rook_image, Point( 0, 15*w/16 ), Point( w, 15*w/16 ) );
|
||||
MyLine( rook_image, Point( w/4, 7*w/8 ), Point( w/4, w ) );
|
||||
MyLine( rook_image, Point( w/2, 7*w/8 ), Point( w/2, w ) );
|
||||
MyLine( rook_image, Point( 3*w/4, 7*w/8 ), Point( 3*w/4, w ) );
|
||||
/// 2.c. Create a few lines
|
||||
MyLine( rook_image, Point( 0, 15*w/16 ), Point( w, 15*w/16 ) );
|
||||
MyLine( rook_image, Point( w/4, 7*w/8 ), Point( w/4, w ) );
|
||||
MyLine( rook_image, Point( w/2, 7*w/8 ), Point( w/2, w ) );
|
||||
MyLine( rook_image, Point( 3*w/4, 7*w/8 ), Point( 3*w/4, w ) );
|
||||
|
||||
#. Let's check what is inside each of these functions:
|
||||
|
||||
@@ -117,17 +117,15 @@ Explanation
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void MyLine( Mat img, Point start, Point end )
|
||||
{
|
||||
int thickness = 2;
|
||||
int lineType = 8;
|
||||
line( img,
|
||||
start,
|
||||
end,
|
||||
Scalar( 0, 0, 0 ),
|
||||
thickness,
|
||||
lineType );
|
||||
}
|
||||
void MyLine( Mat img, Point start, Point end )
|
||||
{
|
||||
int thickness = 2;
|
||||
int lineType = 8;
|
||||
line( img, start, end,
|
||||
Scalar( 0, 0, 0 ),
|
||||
thickness,
|
||||
lineType );
|
||||
}
|
||||
|
||||
As we can see, *MyLine* just call the function :line:`line <>`, which does the following:
|
||||
|
||||
@@ -143,32 +141,32 @@ Explanation
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void MyEllipse( Mat img, double angle )
|
||||
{
|
||||
int thickness = 2;
|
||||
int lineType = 8;
|
||||
void MyEllipse( Mat img, double angle )
|
||||
{
|
||||
int thickness = 2;
|
||||
int lineType = 8;
|
||||
|
||||
ellipse( img,
|
||||
Point( w/2.0, w/2.0 ),
|
||||
Size( w/4.0, w/16.0 ),
|
||||
angle,
|
||||
0,
|
||||
360,
|
||||
Scalar( 255, 0, 0 ),
|
||||
thickness,
|
||||
lineType );
|
||||
}
|
||||
ellipse( img,
|
||||
Point( w/2.0, w/2.0 ),
|
||||
Size( w/4.0, w/16.0 ),
|
||||
angle,
|
||||
0,
|
||||
360,
|
||||
Scalar( 255, 0, 0 ),
|
||||
thickness,
|
||||
lineType );
|
||||
}
|
||||
|
||||
From the code above, we can observe that the function :ellipse:`ellipse <>` draws an ellipse such that:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* The ellipse is displayed in the image **img**
|
||||
* The ellipse center is located in the point **(w/2.0, w/2.0)** and is enclosed in a box of size **(w/4.0, w/16.0)**
|
||||
* The ellipse is rotated **angle** degrees
|
||||
* The ellipse extends an arc between **0** and **360** degrees
|
||||
* The color of the figure will be **Scalar( 255, 255, 0)** which means blue in RGB value.
|
||||
* The ellipse's **thickness** is 2.
|
||||
* The ellipse is displayed in the image **img**
|
||||
* The ellipse center is located in the point **(w/2.0, w/2.0)** and is enclosed in a box of size **(w/4.0, w/16.0)**
|
||||
* The ellipse is rotated **angle** degrees
|
||||
* The ellipse extends an arc between **0** and **360** degrees
|
||||
* The color of the figure will be **Scalar( 255, 255, 0)** which means blue in RGB value.
|
||||
* The ellipse's **thickness** is 2.
|
||||
|
||||
|
||||
* *MyFilledCircle*
|
||||
@@ -176,17 +174,17 @@ Explanation
|
||||
.. code-block:: cpp
|
||||
|
||||
void MyFilledCircle( Mat img, Point center )
|
||||
{
|
||||
int thickness = -1;
|
||||
int lineType = 8;
|
||||
{
|
||||
int thickness = -1;
|
||||
int lineType = 8;
|
||||
|
||||
circle( img,
|
||||
center,
|
||||
w/32.0,
|
||||
Scalar( 0, 0, 255 ),
|
||||
thickness,
|
||||
lineType );
|
||||
}
|
||||
circle( img,
|
||||
center,
|
||||
w/32.0,
|
||||
Scalar( 0, 0, 255 ),
|
||||
thickness,
|
||||
lineType );
|
||||
}
|
||||
|
||||
Similar to the ellipse function, we can observe that *circle* receives as arguments:
|
||||
|
||||
@@ -202,43 +200,43 @@ Explanation
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void MyPolygon( Mat img )
|
||||
{
|
||||
int lineType = 8;
|
||||
void MyPolygon( Mat img )
|
||||
{
|
||||
int lineType = 8;
|
||||
|
||||
/** Create some points */
|
||||
Point rook_points[1][20];
|
||||
rook_points[0][0] = Point( w/4.0, 7*w/8.0 );
|
||||
rook_points[0][1] = Point( 3*w/4.0, 7*w/8.0 );
|
||||
rook_points[0][2] = Point( 3*w/4.0, 13*w/16.0 );
|
||||
rook_points[0][3] = Point( 11*w/16.0, 13*w/16.0 );
|
||||
rook_points[0][4] = Point( 19*w/32.0, 3*w/8.0 );
|
||||
rook_points[0][5] = Point( 3*w/4.0, 3*w/8.0 );
|
||||
rook_points[0][6] = Point( 3*w/4.0, w/8.0 );
|
||||
rook_points[0][7] = Point( 26*w/40.0, w/8.0 );
|
||||
rook_points[0][8] = Point( 26*w/40.0, w/4.0 );
|
||||
rook_points[0][9] = Point( 22*w/40.0, w/4.0 );
|
||||
rook_points[0][10] = Point( 22*w/40.0, w/8.0 );
|
||||
rook_points[0][11] = Point( 18*w/40.0, w/8.0 );
|
||||
rook_points[0][12] = Point( 18*w/40.0, w/4.0 );
|
||||
rook_points[0][13] = Point( 14*w/40.0, w/4.0 );
|
||||
rook_points[0][14] = Point( 14*w/40.0, w/8.0 );
|
||||
rook_points[0][15] = Point( w/4.0, w/8.0 );
|
||||
rook_points[0][16] = Point( w/4.0, 3*w/8.0 );
|
||||
rook_points[0][17] = Point( 13*w/32.0, 3*w/8.0 );
|
||||
rook_points[0][18] = Point( 5*w/16.0, 13*w/16.0 );
|
||||
rook_points[0][19] = Point( w/4.0, 13*w/16.0) ;
|
||||
/** Create some points */
|
||||
Point rook_points[1][20];
|
||||
rook_points[0][0] = Point( w/4.0, 7*w/8.0 );
|
||||
rook_points[0][1] = Point( 3*w/4.0, 7*w/8.0 );
|
||||
rook_points[0][2] = Point( 3*w/4.0, 13*w/16.0 );
|
||||
rook_points[0][3] = Point( 11*w/16.0, 13*w/16.0 );
|
||||
rook_points[0][4] = Point( 19*w/32.0, 3*w/8.0 );
|
||||
rook_points[0][5] = Point( 3*w/4.0, 3*w/8.0 );
|
||||
rook_points[0][6] = Point( 3*w/4.0, w/8.0 );
|
||||
rook_points[0][7] = Point( 26*w/40.0, w/8.0 );
|
||||
rook_points[0][8] = Point( 26*w/40.0, w/4.0 );
|
||||
rook_points[0][9] = Point( 22*w/40.0, w/4.0 );
|
||||
rook_points[0][10] = Point( 22*w/40.0, w/8.0 );
|
||||
rook_points[0][11] = Point( 18*w/40.0, w/8.0 );
|
||||
rook_points[0][12] = Point( 18*w/40.0, w/4.0 );
|
||||
rook_points[0][13] = Point( 14*w/40.0, w/4.0 );
|
||||
rook_points[0][14] = Point( 14*w/40.0, w/8.0 );
|
||||
rook_points[0][15] = Point( w/4.0, w/8.0 );
|
||||
rook_points[0][16] = Point( w/4.0, 3*w/8.0 );
|
||||
rook_points[0][17] = Point( 13*w/32.0, 3*w/8.0 );
|
||||
rook_points[0][18] = Point( 5*w/16.0, 13*w/16.0 );
|
||||
rook_points[0][19] = Point( w/4.0, 13*w/16.0) ;
|
||||
|
||||
const Point* ppt[1] = { rook_points[0] };
|
||||
int npt[] = { 20 };
|
||||
const Point* ppt[1] = { rook_points[0] };
|
||||
int npt[] = { 20 };
|
||||
|
||||
fillPoly( img,
|
||||
ppt,
|
||||
npt,
|
||||
1,
|
||||
Scalar( 255, 255, 255 ),
|
||||
lineType );
|
||||
}
|
||||
fillPoly( img,
|
||||
ppt,
|
||||
npt,
|
||||
1,
|
||||
Scalar( 255, 255, 255 ),
|
||||
lineType );
|
||||
}
|
||||
|
||||
To draw a filled polygon we use the function :fill_poly:`fillPoly <>`. We note that:
|
||||
|
||||
@@ -254,12 +252,11 @@ Explanation
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
rectangle( rook_image,
|
||||
Point( 0, 7*w/8.0 ),
|
||||
Point( w, w),
|
||||
Scalar( 0, 255, 255 ),
|
||||
-1,
|
||||
8 );
|
||||
rectangle( rook_image,
|
||||
Point( 0, 7*w/8.0 ),
|
||||
Point( w, w),
|
||||
Scalar( 0, 255, 255 ),
|
||||
-1, 8 );
|
||||
|
||||
Finally we have the :rectangle:`rectangle <>` function (we did not create a special function for this guy). We note that:
|
||||
|
||||
|
@@ -11,17 +11,15 @@ In this tutorial you will learn how to:
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
+ Access pixel values
|
||||
|
||||
+ Initialize a matrix with zeros
|
||||
|
||||
+ Learn what :saturate_cast:`saturate_cast <>` does and why it is useful
|
||||
|
||||
+ Get some cool info about pixel transformations
|
||||
|
||||
Theory
|
||||
=======
|
||||
|
||||
.. note::
|
||||
|
||||
The explanation below belongs to the book `Computer Vision: Algorithms and Applications <http://szeliski.org/Book/>`_ by Richard Szeliski
|
||||
|
||||
Image Processing
|
||||
@@ -38,7 +36,7 @@ Image Processing
|
||||
|
||||
|
||||
Pixel Transforms
|
||||
^^^^^^^^^^^^^^^^^
|
||||
-----------------
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
@@ -47,7 +45,7 @@ Pixel Transforms
|
||||
* Examples of such operators include *brightness and contrast adjustments* as well as color correction and transformations.
|
||||
|
||||
Brightness and contrast adjustments
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
------------------------------------
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
@@ -70,14 +68,11 @@ Brightness and contrast adjustments
|
||||
Code
|
||||
=====
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* The following code performs the operation :math:`g(i,j) = \alpha \cdot f(i,j) + \beta` :
|
||||
* The following code performs the operation :math:`g(i,j) = \alpha \cdot f(i,j) + \beta` :
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <cv.h>
|
||||
#include <highgui.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
@@ -87,38 +82,37 @@ Code
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
/// Read image given by user
|
||||
Mat image = imread( argv[1] );
|
||||
Mat new_image = Mat::zeros( image.size(), image.type() );
|
||||
/// Read image given by user
|
||||
Mat image = imread( argv[1] );
|
||||
Mat new_image = Mat::zeros( image.size(), image.type() );
|
||||
|
||||
/// Initialize values
|
||||
std::cout<<" Basic Linear Transforms "<<std::endl;
|
||||
std::cout<<"-------------------------"<<std::endl;
|
||||
std::cout<<"* Enter the alpha value [1.0-3.0]: ";std::cin>>alpha;
|
||||
std::cout<<"* Enter the beta value [0-100]: "; std::cin>>beta;
|
||||
/// Initialize values
|
||||
std::cout<<" Basic Linear Transforms "<<std::endl;
|
||||
std::cout<<"-------------------------"<<std::endl;
|
||||
std::cout<<"* Enter the alpha value [1.0-3.0]: ";std::cin>>alpha;
|
||||
std::cout<<"* Enter the beta value [0-100]: "; std::cin>>beta;
|
||||
|
||||
/// Do the operation new_image(i,j) = alpha*image(i,j) + beta
|
||||
for( int y = 0; y < image.rows; y++ )
|
||||
{ for( int x = 0; x < image.cols; x++ )
|
||||
{ for( int c = 0; c < 3; c++ )
|
||||
{
|
||||
new_image.at<Vec3b>(y,x)[c] =
|
||||
saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta );
|
||||
}
|
||||
}
|
||||
/// Do the operation new_image(i,j) = alpha*image(i,j) + beta
|
||||
for( int y = 0; y < image.rows; y++ ) {
|
||||
for( int x = 0; x < image.cols; x++ ) {
|
||||
for( int c = 0; c < 3; c++ ) {
|
||||
new_image.at<Vec3b>(y,x)[c] =
|
||||
saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create Windows
|
||||
namedWindow("Original Image", 1);
|
||||
namedWindow("New Image", 1);
|
||||
/// Create Windows
|
||||
namedWindow("Original Image", 1);
|
||||
namedWindow("New Image", 1);
|
||||
|
||||
/// Show stuff
|
||||
imshow("Original Image", image);
|
||||
imshow("New Image", new_image);
|
||||
/// Show stuff
|
||||
imshow("Original Image", image);
|
||||
imshow("New Image", new_image);
|
||||
|
||||
/// Wait until user press some key
|
||||
waitKey();
|
||||
return 0;
|
||||
/// Wait until user press some key
|
||||
waitKey();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Explanation
|
||||
@@ -155,13 +149,14 @@ Explanation
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
for( int y = 0; y < image.rows; y++ )
|
||||
{ for( int x = 0; x < image.cols; x++ )
|
||||
{ for( int c = 0; c < 3; c++ )
|
||||
{ new_image.at<Vec3b>(y,x)[c] =
|
||||
saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta ); }
|
||||
}
|
||||
}
|
||||
for( int y = 0; y < image.rows; y++ ) {
|
||||
for( int x = 0; x < image.cols; x++ ) {
|
||||
for( int c = 0; c < 3; c++ ) {
|
||||
new_image.at<Vec3b>(y,x)[c] =
|
||||
saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Notice the following:
|
||||
|
||||
@@ -209,6 +204,6 @@ Result
|
||||
|
||||
* We get this:
|
||||
|
||||
.. image:: images/Basic_Linear_Transform_Tutorial_Result_0.jpg
|
||||
:alt: Basic Linear Transform - Final Result
|
||||
:align: center
|
||||
.. image:: images/Basic_Linear_Transform_Tutorial_Result_0.jpg
|
||||
:alt: Basic Linear Transform - Final Result
|
||||
:align: center
|
||||
|
@@ -23,9 +23,9 @@ OpenCV 2 received reorganization. No longer are all the functions crammed into a
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
|
||||
|
||||
All the OpenCV related stuff is put into the *cv* namespace to avoid name conflicts with other libraries data structures and functions. Therefore, either you need to prepend the *cv::* keyword before everything that comes from OpenCV or after the includes, you just add a directive to use this:
|
||||
|
@@ -6,26 +6,28 @@ Mat - The Basic Image Container
|
||||
Goal
|
||||
====
|
||||
|
||||
We have multiple ways to acquire digital images from the real world: digital cameras, scanners, computed tomography or magnetic resonance imaging to just name a few. In every case what we (humans) see are images. However, when transforming this to our digital devices what we record are numerical values for each of the points of the image.
|
||||
We have multiple ways to acquire digital images from the real world: digital cameras, scanners, computed tomography, and magnetic resonance imaging to name a few. In every case what we (humans) see are images. However, when transforming this to our digital devices what we record are numerical values for each of the points of the image.
|
||||
|
||||
.. image:: images/MatBasicImageForComputer.jpg
|
||||
:alt: A matrix of the mirror of a car
|
||||
:align: center
|
||||
|
||||
For example in the above image you can see that the mirror of the care is nothing more than a matrix containing all the intensity values of the pixel points. Now, how we get and store the pixels values may vary according to what fits best our need, in the end all images inside a computer world may be reduced to numerical matrices and some other information's describing the matric itself. *OpenCV* is a computer vision library whose main focus is to process and manipulate these information to find out further ones. Therefore, the first thing you need to learn and get accommodated with is how OpenCV stores and handles images.
|
||||
For example in the above image you can see that the mirror of the car is nothing more than a matrix containing all the intensity values of the pixel points. How we get and store the pixels values may vary according to our needs, but in the end all images inside a computer world may be reduced to numerical matrices and other information describing the matrix itself. *OpenCV* is a computer vision 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*
|
||||
=====
|
||||
|
||||
OpenCV has been around ever since 2001. In those days the library was built around a *C* interface. In those days to store the image in the memory they used a C structure entitled *IplImage*. This is the one you'll see in most of the older tutorials and educational materials. The problem with this is that it brings to the table all the minuses of the C language. The biggest issue is the manual management. It builds on the assumption that the user is responsible for taking care of memory allocation and deallocation. While this is no issue in case of smaller programs once your code base start to grove larger and larger it will be more and more a struggle to handle all this rather than focusing on actually solving your development goal.
|
||||
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 in most of the older tutorials and educational materials. The problem with this is that it brings to the table all the minuses of the C language. The biggest issue is the manual memory management. It builds on the assumption that the user is responsible for taking care of memory allocation and deallocation. While this is not a problem with smaller programs, once your code base grows it will be more of a struggle to handle all this rather than focusing on solving your development goal.
|
||||
|
||||
Luckily C++ came around and introduced the concept of classes making possible to build another road for the user: automatic memory management (more or less). The good news is that C++ if fully compatible with C so no compatibility issues can arise from making the change. Therefore, OpenCV with its 2.0 version introduced a new C++ interface that by taking advantage of these offers a new way of doing things. A way, in which you do not need to fiddle with memory management; making your code concise (less to write, to achieve more). The only main downside of the C++ interface is that many embedded development systems at the moment support only C. Therefore, unless you are targeting this platform, there's no point on using the *old* methods (unless you're a masochist programmer and you're asking for trouble).
|
||||
Luckily C++ came around and introduced the concept of classes making easier for the user through automatic memory management (more or less). The good news is that C++ is fully compatible with C so no compatibility issues can arise from making the change. Therefore, OpenCV 2.0 introduced a new C++ interface which offered a new way of doing things which means you do not need to fiddle with memory management, making your code concise (less to write, to achieve more). The main downside of the C++ interface is that many embedded development systems at the moment support only C. Therefore, unless you are targeting embedded platforms, there's no point to using the *old* methods (unless you're a masochist programmer and you're asking for trouble).
|
||||
|
||||
The first thing you need to know about *Mat* is that you no longer need to manually allocate its size and release it as soon as you do not need it. While doing this is still a possibility, most of the OpenCV functions will allocate its output data manually. As a nice bonus if you pass on an already existing *Mat* object, what already has allocated the required space for the matrix, this will be reused. In other words we use at all times only as much memory as much we must to perform the task.
|
||||
The first thing you need to know about *Mat* is that you no longer need to manually allocate its memory and release it as soon as you do not need it. While doing this is still a possibility, most of the OpenCV functions will allocate its output data manually. As a nice bonus if you pass on an already existing *Mat* object, which has already allocated the required space for the matrix, this will be reused. In other words we use at all times only as much memory as we need to perform the task.
|
||||
|
||||
*Mat* is basically a class having two data parts: the matrix header (containing information such as the size of the matrix, the method used for storing, at which address is the matrix stored and so on) and a pointer to the matrix containing the pixel values (may take any dimensionality depending on the method chosen for storing) . The matrix header size is constant. However, the size of the matrix itself may vary from image to image and usually is larger by order of magnitudes. Therefore, when you're passing on images in your program and at some point you need to create a copy of the image the big price you will need to build is for the matrix itself rather than its header. OpenCV is an image processing library. It contains a large collection of image processing functions. To solve a computational challenge most of the time you will end up using multiple functions of the library. Due to this passing on images to functions is a common practice. We should not forget that we are talking about image processing algorithms, which tend to be quite computational heavy. The last thing we want to do is to further decrease the speed of your program by making unnecessary copies of potentially *large* images.
|
||||
*Mat* is basically a class with two data parts: the matrix header (containing information such as the size of the matrix, the method used for storing, at which address is the matrix stored, and so on) and a pointer to the matrix containing the pixel values (taking any dimensionality depending on the method chosen for storing) . The matrix header size is constant, however the size of the matrix itself may vary from image to image and usually is larger by orders of magnitude.
|
||||
|
||||
To tackle this issue OpenCV uses a reference counting system. The idea is that each *Mat* object has its own header, however the matrix may be shared between two instance of them by having their matrix pointer point to the same address. Moreover, the copy operators **will only copy the headers**, and as also copy the pointer to the large matrix too, however not the matrix itself.
|
||||
OpenCV is an image processing library. It contains a large collection of image processing functions. To solve a computational challenge, most of the time you will end up using multiple functions of the library. Because of this, passing images to functions is a common practice. We should not forget that we are talking about image processing algorithms, which tend to be quite computational heavy. The last thing we want to do is further decrease the speed of your program by making unnecessary copies of potentially *large* images.
|
||||
|
||||
To tackle this issue OpenCV uses a reference counting system. The idea is that each *Mat* object has 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-block:: cpp
|
||||
:linenos:
|
||||
@@ -37,7 +39,7 @@ To tackle this issue OpenCV uses a reference counting system. The idea is that e
|
||||
|
||||
C = A; // Assignment operator
|
||||
|
||||
All the above objects, in the end point to the same single data matrix. Their headers are different, however making any modification using either one of them will affect all the other ones too. In practice the different objects just provide different access method to the same underlying data. Nevertheless, their header parts are different. The real interesting part comes that you can create headers that refer only to a subsection of the full data. For example, to create a region of interest (*ROI*) in an image you just create a new header with the new boundaries:
|
||||
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 data. Nevertheless, their header parts are different. The real interesting part is that you can create headers which refer to only a subsection of the full data. For example, to create a region of interest (*ROI*) in an image you just create a new header with the new boundaries:
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
@@ -45,7 +47,7 @@ All the above objects, in the end point to the same single data matrix. Their he
|
||||
Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
|
||||
Mat E = A(Range:all(), Range(1,3)); // using row and column boundaries
|
||||
|
||||
Now you may ask if the matrix itself may belong to multiple *Mat* objects who will take responsibility for its cleaning when it's no longer needed. The short answer is: the last object that used it. For this a reference counting mechanism is used. 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. Because, sometimes you will still want to copy the matrix itself too, there exists the :basicstructures:`clone() <mat-clone>` or the :basicstructures:`copyTo() <mat-copyto>` function.
|
||||
Now you may ask if the matrix itself may belong to multiple *Mat* objects who takes responsibility for cleaning it up when it's no longer needed. The short answer is: the last object that used it. 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 :basicstructures:`clone() <mat-clone>` and :basicstructures:`copyTo() <mat-copyto>` functions.
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
@@ -59,34 +61,34 @@ Now modifying *F* or *G* will not affect the matrix pointed by the *Mat* header.
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Output image allocation for OpenCV functions is automatic (unless specified otherwise).
|
||||
* No need to think about memory freeing with OpenCVs C++ interface.
|
||||
* The assignment operator and the copy constructor (*ctor*)copies only the header.
|
||||
* Use the :basicstructures:`clone()<mat-clone>` or the :basicstructures:`copyTo() <mat-copyto>` function to copy the underlying matrix of an image.
|
||||
* 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 :basicstructures:`clone()<mat-clone>` and :basicstructures:`copyTo() <mat-copyto>` functions.
|
||||
|
||||
*Storing* methods
|
||||
=================
|
||||
|
||||
This is about how you store the pixel values. You can select the color space and the data type used. The color space refers to how we combine color components in order to code a given color. The simplest one is the gray scale. Here the colors at our disposal are black and white. The combination of these allows us to create many shades of gray.
|
||||
This is about how you store the pixel values. You can select the color space and the data type used. The color space refers to how we combine color components in order to code a given color. The simplest one is the gray scale where the colors at our disposal are black and white. The combination of these allows us to create many shades of gray.
|
||||
|
||||
For *colorful* ways we have a lot more of methods to choose from. However, every one of them breaks it down to three or four basic components and the combination of this will give all others. The most popular one of this is RGB, mainly because this is also how our eye builds up colors in our eyes. Its base colors are red, green and blue. To code the transparency of a color sometimes a fourth element: alpha (A) is added.
|
||||
For *colorful* ways we have a lot more methods to choose from. Each of them breaks it down to three or four basic components and we can use the combination of these to create the others. The most popular one is RGB, mainly because this is also how our eye builds up colors. Its base colors are red, green and blue. To code the transparency of a color sometimes a fourth element: alpha (A) is added.
|
||||
|
||||
However, they are many color systems each with their own advantages:
|
||||
There are, however, many other color systems each with their own advantages:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* RGB is the most common as our eyes use something similar, our display systems also compose colors using these.
|
||||
* The HSV and HLS decompose colors into their hue, saturation and value/luminance components, which is a more natural way for us to describe colors. Using you may for example dismiss the last component, making your algorithm less sensible to light conditions of the input image.
|
||||
* The HSV and HLS decompose colors into their hue, saturation and value/luminance components, which is a more natural way for us to describe colors. You might, for example, dismiss the last component, making your algorithm less sensible to the light conditions of the input image.
|
||||
* YCrCb is used by the popular JPEG image format.
|
||||
* CIE L*a*b* is a perceptually uniform color space, which comes handy if you need to measure the *distance* of a given color to another color.
|
||||
|
||||
Now each of the building components has their own valid domains. This leads to the data type used. How we store a component defines just how fine control we have over its domain. The smallest data type possible is *char*, which means one byte or 8 bits. This may be unsigned (so can store values from 0 to 255) or signed (values from -127 to +127). Although in case of three components this already gives 16 million possible colors to represent (like in case of RGB) we may acquire an even finer control by using the float (4 byte = 32 bit) or double (8 byte = 64 bit) data types for each component. Nevertheless, remember that increasing the size of a component also increases the size of the whole picture in the memory.
|
||||
Each of the building components has their own valid domains. This leads to the data type used. How we store a component defines the control we have over its domain. The smallest data type possible is *char*, which means one byte or 8 bits. This may be unsigned (so can store values from 0 to 255) or signed (values from -127 to +127). Although in case of three components this already gives 16 million possible colors to represent (like in case of RGB) we may acquire an even finer control by using the float (4 byte = 32 bit) or double (8 byte = 64 bit) data types for each component. Nevertheless, remember that increasing the size of a component also increases the size of the whole picture in the memory.
|
||||
|
||||
Creating explicitly a *Mat* object
|
||||
Creating a *Mat* object explicitly
|
||||
==================================
|
||||
|
||||
In the :ref:`Load_Save_Image` tutorial you could already see how to write a matrix to an image file by using the :readWriteImageVideo:` imwrite() <imwrite>` function. However, for debugging purposes it's much more convenient to see the actual values. You can achieve this via the << operator of *Mat*. However, be aware that this only works for two dimensional matrices.
|
||||
In the :ref:`Load_Save_Image` tutorial you have already learned how to write a matrix to an image file by using the :readWriteImageVideo:` imwrite() <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.
|
||||
|
||||
Although *Mat* is a great class as image container it is also a general matrix class. Therefore, it is possible to create and manipulate multidimensional matrices. You can create a Mat object in multiple ways:
|
||||
Although *Mat* works really well as an image container, it is also a general matrix class. Therefore, it is possible to create and manipulate multidimensional matrices. You can create a Mat object in multiple ways:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
@@ -103,13 +105,13 @@ Although *Mat* is a great class as image container it is also a general matrix c
|
||||
|
||||
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 made according to the following convention:
|
||||
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-block:: cpp
|
||||
|
||||
CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
|
||||
|
||||
For instance, *CV_8UC3* means we use unsigned char types that are 8 bit long and each pixel has three items of this to form the three channels. This are predefined for up to four channel numbers. The :basicstructures:`Scalar <scalar>` is four element short vector. Specify this and you can initialize all matrix points with a custom value. However if you need more you can create the type with the upper macro and putting the channel number in parenthesis as you can see below.
|
||||
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 :basicstructures:`Scalar <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
|
||||
|
||||
@@ -176,7 +178,7 @@ Although *Mat* is a great class as image container it is also a general matrix c
|
||||
|
||||
.. note::
|
||||
|
||||
You can fill out a matrix with random values using the :operationsOnArrays:`randu() <randu>` function. You need to give the lower and upper value between what you want the random values:
|
||||
You can fill out a matrix with random values using the :operationsOnArrays:`randu() <randu>` function. You need to give the lower and upper value for the random values:
|
||||
|
||||
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp
|
||||
:language: cpp
|
||||
@@ -184,10 +186,10 @@ Although *Mat* is a great class as image container it is also a general matrix c
|
||||
:lines: 57-58
|
||||
|
||||
|
||||
Print out formatting
|
||||
====================
|
||||
Output formatting
|
||||
=================
|
||||
|
||||
In the above examples you could see the default formatting option. Nevertheless, OpenCV allows you to format your matrix output format to fit the rules of:
|
||||
In the above examples you could see the default formatting option. OpenCV, however, allows you to format your matrix output:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
@@ -246,10 +248,10 @@ In the above examples you could see the default formatting option. Nevertheless,
|
||||
:alt: Default Output
|
||||
:align: center
|
||||
|
||||
Print for other common items
|
||||
Output of other common items
|
||||
============================
|
||||
|
||||
OpenCV offers support for print of other common OpenCV data structures too via the << operator like:
|
||||
OpenCV offers support for output of other common OpenCV data structures too via the << operator:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
@@ -298,9 +300,9 @@ OpenCV offers support for print of other common OpenCV data structures too via t
|
||||
:alt: Default Output
|
||||
:align: center
|
||||
|
||||
Most of the samples here have been included into a small console application. You can download it from :download:`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.
|
||||
Most of the samples here have been included in a small console application. You can download it from :download:`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.
|
||||
|
||||
A quick video demonstration of this you can find on `YouTube <https://www.youtube.com/watch?v=1tibU7vGWpk>`_.
|
||||
You can also find a quick video demonstration of this on `YouTube <https://www.youtube.com/watch?v=1tibU7vGWpk>`_.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
@@ -7,6 +7,7 @@
|
||||
.. |Author_ArtemM| unicode:: Artem U+0020 Myagkov
|
||||
.. |Author_FernandoI| unicode:: Fernando U+0020 Iglesias U+0020 Garc U+00ED a
|
||||
.. |Author_EduardF| unicode:: Eduard U+0020 Feicho
|
||||
.. |Author_AlexB| unicode:: Alexandre U+0020 Benoit
|
||||
|
||||
|
||||
.. |Author_AlexB| unicode:: Alexandre U+0020 Benoit
|
||||
.. |Author_EricCh| unicode:: Eric U+0020 Christiansen
|
||||
.. |Author_AndreyP| unicode:: Andrey U+0020 Pavlenko
|
||||
.. |Author_AlexS| unicode:: Alexander U+0020 Smorkalov
|
||||
|
@@ -13,7 +13,7 @@ In this tutorial you will learn how to:
|
||||
* Use the :descriptor_extractor:`DescriptorExtractor<>` interface in order to find the feature vector correspondent to the keypoints. Specifically:
|
||||
|
||||
* Use :surf_descriptor_extractor:`SurfDescriptorExtractor<>` and its function :descriptor_extractor:`compute<>` to perform the required calculations.
|
||||
* Use a :brute_force_matcher:`BruteForceMatcher<>` to match the features vector
|
||||
* Use a :brute_force_matcher:`BFMatcher<>` to match the features vector
|
||||
* Use the function :draw_matches:`drawMatches<>` to draw the detected matches.
|
||||
|
||||
|
||||
@@ -29,9 +29,10 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/features2d.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/nonfree.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
@@ -68,7 +69,7 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
extractor.compute( img_2, keypoints_2, descriptors_2 );
|
||||
|
||||
//-- Step 3: Matching descriptor vectors with a brute force matcher
|
||||
BruteForceMatcher< L2<float> > matcher;
|
||||
BFMatcher matcher(NORM_L2);
|
||||
std::vector< DMatch > matches;
|
||||
matcher.match( descriptors_1, descriptors_2, matches );
|
||||
|
||||
|
@@ -28,9 +28,9 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/features2d.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
|
@@ -25,9 +25,9 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/features2d.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
|
@@ -26,10 +26,10 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/features2d.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/calib3d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
|
@@ -23,8 +23,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@@ -22,127 +22,8 @@ Code
|
||||
|
||||
This tutorial code's is shown lines below. You can also download it from `here <http://code.opencv.org/projects/opencv/repository/revisions/master/raw/samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp>`_
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
/// Global variables
|
||||
Mat src, src_gray;
|
||||
Mat myHarris_dst; Mat myHarris_copy; Mat Mc;
|
||||
Mat myShiTomasi_dst; Mat myShiTomasi_copy;
|
||||
|
||||
int myShiTomasi_qualityLevel = 50;
|
||||
int myHarris_qualityLevel = 50;
|
||||
int max_qualityLevel = 100;
|
||||
|
||||
double myHarris_minVal; double myHarris_maxVal;
|
||||
double myShiTomasi_minVal; double myShiTomasi_maxVal;
|
||||
|
||||
RNG rng(12345);
|
||||
|
||||
char* myHarris_window = "My Harris corner detector";
|
||||
char* myShiTomasi_window = "My Shi Tomasi corner detector";
|
||||
|
||||
/// Function headers
|
||||
void myShiTomasi_function( int, void* );
|
||||
void myHarris_function( int, void* );
|
||||
|
||||
/** @function main */
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
/// Load source image and convert it to gray
|
||||
src = imread( argv[1], 1 );
|
||||
cvtColor( src, src_gray, CV_BGR2GRAY );
|
||||
|
||||
/// Set some parameters
|
||||
int blockSize = 3; int apertureSize = 3;
|
||||
|
||||
/// My Harris matrix -- Using cornerEigenValsAndVecs
|
||||
myHarris_dst = Mat::zeros( src_gray.size(), CV_32FC(6) );
|
||||
Mc = Mat::zeros( src_gray.size(), CV_32FC1 );
|
||||
|
||||
cornerEigenValsAndVecs( src_gray, myHarris_dst, blockSize, apertureSize, BORDER_DEFAULT );
|
||||
|
||||
/* calculate Mc */
|
||||
for( int j = 0; j < src_gray.rows; j++ )
|
||||
{ for( int i = 0; i < src_gray.cols; i++ )
|
||||
{
|
||||
float lambda_1 = myHarris_dst.at<float>( j, i, 0 );
|
||||
float lambda_2 = myHarris_dst.at<float>( j, i, 1 );
|
||||
Mc.at<float>(j,i) = lambda_1*lambda_2 - 0.04*pow( ( lambda_1 + lambda_2 ), 2 );
|
||||
}
|
||||
}
|
||||
|
||||
minMaxLoc( Mc, &myHarris_minVal, &myHarris_maxVal, 0, 0, Mat() );
|
||||
|
||||
/* Create Window and Trackbar */
|
||||
namedWindow( myHarris_window, CV_WINDOW_AUTOSIZE );
|
||||
createTrackbar( " Quality Level:", myHarris_window, &myHarris_qualityLevel, max_qualityLevel,
|
||||
myHarris_function );
|
||||
myHarris_function( 0, 0 );
|
||||
|
||||
/// My Shi-Tomasi -- Using cornerMinEigenVal
|
||||
myShiTomasi_dst = Mat::zeros( src_gray.size(), CV_32FC1 );
|
||||
cornerMinEigenVal( src_gray, myShiTomasi_dst, blockSize, apertureSize, BORDER_DEFAULT );
|
||||
|
||||
minMaxLoc( myShiTomasi_dst, &myShiTomasi_minVal, &myShiTomasi_maxVal, 0, 0, Mat() );
|
||||
|
||||
/* Create Window and Trackbar */
|
||||
namedWindow( myShiTomasi_window, CV_WINDOW_AUTOSIZE );
|
||||
createTrackbar( " Quality Level:", myShiTomasi_window, &myShiTomasi_qualityLevel, max_qualityLevel,
|
||||
myShiTomasi_function );
|
||||
myShiTomasi_function( 0, 0 );
|
||||
|
||||
waitKey(0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/** @function myShiTomasi_function */
|
||||
void myShiTomasi_function( int, void* )
|
||||
{
|
||||
myShiTomasi_copy = src.clone();
|
||||
|
||||
if( myShiTomasi_qualityLevel < 1 ) { myShiTomasi_qualityLevel = 1; }
|
||||
|
||||
for( int j = 0; j < src_gray.rows; j++ )
|
||||
{ for( int i = 0; i < src_gray.cols; i++ )
|
||||
{
|
||||
if( myShiTomasi_dst.at<float>(j,i) > myShiTomasi_minVal + ( myShiTomasi_maxVal -
|
||||
myShiTomasi_minVal )*myShiTomasi_qualityLevel/max_qualityLevel )
|
||||
{ circle( myShiTomasi_copy, Point(i,j), 4, Scalar( rng.uniform(0,255),
|
||||
rng.uniform(0,255), rng.uniform(0,255) ), -1, 8, 0 ); }
|
||||
}
|
||||
}
|
||||
imshow( myShiTomasi_window, myShiTomasi_copy );
|
||||
}
|
||||
|
||||
/** @function myHarris_function */
|
||||
void myHarris_function( int, void* )
|
||||
{
|
||||
myHarris_copy = src.clone();
|
||||
|
||||
if( myHarris_qualityLevel < 1 ) { myHarris_qualityLevel = 1; }
|
||||
|
||||
for( int j = 0; j < src_gray.rows; j++ )
|
||||
{ for( int i = 0; i < src_gray.cols; i++ )
|
||||
{
|
||||
if( Mc.at<float>(j,i) > myHarris_minVal + ( myHarris_maxVal - myHarris_minVal )
|
||||
*myHarris_qualityLevel/max_qualityLevel )
|
||||
{ circle( myHarris_copy, Point(i,j), 4, Scalar( rng.uniform(0,255), rng.uniform(0,255),
|
||||
rng.uniform(0,255) ), -1, 8, 0 ); }
|
||||
}
|
||||
}
|
||||
imshow( myHarris_window, myHarris_copy );
|
||||
}
|
||||
|
||||
|
||||
.. literalinclude:: ../../../../../samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp
|
||||
:language: cpp
|
||||
|
||||
Explanation
|
||||
============
|
||||
|
@@ -22,8 +22,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@@ -155,8 +155,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@@ -28,9 +28,7 @@ Let's modify the program made in the tutorial :ref:`Adding_Images`. We will let
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <cv.h>
|
||||
#include <highgui.h>
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
using namespace cv;
|
||||
|
||||
/// Global Variables
|
||||
@@ -50,41 +48,41 @@ Let's modify the program made in the tutorial :ref:`Adding_Images`. We will let
|
||||
*/
|
||||
void on_trackbar( int, void* )
|
||||
{
|
||||
alpha = (double) alpha_slider/alpha_slider_max ;
|
||||
beta = ( 1.0 - alpha );
|
||||
alpha = (double) alpha_slider/alpha_slider_max ;
|
||||
beta = ( 1.0 - alpha );
|
||||
|
||||
addWeighted( src1, alpha, src2, beta, 0.0, dst);
|
||||
addWeighted( src1, alpha, src2, beta, 0.0, dst);
|
||||
|
||||
imshow( "Linear Blend", dst );
|
||||
imshow( "Linear Blend", dst );
|
||||
}
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
/// Read image ( same size, same type )
|
||||
src1 = imread("../../images/LinuxLogo.jpg");
|
||||
src2 = imread("../../images/WindowsLogo.jpg");
|
||||
/// Read image ( same size, same type )
|
||||
src1 = imread("../../images/LinuxLogo.jpg");
|
||||
src2 = imread("../../images/WindowsLogo.jpg");
|
||||
|
||||
if( !src1.data ) { printf("Error loading src1 \n"); return -1; }
|
||||
if( !src2.data ) { printf("Error loading src2 \n"); return -1; }
|
||||
if( !src1.data ) { printf("Error loading src1 \n"); return -1; }
|
||||
if( !src2.data ) { printf("Error loading src2 \n"); return -1; }
|
||||
|
||||
/// Initialize values
|
||||
alpha_slider = 0;
|
||||
/// Initialize values
|
||||
alpha_slider = 0;
|
||||
|
||||
/// Create Windows
|
||||
namedWindow("Linear Blend", 1);
|
||||
/// Create Windows
|
||||
namedWindow("Linear Blend", 1);
|
||||
|
||||
/// Create Trackbars
|
||||
char TrackbarName[50];
|
||||
sprintf( TrackbarName, "Alpha x %d", alpha_slider_max );
|
||||
/// Create Trackbars
|
||||
char TrackbarName[50];
|
||||
sprintf( TrackbarName, "Alpha x %d", alpha_slider_max );
|
||||
|
||||
createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar );
|
||||
createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar );
|
||||
|
||||
/// Show some stuff
|
||||
on_trackbar( alpha_slider, 0 );
|
||||
/// Show some stuff
|
||||
on_trackbar( alpha_slider, 0 );
|
||||
|
||||
/// Wait until user press some key
|
||||
waitKey(0);
|
||||
return 0;
|
||||
/// Wait until user press some key
|
||||
waitKey(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -16,7 +16,7 @@ Today it is common to have a digital video recording system at your disposal. Th
|
||||
The source code
|
||||
===============
|
||||
|
||||
As a test case where to show off these using OpenCV I've created a small program that reads in two video files and performs a similarity check between them. This is something you could use to check just how well a new video compressing algorithms works. Let there be a reference (original) video like :download:`this small Megamind clip <../../../../samples/cpp/tutorial_code/highgui/video-input-psnr-ssim/video/Megamind.avi>` and :download:`a compressed version of it <../../../../samples/cpp/tutorial_code/highgui/video-input-psnr-ssim/video/Megamind_bugy.avi>`. You may also find the source code and these video file in the :file:`samples/cpp/tutorial_code/highgui/video-input-psnr-ssim/` folder of the OpenCV source library.
|
||||
As a test case where to show off these using OpenCV I've created a small program that reads in two video files and performs a similarity check between them. This is something you could use to check just how well a new video compressing algorithms works. Let there be a reference (original) video like :download:`this small Megamind clip <../../../../samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video/Megamind.avi>` and :download:`a compressed version of it <../../../../samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video/Megamind_bugy.avi>`. You may also find the source code and these video file in the :file:`samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/` folder of the OpenCV source library.
|
||||
|
||||
.. literalinclude:: ../../../../samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video-input-psnr-ssim.cpp
|
||||
:language: cpp
|
||||
@@ -27,9 +27,9 @@ As a test case where to show off these using OpenCV I've created a small program
|
||||
How to read a video stream (online-camera or offline-file)?
|
||||
===========================================================
|
||||
|
||||
Essentially, all the functionalities required for video manipulation is integrated in the :huivideo:`VideoCapture <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 limit of just how many frames they can digitalize per second, this property is less important as at any time the camera sees the current snapshot of the world.
|
||||
Essentially, all the functionalities required for video manipulation is integrated in the :hgvideo:`VideoCapture <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 limit of just how many frames they can digitalize per second, this property is less important as at any time the camera sees the current snapshot of the world.
|
||||
|
||||
The first task you need to do is to assign to a :huivideo:`VideoCapture <videocapture>` class its source. You can do this either via the :huivideo:`constructor <videocapture-videocapture>` or its :huivideo:`open <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 string it will refer to a video file, and the string points to the location and name of the file. For example, to the upper source code a valid command line is:
|
||||
The first task you need to do is to assign to a :hgvideo:`VideoCapture <videocapture>` class its source. You can do this either via the :hgvideo:`constructor <videocapture-videocapture>` or its :hgvideo:`open <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 string it will refer to a video file, and the string points to the location and name of the file. For example, to the upper source code a valid command line is:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@@ -46,7 +46,7 @@ We do a similarity check. This requires a reference and a test case video file.
|
||||
VideoCapture captUndTst;
|
||||
captUndTst.open(sourceCompareWith);
|
||||
|
||||
To check if the binding of the class to a video source was successful or not use the :huivideo:`isOpened <video-isopened>` function:
|
||||
To check if the binding of the class to a video source was successful or not use the :hgvideo:`isOpened <video-isopened>` function:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -56,7 +56,7 @@ To check if the binding of the class to a video source was successful or not use
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 :huivideo:`release <videocapture-release>` function. The frames of the video are just simple images. Therefore, we just need to extract them from the :huivideo:`VideoCapture <videocapture>` object and put them inside a *Mat* one. The video streams are sequential. You may get the frames one after another by the :huivideo:`read <videocapture-read>` or the overloaded >> operator:
|
||||
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 :hgvideo:`release <videocapture-release>` function. The frames of the video are just simple images. Therefore, we just need to extract them from the :hgvideo:`VideoCapture <videocapture>` object and put them inside a *Mat* one. The video streams are sequential. You may get the frames one after another by the :hgvideo:`read <videocapture-read>` or the overloaded >> operator:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -73,9 +73,9 @@ The upper read operations will leave empty the *Mat* objects if no frame could b
|
||||
// exit the program
|
||||
}
|
||||
|
||||
A read method is made of a frame grab and a decoding applied on that. You may call explicitly these two by using the :huivideo:`grab <videocapture-grab>` and then the :huivideo:`retrieve <videocapture-retrieve>` functions.
|
||||
A read method is made of a frame grab and a decoding applied on that. You may call explicitly these two by using the :hgvideo:`grab <videocapture-grab>` and then the :hgvideo:`retrieve <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 :huivideo:`get <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 video file; plus the number of frames inside the reference.
|
||||
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 :hgvideo:`get <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 video file; plus the number of frames inside the reference.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -85,7 +85,7 @@ Videos have many-many information attached to them besides the content of the fr
|
||||
cout << "Reference frame resolution: Width=" << refS.width << " Height=" << refS.height
|
||||
<< " of nr#: " << captRefrnc.get(CV_CAP_PROP_FRAME_COUNT) << endl;
|
||||
|
||||
When you are working with videos you may often want to control these values yourself. To do this there is a :huivideo:`set <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:
|
||||
When you are working with videos you may often want to control these values yourself. To do this there is a :hgvideo:`set <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:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -93,7 +93,7 @@ When you are working with videos you may often want to control these values your
|
||||
captRefrnc.set(CV_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
|
||||
|
||||
For properties you can read and change look into the documentation of the :huivideo:`get <videocapture-get>` and :huivideo:`set <videocapture-set>` functions.
|
||||
For properties you can read and change look into the documentation of the :hgvideo:`get <videocapture-get>` and :hgvideo:`set <videocapture-set>` functions.
|
||||
|
||||
|
||||
Image similarity - PSNR and SSIM
|
||||
|
@@ -39,7 +39,7 @@ Morphological Operations
|
||||
:align: center
|
||||
|
||||
Dilation
|
||||
^^^^^^^^^
|
||||
~~~~~~~~
|
||||
|
||||
* This operations consists of convoluting an image :math:`A` with some kernel (:math:`B`), which can have any shape or size, usually a square or circle.
|
||||
|
||||
@@ -54,7 +54,7 @@ Dilation
|
||||
The background (bright) dilates around the black regions of the letter.
|
||||
|
||||
Erosion
|
||||
^^^^^^^^
|
||||
~~~~~~~
|
||||
|
||||
* This operation is the sister of dilation. What this does is to compute a local minimum over the area of the kernel.
|
||||
|
||||
@@ -74,8 +74,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "highgui.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -216,17 +216,17 @@ Explanation
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
Mat element = getStructuringElement( erosion_type,
|
||||
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
|
||||
Point( erosion_size, erosion_size ) );
|
||||
Mat element = getStructuringElement( erosion_type,
|
||||
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
|
||||
Point( erosion_size, erosion_size ) );
|
||||
|
||||
We can choose any of three shapes for our kernel:
|
||||
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
+ Rectangular box: MORPH_RECT
|
||||
+ Cross: MORPH_CROSS
|
||||
+ Ellipse: MORPH_ELLIPSE
|
||||
+ Rectangular box: MORPH_RECT
|
||||
+ Cross: MORPH_CROSS
|
||||
+ Ellipse: MORPH_ELLIPSE
|
||||
|
||||
Then, we just have to specify the size of our kernel and the *anchor point*. If not specified, it is assumed to be in the center.
|
||||
|
||||
|
@@ -122,8 +122,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
@@ -94,7 +94,7 @@ Code
|
||||
* Loads an image
|
||||
* Convert the original to HSV format and separate only *Hue* channel to be used for the Histogram (using the OpenCV function :mix_channels:`mixChannels <>`)
|
||||
* Let the user to enter the number of bins to be used in the calculation of the histogram.
|
||||
* Calculate the histogram (and update it if the bins change) and the backprojection of the same image.
|
||||
* Calculate the histogram (and update it if the bins change) and the backprojection of the same image.
|
||||
* Display the backprojection and the histogram in windows.
|
||||
|
||||
* **Downloadable code**:
|
||||
@@ -107,8 +107,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@@ -88,8 +88,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -86,8 +86,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -89,8 +89,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -131,8 +131,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -90,8 +90,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -52,8 +52,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -77,8 +77,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -48,8 +48,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -104,8 +104,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@@ -59,8 +59,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -63,8 +63,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -125,8 +125,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -97,8 +97,8 @@ Code
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -115,8 +115,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -84,8 +84,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
@@ -25,8 +25,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -85,7 +85,7 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
for( int i = 0; i < contours.size(); i++ )
|
||||
{ approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
|
||||
boundRect[i] = boundingRect( Mat(contours_poly[i]) );
|
||||
minEnclosingCircle( contours_poly[i], center[i], radius[i] );
|
||||
minEnclosingCircle( (Mat)contours_poly[i], center[i], radius[i] );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -25,8 +25,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@@ -23,8 +23,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@@ -23,8 +23,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@@ -25,8 +25,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@@ -23,8 +23,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@@ -134,8 +134,8 @@ The tutorial code's is shown lines below. You can also download it from `here <h
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@@ -7,9 +7,10 @@ OpenCV4Android SDK
|
||||
|
||||
This tutorial was designed to help you with installation and configuration of OpenCV4Android SDK.
|
||||
|
||||
This guide was written with MS Windows 7 in mind, though it should work with GNU Linux and Apple MacOS as well.
|
||||
This guide was written with MS Windows 7 in mind, though it should work with GNU Linux and Apple
|
||||
Mac OS as well.
|
||||
|
||||
This tutorial assumes you have the following installed and configured:
|
||||
This tutorial assumes you have the following software installed and configured:
|
||||
|
||||
* JDK
|
||||
|
||||
@@ -23,7 +24,20 @@ This tutorial assumes you have the following installed and configured:
|
||||
|
||||
If you need help with anything of the above, you may refer to our :ref:`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 forum <http://answers.opencv.org>`_. We'll do our best to help you out.
|
||||
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 forum <http://answers.opencv.org>`_. We'll do our best to help you out.
|
||||
|
||||
Tegra Android Development Pack users
|
||||
====================================
|
||||
|
||||
You may have used `Tegra Android Development Pack <http://developer.nvidia.com/tegra-android-development-pack>`_
|
||||
(**TADP**) released by **NVIDIA** 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.
|
||||
|
||||
More details regarding TADP can be found in the :ref:`android_dev_intro` guide.
|
||||
|
||||
General info
|
||||
============
|
||||
@@ -34,10 +48,10 @@ The structure of package contents looks as follows:
|
||||
|
||||
::
|
||||
|
||||
OpenCV-2.4.2-android-sdk
|
||||
OpenCV-2.4.5-android-sdk
|
||||
|_ apk
|
||||
| |_ OpenCV_2.4.2_binary_pack_XXX.apk
|
||||
| |_ OpenCV_2.4.2_Manager.apk
|
||||
| |_ OpenCV_2.4.5_binary_pack_armv7a.apk
|
||||
| |_ OpenCV_2.4.5_Manager_2.7_XXX.apk
|
||||
|
|
||||
|_ doc
|
||||
|_ samples
|
||||
@@ -57,32 +71,44 @@ The structure of package contents looks as follows:
|
||||
|
||||
* :file:`sdk` folder contains OpenCV API and libraries for Android:
|
||||
|
||||
* :file:`sdk/java` folder contains an Android library Eclipse project providing OpenCV Java API that can be imported into developer's workspace;
|
||||
* :file:`sdk/java` folder contains an Android library Eclipse project providing OpenCV Java API that
|
||||
can be imported into developer's workspace;
|
||||
|
||||
* :file:`sdk/native` folder contains OpenCV C++ headers (for JNI code) and native Android libraries (\*\.so and \*\.a) for ARM-v5, ARM-v7a and x86 architectures;
|
||||
* :file:`sdk/native` folder contains OpenCV C++ headers (for JNI code) and native Android libraries
|
||||
(\*\.so and \*\.a) for ARM-v5, ARM-v7a and x86 architectures;
|
||||
|
||||
* :file:`sdk/etc` folder contains Haar and LBP cascades distributed with OpenCV.
|
||||
|
||||
* :file:`apk` folder contains Android packages that should be installed on the target Android device to enable OpenCV library access via OpenCV Manager API (see details below).
|
||||
* :file:`apk` folder contains Android packages that should be installed on the target Android device
|
||||
to enable OpenCV library access via OpenCV Manager API (see details below).
|
||||
|
||||
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 dev kits without Market or internet require this packages to be installed manually.
|
||||
(Install the `Manager.apk` and the corresponding `binary_pack.apk` depending on the device CPU, the Manager GUI provides this info).
|
||||
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` for details.
|
||||
|
||||
**Note**: installation from internet is the preferable way since we may publish updated versions of this packages on the Market.
|
||||
.. note:: Installation from Internet is the preferable way since OpenCV team may publish updated
|
||||
versions of this packages on the Market.
|
||||
|
||||
* :file:`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.
|
||||
Import them into Eclipse workspace (like described below) and browse the code to learn possible
|
||||
ways of OpenCV use on Android.
|
||||
|
||||
* :file:`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/trunk/.
|
||||
Generally, it's more up-to-date, but can refer to not-yet-released functionality.
|
||||
.. note:: The most recent docs (nightly build) are at http://docs.opencv.org/trunk/.
|
||||
Generally, it's more up-to-date, but can refer to not-yet-released functionality.
|
||||
|
||||
Starting version 2.4.2 `OpenCV4Android SDK` uses `OpenCV Manager` API for library initialization. `OpenCV Manager` is an Android service based solution providing the following benefits for OpenCV applications developers:
|
||||
.. TODO: I'm not sure that this is the best place to talk about OpenCV Manager
|
||||
|
||||
* Compact apk-size, since all applications use the same binaries from Manager and do not store native libs within themselves;
|
||||
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 applications developers:
|
||||
|
||||
* Compact apk-size, since all applications use the same binaries from Manager and do not store
|
||||
native libs within themselves;
|
||||
|
||||
* Hardware specific optimizations are automatically enabled on all supported platforms;
|
||||
|
||||
@@ -92,7 +118,6 @@ Starting version 2.4.2 `OpenCV4Android SDK` uses `OpenCV Manager` API for librar
|
||||
|
||||
..
|
||||
|
||||
|
||||
For additional information on OpenCV Manager see the:
|
||||
|
||||
* |OpenCV4Android_Slides|_
|
||||
@@ -106,29 +131,21 @@ For additional information on OpenCV Manager see the:
|
||||
.. |OpenCV4Android_Reference| replace:: Reference Manual
|
||||
.. _OpenCV4Android_Reference: http://docs.opencv.org/android/refman.html
|
||||
|
||||
Tegra Android Development Pack users
|
||||
====================================
|
||||
|
||||
You may have used `Tegra Android Development Pack <http://developer.nvidia.com/tegra-android-development-pack>`_
|
||||
(**TADP**) released by **NVIDIA** for Android development environment setup.
|
||||
|
||||
Beside Android development tools the TADP 2.0 includes OpenCV4Android SDK 2.4.2, so it can be already installed in your system and you can skip to running the ``face-detection`` sample.
|
||||
|
||||
More details regarding TADP can be found in the :ref:`android_dev_intro` guide.
|
||||
|
||||
Manual OpenCV4Android SDK setup
|
||||
===============================
|
||||
|
||||
Get the OpenCV4Android SDK
|
||||
--------------------------
|
||||
|
||||
#. Go to the `OpenCV dowload page on SourceForge <http://sourceforge.net/projects/opencvlibrary/files/opencv-android/>`_ and download the latest available version. Currently it's |opencv_android_bin_pack_url|_
|
||||
#. 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_android_bin_pack_url|_.
|
||||
|
||||
#. Create a new folder for Android with OpenCV development. For this tutorial I have unpacked OpenCV to the :file:`C:\\Work\\OpenCV4Android\\` directory.
|
||||
#. Create a new folder for Android with OpenCV development. For this tutorial we have unpacked
|
||||
OpenCV SDK to the :file:`C:\\Work\\OpenCV4Android\\` directory.
|
||||
|
||||
.. note:: Better to use a path without spaces in it. Otherwise you may have problems with :command:`ndk-build`.
|
||||
.. note:: Better to use a path without spaces in it. Otherwise you may have problems with :command:`ndk-build`.
|
||||
|
||||
#. Unpack the OpenCV package into the chosen directory.
|
||||
#. Unpack the SDK archive into the chosen directory.
|
||||
|
||||
You can unpack it using any popular archiver (e.g with |seven_zip|_):
|
||||
|
||||
@@ -140,20 +157,21 @@ Get the OpenCV4Android SDK
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
unzip ~/Downloads/OpenCV-2.4.2-android-sdk.zip
|
||||
unzip ~/Downloads/OpenCV-2.4.5-android-sdk.zip
|
||||
|
||||
.. |opencv_android_bin_pack| replace:: OpenCV-2.4.2-android-sdk.zip
|
||||
.. _opencv_android_bin_pack_url: http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.4.2/OpenCV-2.4.2-android-sdk.zip/download
|
||||
.. |opencv_android_bin_pack| replace:: :file:`OpenCV-2.4.5-android-sdk.zip`
|
||||
.. _opencv_android_bin_pack_url: http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.4.5/OpenCV-2.4.5-android-sdk.zip/download
|
||||
.. |opencv_android_bin_pack_url| replace:: |opencv_android_bin_pack|
|
||||
.. |seven_zip| replace:: 7-Zip
|
||||
.. _seven_zip: http://www.7-zip.org/
|
||||
|
||||
Open OpenCV library and samples in Eclipse
|
||||
------------------------------------------
|
||||
Import OpenCV library and samples to the Eclipse
|
||||
------------------------------------------------
|
||||
|
||||
#. Start *Eclipse* and choose your workspace location.
|
||||
#. Start Eclipse and choose your workspace location.
|
||||
|
||||
We recommend to start working with OpenCV for Android from a new clean workspace. A new Eclipse workspace can for example be created in the folder where you have unpacked OpenCV4Android SDK package:
|
||||
We recommend to start working with OpenCV for Android from a new clean workspace. A new Eclipse
|
||||
workspace can for example be created in the folder where you have unpacked OpenCV4Android SDK package:
|
||||
|
||||
.. image:: images/eclipse_1_choose_workspace.png
|
||||
:alt: Choosing C:\Work\android-opencv\ as workspace location
|
||||
@@ -162,24 +180,30 @@ Open OpenCV library and samples in Eclipse
|
||||
#. Import OpenCV library and samples into workspace.
|
||||
|
||||
OpenCV library is packed as a ready-for-use `Android Library Project
|
||||
<http://developer.android.com/guide/developing/projects/index.html#LibraryProjects>`_. You can simply reference it in your projects.
|
||||
<http://developer.android.com/guide/developing/projects/index.html#LibraryProjects>`_.
|
||||
You can simply reference it in your projects.
|
||||
|
||||
Each sample included into the |opencv_android_bin_pack| is a regular Android project that already references OpenCV library.
|
||||
Follow the steps below to import OpenCV and samples into the workspace:
|
||||
Each sample included into the |opencv_android_bin_pack| is a regular Android project that already
|
||||
references OpenCV library. Follow the steps below to import OpenCV and samples into the workspace:
|
||||
|
||||
* Right click on the :guilabel:`Package Explorer` window and choose :guilabel:`Import...` option from the context menu:
|
||||
.. 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 :guilabel:`Package Explorer` window and choose :guilabel:`Import...` option
|
||||
from the context menu:
|
||||
|
||||
.. image:: images/eclipse_5_import_command.png
|
||||
:alt: Select Import... from context menu
|
||||
:align: center
|
||||
|
||||
* In the main panel select :menuselection:`General --> Existing Projects into Workspace` and press :guilabel:`Next` button:
|
||||
* In the main panel select :menuselection:`General --> Existing Projects into Workspace` and
|
||||
press :guilabel:`Next` button:
|
||||
|
||||
.. image:: images/eclipse_6_import_existing_projects.png
|
||||
:alt: General > Existing Projects into Workspace
|
||||
:align: center
|
||||
|
||||
* In the :guilabel:`Select root directory` field locate your OpenCV package folder. Eclipse should automatically locate OpenCV library and samples:
|
||||
* In the :guilabel:`Select root directory` field locate your OpenCV package folder. Eclipse
|
||||
should automatically locate OpenCV library and samples:
|
||||
|
||||
.. image:: images/eclipse_7_select_projects.png
|
||||
:alt: Locate OpenCV library and samples
|
||||
@@ -187,34 +211,28 @@ Open OpenCV library and samples in Eclipse
|
||||
|
||||
* Click :guilabel:`Finish` button to complete the import operation.
|
||||
|
||||
After clicking :guilabel:`Finish` button Eclipse will load all selected projects into workspace. Numerous errors will be indicated:
|
||||
After clicking :guilabel:`Finish` button Eclipse will load all selected projects into workspace,
|
||||
and you have to wait some time while it is building OpenCV samples. Just give a minute to
|
||||
Eclipse to complete initialization.
|
||||
|
||||
.. image:: images/eclipse_8_false_alarm.png
|
||||
:alt: Confusing Eclipse screen with numerous errors
|
||||
:align: center
|
||||
.. warning :: After the initial import, on a non-Windows (Linux and Mac OS) operating system Eclipse
|
||||
will still show build errors for applications with native C++ code. To resolve the
|
||||
issues, please do the following:
|
||||
|
||||
However, **all these errors are only false-alarms**!
|
||||
Open :guilabel:`Project Properties -> C/C++ Build`, and replace "Build command" text
|
||||
to ``"${NDKROOT}/ndk-build"`` (remove .cmd at the end).
|
||||
|
||||
Just give a minute to Eclipse to complete initialization.
|
||||
.. note :: In some cases the build errors don't disappear, then try the following actions:
|
||||
|
||||
In some cases these errors disappear after :menuselection:`Project --> Clean... --> Clean all --> OK`
|
||||
or after pressing :kbd:`F5` (for Refresh action) when selecting error-label-marked projects in :guilabel:`Package Explorer`.
|
||||
* right click on ``OpenCV Library`` project -> :guilabel:`Android Tools -> Fix Project Properties`,
|
||||
then menu :guilabel:`Project -> Clean... -> Clean all`
|
||||
* right click on the project with errors -> :guilabel:`Properties -> Android`, make sure the
|
||||
``Target`` is selected and is ``Android 3.0`` or higher
|
||||
* check the build errors in the :guilabel:`Problems` view window and try to resolve them by yourselves
|
||||
|
||||
Sometimes more advanced manipulations are required:
|
||||
|
||||
The provided projects are configured for ``API 11`` target (and ``API 9`` for the library) that can be missing platform in your Android SDK.
|
||||
After right click on any project select :guilabel:`Properties` and then :guilabel:`Android` on the left pane.
|
||||
Click some target with `API Level` 11 or higher:
|
||||
|
||||
.. image:: images/eclipse_8a_target.png
|
||||
:alt: Updating target
|
||||
:align: center
|
||||
|
||||
Eclipse will rebuild your workspace and error icons will disappear one by one:
|
||||
|
||||
.. image:: images/eclipse_9_errors_dissapearing.png
|
||||
:alt: After small help Eclipse removes error icons!
|
||||
:align: center
|
||||
.. image:: images/eclipse_cdt_cfg4.png
|
||||
:alt: Configure CDT
|
||||
:align: center
|
||||
|
||||
Once Eclipse completes build you will have the clean workspace without any build errors:
|
||||
|
||||
@@ -227,13 +245,17 @@ Open OpenCV library and samples in Eclipse
|
||||
Running OpenCV Samples
|
||||
----------------------
|
||||
|
||||
At this point you should be able to build and run the samples. Keep in mind, that ``face-detection``, ``Tutorial 3`` and ``Tutorial 4`` include some native code and require Android NDK and CDT plugin for Eclipse to build working applications.
|
||||
If you haven't installed these tools see the corresponding section of :ref:`Android_Dev_Intro`.
|
||||
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`.
|
||||
|
||||
Also, please consider that ``Tutorial 0`` and ``Tutorial 1`` samples use Java Camera API that definitelly accessible on emulator from the Android SDK.
|
||||
Other samples use OpenCV Native Camera which may not work with emulator.
|
||||
.. warning:: Please consider that some samples use Android Java Camera API, which is accessible
|
||||
with an AVD. But most of samples use OpenCV Native Camera which **may not work** with
|
||||
an emulator.
|
||||
|
||||
.. note:: Recent *Android SDK tools, revision 19+* can run ARM v7a OS images but they available not for all Android versions.
|
||||
.. 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:
|
||||
|
||||
@@ -245,7 +267,8 @@ Well, running samples from Eclipse is very simple:
|
||||
<http://developer.android.com/guide/developing/device.html>`_ for help with real devices (not emulators).
|
||||
|
||||
|
||||
* Select project you want to start in :guilabel:`Package Explorer` and just press :kbd:`Ctrl + F11` or select option :menuselection:`Run --> Run` from the main menu, or click :guilabel:`Run` button on the toolbar.
|
||||
* Select project you want to start in :guilabel:`Package Explorer` and just press :kbd:`Ctrl + F11`
|
||||
or select option :menuselection:`Run --> Run` from the main menu, or click :guilabel:`Run` button on the toolbar.
|
||||
|
||||
.. note:: Android Emulator can take several minutes to start. So, please, be patient.
|
||||
|
||||
@@ -267,30 +290,52 @@ Well, running samples from Eclipse is very simple:
|
||||
To get rid of the message you will need to install `OpenCV Manager` and the appropriate `OpenCV binary pack`.
|
||||
Simply tap :menuselection:`Yes` if you have *Google Play Market* installed on your 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. Open the console/terminal and type in the following two commands:
|
||||
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 details.
|
||||
|
||||
.. code-block:: sh
|
||||
:linenos:
|
||||
|
||||
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.2_Manager.apk
|
||||
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.2_binary_pack_armv7a.apk
|
||||
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.5_Manager_2.7_armv7a-neon.apk
|
||||
|
||||
If you're running Windows, that will probably look like this:
|
||||
.. 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-block:: sh
|
||||
|
||||
adb shell getprop ro.product.cpu.abi
|
||||
|
||||
If you're using an AVD emulator, go :menuselection:`Window > AVD Manager` to see the
|
||||
list of availible devices. Click :menuselection:`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.
|
||||
|
||||
.. image:: images/install_opencv_manager_with_adb.png
|
||||
:alt: Run these commands in the console to install OpenCV Manager
|
||||
:align: center
|
||||
|
||||
When done, you will be able to run OpenCV samples on your device/emulator seamlessly.
|
||||
|
||||
* Here is ``Tutorial 2 - Use OpenCV Camera`` sample, running on top of stock camera-preview of the emulator.
|
||||
* Here is ``Sample - image-manipulations`` sample, running on top of stock camera-preview of the emulator.
|
||||
|
||||
.. image:: images/emulator_canny.png
|
||||
:height: 600px
|
||||
:alt: Tutorial 1 Basic - 1. Add OpenCV - running Canny
|
||||
:alt: 'Sample - image-manipulations' running Canny
|
||||
:align: center
|
||||
|
||||
|
||||
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.
|
||||
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.
|
||||
|
@@ -5,47 +5,63 @@
|
||||
Introduction into Android Development
|
||||
*************************************
|
||||
|
||||
This guide was designed to help you in learning Android development basics and seting up your working environment quickly.
|
||||
This guide was designed to help you in learning Android development basics and seting up your
|
||||
working environment quickly. It was written with Windows 7 in mind, though it would work with Linux
|
||||
(Ubuntu), Mac OS X and any other OS supported by Android SDK.
|
||||
|
||||
This guide was written with Windows 7 in mind, though it would work with Linux (Ubuntu), Mac OS X and any other OS supported by Android SDK.
|
||||
|
||||
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 forum <http://answers.opencv.org>`_. We'll do our best to help you out.
|
||||
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 forum <http://answers.opencv.org>`_. We'll do our best to help you out.
|
||||
|
||||
Preface
|
||||
=======
|
||||
Android is a Linux-based, open source mobile operating system developed by Open Handset Alliance led by Google. See the `Android home site <http://www.android.com/about/>`_ for general details.
|
||||
Android is a Linux-based, open source mobile operating system developed by Open Handset Alliance
|
||||
led by Google. See the `Android home site <http://www.android.com/about/>`_ for general details.
|
||||
|
||||
Development for Android significantly differs from development for other platforms.
|
||||
So before starting programming for Android we recommend you make sure that you are familiar with the following key topis:
|
||||
So before starting programming for Android we recommend you make sure that you are familiar with the
|
||||
following key topis:
|
||||
|
||||
#. `Java <http://en.wikipedia.org/wiki/Java_(programming_language)>`_ programming language that is
|
||||
the primary development technology for Android OS. Also, you can find
|
||||
`Oracle docs on Java <http://docs.oracle.com/javase/>`_ useful.
|
||||
#. `Java Native Interface (JNI) <http://en.wikipedia.org/wiki/Java_Native_Interface>`_ that is a
|
||||
technology of running native code in Java virtual machine. Also, you can find
|
||||
`Oracle docs on JNI <http://docs.oracle.com/javase/7/docs/technotes/guides/jni/>`_ useful.
|
||||
#. `Android Activity <http://developer.android.com/training/basics/activity-lifecycle/starting.html>`_
|
||||
and its lifecycle, that is an essential Android API class.
|
||||
#. OpenCV development will certainly require some knowlege of the
|
||||
`Android Camera <http://developer.android.com/guide/topics/media/camera.html>`_ specifics.
|
||||
|
||||
#. `Java <http://en.wikipedia.org/wiki/Java_(programming_language)>`_ programming language that is the primary development technology for Android OS. Also, you can find `Oracle docs on Java <http://docs.oracle.com/javase/>`_ useful.
|
||||
#. `Java Native Interface (JNI) <http://en.wikipedia.org/wiki/Java_Native_Interface>`_ that is a technology of running native code in Java virtual machine. Also, you can find `Oracle docs on JNI <http://docs.oracle.com/javase/7/docs/technotes/guides/jni/>`_ useful.
|
||||
#. `Android Activity <http://developer.android.com/training/basics/activity-lifecycle/starting.html>`_ and its lifecycle, that is an essential Android API class.
|
||||
#. OpenCV development will certainly require some knowlege of the `Android Camera <http://developer.android.com/guide/topics/media/camera.html>`_ specifics.
|
||||
|
||||
Quick environment setup for Android development
|
||||
===============================================
|
||||
|
||||
If you are making a clean environment install, then you can try `Tegra Android Development Pack <http://developer.nvidia.com/mobile/tegra-android-development-pack>`_
|
||||
If you are making a clean environment install, then you can try `Tegra Android Development Pack <https://developer.nvidia.com/tegra-android-development-pack>`_
|
||||
(**TADP**) released by **NVIDIA**.
|
||||
|
||||
.. note:: Starting the *version 2.0* the TADP package includes *OpenCV for Tegra* SDK that is a regular *OpenCV4Android SDK* extended with Tegra-specific stuff.
|
||||
|
||||
When unpacked, TADP will cover all of the environment setup automatically and you can skip the rest of the guide.
|
||||
|
||||
If you are a beginner in Android development then we also recommend you to start with TADP.
|
||||
|
||||
.. note:: *NVIDIA*\ 's Tegra Android Development Pack includes some special features for |Nvidia_Tegra_Platform|_ but its use is not limited to *Tegra* devices only.
|
||||
.. note:: *NVIDIA*\ 's Tegra Android Development Pack includes some special features for
|
||||
|Nvidia_Tegra_Platform|_ but its use is not limited to *Tegra* devices only.
|
||||
|
||||
* You need at least *1.6 Gb* free disk space for the install.
|
||||
* You need at least *1.6 Gb* free disk space for the install.
|
||||
|
||||
* TADP will download Android SDK platforms and Android NDK from Google's server, so Internet connection is required for the installation.
|
||||
* TADP will download Android SDK platforms and Android NDK from Google's server, so Internet
|
||||
connection is required for the installation.
|
||||
|
||||
* TADP may ask you to flash your development kit at the end of installation process. Just skip this step if you have no |Tegra_Development_Kit|_\ .
|
||||
* TADP may ask you to flash your development kit at the end of installation process. Just skip
|
||||
this step if you have no |Tegra_Development_Kit|_\ .
|
||||
|
||||
* (``UNIX``) TADP will ask you for *root* in the middle of installation, so you need to be a member of *sudo* group.
|
||||
* (``UNIX``) TADP will ask you for *root* in the middle of installation, so you need to be a
|
||||
member of *sudo* group.
|
||||
|
||||
..
|
||||
|
||||
|
||||
.. |Nvidia_Tegra_Platform| replace:: *NVIDIA*\ ’s Tegra platform
|
||||
.. _Nvidia_Tegra_Platform: http://www.nvidia.com/object/tegra-3-processor.html
|
||||
.. |Tegra_Development_Kit| replace:: Tegra Development Kit
|
||||
@@ -53,6 +69,7 @@ If you are a beginner in Android development then we also recommend you to start
|
||||
|
||||
.. _Android_Environment_Setup_Lite:
|
||||
|
||||
|
||||
Manual environment setup for Android development
|
||||
================================================
|
||||
|
||||
@@ -61,21 +78,24 @@ Development in Java
|
||||
|
||||
You need the following software to be installed in order to develop for Android in Java:
|
||||
|
||||
#. **Sun JDK 6**
|
||||
#. **Sun JDK 6** (Sun JDK 7 is also possible)
|
||||
|
||||
Visit `Java SE Downloads page <http://www.oracle.com/technetwork/java/javase/downloads/>`_ and download an installer for your OS.
|
||||
Visit `Java SE Downloads page <http://www.oracle.com/technetwork/java/javase/downloads/>`_
|
||||
and download an installer for your OS.
|
||||
|
||||
Here is a detailed :abbr:`JDK (Java Development Kit)` `installation guide <http://source.android.com/source/initializing.html#installing-the-jdk>`_
|
||||
Here is a detailed :abbr:`JDK (Java Development Kit)`
|
||||
`installation guide <http://source.android.com/source/initializing.html#installing-the-jdk>`_
|
||||
for Ubuntu and Mac OS (only JDK sections are applicable for OpenCV)
|
||||
|
||||
.. note:: OpenJDK is not suitable for Android development, since Android SDK supports only Sun JDK.
|
||||
If you use Ubuntu, after installation of Sun JDK you should run the following command to set Sun java environment:
|
||||
If you use Ubuntu, after installation of Sun JDK you should run the following command to set
|
||||
Sun java environment:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo update-java-alternatives --set java-6-sun
|
||||
|
||||
.. **TODO:** add a note on Sun/Oracle Java installation on Ubuntu 12.
|
||||
.. TODO: Add a note on Sun/Oracle Java installation on Ubuntu 12.
|
||||
|
||||
#. **Android SDK**
|
||||
|
||||
@@ -83,69 +103,93 @@ You need the following software to be installed in order to develop for Android
|
||||
|
||||
Here is Google's `install guide <http://developer.android.com/sdk/installing.html>`_ for the SDK.
|
||||
|
||||
.. note:: If you choose SDK packed into a Windows installer, then you should have 32-bit JRE installed. It is not a prerequisite for Android development, but installer is a x86 application and requires 32-bit Java runtime.
|
||||
.. note:: You can choose downloading **ADT Bundle package** that in addition to Android SDK Tools includes
|
||||
Eclipse + ADT + NDK/CDT plugins, Android Platform-tools, the latest Android platform and the latest
|
||||
Android system image for the emulator - this is the best choice for those who is setting up Android
|
||||
development environment the first time!
|
||||
|
||||
.. note:: If you are running x64 version of Ubuntu Linux, then you need ia32 shared libraries for use on amd64 and ia64 systems to be installed. You can install them with the following command:
|
||||
.. note:: If you are running x64 version of Ubuntu Linux, then you need ia32 shared libraries
|
||||
for use on amd64 and ia64 systems to be installed. You can install them with the
|
||||
following command:
|
||||
|
||||
.. code-block:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt-get install ia32-libs
|
||||
sudo apt-get install ia32-libs
|
||||
|
||||
For Red Hat based systems the following command might be helpful:
|
||||
For Red Hat based systems the following command might be helpful:
|
||||
|
||||
.. code-block:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
sudo yum install libXtst.i386
|
||||
sudo yum install libXtst.i386
|
||||
|
||||
#. **Android SDK components**
|
||||
|
||||
You need the following SDK components to be installed:
|
||||
|
||||
* *Android SDK Tools, revision14* or newer.
|
||||
* *Android SDK Tools, revision 20* or newer.
|
||||
|
||||
Older revisions should also work, but they are not recommended.
|
||||
|
||||
* *SDK Platform Android 3.0*, ``API 11`` and *Android 2.3.1*, ``API 9``.
|
||||
* *SDK Platform Android 3.0* (``API 11``).
|
||||
|
||||
The minimal platform supported by OpenCV Java API is **Android 2.2** (``API 8``). This is also the minimum API Level required for the provided samples to run.
|
||||
The minimal platform supported by OpenCV Java API is **Android 2.2** (``API 8``). This is also
|
||||
the minimum API Level required for the provided samples to run.
|
||||
See the ``<uses-sdk android:minSdkVersion="8"/>`` tag in their **AndroidManifest.xml** files.
|
||||
But for successful compilation of some samples the **target** platform should be set to Android 3.0 (API 11) or higher. It will not prevent them from running on Android 2.2.
|
||||
But for successful compilation the **target** platform should be set to Android 3.0 (API 11) or higher. It will not prevent them from running on Android 2.2.
|
||||
|
||||
.. image:: images/android_sdk_and_avd_manager.png
|
||||
:height: 500px
|
||||
:alt: Android SDK Manager
|
||||
:align: center
|
||||
|
||||
See `Adding Platforms and Packages <http://developer.android.com/sdk/installing/adding-packages.html>`_ for help with installing/updating SDK components.
|
||||
See `Adding Platforms and Packages <http://developer.android.com/sdk/installing/adding-packages.html>`_
|
||||
for help with installing/updating SDK components.
|
||||
|
||||
#. **Eclipse IDE**
|
||||
|
||||
Check the `Android SDK System Requirements <http://developer.android.com/sdk/requirements.html>`_ document for a list of Eclipse versions that are compatible with the Android SDK.
|
||||
For OpenCV 2.4.x we recommend **Eclipse 3.7 (Indigo)** or later versions. They work well for OpenCV under both Windows and Linux.
|
||||
Check the `Android SDK System Requirements <http://developer.android.com/sdk/requirements.html>`_
|
||||
document for a list of Eclipse versions that are compatible with the Android SDK.
|
||||
For OpenCV 2.4.x we recommend **Eclipse 3.7 (Indigo)** or **Eclipse 4.2 (Juno)**. They work well for
|
||||
OpenCV under both Windows and Linux.
|
||||
|
||||
If you have no Eclipse installed, you can get it from the `official site <http://www.eclipse.org/downloads/>`_.
|
||||
|
||||
#. **ADT plugin for Eclipse**
|
||||
|
||||
These instructions are copied from `Android Developers site <http://developer.android.com/sdk/installing/installing-adt.html>`_, check it out in case of any ADT-related problem.
|
||||
These instructions are copied from
|
||||
`Android Developers site <http://developer.android.com/sdk/installing/installing-adt.html>`_,
|
||||
check it out in case of any ADT-related problem.
|
||||
|
||||
Assuming that you have Eclipse IDE installed, as described above, follow these steps to download and install the ADT plugin:
|
||||
Assuming that you have Eclipse IDE installed, as described above, follow these steps to download
|
||||
and install the ADT plugin:
|
||||
|
||||
#. Start Eclipse, then select :menuselection:`Help --> Install New Software...`
|
||||
#. Click :guilabel:`Add` (in the top-right corner).
|
||||
#. In the :guilabel:`Add Repository` dialog that appears, enter "ADT Plugin" for the Name and the following URL for the Location:
|
||||
#. In the :guilabel:`Add Repository` dialog that appears, enter "ADT Plugin" for the Name and the
|
||||
following URL for the Location:
|
||||
|
||||
https://dl-ssl.google.com/android/eclipse/
|
||||
|
||||
#. Click :guilabel:`OK`
|
||||
|
||||
.. note:: If you have trouble acquiring the plugin, try using "http" in the Location URL, instead of "https" (https is preferred for security reasons).
|
||||
.. note:: If you have trouble acquiring the plugin, try using "http" in the Location URL,
|
||||
instead of "https" (https is preferred for security reasons).
|
||||
|
||||
#. In the :guilabel:`Available Software` dialog, select the checkbox next to :guilabel:`Developer Tools` and click :guilabel:`Next`.
|
||||
#. In the :guilabel:`Available Software` dialog, select the checkbox next to
|
||||
:guilabel:`Developer Tools` and click :guilabel:`Next`.
|
||||
#. In the next window, you'll see a list of the tools to be downloaded. Click :guilabel:`Next`.
|
||||
|
||||
.. note:: If you also plan to develop native C++ code with Android NDK don't forget to
|
||||
enable `NDK Plugins` installations as well.
|
||||
|
||||
.. image:: images/eclipse_inst_adt.png
|
||||
:alt: ADT installation
|
||||
:align: center
|
||||
|
||||
|
||||
#. Read and accept the license agreements, then click :guilabel:`Finish`.
|
||||
|
||||
.. note:: If you get a security warning saying that the authenticity or validity of the software can't be established, click :guilabel:`OK`.
|
||||
.. note:: If you get a security warning saying that the authenticity or validity of the software
|
||||
can't be established, click :guilabel:`OK`.
|
||||
|
||||
#. When the installation completes, restart Eclipse.
|
||||
|
||||
@@ -158,39 +202,26 @@ You need the following software to be installed in order to develop for Android
|
||||
|
||||
To compile C++ code for Android platform you need ``Android Native Development Kit`` (*NDK*).
|
||||
|
||||
You can get the latest version of NDK from the `download page <http://developer.android.com/tools/sdk/ndk/index.html>`_. To install Android NDK just extract the archive to some folder on your computer. Here are `installation instructions <http://developer.android.com/tools/sdk/ndk/index.html#Installing>`_.
|
||||
You can get the latest version of NDK from the
|
||||
`download page <http://developer.android.com/tools/sdk/ndk/index.html>`_.
|
||||
To install Android NDK just extract the archive to some folder on your computer. Here are
|
||||
`installation instructions <http://developer.android.com/tools/sdk/ndk/index.html#Installing>`_.
|
||||
|
||||
.. note:: Before start you can read official Android NDK documentation which is in the Android NDK archive, in the folder :file:`docs/`.
|
||||
|
||||
The main article about using Android NDK build system is in the :file:`ANDROID-MK.html` file.
|
||||
|
||||
Some additional information you can find in the :file:`APPLICATION-MK.html`, :file:`NDK-BUILD.html` files, and :file:`CPU-ARM-NEON.html`, :file:`CPLUSPLUS-SUPPORT.html`, :file:`PREBUILTS.html`.
|
||||
.. note:: Before start you can read official Android NDK documentation which is in the Android
|
||||
NDK archive, in the folder :file:`docs/`.
|
||||
The main article about using Android NDK build system is in the :file:`ANDROID-MK.html` file.
|
||||
Some additional information you can find in
|
||||
the :file:`APPLICATION-MK.html`, :file:`NDK-BUILD.html` files,
|
||||
and :file:`CPU-ARM-NEON.html`, :file:`CPLUSPLUS-SUPPORT.html`, :file:`PREBUILTS.html`.
|
||||
|
||||
#. **CDT plugin for Eclipse**
|
||||
|
||||
There are several possible ways to integrate compilation of C++ code by Android NDK into Eclipse compilation process.
|
||||
We recommend the approach based on Eclipse :abbr:`CDT(C/C++ Development Tooling)` Builder.
|
||||
If you selected for installation the ``NDK plugins`` component of Eclipse ADT plugin (see the picture above) your Eclipse IDE
|
||||
should already have ``CDT plugin`` (that means ``C/C++ Development Tooling``).
|
||||
There are several possible ways to integrate compilation of C++ code by Android NDK into Eclipse
|
||||
compilation process. We recommend the approach based on Eclipse
|
||||
:abbr:`CDT(C/C++ Development Tooling)` Builder.
|
||||
|
||||
.. important:: Make sure your Eclipse IDE has the :abbr:`CDT(C/C++ Development Tooling)` plugin installed. Menu :guilabel:`Help -> About Eclipse SDK` and push :guilabel:`Installation Details` button.
|
||||
|
||||
.. image:: images/eclipse_inst_details.png
|
||||
:alt: Configure builders
|
||||
:align: center
|
||||
|
||||
To install the `CDT plugin <http://eclipse.org/cdt/>`_ use menu :guilabel:`Help -> Install New Software...`,
|
||||
then paste the CDT 8.0 repository URL http://download.eclipse.org/tools/cdt/releases/indigo as shown in the picture below and click :guilabel:`Add...`, name it *CDT* and click :guilabel:`OK`.
|
||||
|
||||
.. image:: images/eclipse_inst_cdt.png
|
||||
:alt: Configure builders
|
||||
:align: center
|
||||
|
||||
``CDT Main Features`` should be enough:
|
||||
|
||||
.. image:: images/eclipse_inst_cdt_2.png
|
||||
:alt: Configure builders
|
||||
:align: center
|
||||
|
||||
That's it. Compilation of C++ code is fully integrated into Eclipse building process now.
|
||||
|
||||
Android application structure
|
||||
=============================
|
||||
@@ -213,27 +244,32 @@ Usually source code of an Android application has the following structure:
|
||||
|
||||
- :file:`... other files ...`
|
||||
|
||||
where:
|
||||
Where:
|
||||
|
||||
* the :file:`src` folder contains Java code of the application,
|
||||
|
||||
* the :file:`res` folder contains resources of the application (images, xml files describing UI layout, etc),
|
||||
* the :file:`res` folder contains resources of the application (images, xml files describing UI
|
||||
layout, etc),
|
||||
|
||||
* the :file:`libs` folder will contain native libraries after a successful build,
|
||||
|
||||
* and the :file:`jni` folder contains C/C++ application source code and NDK's build scripts :file:`Android.mk` and :file:`Application.mk`
|
||||
producing the native libraries,
|
||||
* and the :file:`jni` folder contains C/C++ application source code and NDK's build scripts
|
||||
:file:`Android.mk` and :file:`Application.mk` producing the native libraries,
|
||||
|
||||
* :file:`AndroidManifest.xml` file presents essential information about application to the Android system
|
||||
(name of the Application, name of main application's package, components of the application, required permissions, etc).
|
||||
* :file:`AndroidManifest.xml` file presents essential information about application to the Android
|
||||
system (name of the Application, name of main application's package, components of the
|
||||
application, required permissions, etc).
|
||||
|
||||
It can be created using Eclipse wizard or :command:`android` tool from Android SDK.
|
||||
|
||||
* :file:`project.properties` is a text file containing information about target Android platform and other build details.
|
||||
This file is generated by Eclipse or can be created with :command:`android` tool included in Android SDK.
|
||||
* :file:`project.properties` is a text file containing information about target Android platform
|
||||
and other build details. This file is generated by Eclipse or can be created with
|
||||
:command:`android` tool included in Android SDK.
|
||||
|
||||
.. note:: Both :file:`AndroidManifest.xml` and :file:`project.properties` files are required to
|
||||
compile the C++ part of the application, since Android NDK build system relies on them.
|
||||
If any of these files does not exist, compile the Java part of the project before the C++ part.
|
||||
|
||||
.. note:: Both files (:file:`AndroidManifest.xml` and :file:`project.properties`) are required to compile the C++ part of the application,
|
||||
since Android NDK build system relies on them. If any of these files does not exist, compile the Java part of the project before the C++ part.
|
||||
|
||||
:file:`Android.mk` and :file:`Application.mk` scripts
|
||||
==================================================================
|
||||
@@ -254,16 +290,22 @@ The script :file:`Android.mk` usually has the following structure:
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
This is the minimal file :file:`Android.mk`, which builds C++ source code of an Android application. Note that the first two lines and the last line are mandatory for any :file:`Android.mk`.
|
||||
This is the minimal file :file:`Android.mk`, which builds C++ source code of an Android application.
|
||||
Note that the first two lines and the last line are mandatory for any :file:`Android.mk`.
|
||||
|
||||
Usually the file :file:`Application.mk` is optional, but in case of project using OpenCV, when STL and exceptions are used in C++, it also should be created. Example of the file :file:`Application.mk`:
|
||||
Usually the file :file:`Application.mk` is optional, but in case of project using OpenCV, when STL
|
||||
and exceptions are used in C++, it also should be created. Example of the file :file:`Application.mk`:
|
||||
|
||||
.. code-block:: make
|
||||
:linenos:
|
||||
|
||||
APP_STL := gnustl_static
|
||||
APP_CPPFLAGS := -frtti -fexceptions
|
||||
APP_ABI := armeabi-v7a
|
||||
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.
|
||||
|
||||
|
||||
.. _NDK_build_cli:
|
||||
@@ -273,6 +315,11 @@ Building application native part from command line
|
||||
|
||||
Here is the standard way to compile C++ part of an Android application:
|
||||
|
||||
.. warning:: We strongly reccomend using ``cmd.exe`` (standard Windows console) instead of Cygwin on
|
||||
**Windows**. Use the latter if only you're absolutely sure about, what you're doing. Cygwin
|
||||
is not really supported and we are unlikely to help you in case you encounter some
|
||||
problems with it. So, use it only if you're capable of handling the consequences yourself.
|
||||
|
||||
#. Open console and go to the root folder of an Android application
|
||||
|
||||
.. code-block:: bash
|
||||
@@ -285,7 +332,8 @@ Here is the standard way to compile C++ part of an Android application:
|
||||
|
||||
<path_where_NDK_is_placed>/ndk-build
|
||||
|
||||
.. note:: On Windows we recommend to use ``ndk-build.cmd`` in standard Windows console (``cmd.exe``) rather than the similar ``bash`` script in ``Cygwin`` shell.
|
||||
.. note:: On Windows we recommend to use ``ndk-build.cmd`` in standard Windows console (``cmd.exe``)
|
||||
rather than the similar ``bash`` script in ``Cygwin`` shell.
|
||||
|
||||
.. image:: images/ndk_build.png
|
||||
:alt: NDK build
|
||||
@@ -314,22 +362,29 @@ After that the Java part of the application can be (re)compiled (using either *E
|
||||
Building application native part from *Eclipse* (CDT Builder)
|
||||
=============================================================
|
||||
|
||||
There are several possible ways to integrate compilation of native C++ code by Android NDK into Eclipse build process.
|
||||
We recommend the approach based on Eclipse :abbr:`CDT(C/C++ Development Tooling)` Builder.
|
||||
There are several possible ways to integrate compilation of native C++ code by Android NDK into
|
||||
Eclipse build process. We recommend the approach based on Eclipse
|
||||
:abbr:`CDT(C/C++ Development Tooling)` Builder.
|
||||
|
||||
.. important:: Make sure your Eclipse IDE has the :abbr:`CDT(C/C++ Development Tooling)` plugin installed. Menu :guilabel:`Help -> About Eclipse SDK -> Installation Details`.
|
||||
.. important:: OpenCV for Android package since version 2.4.2 contains sample projects
|
||||
pre-configured CDT Builders. For your own projects follow the steps below.
|
||||
|
||||
.. image:: images/eclipse_inst_details.png
|
||||
:alt: Eclipse About
|
||||
:align: center
|
||||
#. Define the ``NDKROOT`` environment variable containing the path to Android NDK in your system
|
||||
(e.g. ``"X:\\Apps\\android-ndk-r8"`` or ``"/opt/android-ndk-r8"``).
|
||||
|
||||
.. important:: OpenCV for Android package since version 2.4.2 contains sample projects pre-configured CDT Builders. For your own projects follow the steps below.
|
||||
**On Windows** an environment variable can be set via
|
||||
:guilabel:`My Computer -> Properties -> Advanced -> Environment variables`.
|
||||
On Windows 7 it's also possible to use `setx <http://ss64.com/nt/setx.html>`_ command in a console session.
|
||||
|
||||
#. Define the ``NDKROOT`` environment variable containing the path to Android NDK in your system (e.g. ``"X:\\Apps\\android-ndk-r8"`` or ``"/opt/android-ndk-r8"``).
|
||||
**On Windows** an environment variable can be set via :guilabel:`My Computer -> Properties -> Advanced -> Environment variables` and restarting Eclipse.
|
||||
On Windows 7 it's also possible to use `setx <http://ss64.com/nt/setx.html>`_ command in a console session.
|
||||
**On Linux** and **MacOS** an environment variable can be set via appending a
|
||||
``"export VAR_NAME=VAR_VALUE"`` line to the :file:`"~/.bashrc"` file and logging off and then on.
|
||||
|
||||
**On Linux** and **MacOS** an environment variable can be set via appending a ``"export VAR_NAME=VAR_VALUE"`` line to the :file:`"~/.bashrc"` file and logging off and then on.
|
||||
.. note:: It's also possible to define the ``NDKROOT`` environment variable within Eclipse IDE,
|
||||
but it should be done for every new workspace you create. If you prefer this option better than setting system
|
||||
environment variable, open Eclipse menu :guilabel:`Window -> Preferences -> C/C++ -> Build -> Environment`,
|
||||
press the :guilabel:`Add...` button and set variable name to ``NDKROOT`` and value to local Android NDK path.
|
||||
|
||||
#. After that you need to **restart Eclipse** to apply the changes.
|
||||
|
||||
#. Open Eclipse and load the Android app project to configure.
|
||||
|
||||
@@ -345,13 +400,15 @@ We recommend the approach based on Eclipse :abbr:`CDT(C/C++ Development Tooling)
|
||||
:alt: Configure CDT
|
||||
:align: center
|
||||
|
||||
#. Select the project(s) to convert. Specify "Project type" = ``Makefile project``, "Toolchains" = ``Other Toolchain``.
|
||||
#. Select the project(s) to convert. Specify "Project type" = ``Makefile project``,
|
||||
"Toolchains" = ``Other Toolchain``.
|
||||
|
||||
.. image:: images/eclipse_cdt_cfg3.png
|
||||
:alt: Configure CDT
|
||||
:align: center
|
||||
|
||||
#. Open :guilabel:`Project Properties -> C/C++ Build`, unckeck ``Use default build command``, replace "Build command" text from ``"make"`` to
|
||||
#. Open :guilabel:`Project Properties -> C/C++ Build`, uncheck ``Use default build command``,
|
||||
replace "Build command" text from ``"make"`` to
|
||||
|
||||
``"${NDKROOT}/ndk-build.cmd"`` on Windows,
|
||||
|
||||
@@ -373,21 +430,32 @@ We recommend the approach based on Eclipse :abbr:`CDT(C/C++ Development Tooling)
|
||||
:alt: Configure CDT
|
||||
:align: center
|
||||
|
||||
#. If you open your C++ source file in Eclipse editor, you'll see syntax error notifications. They are not real errors, but additional CDT configuring is required.
|
||||
#. If you open your C++ source file in Eclipse editor, you'll see syntax error notifications.
|
||||
They are not real errors, but additional CDT configuring is required.
|
||||
|
||||
.. image:: images/eclipse_cdt_cfg7.png
|
||||
:alt: Configure CDT
|
||||
:align: center
|
||||
|
||||
#. Open :guilabel:`Project Properties -> C/C++ General -> Paths and Symbols` and add the following **Include** paths for **C++**:
|
||||
#. Open :guilabel:`Project Properties -> C/C++ General -> Paths and Symbols` and add the following
|
||||
**Include** paths for **C++**:
|
||||
|
||||
::
|
||||
|
||||
# for NDK r8 and prior:
|
||||
${NDKROOT}/platforms/android-9/arch-arm/usr/include
|
||||
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/include
|
||||
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include
|
||||
${ProjDirPath}/../../sdk/native/jni/include
|
||||
|
||||
::
|
||||
|
||||
# for NDK r8b and later:
|
||||
${NDKROOT}/platforms/android-9/arch-arm/usr/include
|
||||
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/include
|
||||
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include
|
||||
${ProjDirPath}/../../sdk/native/jni/include
|
||||
|
||||
The last path should be changed to the correct absolute or relative path to OpenCV4Android SDK location.
|
||||
|
||||
This should clear the syntax error notifications in Eclipse C++ editor.
|
||||
@@ -396,58 +464,65 @@ We recommend the approach based on Eclipse :abbr:`CDT(C/C++ Development Tooling)
|
||||
:alt: Configure CDT
|
||||
:align: center
|
||||
|
||||
.. note:: The latest Android NDK **r8b** uses different STL headers path. So if you use this NDK release add the following **Include** paths list instead:
|
||||
|
||||
::
|
||||
|
||||
${NDKROOT}/platforms/android-9/arch-arm/usr/include
|
||||
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/include
|
||||
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include
|
||||
${ProjDirPath}/../../sdk/native/jni/include
|
||||
|
||||
|
||||
Debugging and Testing
|
||||
=====================
|
||||
In this section we will give you some easy-to-follow instructions on how to set up an emulator or hardware device for testing and debugging an Android project.
|
||||
In this section we will give you some easy-to-follow instructions on how to set up an emulator or
|
||||
hardware device for testing and debugging an Android project.
|
||||
|
||||
AVD
|
||||
---
|
||||
AVD (*Android Virtual Device*) is not probably the most convenient way to test an OpenCV-dependent application, but sure the most uncomplicated one to configure.
|
||||
AVD (*Android Virtual Device*) is not probably the most convenient way to test an OpenCV-dependent
|
||||
application, but sure the most uncomplicated one to configure.
|
||||
|
||||
#. Assuming you already have *Android SDK* and *Eclipse IDE* installed, in Eclipse go :guilabel:`Window -> AVD Manager`.
|
||||
#. Assuming you already have *Android SDK* and *Eclipse IDE* installed, in Eclipse go
|
||||
:guilabel:`Window -> AVD Manager`.
|
||||
|
||||
.. **TBD:** how to start AVD Manager without Eclipse...
|
||||
.. TODO: how to start AVD Manager without Eclipse...
|
||||
|
||||
#. Press the :guilabel:`New` button in :guilabel:`AVD Manager` window.
|
||||
#. :guilabel:`Create new Android Virtual Device` window will let you select some properties for your new device, like target API level, size of SD-card and other.
|
||||
#. :guilabel:`Create new Android Virtual Device` window will let you select some properties for your
|
||||
new device, like target API level, size of SD-card and other.
|
||||
|
||||
.. image:: images/AVD_create.png
|
||||
:alt: Configure builders
|
||||
:align: center
|
||||
|
||||
#. When you click the :guilabel:`Create AVD` button, your new AVD will be availible in :guilabel:`AVD Manager`.
|
||||
#. Press :guilabel:`Start` to launch the device. Be aware that any AVD (a.k.a. Emulator) is usually much slower than a hardware Android device, so it may take up to several minutes to start.
|
||||
#. Go :guilabel:`Run -> Run/Debug` in Eclipse IDE to run your application in regular or debugging mode. :guilabel:`Device Chooser` will let you choose among the running devices or to start a new one.
|
||||
#. Press :guilabel:`Start` to launch the device. Be aware that any AVD (a.k.a. Emulator) is usually
|
||||
much slower than a hardware Android device, so it may take up to several minutes to start.
|
||||
#. Go :guilabel:`Run -> Run/Debug` in Eclipse IDE to run your application in regular or debugging
|
||||
mode. :guilabel:`Device Chooser` will let you choose among the running devices or to start a new one.
|
||||
|
||||
Hardware Device
|
||||
---------------
|
||||
If you have an Android device, you can use it to test and debug your applications. This way is more authentic, though a little bit harder to set up. You need to make some actions for Windows and Linux operating systems to be able to work with Android devices. No extra actions are required for Mac OS. See detailed information on configuring hardware devices in subsections below.
|
||||
If you have an Android device, you can use it to test and debug your applications. This way is more
|
||||
authentic, though a little bit harder to set up. You need to make some actions for Windows and Linux
|
||||
operating systems to be able to work with Android devices. No extra actions are required for Mac OS.
|
||||
See detailed information on configuring hardware devices in subsections below.
|
||||
|
||||
You may also consult the official `Android Developers site instructions <http://developer.android.com/tools/device.html>`_ for more information.
|
||||
You may also consult the official
|
||||
`Android Developers site instructions <http://developer.android.com/tools/device.html>`_
|
||||
for more information.
|
||||
|
||||
Windows host computer
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
#. Enable USB debugging on the Android device (via :guilabel:`Settings` menu).
|
||||
#. Attach the Android device to your PC with a USB cable.
|
||||
#. Go to :guilabel:`Start Menu` and **right-click** on :guilabel:`Computer`. Select :guilabel:`Manage` in the context menu. You may be asked for Administrative permissions.
|
||||
#. Select :guilabel:`Device Manager` in the left pane and find an unknown device in the list. You may try unplugging it and then plugging back in order to check whether it's your exact equipment appears in the list.
|
||||
#. Go to :guilabel:`Start Menu` and **right-click** on :guilabel:`Computer`.
|
||||
Select :guilabel:`Manage` in the context menu. You may be asked for Administrative permissions.
|
||||
#. Select :guilabel:`Device Manager` in the left pane and find an unknown device in the list.
|
||||
You may try unplugging it and then plugging back in order to check whether it's your exact
|
||||
equipment appears in the list.
|
||||
|
||||
.. image:: images/usb_device_connect_01.png
|
||||
:alt: Unknown device
|
||||
:align: center
|
||||
|
||||
#. Try your luck installing `Google USB drivers` without any modifications: **right-click** on the unknown device, select :guilabel:`Properties` menu item --> :guilabel:`Details` tab --> :guilabel:`Update Driver` button.
|
||||
#. Try your luck installing `Google USB drivers` without any modifications: **right-click** on the
|
||||
unknown device, select :guilabel:`Properties` menu item --> :guilabel:`Details` tab -->
|
||||
:guilabel:`Update Driver` button.
|
||||
|
||||
.. image:: images/usb_device_connect_05.png
|
||||
:alt: Device properties
|
||||
@@ -465,13 +540,15 @@ Windows host computer
|
||||
:alt: Browse for driver
|
||||
:align: center
|
||||
|
||||
#. If you get the prompt to install unverified drivers and report about success - you've finished with USB driver installation.
|
||||
#. If you get the prompt to install unverified drivers and report about success - you've finished
|
||||
with USB driver installation.
|
||||
|
||||
.. image:: images/usb_device_connect_08.png
|
||||
:alt: Install prompt
|
||||
:align: center
|
||||
|
||||
` `
|
||||
.. FIXME: All such places should be replaced with something else! This is a bad separator.
|
||||
|
||||
.. image:: images/usb_device_connect_09.png
|
||||
:alt: Installed OK
|
||||
@@ -483,13 +560,15 @@ Windows host computer
|
||||
:alt: No driver
|
||||
:align: center
|
||||
|
||||
#. Again **right-click** on the unknown device, select :guilabel:`Properties --> Details --> Hardware Ids` and copy the line like ``USB\VID_XXXX&PID_XXXX&MI_XX``.
|
||||
#. Again **right-click** on the unknown device, select :guilabel:`Properties --> Details --> Hardware Ids`
|
||||
and copy the line like ``USB\VID_XXXX&PID_XXXX&MI_XX``.
|
||||
|
||||
.. image:: images/usb_device_connect_02.png
|
||||
:alt: Device properties details
|
||||
:align: center
|
||||
|
||||
#. Now open file :file:`<Android SDK folder>/extras/google/usb_driver/android_winusb.inf`. Select either ``Google.NTx86`` or ``Google.NTamd64`` section depending on your host system architecture.
|
||||
#. Now open file :file:`<Android SDK folder>/extras/google/usb_driver/android_winusb.inf`. Select
|
||||
either ``Google.NTx86`` or ``Google.NTamd64`` section depending on your host system architecture.
|
||||
|
||||
.. image:: images/usb_device_connect_03.png
|
||||
:alt: "android_winusb.inf"
|
||||
@@ -543,27 +622,34 @@ Windows host computer
|
||||
:alt: "adb devices"
|
||||
:align: center
|
||||
|
||||
#. Now, in Eclipse go :guilabel:`Run -> Run/Debug` to run your application in regular or debugging mode. :guilabel:`Device Chooser` will let you choose among the devices.
|
||||
#. Now, in Eclipse go :guilabel:`Run -> Run/Debug` to run your application in regular or debugging
|
||||
mode. :guilabel:`Device Chooser` will let you choose among the devices.
|
||||
|
||||
Linux host computer
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
By default Linux doesn't recognize Android devices, but it's easy to fix this issue. On Ubuntu Linux you have to create a new **/etc/udev/rules.d/51-android.rules** configuration file that contains information about your Android device. You may find some Vendor ID's `here <http://developer.android.com/tools/device.html#VendorIds>`_ or execute :command:`lsusb` command to view VendorID of plugged Android device. Here is an example of such file for LG device:
|
||||
By default Linux doesn't recognize Android devices, but it's easy to fix this issue. On Ubuntu Linux
|
||||
you have to create a new **/etc/udev/rules.d/51-android.rules** configuration file that contains
|
||||
information about your Android device. You may find some Vendor ID's
|
||||
`here <http://developer.android.com/tools/device.html#VendorIds>`_ or execute :command:`lsusb`
|
||||
command to view VendorID of plugged Android device. Here is an example of such file for LG device:
|
||||
|
||||
.. code-block:: guess
|
||||
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="1004", MODE="0666", GROUP="plugdev"
|
||||
|
||||
Then restart your adb server (even better to restart the system), plug in your Android device and execute :command:`adb devices` command. You will see the list of attached devices:
|
||||
Then restart your adb server (even better to restart the system), plug in your Android device and
|
||||
execute :command:`adb devices` command. You will see the list of attached devices:
|
||||
|
||||
.. image:: images/usb_device_connect_ubuntu.png
|
||||
:alt: List of attached devices
|
||||
:align: center
|
||||
|
||||
MacOS host computer
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
Mac OS host computer
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
No actions are required, just connect your device via USB and run ``adb devices`` to check connection.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
@@ -1,13 +1,13 @@
|
||||
|
||||
.. _dev_with_OCV_on_Android:
|
||||
|
||||
|
||||
Android development with OpenCV
|
||||
Android Development with OpenCV
|
||||
*******************************
|
||||
|
||||
This tutorial is created to help you use OpenCV library within your Android project.
|
||||
This tutorial has been created to help you use OpenCV library within your Android project.
|
||||
|
||||
This guide was written with Windows 7 in mind, though it should work with any other OS supported by OpenCV4Android SDK.
|
||||
This guide was written with Windows 7 in mind, though it should work with any other OS supported by
|
||||
OpenCV4Android SDK.
|
||||
|
||||
This tutorial assumes you have the following installed and configured:
|
||||
|
||||
@@ -23,121 +23,132 @@ This tutorial assumes you have the following installed and configured:
|
||||
|
||||
If you need help with anything of the above, you may refer to our :ref:`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.
|
||||
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.
|
||||
|
||||
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 forum <http://answers.opencv.org>`_ . We'll do our best to help you out.
|
||||
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 forum <http://answers.opencv.org>`_ . We'll do our best to help you out.
|
||||
|
||||
Using OpenCV library within your Android project
|
||||
|
||||
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 `slides <https://docs.google.com/a/itseez.com/presentation/d/1EO_1kijgBg_BsjNp2ymk-aarg-0K279_1VZRcPplSuk/present#slide=id.p>`_.
|
||||
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
|
||||
`slides <https://docs.google.com/a/itseez.com/presentation/d/1EO_1kijgBg_BsjNp2ymk-aarg-0K279_1VZRcPplSuk/present#slide=id.p>`_.
|
||||
|
||||
|
||||
Java
|
||||
----
|
||||
Application development with async initialization
|
||||
|
||||
Application Development with Async Initialization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Using async initialization is a **recommended** way for application development. It uses the OpenCV Manager to access OpenCV libraries externally installed in the target system.
|
||||
Using async initialization is a **recommended** way for application development. It uses the OpenCV
|
||||
Manager to access OpenCV libraries externally installed in the target system.
|
||||
|
||||
#. Add OpenCV library project to your workspace. Use menu :guilabel:`File -> Import -> Existing project in your workspace`,
|
||||
press :guilabel:`Browse` button and locate OpenCV4Android SDK (:file:`OpenCV-2.4.2-android-sdk/sdk`).
|
||||
#. Add OpenCV library project to your workspace. Use menu
|
||||
:guilabel:`File -> Import -> Existing project in your workspace`.
|
||||
|
||||
Press :guilabel:`Browse` button and locate OpenCV4Android SDK
|
||||
(:file:`OpenCV-2.4.5-android-sdk/sdk`).
|
||||
|
||||
.. image:: images/eclipse_opencv_dependency0.png
|
||||
:alt: Add dependency from OpenCV library
|
||||
:align: center
|
||||
|
||||
#. In application project add a reference to the OpenCV Java SDK in :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.2``.
|
||||
#. In application project add a reference to the OpenCV Java SDK in
|
||||
:guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.5``.
|
||||
|
||||
.. image:: images/eclipse_opencv_dependency1.png
|
||||
:alt: Add dependency from OpenCV library
|
||||
:align: center
|
||||
|
||||
To run OpenCV Manager-based application for the first time you need to install package with the `OpenCV Manager` for your platform. Armeabi, Armeabi-v7a with NEON, x86 and MIPS achitectures supported.
|
||||
You can do it using Google Play Market or manually with ``adb`` tool:
|
||||
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.
|
||||
|
||||
.. code-block:: sh
|
||||
:linenos:
|
||||
|
||||
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.2_Manager.apk
|
||||
|
||||
For rare cases if NEON instruction set is not supported you need to install aditional OpenCV Library package:
|
||||
|
||||
.. code-block:: sh
|
||||
:linenos:
|
||||
|
||||
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.2_binary_pack_armv7a.apk
|
||||
|
||||
There is a very base code snippet implementing the async initialization. It shows basic principles. See the "15-puzzle" OpenCV sample 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.
|
||||
|
||||
.. code-block:: java
|
||||
:linenos:
|
||||
|
||||
public class MyActivity extends Activity implements HelperCallbackInterface
|
||||
{
|
||||
private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
// Create and set View
|
||||
mView = new puzzle15View(mAppContext);
|
||||
setContentView(mView);
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
public class Sample1Java extends Activity implements CvCameraViewListener {
|
||||
|
||||
/** Call on every application resume **/
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
Log.i(TAG, "called onResume");
|
||||
super.onResume();
|
||||
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
mOpenCvCameraView.enableView();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Log.i(TAG, "Trying to load OpenCV library");
|
||||
if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack))
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
Log.e(TAG, "Cannot connect to OpenCV Manager");
|
||||
super.onResume();
|
||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_5, this, mLoaderCallback);
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
It this case application works with OpenCV Manager in asynchronous fashion. ``OnManagerConnected`` callback will be called in UI thread, when initialization finishes.
|
||||
Please note, that it is not allowed to use OpenCV calls or load OpenCV-dependent native libs before invoking this callback.
|
||||
It this case application works with OpenCV Manager in asynchronous fashion. ``OnManagerConnected``
|
||||
callback will be called in UI thread, when initialization finishes. Please note, that it is not
|
||||
allowed to use OpenCV calls or load OpenCV-dependent native libs before invoking this callback.
|
||||
Load your own native libraries that depend on OpenCV after the successful OpenCV initialization.
|
||||
Default BaseLoaderCallback implementation treat application context as Activity and calls Activity.finish() method to exit in case of initialization failure.
|
||||
To override this behavior you need to override finish() method of BaseLoaderCallback class and implement your own finalization method.
|
||||
Default ``BaseLoaderCallback`` implementation treat application context as Activity and calls
|
||||
``Activity.finish()`` method to exit in case of initialization failure. To override this behavior
|
||||
you need to override ``finish()`` method of ``BaseLoaderCallback`` class and implement your own
|
||||
finalization method.
|
||||
|
||||
Application development with static initialization
|
||||
|
||||
Application Development with Static Initialization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
According to this approach all OpenCV binaries are included into your application package. It is designed mostly for development purposes.
|
||||
This approach is deprecated for the production code, release package is recommended to communicate with OpenCV Manager via the async initialization described above.
|
||||
According to this approach all OpenCV binaries are included into your application package. It is
|
||||
designed mostly for development purposes. This approach is deprecated for the production code,
|
||||
release package is recommended to communicate with OpenCV Manager via the async initialization
|
||||
described above.
|
||||
|
||||
#. Add the OpenCV library project to your workspace the same way as for the async initialization above.
|
||||
Use menu :guilabel:`File -> Import -> Existing project in your workspace`, push :guilabel:`Browse` button and select OpenCV SDK path (:file:`OpenCV-2.4.2-android-sdk/sdk`).
|
||||
#. Add the OpenCV library project to your workspace the same way as for the async initialization
|
||||
above. Use menu :guilabel:`File -> Import -> Existing project in your workspace`,
|
||||
press :guilabel:`Browse` button and select OpenCV SDK path
|
||||
(:file:`OpenCV-2.4.5-android-sdk/sdk`).
|
||||
|
||||
.. image:: images/eclipse_opencv_dependency0.png
|
||||
:alt: Add dependency from OpenCV library
|
||||
:align: center
|
||||
|
||||
#. In the application project add a reference to the OpenCV4Android SDK in :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.2``;
|
||||
#. In the application project add a reference to the OpenCV4Android SDK in
|
||||
:guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.5``;
|
||||
|
||||
.. image:: images/eclipse_opencv_dependency1.png
|
||||
:alt: Add dependency from OpenCV library
|
||||
:align: center
|
||||
|
||||
#. If your application project **doesn't have a JNI part**, just copy the corresponding OpenCV native libs from :file:`<OpenCV-2.4.2-android-sdk>/sdk/native/libs/<target_arch>` to your project directory to folder :file:`libs/<target_arch>`.
|
||||
#. If your application project **doesn't have a JNI part**, just copy the corresponding OpenCV
|
||||
native libs from :file:`<OpenCV-2.4.5-android-sdk>/sdk/native/libs/<target_arch>` to your
|
||||
project directory to folder :file:`libs/<target_arch>`.
|
||||
|
||||
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 $(CLEAR_VARS)"`` and before ``"include path_to_OpenCV-2.4.2-android-sdk/sdk/native/jni/OpenCV.mk"``
|
||||
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 $(CLEAR_VARS)"`` and before
|
||||
``"include path_to_OpenCV-2.4.5-android-sdk/sdk/native/jni/OpenCV.mk"``
|
||||
|
||||
.. code-block:: make
|
||||
:linenos:
|
||||
@@ -157,12 +168,14 @@ This approach is deprecated for the production code, release package is recommen
|
||||
OPENCV_INSTALL_MODULES:=on
|
||||
include ../../sdk/native/jni/OpenCV.mk
|
||||
|
||||
After that the OpenCV libraries will be copied to your application :file:`libs` folder during the JNI part build.
|
||||
After that the OpenCV libraries will be copied to your application :file:`libs` folder during
|
||||
the JNI build.v
|
||||
|
||||
Eclipse will automatically include all the libraries from the :file:`libs` folder to the application package (APK).
|
||||
Eclipse will automatically include all the libraries from the :file:`libs` folder to the
|
||||
application package (APK).
|
||||
|
||||
#. The last step of enabling OpenCV in your application is Java initialization code before call to OpenCV API.
|
||||
It can be done, for example, in the static section of the ``Activity`` class:
|
||||
#. The last step of enabling OpenCV in your application is Java initialization code before calling
|
||||
OpenCV API. It can be done, for example, in the static section of the ``Activity`` class:
|
||||
|
||||
.. code-block:: java
|
||||
:linenos:
|
||||
@@ -173,7 +186,8 @@ This approach is deprecated for the production code, release package is recommen
|
||||
}
|
||||
}
|
||||
|
||||
If you application includes other OpenCV-dependent native libraries you should load them **after** OpenCV initialization:
|
||||
If you application includes other OpenCV-dependent native libraries you should load them
|
||||
**after** OpenCV initialization:
|
||||
|
||||
.. code-block:: java
|
||||
:linenos:
|
||||
@@ -187,39 +201,45 @@ This approach is deprecated for the production code, release package is recommen
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Native/C++
|
||||
----------
|
||||
|
||||
To build your own Android application, which uses OpenCV from native part, the following steps should be done:
|
||||
To build your own Android application, using OpenCV as native part, the following steps should be
|
||||
taken:
|
||||
|
||||
#. You can use an environment variable to specify the location of OpenCV package or just hardcode absolute or relative path in the :file:`jni/Android.mk` of your projects.
|
||||
#. You can use an environment variable to specify the location of OpenCV package or just hardcode
|
||||
absolute or relative path in the :file:`jni/Android.mk` of your projects.
|
||||
|
||||
#. The file :file:`jni/Android.mk` should be written for the current application using the common rules for this file.
|
||||
#. The file :file:`jni/Android.mk` should be written for the current application using the common
|
||||
rules for this file.
|
||||
|
||||
For detailed information see the Android NDK documentation from the Android NDK archive, in the file
|
||||
:file:`<path_where_NDK_is_placed>/docs/ANDROID-MK.html`
|
||||
For detailed information see the Android NDK documentation from the Android NDK archive, in the
|
||||
file :file:`<path_where_NDK_is_placed>/docs/ANDROID-MK.html`.
|
||||
|
||||
#. The line
|
||||
#. The following line:
|
||||
|
||||
.. code-block:: make
|
||||
|
||||
include C:\Work\OpenCV4Android\OpenCV-2.4.2-android-sdk\sdk\native\jni\OpenCV.mk
|
||||
include C:\Work\OpenCV4Android\OpenCV-2.4.5-android-sdk\sdk\native\jni\OpenCV.mk
|
||||
|
||||
should be inserted into the :file:`jni/Android.mk` file **after** the line
|
||||
Should be inserted into the :file:`jni/Android.mk` file **after** this line:
|
||||
|
||||
.. code-block:: make
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
#. 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.
|
||||
#. 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-block:: make
|
||||
.. code-block:: make
|
||||
|
||||
OPENCV_INSTALL_MODULES:=on
|
||||
OPENCV_INSTALL_MODULES:=on
|
||||
|
||||
Copies necessary OpenCV dynamic libs to the project ``libs`` folder in order to include them into the APK.
|
||||
Copies necessary OpenCV dynamic libs to the project ``libs`` folder in order to include them
|
||||
into the APK.
|
||||
|
||||
.. code-block:: make
|
||||
|
||||
@@ -231,7 +251,8 @@ To build your own Android application, which uses OpenCV from native part, the f
|
||||
|
||||
OPENCV_LIB_TYPE:=STATIC
|
||||
|
||||
Perform static link with OpenCV. By default dynamic link is used and the project JNI lib depends on ``libopencv_java.so``.
|
||||
Perform static linking with OpenCV. By default dynamic link is used and the project JNI lib
|
||||
depends on ``libopencv_java.so``.
|
||||
|
||||
#. The file :file:`Application.mk` should exist and should contain lines:
|
||||
|
||||
@@ -240,145 +261,46 @@ To build your own Android application, which uses OpenCV from native part, the f
|
||||
APP_STL := gnustl_static
|
||||
APP_CPPFLAGS := -frtti -fexceptions
|
||||
|
||||
Also the line like this one:
|
||||
Also, the line like this one:
|
||||
|
||||
.. code-block:: make
|
||||
|
||||
APP_ABI := armeabi-v7a
|
||||
|
||||
should specify the application target platforms.
|
||||
Should specify the application target platforms.
|
||||
|
||||
In some cases a linkage error (like ``"In function 'cv::toUtf16(std::basic_string<...>... undefined reference to 'mbstowcs'"``) happens
|
||||
when building an application JNI library depending on OpenCV.
|
||||
The following line in the :file:`Application.mk` usually fixes it:
|
||||
In some cases a linkage error (like ``"In function 'cv::toUtf16(std::basic_string<...>...
|
||||
undefined reference to 'mbstowcs'"``) happens when building an application JNI library,
|
||||
depending on OpenCV. The following line in the :file:`Application.mk` usually fixes it:
|
||||
|
||||
.. code-block:: make
|
||||
|
||||
APP_PLATFORM := android-9
|
||||
|
||||
|
||||
#. Either use :ref:`manual <NDK_build_cli>` ``ndk-build`` invocation or :ref:`setup Eclipse CDT Builder <CDT_Builder>` to build native JNI lib before Java part [re]build and APK creation.
|
||||
#. 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 an APK.
|
||||
|
||||
|
||||
Hello OpenCV Sample
|
||||
===================
|
||||
|
||||
Here are basic steps to guide you trough the process of creating a simple OpenCV-centric application.
|
||||
It will be capable of accessing camera output, processing it and displaying the result.
|
||||
Here are basic steps to guide you trough the process of creating a simple OpenCV-centric
|
||||
application. It will be capable of accessing camera output, processing it and displaying the
|
||||
result.
|
||||
|
||||
#. Open Eclipse IDE, create a new clean workspace, create a new Android project (*File -> New -> Android Project*).
|
||||
#. Open Eclipse IDE, create a new clean workspace, create a new Android project
|
||||
:menuselection:`File --> New --> Android Project`
|
||||
|
||||
#. Set name, target, package and minSDKVersion accordingly.
|
||||
#. Set name, target, package and ``minSDKVersion`` accordingly. The minimal SDK version for build
|
||||
with OpenCV4Android SDK is 11. Minimal device API Level (for application manifest) is 8.
|
||||
|
||||
#. Create a new class (*File -> New -> Class*). Name it for example: *HelloOpenCVView*.
|
||||
#. Allow Eclipse to create default activity. Lets name the activity ``HelloOpenCvActivity``.
|
||||
|
||||
.. image:: images/dev_OCV_new_class.png
|
||||
:alt: Add a new class.
|
||||
:align: center
|
||||
#. Choose Blank Activity with full screen layout. Lets name the layout ``HelloOpenCvLayout``.
|
||||
|
||||
* It should extend *SurfaceView* class.
|
||||
* It also should implement *SurfaceHolder.Callback*, *Runnable*.
|
||||
|
||||
#. Edit *HelloOpenCVView* class.
|
||||
|
||||
* Add an *import* line for *android.content.context*.
|
||||
|
||||
* Modify autogenerated stubs: *HelloOpenCVView*, *surfaceCreated*, *surfaceDestroyed* and *surfaceChanged*.
|
||||
|
||||
.. code-block:: java
|
||||
:linenos:
|
||||
|
||||
package com.hello.opencv.test;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public class HelloOpenCVView extends SurfaceView implements Callback, Runnable {
|
||||
|
||||
public HelloOpenCVView(Context context) {
|
||||
super(context);
|
||||
getHolder().addCallback(this);
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
(new Thread(this)).start();
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
cameraRelease();
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
cameraSetup(width, height);
|
||||
}
|
||||
|
||||
//...
|
||||
|
||||
* Add *cameraOpen*, *cameraRelease* and *cameraSetup* voids as shown below.
|
||||
|
||||
* Also, don't forget to add the public void *run()* as follows:
|
||||
|
||||
.. code-block:: java
|
||||
:linenos:
|
||||
|
||||
public void run() {
|
||||
// TODO: loop { getFrame(), processFrame(), drawFrame() }
|
||||
}
|
||||
|
||||
public boolean cameraOpen() {
|
||||
return false; //TODO: open camera
|
||||
}
|
||||
|
||||
private void cameraRelease() {
|
||||
// TODO release camera
|
||||
}
|
||||
|
||||
private void cameraSetup(int width, int height) {
|
||||
// TODO setup camera
|
||||
}
|
||||
|
||||
#. Create a new *Activity* (*New -> Other -> Android -> Android Activity*) and name it, for example: *HelloOpenCVActivity*. For this activity define *onCreate*, *onResume* and *onPause* voids.
|
||||
|
||||
.. code-block:: java
|
||||
:linenos:
|
||||
|
||||
public void onCreate (Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mView = new HelloOpenCVView(this);
|
||||
setContentView (mView);
|
||||
}
|
||||
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mView.cameraRelease();
|
||||
}
|
||||
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if( !mView.cameraOpen() ) {
|
||||
// MessageBox and exit app
|
||||
AlertDialog ad = new AlertDialog.Builder(this).create();
|
||||
ad.setCancelable(false); // This blocks the "BACK" button
|
||||
ad.setMessage("Fatal error: can't open camera!");
|
||||
ad.setButton("OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
ad.show();
|
||||
}
|
||||
}
|
||||
|
||||
#. Add the following permissions to the AndroidManifest.xml file:
|
||||
|
||||
.. code-block:: xml
|
||||
:linenos:
|
||||
|
||||
</application>
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||
#. Import OpenCV library project to your workspace.
|
||||
|
||||
#. Reference OpenCV library within your project properties.
|
||||
|
||||
@@ -386,98 +308,153 @@ It will be capable of accessing camera output, processing it and displaying the
|
||||
:alt: Reference OpenCV library.
|
||||
:align: center
|
||||
|
||||
#. We now need some code to handle the camera. Update the *HelloOpenCVView* class as follows:
|
||||
#. Edit your layout file as xml file and pass the following layout there:
|
||||
|
||||
.. code-block:: xml
|
||||
:linenos:
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:opencv="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<org.opencv.android.JavaCameraView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:visibility="gone"
|
||||
android:id="@+id/HelloOpenCvView"
|
||||
opencv:show_fps="true"
|
||||
opencv:camera_id="any" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
#. Add the following permissions to the :file:`AndroidManifest.xml` file:
|
||||
|
||||
.. code-block:: xml
|
||||
:linenos:
|
||||
|
||||
</application>
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
|
||||
|
||||
#. Set application theme in AndroidManifest.xml to hide title and system buttons.
|
||||
|
||||
.. code-block:: xml
|
||||
:linenos:
|
||||
|
||||
<application
|
||||
android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
||||
|
||||
#. Add OpenCV library initialization to your activity. Fix errors by adding requited imports.
|
||||
|
||||
.. code-block:: java
|
||||
:linenos:
|
||||
|
||||
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
mOpenCvCameraView.enableView();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
|
||||
}
|
||||
|
||||
#. Defines that your activity implements ``CvViewFrameListener2`` interface and fix activity related
|
||||
errors by defining missed methods. For this activity define ``onCreate``, ``onDestroy`` and
|
||||
``onPause`` and implement them according code snippet bellow. Fix errors by adding requited
|
||||
imports.
|
||||
|
||||
.. code-block:: java
|
||||
:linenos:
|
||||
|
||||
private VideoCapture mCamera;
|
||||
private CameraBridgeViewBase mOpenCvCameraView;
|
||||
|
||||
public boolean cameraOpen() {
|
||||
synchronized (this) {
|
||||
cameraRelease();
|
||||
mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
|
||||
if (!mCamera.isOpened()) {
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
Log.e("HelloOpenCVView", "Failed to open native camera");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.i(TAG, "called onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
setContentView(R.layout.HelloOpenCvLayout);
|
||||
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.HelloOpenCvView);
|
||||
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
|
||||
mOpenCvCameraView.setCvCameraViewListener(this);
|
||||
}
|
||||
|
||||
public void cameraRelease() {
|
||||
synchronized(this) {
|
||||
if (mCamera != null) {
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
private void cameraSetup(int width, int height) {
|
||||
synchronized (this) {
|
||||
if (mCamera != null && mCamera.isOpened()) {
|
||||
List<Size> sizes = mCamera.getSupportedPreviewSizes();
|
||||
int mFrameWidth = width;
|
||||
int mFrameHeight = height;
|
||||
{ // selecting optimal camera preview size
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
for (Size size : sizes) {
|
||||
if (Math.abs(size.height - height) < minDiff) {
|
||||
mFrameWidth = (int) size.width;
|
||||
mFrameHeight = (int) size.height;
|
||||
minDiff = Math.abs(size.height - height);
|
||||
}
|
||||
}
|
||||
}
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
#. The last step would be to update the *run()* void in *HelloOpenCVView* class as follows:
|
||||
public void onCameraViewStarted(int width, int height) {
|
||||
}
|
||||
|
||||
.. code-block:: java
|
||||
:linenos:
|
||||
public void onCameraViewStopped() {
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
Bitmap bmp = null;
|
||||
synchronized (this) {
|
||||
if (mCamera == null)
|
||||
break;
|
||||
if (!mCamera.grab())
|
||||
break;
|
||||
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
|
||||
return inputFrame.rgba();
|
||||
}
|
||||
|
||||
bmp = processFrame(mCamera);
|
||||
}
|
||||
if (bmp != null) {
|
||||
Canvas canvas = getHolder().lockCanvas();
|
||||
if (canvas != null) {
|
||||
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2,
|
||||
(canvas.getHeight() - bmp.getHeight()) / 2, null);
|
||||
getHolder().unlockCanvasAndPost(canvas);
|
||||
#. Run your application on device or emulator.
|
||||
|
||||
}
|
||||
bmp.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
Lets discuss some most important steps. Every Android application with UI must implement Activity
|
||||
and View. By the first steps we create blank activity and default view layout. The simplest
|
||||
OpenCV-centric application must implement OpenCV initialization, create its own view to show
|
||||
preview from camera and implements ``CvViewFrameListener2`` interface to get frames from camera and
|
||||
process it.
|
||||
|
||||
protected Bitmap processFrame(VideoCapture capture) {
|
||||
Mat mRgba = new Mat();
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
//process mRgba
|
||||
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
|
||||
try {
|
||||
Utils.matToBitmap(mRgba, bmp);
|
||||
} catch(Exception e) {
|
||||
Log.e("processFrame", "Utils.matToBitmap() throws an exception: " + e.getMessage());
|
||||
bmp.recycle();
|
||||
bmp = null;
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
First of all we create our application view using xml layout. Our layout consists of the only
|
||||
one full screen component of class ``org.opencv.android.JavaCameraView``. This class is
|
||||
implemented inside OpenCV library. It is inherited from ``CameraBridgeViewBase``, that extends
|
||||
``SurfaceView`` and uses standard Android camera API. Alternatively you can use
|
||||
``org.opencv.android.NativeCameraView`` class, that implements the same interface, but uses
|
||||
``VideoCapture`` class as camera access back-end. ``opencv:show_fps="true"`` and
|
||||
``opencv:camera_id="any"`` options enable FPS message and allow to use any camera on device.
|
||||
Application tries to use back camera first.
|
||||
|
||||
After creating layout we need to implement ``Activity`` class. OpenCV initialization process has
|
||||
been already discussed above. In this sample we use asynchronous initialization. Implementation of
|
||||
``CvCameraViewListener`` interface allows you to add processing steps after frame grabbing from
|
||||
camera and before its rendering on screen. The most important function is ``onCameraFrame``. It is
|
||||
callback function and it is called on retrieving frame from camera. The callback input is object
|
||||
of ``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()`` 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.
|
||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,115 @@
|
||||
|
||||
.. _ARM-Linux-cross-compile:
|
||||
|
||||
Cross compilation for ARM based Linux systems
|
||||
*********************************************
|
||||
|
||||
This steps are tested on Ubuntu Linux 12.04, but should work for other Linux distributions.
|
||||
I case of other distributions package names and names of cross compilation tools may differ.
|
||||
There are several popular EABI versions that are used on ARM platform. This tutorial is
|
||||
written for *gnueabi* and *gnueabihf*, but other variants should work with minimal changes.
|
||||
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
|
||||
* Host computer with Linux;
|
||||
* Git;
|
||||
* CMake 2.6 or higher;
|
||||
* Cross compilation tools for ARM: gcc, libstc++, etc. Depending on target platform you need
|
||||
to choose *gnueabi* or *gnueabihf* tools.
|
||||
Install command for *gnueabi*:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt-get install gcc-arm-linux-gnueabi
|
||||
|
||||
Install command for *gnueabihf*:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt-get install gcc-arm-linux-gnueabihf
|
||||
|
||||
* pkgconfig;
|
||||
* Python 2.6 for host system;
|
||||
* [optional] ffmpeg or libav development packages for armeabi(hf): libavcodec-dev, libavformat-dev, libswscale-dev;
|
||||
* [optional] GTK+2.x or higher, including headers (libgtk2.0-dev) for armeabi(hf);
|
||||
* [optional] libdc1394 2.x;
|
||||
* [optional] libjpeg-dev, libpng-dev, libtiff-dev, libjasper-dev for armeabi(hf).
|
||||
|
||||
|
||||
Getting OpenCV Source Code
|
||||
==========================
|
||||
|
||||
You can use the latest stable OpenCV version available in *sourceforge* or you can grab the latest
|
||||
snapshot from our `Git repository <https://github.com/Itseez/opencv.git>`_.
|
||||
|
||||
|
||||
Getting the Latest Stable OpenCV Version
|
||||
----------------------------------------
|
||||
|
||||
* Go to our `page on Sourceforge <http://sourceforge.net/projects/opencvlibrary>`_;
|
||||
|
||||
* Download the source tarball and unpack it.
|
||||
|
||||
|
||||
Getting the Cutting-edge OpenCV from the Git Repository
|
||||
-------------------------------------------------------
|
||||
|
||||
Launch Git client and clone `OpenCV repository <http://github.com/itseez/opencv>`_
|
||||
|
||||
In Linux it can be achieved with the following command in Terminal:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd ~/<my_working _directory>
|
||||
git clone https://github.com/Itseez/opencv.git
|
||||
|
||||
|
||||
Building OpenCV
|
||||
===============
|
||||
|
||||
#. Create a build directory, make it current and run the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cmake [<some optional parameters>] -DCMAKE_TOOLCHAIN_FILE=<path to the OpenCV source directory>/platforms/linux/arm-gnueabi.toolchain.cmake <path to the OpenCV source directory>
|
||||
|
||||
Toolchain uses *gnueabihf* EABI convention by default. Add ``-DSOFTFP=ON`` cmake argument to switch on softfp compiler.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cmake [<some optional parameters>] -DSOFTFP=ON -DCMAKE_TOOLCHAIN_FILE=<path to the OpenCV source directory>/platforms/linux/arm-gnueabi.toolchain.cmake <path to the OpenCV source directory>
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd ~/opencv/platforms/linux
|
||||
mkdir -p build_hardfp
|
||||
cd build_hardfp
|
||||
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=../arm-gnueabi.toolchain.cmake ../../..
|
||||
|
||||
#. Run make in build (<cmake_binary_dir>) directory:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make
|
||||
|
||||
.. note::
|
||||
|
||||
Optionally you can strip symbols info from the created library via install/strip make target.
|
||||
This option produces smaller binary (~ twice smaller) but makes further debugging harder.
|
||||
|
||||
Enable hardware optimizations
|
||||
-----------------------------
|
||||
|
||||
Depending on target platfrom architecture different instruction sets can be used. By default
|
||||
compiler generates code for armv5l without VFPv3 and NEON extensions. Add ``-DUSE_VFPV3=ON``
|
||||
to cmake command line to enable code generation for VFPv3 and ``-DUSE_NEON=ON`` for using
|
||||
NEON SIMD extensions.
|
||||
|
||||
TBB is supported on multi core ARM SoCs also.
|
||||
Add ``-DWITH_TBB=ON`` and ``-DBUILD_TBB=ON`` to enable it. Cmake scripts download TBB sources
|
||||
from official project site `<http://threadingbuildingblocks.org/>`_ and build it.
|
BIN
doc/tutorials/introduction/desktop_java/images/Java_logo.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
doc/tutorials/introduction/desktop_java/images/ant_output.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
doc/tutorials/introduction/desktop_java/images/cmake_output.png
Normal file
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 12 KiB |
BIN
doc/tutorials/introduction/desktop_java/images/eclipse_run.png
Normal file
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 25 KiB |
BIN
doc/tutorials/introduction/desktop_java/images/faceDetection.png
Normal file
After Width: | Height: | Size: 500 KiB |
BIN
doc/tutorials/introduction/desktop_java/images/lena.png
Normal file
After Width: | Height: | Size: 606 KiB |
BIN
doc/tutorials/introduction/desktop_java/images/sbt_eclipse.png
Normal file
After Width: | Height: | Size: 248 KiB |
BIN
doc/tutorials/introduction/desktop_java/images/sbt_run.png
Normal file
After Width: | Height: | Size: 195 KiB |
BIN
doc/tutorials/introduction/desktop_java/images/sbt_run_face.png
Normal file
After Width: | Height: | Size: 258 KiB |
538
doc/tutorials/introduction/desktop_java/java_dev_intro.rst
Normal file
@@ -0,0 +1,538 @@
|
||||
|
||||
.. _Java_Dev_Intro:
|
||||
|
||||
|
||||
Introduction to Java Development
|
||||
********************************
|
||||
|
||||
As of OpenCV 2.4.4, OpenCV supports desktop Java development using nearly the same interface as for
|
||||
Android development. This guide will help you to create your first Java (or Scala) application using OpenCV.
|
||||
We will use either `Eclipse <http://eclipse.org/>`_, `Apache Ant <http://ant.apache.org/>`_ or the
|
||||
`Simple Build Tool (SBT) <http://www.scala-sbt.org/>`_ to build the application.
|
||||
|
||||
For further reading after this guide, look at the :ref:`Android_Dev_Intro` tutorials.
|
||||
|
||||
What we'll do in this guide
|
||||
===========================
|
||||
|
||||
In this guide, we will:
|
||||
|
||||
* Get OpenCV with desktop Java support
|
||||
|
||||
* Create an ``Ant``, ``Eclipse`` or ``SBT`` project
|
||||
|
||||
* Write a simple OpenCV application in Java or Scala
|
||||
|
||||
The same process was used to create the samples in the :file:`samples/java` folder of the OpenCV repository,
|
||||
so consult those files if you get lost.
|
||||
|
||||
Get proper OpenCV
|
||||
=================
|
||||
|
||||
Starting from version 2.4.4 OpenCV includes desktop Java bindings.
|
||||
|
||||
Download
|
||||
--------
|
||||
|
||||
The most simple way to get it is downloading the appropriate package of **version 2.4.4 or higher** from the
|
||||
`OpenCV SourceForge repository <http://sourceforge.net/projects/opencvlibrary/files/>`_.
|
||||
|
||||
.. note:: Windows users can find the prebuilt files needed for Java development in
|
||||
the :file:`opencv/build/java/` folder inside the package.
|
||||
For other OSes it's required to build OpenCV from sources.
|
||||
|
||||
Another option to get OpenCV sources is to clone `OpenCV git repository
|
||||
<https://github.com/Itseez/opencv/>`_.
|
||||
In order to build OpenCV with Java bindings you need :abbr:`JDK (Java Development Kit)`
|
||||
(we recommend `Oracle/Sun JDK 6 or 7 <http://www.oracle.com/technetwork/java/javase/downloads/>`_),
|
||||
`Apache Ant <http://ant.apache.org/>`_ and `Python` v2.6 or higher to be installed.
|
||||
|
||||
Build
|
||||
-----
|
||||
|
||||
Let's build OpenCV:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone git://github.com/Itseez/opencv.git
|
||||
cd opencv
|
||||
git checkout 2.4
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
Generate a Makefile or a MS Visual Studio* solution, or whatever you use for
|
||||
building executables in your system:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cmake -DBUILD_SHARED_LIBS=OFF ..
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: bat
|
||||
|
||||
cmake -DBUILD_SHARED_LIBS=OFF -G "Visual Studio 10" ..
|
||||
|
||||
.. 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 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
|
||||
:alt: CMake output
|
||||
:align: center
|
||||
|
||||
.. 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-block:: bash
|
||||
|
||||
export JAVA_HOME=/usr/lib/jvm/java-6-oracle
|
||||
cmake -DBUILD_SHARED_LIBS=OFF ..
|
||||
|
||||
|
||||
Now start the build:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make -j8
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: bat
|
||||
|
||||
msbuild /m OpenCV.sln /t:Build /p:Configuration=Release /v:m
|
||||
|
||||
Besides all this will create a ``jar`` containing the Java interface (:file:`bin/opencv-244.jar`)
|
||||
and a native dynamic library containing Java bindings and all the OpenCV stuff
|
||||
(:file:`lib/libopencv_java244.so` or :file:`bin/Release/opencv_java244.dll` respectively).
|
||||
We'll use these files later.
|
||||
|
||||
Java sample with Ant
|
||||
====================
|
||||
|
||||
.. note::
|
||||
The described sample is provided with OpenCV library in the :file:`opencv/samples/java/ant` folder.
|
||||
|
||||
* Create a folder where you'll develop this sample application.
|
||||
|
||||
* In this folder create the :file:`build.xml` file with the following content using any text editor:
|
||||
|
||||
.. code-block:: xml
|
||||
:linenos:
|
||||
|
||||
<project name="SimpleSample" basedir="." default="rebuild-run">
|
||||
|
||||
<property name="src.dir" value="src"/>
|
||||
|
||||
<property name="lib.dir" value="${ocvJarDir}"/>
|
||||
<path id="classpath">
|
||||
<fileset dir="${lib.dir}" includes="**/*.jar"/>
|
||||
</path>
|
||||
|
||||
<property name="build.dir" value="build"/>
|
||||
<property name="classes.dir" value="${build.dir}/classes"/>
|
||||
<property name="jar.dir" value="${build.dir}/jar"/>
|
||||
|
||||
<property name="main-class" value="${ant.project.name}"/>
|
||||
|
||||
|
||||
<target name="clean">
|
||||
<delete dir="${build.dir}"/>
|
||||
</target>
|
||||
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes.dir}"/>
|
||||
<javac includeantruntime="false" srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
|
||||
</target>
|
||||
|
||||
<target name="jar" depends="compile">
|
||||
<mkdir dir="${jar.dir}"/>
|
||||
<jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="run" depends="jar">
|
||||
<java fork="true" classname="${main-class}">
|
||||
<sysproperty key="java.library.path" path="${ocvLibDir}"/>
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
<path location="${jar.dir}/${ant.project.name}.jar"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<target name="rebuild" depends="clean,jar"/>
|
||||
|
||||
<target name="rebuild-run" depends="clean,run"/>
|
||||
|
||||
</project>
|
||||
|
||||
.. 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
|
||||
(``"${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 :file:`src` folder next to the :file:`build.xml` file and a :file:`SimpleSample.java` file in it.
|
||||
|
||||
* Put the following Java code into the :file:`SimpleSample.java` file:
|
||||
.. code-block:: java
|
||||
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Scalar;
|
||||
|
||||
class SimpleSample {
|
||||
|
||||
static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Welcome to OpenCV " + Core.VERSION);
|
||||
Mat m = new Mat(5, 10, CvType.CV_8UC1, new Scalar(0));
|
||||
System.out.println("OpenCV Mat: " + m);
|
||||
Mat mr1 = m.row(1);
|
||||
mr1.setTo(new Scalar(1));
|
||||
Mat mc5 = m.col(5);
|
||||
mc5.setTo(new Scalar(5));
|
||||
System.out.println("OpenCV Mat data:\n" + m.dump());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
* Run the following command in console in the folder containing :file:`build.xml`:
|
||||
.. code-block:: bash
|
||||
|
||||
ant -DocvJarDir=path/to/dir/containing/opencv-244.jar -DocvLibDir=path/to/dir/containing/opencv_java244/native/library
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: bat
|
||||
|
||||
ant -DocvJarDir=X:\opencv-2.4.4\bin -DocvLibDir=X:\opencv-2.4.4\bin\Release
|
||||
|
||||
The command should initiate [re]building and running the sample.
|
||||
You should see on the screen something like this:
|
||||
|
||||
.. image:: images/ant_output.png
|
||||
:alt: run app with Ant
|
||||
:align: center
|
||||
|
||||
Java project in Eclipse
|
||||
=======================
|
||||
|
||||
Now let's look at the possiblity of using OpenCV in Java when developing in Eclipse IDE.
|
||||
|
||||
* Create a new Eclipse workspace
|
||||
* Create a new Java project via :guilabel:`File --> New --> Java Project`
|
||||
|
||||
.. image:: images/eclipse_new_java_prj.png
|
||||
:alt: Eclipse: new Java project
|
||||
:align: center
|
||||
|
||||
Call it say "HelloCV".
|
||||
|
||||
* Open :guilabel:`Java Build Path` tab on :guilabel:`Project Properties` dialog
|
||||
and configure additional library (OpenCV) reference (jar and native library location):
|
||||
|
||||
.. image:: images/eclipse_user_lib.png
|
||||
:alt: Eclipse: external JAR
|
||||
:align: center
|
||||
|
||||
|
|
||||
|
||||
.. image:: images/eclipse_user_lib2.png
|
||||
:alt: Eclipse: external JAR
|
||||
:align: center
|
||||
|
||||
|
|
||||
|
||||
.. image:: images/eclipse_user_lib3.png
|
||||
:alt: Eclipse: external JAR
|
||||
:align: center
|
||||
|
||||
|
|
||||
|
||||
.. image:: images/eclipse_user_lib4.png
|
||||
:alt: Eclipse: external JAR
|
||||
:align: center
|
||||
|
||||
|
|
||||
|
||||
.. image:: images/eclipse_user_lib5.png
|
||||
:alt: Eclipse: external JAR
|
||||
:align: center
|
||||
|
||||
|
|
||||
|
||||
.. image:: images/eclipse_user_lib6.png
|
||||
:alt: Eclipse: external JAR
|
||||
:align: center
|
||||
|
||||
|
|
||||
|
||||
.. image:: images/eclipse_user_lib7.png
|
||||
:alt: Eclipse: external JAR
|
||||
:align: center
|
||||
|
||||
|
|
||||
|
||||
.. image:: images/eclipse_user_lib8.png
|
||||
:alt: Eclipse: external JAR
|
||||
:align: center
|
||||
|
||||
|
||||
* Add a new Java class (say ``Main``) containing the application entry:
|
||||
|
||||
.. image:: images/eclipse_main_class.png
|
||||
:alt: Eclipse: Main class
|
||||
:align: center
|
||||
|
||||
* Put some simple OpenCV calls there, e.g.:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
|
||||
Mat m = Mat.eye(3, 3, CvType.CV_8UC1);
|
||||
System.out.println("m = " + m.dump());
|
||||
}
|
||||
}
|
||||
|
||||
* Press :guilabel:`Run` button and find the identity matrix content in the Eclipse ``Console`` window.
|
||||
|
||||
.. image:: images/eclipse_run.png
|
||||
:alt: Eclipse: run
|
||||
:align: center
|
||||
|
||||
SBT project for Java and Scala
|
||||
==============================
|
||||
|
||||
Now we'll create a simple Java application using SBT. This serves as a brief introduction to
|
||||
those unfamiliar with this build tool. We're using SBT because it is particularly easy and powerful.
|
||||
|
||||
First, download and install `SBT <http://www.scala-sbt.org/>`_ using the instructions on its `web site <http://www.scala-sbt.org/>`_.
|
||||
|
||||
Next, navigate to a new directory where you'd like the application source to live (outside :file:`opencv` dir).
|
||||
Let's call it "JavaSample" and create a directory for it:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd <somewhere outside opencv>
|
||||
mkdir JavaSample
|
||||
|
||||
Now we will create the necessary folders and an SBT project:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd JavaSample
|
||||
mkdir -p src/main/java # This is where SBT expects to find Java sources
|
||||
mkdir project # This is where the build definitions live
|
||||
|
||||
Now open :file:`project/build.scala` in your favorite editor and paste the following.
|
||||
It defines your project:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
import sbt._
|
||||
import Keys._
|
||||
|
||||
object JavaSampleBuild extends Build {
|
||||
def scalaSettings = Seq(
|
||||
scalaVersion := "2.10.0",
|
||||
scalacOptions ++= Seq(
|
||||
"-optimize",
|
||||
"-unchecked",
|
||||
"-deprecation"
|
||||
)
|
||||
)
|
||||
|
||||
def buildSettings =
|
||||
Project.defaultSettings ++
|
||||
scalaSettings
|
||||
|
||||
lazy val root = {
|
||||
val settings = buildSettings ++ Seq(name := "JavaSample")
|
||||
Project(id = "JavaSample", base = file("."), settings = settings)
|
||||
}
|
||||
}
|
||||
|
||||
Now edit :file:`project/plugins.sbt` and paste the following.
|
||||
This will enable auto-generation of an Eclipse project:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")
|
||||
|
||||
Now run ``sbt`` from the :file:`JavaSample` root and from within SBT run ``eclipse`` to generate an eclipse project:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sbt # Starts the sbt console
|
||||
> eclipse # Running "eclipse" from within the sbt console
|
||||
|
||||
You should see something like this:
|
||||
|
||||
.. image:: images/sbt_eclipse.png
|
||||
:alt: SBT output
|
||||
:align: center
|
||||
|
||||
You can now import the SBT project to Eclipse using :guilabel:`Import ... -> Existing projects into workspace`.
|
||||
Whether you actually do this is optional for the guide;
|
||||
we'll be using SBT to build the project, so if you choose to use Eclipse it will just serve as a text editor.
|
||||
|
||||
To test that everything is working, create a simple "Hello OpenCV" application.
|
||||
Do this by creating a file :file:`src/main/java/HelloOpenCV.java` with the following contents:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
public class HelloOpenCV {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello, OpenCV");
|
||||
}
|
||||
}
|
||||
|
||||
Now execute ``run`` from the sbt console, or more concisely, run ``sbt run`` from the command line:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sbt run
|
||||
|
||||
You should see something like this:
|
||||
|
||||
.. image:: images/sbt_run.png
|
||||
:alt: SBT run
|
||||
:align: center
|
||||
|
||||
Running SBT samples
|
||||
-------------------
|
||||
|
||||
Now we'll create a simple face detection application using OpenCV.
|
||||
|
||||
First, create a :file:`lib/` folder and copy the OpenCV jar into it.
|
||||
By default, SBT adds jars in the lib folder to the Java library search path.
|
||||
You can optionally rerun ``sbt eclipse`` to update your Eclipse project.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir lib
|
||||
cp <opencv_dir>/build/bin/opencv_<version>.jar lib/
|
||||
sbt eclipse
|
||||
|
||||
Next, create the directory :file:`src/main/resources` and download this Lena image into it:
|
||||
|
||||
.. image:: images/lena.png
|
||||
:alt: Lena
|
||||
:align: center
|
||||
|
||||
Make sure it's called :file:`"lena.png"`.
|
||||
Items in the resources directory are available to the Java application at runtime.
|
||||
|
||||
Next, copy :file:`lbpcascade_frontalface.xml` from :file:`opencv/data/lbpcascades/` into the :file:`resources`
|
||||
directory:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cp <opencv_dir>/data/lbpcascades/lbpcascade_frontalface.xml src/main/resources/
|
||||
|
||||
Now modify src/main/java/HelloOpenCV.java so it contains the following Java code:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfRect;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Rect;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.highgui.Highgui;
|
||||
import org.opencv.objdetect.CascadeClassifier;
|
||||
|
||||
//
|
||||
// Detects faces in an image, draws boxes around them, and writes the results
|
||||
// to "faceDetection.png".
|
||||
//
|
||||
class DetectFaceDemo {
|
||||
public void run() {
|
||||
System.out.println("\nRunning DetectFaceDemo");
|
||||
|
||||
// Create a face detector from the cascade file in the resources
|
||||
// directory.
|
||||
CascadeClassifier faceDetector = new CascadeClassifier(getClass().getResource("/lbpcascade_frontalface.xml").getPath());
|
||||
Mat image = Highgui.imread(getClass().getResource("/lena.png").getPath());
|
||||
|
||||
// Detect faces in the image.
|
||||
// MatOfRect is a special container class for Rect.
|
||||
MatOfRect faceDetections = new MatOfRect();
|
||||
faceDetector.detectMultiScale(image, faceDetections);
|
||||
|
||||
System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));
|
||||
|
||||
// Draw a bounding box around each face.
|
||||
for (Rect rect : faceDetections.toArray()) {
|
||||
Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
|
||||
}
|
||||
|
||||
// Save the visualized detection.
|
||||
String filename = "faceDetection.png";
|
||||
System.out.println(String.format("Writing %s", filename));
|
||||
Highgui.imwrite(filename, image);
|
||||
}
|
||||
}
|
||||
|
||||
public class HelloOpenCV {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello, OpenCV");
|
||||
|
||||
// Load the native library.
|
||||
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
|
||||
new DetectFaceDemo().run();
|
||||
}
|
||||
}
|
||||
|
||||
Note the call to ``System.loadLibrary(Core.NATIVE_LIBRARY_NAME)``.
|
||||
This command must be executed exactly once per Java process prior to using any native OpenCV methods.
|
||||
If you don't call it, you will get ``UnsatisfiedLink errors``.
|
||||
You will also get errors if you try to load OpenCV when it has already been loaded.
|
||||
|
||||
Now run the face detection app using ``sbt run``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sbt run
|
||||
|
||||
You should see something like this:
|
||||
|
||||
.. image:: images/sbt_run_face.png
|
||||
:alt: SBT run
|
||||
:align: center
|
||||
|
||||
It should also write the following image to :file:`faceDetection.png`:
|
||||
|
||||
.. image:: images/faceDetection.png
|
||||
:alt: Detected face
|
||||
:align: center
|
||||
|
||||
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!
|
@@ -65,8 +65,7 @@ Making a project
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <cv.h>
|
||||
#include <highgui.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
@@ -81,7 +80,7 @@ Making a project
|
||||
return -1;
|
||||
}
|
||||
|
||||
namedWindow( "Display Image", CV_WINDOW_AUTOSIZE );
|
||||
namedWindow( "Display Image", WINDOW_AUTOSIZE );
|
||||
imshow( "Display Image", image );
|
||||
|
||||
waitKey(0);
|
||||
@@ -201,29 +200,20 @@ Assuming that the image to use as the argument would be located in <DisplayImage
|
||||
V2: Using CMake+OpenCV with Eclipse (plugin CDT)
|
||||
==================================================
|
||||
|
||||
(See the `getting started <http://opencv.willowgarage.com/wiki/Getting_started>` section of the OpenCV Wiki)
|
||||
|
||||
Say you have or create a new file, *helloworld.cpp* in a directory called *foo*:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
|
||||
#include <cv.h>
|
||||
#include <highgui.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
using namespace cv;
|
||||
|
||||
int main ( int argc, char **argv )
|
||||
{
|
||||
cvNamedWindow( "My Window", 1 );
|
||||
IplImage *img = cvCreateImage( cvSize( 640, 480 ), IPL_DEPTH_8U, 1 );
|
||||
CvFont font;
|
||||
double hScale = 1.0;
|
||||
double vScale = 1.0;
|
||||
int lineWidth = 1;
|
||||
cvInitFont( &font, CV_FONT_HERSHEY_SIMPLEX | CV_FONT_ITALIC,
|
||||
hScale, vScale, 0, lineWidth );
|
||||
cvPutText( img, "Hello World!", cvPoint( 200, 400 ), &font,
|
||||
cvScalar( 255, 255, 0 ) );
|
||||
cvShowImage( "My Window", img );
|
||||
cvWaitKey();
|
||||
Mat img(480, 640, CV_8U);
|
||||
putText(img, "Hello World!", Point( 200, 400 ), FONT_HERSHEY_SIMPLEX | FONT_ITALIC, 1.0, Scalar( 255, 255, 0 ));
|
||||
imshow("My Window", img);
|
||||
waitKey();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -25,8 +25,8 @@ Let's use a simple program such as DisplayImage.cpp shown below.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <cv.h>
|
||||
#include <highgui.h>
|
||||
#include <stdio.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
@@ -55,9 +55,10 @@ Now you have to create your CMakeLists.txt file. It should look like this:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project( DisplayImage )
|
||||
find_package( OpenCV REQUIRED )
|
||||
add_executable( DisplayImage DisplayImage )
|
||||
add_executable( DisplayImage DisplayImage.cpp )
|
||||
target_link_libraries( DisplayImage ${OpenCV_LIBS} )
|
||||
|
||||
Generate the executable
|
||||
|
@@ -15,7 +15,7 @@ In this tutorial you will learn how to:
|
||||
.. container:: enumeratevisibleitemswithsquare
|
||||
|
||||
* Load an image using :imread:`imread <>`
|
||||
* Transform an image from RGB to Grayscale format by using :cvt_color:`cvtColor <>`
|
||||
* Transform an image from BGR to Grayscale format by using :cvt_color:`cvtColor <>`
|
||||
* Save your transformed image in a file on disk (using :imwrite:`imwrite <>`)
|
||||
|
||||
Code
|
||||
@@ -26,8 +26,7 @@ Here it is:
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
#include <cv.h>
|
||||
#include <highgui.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
@@ -45,12 +44,12 @@ Here it is:
|
||||
}
|
||||
|
||||
Mat gray_image;
|
||||
cvtColor( image, gray_image, CV_RGB2GRAY );
|
||||
cvtColor( image, gray_image, COLOR_BGR2GRAY );
|
||||
|
||||
imwrite( "../../images/Gray_Image.jpg", gray_image );
|
||||
|
||||
namedWindow( imageName, CV_WINDOW_AUTOSIZE );
|
||||
namedWindow( "Gray image", CV_WINDOW_AUTOSIZE );
|
||||
namedWindow( imageName, WINDOW_AUTOSIZE );
|
||||
namedWindow( "Gray image", WINDOW_AUTOSIZE );
|
||||
|
||||
imshow( imageName, image );
|
||||
imshow( "Gray image", gray_image );
|
||||
@@ -68,11 +67,11 @@ Explanation
|
||||
* Creating a Mat object to store the image information
|
||||
* Load an image using :imread:`imread <>`, located in the path given by *imageName*. Fort this example, assume you are loading a RGB image.
|
||||
|
||||
#. Now we are going to convert our image from RGB to Grayscale format. OpenCV has a really nice function to do this kind of transformations:
|
||||
#. Now we are going to convert our image from BGR to Grayscale format. OpenCV has a really nice function to do this kind of transformations:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
cvtColor( image, gray_image, CV_RGB2GRAY );
|
||||
cvtColor( image, gray_image, CV_BGR2GRAY );
|
||||
|
||||
As you can see, :cvt_color:`cvtColor <>` takes as arguments:
|
||||
|
||||
@@ -80,7 +79,7 @@ Explanation
|
||||
|
||||
* a source image (*image*)
|
||||
* a destination image (*gray_image*), in which we will save the converted image.
|
||||
* an additional parameter that indicates what kind of transformation will be performed. In this case we use **CV_RGB2GRAY** (self-explanatory).
|
||||
* an additional parameter that indicates what kind of transformation will be performed. In this case we use **CV_BGR2GRAY** (because of :imread:`imread <>` has BGR default channel order in case of color images).
|
||||
|
||||
#. So now we have our new *gray_image* and want to save it on disk (otherwise it will get lost after the program ends). To save it, we will use a function analagous to :imread:`imread <>`: :imwrite:`imwrite <>`
|
||||
|
||||
|
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 18 KiB |
@@ -3,7 +3,9 @@
|
||||
Introduction to OpenCV
|
||||
-----------------------------------------------------------
|
||||
|
||||
Here you can read tutorials about how to set up your computer to work with the OpenCV library. Additionaly you can find a few very basic sample source code that will let introduce you to the world of the OpenCV.
|
||||
Here you can read tutorials about how to set up your computer to work with the OpenCV library.
|
||||
Additionally you can find a few very basic sample source code that will let introduce you to the
|
||||
world of the OpenCV.
|
||||
|
||||
.. include:: ../../definitions/tocDefinitions.rst
|
||||
|
||||
@@ -101,6 +103,41 @@ Here you can read tutorials about how to set up your computer to work with the O
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
=========== ======================================================
|
||||
|WinVSVis| **Title:** :ref:`Windows_Visual_Studio_Image_Watch`
|
||||
|
||||
*Compatibility:* >= OpenCV 2.4
|
||||
|
||||
*Author:* Wolf Kienzle
|
||||
|
||||
You will learn how to visualize OpenCV matrices and images within Visual Studio 2012.
|
||||
|
||||
=========== ======================================================
|
||||
|
||||
.. |WinVSVis| image:: images/visual_studio_image_watch.png
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
* **Desktop Java**
|
||||
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
================ =================================================
|
||||
|JavaLogo| **Title:** :ref:`Java_Dev_Intro`
|
||||
|
||||
*Compatibility:* > OpenCV 2.4.4
|
||||
|
||||
*Authors:* |Author_EricCh| and |Author_AndreyP|
|
||||
|
||||
Explains how to build and run a simple desktop Java application using Eclipse, Ant or the Simple Build Tool (SBT).
|
||||
|
||||
================ =================================================
|
||||
|
||||
.. |JavaLogo| image:: images/Java_logo.png
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
* **Android**
|
||||
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
@@ -137,7 +174,7 @@ Here you can read tutorials about how to set up your computer to work with the O
|
||||
================ =================================================
|
||||
|AndroidLogo| **Title:** :ref:`dev_with_OCV_on_Android`
|
||||
|
||||
*Compatibility:* > OpenCV 2.4.2
|
||||
*Compatibility:* > OpenCV 2.4.3
|
||||
|
||||
*Author:* |Author_VsevolodG|
|
||||
|
||||
@@ -169,6 +206,24 @@ Here you can read tutorials about how to set up your computer to work with the O
|
||||
.. |Install_iOS| image:: images/opencv_ios.png
|
||||
:width: 90pt
|
||||
|
||||
* **Embedded Linux**
|
||||
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
=========== ======================================================
|
||||
|Usage_1| **Title:** :ref:`ARM-Linux-cross-compile`
|
||||
|
||||
*Compatibility:* > OpenCV 2.4.4
|
||||
|
||||
*Author:* |Author_AlexS|
|
||||
|
||||
We will learn how to setup OpenCV cross compilation environment for ARM Linux.
|
||||
|
||||
=========== ======================================================
|
||||
|
||||
* **Common**
|
||||
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
.. cssclass:: toctableopencv
|
||||
|
||||
@@ -229,7 +284,7 @@ Here you can read tutorials about how to set up your computer to work with the O
|
||||
|
||||
\pagebreak
|
||||
|
||||
.. We use a custom table of content format and as the table of content only imforms Sphinx about the hierarchy of the files, no need to show it.
|
||||
.. We use a custom table of content format and as the table of content only informs Sphinx about the hierarchy of the files, no need to show it.
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
@@ -238,10 +293,13 @@ Here you can read tutorials about how to set up your computer to work with the O
|
||||
../linux_eclipse/linux_eclipse
|
||||
../windows_install/windows_install
|
||||
../windows_visual_studio_Opencv/windows_visual_studio_Opencv
|
||||
../windows_visual_studio_image_watch/windows_visual_studio_image_watch
|
||||
../desktop_java/java_dev_intro
|
||||
../android_binary_package/android_dev_intro
|
||||
../android_binary_package/O4A_SDK
|
||||
../android_binary_package/dev_with_OCV_on_Android
|
||||
../ios_install/ios_install
|
||||
../crosscompilation/arm_crosscompile_with_cmake
|
||||
../display_image/display_image
|
||||
../load_save_image/load_save_image
|
||||
../how_to_write_a_tutorial/how_to_write_a_tutorial
|
||||
../how_to_write_a_tutorial/how_to_write_a_tutorial
|
||||
|
@@ -20,11 +20,7 @@ Installation by Using the Pre-built Libraries
|
||||
|
||||
.. If you downloaded the source files present here see :ref:`CppTutWindowsMakeOwn`.
|
||||
|
||||
#. Make sure you have admin rights. Start the setup and follow the wizard.
|
||||
|
||||
#. While adding the OpenCV library to the system path is a good decision for a better control, we will do it manually for the sake of this tutorial. Make sure you do not set this option.
|
||||
|
||||
#. Most of the time it is a good idea to install the source files too, as this will allow for you to debug into the OpenCV library, if it is necessary. Follow the default settings of the wizard and finish the installation.
|
||||
#. Make sure you have admin rights. Unpack the self-extracting archive.
|
||||
|
||||
#. You can check the installation at the chosen path as you can see below.
|
||||
|
||||
@@ -294,15 +290,7 @@ Building the library
|
||||
:alt: The Install Project
|
||||
:align: center
|
||||
|
||||
This will create an *install* directory inside the *Build* one collecting all the built binaries into a single place. Use this only after you built both the *Release* and *Debug* versions.
|
||||
|
||||
.. note::
|
||||
|
||||
To create an installer you need to install `NSIS <http://nsis.sourceforge.net/Download>`_. Then just build the *Package* project to build the installer into the :file:`Build/_CPack_Packages/{win32}/NSIS` folder. You can then use this to distribute OpenCV with your build settings on other systems.
|
||||
|
||||
.. image:: images/WindowsOpenCVInstaller.png
|
||||
:alt: The Installer directory
|
||||
:align: center
|
||||
This will create an *Install* directory inside the *Build* one collecting all the built binaries into a single place. Use this only after you built both the *Release* and *Debug* versions.
|
||||
|
||||
To test your build just go into the :file:`Build/bin/Debug` or :file:`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 via our :opencv_group:`user group <>`.
|
||||
If everything is okay the *contours.exe* output should resemble the following image (if built with Qt support):
|
||||
@@ -320,15 +308,15 @@ Building the library
|
||||
Set the OpenCV enviroment variable and add it to the systems path
|
||||
=================================================================
|
||||
|
||||
First we set an enviroment variable to make easier our work. This will hold the install directory of our OpenCV library that we use in our projects. Start up a command window and enter:
|
||||
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:
|
||||
|
||||
::
|
||||
|
||||
setx -m OPENCV_DIR D:\OpenCV\Build\Install
|
||||
setx -m OPENCV_DIR D:\OpenCV\Build\x86\vc10
|
||||
|
||||
Here the directory is where you have your OpenCV binaries (*installed* or *built*). Inside this you should have folders like *bin* and *include*. The -m should be added if you wish to make the settings computer wise, instead of user wise.
|
||||
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 folders like *bin* and *include*. The -m should be added if you wish to make the settings computer wise, instead of user wise.
|
||||
|
||||
If you built static libraries then you are done. Otherwise, you need to add the *bin* folders path to the systems path.This is cause you will use the OpenCV library in form of *\"Dynamic-link libraries\"* (also known as **DLL**). Inside these are stored all the algorithms and information the OpenCV library contains. The operating system will load them only on demand, during runtime. However, to do this he needs to know where they are. The systems **PATH** contains 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 following new entry (right click in the application to bring up the menu):
|
||||
If you built static libraries then you are done. Otherwise, you need to add the *bin* folders path to the systems path. This is cause you will use the OpenCV library in form of *\"Dynamic-link libraries\"* (also known as **DLL**). Inside these are stored all the algorithms and information the OpenCV library contains. The operating system will load them only on demand, during runtime. However, to do this he needs to know where they are. The systems **PATH** contains 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 following new entry (right click in the application to bring up the menu):
|
||||
|
||||
::
|
||||
|
||||
@@ -342,6 +330,6 @@ If you built static libraries then you are done. Otherwise, you need to add the
|
||||
:alt: Add the entry.
|
||||
:align: center
|
||||
|
||||
Save it to the registry and you are done. If you ever change the location of your install directories 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.
|
||||
Save it to the registry and you are done. If you ever change the location of your build directories 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. There you will find out how to use the OpenCV library in your own projects with the help of the Microsoft Visual Studio IDE.
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 4.8 KiB |
@@ -0,0 +1,144 @@
|
||||
.. _Windows_Visual_Studio_Image_Watch:
|
||||
|
||||
Image Watch: viewing in-memory images in the Visual Studio debugger
|
||||
*******************************************************************
|
||||
|
||||
Image Watch is a plug-in for Microsoft Visual Studio that lets you to visualize in-memory images (*cv::Mat* or *IplImage\_* objects, for example) while debugging an application. This can be helpful for tracking down bugs, or for simply understanding what a given piece of code is doing.
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
|
||||
This tutorial assumes that you have the following available:
|
||||
|
||||
#. 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>`_.
|
||||
|
||||
#. An OpenCV installation on your Windows machine (Tutorial: :ref:`Windows_Installation`).
|
||||
|
||||
#. Ability to create and build OpenCV projects in Visual Studio (Tutorial: :ref:`Windows_Visual_Studio_How_To`).
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
`Download <http://go.microsoft.com/fwlink/?LinkId=285460>`_ the Image Watch installer. The installer comes in a single file with extension .vsix (*Visual Studio Extension*). To launch it, simply double-click on the .vsix file in Windows Explorer. When the installer has finished, make sure to restart Visual Studio to complete the installation.
|
||||
|
||||
Example
|
||||
========
|
||||
|
||||
Image Watch works with any existing project that uses OpenCV image objects (for example, *cv::Mat*). In this example, we use a minimal test program that loads an image from a file and runs an edge detector. To build the program, create a console application project in Visual Studio, name it "image-watch-demo", and insert the source code below.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Test application for the Visual Studio Image Watch Debugger extension
|
||||
|
||||
#include <iostream> // std::cout
|
||||
#include <opencv2/core/core.hpp> // cv::Mat
|
||||
#include <opencv2/highgui/highgui.hpp> // cv::imread()
|
||||
#include <opencv2/imgproc/imgproc.hpp> // cv::Canny()
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void help()
|
||||
{
|
||||
cout
|
||||
<< "----------------------------------------------------" << endl
|
||||
<< "This is a test program for the Image Watch Debugger " << endl
|
||||
<< "plug-in for Visual Studio. The program loads an " << endl
|
||||
<< "image from a file and runs the Canny edge detector. " << endl
|
||||
<< "No output is displayed or written to disk."
|
||||
<< endl
|
||||
<< "Usage:" << endl
|
||||
<< "image-watch-demo inputimage" << endl
|
||||
<< "----------------------------------------------------" << endl
|
||||
<< endl;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
help();
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
cout << "Wrong number of parameters" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cout << "Loading input image: " << argv[1] << endl;
|
||||
Mat input;
|
||||
input = imread(argv[1], CV_LOAD_IMAGE_COLOR);
|
||||
|
||||
cout << "Detecting edges in input image" << endl;
|
||||
Mat edges;
|
||||
Canny(input, edges, 10, 100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Make sure your active solution configuration (:menuselection:`Build --> Configuration Manager`) is set to a debug build (usually called "Debug"). This should disable compiler optimizations so that viewing variables in the debugger can work reliably.
|
||||
|
||||
Build your solution (:menuselection:`Build --> Build Solution`, or press *F7*).
|
||||
|
||||
Now set a breakpoint on the source line that says
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
Mat edges;
|
||||
|
||||
To set the breakpoint, right-click on the source line and select :menuselection:`Breakpoints --> Insert Breakpoint` from the context menu.
|
||||
|
||||
Launch the program in the debugger (:menuselection:`Debug --> Start Debugging`, or hit *F5*). When the breakpoint is hit, the program is paused and Visual Studio displays a yellow instruction pointer at the breakpoint:
|
||||
|
||||
.. image:: images/breakpoint.png
|
||||
|
||||
Now you can inspect the state of you program. For example, you can bring up the *Locals* window (:menuselection:`Debug --> Windows --> Locals`), which will show the names and values of the variables in the current scope:
|
||||
|
||||
.. image:: images/vs_locals.png
|
||||
|
||||
Note that the built-in *Locals* window will display text only. This is where the Image Watch plug-in comes in. Image Watch is like another *Locals* window, but with an image viewer built into it. To bring up Image Watch, select :menuselection:`View --> Other Windows --> Image Watch`. Like Visual Studio's *Locals* window, Image Watch can dock to the Visual Studio IDE. Also, Visual Studio will remember whether you had Image Watch open, and where it was located between debugging sessions. This means you only have to do this once--the next time you start debugging, Image Watch will be back where you left it. Here's what the docked Image Watch window looks like at our breakpoint:
|
||||
|
||||
.. image:: images/toolwindow.jpg
|
||||
:height: 320pt
|
||||
|
||||
The radio button at the top left (*Locals/Watch*) selects what is shown in the *Image List* below: *Locals* lists all OpenCV image objects in the current scope (this list is automatically populated). *Watch* shows image expressions that have been pinned for continuous inspection (not described here, see `Image Watch documentation <http://go.microsoft.com/fwlink/?LinkId=285461>`_ for details). The image list shows basic information such as width, height, number of channels, and, if available, a thumbnail. In our example, the image list contains our two local image variables, *input* and *edges*.
|
||||
|
||||
If an image has a thumbnail, left-clicking on that image will select it for detailed viewing in the *Image Viewer* on the right. The viewer lets you pan (drag mouse) and zoom (mouse wheel). It also displays the pixel coordinate and value at the current mouse position.
|
||||
|
||||
.. image:: images/viewer.jpg
|
||||
:height: 160pt
|
||||
|
||||
Note that the second image in the list, *edges*, is shown as "invalid". This indicates that some data members of this image object have corrupt or invalid values (for example, a negative image width). This is expected at this point in the program, since the C++ constructor for *edges* has not run yet, and so its members have undefined values (in debug mode they are usually filled with "0xCD" bytes).
|
||||
|
||||
From here you can single-step through your code (:menuselection:`Debug->Step Over`, or press *F10*) and watch the pixels change: if you step once, over the *Mat edges;* statement, the *edges* image will change from "invalid" to "empty", which means that it is now in a valid state (default constructed), even though it has not been initialized yet (using *cv::Mat::create()*, for example). If you make one more step over the *cv::Canny()* call, you will see a thumbnail of the edge image appear in the image list.
|
||||
|
||||
Now assume you want to do a visual sanity check of the *cv::Canny()* implementation. Bring the *edges* image into the viewer by selecting it in the *Image List* and zoom into a region with a clearly defined edge:
|
||||
|
||||
.. image:: images/edges_zoom.png
|
||||
:height: 160pt
|
||||
|
||||
Right-click on the *Image Viewer* to bring up the view context menu and enable :menuselection:`Link Views` (a check box next to the menu item indicates whether the option is enabled).
|
||||
|
||||
.. image:: images/viewer_context_menu.png
|
||||
:height: 120pt
|
||||
|
||||
The :menuselection:`Link Views` feature keeps the view region fixed when flipping between images of the same size. To see how this works, select the input image from the image list--you should now see the corresponding zoomed-in region in the input image:
|
||||
|
||||
.. image:: images/input_zoom.png
|
||||
:height: 160pt
|
||||
|
||||
You may also switch back and forth between viewing input and edges with your up/down cursor keys. That way you can easily verify that the detected edges line up nicely with the data in the input image.
|
||||
|
||||
More ...
|
||||
====================
|
||||
|
||||
Image watch has a number of more advanced features, such as
|
||||
|
||||
#. pinning images to a *Watch* list for inspection across scopes or between debugging sessions
|
||||
|
||||
#. clamping, thresholding, or diff'ing images directly inside the Watch window
|
||||
|
||||
#. comparing an in-memory image against a reference image from a file
|
||||
|
||||
Please refer to the online `Image Watch Documentation <http://go.microsoft.com/fwlink/?LinkId=285461>`_ for details--you also can get to the documentation page by clicking on the *Help* link in the Image Watch window:
|
||||
|
||||
.. image:: images/help_button.jpg
|
||||
:height: 80pt
|
@@ -26,9 +26,9 @@ This tutorial code's is shown lines below. You can also download it from `here <
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "opencv2/objdetect/objdetect.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|