diff --git a/doc/conf.py b/doc/conf.py index 3f47131209..4636e2ef38 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -349,7 +349,8 @@ extlinks = {'cvt_color': ('http://opencv.willowgarage.com/documentation/cpp/imgp 'basicstructures' : ('http://opencv.itseez.com/modules/core/doc/basic_structures.html#%s', None), 'readwriteimagevideo' : ('http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None), 'operationsonarrays' : ('http://opencv.itseez.com/modules/core/doc/operations_on_arrays.html#%s', None), - 'utilitysystemfunctions':('http://opencv.itseez.com/modules/core/doc/utility_and_system_functions_and_macros.html%s', None), + 'utilitysystemfunctions':('http://opencv.itseez.com/modules/core/doc/utility_and_system_functions_and_macros.html#%s', None), + 'imgprocfilter':('http://opencv.itseez.com/modules/imgproc/doc/filtering.html#%s', None), 'point_polygon_test' : ('http://opencv.willowgarage.com/documentation/cpp/imgproc_structural_analysis_and_shape_descriptors.html#cv-pointpolygontest%s', None) } diff --git a/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.rst b/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.rst new file mode 100644 index 0000000000..601445ad1f --- /dev/null +++ b/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.rst @@ -0,0 +1,62 @@ +.. _CameraCalibrationSquareChessBoardTutorial: + +Camera calibration with square chessboard +***************************************** + +.. highlight:: cpp + +The goal of this tutorial is to learn how to calibrate a camera given a set of chessboard images. + +*Test data*: use images in your data/chess folder. + +#. + Compile opencv with samples by setting ``BUILD_EXAMPLES`` to ``ON`` in cmake configuration. + +#. + Go to ``bin`` folder and use ``imagelist_creator`` to create an ``XML/YAML`` list of your images. + +#. + Then, run ``calibration`` sample to get camera parameters. Use square size equal to 3cm. + +Pose estimation +=============== + +Now, let us write a code that detects a chessboard in a new image and finds its distance from the camera. You can apply the same method to any object with known 3D geometry that you can detect in an image. + +*Test data*: use chess_test*.jpg images from your data folder. + +#. + Create an empty console project. Load a test image: :: + + Mat img = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); + +#. + Detect a chessboard in this image using findChessboard function. :: + + bool found = findChessboardCorners( img, boardSize, ptvec, CV_CALIB_CB_ADAPTIVE_THRESH ); + +#. + Now, write a function that generates a ``vector`` array of 3d coordinates of a chessboard in any coordinate system. For simplicity, let us choose a system such that one of the chessboard corners is in the origin and the board is in the plane *z = 0*. + +#. + Read camera parameters from XML/YAML file: :: + + FileStorage fs(filename, FileStorage::READ); + Mat intrinsics, distortion; + fs["camera_matrix"] >> intrinsics; + fs["distortion_coefficients"] >> distortion; + +#. + Now we are ready to find chessboard pose by running ``solvePnP``: :: + + vector boardPoints; + // fill the array + ... + + solvePnP(Mat(boardPoints), Mat(foundBoardCorners), cameraMatrix, + distCoeffs, rvec, tvec, false); + +#. + Calculate reprojection error like it is done in ``calibration`` sample (see ``opencv/samples/cpp/calibration.cpp``, function ``computeReprojectionErrors``). + +Question: how to calculate the distance from the camera origin to any of the corners? \ No newline at end of file diff --git a/doc/tutorials/calib3d/table_of_content_calib3d/images/camera_calibration_square_chess.jpg b/doc/tutorials/calib3d/table_of_content_calib3d/images/camera_calibration_square_chess.jpg new file mode 100644 index 0000000000..1fcab0f83c Binary files /dev/null and b/doc/tutorials/calib3d/table_of_content_calib3d/images/camera_calibration_square_chess.jpg differ diff --git a/doc/tutorials/calib3d/table_of_content_calib3d/table_of_content_calib3d.rst b/doc/tutorials/calib3d/table_of_content_calib3d/table_of_content_calib3d.rst index 21d58f43fe..ce5812ec2c 100644 --- a/doc/tutorials/calib3d/table_of_content_calib3d/table_of_content_calib3d.rst +++ b/doc/tutorials/calib3d/table_of_content_calib3d/table_of_content_calib3d.rst @@ -5,8 +5,32 @@ Although we got most of our images in a 2D format they do come from a 3D world. Here you will learn how to find out from the 2D images information about the 3D world. -.. include:: ../../definitions/noContent.rst +.. include:: ../../definitions/tocDefinitions.rst + ++ + .. tabularcolumns:: m{100pt} m{300pt} + .. cssclass:: toctableopencv + + ===================== ============================================== + |CameraCalSqChess| **Title:** :ref:`CameraCalibrationSquareChessBoardTutorial` + + *Compatibility:* > OpenCV 2.0 + + *Author:* |Author_VictorE| + + You will use some chessboard images to calibrate your camera. + + ===================== ============================================== + + .. |CameraCalSqChess| image:: images/camera_calibration_square_chess.jpg + :height: 90pt + :width: 90pt .. raw:: latex \pagebreak + +.. toctree:: + :hidden: + + ../camera_calibration_square_chess/camera_calibration_square_chess diff --git a/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.rst b/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.rst new file mode 100644 index 0000000000..bf98b5b5df --- /dev/null +++ b/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.rst @@ -0,0 +1,15 @@ +.. _discretFourierTransform: + +Discrete Fourier Transform +************************** + +Goal +==== + +We'll seek answers for the following questions: + +.. container:: enumeratevisibleitemswithsquare + + + What is a Fourier transform and why use it? + + How to do it in OpenCV? + + Usage of functions such as: :imgprocfilter:`copyMakeBorder() `, :operationsonarrays:`merge() `, :operationsonarrays:`dft() `, :operationsonarrays:`getOptimalDFTSize() `, :operationsonarrays:`log() ` and :operationsonarrays:`normalize() ` . diff --git a/doc/tutorials/core/table_of_content_core/images/discrete_fourier_transform.png b/doc/tutorials/core/table_of_content_core/images/discrete_fourier_transform.png new file mode 100644 index 0000000000..07bd1119f4 Binary files /dev/null and b/doc/tutorials/core/table_of_content_core/images/discrete_fourier_transform.png differ diff --git a/doc/tutorials/core/table_of_content_core/table_of_content_core.rst b/doc/tutorials/core/table_of_content_core/table_of_content_core.rst index 9049ad324f..6d64fd94d1 100644 --- a/doc/tutorials/core/table_of_content_core/table_of_content_core.rst +++ b/doc/tutorials/core/table_of_content_core/table_of_content_core.rst @@ -124,6 +124,25 @@ Here you will learn the about the basic building blocks of the library. A must r :height: 90pt :width: 90pt ++ + .. tabularcolumns:: m{100pt} m{300pt} + .. cssclass:: toctableopencv + + =============== ====================================================== + |DiscFourTr| **Title:** * :ref:`discretFourierTransform` + + *Compatibility:* > OpenCV 2.0 + + *Author:* |Author_BernatG| + + You will see how and why use the Discrete Fourier transformation with OpenCV. + + =============== ====================================================== + + .. |DiscFourTr| image:: images/discrete_fourier_transform.png + :height: 90pt + :width: 90pt + .. raw:: latex \pagebreak @@ -137,4 +156,5 @@ Here you will learn the about the basic building blocks of the library. A must r ../basic_linear_transform/basic_linear_transform ../basic_geometric_drawing/basic_geometric_drawing ../random_generator_and_text/random_generator_and_text - ../mat-mask-operations/mat-mask-operations.rst \ No newline at end of file + ../mat-mask-operations/mat-mask-operations + ../discrete_fourier_transform/discrete_fourier_transform \ No newline at end of file diff --git a/doc/tutorials/definitions/tocDefinitions.rst b/doc/tutorials/definitions/tocDefinitions.rst index 61ac91291e..7f7dca7aa1 100644 --- a/doc/tutorials/definitions/tocDefinitions.rst +++ b/doc/tutorials/definitions/tocDefinitions.rst @@ -1,7 +1,7 @@ .. |Author_AnaH| unicode:: Ana U+0020 Huam U+00E1 n .. |Author_BernatG| unicode:: Bern U+00E1 t U+0020 G U+00E1 bor .. |Author_AndreyK| unicode:: Andrey U+0020 Kamaev - +.. |Author_VictorE| unicode:: Victor Eruhimov diff --git a/doc/tutorials/features2d/detection_of_planar_objects/detection_of_planar_objects.rst b/doc/tutorials/features2d/detection_of_planar_objects/detection_of_planar_objects.rst new file mode 100644 index 0000000000..2345b9e5a8 --- /dev/null +++ b/doc/tutorials/features2d/detection_of_planar_objects/detection_of_planar_objects.rst @@ -0,0 +1,72 @@ +.. _detectionOfPlanarObjects: + +Detection of planar objects +*************************** + +.. highlight:: cpp + +The goal of this tutorial is to learn how to use *features2d* and *calib3d* modules for detecting known planar objects in scenes. + +*Test data*: use images in your data folder, for instance, ``box.png`` and ``box_in_scene.png``. + +#. + Create a new console project. Read two input images. :: + + Mat img1 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); + Mat img2 = imread(argv[2], CV_LOAD_IMAGE_GRAYSCALE); + +#. + Detect keypoints in both images. :: + + // detecting keypoints + FastFeatureDetector detector(15); + vector keypoints1; + detector.detect(img1, keypoints1); + + ... // do the same for the second image + +#. + Compute descriptors for each of the keypoints. :: + + // computing descriptors + SurfDescriptorExtractor extractor; + Mat descriptors1; + extractor.compute(img1, keypoints1, descriptors1); + + ... // process keypoints from the second image as well + +#. + Now, find the closest matches between descriptors from the first image to the second: :: + + // matching descriptors + BruteForceMatcher > matcher; + vector matches; + matcher.match(descriptors1, descriptors2, matches); + +#. + Visualize the results: :: + + // drawing the results + namedWindow("matches", 1); + Mat img_matches; + drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches); + imshow("matches", img_matches); + waitKey(0); + +#. + Find the homography transformation between two sets of points: :: + + vector points1, points2; + // fill the arrays with the points + .... + Mat H = findHomography(Mat(points1), Mat(points2), CV_RANSAC, ransacReprojThreshold); + + +#. + Create a set of inlier matches and draw them. Use perspectiveTransform function to map points with homography: + + Mat points1Projected; + perspectiveTransform(Mat(points1), points1Projected, H); + +#. + Use ``drawMatches`` for drawing inliers. diff --git a/doc/tutorials/features2d/table_of_content_features2d/images/detection_of_planar_objects.png b/doc/tutorials/features2d/table_of_content_features2d/images/detection_of_planar_objects.png new file mode 100644 index 0000000000..92de70cfdc Binary files /dev/null and b/doc/tutorials/features2d/table_of_content_features2d/images/detection_of_planar_objects.png differ diff --git a/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.rst b/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.rst index a8a249ef4a..062f03fd70 100644 --- a/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.rst +++ b/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.rst @@ -86,6 +86,25 @@ Learn about how to use the feature points detectors, descriptors and matching f :height: 90pt :width: 90pt ++ + .. tabularcolumns:: m{100pt} m{300pt} + .. cssclass:: toctableopencv + + ===================== ============================================== + |DetectPlanar| **Title:** :ref:`detectionOfPlanarObjects` + + *Compatibility:* > OpenCV 2.0 + + *Author:* |Author_VictorE| + + You will use *features2d* and *calib3d* modules for detecting known planar objects in scenes. + + ===================== ============================================== + + .. |DetectPlanar| image:: images/detection_of_planar_objects.png + :height: 90pt + :width: 90pt + .. raw:: latex \pagebreak @@ -97,3 +116,4 @@ Learn about how to use the feature points detectors, descriptors and matching f ../trackingmotion/good_features_to_track/good_features_to_track.rst ../trackingmotion/generic_corner_detector/generic_corner_detector ../trackingmotion/corner_subpixeles/corner_subpixeles + ../detection_of_planar_objects/detection_of_planar_objects \ No newline at end of file diff --git a/doc/tutorials/introduction/linux_eclipse/linux_eclipse.rst b/doc/tutorials/introduction/linux_eclipse/linux_eclipse.rst index 4ce835b377..2d300f0100 100644 --- a/doc/tutorials/introduction/linux_eclipse/linux_eclipse.rst +++ b/doc/tutorials/introduction/linux_eclipse/linux_eclipse.rst @@ -207,6 +207,7 @@ Say you have or create a new file, *helloworld.cpp* in a directory called *foo*: .. code-block:: cpp + #include #include int main ( int argc, char **argv ) @@ -243,9 +244,9 @@ Say you have or create a new file, *helloworld.cpp* in a directory called *foo*: #. Run ``make -j4`` *(the ``-j4`` is optional, it just tells the compiler to build in 4 threads)*. Make sure it builds. -#. Start ``eclipse``. Put the workspace in some directory but **not** in ``foo`` or ``foo\\build`` +#. Start ``eclipse`` . Put the workspace in some directory but **not** in ``foo`` or ``foo\\build`` -#. Right click in the ``Project Explorer`` section. Select ``Import`` And then open the ``C/C++`` filter. Choose *Existing Code as a Makefile Project`` +#. Right click in the ``Project Explorer`` section. Select ``Import`` And then open the ``C/C++`` filter. Choose *Existing Code* as a Makefile Project`` #. Name your project, say *helloworld*. Browse to the Existing Code location ``foo\\build`` (where you ran your cmake-gui from). Select *Linux GCC* in the *"Toolchain for Indexer Settings"* and press *Finish*. diff --git a/doc/tutorials/introduction/linux_install/linux_install.rst b/doc/tutorials/introduction/linux_install/linux_install.rst index 52f080addd..e78e1d849c 100644 --- a/doc/tutorials/introduction/linux_install/linux_install.rst +++ b/doc/tutorials/introduction/linux_install/linux_install.rst @@ -19,7 +19,7 @@ Required packages * pkgconfig * libpng, zlib, libjpeg, libtiff, libjasper with development files (e.g. libpjeg-dev) * Python 2.3 or later with developer packages (e.g. python-dev) - * SWIG 1.3.30 or later + * SWIG 1.3.30 or later (only for versions prior to OpenCV 2.3) * libavcodec * libdc1394 2.x diff --git a/doc/tutorials/introduction/windows_install/windows_install.rst b/doc/tutorials/introduction/windows_install/windows_install.rst index 078813964e..720249d46f 100644 --- a/doc/tutorials/introduction/windows_install/windows_install.rst +++ b/doc/tutorials/introduction/windows_install/windows_install.rst @@ -60,7 +60,7 @@ If you are building your own libraries you can take either the source files from .. container:: enumeratevisibleitemswithsquare - + stable and tested build - https://code.ros.org/svn/opencv/branches/ + + stable and tested build - https://code.ros.org/svn/opencv/branches/2.3 (this will change with every new realease) + development build - https://code.ros.org/svn/opencv/trunk/ While the later one may contain a couple of new and experimental algorithms, performance increases and interface improvements, be aware, that it may also contain many-many bugs. Using the first one is recommended in most of the cases. That is unless you are extending the OpenCV library itself or really need to most up to date version of it. @@ -285,11 +285,11 @@ Building the library .. container:: enumeratevisibleitemswithsquare - + *BUILD_DOCS* -> Build the documentation of OpenCV (there will be a separate project for building the HTML and the PDF files). + + *BUILD_DOCS* -> It creates two projects for building the documentation of OpenCV (there will be a separate project for building the HTML and the PDF files). Note that these aren't built together with the solution. You need to make an explicit build project command on these to do so. + *BUILD_EXAMPLES* -> OpenCV comes with many example applications from which you may learn most of the libraries capabilities. This will also come handy to easily try out if OpenCV is fully functional on your computer. - + *BUILD_JAVA_SUPPORT* -> This is a fresh addition to OpenCV, which slowly start to support the java language. + + *BUILD_JAVA_SUPPORT* -> At the moment this has no real meaning on the Windows platform. Ignore it. + *BUILD_NEW_PYTHON_SUPPORT* -> Self-explanatory. Create the binaries to use OpenCV from the Python language. - + *BUILD_PACKAGE* -> Build a project that will build an OpenCV installer. With this you can easily install your OpenCV flavor on other systems. + + *BUILD_PACKAGE* -> Prior to version 2.3 with this you could build a project that will build an OpenCV installer. With this you can easily install your OpenCV flavor on other systems. For the latest source files of OpenCV it generates a new project that simply creates zip archive with OpenCV sources. + *BUILD_SHARED_LIBS* -> With this you can control to build DLL files (when turned on) or static library files (\*.lib) otherwise. + *BUILD_TESTS* -> Each module of OpenCV has a test project assigned to it. Building these test projects is also a good way to try out, that the modules work just as expected on your system too. diff --git a/samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp b/samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp new file mode 100644 index 0000000000..ecd40dd689 --- /dev/null +++ b/samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp @@ -0,0 +1,172 @@ +/** + * @file Drawing_1.cpp + * @brief Simple sample code + */ + +#include +#include + +#define w 400 + +using namespace cv; + +/// Function headers +void MyEllipse( Mat img, double angle ); +void MyFilledCircle( Mat img, Point center ); +void MyPolygon( Mat img ); +void MyLine( Mat img, Point start, Point end ); + +/** + * @function main + * @brief Main function + */ +int main( int argc, char **argv ){ + + /// 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 ); + + /// 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.b. Creating circles + MyFilledCircle( atom_image, Point( w/2.0, w/2.0) ); + + /// 2. Draw a rook + /// ------------------ + + /// 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.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 ) ); + + /// 3. Display your stuff! + imshow( atom_window, atom_image ); + cvMoveWindow( atom_window, 0, 200 ); + imshow( rook_window, rook_image ); + cvMoveWindow( rook_window, w, 200 ); + + waitKey( 0 ); + return(0); +} + +/// Function Declaration + +/** + * @function MyEllipse + * @brief Draw a fixed-size ellipse with different angles + */ +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 ); +} + +/** + * @function MyFilledCircle + * @brief Draw a fixed-size filled circle + */ +void MyFilledCircle( Mat img, Point center ) +{ + int thickness = -1; + int lineType = 8; + + circle( img, + center, + w/32.0, + Scalar( 0, 0, 255 ), + thickness, + lineType ); +} + +/** + * @function MyPolygon + * @function Draw a simple concave polygon (rook) + */ +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) ; + + const Point* ppt[1] = { rook_points[0] }; + int npt[] = { 20 }; + + fillPoly( img, + ppt, + npt, + 1, + Scalar( 255, 255, 255 ), + lineType ); +} + +/** + * @function MyLine + * @brief Draw a simple line + */ +void MyLine( Mat img, Point start, Point end ) +{ + int thickness = 2; + int lineType = 8; + line( img, + start, + end, + Scalar( 0, 0, 0 ), + thickness, + lineType ); +} + + diff --git a/samples/cpp/tutorial_code/core/Matrix/Drawing_2.cpp b/samples/cpp/tutorial_code/core/Matrix/Drawing_2.cpp new file mode 100644 index 0000000000..f66f205e7a --- /dev/null +++ b/samples/cpp/tutorial_code/core/Matrix/Drawing_2.cpp @@ -0,0 +1,326 @@ +/** + * @file Drawing_2.cpp + * @brief Simple sample code + */ + +#include +#include +#include +#include + +using namespace cv; + +/// Global Variables +const int NUMBER = 100; +const int DELAY = 5; + +const int window_width = 900; +const int window_height = 600; +int x_1 = -window_width/2; +int x_2 = window_width*3/2; +int y_1 = -window_width/2; +int y_2 = window_width*3/2; + +/// Function headers +static Scalar randomColor( RNG& rng ); +int Drawing_Random_Lines( Mat image, char* window_name, RNG rng ); +int Drawing_Random_Rectangles( Mat image, char* window_name, RNG rng ); +int Drawing_Random_Ellipses( Mat image, char* window_name, RNG rng ); +int Drawing_Random_Polylines( Mat image, char* window_name, RNG rng ); +int Drawing_Random_Filled_Polygons( Mat image, char* window_name, RNG rng ); +int Drawing_Random_Circles( Mat image, char* window_name, RNG rng ); +int Displaying_Random_Text( Mat image, char* window_name, RNG rng ); +int Displaying_Big_End( Mat image, char* window_name, RNG rng ); + + +/** + * @function main + */ +int main( int argc, char** argv ) +{ + int c; + + /// Start creating a window + char window_name[] = "Drawing_2 Tutorial"; + + /// Also create a random object (RNG) + RNG rng( 0xFFFFFFFF ); + + /// Initialize a matrix filled with zeros + Mat image = Mat::zeros( window_height, window_width, CV_8UC3 ); + /// Show it in a window during DELAY ms + imshow( window_name, image ); + waitKey( DELAY ); + + /// Now, let's draw some lines + c = Drawing_Random_Lines(image, window_name, rng); + if( c != 0 ) return 0; + + /// Go on drawing, this time nice rectangles + c = Drawing_Random_Rectangles(image, window_name, rng); + if( c != 0 ) return 0; + + /// Draw some ellipses + c = Drawing_Random_Ellipses( image, window_name, rng ); + if( c != 0 ) return 0; + + /// Now some polylines + c = Drawing_Random_Polylines( image, window_name, rng ); + if( c != 0 ) return 0; + + /// Draw filled polygons + c = Drawing_Random_Filled_Polygons( image, window_name, rng ); + if( c != 0 ) return 0; + + /// Draw circles + c = Drawing_Random_Circles( image, window_name, rng ); + if( c != 0 ) return 0; + + /// Display text in random positions + c = Displaying_Random_Text( image, window_name, rng ); + if( c != 0 ) return 0; + + /// Displaying the big end! + c = Displaying_Big_End( image, window_name, rng ); + if( c != 0 ) return 0; + + waitKey(0); + return 0; +} + +/// Function definitions + +/** + * @function randomColor + * @brief Produces a random color given a random object + */ +static Scalar randomColor( RNG& rng ) +{ + int icolor = (unsigned) rng; + return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 ); +} + + +/** + * @function Drawing_Random_Lines + */ +int Drawing_Random_Lines( Mat image, char* window_name, RNG rng ) +{ + int lineType = 8; + Point pt1, pt2; + + for( int i = 0; i < NUMBER; i++ ) + { + pt1.x = rng.uniform( x_1, x_2 ); + pt1.y = rng.uniform( y_1, y_2 ); + pt2.x = rng.uniform( x_1, x_2 ); + pt2.y = rng.uniform( y_1, y_2 ); + + line( image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8 ); + imshow( window_name, image ); + if( waitKey( DELAY ) >= 0 ) + { return -1; } + } + + return 0; +} + +/** + * @function Drawing_Rectangles + */ +int Drawing_Random_Rectangles( Mat image, char* window_name, RNG rng ) +{ + Point pt1, pt2; + int lineType = 8; + int thickness = rng.uniform( -3, 10 ); + + for( int i = 0; i < NUMBER; i++ ) + { + pt1.x = rng.uniform( x_1, x_2 ); + pt1.y = rng.uniform( y_1, y_2 ); + pt2.x = rng.uniform( x_1, x_2 ); + pt2.y = rng.uniform( y_1, y_2 ); + + rectangle( image, pt1, pt2, randomColor(rng), MAX( thickness, -1 ), lineType ); + + imshow( window_name, image ); + if( waitKey( DELAY ) >= 0 ) + { return -1; } + } + + return 0; +} + +/** + * @function Drawing_Random_Ellipses + */ +int Drawing_Random_Ellipses( Mat image, char* window_name, RNG rng ) +{ + int lineType = 8; + + for ( int i = 0; i < NUMBER; i++ ) + { + Point center; + center.x = rng.uniform(x_1, x_2); + center.y = rng.uniform(y_1, y_2); + + Size axes; + axes.width = rng.uniform(0, 200); + axes.height = rng.uniform(0, 200); + + double angle = rng.uniform(0, 180); + + ellipse( image, center, axes, angle, angle - 100, angle + 200, + randomColor(rng), rng.uniform(-1,9), lineType ); + + imshow( window_name, image ); + + if( waitKey(DELAY) >= 0 ) + { return -1; } + } + + return 0; +} + +/** + * @function Drawing_Random_Polylines + */ +int Drawing_Random_Polylines( Mat image, char* window_name, RNG rng ) +{ + int lineType = 8; + + for( int i = 0; i< NUMBER; i++ ) + { + Point pt[2][3]; + pt[0][0].x = rng.uniform(x_1, x_2); + pt[0][0].y = rng.uniform(y_1, y_2); + pt[0][1].x = rng.uniform(x_1, x_2); + pt[0][1].y = rng.uniform(y_1, y_2); + pt[0][2].x = rng.uniform(x_1, x_2); + pt[0][2].y = rng.uniform(y_1, y_2); + pt[1][0].x = rng.uniform(x_1, x_2); + pt[1][0].y = rng.uniform(y_1, y_2); + pt[1][1].x = rng.uniform(x_1, x_2); + pt[1][1].y = rng.uniform(y_1, y_2); + pt[1][2].x = rng.uniform(x_1, x_2); + pt[1][2].y = rng.uniform(y_1, y_2); + + const Point* ppt[2] = {pt[0], pt[1]}; + int npt[] = {3, 3}; + + polylines(image, ppt, npt, 2, true, randomColor(rng), rng.uniform(1,10), lineType); + + imshow( window_name, image ); + if( waitKey(DELAY) >= 0 ) + { return -1; } + } + return 0; +} + +/** + * @function Drawing_Random_Filled_Polygons + */ +int Drawing_Random_Filled_Polygons( Mat image, char* window_name, RNG rng ) +{ + int lineType = 8; + + for ( int i = 0; i < NUMBER; i++ ) + { + Point pt[2][3]; + pt[0][0].x = rng.uniform(x_1, x_2); + pt[0][0].y = rng.uniform(y_1, y_2); + pt[0][1].x = rng.uniform(x_1, x_2); + pt[0][1].y = rng.uniform(y_1, y_2); + pt[0][2].x = rng.uniform(x_1, x_2); + pt[0][2].y = rng.uniform(y_1, y_2); + pt[1][0].x = rng.uniform(x_1, x_2); + pt[1][0].y = rng.uniform(y_1, y_2); + pt[1][1].x = rng.uniform(x_1, x_2); + pt[1][1].y = rng.uniform(y_1, y_2); + pt[1][2].x = rng.uniform(x_1, x_2); + pt[1][2].y = rng.uniform(y_1, y_2); + + const Point* ppt[2] = {pt[0], pt[1]}; + int npt[] = {3, 3}; + + fillPoly( image, ppt, npt, 2, randomColor(rng), lineType ); + + imshow( window_name, image ); + if( waitKey(DELAY) >= 0 ) + { return -1; } + } + return 0; +} + +/** + * @function Drawing_Random_Circles + */ +int Drawing_Random_Circles( Mat image, char* window_name, RNG rng ) +{ + int lineType = 8; + + for (int i = 0; i < NUMBER; i++) + { + Point center; + center.x = rng.uniform(x_1, x_2); + center.y = rng.uniform(y_1, y_2); + + circle( image, center, rng.uniform(0, 300), randomColor(rng), + rng.uniform(-1, 9), lineType ); + + imshow( window_name, image ); + if( waitKey(DELAY) >= 0 ) + { return -1; } + } + + return 0; +} + +/** + * @function Displaying_Random_Text + */ +int Displaying_Random_Text( Mat image, char* window_name, RNG rng ) +{ + int lineType = 8; + + for ( int i = 1; i < NUMBER; i++ ) + { + Point org; + org.x = rng.uniform(x_1, x_2); + org.y = rng.uniform(y_1, y_2); + + putText( image, "Testing text rendering", org, rng.uniform(0,8), + rng.uniform(0,100)*0.05+0.1, randomColor(rng), rng.uniform(1, 10), lineType); + + imshow( window_name, image ); + if( waitKey(DELAY) >= 0 ) + { return -1; } + } + + return 0; +} + +/** + * @function Displaying_Big_End + */ +int Displaying_Big_End( Mat image, char* window_name, RNG rng ) +{ + Size textsize = getTextSize("OpenCV forever!", CV_FONT_HERSHEY_COMPLEX, 3, 5, 0); + Point org((window_width - textsize.width)/2, (window_height - textsize.height)/2); + int lineType = 8; + + Mat image2; + + for( int i = 0; i < 255; i += 2 ) + { + image2 = image - Scalar::all(i); + putText( image2, "OpenCV forever!", org, CV_FONT_HERSHEY_COMPLEX, 3, + Scalar(i, i, 255), 5, lineType ); + + imshow( window_name, image2 ); + if( waitKey(DELAY) >= 0 ) + { return -1; } + } + + return 0; +} diff --git a/samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp b/samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp new file mode 100644 index 0000000000..6f05d07804 --- /dev/null +++ b/samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp @@ -0,0 +1,79 @@ +#include "opencv2/core/core.hpp" +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/highgui/highgui.hpp" + +#include + +using namespace cv; +using namespace std; + +void help(char* progName) +{ + cout << endl + << "This program demonstrated the use of the discrete Fourier transform (DFT). " << endl + << "The dft of an image is taken and it's power spectrum is displayed." << endl + << "Usage:" << endl + << progName << " [image_name -- default lena.jpg] " << endl << endl; +} + +int main(int argc, char ** argv) +{ + help(argv[0]); + + const char* filename = argc >=2 ? argv[1] : "lena.jpg"; + + Mat I = imread(filename, CV_LOAD_IMAGE_GRAYSCALE); + if( I.empty()) + return -1; + + Mat padded; //expand input image to optimal size + int m = getOptimalDFTSize( I.rows ); + int n = getOptimalDFTSize( I.cols ); // on the border keep the values + copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0)); + + Mat planes[] = {Mat_(padded), Mat::zeros(padded.size(), CV_32F)}; + Mat complexI; + merge(planes, 2, complexI); // Add to the expanded another plane with zeros + + dft(complexI, complexI); // this way the result may fit in the source matrix + + // compute the magnitude and switch to logarithmic scale + // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)) + split(complexI, planes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) + magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude + Mat magI = planes[0]; + + magI += Scalar::all(1); // switch to logarithmic scale + log(magI, magI); + + // crop the spectrum, if it has an odd number of rows or columns + magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2)); + + // rearrange the quadrants of Fourier image so that the origin is at the image center + int cx = magI.cols/2; + int cy = magI.rows/2; + + Mat q0(magI, Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant + Mat q1(magI, Rect(cx, 0, cx, cy)); // Top-Right + Mat q2(magI, Rect(0, cy, cx, cy)); // Bottom-Left + Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right + + Mat tmp; // swap quadrants (Top-Left with Bottom-Right) + q0.copyTo(tmp); + q3.copyTo(q0); + tmp.copyTo(q3); + + q1.copyTo(tmp); // swap quadrant (Top-Right with Bottom-Left) + q2.copyTo(q1); + tmp.copyTo(q2); + + normalize(magI, magI, 0, 1, CV_MINMAX); // Transform the matrix with float values into a + // viewable image form (float between values 0 and 1). + + imshow("Input Image" , I ); // Show the result + imshow("spectrum magnitude", magI); + waitKey(); + + return 0; +} + diff --git a/samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp b/samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp new file mode 100644 index 0000000000..7083cc0226 --- /dev/null +++ b/samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp @@ -0,0 +1,144 @@ +#include "opencv2/core/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +void help(char** av) +{ + cout << endl + << av[0] << " shows the usage of the OpenCV serialization functionality." << endl + << "usage: " << endl + << av[0] << " outputfile.yml.gz" << endl + << "The output file may be either XML (xml) or YAML (yml/yaml). You can even compress it by " + << "specifying this in its extension like xml.gz yaml.gz etc... " << endl + << "With FileStorage you can serialize objects in OpenCV by using the << and >> operators" << endl + << "For example: - create a class and have it serialized" << endl + << " - use it to read and write matrices." << endl; +} + +class MyData +{ +public: + MyData() : A(0), X(0), id() + {} + explicit MyData(int) : A(97), X(CV_PI), id("mydata1234") // explicit to avoid implicit conversion + {} + + void write(FileStorage& fs) const //Write serialization for this class + { + fs << "{" << "A" << A << "X" << X << "id" << id << "}"; + } + void read(const FileNode& node) //Read serialization for this class + { + A = (int)node["A"]; + X = (double)node["X"]; + id = (string)node["id"]; + } +public: // Data Members + int A; + double X; + string id; +}; + +//These write and read functions must be defined for the serialization in FileStorage to work +void write(FileStorage& fs, const std::string&, const MyData& x) +{ + x.write(fs); +} +void read(const FileNode& node, MyData& x, const MyData& default_value = MyData()){ + if(node.empty()) + x = default_value; + else + x.read(node); +} + +// This function will print our custom class to the console +ostream& operator<<(ostream& out, const MyData& m) +{ + out << "{ id = " << m.id << ", "; + out << "X = " << m.X << ", "; + out << "A = " << m.A << "}"; + return out; +} + +int main(int ac, char** av) +{ + if (ac != 2) + { + help(av); + return 1; + } + + string filename = av[1]; + + //write + { + Mat R = Mat_::eye(3, 3), + T = Mat_::zeros(3, 1); + + MyData m(1); + + FileStorage fs(filename, FileStorage::WRITE); + + + fs << "strings" << "["; + fs << "image1.jpg" << "Awesomeness" << "baboon.jpg"; + fs << "]"; + + fs << "R" << R; + fs << "T" << T; + + fs << "MyData" << m; + + cout << "Write Done." << endl; + } + + //read + { + cout << endl << "Reading: " << endl; + FileStorage fs(filename, FileStorage::READ); + + if (!fs.isOpened()) + { + cerr << "Failed to open " << filename << endl; + help(av); + return 1; + } + + FileNode n = fs["strings"]; + if (n.type() != FileNode::SEQ) + { + cerr << "strings is not a sequence! FAIL" << endl; + return 1; + } + + + FileNodeIterator it = n.begin(), it_end = n.end(); + for (; it != it_end; ++it) + cout << (string)*it << endl; + + MyData m; + Mat R, T; + + fs["R"] >> R; + fs["T"] >> T; + fs["MyData"] >> m; + + cout << endl + << "R = " << R << "\n"; + cout << "T = " << T << endl << endl; + cout << "MyData = " << endl << m << endl << endl; + + //Show default behavior for non existing nodes + cout << "Attempt to read NonExisting (should initialize the data structure with its default)."; + fs["NonExisting"] >> m; + cout << endl << "NonExisting = " << endl << m << endl; + } + + cout << endl + << "Tip: Open up " << filename << " with a text editor to see the serialized data." << endl; + + return 0; +} diff --git a/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp b/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp new file mode 100644 index 0000000000..d9d37a061b --- /dev/null +++ b/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +void help() +{ + cout + << "\n--------------------------------------------------------------------------" << endl + << "This program shows how to scan image objects in OpenCV (cv::Mat). As use case" + << " we take an input image and divide the native color palette (255) with the " << endl + << "input. Shows C operator[] method, iterators and at function for random access"<< endl + << "Usage:" << endl + << "./howToScanImages imageNameToUse divideWith [G]" << endl + << "if you add a G parameter the image is processed in gray scale" << endl + << "--------------------------------------------------------------------------" << endl + << endl; +} + +Mat& ScanImageAndReduceC(Mat& I, const uchar* table); +Mat& ScanImageAndReduceIterator(Mat& I, const uchar* table); +Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar * table); + +int main( int argc, char* argv[]) +{ + help(); + if (argc < 3) + { + cout << "Not enough parameters" << endl; + return -1; + } + + Mat I, J; + if( argc == 4 && !strcmp(argv[3],"G") ) + I = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); + else + I = imread(argv[1], CV_LOAD_IMAGE_COLOR); + + if (!I.data) + { + cout << "The image" << argv[1] << " could not be loaded." << endl; + return -1; + } + + int divideWith; // convert our input string to number - C++ style + stringstream s; + s << argv[2]; + s >> divideWith; + if (!s) + { + cout << "Invalid number entered for dividing. " << endl; + return -1; + } + + uchar table[256]; + for (int i = 0; i < 256; ++i) + table[i] = divideWith* (i/divideWith); + + const int times = 100; + double t; + + t = (double)getTickCount(); + + for (int i = 0; i < times; ++i) + J = ScanImageAndReduceC(I.clone(), table); + + t = 1000*((double)getTickCount() - t)/getTickFrequency(); + t /= times; + + cout << "Time of reducing with the C operator [] (averaged for " + << times << " runs): " << t << " milliseconds."<< endl; + + t = (double)getTickCount(); + + for (int i = 0; i < times; ++i) + J = ScanImageAndReduceIterator(I.clone(), table); + + t = 1000*((double)getTickCount() - t)/getTickFrequency(); + t /= times; + + cout << "Time of reducing with the iterator (averaged for " + << times << " runs): " << t << " milliseconds."<< endl; + + t = (double)getTickCount(); + + for (int i = 0; i < times; ++i) + ScanImageAndReduceRandomAccess(I.clone(), table); + + t = 1000*((double)getTickCount() - t)/getTickFrequency(); + t /= times; + + cout << "Time of reducing with the random access operator (averaged for " + << times << " runs): " << t << " milliseconds."<< endl; + + Mat lookUpTable(1, 256, CV_8U); + uchar* p = lookUpTable.data; + for( int i = 0; i < 256; ++i) + p[i] = table[i]; + + t = (double)getTickCount(); + + for (int i = 0; i < times; ++i) + LUT(I, lookUpTable, J); + + t = 1000*((double)getTickCount() - t)/getTickFrequency(); + t /= times; + + cout << "Time of reducing with the LUT function (averaged for " + << times << " runs): " << t << " milliseconds."<< endl; + return 0; +} + +Mat& ScanImageAndReduceC(Mat& I, const uchar* const table) +{ + // accept only char type matrices + CV_Assert(I.depth() != sizeof(uchar)); + + int channels = I.channels(); + + int nRows = I.rows * channels; + int nCols = I.cols; + + if (I.isContinuous()) + { + nCols *= nRows; + nRows = 1; + } + + int i,j; + uchar* p; + for( i = 0; i < nRows; ++i) + { + p = I.ptr(i); + for ( j = 0; j < nCols; ++j) + { + p[j] = table[p[j]]; + } + } + return I; +} + +Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table) +{ + // accept only char type matrices + CV_Assert(I.depth() != sizeof(uchar)); + + const int channels = I.channels(); + switch(channels) + { + case 1: + { + MatIterator_ it, end; + for( it = I.begin(), end = I.end(); it != end; ++it) + *it = table[*it]; + break; + } + case 3: + { + MatIterator_ it, end; + for( it = I.begin(), end = I.end(); it != end; ++it) + { + (*it)[0] = table[(*it)[0]]; + (*it)[1] = table[(*it)[1]]; + (*it)[2] = table[(*it)[2]]; + } + } + } + + return I; +} + +Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table) +{ + // accept only char type matrices + CV_Assert(I.depth() != sizeof(uchar)); + + const int channels = I.channels(); + switch(channels) + { + case 1: + { + for( int i = 0; i < I.rows; ++i) + for( int j = 0; j < I.cols; ++j ) + I.at(i,j) = table[I.at(i,j)]; + break; + } + case 3: + { + Mat_ _I = I; + + for( int i = 0; i < I.rows; ++i) + for( int j = 0; j < I.cols; ++j ) + { + _I(i,j)[0] = table[_I(i,j)[0]]; + _I(i,j)[1] = table[_I(i,j)[1]]; + _I(i,j)[2] = table[_I(i,j)[2]]; + } + I = _I; + break; + } + } + + return I; +} \ No newline at end of file diff --git a/samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp b/samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp new file mode 100644 index 0000000000..2b6c9af467 --- /dev/null +++ b/samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp @@ -0,0 +1,85 @@ +/* For description look into the help() function. */ + +#include "opencv2/core/core.hpp" +#include + +using namespace std; +using namespace cv; + +void help() +{ + cout + << "\n--------------------------------------------------------------------------" << endl + << "This program shows how to create matrices(cv::Mat) in OpenCV and its serial" + << " out capabilities" << endl + << "That is, cv::Mat M(...); M.create and cout << M. " << endl + << "Shows how output can be formated to OpenCV, python, numpy, csv and C styles." << endl + << "Usage:" << endl + << "./cvout_sample" << endl + << "--------------------------------------------------------------------------" << endl + << endl; +} + +int main(int,char**) +{ + help(); + // create by using the constructor + Mat M(2,2, CV_8UC3, Scalar(0,0,255)); + cout << "M = " << endl << " " << M << endl << endl; + + // create by using the create function() + M.create(4,4, CV_8UC(2)); + cout << "M = "<< endl << " " << M << endl << endl; + + // create multidimensional matrices + int sz[3] = {2,2,2}; + Mat L(3,sz, CV_8UC(1), Scalar::all(0)); + // Cannot print via operator << + + // Create using MATLAB style eye, ones or zero matrix + Mat E = Mat::eye(4, 4, CV_64F); + cout << "E = " << endl << " " << E << endl << endl; + + Mat O = Mat::ones(2, 2, CV_32F); + cout << "O = " << endl << " " << O << endl << endl; + + Mat Z = Mat::zeros(3,3, CV_8UC1); + cout << "Z = " << endl << " " << Z << endl << endl; + + // create a 3x3 double-precision identity matrix + Mat C = (Mat_(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); + cout << "C = " << endl << " " << C << endl << endl; + + Mat RowClone = C.row(1).clone(); + cout << "RowClone = " << endl << " " << RowClone << endl << endl; + + // Fill a matrix with random values + Mat R = Mat(3, 2, CV_8UC3); + randu(R, Scalar::all(0), Scalar::all(255)); + + // Demonstrate the output formating options + cout << "R (default) = " << endl << R << endl << endl; + cout << "R (python) = " << endl << format(R,"python") << endl << endl; + cout << "R (numpy) = " << endl << format(R,"numpy" ) << endl << endl; + cout << "R (csv) = " << endl << format(R,"csv" ) << endl << endl; + cout << "R (c) = " << endl << format(R,"C" ) << endl << endl; + + Point2f P(5, 1); + cout << "Point (2D) = " << P << endl << endl; + + Point3f P3f(2, 6, 7); + cout << "Point (3D) = " << P3f << endl << endl; + + + vector v; + v.push_back( (float)CV_PI); v.push_back(2); v.push_back(3.01f); + + cout << "Vector of floats via Mat = " << Mat(v) << endl << endl; + + vector vPoints(20); + for (size_t E = 0; E < vPoints.size(); ++E) + vPoints[E] = Point2f((float)(E * 5), (float)(E % 7)); + + cout << "A vector of 2D Points = " << vPoints << endl << endl; + return 0; +} \ No newline at end of file diff --git a/samples/cpp/tutorial_code/core/switching_to_the_new_interface/switching_to_the_new_interface.txt b/samples/cpp/tutorial_code/core/switching_to_the_new_interface/switching_to_the_new_interface.txt new file mode 100644 index 0000000000..4e004e1d97 --- /dev/null +++ b/samples/cpp/tutorial_code/core/switching_to_the_new_interface/switching_to_the_new_interface.txt @@ -0,0 +1,134 @@ +#include +#include + +#include +#include +#include + +using namespace cv; // The new C++ interface API is inside this namespace. Import it. +using namespace std; + +void help( char* progName) +{ + cout << endl << progName + << " shows how to use cv::Mat and IplImages together (converting back and forth)." << endl + << "Also contains example for image read, spliting the planes, merging back and " << endl + << " color conversion, plus iterating through pixels. " << endl + << "Usage:" << endl + << progName << " [image-name Default: lena.jpg]" << endl << endl; +} + +// comment out the define to use only the latest C++ API +#define DEMO_MIXED_API_USE + +int main( int argc, char** argv ) +{ + help(argv[0]); + const char* imagename = argc > 1 ? argv[1] : "lena.jpg"; + +#ifdef DEMO_MIXED_API_USE + Ptr IplI = cvLoadImage(imagename); // Ptr is safe ref-counting pointer class + if(IplI.empty()) + { + cerr << "Can not load image " << imagename << endl; + return -1; + } + Mat I(IplI); // Convert to the new style container. Only header created. Image not copied. +#else + Mat I = imread(imagename); // the newer cvLoadImage alternative, MATLAB-style function + if( I.empty() ) // same as if( !I.data ) + { + cerr << "Can not load image " << imagename << endl; + return -1; + } +#endif + + // convert image to YUV color space. The output image will be created automatically. + Mat I_YUV; + cvtColor(I, I_YUV, CV_BGR2YCrCb); + + vector planes; // Use the STL's vector structure to store multiple Mat objects + split(I_YUV, planes); // split the image into separate color planes (Y U V) + +#if 0 // change it to 0 if you want to see a blurred and noisy version of this processing + // Mat scanning + // Method 1. process Y plane using an iterator + MatIterator_ it = planes[0].begin(), it_end = planes[0].end(); + for(; it != it_end; ++it) + { + double v = *it * 1.7 + rand()%21 - 10; + *it = saturate_cast(v*v/255); + } + + for( int y = 0; y < I_YUV.rows; y++ ) + { + // Method 2. process the first chroma plane using pre-stored row pointer. + uchar* Uptr = planes[1].ptr(y); + for( int x = 0; x < I_YUV.cols; x++ ) + { + Uptr[x] = saturate_cast((Uptr[x]-128)/2 + 128); + + // Method 3. process the second chroma plane using individual element access + uchar& Vxy = planes[2].at(y, x); + Vxy = saturate_cast((Vxy-128)/2 + 128); + } + } + +#else + + Mat noisyI(I.size(), CV_8U); // Create a matrix of the specified size and type + + // Fills the matrix with normally distributed random values (around number with deviation off). + // There is also randu() for uniformly distributed random number generation + randn(noisyI, Scalar::all(128), Scalar::all(20)); + + // blur the noisyI a bit, kernel size is 3x3 and both sigma's are set to 0.5 + GaussianBlur(noisyI, noisyI, Size(3, 3), 0.5, 0.5); + + const double brightness_gain = 0; + const double contrast_gain = 1.7; + +#ifdef DEMO_MIXED_API_USE + // To pass the new matrices to the functions that only work with IplImage or CvMat do: + // step 1) Convert the headers (tip: data will not be copied). + // step 2) call the function (tip: to pass a pointer do not forget unary "&" to form pointers) + + IplImage cv_planes_0 = planes[0], cv_noise = noisyI; + cvAddWeighted(&cv_planes_0, contrast_gain, &cv_noise, 1, -128 + brightness_gain, &cv_planes_0); +#else + addWeighted(planes[0], contrast_gain, noisyI, 1, -128 + brightness_gain, planes[0]); +#endif + + const double color_scale = 0.5; + // Mat::convertTo() replaces cvConvertScale. + // One must explicitly specify the output matrix type (we keep it intact - planes[1].type()) + planes[1].convertTo(planes[1], planes[1].type(), color_scale, 128*(1-color_scale)); + + // alternative form of cv::convertScale if we know the datatype at compile time ("uchar" here). + // This expression will not create any temporary arrays ( so should be almost as fast as above) + planes[2] = Mat_(planes[2]*color_scale + 128*(1-color_scale)); + + // Mat::mul replaces cvMul(). Again, no temporary arrays are created in case of simple expressions. + planes[0] = planes[0].mul(planes[0], 1./255); +#endif + + + merge(planes, I_YUV); // now merge the results back + cvtColor(I_YUV, I, CV_YCrCb2BGR); // and produce the output RGB image + + + namedWindow("image with grain", CV_WINDOW_AUTOSIZE); // use this to create images + +#ifdef DEMO_MIXED_API_USE + // this is to demonstrate that I and IplI really share the data - the result of the above + // processing is stored in I and thus in IplI too. + cvShowImage("image with grain", IplI); +#else + imshow("image with grain", I); // the new MATLAB style function show +#endif + waitKey(); + + // Tip: No memory freeing is required! + // All the memory will be automatically released by the Vector<>, Mat and Ptr<> destructor. + return 0; +}