Merge remote-tracking branch 'origin/2.4' into merge-2.4
authorRoman Donchenko <roman.donchenko@itseez.com>
Wed, 3 Jul 2013 15:53:21 +0000 (19:53 +0400)
committerRoman Donchenko <roman.donchenko@itseez.com>
Wed, 3 Jul 2013 15:53:21 +0000 (19:53 +0400)
Conflicts:
doc/tutorials/definitions/noContent.rst
doc/tutorials/gpu/gpu-basics-similarity/gpu-basics-similarity.rst
doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.rst
doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst
modules/core/include/opencv2/core/core.hpp
modules/core/include/opencv2/core/internal.hpp
modules/core/include/opencv2/core/version.hpp
modules/gpu/CMakeLists.txt
modules/highgui/perf/perf_output.cpp
modules/highgui/test/test_video_io.cpp
modules/ocl/include/opencv2/ocl/ocl.hpp
modules/ocl/perf/main.cpp
modules/ocl/src/hog.cpp
modules/ocl/src/initialization.cpp
modules/ocl/src/moments.cpp
modules/ocl/src/opencl/moments.cl
modules/ocl/test/main.cpp
modules/ocl/test/test_moments.cpp
modules/python/test/test.py
modules/ts/include/opencv2/ts/ts_perf.hpp
modules/ts/src/precomp.hpp
modules/ts/src/ts_perf.cpp

61 files changed:
1  2 
cmake/OpenCVDetectCUDA.cmake
cmake/templates/cvconfig.h.cmake
doc/tutorials/definitions/noContent.rst
doc/tutorials/gpu/gpu-basics-similarity/gpu-basics-similarity.rst
doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.rst
doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst
doc/tutorials/introduction/ios_install/ios_install.rst
doc/tutorials/introduction/windows_install/windows_install.rst
doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.rst
doc/tutorials/ml/introduction_to_svm/introduction_to_svm.rst
modules/contrib/src/inputoutput.cpp
modules/core/doc/basic_structures.rst
modules/core/doc/clustering.rst
modules/core/doc/drawing_functions.rst
modules/core/doc/operations_on_arrays.rst
modules/core/doc/utility_and_system_functions_and_macros.rst
modules/core/doc/xml_yaml_persistence.rst
modules/core/include/opencv2/core/mat.hpp
modules/core/include/opencv2/core/private.hpp
modules/highgui/CMakeLists.txt
modules/highgui/include/opencv2/highgui/highgui_c.h
modules/highgui/perf/perf_input.cpp
modules/highgui/perf/perf_output.cpp
modules/highgui/perf/perf_precomp.hpp
modules/highgui/src/cap.cpp
modules/highgui/src/cap_ffmpeg.cpp
modules/highgui/src/cap_v4l.cpp
modules/highgui/src/precomp.hpp
modules/highgui/src/window_QT.cpp
modules/highgui/test/test_precomp.hpp
modules/highgui/test/test_video_io.cpp
modules/imgproc/perf/perf_cvt_color.cpp
modules/imgproc/perf/perf_resize.cpp
modules/ocl/include/opencv2/ocl.hpp
modules/ocl/perf/main.cpp
modules/ocl/perf/perf_imgproc.cpp
modules/ocl/perf/precomp.cpp
modules/ocl/src/haar.cpp
modules/ocl/src/hog.cpp
modules/ocl/src/imgproc.cpp
modules/ocl/src/initialization.cpp
modules/ocl/src/mcwutil.cpp
modules/ocl/src/moments.cpp
modules/ocl/src/opencl/moments.cl
modules/ocl/src/opencl/objdetect_hog.cl
modules/ocl/test/main.cpp
modules/ocl/test/test_imgproc.cpp
modules/ocl/test/test_moments.cpp
modules/ocl/test/test_objdetect.cpp
modules/ts/include/opencv2/ts/ts_gtest.h
modules/ts/include/opencv2/ts/ts_perf.hpp
modules/ts/src/precomp.hpp
modules/ts/src/ts_func.cpp
modules/ts/src/ts_perf.cpp
samples/cpp/freak_demo.cpp
samples/cpp/latentsvm_multidetect.cpp
samples/cpp/stereo_calib.cpp
samples/ocl/clahe.cpp
samples/ocl/facedetect.cpp
samples/ocl/hog.cpp
samples/ocl/stereo_match.cpp

Simple merge
Simple merge
@@@ -1,3 -1,3 +1,3 @@@
  
  .. note::
-    Unfortunetly we have no tutorials into this section. Nevertheless, our tutorial writting team is working on it. If you have a tutorial suggestion or you have writen yourself a tutorial (or coded a sample code) that you would like to see here please contact us via our :opencv_group:`user group <>`.
 -   Unfortunetly we have no tutorials into this section. And you can help us with that, since OpenCV is a community effort. If you have a tutorial suggestion or you have written a tutorial yourself (or coded a sample code) that you would like to see here, please contact follow these instructions: :ref:`howToWriteTutorial` and :how_to_contribute:`How to contribute <>`.
++   Unfortunetly we have no tutorials into this section. And you can help us with that, since OpenCV is a community effort. If you have a tutorial suggestion or you have written a tutorial yourself (or coded a sample code) that you would like to see here, please contact follow these instructions: :ref:`howToWriteTutorial` and :how_to_contribute:`How to contribute <>`.
- ï»¿.. _gpuBasicsSimilarity:\r\rSimilarity check (PNSR and SSIM) on the GPU\r*******************************************\r\rGoal\r====\r\rIn the :ref:`videoInputPSNRMSSIM` tutorial I already presented the PSNR and SSIM methods for\rchecking the similarity between the two images. And as you could see there performing these takes\rquite some time, especially in the case of the SSIM. However, if the performance numbers of an\rOpenCV implementation for the CPU do not satisfy you and you happen to have an NVidia CUDA GPU\rdevice in your system all is not lost. You may try to port or write your algorithm for the video\rcard.\r\rThis tutorial will give a good grasp on how to approach coding by using the GPU module of OpenCV. As\ra prerequisite you should already know how to handle the core, highgui and imgproc modules. So, our\rgoals are:\r\r.. container:: enumeratevisibleitemswithsquare\r\r   + What's different compared to the CPU?\r   + Create the GPU code for the PSNR and SSIM\r   + Optimize the code for maximal performance\r\rThe source code\r===============\r\rYou may also find the source code and these video file in the\r:file:`samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity` folder of the\rOpenCV source library or :download:`download it from here\r<../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp>`. The\rfull source code is quite long (due to the controlling of the application via the command line\rarguments and performance measurement). Therefore, to avoid cluttering up these sections with those\ryou'll find here only the functions itself.\r\rThe PSNR returns a float number, that if the two inputs are similar between 30 and 50 (higher is\rbetter).\r\r.. literalinclude:: ../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp\r   :language: cpp\r   :linenos:\r   :tab-width: 4\r   :lines: 165-210, 18-23, 210-235\r\rThe SSIM returns the MSSIM of the images. This is too a float number between zero and one (higher is\rbetter), however we have one for each channel. Therefore, we return a *Scalar* OpenCV data\rstructure:\r\r.. literalinclude:: ../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp\r   :language: cpp\r   :linenos:\r   :tab-width: 4\r   :lines: 235-355, 26-42, 357-\r\rHow to do it? - The GPU\r=======================\r\rNow as you can see we have three types of functions for each operation. One for the CPU and two for\rthe GPU. The reason I made two for the GPU is too illustrate that often simple porting your CPU to\rGPU will actually make it slower. If you want some performance gain you will need to remember a few\rrules, whose I'm going to detail later on.\r\rThe development of the GPU module was made so that it resembles as much as possible its CPU\rcounterpart. This is to make porting easy. The first thing you need to do before writing any code is\rto link the GPU module to your project, and include the header file for the module. All the\rfunctions and data structures of the GPU are in a *gpu* sub namespace of the *cv* namespace. You may\radd this to the default one via the *use namespace* keyword, or mark it everywhere explicitly via\rthe cv:: to avoid confusion. I'll do the later.\r\r.. code-block:: cpp\r\r   #include <opencv2/gpu.hpp>        // GPU structures and methods\r\rGPU stands for **g**\ raphics **p**\ rocessing **u**\ nit. It was originally build to render\rgraphical scenes. These scenes somehow build on a lot of data. Nevertheless, these aren't all\rdependent one from another in a sequential way and as it is possible a parallel processing of them.\rDue to this a GPU will contain multiple smaller processing units. These aren't the state of the art\rprocessors and on a one on one test with a CPU it will fall behind. However, its strength lies in\rits numbers. In the last years there has been an increasing trend to harvest these massive parallel\rpowers of the GPU in non-graphical scene rendering too. This gave birth to the general-purpose\rcomputation on graphics processing units (GPGPU).\r\rThe GPU has its own memory. When you read data from the hard drive with OpenCV into a *Mat* object\rthat takes place in your systems memory. The CPU works somehow directly on this (via its cache),\rhowever the GPU cannot. He has too transferred the information he will use for calculations from the\rsystem memory to its own. This is done via an upload process and takes time. In the end the result\rwill have to be downloaded back to your system memory for your CPU to see it and use it. Porting\rsmall functions to GPU is not recommended as the upload/download time will be larger than the amount\ryou gain by a parallel execution.\r\rMat objects are stored only in the system memory (or the CPU cache). For getting an OpenCV matrix\rto the GPU you'll need to use its GPU counterpart :gpudatastructure:`GpuMat <gpu-gpumat>`. It works\rsimilar to the Mat with a 2D only limitation and no reference returning for its functions (cannot\rmix GPU references with CPU ones). To upload a Mat object to the GPU you need to call the upload\rfunction after creating an instance of the class. To download you may use simple assignment to a\rMat object or use the download function.\r\r.. code-block:: cpp\r\r   Mat I1;         // Main memory item - read image into with imread for example\r   gpu::GpuMat gI; // GPU matrix - for now empty\r   gI1.upload(I1); // Upload a data from the system memory to the GPU memory\r\r   I1 = gI1;       // Download, gI1.download(I1) will work too\r\rOnce you have your data up in the GPU memory you may call GPU enabled functions of OpenCV. Most of\rthe functions keep the same name just as on the CPU, with the difference that they only accept\r*GpuMat* inputs. A full list of these you will find in the documentation: `online here\r<http://opencv.itseez.com/modules/gpu/doc/gpu.html>`_ or the OpenCV reference manual that comes with\rthe source code.\r\rAnother thing to keep in mind is that not for all channel numbers you can make efficient algorithms\ron the GPU. Generally, I found that the input images for the GPU images need to be either one or\rfour channel ones and one of the char or float type for the item sizes. No double support on the\rGPU, sorry. Passing other types of objects for some functions will result in an exception thrown,\rand an error message on the error output. The documentation details in most of the places the types\raccepted for the inputs. If you have three channel images as an input you can do two things: either\radds a new channel (and use char elements) or split up the image and call the function for each\rimage. The first one isn't really recommended as you waste memory.\r\rFor some functions, where the position of the elements (neighbor items) doesn't matter quick\rsolution is to just reshape it into a single channel image. This is the case for the PSNR\rimplementation where for the *absdiff* method the value of the neighbors is not important. However,\rfor the *GaussianBlur* this isn't an option and such need to use the split method for the SSIM. With\rthis knowledge you can already make a GPU viable code (like mine GPU one) and run it. You'll be\rsurprised to see that it might turn out slower than your CPU implementation.\r\rOptimization\r============\r\rThe reason for this is that you're throwing out on the window the price for memory allocation and\rdata transfer. And on the GPU this is damn high. Another possibility for optimization is to\rintroduce asynchronous OpenCV GPU calls too with the help of the\r:gpudatastructure:`gpu::Stream<gpu-stream>`.\r\r1. Memory allocation on the GPU is considerable. Therefore, if it’s possible allocate new memory as\r   few times as possible. If you create a function what you intend to call multiple times it is a\r   good idea to allocate any local parameters for the function only once, during the first call.\r   To do this you create a data structure containing all the local variables you will use. For\r   instance in case of the PSNR these are:\r\r   .. code-block:: cpp\r\r      struct BufferPSNR                                     // Optimized GPU versions\r        {   // Data allocations are very expensive on GPU. Use a buffer to solve: allocate once reuse later.\r        gpu::GpuMat gI1, gI2, gs, t1,t2;\r\r        gpu::GpuMat buf;\r      };\r\r   Then create an instance of this in the main program:\r\r   .. code-block:: cpp\r\r      BufferPSNR bufferPSNR;\r\r   And finally pass this to the function each time you call it:\r\r   .. code-block:: cpp\r\r      double getPSNR_GPU_optimized(const Mat& I1, const Mat& I2, BufferPSNR& b)\r\r   Now you access these local parameters as: *b.gI1*, *b.buf* and so on. The GpuMat will only\r   reallocate itself on a new call if the new matrix size is different from the previous one.\r\r#. Avoid unnecessary function data transfers. Any small data transfer will be significant one once\r   you go to the GPU. Therefore, if possible make all calculations in-place (in other words do not\r   create new memory objects - for reasons explained at the previous point). For example, although\r   expressing arithmetical operations may be easier to express in one line formulas, it will be\r   slower. In case of the SSIM at one point I need to calculate:\r\r   .. code-block:: cpp\r\r      b.t1 = 2 * b.mu1_mu2 + C1;\r\r   Although the upper call will succeed observe that there is a hidden data transfer present. Before\r   it makes the addition it needs to store somewhere the multiplication. Therefore, it will create a\r   local matrix in the background, add to that the *C1* value and finally assign that to *t1*. To\r   avoid this we use the gpu functions, instead of the arithmetic operators:\r\r   .. code-block:: cpp\r\r      gpu::multiply(b.mu1_mu2, 2, b.t1); //b.t1 = 2 * b.mu1_mu2 + C1;\r      gpu::add(b.t1, C1, b.t1);\r\r#. Use asynchronous calls (the :gpudatastructure:`gpu::Stream <gpu-stream>`). By default whenever\r   you call a gpu function it will wait for the call to finish and return with the result\r   afterwards. However, it is possible to make asynchronous calls, meaning it will call for the\r   operation execution, make the costly data allocations for the algorithm and return back right\r   away. Now you can call another function if you wish to do so. For the MSSIM this is a small\r   optimization point. In our default implementation we split up the image into channels and call\r   then for each channel the gpu functions. A small degree of parallelization is possible with the\r   stream. By using a stream we can make the data allocation, upload operations while the GPU is\r   already executing a given method. For example we need to upload two images. We queue these one\r   after another and call already the function that processes it. The functions will wait for the\r   upload to finish, however while that happens makes the output buffer allocations for the function\r   to be executed next.\r\r   .. code-block:: cpp\r\r      gpu::Stream stream;\r\r      stream.enqueueConvert(b.gI1, b.t1, CV_32F);    // Upload\r\r      gpu::split(b.t1, b.vI1, stream);              // Methods (pass the stream as final parameter).\r      gpu::multiply(b.vI1[i], b.vI1[i], b.I1_2, stream);        // I1^2\r\rResult and conclusion\r=====================\r\rOn an Intel P8700 laptop CPU paired with a low end NVidia GT220M here are the performance numbers:\r\r.. code-block:: cpp\r\r   Time of PSNR CPU (averaged for 10 runs): 41.4122 milliseconds. With result of: 19.2506\r   Time of PSNR GPU (averaged for 10 runs): 158.977 milliseconds. With result of: 19.2506\r   Initial call GPU optimized:              31.3418 milliseconds. With result of: 19.2506\r   Time of PSNR GPU OPTIMIZED ( / 10 runs): 24.8171 milliseconds. With result of: 19.2506\r\r   Time of MSSIM CPU (averaged for 10 runs): 484.343 milliseconds. With result of B0.890964 G0.903845 R0.936934\r   Time of MSSIM GPU (averaged for 10 runs): 745.105 milliseconds. With result of B0.89922 G0.909051 R0.968223\r   Time of MSSIM GPU Initial Call            357.746 milliseconds. With result of B0.890964 G0.903845 R0.936934\r   Time of MSSIM GPU OPTIMIZED ( / 10 runs): 203.091 milliseconds. With result of B0.890964 G0.903845 R0.936934\r\rIn both cases we managed a performance increase of almost 100% compared to the CPU implementation.\rIt may be just the improvement needed for your application to work. You may observe a runtime\rinstance of this on the `YouTube here <https://www.youtube.com/watch?v=3_ESXmFlnvY>`_.\r\r.. raw:: html\r\r  <div align="center">\r  <iframe title="Similarity check (PNSR and SSIM) on the GPU" width="560" height="349" src="http://www.youtube.com/embed/3_ESXmFlnvY?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>\r  </div>
 -.. _gpuBasicsSimilarity:
++.. _gpuBasicsSimilarity:
+ Similarity check (PNSR and SSIM) on the GPU
+ *******************************************
+ Goal
+ ====
 -In the :ref:`videoInputPSNRMSSIM` tutorial I already presented the PSNR and SSIM methods for checking the similarity between the two images. And as you could see there performing these takes quite some time, especially in the case of the SSIM. However, if the performance numbers of an OpenCV implementation for the CPU do not satisfy you and you happen to have an NVidia CUDA GPU device in your system all is not lost. You may try to port or write your algorithm for the video card.
++In the :ref:`videoInputPSNRMSSIM` tutorial I already presented the PSNR and SSIM methods for
++checking the similarity between the two images. And as you could see there performing these takes
++quite some time, especially in the case of the SSIM. However, if the performance numbers of an
++OpenCV implementation for the CPU do not satisfy you and you happen to have an NVidia CUDA GPU
++device in your system all is not lost. You may try to port or write your algorithm for the video
++card.
 -This tutorial will give a good grasp on how to approach coding by using the GPU module of OpenCV. As a prerequisite you should already know how to handle the core, highgui and imgproc modules. So, our goals are:
++This tutorial will give a good grasp on how to approach coding by using the GPU module of OpenCV. As
++a prerequisite you should already know how to handle the core, highgui and imgproc modules. So, our
++goals are:
+ .. container:: enumeratevisibleitemswithsquare
+    + What's different compared to the CPU?
+    + Create the GPU code for the PSNR and SSIM
+    + Optimize the code for maximal performance
+ The source code
+ ===============
 -You may also find the source code and these video file in the :file:`samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity` folder of the OpenCV source library or :download:`download it from here <../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp>`. The full source code is quite long (due to the controlling of the application via the command line arguments and performance measurement). Therefore, to avoid cluttering up these sections with those you'll find here only the functions itself.
++You may also find the source code and these video file in the
++:file:`samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity` folder of the
++OpenCV source library or :download:`download it from here
++<../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp>`. The
++full source code is quite long (due to the controlling of the application via the command line
++arguments and performance measurement). Therefore, to avoid cluttering up these sections with those
++you'll find here only the functions itself.
 -The PSNR returns a float number, that if the two inputs are similar between 30 and 50 (higher is better).
++The PSNR returns a float number, that if the two inputs are similar between 30 and 50 (higher is
++better).
+ .. literalinclude:: ../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp
+    :language: cpp
+    :linenos:
+    :tab-width: 4
+    :lines: 165-210, 18-23, 210-235
 -The SSIM returns the MSSIM of the images. This is too a float number between zero and one (higher is better), however we have one for each channel. Therefore, we return a *Scalar* OpenCV data structure:
++The SSIM returns the MSSIM of the images. This is too a float number between zero and one (higher is
++better), however we have one for each channel. Therefore, we return a *Scalar* OpenCV data
++structure:
+ .. literalinclude:: ../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp
+    :language: cpp
+    :linenos:
+    :tab-width: 4
+    :lines: 235-355, 26-42, 357-
+ How to do it? - The GPU
+ =======================
 -Now as you can see we have three types of functions for each operation. One for the CPU and two for the GPU. The reason I made two for the GPU is too illustrate that often simple porting your CPU to GPU will actually make it slower. If you want some performance gain you will need to remember a few rules, whose I'm going to detail later on.
++Now as you can see we have three types of functions for each operation. One for the CPU and two for
++the GPU. The reason I made two for the GPU is too illustrate that often simple porting your CPU to
++GPU will actually make it slower. If you want some performance gain you will need to remember a few
++rules, whose I'm going to detail later on.
 -The development of the GPU module was made so that it resembles as much as possible its CPU counterpart. This is to make porting easy. The first thing you need to do before writing any code is to link the GPU module to your project, and include the header file for the module. All the functions and data structures of the GPU are in a *gpu* sub namespace of the *cv* namespace. You may add this to the default one via the *use namespace* keyword, or mark it everywhere explicitly via the cv:: to avoid confusion. I'll do the later.
++The development of the GPU module was made so that it resembles as much as possible its CPU
++counterpart. This is to make porting easy. The first thing you need to do before writing any code is
++to link the GPU module to your project, and include the header file for the module. All the
++functions and data structures of the GPU are in a *gpu* sub namespace of the *cv* namespace. You may
++add this to the default one via the *use namespace* keyword, or mark it everywhere explicitly via
++the cv:: to avoid confusion. I'll do the later.
+ .. code-block:: cpp
 -   #include <opencv2/gpu/gpu.hpp>        // GPU structures and methods
 -
 -GPU stands for **g**\ raphics **p**\ rocessing **u**\ nit. It was originally build to render graphical scenes. These scenes somehow build on a lot of data. Nevertheless, these aren't all dependent one from another in a sequential way and as it is possible a parallel processing of them. Due to this a GPU will contain multiple smaller processing units. These aren't the state of the art processors and on a one on one test with a CPU it will fall behind. However, its strength lies in its numbers. In the last years there has been an increasing trend to harvest these massive parallel powers of the GPU in non-graphical scene rendering too. This gave birth to the general-purpose computation on graphics processing units (GPGPU).
 -
 -The GPU has its own memory. When you read data from the hard drive with OpenCV into a *Mat* object that takes place in your systems memory. The CPU works somehow directly on this (via its cache), however the GPU cannot. He has too transferred the information he will use for calculations from the system memory to its own. This is done via an upload process and takes time. In the end the result will have to be downloaded back to your system memory for your CPU to see it and use it. Porting small functions to GPU is not recommended as the upload/download time will be larger than the amount you gain by a parallel execution.
 -
 -*Mat* objects are stored **only** in the system memory (or the CPU cache). For getting an OpenCV matrix to the GPU you'll need to use its GPU counterpart :gpudatastructure:`GpuMat <gpu-gpumat>`. It works similar to the *Mat* with a 2D only limitation and no reference returning for its functions (cannot mix GPU references with CPU ones). To upload a *Mat* object to the *GPU* you need to call the *upload* function after creating an instance of the class. To download you may use simple assignment to a *Mat* object or use the *download* function.
++   #include <opencv2/gpu.hpp>        // GPU structures and methods
++
++GPU stands for **g**\ raphics **p**\ rocessing **u**\ nit. It was originally build to render
++graphical scenes. These scenes somehow build on a lot of data. Nevertheless, these aren't all
++dependent one from another in a sequential way and as it is possible a parallel processing of them.
++Due to this a GPU will contain multiple smaller processing units. These aren't the state of the art
++processors and on a one on one test with a CPU it will fall behind. However, its strength lies in
++its numbers. In the last years there has been an increasing trend to harvest these massive parallel
++powers of the GPU in non-graphical scene rendering too. This gave birth to the general-purpose
++computation on graphics processing units (GPGPU).
++
++The GPU has its own memory. When you read data from the hard drive with OpenCV into a *Mat* object
++that takes place in your systems memory. The CPU works somehow directly on this (via its cache),
++however the GPU cannot. He has too transferred the information he will use for calculations from the
++system memory to its own. This is done via an upload process and takes time. In the end the result
++will have to be downloaded back to your system memory for your CPU to see it and use it. Porting
++small functions to GPU is not recommended as the upload/download time will be larger than the amount
++you gain by a parallel execution.
++
++Mat objects are stored only in the system memory (or the CPU cache). For getting an OpenCV matrix
++to the GPU you'll need to use its GPU counterpart :gpudatastructure:`GpuMat <gpu-gpumat>`. It works
++similar to the Mat with a 2D only limitation and no reference returning for its functions (cannot
++mix GPU references with CPU ones). To upload a Mat object to the GPU you need to call the upload
++function after creating an instance of the class. To download you may use simple assignment to a
++Mat object or use the download function.
+ .. code-block:: cpp
+    Mat I1;         // Main memory item - read image into with imread for example
+    gpu::GpuMat gI; // GPU matrix - for now empty
+    gI1.upload(I1); // Upload a data from the system memory to the GPU memory
+    I1 = gI1;       // Download, gI1.download(I1) will work too
 -Once you have your data up in the GPU memory you may call GPU enabled functions of OpenCV. Most of the functions keep the same name just as on the CPU, with the difference that they only accept *GpuMat* inputs. A full list of these you will find in the documentation: `online here <http://docs.opencv.org/modules/gpu/doc/gpu.html>`_ or the OpenCV reference manual that comes with the source code.
 -
 -Another thing to keep in mind is that not for all channel numbers you can make efficient algorithms on the GPU. Generally, I found that the input images for the GPU images need to be either one or four channel ones and one of the char or float type for the item sizes. No double support on the GPU, sorry. Passing other types of objects for some functions will result in an exception thrown, and an error message on the error output. The documentation details in most of the places the types accepted for the inputs. If you have three channel images as an input you can do two things: either adds a new channel (and use char elements) or split up the image and call the function for each image. The first one isn't really recommended as you waste memory.
 -
 -For some functions, where the position of the elements (neighbor items) doesn't matter quick solution is to just reshape it into a single channel image. This is the case for the PSNR implementation where for the *absdiff* method the value of the neighbors is not important. However, for the *GaussianBlur* this isn't an option and such need to use the split method for the SSIM. With this knowledge you can already make a GPU viable code (like mine GPU one) and run it. You'll be surprised to see that it might turn out slower than your CPU implementation.
++Once you have your data up in the GPU memory you may call GPU enabled functions of OpenCV. Most of
++the functions keep the same name just as on the CPU, with the difference that they only accept
++*GpuMat* inputs. A full list of these you will find in the documentation: `online here
++<http://docs.opencv.org/modules/gpu/doc/gpu.html>`_ or the OpenCV reference manual that comes with
++the source code.
++
++Another thing to keep in mind is that not for all channel numbers you can make efficient algorithms
++on the GPU. Generally, I found that the input images for the GPU images need to be either one or
++four channel ones and one of the char or float type for the item sizes. No double support on the
++GPU, sorry. Passing other types of objects for some functions will result in an exception thrown,
++and an error message on the error output. The documentation details in most of the places the types
++accepted for the inputs. If you have three channel images as an input you can do two things: either
++adds a new channel (and use char elements) or split up the image and call the function for each
++image. The first one isn't really recommended as you waste memory.
++
++For some functions, where the position of the elements (neighbor items) doesn't matter quick
++solution is to just reshape it into a single channel image. This is the case for the PSNR
++implementation where for the *absdiff* method the value of the neighbors is not important. However,
++for the *GaussianBlur* this isn't an option and such need to use the split method for the SSIM. With
++this knowledge you can already make a GPU viable code (like mine GPU one) and run it. You'll be
++surprised to see that it might turn out slower than your CPU implementation.
+ Optimization
+ ============
 -The reason for this is that you're throwing out on the window the price for memory allocation and data transfer. And on the GPU this is damn high. Another possibility for optimization is to introduce asynchronous OpenCV GPU calls too with the help of the :gpudatastructure:`gpu::Stream <gpu-stream>`.
++The reason for this is that you're throwing out on the window the price for memory allocation and
++data transfer. And on the GPU this is damn high. Another possibility for optimization is to
++introduce asynchronous OpenCV GPU calls too with the help of the
++:gpudatastructure:`gpu::Stream<gpu-stream>`.
 -1. Memory allocation on the GPU is considerable. Therefore, if it’s possible allocate new memory as few times as possible. If you create a function what you intend to call multiple times it is a good idea to allocate any local parameters for the function only once, during the first call. To do this you create a data structure containing all the local variables you will use. For instance in case of the PSNR these are:
++1. Memory allocation on the GPU is considerable. Therefore, if it’s possible allocate new memory as
++   few times as possible. If you create a function what you intend to call multiple times it is a
++   good idea to allocate any local parameters for the function only once, during the first call.
++   To do this you create a data structure containing all the local variables you will use. For
++   instance in case of the PSNR these are:
+    .. code-block:: cpp
+       struct BufferPSNR                                     // Optimized GPU versions
+         {   // Data allocations are very expensive on GPU. Use a buffer to solve: allocate once reuse later.
+         gpu::GpuMat gI1, gI2, gs, t1,t2;
+         gpu::GpuMat buf;
+       };
+    Then create an instance of this in the main program:
+    .. code-block:: cpp
+       BufferPSNR bufferPSNR;
+    And finally pass this to the function each time you call it:
+    .. code-block:: cpp
+       double getPSNR_GPU_optimized(const Mat& I1, const Mat& I2, BufferPSNR& b)
 -   Now you access these local parameters as: *b.gI1*, *b.buf* and so on. The GpuMat will only reallocate itself on a new call if the new matrix size is different from the previous one.
++   Now you access these local parameters as: *b.gI1*, *b.buf* and so on. The GpuMat will only
++   reallocate itself on a new call if the new matrix size is different from the previous one.
 -#. Avoid unnecessary function data transfers. Any small data transfer will be significant one once you go to the GPU. Therefore, if possible make all calculations in-place (in other words do not create new memory objects - for reasons explained at the previous point). For example, although expressing arithmetical operations may be easier to express in one line formulas, it will be slower. In case of the SSIM at one point I need to calculate:
++#. Avoid unnecessary function data transfers. Any small data transfer will be significant one once
++   you go to the GPU. Therefore, if possible make all calculations in-place (in other words do not
++   create new memory objects - for reasons explained at the previous point). For example, although
++   expressing arithmetical operations may be easier to express in one line formulas, it will be
++   slower. In case of the SSIM at one point I need to calculate:
+    .. code-block:: cpp
+       b.t1 = 2 * b.mu1_mu2 + C1;
 -   Although the upper call will succeed observe that there is a hidden data transfer present. Before it makes the addition it needs to store somewhere the multiplication. Therefore, it will create a local matrix in the background, add to that the *C1* value and finally assign that to *t1*. To avoid this we use the gpu functions, instead of the arithmetic operators:
++   Although the upper call will succeed observe that there is a hidden data transfer present. Before
++   it makes the addition it needs to store somewhere the multiplication. Therefore, it will create a
++   local matrix in the background, add to that the *C1* value and finally assign that to *t1*. To
++   avoid this we use the gpu functions, instead of the arithmetic operators:
+    .. code-block:: cpp
+       gpu::multiply(b.mu1_mu2, 2, b.t1); //b.t1 = 2 * b.mu1_mu2 + C1;
+       gpu::add(b.t1, C1, b.t1);
 -#. Use asynchronous calls (the :gpudatastructure:`gpu::Stream <gpu-stream>`). By default whenever you call a gpu function it will wait for the call to finish and return with the result afterwards. However, it is possible to make asynchronous calls, meaning it will call for the operation execution, make the costly data allocations for the algorithm and return back right away. Now you can call another function if you wish to do so. For the MSSIM this is a small optimization point. In our default implementation we split up the image into channels and call then for each channel the gpu functions. A small degree of parallelization is possible with the stream. By using a stream we can make the data allocation, upload operations while the GPU is already executing a given method. For example we need to upload two images. We queue these one after another and call already the function that processes it. The functions will wait for the upload to finish, however while that happens makes the output buffer allocations for the function to be executed next.
++#. Use asynchronous calls (the :gpudatastructure:`gpu::Stream <gpu-stream>`). By default whenever
++   you call a gpu function it will wait for the call to finish and return with the result
++   afterwards. However, it is possible to make asynchronous calls, meaning it will call for the
++   operation execution, make the costly data allocations for the algorithm and return back right
++   away. Now you can call another function if you wish to do so. For the MSSIM this is a small
++   optimization point. In our default implementation we split up the image into channels and call
++   then for each channel the gpu functions. A small degree of parallelization is possible with the
++   stream. By using a stream we can make the data allocation, upload operations while the GPU is
++   already executing a given method. For example we need to upload two images. We queue these one
++   after another and call already the function that processes it. The functions will wait for the
++   upload to finish, however while that happens makes the output buffer allocations for the function
++   to be executed next.
+    .. code-block:: cpp
+       gpu::Stream stream;
+       stream.enqueueConvert(b.gI1, b.t1, CV_32F);    // Upload
+       gpu::split(b.t1, b.vI1, stream);              // Methods (pass the stream as final parameter).
+       gpu::multiply(b.vI1[i], b.vI1[i], b.I1_2, stream);        // I1^2
+ Result and conclusion
+ =====================
+ On an Intel P8700 laptop CPU paired with a low end NVidia GT220M here are the performance numbers:
+ .. code-block:: cpp
+    Time of PSNR CPU (averaged for 10 runs): 41.4122 milliseconds. With result of: 19.2506
+    Time of PSNR GPU (averaged for 10 runs): 158.977 milliseconds. With result of: 19.2506
+    Initial call GPU optimized:              31.3418 milliseconds. With result of: 19.2506
+    Time of PSNR GPU OPTIMIZED ( / 10 runs): 24.8171 milliseconds. With result of: 19.2506
+    Time of MSSIM CPU (averaged for 10 runs): 484.343 milliseconds. With result of B0.890964 G0.903845 R0.936934
+    Time of MSSIM GPU (averaged for 10 runs): 745.105 milliseconds. With result of B0.89922 G0.909051 R0.968223
+    Time of MSSIM GPU Initial Call            357.746 milliseconds. With result of B0.890964 G0.903845 R0.936934
+    Time of MSSIM GPU OPTIMIZED ( / 10 runs): 203.091 milliseconds. With result of B0.890964 G0.903845 R0.936934
 -In both cases we managed a performance increase of almost 100% compared to the CPU implementation. It may be just the improvement needed for your application to work. You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=3_ESXmFlnvY>`_.
++In both cases we managed a performance increase of almost 100% compared to the CPU implementation.
++It may be just the improvement needed for your application to work. You may observe a runtime
++instance of this on the `YouTube here <https://www.youtube.com/watch?v=3_ESXmFlnvY>`_.
+ .. raw:: html
+   <div align="center">
+   <iframe title="Similarity check (PNSR and SSIM) on the GPU" width="560" height="349" src="http://www.youtube.com/embed/3_ESXmFlnvY?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
+   </div>
@@@ -48,21 -48,21 +48,21 @@@ Jav
  Application Development with Async Initialization
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
 -Using async initialization is a **recommended** way for application development. It uses the OpenCV 
 +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 
 +#. 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 
 +   Press :guilabel:`Browse`  button and locate OpenCV4Android SDK
-    (:file:`OpenCV-2.4.5-android-sdk/sdk`).
+    (:file:`OpenCV-2.4.6-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 
 +#. In application project add a reference to the OpenCV Java SDK in
-    :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.5``.
+    :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.6``.
  
     .. image:: images/eclipse_opencv_dependency1.png
          :alt: Add dependency from OpenCV library
@@@ -120,35 -120,35 +120,35 @@@ finalization method
  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 
 +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
+ #. 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`, 
 +   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`).
+    press :guilabel:`Browse` button and select OpenCV SDK path 
+    (:file:`OpenCV-2.4.6-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 
 +#. In the application project add a reference to the OpenCV4Android SDK in
-    :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.5``;
+    :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.6``;
  
     .. 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 
 +#. 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
+    native libs from :file:`<OpenCV-2.4.6-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 
 +   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 
 +   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"``
+    ``"include path_to_OpenCV-2.4.6-android-sdk/sdk/native/jni/OpenCV.mk"``
  
     .. code-block:: make
        :linenos:
- .. _howToWriteTutorial:\r\rHow to write a tutorial for OpenCV?\r***********************************\r\rOkay, so assume you have just finished a project of yours implementing something based on OpenCV and you want to present/share it with the community. Luckily, OpenCV is an *open source project*. This means that in theory anyone has access to the full source code and may extend it. While making a robust and practical library (like OpenCV) is great, the success of a library also depends on how user friendly it is. To improve on this aspect, the OpenCV team has already been listening to user feedback from its :opencv_group:`Yahoo user group <>` and by making samples you can find in the source directories sample folder. The addition of the tutorials (in both online and PDF format) is an extension of these efforts.\r\rGoal\r====\r\r.. _reST: http://docutils.sourceforge.net/rst.html\r.. |reST| replace:: reStructuredText\r.. |Sphinx| replace:: Sphinx\r.. _Sphinx: http://sphinx.pocoo.org/\r\rThe tutorials are just as an important part of the library as  the implementation of those crafty data structures and algorithms you can find in OpenCV. Therefore, the source codes for the tutorials are part of the library. And yes, I meant source codes. The reason for this formulation is that the tutorials are written by using the |Sphinx|_ documentation generation system. This is based on the popular python documentation system called |reST|_ (reST). ReStructuredText is a really neat language that by using a few simple conventions (indentation, directives) and emulating old school e-mail writing techniques (text only) tries to offer a simple way to create and edit documents. Sphinx extends this with some new features and creates the resulting document in both HTML (for web) and PDF (for offline usage) format.\r\rUsually, an OpenCV tutorial has the following parts:\r\r1. A source code demonstration of an OpenCV feature:\r\r   a. One or more CPP, Python, Java or other type of files depending for what OpenCV offers support and for what language you make the tutorial.\r   #. Occasionaly, input resource files required for running your tutorials application.\r\r\r#. A table of content entry (so people may easily find the tutorial):\r\r   a. Adding your stuff to the tutorials table of content (**reST** file).\r   #. Add an image file near the TOC entry.\r\r\r#. The content of the tutorial itself:\r\r   a. The **reST** text of the tutorial\r   #. Images following the idea that "*A picture is worth a thousand words*".\r   #. For more complex demonstrations you may create a video.\r\rAs you can see you will need at least some basic knowledge of the *reST* system in order to complete the task at hand with success. However, don't worry *reST* (and *Sphinx*) was made with simplicity in mind. It is easy to grasp its basics. I found that the `OpenAlea documentations introduction on this subject <http://openalea.gforge.inria.fr/doc/openalea/doc/_build/html/source/tutorial/rest_syntax.html>`_ (or the `Thomas Cokelaer one <http://thomas-cokelaer.info/tutorials/sphinx/rest_syntax.html>`_ ) should enough for this. If for some directive or feature you need a more in-depth description look it up in the official |reST|_ help files or at the |Sphinx|_ documentation.\r\rIn our world achieving some tasks is possible in multiple ways. However, some of the roads to take may have obvious or hidden advantages over others. Then again, in some other cases it may come down to just simple user preference. Here, I'll present how I decided to write the tutorials, based on my personal experience. If for some of them you know a better solution and you can back it up feel free to use that. I've nothing against it, as long as it gets the job done in an elegant fashion.\r\rNow the best would be if you could make the integration yourself. For this you need first to have the source code. I recommend following the guides for your operating system on acquiring OpenCV sources. For Linux users look :ref:`here <Linux-Installation>` and for :ref:`Windows here <Windows_Installation>`. You must also install python and sphinx with its dependencies in order to be able to build the documentation.\r\rOnce you have downloaded the repository to your hard drive you can take a look in the OpenCV directory to make sure you have both the samples and doc folder present. Anyone may download the trunk source files from  :file:`git://code.opencv.org/opencv.git` . Nevertheless, not everyone has upload (commit/submit) rights. This is to protect the integrity of the library. If you plan doing more than one tutorial, and would like to have an account with commit user rights you should first register an account at http://code.opencv.org/ and then contact dr. Gary Bradski at -delete-bradski@-delete-willowgarage.com. Otherwise, you can just send the resulting files to us via the :opencv_group:`Yahoo user group <>` or to me at -delete-bernat@-delete-primeranks.net and I'll add it. If you have questions, suggestions or constructive critics I will gladly listen to them. If you send it to the OpenCV group please tag its subject with a **[Tutorial]** entry.\r\rFormat the Source Code\r======================\r\rBefore I start this let it be clear: the main goal is to have a working sample code. However, for your tutorial to be of a top notch quality you should follow a few guide lines I am going to present here.\r\rIn case you have an application by using the older interface (with *IplImage*, *CVMat*, *cvLoadImage* and such) consider migrating it to the new C++ interface. The tutorials are intended to be an up to date help for our users. And as of OpenCV 2 the OpenCV emphasis on using the less error prone and clearer C++ interface. Therefore, if possible please convert your code to the C++ interface. For this it may help to read the :ref:`InteroperabilityWithOpenCV1` tutorial. However, once you have an OpenCV 2 working code, then you should make your source code snippet as easy to read as possible. Here're a couple of advices for this:\r\r.. container:: enumeratevisibleitemswithsquare\r\r   + Add a standard output with the description of what your program does. Keep it short and yet, descriptive. This output is at the start of the program. In my example files this usually takes the form of a *help* function containing the output. This way both the source file viewer and application runner can see what all is about in your sample. Here's an instance of this:\r\r     .. code-block:: cpp\r\r        void help()\r        {\r        cout\r        << "--------------------------------------------------------------------------"   << endl\r        << "This program shows how to write video files. You can extract the R or G or B color channel "\r        << " of the input video. You can choose to use the source codec (Y) or select a custom one. (N)"<< endl\r        << "Usage:"                                                                       << endl\r        << "./video-write inputvideoName [ R | G | B] [Y | N]"                            << endl\r        << "--------------------------------------------------------------------------"   << endl\r        << endl;\r        }\r        // ...\r        int main(int argc, char *argv[], char *window_name)\r        {\r        help();\r        // here comes the actual source code\r        }\r\r     Additionally, finalize the description with a short usage guide. This way the user will know how to call your programs, what leads us to the next point.\r\r   + Prefer command line argument controlling instead of hard coded one. If your program has some variables that may be changed use command line arguments for this. The tutorials, can be a simple try-out ground for the user. If you offer command line controlling for the input image (for example), then you offer the possibility for the user to try it out with his/her own images, without the need to mess in the source code. In the upper example you can see that the input image, channel and codec selection may all be changed from the command line. Just compile the program and run it with your own input arguments.\r\r   + Be as verbose as possible. There is no shame in filling the source code with comments. This way the more advanced user may figure out what's happening right from the sample code. This advice goes for the output console too. Specify to the user what's happening. Never leave the user hanging there and thinking on: "Is this program now crashing or just doing some computationally intensive task?." So, if you do a training task that may take some time, make sure you print out a message about this before starting and after finishing it.\r\r   + Throw out unnecessary stuff from your source code. This is a warning to not take the previous point too seriously. Balance is the key. If it's something that can be done in a fewer lines or simpler than that's the way you should do it. Nevertheless, if for some reason you have such sections notify the user why you have chosen to do so. Keep the amount of information as low as possible, while still getting the job done in an elegant way.\r\r   + Put your sample file into the :file:`opencv/samples/cpp/tutorial_code/sectionName` folder. If you write a tutorial for other languages than cpp, then change that part of the path. Before completing this you need to decide that to what section (module) does your tutorial goes. Think about on what module relies most heavily your code and that is the one to use. If the answer to this question is more than one modules then the *general* section is the one to use. For finding the *opencv* directory open up your file system and navigate where you downloaded our repository.\r\r   + If the input resources are hard to acquire for the end user consider adding a few of them to the :file:`opencv/samples/cpp/tutorial_code/images`. Make sure that who reads your code can try it out!\r\rAdd the TOC entry\r=================\r\rFor this you will need to know some |reST|_. There is no going around this. |reST|_ files have **rst** extensions. However, these are simple text files. Use any text editor you like. Finding a text editor that offers syntax highlighting for |reST|_ was quite a challenge at the time of writing this tutorial. In my experience, `Intype <http://intype.info/>`_ is a solid option on Windows, although there is still place for improvement.\r\rAdding your source code to a table of content is important for multiple reasons. First and foremost this will allow for the user base to find your tutorial from our websites tutorial table of content. Secondly, if you omit this *Sphinx* will throw a warning that your tutorial file isn't part of any TOC tree entry. And there is nothing more than the developer team hates than an ever increasing warning/error list for their builds. *Sphinx* also uses this to build up the previous-back-up buttons on the website. Finally, omitting this step will lead to that your tutorial will **not** be added to the PDF version of the tutorials.\r\rNavigate to the :file:`opencv/doc/tutorials/section/table_of_content_section` folder (where the section is the module to which you're adding the tutorial). Open the *table_of_content_section* file. Now this may have two forms. If no prior tutorials are present in this section that there is a template message about this and has the following form:\r\r.. code-block:: rst\r\r  .. _Table-Of-Content-Section:\r\r   Section title\r   -----------------------------------------------------------\r\r   Description about the section.\r\r   .. include:: ../../definitions/noContent.rst\r\r   .. raw:: latex\r\r      \pagebreak\r\rThe first line is a reference to the section title in the reST system. The section title will be a link and you may refer to it via the ``:ref:`` directive. The *include* directive imports the template text from the definitions directories *noContent.rst* file. *Sphinx* does not creates the PDF from scratch. It does this by first creating a latex file. Then creates the PDF from the latex file. With the *raw* directive you can directly add to this output commands. Its unique argument is for what kind of output to add the content of the directive. For the PDFs it may happen that multiple sections will overlap on a single page. To avoid this at the end of the TOC we add a *pagebreak* latex command, that hints to the LATEX system that the next line should be on a new page.\r\rIf you have one of this, try to transform it to the following form:\r\r.. include:: ../../definitions/tocDefinitions.rst\r\r.. code-block:: rst\r\r   .. _Table-Of-Content-Section:\r\r   Section title\r   -----------------------------------------------------------\r\r   .. include:: ../../definitions/tocDefinitions.rst\r\r   +\r     .. tabularcolumns:: m{100pt} m{300pt}\r     .. cssclass:: toctableopencv\r\r     =============== ======================================================\r      |MatBasicIma|  **Title:** :ref:`matTheBasicImageContainer`\r\r                     *Compatibility:* > OpenCV 2.0\r\r                     *Author:* |Author_BernatG|\r\r                     You will learn how to store images in the memory and how to print out their content to the console.\r\r     =============== =====================================================\r\r     .. |MatBasicIma| image:: images/matTheBasicImageStructure.jpg\r                      :height: 90pt\r                      :width:  90pt\r\r   .. raw:: latex\r\r      \pagebreak\r\r   .. toctree::\r      :hidden:\r\r      ../mat - the basic image container/mat - the basic image container\r\rIf this is already present just add a new section of the content between the include and the raw directives (excluding those lines). Here you'll see a new include directive. This should be present only once in a TOC tree and the reST file contains the definitions of all the authors contributing to the OpenCV tutorials. We are a multicultural community and some of our name may contain some funky characters. However, reST **only supports** ANSI characters. Luckily we can specify Unicode characters with the *unicode* directive. Doing this for all of your tutorials is a troublesome procedure. Therefore, the tocDefinitions file contains the definition of your author name. Add it here once and afterwards just use the replace construction. For example here's the definition for my name:\r\r.. code-block:: rst\r\r   .. |Author_BernatG| unicode:: Bern U+00E1 t U+0020 G U+00E1 bor\r\rThe ``|Author_BernatG|`` is the text definitions alias. I can use later this to add the definition, like I've done in the TOCs *Author* part. After the ``::`` and a space you start the definition. If you want to add an UNICODE character (non-ASCI) leave an empty space and specify it in the format U+(UNICODE code). To find the UNICODE code of a character I recommend using the `FileFormat <http://www.fileformat.info>`_ websites service. Spaces are trimmed from the definition, therefore we add a space by its UNICODE character (U+0020).\r\rUntil the *raw* directive what you can see is a TOC tree entry. Here's how a TOC entry will look like:\r\r+\r  .. tabularcolumns:: m{100pt} m{300pt}\r  .. cssclass:: toctableopencv\r\r  =============== ======================================================\r   |MatBasicIma|  **Title:** :ref:`matTheBasicImageContainer`\r\r                  *Compatibility:* > OpenCV 2.0\r\r                  *Author:* |Author_BernatG|\r\r                  You will learn how to store images in the memory and how to print out their content to the console.\r\r  =============== ======================================================\r\r  .. |MatBasicIma| image:: images/matTheBasicImageStructure.jpg\r                   :height: 90pt\r                   :width:  90pt\r\rAs you can see we have an image to the left and a description box to the right. To create two boxes we use a table with two columns and a single row. In the left column is the image and in the right one the description. However, the image directive is way too long to fit in a column. Therefore, we need to use the substitution definition system. We add this definition after the TOC tree. All images for the TOC tree are to be put in the images folder near its |reST|_ file. We use the point measurement system because we are also creating PDFs. PDFs are printable documents, where there is no such thing that pixels (px), just points (pt). And while generally space is no problem for web pages (we have monitors with **huge** resolutions) the size of the paper (A4 or letter) is constant and will be for a long time in the future. Therefore, size constrains come in play more like for the PDF, than the generated HTML code.\r\rNow your images should be as small as possible, while still offering the intended information for the user. Remember that the tutorial will become part of the OpenCV source code. If you add large images (that manifest in form of large image size) it will just increase the size of the repository pointlessly. If someone wants to download it later, its download time will be that much longer. Not to mention the larger PDF size for the tutorials and the longer load time for the web pages. In terms of pixels a TOC image should not be larger than 120 X 120 pixels. Resize your images if they are larger!\r\r.. note::\r\r   If you add a larger image and specify a smaller image size, *Sphinx* will not resize that. At build time will add the full size image and the resize will be done by your browser after the image is loaded. A 120 X 120 image is somewhere below 10KB. If you add a 110KB image, you have just pointlessly added a 100KB extra data to transfer over the internet for every user!\r\rGenerally speaking you shouldn't need to specify your images size (excluding the TOC entries). If no such is found *Sphinx* will use the size of the image itself (so no resize occurs). Then again if for some reason you decide to specify a size that should be the **width** of the image rather than its height. The reason for this again goes back to the PDFs. On a PDF page the height is larger than the width. In the PDF the images will not be resized. If you specify a size that does not fit in the page, then what does not fits in **will be cut off**. When creating your images for your tutorial you should try to keep the image widths below 500 pixels, and calculate with around 400 point page width when specifying image widths.\r\rThe image format depends on the content of the image. If you have some complex scene (many random like colors) then use *jpg*. Otherwise, prefer using *png*. They are even some tools out there that optimize the size of *PNG* images, such as `PNGGauntlet <http://pnggauntlet.com/>`_. Use them to make your images as small as possible in size.\r\rNow on the right side column of the table we add the information about the tutorial:\r\r.. container:: enumeratevisibleitemswithsquare\r\r   + In the first line it is the title of the tutorial. However, there is no need to specify it explicitly. We use the reference system. We'll start up our tutorial with a reference specification, just like in case of this TOC entry with its  `` .. _Table-Of-Content-Section:`` . If after this you have a title (pointed out by the following line of -), then Sphinx will replace the ``:ref:`Table-Of-Content-Section``` directive with the tile of the section in reference form (creates a link in web page). Here's how the definition looks in my case:\r\r     .. code-block:: rst\r\r        .. _matTheBasicImageContainer:\r\r           Mat - The Basic Image Container\r           *******************************\r\r     Note, that according to the |reST|_ rules the * should be as long as your title.\r\r   + Compatibility. What version of OpenCV is required to run your sample code.\r\r   + Author. Use the substitution markup of |reST|_.\r\r   + A short sentence describing the essence of your tutorial.\r\rNow before each TOC entry you need to add the three lines of:\r\r.. code-block:: cpp\r\r   +\r     .. tabularcolumns:: m{100pt} m{300pt}\r     .. cssclass:: toctableopencv\r\rThe plus sign (+) is to enumerate tutorials by using bullet points. So for every TOC entry we have a corresponding bullet point represented by the +. Sphinx is highly indenting sensitive. Indentation is used to express from which point until to which point does a construction last. Un-indentation means end of that construction. So to keep all the bullet points to the same group the following TOC entries (until the next +) should be indented by two spaces.\r\rHere, I should also mention that **always** prefer using spaces instead of tabs. Working with only spaces makes possible that if we both use monotype fonts we will see the same thing. Tab size is text editor dependent and as should be avoided. *Sphinx* translates all tabs into 8 spaces before interpreting it.\r\rIt turns out that the automatic formatting of both the HTML and PDF(LATEX) system messes up our tables. Therefore, we need to help them out a little. For the PDF generation we add the ``.. tabularcolumns:: m{100pt} m{300pt}`` directive. This means that the first column should be 100 points wide and middle aligned. For the HTML look we simply name the following table of a *toctableopencv* class type. Then, we can modify the look of the table by modifying the CSS of our web page. The CSS definitions go into the :file:`opencv/doc/_themes/blue/static/default.css_t` file.\r\r.. code-block:: css\r\r   .toctableopencv\r   {\r    width: 100% ;\r    table-layout: fixed;\r   }\r\r\r   .toctableopencv colgroup col:first-child\r   {\r    width: 100pt !important;\r    max-width: 100pt !important;\r    min-width: 100pt !important;\r   }\r\r   .toctableopencv colgroup col:nth-child(2)\r   {\r    width: 100% !important;\r   }\r\rHowever, you should not need to modify this. Just add these three lines (plus keep the two space indentation) for all TOC entries you add. At the end of the TOC file you'll find:\r\r.. code-block:: rst\r\r   .. raw:: latex\r\r      \pagebreak\r\r   .. toctree::\r      :hidden:\r\r      ../mat - the basic image container/mat - the basic image container\r\rThe page break entry comes for separating sections and should be only one in a TOC tree |reST|_ file. Finally, at the end of the TOC tree we need to add our tutorial to the *Sphinx* TOC tree system. *Sphinx* will generate from this the previous-next-up information for the HTML file and add items to the PDF according to the order here. By default this TOC tree directive generates a simple table of contents. However, we already created a fancy looking one so we no longer need this basic one. Therefore, we add the *hidden* option to do not show it.\r\rThe path is of a relative type. We step back in the file system and then go into the :file:`mat - the basic image container` directory for the :file:`mat - the basic image container.rst` file. Putting out the *rst* extension for the file is optional.\r\rWrite the tutorial\r==================\r\rCreate a folder with the name of your tutorial. Preferably, use small letters only. Then create a text file in this folder with *rst* extension and the same name. If you have images for the tutorial create an :file:`images` folder and add your images there. When creating your images follow the guidelines described in the previous part!\r\rNow here's our recommendation for the structure of the tutorial (although, remember that this is not carved in the stone; if you have a better idea, use it!):\r\r\r.. container:: enumeratevisibleitemswithsquare\r\r   + Create the reference point and the title.\r\r     .. code-block:: rst\r\r        .. _matTheBasicImageContainer:\r\r        Mat - The Basic Image Container\r        *******************************\r\r     You start the tutorial by specifying a reference point by the ``.. _matTheBasicImageContainer:`` and then its title. The name of the reference point should be a unique one over the whole documentation. Therefore, do not use general names like *tutorial1*. Use the * character to underline the title for its full width. The subtitles of the tutorial should be underlined with = charachter.\r\r   + Goals. You start your tutorial by specifying what you will present. You can also enumerate the sub jobs to be done. For this you can use a bullet point construction. There is a single configuration file for both the reference manual and the tutorial documentation. In the reference manuals at the argument enumeration we do not want any kind of bullet point style enumeration. Therefore, by default all the bullet points at this level are set to do not show the dot before the entries in the HTML. You can override this by putting the bullet point in a container. I've defined a square type bullet point view under the name *enumeratevisibleitemswithsquare*. The CSS style definition for this is again in the  :file:`opencv\doc\_themes\blue\static\default.css_t` file. Here's a quick example of using it:\r\r     .. code-block:: rst\r\r        .. container:: enumeratevisibleitemswithsquare\r\r           + Create the reference point and the title.\r           + Second entry\r           + Third entry\r\r     Note that you need the keep the indentation of the container directive. Directive indentations are always three (3) spaces. Here you may even give usage tips for your sample code.\r\r   + Source code. Present your samples code to the user. It's a good idea to offer a quick download link for the HTML page by using the *download* directive and pointing out where the user may find your source code in the file system by using the *file* directive:\r\r     .. code-block:: rst\r\r        Text :file:`samples/cpp/tutorial_code/highgui/video-write/` folder of the OpenCV source library\r        or :download:`text to appear in the webpage\r        <../../../../samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp>`.\r\r     For the download link the path is a relative one, hence the multiple back stepping operations (..). Then you can add the source code either by using the *code block* directive or the *literal include* one. In case of the code block you will need to actually add all the source code text into your |reST|_ text and also apply the required indentation:\r\r     .. code-block:: rst\r\r        .. code-block:: cpp\r\r           int i = 0;\r           l = ++j;\r\r     The only argument of the directive is the language used (here CPP). Then you add the source code into its content (meaning one empty line after the directive) by keeping the indentation of the directive (3 spaces). With the *literal include* directive you do not need to add the source code of the sample. You just specify the sample and *Sphinx* will load it for you, during build time. Here's an example usage:\r\r     .. code-block:: rst\r\r        .. literalinclude:: ../../../../samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp\r           :language: cpp\r           :linenos:\r           :tab-width: 4\r           :lines: 1-8, 21-22, 24-\r\r     After the directive you specify a relative path to the file from what to import. It has four options: the language to use, if you add the ``:linenos:`` the line numbers will be shown, you can specify the tab size with the ``:tab-width:`` and you do not need to load the whole file, you can show just the important lines. Use the *lines* option to do not show redundant information (such as the *help* function). Here basically you specify ranges, if the second range line number is missing than that means that until the end of the file. The ranges specified here do no need to be in an ascending order, you may even reorganize the structure of how you want to show your sample inside the tutorial.\r\r   + The tutorial. Well here goes the explanation for why and what have you used. Try to be short, clear, concise and yet a thorough one. There's no magic formula. Look into a few already made tutorials and start out from there. Try to mix sample OpenCV code with your explanations. If with words is hard to describe something do not hesitate to add in a reasonable size image, to overcome this issue.\r\r     When you present OpenCV functionality it's a good idea to give a link to the used OpenCV data structure or function. Because the OpenCV tutorials and reference manual are in separate PDF files it is not possible to make this link work for the PDF format. Therefore, we use here only web page links to the **opencv.itseez.com** website. The OpenCV functions and data structures may be used for multiple tasks. Nevertheless, we want to avoid that every users creates its own reference to a commonly used function. So for this we use the global link collection of *Sphinx*. This is defined in the file:`opencv/doc/conf.py` configuration file. Open it and go all the way down to the last entry:\r\r     .. code-block:: py\r\r       # ---- External links for tutorials -----------------\r       extlinks = {\r           'hgvideo' : ('http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None)\r           }\r\r     In short here we defined a new **hgvideo** directive that refers to an external webpage link. Its usage is:\r\r     .. code-block:: rst\r\r       A sample function of the highgui modules image write and read page is the :hgvideo:`imread() function <imread>`.\r\r     Which turns to: A sample function of the highgui modules image write and read page is the :hgvideo:`imread() function <imread>`. The argument you give between the <> will be put in place of the ``%s`` in the upper definition, and as the link will anchor to the correct function. To find out the anchor of a given function just open up a web page, search for the function and click on it. In the address bar it should appear like: ``http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html#imread`` .  Look here for the name of the directives for each page of the OpenCV reference manual. If none present for one of them feel free to add one for it.\r\r     For formulas you can add LATEX code that will translate in the web pages into images. You do this by using the *math* directive. A usage tip:\r\r     .. code-block:: latex\r\r        .. math::\r\r           MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}\r\r     That after build turns into:\r\r     .. math::\r\r        MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}\r\r     You can even use it inline as ``:math:` MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}``` that turns into :math:`MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}`.\r\r     If you use some crazy LATEX library extension you need to add those to the ones to use at build time. Look into the file:`opencv/doc/conf.py` configuration file for more information on this.\r\r   + Results. Well, here depending on your program show one of more of the following:\r\r     - Console outputs by using the code block directive.\r     - Output images.\r     - Runtime videos, visualization. For this use your favorite screens capture software. `Camtasia Studio <http://www.techsmith.com/camtasia/>`_ certainly is one of the better choices, however their prices are out of this world. `CamStudio <http://camstudio.org/>`_ is a free alternative, but less powerful. If you do a video you can upload it to YouTube and then use the raw directive with HTML option to embed it into the generated web page:\r\r       .. code-block:: rst\r\r          You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=jpBwHxsl1_0>`_.\r\r          .. raw:: html\r\r             <div align="center">\r             <iframe title="Creating a video with OpenCV" width="560" height="349" src="http://www.youtube.com/embed/jpBwHxsl1_0?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>\r             </div>\r\r       This results in the text and video: You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=jpBwHxsl1_0>`_.\r\r       .. raw:: html\r\r          <div align="center">\r          <iframe title="Creating a video with OpenCV" width="560" height="349" src="http://www.youtube.com/embed/jpBwHxsl1_0?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>\r          </div>\r\r     When these aren't self-explanatory make sure to throw in a few guiding lines about what and why we can see.\r\r   + Build the documentation and check for errors or warnings. In the CMake make sure you check or pass the option for building documentation. Then simply build the **docs** project for the PDF file and the **docs_html** project for the web page. Read the output of the build and check for errors/warnings for what you have added. This is also the time to observe and correct any kind of *not so good looking* parts. Remember to keep clean our build logs.\r\r   + Read again your tutorial and check for both programming and spelling errors. If found any, please correct them.\r\r\rTake home the pride and joy of a job well done!\r===============================================\r\rOnce you are done contact me or dr. Gary Bradski with the tutorial. We may submit the tutorial ourselves to the trunk branch of our repository or ask you to do so.\r\rNow, to see your work **live** you may need to wait some time. The PDFs are updated usually at the launch of a new OpenCV version. The web pages are a little more diverse. They are automatically rebuilt in each evening. However, the **opencv.itseez.com** website contains only the most recent **stable branch** of OpenCV. Currently this is 2.3. When we add something new (like a tutorial) that first goes to the **trunk branch** of our repository. A build of this you may find on the **opencv.itseez.com/trunk** website. Although, we try to make a build every night occasionally we might freeze any of the branches to fix upcoming issues. During this it may take a little longer to see your work *live*, however if you submited it, be sure that eventually it will show up.\r\rIf you have any questions or advices relating to this tutorial you can contact me at -delete-bernat@-delete-primeranks.net. Of course, delete the -delete- parts of that e-mail address.
+ .. _howToWriteTutorial:
+ How to write a tutorial for OpenCV
+ **********************************
+ Okay, so assume you have just finished a project of yours implementing something
+ based on OpenCV and you want to present/share it with the community. Luckily, OpenCV
+ is an *open source project*. This means that anyone has access to the full source
+ code and may propose extensions. And a good tutorial is a valuable addition to the
+ library! Please read instructions on contribution process here:
+ http://opencv.org/contribute.html. You may also find this page helpful:
+ :how_to_contribute:`How to contribute <>`.
+ While making a robust and practical library (like OpenCV) is great, the success of a
+ library also depends on how user friendly it is. To improve on this aspect, the
+ OpenCV team has already been listening to user feedback at :opencv_qa:`OpenCV Q&A
+ forum <>` and by making samples you can find in the source directories
+ :file:`samples` folder. The addition of the tutorials (in both online and PDF format)
+ is an extension of these efforts.
+ Goal
+ ====
 -.. _reST: http://docutils.sourceforge.net/rst.html
++.. _reST: http://docutils.sourceforge.net/rst.html
+ .. |reST| replace:: reStructuredText
 -
+ .. |Sphinx| replace:: Sphinx
 -
+ .. _Sphinx: http://sphinx.pocoo.org/
+ The tutorials are just as an important part of the library as the implementation of
+ those crafty data structures and algorithms you can find in OpenCV. Therefore, the
+ source codes for the tutorials are part of the library. And yes, I meant source
+ codes. The reason for this formulation is that the tutorials are written by using the
+ |Sphinx|_ documentation generation system. This is based on the popular Python
+ documentation system called |reST|_ (reST). ReStructuredText is a really neat
+ language that by using a few simple conventions (indentation, directives) and
+ emulating old school email writing techniques (text only) tries to offer a simple
+ way to create and edit documents. Sphinx extends this with some new features and
+ creates the resulting document in both HTML (for web) and PDF (for offline usage)
+ format.
++
+ Usually, an OpenCV tutorial has the following parts:
 -  1. A source code demonstration of an OpenCV feature:
++1. A source code demonstration of an OpenCV feature:
++
++   a. One or more CPP, Python, Java or other type of files depending for what OpenCV offers support and for what language you make the tutorial.
++   #. Occasionaly, input resource files required for running your tutorials application.
 -    a. One or more CPP, Python, Java or other type of files depending for what OpenCV offers support and for what language you make the tutorial.
 -    #. Occasionaly, input resource files required for running your tutorials application.
 -  2. A table of content entry (so people may easily find the tutorial):
++#. A table of content entry (so people may easily find the tutorial):
 -    a. Adding your stuff to the tutorials table of content (**reST** file).
 -    #. Add an image file near the TOC entry.
++   a. Adding your stuff to the tutorials table of content (**reST** file).
++   #. Add an image file near the TOC entry.
 -  3. The content of the tutorial itself:
 -    a. The **reST** text of the tutorial
 -    #. Images following the idea that "*A picture is worth a thousand words*".
 -    #. For more complex demonstrations you may create a video.
++#. The content of the tutorial itself:
++
++   a. The **reST** text of the tutorial
++   #. Images following the idea that "*A picture is worth a thousand words*".
++   #. For more complex demonstrations you may create a video.
+ As you can see you will need at least some basic knowledge of the *reST* system in order to complete the task at hand with success. However, don't worry *reST* (and *Sphinx*) was made with simplicity in mind. It is easy to grasp its basics. I found that the `OpenAlea documentations introduction on this subject <http://openalea.gforge.inria.fr/doc/openalea/doc/_build/html/source/tutorial/rest_syntax.html>`_ (or the `Thomas Cokelaer one <http://thomas-cokelaer.info/tutorials/sphinx/rest_syntax.html>`_ ) should enough for this. If for some directive or feature you need a more in-depth description look it up in the official |reST|_ help files or at the |Sphinx|_ documentation.
+ In our world achieving some tasks is possible in multiple ways. However, some of the roads to take may have obvious or hidden advantages over others. Then again, in some other cases it may come down to just simple user preference. Here, I'll present how I decided to write the tutorials, based on my personal experience. If for some of them you know a better solution and you can back it up feel free to use that. I've nothing against it, as long as it gets the job done in an elegant fashion.
+ Now the best would be if you could make the integration yourself. For this you need first to have the source code. I recommend following the guides for your operating system on acquiring OpenCV sources. For Linux users look :ref:`here <Linux-Installation>` and for :ref:`Windows here <Windows_Installation>`. You must also install python and sphinx with its dependencies in order to be able to build the documentation.
+ Once you have downloaded the repository to your hard drive you can take a look in the OpenCV directory to make sure you have both the samples and doc folder present. Anyone may download the latest source files from :file:`git://github.com/Itseez/opencv.git` . Nevertheless, not everyone has upload (commit/submit) rights. This is to protect the integrity of the library. If you plan doing more than one tutorial, and would like to have an account with commit user rights you should first register an account at http://code.opencv.org/ and then contact OpenCV administrator -delete-admin@-delete-opencv.org. Otherwise, you can just send the resulting files to us at -delete-admin@-delete-opencv.org and we'll add it.
++
+ Format the Source Code
+ ======================
+ Before I start this let it be clear: the main goal is to have a working sample code. However, for your tutorial to be of a top notch quality you should follow a few guide lines I am going to present here. In case you have an application by using the older interface (with *IplImage*, *cvMat*, *cvLoadImage* and such) consider migrating it to the new C++ interface. The tutorials are intended to be an up to date help for our users. And as of OpenCV 2 the OpenCV emphasis on using the less error prone and clearer C++ interface. Therefore, if possible please convert your code to the C++ interface. For this it may help to read the :ref:`InteroperabilityWithOpenCV1` tutorial. However, once you have an OpenCV 2 working code, then you should make your source code snippet as easy to read as possible. Here're a couple of advices for this:
++
+ .. container:: enumeratevisibleitemswithsquare
+    + Add a standard output with the description of what your program does. Keep it short and yet, descriptive. This output is at the start of the program. In my example files this usually takes the form of a *help* function containing the output. This way both the source file viewer and application runner can see what all is about in your sample. Here's an instance of this:
+      .. code-block:: cpp
+         void help()
+         {
+         cout
+         << "--------------------------------------------------------------------------"   << endl
+         << "This program shows how to write video files. You can extract the R or G or B color channel "
+         << " of the input video. You can choose to use the source codec (Y) or select a custom one. (N)"<< endl
+         << "Usage:"                                                                       << endl
+         << "./video-write inputvideoName [ R | G | B] [Y | N]"                            << endl
+         << "--------------------------------------------------------------------------"   << endl
+         << endl;
+         }
+         // ...
+         int main(int argc, char *argv[], char *window_name)
+         {
+         help();
+         // here comes the actual source code
+         }
+      Additionally, finalize the description with a short usage guide. This way the user will know how to call your programs, what leads us to the next point.
+    + Prefer command line argument controlling instead of hard coded one. If your program has some variables that may be changed use command line arguments for this. The tutorials, can be a simple try-out ground for the user. If you offer command line controlling for the input image (for example), then you offer the possibility for the user to try it out with his/her own images, without the need to mess in the source code. In the upper example you can see that the input image, channel and codec selection may all be changed from the command line. Just compile the program and run it with your own input arguments.
+    + Be as verbose as possible. There is no shame in filling the source code with comments. This way the more advanced user may figure out what's happening right from the sample code. This advice goes for the output console too. Specify to the user what's happening. Never leave the user hanging there and thinking on: "Is this program now crashing or just doing some computationally intensive task?." So, if you do a training task that may take some time, make sure you print out a message about this before starting and after finishing it.
+    + Throw out unnecessary stuff from your source code. This is a warning to not take the previous point too seriously. Balance is the key. If it's something that can be done in a fewer lines or simpler than that's the way you should do it. Nevertheless, if for some reason you have such sections notify the user why you have chosen to do so. Keep the amount of information as low as possible, while still getting the job done in an elegant way.
+    + Put your sample file into the :file:`opencv/samples/cpp/tutorial_code/sectionName` folder. If you write a tutorial for other languages than cpp, then change that part of the path. Before completing this you need to decide that to what section (module) does your tutorial goes. Think about on what module relies most heavily your code and that is the one to use. If the answer to this question is more than one modules then the *general* section is the one to use. For finding the *opencv* directory open up your file system and navigate where you downloaded our repository.
+    + If the input resources are hard to acquire for the end user consider adding a few of them to the :file:`opencv/samples/cpp/tutorial_code/images`. Make sure that who reads your code can try it out!
+ Add the TOC entry
+ =================
+ For this you will need to know some |reST|_. There is no going around this. |reST|_ files have **rst** extensions. However, these are simple text files. Use any text editor you like. Finding a text editor that offers syntax highlighting for |reST|_ was quite a challenge at the time of writing this tutorial. In my experience, `Intype <http://intype.info/>`_ is a solid option on Windows, although there is still place for improvement.
+ Adding your source code to a table of content is important for multiple reasons. First and foremost this will allow for the user base to find your tutorial from our websites tutorial table of content. Secondly, if you omit this *Sphinx* will throw a warning that your tutorial file isn't part of any TOC tree entry. And there is nothing more than the developer team hates than an ever increasing warning/error list for their builds. *Sphinx* also uses this to build up the previous-back-up buttons on the website. Finally, omitting this step will lead to that your tutorial will **not** be added to the PDF version of the tutorials.
+ Navigate to the :file:`opencv/doc/tutorials/section/table_of_content_section` folder (where the section is the module to which you're adding the tutorial). Open the *table_of_content_section* file. Now this may have two forms. If no prior tutorials are present in this section that there is a template message about this and has the following form:
+ .. code-block:: rst
+   .. _Table-Of-Content-Section:
+    Section title
+    -----------------------------------------------------------
++
+    Description about the section.
++
+    .. include:: ../../definitions/noContent.rst
++
+    .. raw:: latex
++
+       \pagebreak
+ The first line is a reference to the section title in the reST system. The section title will be a link and you may refer to it via the ``:ref:`` directive. The *include* directive imports the template text from the definitions directories *noContent.rst* file. *Sphinx* does not creates the PDF from scratch. It does this by first creating a latex file. Then creates the PDF from the latex file. With the *raw* directive you can directly add to this output commands. Its unique argument is for what kind of output to add the content of the directive. For the PDFs it may happen that multiple sections will overlap on a single page. To avoid this at the end of the TOC we add a *pagebreak* latex command, that hints to the LATEX system that the next line should be on a new page.
+ If you have one of this, try to transform it to the following form:
+ .. include:: ../../definitions/tocDefinitions.rst
+ .. code-block:: rst
+    .. _Table-Of-Content-Section:
++
+    Section title
+    -----------------------------------------------------------
++
+    .. include:: ../../definitions/tocDefinitions.rst
++
+    +
+      .. tabularcolumns:: m{100pt} m{300pt}
+      .. cssclass:: toctableopencv
++
+      =============== ======================================================
+       |MatBasicIma|  **Title:** :ref:`matTheBasicImageContainer`
++
+                      *Compatibility:* > OpenCV 2.0
++
+                      *Author:* |Author_BernatG|
++
+                      You will learn how to store images in the memory and how to print out their content to the console.
++
+      =============== =====================================================
++
+      .. |MatBasicIma| image:: images/matTheBasicImageStructure.jpg
+                       :height: 90pt
+                       :width:  90pt
++
+    .. raw:: latex
+       \pagebreak
+    .. toctree::
 -
+       :hidden:
++
+       ../mat - the basic image container/mat - the basic image container
+ If this is already present just add a new section of the content between the include and the raw directives (excluding those lines). Here you'll see a new include directive. This should be present only once in a TOC tree and the reST file contains the definitions of all the authors contributing to the OpenCV tutorials. We are a multicultural community and some of our name may contain some funky characters. However, reST **only supports** ANSI characters. Luckily we can specify Unicode characters with the *unicode* directive. Doing this for all of your tutorials is a troublesome procedure. Therefore, the tocDefinitions file contains the definition of your author name. Add it here once and afterwards just use the replace construction. For example here's the definition for my name:
+ .. code-block:: rst
+    .. |Author_BernatG| unicode:: Bern U+00E1 t U+0020 G U+00E1 bor
+ The ``|Author_BernatG|`` is the text definitions alias. I can use later this to add the definition, like I've done in the TOCs *Author* part. After the ``::`` and a space you start the definition. If you want to add an UNICODE character (non-ASCI) leave an empty space and specify it in the format U+(UNICODE code). To find the UNICODE code of a character I recommend using the `FileFormat <http://www.fileformat.info>`_ websites service. Spaces are trimmed from the definition, therefore we add a space by its UNICODE character (U+0020).
 -Until the *raw* directive what you can see is a TOC tree entry. Here's how a TOC entry will look like:
 -.. code-block:: rst
++Until the *raw* directive what you can see is a TOC tree entry. Here's how a TOC entry will look like:
+++
+   .. tabularcolumns:: m{100pt} m{300pt}
+   .. cssclass:: toctableopencv
++
+   =============== ======================================================
+    |MatBasicIma|  **Title:** :ref:`matTheBasicImageContainer`
++
+                   *Compatibility:* > OpenCV 2.0
++
+                   *Author:* |Author_BernatG|
++
+                   You will learn how to store images in the memory and how to print out their content to the console.
++
+   =============== ======================================================
++
+   .. |MatBasicIma| image:: images/matTheBasicImageStructure.jpg
+                    :height: 90pt
+                    :width:  90pt
+ As you can see we have an image to the left and a description box to the right. To create two boxes we use a table with two columns and a single row. In the left column is the image and in the right one the description. However, the image directive is way too long to fit in a column. Therefore, we need to use the substitution definition system. We add this definition after the TOC tree. All images for the TOC tree are to be put in the images folder near its |reST|_ file. We use the point measurement system because we are also creating PDFs. PDFs are printable documents, where there is no such thing that pixels (px), just points (pt). And while generally space is no problem for web pages (we have monitors with **huge** resolutions) the size of the paper (A4 or letter) is constant and will be for a long time in the future. Therefore, size constrains come in play more like for the PDF, than the generated HTML code.
+ Now your images should be as small as possible, while still offering the intended information for the user. Remember that the tutorial will become part of the OpenCV source code. If you add large images (that manifest in form of large image size) it will just increase the size of the repository pointlessly. If someone wants to download it later, its download time will be that much longer. Not to mention the larger PDF size for the tutorials and the longer load time for the web pages. In terms of pixels a TOC image should not be larger than 120 X 120 pixels. Resize your images if they are larger!
 -.. note:: If you add a larger image and specify a smaller image size, *Sphinx* will not resize that. At build time will add the full size image and the resize will be done by your browser after the image is loaded. A 120 X 120 image is somewhere below 10KB. If you add a 110KB image, you have just pointlessly added a 100KB extra data to transfer over the internet for every user!
++.. note::
++
++   If you add a larger image and specify a smaller image size, *Sphinx* will not resize that. At build time will add the full size image and the resize will be done by your browser after the image is loaded. A 120 X 120 image is somewhere below 10KB. If you add a 110KB image, you have just pointlessly added a 100KB extra data to transfer over the internet for every user!
+ Generally speaking you shouldn't need to specify your images size (excluding the TOC entries). If no such is found *Sphinx* will use the size of the image itself (so no resize occurs). Then again if for some reason you decide to specify a size that should be the **width** of the image rather than its height. The reason for this again goes back to the PDFs. On a PDF page the height is larger than the width. In the PDF the images will not be resized. If you specify a size that does not fit in the page, then what does not fits in **will be cut off**. When creating your images for your tutorial you should try to keep the image widths below 500 pixels, and calculate with around 400 point page width when specifying image widths.
 -The image format depends on the content of the image. If you have some complex scene (many random like colors) then use *jpg*. Otherwise, prefer using *png*. They are even some tools out there that optimize the size of *PNG* images, such as `PNGGauntlet <http://pnggauntlet.com/>`_. Use them to make your images as small as possible in size. Now on the right side column of the table we add the information about the tutorial:
++The image format depends on the content of the image. If you have some complex scene (many random like colors) then use *jpg*. Otherwise, prefer using *png*. They are even some tools out there that optimize the size of *PNG* images, such as `PNGGauntlet <http://pnggauntlet.com/>`_. Use them to make your images as small as possible in size.
++
++Now on the right side column of the table we add the information about the tutorial:
+ .. container:: enumeratevisibleitemswithsquare
+    + In the first line it is the title of the tutorial. However, there is no need to specify it explicitly. We use the reference system. We'll start up our tutorial with a reference specification, just like in case of this TOC entry with its  `` .. _Table-Of-Content-Section:`` . If after this you have a title (pointed out by the following line of -), then Sphinx will replace the ``:ref:`Table-Of-Content-Section``` directive with the tile of the section in reference form (creates a link in web page). Here's how the definition looks in my case:
+      .. code-block:: rst
+         .. _matTheBasicImageContainer:
++
+            Mat - The Basic Image Container
+            *******************************
+      Note, that according to the |reST|_ rules the * should be as long as your title.
++
+    + Compatibility. What version of OpenCV is required to run your sample code.
++
+    + Author. Use the substitution markup of |reST|_.
++
+    + A short sentence describing the essence of your tutorial.
+ Now before each TOC entry you need to add the three lines of:
+ .. code-block:: cpp
+    +
+      .. tabularcolumns:: m{100pt} m{300pt}
+      .. cssclass:: toctableopencv
+ The plus sign (+) is to enumerate tutorials by using bullet points. So for every TOC entry we have a corresponding bullet point represented by the +. Sphinx is highly indenting sensitive. Indentation is used to express from which point until to which point does a construction last. Un-indentation means end of that construction. So to keep all the bullet points to the same group the following TOC entries (until the next +) should be indented by two spaces.
+ Here, I should also mention that **always** prefer using spaces instead of tabs. Working with only spaces makes possible that if we both use monotype fonts we will see the same thing. Tab size is text editor dependent and as should be avoided. *Sphinx* translates all tabs into 8 spaces before interpreting it.
+ It turns out that the automatic formatting of both the HTML and PDF(LATEX) system messes up our tables. Therefore, we need to help them out a little. For the PDF generation we add the ``.. tabularcolumns:: m{100pt} m{300pt}`` directive. This means that the first column should be 100 points wide and middle aligned. For the HTML look we simply name the following table of a *toctableopencv* class type. Then, we can modify the look of the table by modifying the CSS of our web page. The CSS definitions go into the :file:`opencv/doc/_themes/blue/static/default.css_t` file.
+ .. code-block:: css
+    .toctableopencv
+    {
+     width: 100% ;
+     table-layout: fixed;
+    }
++
++
+    .toctableopencv colgroup col:first-child
+    {
+     width: 100pt !important;
+     max-width: 100pt !important;
+     min-width: 100pt !important;
+    }
++
+    .toctableopencv colgroup col:nth-child(2)
+    {
+     width: 100% !important;
+    }
+ However, you should not need to modify this. Just add these three lines (plus keep the two space indentation) for all TOC entries you add. At the end of the TOC file you'll find:
+ .. code-block:: rst
+    .. raw:: latex
++
+       \pagebreak
++
+    .. toctree::
+       :hidden:
++
+       ../mat - the basic image container/mat - the basic image container
+ The page break entry comes for separating sections and should be only one in a TOC tree |reST|_ file. Finally, at the end of the TOC tree we need to add our tutorial to the *Sphinx* TOC tree system. *Sphinx* will generate from this the previous-next-up information for the HTML file and add items to the PDF according to the order here. By default this TOC tree directive generates a simple table of contents. However, we already created a fancy looking one so we no longer need this basic one. Therefore, we add the *hidden* option to do not show it.
+ The path is of a relative type. We step back in the file system and then go into the :file:`mat - the basic image container` directory for the :file:`mat - the basic image container.rst` file. Putting out the *rst* extension for the file is optional.
+ Write the tutorial
+ ==================
+ Create a folder with the name of your tutorial. Preferably, use small letters only. Then create a text file in this folder with *rst* extension and the same name. If you have images for the tutorial create an :file:`images` folder and add your images there. When creating your images follow the guidelines described in the previous part!
+ Now here's our recommendation for the structure of the tutorial (although, remember that this is not carved in the stone; if you have a better idea, use it!):
++
+ .. container:: enumeratevisibleitemswithsquare
+    + Create the reference point and the title.
+      .. code-block:: rst
+         .. _matTheBasicImageContainer:
++
+         Mat - The Basic Image Container
+         *******************************
+      You start the tutorial by specifying a reference point by the ``.. _matTheBasicImageContainer:`` and then its title. The name of the reference point should be a unique one over the whole documentation. Therefore, do not use general names like *tutorial1*. Use the * character to underline the title for its full width. The subtitles of the tutorial should be underlined with = charachter.
++
+    + Goals. You start your tutorial by specifying what you will present. You can also enumerate the sub jobs to be done. For this you can use a bullet point construction. There is a single configuration file for both the reference manual and the tutorial documentation. In the reference manuals at the argument enumeration we do not want any kind of bullet point style enumeration. Therefore, by default all the bullet points at this level are set to do not show the dot before the entries in the HTML. You can override this by putting the bullet point in a container. I've defined a square type bullet point view under the name *enumeratevisibleitemswithsquare*. The CSS style definition for this is again in the  :file:`opencv\doc\_themes\blue\static\default.css_t` file. Here's a quick example of using it:
+      .. code-block:: rst
+         .. container:: enumeratevisibleitemswithsquare
++
+            + Create the reference point and the title.
+            + Second entry
+            + Third entry
+      Note that you need the keep the indentation of the container directive. Directive indentations are always three (3) spaces. Here you may even give usage tips for your sample code.
++
+    + Source code. Present your samples code to the user. It's a good idea to offer a quick download link for the HTML page by using the *download* directive and pointing out where the user may find your source code in the file system by using the *file* directive:
+      .. code-block:: rst
+         Text :file:`samples/cpp/tutorial_code/highgui/video-write/` folder of the OpenCV source library
+         or :download:`text to appear in the webpage
+         <../../../../samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp>`.
+      For the download link the path is a relative one, hence the multiple back stepping operations (..). Then you can add the source code either by using the *code block* directive or the *literal include* one. In case of the code block you will need to actually add all the source code text into your |reST|_ text and also apply the required indentation:
+      .. code-block:: rst
+         .. code-block:: cpp
++
+            int i = 0;
+            l = ++j;
+      The only argument of the directive is the language used (here CPP). Then you add the source code into its content (meaning one empty line after the directive) by keeping the indentation of the directive (3 spaces). With the *literal include* directive you do not need to add the source code of the sample. You just specify the sample and *Sphinx* will load it for you, during build time. Here's an example usage:
+      .. code-block:: rst
+         .. literalinclude:: ../../../../samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp
+            :language: cpp
+            :linenos:
+            :tab-width: 4
+            :lines: 1-8, 21-22, 24-
+      After the directive you specify a relative path to the file from what to import. It has four options: the language to use, if you add the ``:linenos:`` the line numbers will be shown, you can specify the tab size with the ``:tab-width:`` and you do not need to load the whole file, you can show just the important lines. Use the *lines* option to do not show redundant information (such as the *help* function). Here basically you specify ranges, if the second range line number is missing than that means that until the end of the file. The ranges specified here do no need to be in an ascending order, you may even reorganize the structure of how you want to show your sample inside the tutorial.
++
+    + The tutorial. Well here goes the explanation for why and what have you used. Try to be short, clear, concise and yet a thorough one. There's no magic formula. Look into a few already made tutorials and start out from there. Try to mix sample OpenCV code with your explanations. If with words is hard to describe something do not hesitate to add in a reasonable size image, to overcome this issue.
++
+      When you present OpenCV functionality it's a good idea to give a link to the used OpenCV data structure or function. Because the OpenCV tutorials and reference manual are in separate PDF files it is not possible to make this link work for the PDF format. Therefore, we use here only web page links to the http://docs.opencv.org website. The OpenCV functions and data structures may be used for multiple tasks. Nevertheless, we want to avoid that every users creates its own reference to a commonly used function. So for this we use the global link collection of *Sphinx*. This is defined in the file:`opencv/doc/conf.py` configuration file. Open it and go all the way down to the last entry:
+      .. code-block:: py
+        # ---- External links for tutorials -----------------
+        extlinks = {
+            'hgvideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None)
+            }
+      In short here we defined a new **hgvideo** directive that refers to an external webpage link. Its usage is:
+      .. code-block:: rst
+        A sample function of the highgui modules image write and read page is the :hgvideo:`imread() function <imread>`.
+      Which turns to: A sample function of the highgui modules image write and read page is the :hgvideo:`imread() function <imread>`. The argument you give between the <> will be put in place of the ``%s`` in the upper definition, and as the link will anchor to the correct function. To find out the anchor of a given function just open up a web page, search for the function and click on it. In the address bar it should appear like: ``http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#imread`` .  Look here for the name of the directives for each page of the OpenCV reference manual. If none present for one of them feel free to add one for it.
++
+      For formulas you can add LATEX code that will translate in the web pages into images. You do this by using the *math* directive. A usage tip:
+      .. code-block:: latex
+         .. math::
++
+            MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}
+      That after build turns into:
+      .. math::
+         MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}
+      You can even use it inline as ``:math:` MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}``` that turns into :math:`MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}`.
++
+      If you use some crazy LATEX library extension you need to add those to the ones to use at build time. Look into the file:`opencv/doc/conf.py` configuration file for more information on this.
++
+    + Results. Well, here depending on your program show one of more of the following:
++
+      - Console outputs by using the code block directive.
+      - Output images.
+      - Runtime videos, visualization. For this use your favorite screens capture software. `Camtasia Studio <http://www.techsmith.com/camtasia/>`_ certainly is one of the better choices, however their prices are out of this world. `CamStudio <http://camstudio.org/>`_ is a free alternative, but less powerful. If you do a video you can upload it to YouTube and then use the raw directive with HTML option to embed it into the generated web page:
+        .. code-block:: rst
+           You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=jpBwHxsl1_0>`_.
+           .. raw:: html
+              <div align="center">
+              <iframe title="Creating a video with OpenCV" width="560" height="349" src="http://www.youtube.com/embed/jpBwHxsl1_0?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
+              </div>
+        This results in the text and video: You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=jpBwHxsl1_0>`_.
+        .. raw:: html
+           <div align="center">
+           <iframe title="Creating a video with OpenCV" width="560" height="349" src="http://www.youtube.com/embed/jpBwHxsl1_0?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
+           </div>
+      When these aren't self-explanatory make sure to throw in a few guiding lines about what and why we can see.
++
+    + Build the documentation and check for errors or warnings. In the CMake make sure you check or pass the option for building documentation. Then simply build the **docs** project for the PDF file and the **docs_html** project for the web page. Read the output of the build and check for errors/warnings for what you have added. This is also the time to observe and correct any kind of *not so good looking* parts. Remember to keep clean our build logs.
++
+    + Read again your tutorial and check for both programming and spelling errors. If found any, please correct them.
++
+ Take home the pride and joy of a job well done!
+ ===============================================
+ Once you are done please make a GitHub pull request with the tutorial. Now, to see
+ your work **live** you may need to wait some time. The PDFs are updated usually at
+ the launch of a new OpenCV version. The web pages are a little more diverse. They are
+ automatically rebuilt nightly. Currently we use ``2.4`` and ``master`` branches for
+ daily builds. So, if your pull request was merged to any of these branches, your
+ material will be published at `docs.opencv.org/2.4 <http:/docs.opencv.org/2.4>`_ or
+ `docs.opencv.org/master <http:/docs.opencv.org/master>`_ correspondingly. Everything
+ that was added to ``2.4`` is merged to ``master`` branch every week. Although, we try
+ to make a build every night, occasionally we might freeze any of the branches to fix
+ upcoming issues. During this it may take a little longer to see your work online,
+ however if you submitted it, be sure that eventually it will show up.
+ If you have any questions or advices relating to this tutorial you can contact us at
 --delete-admin@-delete-opencv.org (delete the -delete- parts of that email address).
++-delete-admin@-delete-opencv.org (delete the -delete- parts of that email address).
@@@ -1,7 -1,7 +1,7 @@@
  
 -#include "opencv2/contrib/contrib.hpp"
 +#include "opencv2/contrib.hpp"
  
- #ifdef WIN32
+ #if defined(WIN32) || defined(_WIN32)
      #include <windows.h>
      #include <tchar.h>
  #else
Simple merge
@@@ -13,10 -13,16 +13,14 @@@ Finds centers of clusters and groups in
  
  .. ocv:cfunction:: int cvKMeans2( const CvArr* samples, int cluster_count, CvArr* labels, CvTermCriteria termcrit, int attempts=1, CvRNG* rng=0, int flags=0, CvArr* _centers=0, double* compactness=0 )
  
 -.. ocv:pyoldfunction:: cv.KMeans2(samples, nclusters, labels, termcrit, attempts=1, flags=0, centers=None) -> float
 -
      :param samples: Floating-point matrix of input samples, one row per sample.
  
+     :param data: Data for clustering.
      :param cluster_count: Number of clusters to split the set by.
  
+     :param K: Number of clusters to split the set by.
      :param labels: Input/output integer array that stores the cluster indices for every sample.
  
      :param criteria: The algorithm termination criteria, that is, the maximum number of iterations and/or the desired accuracy. The accuracy is specified as ``criteria.epsilon``. As soon as each of the cluster centers moves by less than ``criteria.epsilon`` on some iteration, the algorithm stops.
@@@ -223,8 -230,12 +223,10 @@@ Calculates the width and height of a te
  
  .. ocv:cfunction:: void cvGetTextSize( const char* text_string, const CvFont* font, CvSize* text_size, int* baseline )
  
 -.. ocv:pyoldfunction:: cv.GetTextSize(textString, font)-> (textSize, baseline)
 -
      :param text: Input text string.
  
+     :param text_string: Input text string in C format.
      :param fontFace: Font to use. See the  :ocv:func:`putText` for details.
  
      :param fontScale: Font scale. See the  :ocv:func:`putText`  for details.
@@@ -1031,8 -1058,12 +1031,10 @@@ Returns the determinant of a square flo
  
  .. ocv:cfunction:: double cvDet( const CvArr* mat )
  
 -.. ocv:pyoldfunction:: cv.Det(mat) -> float
 -
      :param mtx: input matrix that must have ``CV_32FC1`` or ``CV_64FC1`` type and square size.
  
+     :param mat: input matrix that must have ``CV_32FC1`` or ``CV_64FC1`` type and square size.
  The function ``determinant`` calculates and returns the determinant of the specified matrix. For small matrices ( ``mtx.cols=mtx.rows<=3`` ),
  the direct method is used. For larger matrices, the function uses LU factorization with partial pivoting.
  
@@@ -179,8 -179,19 +179,19 @@@ FileStorage::ope
  -----------------
  Opens a file.
  
 -.. ocv:function:: bool FileStorage::open(const string& filename, int flags, const string& encoding=string())
 +.. ocv:function:: bool FileStorage::open(const String& filename, int flags, const String& encoding=String())
  
+     :param filename: Name of the file to open or the text string to read the data from.
+                      Extension of the file (``.xml`` or ``.yml``/``.yaml``) determines its format (XML or YAML respectively).
+                      Also you can append ``.gz`` to work with compressed files, for example ``myHugeMatrix.xml.gz``.
+                      If both ``FileStorage::WRITE`` and ``FileStorage::MEMORY`` flags are specified, ``source``
+                      is used just to specify the output file format (e.g. ``mydata.xml``, ``.yml`` etc.).
+     :param flags: Mode of operation. See FileStorage constructor for more details.
+     :param encoding: Encoding of the file. Note that UTF-16 XML encoding is not supported currently and you should use 8-bit encoding instead of it.
  See description of parameters in :ocv:func:`FileStorage::FileStorage`. The method calls :ocv:func:`FileStorage::release` before opening the file.
  
  
  //
  //M*/
  
 -#ifndef __OPENCV_CORE_MATRIX_OPERATIONS_HPP__
 -#define __OPENCV_CORE_MATRIX_OPERATIONS_HPP__
 +#ifndef __OPENCV_CORE_MAT_HPP__
 +#define __OPENCV_CORE_MAT_HPP__
  
 -#ifndef SKIP_INCLUDES
 -#include <limits.h>
 -#include <string.h>
 -#endif // SKIP_INCLUDES
 -
 -#ifdef __cplusplus
 -
 -namespace cv
 -{
 +#ifndef __cplusplus
 +#  error mat.hpp header must be compiled as C++
 +#endif
  
 -//////////////////////////////// Mat ////////////////////////////////
 +#include "opencv2/core/matx.hpp"
 +#include "opencv2/core/types.hpp"
  
 -inline void Mat::initEmpty()
 -{
 -    flags = MAGIC_VAL;
 -    dims = rows = cols = 0;
 -    data = datastart = dataend = datalimit = 0;
 -    refcount = 0;
 -    allocator = 0;
 -}
 -
 -inline Mat::Mat() : size(&rows)
 -{
 -    initEmpty();
 -}
  
 -inline Mat::Mat(int _rows, int _cols, int _type) : size(&rows)
 +namespace cv
  {
 -    initEmpty();
 -    create(_rows, _cols, _type);
 -}
  
 -inline Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s) : size(&rows)
 -{
 -    initEmpty();
 -    create(_rows, _cols, _type);
 -    *this = _s;
 -}
 +//////////////////////// Input/Output Array Arguments /////////////////////////////////
  
 -inline Mat::Mat(Size _sz, int _type) : size(&rows)
 +/*!
 + Proxy datatype for passing Mat's and vector<>'s as input parameters
 + */
 +class CV_EXPORTS _InputArray
  {
 -    initEmpty();
 -    create( _sz.height, _sz.width, _type );
 -}
 +public:
 +    enum {
 +        KIND_SHIFT = 16,
 +        FIXED_TYPE = 0x8000 << KIND_SHIFT,
 +        FIXED_SIZE = 0x4000 << KIND_SHIFT,
 +        KIND_MASK = ~(FIXED_TYPE|FIXED_SIZE) - (1 << KIND_SHIFT) + 1,
 +
 +        NONE              = 0 << KIND_SHIFT,
 +        MAT               = 1 << KIND_SHIFT,
 +        MATX              = 2 << KIND_SHIFT,
 +        STD_VECTOR        = 3 << KIND_SHIFT,
 +        STD_VECTOR_VECTOR = 4 << KIND_SHIFT,
 +        STD_VECTOR_MAT    = 5 << KIND_SHIFT,
 +        EXPR              = 6 << KIND_SHIFT,
 +        OPENGL_BUFFER     = 7 << KIND_SHIFT,
 +        CUDA_MEM          = 8 << KIND_SHIFT,
 +        GPU_MAT           = 9 << KIND_SHIFT,
 +        OCL_MAT           =10 << KIND_SHIFT
 +    };
 +
 +    _InputArray();
 +    _InputArray(const Mat& m);
 +    _InputArray(const MatExpr& expr);
 +    _InputArray(const std::vector<Mat>& vec);
 +    template<typename _Tp> _InputArray(const Mat_<_Tp>& m);
 +    template<typename _Tp> _InputArray(const std::vector<_Tp>& vec);
 +    template<typename _Tp> _InputArray(const std::vector<std::vector<_Tp> >& vec);
 +    template<typename _Tp> _InputArray(const std::vector<Mat_<_Tp> >& vec);
 +    template<typename _Tp> _InputArray(const _Tp* vec, int n);
 +    template<typename _Tp, int m, int n> _InputArray(const Matx<_Tp, m, n>& matx);
 +    _InputArray(const double& val);
 +    _InputArray(const gpu::GpuMat& d_mat);
 +    _InputArray(const ogl::Buffer& buf);
 +    _InputArray(const gpu::CudaMem& cuda_mem);
 +
 +    virtual Mat getMat(int i=-1) const;
 +    virtual void getMatVector(std::vector<Mat>& mv) const;
 +    virtual gpu::GpuMat getGpuMat() const;
 +    virtual ogl::Buffer getOGlBuffer() const;
 +
 +    virtual int kind() const;
 +    virtual Size size(int i=-1) const;
 +    virtual size_t total(int i=-1) const;
 +    virtual int type(int i=-1) const;
 +    virtual int depth(int i=-1) const;
 +    virtual int channels(int i=-1) const;
 +    virtual bool empty() const;
 +
 +    virtual ~_InputArray();
  
 -inline Mat::Mat(Size _sz, int _type, const Scalar& _s) : size(&rows)
 -{
 -    initEmpty();
 -    create(_sz.height, _sz.width, _type);
 -    *this = _s;
 -}
 +    int flags;
 +    void* obj;
 +    Size sz;
 +};
  
 -inline Mat::Mat(int _dims, const int* _sz, int _type) : size(&rows)
 -{
 -    initEmpty();
 -    create(_dims, _sz, _type);
 -}
  
 -inline Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s) : size(&rows)
 -{
 -    initEmpty();
 -    create(_dims, _sz, _type);
 -    *this = _s;
 -}
 -
 -inline Mat::Mat(const Mat& m)
 -    : flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), data(m.data),
 -    refcount(m.refcount), datastart(m.datastart), dataend(m.dataend),
 -    datalimit(m.datalimit), allocator(m.allocator), size(&rows)
 -{
 -    if( refcount )
 -        CV_XADD(refcount, 1);
 -    if( m.dims <= 2 )
 -    {
 -        step[0] = m.step[0]; step[1] = m.step[1];
 -    }
 -    else
 -    {
 -        dims = 0;
 -        copySize(m);
 -    }
 -}
 -
 -inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step)
 -    : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_rows), cols(_cols),
 -    data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0),
 -    datalimit(0), allocator(0), size(&rows)
 -{
 -    size_t esz = CV_ELEM_SIZE(_type), minstep = cols*esz;
 -    if( _step == AUTO_STEP )
 -    {
 -        _step = minstep;
 -        flags |= CONTINUOUS_FLAG;
 -    }
 -    else
 -    {
 -        if( rows == 1 ) _step = minstep;
 -        CV_DbgAssert( _step >= minstep );
 -        flags |= _step == minstep ? CONTINUOUS_FLAG : 0;
 -    }
 -    step[0] = _step; step[1] = esz;
 -    datalimit = datastart + _step*rows;
 -    dataend = datalimit - _step + minstep;
 -}
 -
 -inline Mat::Mat(Size _sz, int _type, void* _data, size_t _step)
 -    : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_sz.height), cols(_sz.width),
 -    data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0),
 -    datalimit(0), allocator(0), size(&rows)
 -{
 -    size_t esz = CV_ELEM_SIZE(_type), minstep = cols*esz;
 -    if( _step == AUTO_STEP )
 -    {
 -        _step = minstep;
 -        flags |= CONTINUOUS_FLAG;
 -    }
 -    else
 -    {
 -        if( rows == 1 ) _step = minstep;
 -        CV_DbgAssert( _step >= minstep );
 -        flags |= _step == minstep ? CONTINUOUS_FLAG : 0;
 -    }
 -    step[0] = _step; step[1] = esz;
 -    datalimit = datastart + _step*rows;
 -    dataend = datalimit - _step + minstep;
 -}
 -
 -
 -template<typename _Tp> inline Mat::Mat(const vector<_Tp>& vec, bool copyData)
 -    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG),
 -    dims(2), rows((int)vec.size()), cols(1), data(0), refcount(0),
 -    datastart(0), dataend(0), allocator(0), size(&rows)
 +/*!
 + Proxy datatype for passing Mat's and vector<>'s as input parameters
 + */
 +class CV_EXPORTS _OutputArray : public _InputArray
  {
 -    if(vec.empty())
 -        return;
 -    if( !copyData )
 -    {
 -        step[0] = step[1] = sizeof(_Tp);
 -        data = datastart = (uchar*)&vec[0];
 -        datalimit = dataend = datastart + rows*step[0];
 -    }
 -    else
 -        Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this);
 -}
 -
 -
 -template<typename _Tp, int n> inline Mat::Mat(const Vec<_Tp, n>& vec, bool copyData)
 -    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG),
 -    dims(2), rows(n), cols(1), data(0), refcount(0),
 -    datastart(0), dataend(0), allocator(0), size(&rows)
 -{
 -    if( !copyData )
 -    {
 -        step[0] = step[1] = sizeof(_Tp);
 -        data = datastart = (uchar*)vec.val;
 -        datalimit = dataend = datastart + rows*step[0];
 -    }
 -    else
 -        Mat(n, 1, DataType<_Tp>::type, (void*)vec.val).copyTo(*this);
 -}
 -
 -
 -template<typename _Tp, int m, int n> inline Mat::Mat(const Matx<_Tp,m,n>& M, bool copyData)
 -    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG),
 -    dims(2), rows(m), cols(n), data(0), refcount(0),
 -    datastart(0), dataend(0), allocator(0), size(&rows)
 -{
 -    if( !copyData )
 -    {
 -        step[0] = cols*sizeof(_Tp);
 -        step[1] = sizeof(_Tp);
 -        data = datastart = (uchar*)M.val;
 -        datalimit = dataend = datastart + rows*step[0];
 -    }
 -    else
 -        Mat(m, n, DataType<_Tp>::type, (uchar*)M.val).copyTo(*this);
 -}
 -
 -
 -template<typename _Tp> inline Mat::Mat(const Point_<_Tp>& pt, bool copyData)
 -    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG),
 -    dims(2), rows(2), cols(1), data(0), refcount(0),
 -    datastart(0), dataend(0), allocator(0), size(&rows)
 -{
 -    if( !copyData )
 -    {
 -        step[0] = step[1] = sizeof(_Tp);
 -        data = datastart = (uchar*)&pt.x;
 -        datalimit = dataend = datastart + rows*step[0];
 -    }
 -    else
 +public:
 +    enum
      {
 -        create(2, 1, DataType<_Tp>::type);
 -        ((_Tp*)data)[0] = pt.x;
 -        ((_Tp*)data)[1] = pt.y;
 -    }
 -}
 -
 +        DEPTH_MASK_8U = 1 << CV_8U,
 +        DEPTH_MASK_8S = 1 << CV_8S,
 +        DEPTH_MASK_16U = 1 << CV_16U,
 +        DEPTH_MASK_16S = 1 << CV_16S,
 +        DEPTH_MASK_32S = 1 << CV_32S,
 +        DEPTH_MASK_32F = 1 << CV_32F,
 +        DEPTH_MASK_64F = 1 << CV_64F,
 +        DEPTH_MASK_ALL = (DEPTH_MASK_64F<<1)-1,
 +        DEPTH_MASK_ALL_BUT_8S = DEPTH_MASK_ALL & ~DEPTH_MASK_8S,
 +        DEPTH_MASK_FLT = DEPTH_MASK_32F + DEPTH_MASK_64F
 +    };
 +
 +    _OutputArray();
 +    _OutputArray(Mat& m);
 +    _OutputArray(std::vector<Mat>& vec);
 +    _OutputArray(gpu::GpuMat& d_mat);
 +    _OutputArray(ogl::Buffer& buf);
 +    _OutputArray(gpu::CudaMem& cuda_mem);
 +    template<typename _Tp> _OutputArray(std::vector<_Tp>& vec);
 +    template<typename _Tp> _OutputArray(std::vector<std::vector<_Tp> >& vec);
 +    template<typename _Tp> _OutputArray(std::vector<Mat_<_Tp> >& vec);
 +    template<typename _Tp> _OutputArray(Mat_<_Tp>& m);
 +    template<typename _Tp> _OutputArray(_Tp* vec, int n);
 +    template<typename _Tp, int m, int n> _OutputArray(Matx<_Tp, m, n>& matx);
 +
 +    _OutputArray(const Mat& m);
 +    _OutputArray(const std::vector<Mat>& vec);
 +    _OutputArray(const gpu::GpuMat& d_mat);
 +    _OutputArray(const ogl::Buffer& buf);
 +    _OutputArray(const gpu::CudaMem& cuda_mem);
 +    template<typename _Tp> _OutputArray(const std::vector<_Tp>& vec);
 +    template<typename _Tp> _OutputArray(const std::vector<std::vector<_Tp> >& vec);
 +    template<typename _Tp> _OutputArray(const std::vector<Mat_<_Tp> >& vec);
 +    template<typename _Tp> _OutputArray(const Mat_<_Tp>& m);
 +    template<typename _Tp> _OutputArray(const _Tp* vec, int n);
 +    template<typename _Tp, int m, int n> _OutputArray(const Matx<_Tp, m, n>& matx);
 +
 +    virtual bool fixedSize() const;
 +    virtual bool fixedType() const;
 +    virtual bool needed() const;
 +    virtual Mat& getMatRef(int i=-1) const;
 +    virtual gpu::GpuMat& getGpuMatRef() const;
 +    virtual ogl::Buffer& getOGlBufferRef() const;
 +    virtual gpu::CudaMem& getCudaMemRef() const;
 +    virtual void create(Size sz, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const;
 +    virtual void create(int rows, int cols, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const;
 +    virtual void create(int dims, const int* size, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const;
 +    virtual void release() const;
 +    virtual void clear() const;
 +
 +    virtual ~_OutputArray();
 +};
  
 -template<typename _Tp> inline Mat::Mat(const Point3_<_Tp>& pt, bool copyData)
 -    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG),
 -    dims(2), rows(3), cols(1), data(0), refcount(0),
 -    datastart(0), dataend(0), allocator(0), size(&rows)
 -{
 -    if( !copyData )
 -    {
 -        step[0] = step[1] = sizeof(_Tp);
 -        data = datastart = (uchar*)&pt.x;
 -        datalimit = dataend = datastart + rows*step[0];
 -    }
 -    else
 -    {
 -        create(3, 1, DataType<_Tp>::type);
 -        ((_Tp*)data)[0] = pt.x;
 -        ((_Tp*)data)[1] = pt.y;
 -        ((_Tp*)data)[2] = pt.z;
 -    }
 -}
 -
 -
 -template<typename _Tp> inline Mat::Mat(const MatCommaInitializer_<_Tp>& commaInitializer)
 -    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG),
 -    dims(0), rows(0), cols(0), data(0), refcount(0),
 -    datastart(0), dataend(0), allocator(0), size(&rows)
 -{
 -    *this = *commaInitializer;
 -}
 +typedef const _InputArray& InputArray;
 +typedef InputArray InputArrayOfArrays;
 +typedef const _OutputArray& OutputArray;
 +typedef OutputArray OutputArrayOfArrays;
 +typedef OutputArray InputOutputArray;
 +typedef OutputArray InputOutputArrayOfArrays;
  
 -inline Mat::~Mat()
 -{
 -    release();
 -    if( step.p != step.buf )
 -        fastFree(step.p);
 -}
 +CV_EXPORTS OutputArray noArray();
  
 -inline Mat& Mat::operator = (const Mat& m)
 -{
 -    if( this != &m )
 -    {
 -        if( m.refcount )
 -            CV_XADD(m.refcount, 1);
 -        release();
 -        flags = m.flags;
 -        if( dims <= 2 && m.dims <= 2 )
 -        {
 -            dims = m.dims;
 -            rows = m.rows;
 -            cols = m.cols;
 -            step[0] = m.step[0];
 -            step[1] = m.step[1];
 -        }
 -        else
 -            copySize(m);
 -        data = m.data;
 -        datastart = m.datastart;
 -        dataend = m.dataend;
 -        datalimit = m.datalimit;
 -        refcount = m.refcount;
 -        allocator = m.allocator;
 -    }
 -    return *this;
 -}
 -
 -inline Mat Mat::row(int y) const { return Mat(*this, Range(y, y+1), Range::all()); }
 -inline Mat Mat::col(int x) const { return Mat(*this, Range::all(), Range(x, x+1)); }
 -inline Mat Mat::rowRange(int startrow, int endrow) const
 -    { return Mat(*this, Range(startrow, endrow), Range::all()); }
 -inline Mat Mat::rowRange(const Range& r) const
 -    { return Mat(*this, r, Range::all()); }
 -inline Mat Mat::colRange(int startcol, int endcol) const
 -    { return Mat(*this, Range::all(), Range(startcol, endcol)); }
 -inline Mat Mat::colRange(const Range& r) const
 -    { return Mat(*this, Range::all(), r); }
 -
 -inline Mat Mat::diag(const Mat& d)
 -{
 -    CV_Assert( d.cols == 1 || d.rows == 1 );
 -    int len = d.rows + d.cols - 1;
 -    Mat m(len, len, d.type(), Scalar(0)), md = m.diag();
 -    if( d.cols == 1 )
 -        d.copyTo(md);
 -    else
 -        transpose(d, md);
 -    return m;
 -}
 -
 -inline Mat Mat::clone() const
 -{
 -    Mat m;
 -    copyTo(m);
 -    return m;
 -}
  
 -inline void Mat::assignTo( Mat& m, int _type ) const
 -{
 -    if( _type < 0 )
 -        m = *this;
 -    else
 -        convertTo(m, _type);
 -}
  
 -inline void Mat::create(int _rows, int _cols, int _type)
 -{
 -    _type &= TYPE_MASK;
 -    if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && data )
 -        return;
 -    int sz[] = {_rows, _cols};
 -    create(2, sz, _type);
 -}
 -
 -inline void Mat::create(Size _sz, int _type)
 -{
 -    create(_sz.height, _sz.width, _type);
 -}
 +/////////////////////////////////// MatAllocator //////////////////////////////////////
  
 -inline void Mat::addref()
 -{ if( refcount ) CV_XADD(refcount, 1); }
 +/*!
 +   Custom array allocator
  
 -inline void Mat::release()
 +*/
 +class CV_EXPORTS MatAllocator
  {
 -    if( refcount && CV_XADD(refcount, -1) == 1 )
 -        deallocate();
 -    data = datastart = dataend = datalimit = 0;
 -    size.p[0] = 0;
 -    refcount = 0;
 -}
 -
 -inline Mat Mat::operator()( Range _rowRange, Range _colRange ) const
 -{
 -    return Mat(*this, _rowRange, _colRange);
 -}
 -
 -inline Mat Mat::operator()( const Rect& roi ) const
 -{ return Mat(*this, roi); }
 +public:
 +    MatAllocator() {}
 +    virtual ~MatAllocator() {}
 +    virtual void allocate(int dims, const int* sizes, int type, int*& refcount,
 +                          uchar*& datastart, uchar*& data, size_t* step) = 0;
 +    virtual void deallocate(int* refcount, uchar* datastart, uchar* data) = 0;
 +};
  
 -inline Mat Mat::operator()(const Range* ranges) const
 -{
 -    return Mat(*this, ranges);
 -}
  
 -inline Mat::operator CvMat() const
 -{
 -    CV_DbgAssert(dims <= 2);
 -    CvMat m = cvMat(rows, dims == 1 ? 1 : cols, type(), data);
 -    m.step = (int)step[0];
 -    m.type = (m.type & ~CONTINUOUS_FLAG) | (flags & CONTINUOUS_FLAG);
 -    return m;
 -}
 -
 -inline bool Mat::isContinuous() const { return (flags & CONTINUOUS_FLAG) != 0; }
 -inline bool Mat::isSubmatrix() const { return (flags & SUBMATRIX_FLAG) != 0; }
 -inline size_t Mat::elemSize() const { return dims > 0 ? step.p[dims-1] : 0; }
 -inline size_t Mat::elemSize1() const { return CV_ELEM_SIZE1(flags); }
 -inline int Mat::type() const { return CV_MAT_TYPE(flags); }
 -inline int Mat::depth() const { return CV_MAT_DEPTH(flags); }
 -inline int Mat::channels() const { return CV_MAT_CN(flags); }
 -inline size_t Mat::step1(int i) const { return step.p[i]/elemSize1(); }
 -inline bool Mat::empty() const { return data == 0 || total() == 0; }
 -inline size_t Mat::total() const
 -{
 -    if( dims <= 2 )
 -        return (size_t)rows*cols;
 -    size_t p = 1;
 -    for( int i = 0; i < dims; i++ )
 -        p *= size[i];
 -    return p;
 -}
 -
 -inline uchar* Mat::ptr(int y)
 -{
 -    CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) );
 -    return data + step.p[0]*y;
 -}
  
 -inline const uchar* Mat::ptr(int y) const
 -{
 -    CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) );
 -    return data + step.p[0]*y;
 -}
 +//////////////////////////////// MatCommaInitializer //////////////////////////////////
  
 -template<typename _Tp> inline _Tp* Mat::ptr(int y)
 -{
 -    CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) );
 -    return (_Tp*)(data + step.p[0]*y);
 -}
 +/*!
 + Comma-separated Matrix Initializer
  
 -template<typename _Tp> inline const _Tp* Mat::ptr(int y) const
 -{
 -    CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) );
 -    return (const _Tp*)(data + step.p[0]*y);
 -}
 + The class instances are usually not created explicitly.
 + Instead, they are created on "matrix << firstValue" operator.
  
 + The sample below initializes 2x2 rotation matrix:
  
 -inline uchar* Mat::ptr(int i0, int i1)
 + \code
 + double angle = 30, a = cos(angle*CV_PI/180), b = sin(angle*CV_PI/180);
 + Mat R = (Mat_<double>(2,2) << a, -b, b, a);
 + \endcode
 +*/
 +template<typename _Tp> class MatCommaInitializer_
  {
 -    CV_DbgAssert( dims >= 2 && data &&
 -                  (unsigned)i0 < (unsigned)size.p[0] &&
 -                  (unsigned)i1 < (unsigned)size.p[1] );
 -    return data + i0*step.p[0] + i1*step.p[1];
 -}
 +public:
 +    //! the constructor, created by "matrix << firstValue" operator, where matrix is cv::Mat
 +    MatCommaInitializer_(Mat_<_Tp>* _m);
 +    //! the operator that takes the next value and put it to the matrix
 +    template<typename T2> MatCommaInitializer_<_Tp>& operator , (T2 v);
 +    //! another form of conversion operator
 +    operator Mat_<_Tp>() const;
 +protected:
 +    MatIterator_<_Tp> it;
 +};
  
 -inline const uchar* Mat::ptr(int i0, int i1) const
 -{
 -    CV_DbgAssert( dims >= 2 && data &&
 -                 (unsigned)i0 < (unsigned)size.p[0] &&
 -                 (unsigned)i1 < (unsigned)size.p[1] );
 -    return data + i0*step.p[0] + i1*step.p[1];
 -}
  
 -template<typename _Tp> inline _Tp* Mat::ptr(int i0, int i1)
 -{
 -    CV_DbgAssert( dims >= 2 && data &&
 -                  (unsigned)i0 < (unsigned)size.p[0] &&
 -                  (unsigned)i1 < (unsigned)size.p[1] );
 -    return (_Tp*)(data + i0*step.p[0] + i1*step.p[1]);
 -}
  
 -template<typename _Tp> inline const _Tp* Mat::ptr(int i0, int i1) const
 -{
 -    CV_DbgAssert( dims >= 2 && data &&
 -                  (unsigned)i0 < (unsigned)size.p[0] &&
 -                  (unsigned)i1 < (unsigned)size.p[1] );
 -    return (const _Tp*)(data + i0*step.p[0] + i1*step.p[1]);
 -}
  
 -inline uchar* Mat::ptr(int i0, int i1, int i2)
 -{
 -    CV_DbgAssert( dims >= 3 && data &&
 -                  (unsigned)i0 < (unsigned)size.p[0] &&
 -                  (unsigned)i1 < (unsigned)size.p[1] &&
 -                  (unsigned)i2 < (unsigned)size.p[2] );
 -    return data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2];
 -}
 -
 -inline const uchar* Mat::ptr(int i0, int i1, int i2) const
 -{
 -    CV_DbgAssert( dims >= 3 && data &&
 -                  (unsigned)i0 < (unsigned)size.p[0] &&
 -                  (unsigned)i1 < (unsigned)size.p[1] &&
 -                  (unsigned)i2 < (unsigned)size.p[2] );
 -    return data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2];
 -}
 -
 -template<typename _Tp> inline _Tp* Mat::ptr(int i0, int i1, int i2)
 +/////////////////////////////////////// Mat ///////////////////////////////////////////
 +
 +/*!
 +   The n-dimensional matrix class.
 +
 +   The class represents an n-dimensional dense numerical array that can act as
 +   a matrix, image, optical flow map, 3-focal tensor etc.
 +   It is very similar to CvMat and CvMatND types from earlier versions of OpenCV,
 +   and similarly to those types, the matrix can be multi-channel. It also fully supports ROI mechanism.
 +
 +   There are many different ways to create cv::Mat object. Here are the some popular ones:
 +   <ul>
 +   <li> using cv::Mat::create(nrows, ncols, type) method or
 +     the similar constructor cv::Mat::Mat(nrows, ncols, type[, fill_value]) constructor.
 +     A new matrix of the specified size and specifed type will be allocated.
 +     "type" has the same meaning as in cvCreateMat function,
 +     e.g. CV_8UC1 means 8-bit single-channel matrix, CV_32FC2 means 2-channel (i.e. complex)
 +     floating-point matrix etc:
 +
 +     \code
 +     // make 7x7 complex matrix filled with 1+3j.
 +     cv::Mat M(7,7,CV_32FC2,Scalar(1,3));
 +     // and now turn M to 100x60 15-channel 8-bit matrix.
 +     // The old content will be deallocated
 +     M.create(100,60,CV_8UC(15));
 +     \endcode
 +
 +     As noted in the introduction of this chapter, Mat::create()
 +     will only allocate a new matrix when the current matrix dimensionality
 +     or type are different from the specified.
 +
 +   <li> by using a copy constructor or assignment operator, where on the right side it can
 +     be a matrix or expression, see below. Again, as noted in the introduction,
 +     matrix assignment is O(1) operation because it only copies the header
 +     and increases the reference counter. cv::Mat::clone() method can be used to get a full
 +     (a.k.a. deep) copy of the matrix when you need it.
 +
 +   <li> by constructing a header for a part of another matrix. It can be a single row, single column,
 +     several rows, several columns, rectangular region in the matrix (called a minor in algebra) or
 +     a diagonal. Such operations are also O(1), because the new header will reference the same data.
 +     You can actually modify a part of the matrix using this feature, e.g.
 +
 +     \code
 +     // add 5-th row, multiplied by 3 to the 3rd row
 +     M.row(3) = M.row(3) + M.row(5)*3;
 +
 +     // now copy 7-th column to the 1-st column
 +     // M.col(1) = M.col(7); // this will not work
 +     Mat M1 = M.col(1);
 +     M.col(7).copyTo(M1);
 +
 +     // create new 320x240 image
 +     cv::Mat img(Size(320,240),CV_8UC3);
 +     // select a roi
 +     cv::Mat roi(img, Rect(10,10,100,100));
 +     // fill the ROI with (0,255,0) (which is green in RGB space);
 +     // the original 320x240 image will be modified
 +     roi = Scalar(0,255,0);
 +     \endcode
 +
 +     Thanks to the additional cv::Mat::datastart and cv::Mat::dataend members, it is possible to
 +     compute the relative sub-matrix position in the main "container" matrix using cv::Mat::locateROI():
 +
 +     \code
 +     Mat A = Mat::eye(10, 10, CV_32S);
 +     // extracts A columns, 1 (inclusive) to 3 (exclusive).
 +     Mat B = A(Range::all(), Range(1, 3));
 +     // extracts B rows, 5 (inclusive) to 9 (exclusive).
 +     // that is, C ~ A(Range(5, 9), Range(1, 3))
 +     Mat C = B(Range(5, 9), Range::all());
 +     Size size; Point ofs;
 +     C.locateROI(size, ofs);
 +     // size will be (width=10,height=10) and the ofs will be (x=1, y=5)
 +     \endcode
 +
 +     As in the case of whole matrices, if you need a deep copy, use cv::Mat::clone() method
 +     of the extracted sub-matrices.
 +
 +   <li> by making a header for user-allocated-data. It can be useful for
 +      <ol>
 +      <li> processing "foreign" data using OpenCV (e.g. when you implement
 +         a DirectShow filter or a processing module for gstreamer etc.), e.g.
 +
 +         \code
 +         void process_video_frame(const unsigned char* pixels,
 +                                  int width, int height, int step)
 +         {
 +            cv::Mat img(height, width, CV_8UC3, pixels, step);
 +            cv::GaussianBlur(img, img, cv::Size(7,7), 1.5, 1.5);
 +         }
 +         \endcode
 +
 +      <li> for quick initialization of small matrices and/or super-fast element access
 +
 +         \code
 +         double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}};
 +         cv::Mat M = cv::Mat(3, 3, CV_64F, m).inv();
 +         \endcode
 +      </ol>
 +
 +       partial yet very common cases of this "user-allocated data" case are conversions
 +       from CvMat and IplImage to cv::Mat. For this purpose there are special constructors
 +       taking pointers to CvMat or IplImage and the optional
 +       flag indicating whether to copy the data or not.
 +
 +       Backward conversion from cv::Mat to CvMat or IplImage is provided via cast operators
 +       cv::Mat::operator CvMat() an cv::Mat::operator IplImage().
 +       The operators do not copy the data.
 +
 +
 +       \code
 +       IplImage* img = cvLoadImage("greatwave.jpg", 1);
 +       Mat mtx(img); // convert IplImage* -> cv::Mat
 +       CvMat oldmat = mtx; // convert cv::Mat -> CvMat
 +       CV_Assert(oldmat.cols == img->width && oldmat.rows == img->height &&
 +           oldmat.data.ptr == (uchar*)img->imageData && oldmat.step == img->widthStep);
 +       \endcode
 +
 +   <li> by using MATLAB-style matrix initializers, cv::Mat::zeros(), cv::Mat::ones(), cv::Mat::eye(), e.g.:
 +
 +   \code
 +   // create a double-precision identity martix and add it to M.
 +   M += Mat::eye(M.rows, M.cols, CV_64F);
 +   \endcode
 +
 +   <li> by using comma-separated initializer:
 +
 +   \code
 +   // create 3x3 double-precision identity matrix
 +   Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
 +   \endcode
 +
 +   here we first call constructor of cv::Mat_ class (that we describe further) with the proper matrix,
 +   and then we just put "<<" operator followed by comma-separated values that can be constants,
 +   variables, expressions etc. Also, note the extra parentheses that are needed to avoid compiler errors.
 +
 +   </ul>
 +
 +   Once matrix is created, it will be automatically managed by using reference-counting mechanism
 +   (unless the matrix header is built on top of user-allocated data,
 +   in which case you should handle the data by yourself).
 +   The matrix data will be deallocated when no one points to it;
 +   if you want to release the data pointed by a matrix header before the matrix destructor is called,
 +   use cv::Mat::release().
 +
 +   The next important thing to learn about the matrix class is element access. Here is how the matrix is stored.
 +   The elements are stored in row-major order (row by row). The cv::Mat::data member points to the first element of the first row,
 +   cv::Mat::rows contains the number of matrix rows and cv::Mat::cols - the number of matrix columns. There is yet another member,
 +   cv::Mat::step that is used to actually compute address of a matrix element. cv::Mat::step is needed because the matrix can be
 +   a part of another matrix or because there can some padding space in the end of each row for a proper alignment.
 +
 +   \image html roi.png
 +
 +   Given these parameters, address of the matrix element M_{ij} is computed as following:
 +
 +   addr(M_{ij})=M.data + M.step*i + j*M.elemSize()
 +
 +   if you know the matrix element type, e.g. it is float, then you can use cv::Mat::at() method:
 +
 +   addr(M_{ij})=&M.at<float>(i,j)
 +
 +   (where & is used to convert the reference returned by cv::Mat::at() to a pointer).
 +   if you need to process a whole row of matrix, the most efficient way is to get
 +   the pointer to the row first, and then just use plain C operator []:
 +
 +   \code
 +   // compute sum of positive matrix elements
 +   // (assuming that M is double-precision matrix)
 +   double sum=0;
 +   for(int i = 0; i < M.rows; i++)
 +   {
 +       const double* Mi = M.ptr<double>(i);
 +       for(int j = 0; j < M.cols; j++)
 +           sum += std::max(Mi[j], 0.);
 +   }
 +   \endcode
 +
 +   Some operations, like the above one, do not actually depend on the matrix shape,
 +   they just process elements of a matrix one by one (or elements from multiple matrices
 +   that are sitting in the same place, e.g. matrix addition). Such operations are called
 +   element-wise and it makes sense to check whether all the input/output matrices are continuous,
 +   i.e. have no gaps in the end of each row, and if yes, process them as a single long row:
 +
 +   \code
 +   // compute sum of positive matrix elements, optimized variant
 +   double sum=0;
 +   int cols = M.cols, rows = M.rows;
 +   if(M.isContinuous())
 +   {
 +       cols *= rows;
 +       rows = 1;
 +   }
 +   for(int i = 0; i < rows; i++)
 +   {
 +       const double* Mi = M.ptr<double>(i);
 +       for(int j = 0; j < cols; j++)
 +           sum += std::max(Mi[j], 0.);
 +   }
 +   \endcode
 +   in the case of continuous matrix the outer loop body will be executed just once,
 +   so the overhead will be smaller, which will be especially noticeable in the case of small matrices.
 +
 +   Finally, there are STL-style iterators that are smart enough to skip gaps between successive rows:
 +   \code
 +   // compute sum of positive matrix elements, iterator-based variant
 +   double sum=0;
 +   MatConstIterator_<double> it = M.begin<double>(), it_end = M.end<double>();
 +   for(; it != it_end; ++it)
 +       sum += std::max(*it, 0.);
 +   \endcode
 +
 +   The matrix iterators are random-access iterators, so they can be passed
 +   to any STL algorithm, including std::sort().
 +*/
 +class CV_EXPORTS Mat
  {
 -    CV_DbgAssert( dims >= 3 && data &&
 -                  (unsigned)i0 < (unsigned)size.p[0] &&
 -                  (unsigned)i1 < (unsigned)size.p[1] &&
 -                  (unsigned)i2 < (unsigned)size.p[2] );
 -    return (_Tp*)(data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]);
 -}
 -
 -template<typename _Tp> inline const _Tp* Mat::ptr(int i0, int i1, int i2) const
 -{
 -    CV_DbgAssert( dims >= 3 && data &&
 -                  (unsigned)i0 < (unsigned)size.p[0] &&
 -                  (unsigned)i1 < (unsigned)size.p[1] &&
 -                  (unsigned)i2 < (unsigned)size.p[2] );
 -    return (const _Tp*)(data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]);
 -}
 -
 -inline uchar* Mat::ptr(const int* idx)
 -{
 -    int i, d = dims;
 -    uchar* p = data;
 -    CV_DbgAssert( d >= 1 && p );
 -    for( i = 0; i < d; i++ )
 +public:
 +    //! default constructor
 +    Mat();
 +    //! constructs 2D matrix of the specified size and type
 +    // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
 +    Mat(int rows, int cols, int type);
 +    Mat(Size size, int type);
 +    //! constucts 2D matrix and fills it with the specified value _s.
 +    Mat(int rows, int cols, int type, const Scalar& s);
 +    Mat(Size size, int type, const Scalar& s);
 +
 +    //! constructs n-dimensional matrix
 +    Mat(int ndims, const int* sizes, int type);
 +    Mat(int ndims, const int* sizes, int type, const Scalar& s);
 +
 +    //! copy constructor
 +    Mat(const Mat& m);
 +    //! constructor for matrix headers pointing to user-allocated data
 +    Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
 +    Mat(Size size, int type, void* data, size_t step=AUTO_STEP);
 +    Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0);
 +
 +    //! creates a matrix header for a part of the bigger matrix
 +    Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all());
 +    Mat(const Mat& m, const Rect& roi);
 +    Mat(const Mat& m, const Range* ranges);
 +    //! builds matrix from std::vector with or without copying the data
 +    template<typename _Tp> explicit Mat(const std::vector<_Tp>& vec, bool copyData=false);
 +    //! builds matrix from cv::Vec; the data is copied by default
 +    template<typename _Tp, int n> explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true);
 +    //! builds matrix from cv::Matx; the data is copied by default
 +    template<typename _Tp, int m, int n> explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true);
 +    //! builds matrix from a 2D point
 +    template<typename _Tp> explicit Mat(const Point_<_Tp>& pt, bool copyData=true);
 +    //! builds matrix from a 3D point
 +    template<typename _Tp> explicit Mat(const Point3_<_Tp>& pt, bool copyData=true);
 +    //! builds matrix from comma initializer
 +    template<typename _Tp> explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer);
 +
 +    // //! converts old-style CvMat to the new matrix; the data is not copied by default
 +    // Mat(const CvMat* m, bool copyData=false);
 +    // //! converts old-style CvMatND to the new matrix; the data is not copied by default
 +    // Mat(const CvMatND* m, bool copyData=false);
 +    // //! converts old-style IplImage to the new matrix; the data is not copied by default
 +    // Mat(const IplImage* img, bool copyData=false);
 +    //Mat(const void* img, bool copyData=false);
 +
 +    //! download data from GpuMat
 +    explicit Mat(const gpu::GpuMat& m);
 +
 +    //! destructor - calls release()
 +    ~Mat();
 +    //! assignment operators
 +    Mat& operator = (const Mat& m);
 +    Mat& operator = (const MatExpr& expr);
 +
 +    //! returns a new matrix header for the specified row
 +    Mat row(int y) const;
 +    //! returns a new matrix header for the specified column
 +    Mat col(int x) const;
 +    //! ... for the specified row span
 +    Mat rowRange(int startrow, int endrow) const;
 +    Mat rowRange(const Range& r) const;
 +    //! ... for the specified column span
 +    Mat colRange(int startcol, int endcol) const;
 +    Mat colRange(const Range& r) const;
 +    //! ... for the specified diagonal
 +    // (d=0 - the main diagonal,
 +    //  >0 - a diagonal from the lower half,
 +    //  <0 - a diagonal from the upper half)
 +    Mat diag(int d=0) const;
 +    //! constructs a square diagonal matrix which main diagonal is vector "d"
 +    static Mat diag(const Mat& d);
 +
 +    //! returns deep copy of the matrix, i.e. the data is copied
 +    Mat clone() const;
 +    //! copies the matrix content to "m".
 +    // It calls m.create(this->size(), this->type()).
 +    void copyTo( OutputArray m ) const;
 +    //! copies those matrix elements to "m" that are marked with non-zero mask elements.
 +    void copyTo( OutputArray m, InputArray mask ) const;
 +    //! converts matrix to another datatype with optional scalng. See cvConvertScale.
 +    void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
 +
 +    void assignTo( Mat& m, int type=-1 ) const;
 +
 +    //! sets every matrix element to s
 +    Mat& operator = (const Scalar& s);
 +    //! sets some of the matrix elements to s, according to the mask
 +    Mat& setTo(InputArray value, InputArray mask=noArray());
 +    //! creates alternative matrix header for the same data, with different
 +    // number of channels and/or different number of rows. see cvReshape.
 +    Mat reshape(int cn, int rows=0) const;
 +    Mat reshape(int cn, int newndims, const int* newsz) const;
 +
 +    //! matrix transposition by means of matrix expressions
 +    MatExpr t() const;
 +    //! matrix inversion by means of matrix expressions
 +    MatExpr inv(int method=DECOMP_LU) const;
 +    //! per-element matrix multiplication by means of matrix expressions
 +    MatExpr mul(InputArray m, double scale=1) const;
 +
 +    //! computes cross-product of 2 3D vectors
 +    Mat cross(InputArray m) const;
 +    //! computes dot-product
 +    double dot(InputArray m) const;
 +
 +    //! Matlab-style matrix initialization
 +    static MatExpr zeros(int rows, int cols, int type);
 +    static MatExpr zeros(Size size, int type);
 +    static MatExpr zeros(int ndims, const int* sz, int type);
 +    static MatExpr ones(int rows, int cols, int type);
 +    static MatExpr ones(Size size, int type);
 +    static MatExpr ones(int ndims, const int* sz, int type);
 +    static MatExpr eye(int rows, int cols, int type);
 +    static MatExpr eye(Size size, int type);
 +
 +    //! allocates new matrix data unless the matrix already has specified size and type.
 +    // previous data is unreferenced if needed.
 +    void create(int rows, int cols, int type);
 +    void create(Size size, int type);
 +    void create(int ndims, const int* sizes, int type);
 +
 +    //! increases the reference counter; use with care to avoid memleaks
 +    void addref();
 +    //! decreases reference counter;
 +    // deallocates the data when reference counter reaches 0.
 +    void release();
 +
 +    //! deallocates the matrix data
 +    void deallocate();
 +    //! internal use function; properly re-allocates _size, _step arrays
 +    void copySize(const Mat& m);
 +
 +    //! reserves enough space to fit sz hyper-planes
 +    void reserve(size_t sz);
 +    //! resizes matrix to the specified number of hyper-planes
 +    void resize(size_t sz);
 +    //! resizes matrix to the specified number of hyper-planes; initializes the newly added elements
 +    void resize(size_t sz, const Scalar& s);
 +    //! internal function
 +    void push_back_(const void* elem);
 +    //! adds element to the end of 1d matrix (or possibly multiple elements when _Tp=Mat)
 +    template<typename _Tp> void push_back(const _Tp& elem);
 +    template<typename _Tp> void push_back(const Mat_<_Tp>& elem);
 +    void push_back(const Mat& m);
 +    //! removes several hyper-planes from bottom of the matrix
 +    void pop_back(size_t nelems=1);
 +
 +    //! locates matrix header within a parent matrix. See below
 +    void locateROI( Size& wholeSize, Point& ofs ) const;
 +    //! moves/resizes the current matrix ROI inside the parent matrix.
 +    Mat& adjustROI( int dtop, int dbottom, int dleft, int dright );
 +    //! extracts a rectangular sub-matrix
 +    // (this is a generalized form of row, rowRange etc.)
 +    Mat operator()( Range rowRange, Range colRange ) const;
 +    Mat operator()( const Rect& roi ) const;
 +    Mat operator()( const Range* ranges ) const;
 +
 +    // //! converts header to CvMat; no data is copied
 +    // operator CvMat() const;
 +    // //! converts header to CvMatND; no data is copied
 +    // operator CvMatND() const;
 +    // //! converts header to IplImage; no data is copied
 +    // operator IplImage() const;
 +
 +    template<typename _Tp> operator std::vector<_Tp>() const;
 +    template<typename _Tp, int n> operator Vec<_Tp, n>() const;
 +    template<typename _Tp, int m, int n> operator Matx<_Tp, m, n>() const;
 +
 +    //! returns true iff the matrix data is continuous
 +    // (i.e. when there are no gaps between successive rows).
 +    // similar to CV_IS_MAT_CONT(cvmat->type)
 +    bool isContinuous() const;
 +
 +    //! returns true if the matrix is a submatrix of another matrix
 +    bool isSubmatrix() const;
 +
 +    //! returns element size in bytes,
 +    // similar to CV_ELEM_SIZE(cvmat->type)
 +    size_t elemSize() const;
 +    //! returns the size of element channel in bytes.
 +    size_t elemSize1() const;
 +    //! returns element type, similar to CV_MAT_TYPE(cvmat->type)
 +    int type() const;
 +    //! returns element type, similar to CV_MAT_DEPTH(cvmat->type)
 +    int depth() const;
 +    //! returns element type, similar to CV_MAT_CN(cvmat->type)
 +    int channels() const;
 +    //! returns step/elemSize1()
 +    size_t step1(int i=0) const;
 +    //! returns true if matrix data is NULL
 +    bool empty() const;
 +    //! returns the total number of matrix elements
 +    size_t total() const;
 +
 +    //! returns N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise
 +    int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const;
 +
 +    //! returns pointer to i0-th submatrix along the dimension #0
 +    uchar* ptr(int i0=0);
 +    const uchar* ptr(int i0=0) const;
 +
 +    //! returns pointer to (i0,i1) submatrix along the dimensions #0 and #1
 +    uchar* ptr(int i0, int i1);
 +    const uchar* ptr(int i0, int i1) const;
 +
 +    //! returns pointer to (i0,i1,i3) submatrix along the dimensions #0, #1, #2
 +    uchar* ptr(int i0, int i1, int i2);
 +    const uchar* ptr(int i0, int i1, int i2) const;
 +
 +    //! returns pointer to the matrix element
 +    uchar* ptr(const int* idx);
 +    //! returns read-only pointer to the matrix element
 +    const uchar* ptr(const int* idx) const;
 +
 +    template<int n> uchar* ptr(const Vec<int, n>& idx);
 +    template<int n> const uchar* ptr(const Vec<int, n>& idx) const;
 +
 +    //! template version of the above method
 +    template<typename _Tp> _Tp* ptr(int i0=0);
 +    template<typename _Tp> const _Tp* ptr(int i0=0) const;
 +
 +    template<typename _Tp> _Tp* ptr(int i0, int i1);
 +    template<typename _Tp> const _Tp* ptr(int i0, int i1) const;
 +
 +    template<typename _Tp> _Tp* ptr(int i0, int i1, int i2);
 +    template<typename _Tp> const _Tp* ptr(int i0, int i1, int i2) const;
 +
 +    template<typename _Tp> _Tp* ptr(const int* idx);
 +    template<typename _Tp> const _Tp* ptr(const int* idx) const;
 +
 +    template<typename _Tp, int n> _Tp* ptr(const Vec<int, n>& idx);
 +    template<typename _Tp, int n> const _Tp* ptr(const Vec<int, n>& idx) const;
 +
 +    //! the same as above, with the pointer dereferencing
 +    template<typename _Tp> _Tp& at(int i0=0);
 +    template<typename _Tp> const _Tp& at(int i0=0) const;
 +
 +    template<typename _Tp> _Tp& at(int i0, int i1);
 +    template<typename _Tp> const _Tp& at(int i0, int i1) const;
 +
 +    template<typename _Tp> _Tp& at(int i0, int i1, int i2);
 +    template<typename _Tp> const _Tp& at(int i0, int i1, int i2) const;
 +
 +    template<typename _Tp> _Tp& at(const int* idx);
 +    template<typename _Tp> const _Tp& at(const int* idx) const;
 +
 +    template<typename _Tp, int n> _Tp& at(const Vec<int, n>& idx);
 +    template<typename _Tp, int n> const _Tp& at(const Vec<int, n>& idx) const;
 +
 +    //! special versions for 2D arrays (especially convenient for referencing image pixels)
 +    template<typename _Tp> _Tp& at(Point pt);
 +    template<typename _Tp> const _Tp& at(Point pt) const;
 +
 +    //! template methods for iteration over matrix elements.
 +    // the iterators take care of skipping gaps in the end of rows (if any)
 +    template<typename _Tp> MatIterator_<_Tp> begin();
 +    template<typename _Tp> MatIterator_<_Tp> end();
 +    template<typename _Tp> MatConstIterator_<_Tp> begin() const;
 +    template<typename _Tp> MatConstIterator_<_Tp> end() const;
 +
 +    enum { MAGIC_VAL  = 0x42FF0000, AUTO_STEP = 0, CONTINUOUS_FLAG = CV_MAT_CONT_FLAG, SUBMATRIX_FLAG = CV_SUBMAT_FLAG };
 +    enum { MAGIC_MASK = 0xFFFF0000, TYPE_MASK = 0x00000FFF, DEPTH_MASK = 7 };
 +
 +    /*! includes several bit-fields:
 +         - the magic signature
 +         - continuity flag
 +         - depth
 +         - number of channels
 +     */
 +    int flags;
 +    //! the matrix dimensionality, >= 2
 +    int dims;
 +    //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
 +    int rows, cols;
 +    //! pointer to the data
 +    uchar* data;
 +
 +    //! pointer to the reference counter;
 +    // when matrix points to user-allocated data, the pointer is NULL
 +    int* refcount;
 +
 +    //! helper fields used in locateROI and adjustROI
 +    uchar* datastart;
 +    uchar* dataend;
 +    uchar* datalimit;
 +
 +    //! custom allocator
 +    MatAllocator* allocator;
 +
 +    struct CV_EXPORTS MSize
      {
 -        CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] );
 -        p += idx[i]*step.p[i];
 -    }
 -    return p;
 -}
 -
 -inline const uchar* Mat::ptr(const int* idx) const
 -{
 -    int i, d = dims;
 -    uchar* p = data;
 -    CV_DbgAssert( d >= 1 && p );
 -    for( i = 0; i < d; i++ )
 +        MSize(int* _p);
 +        Size operator()() const;
 +        const int& operator[](int i) const;
 +        int& operator[](int i);
 +        operator const int*() const;
 +        bool operator == (const MSize& sz) const;
 +        bool operator != (const MSize& sz) const;
 +
 +        int* p;
 +    };
 +
 +    struct CV_EXPORTS MStep
      {
 -        CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] );
 -        p += idx[i]*step.p[i];
 -    }
 -    return p;
 -}
 -
 -template<typename _Tp> inline _Tp& Mat::at(int i0, int i1)
 -{
 -    CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] &&
 -        (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) &&
 -        CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
 -    return ((_Tp*)(data + step.p[0]*i0))[i1];
 -}
 -
 -template<typename _Tp> inline const _Tp& Mat::at(int i0, int i1) const
 -{
 -    CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] &&
 -        (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) &&
 -        CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
 -    return ((const _Tp*)(data + step.p[0]*i0))[i1];
 -}
 -
 -template<typename _Tp> inline _Tp& Mat::at(Point pt)
 -{
 -    CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] &&
 -        (unsigned)(pt.x*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) &&
 -        CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
 -    return ((_Tp*)(data + step.p[0]*pt.y))[pt.x];
 -}
 -
 -template<typename _Tp> inline const _Tp& Mat::at(Point pt) const
 -{
 -    CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] &&
 -        (unsigned)(pt.x*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) &&
 -        CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
 -    return ((const _Tp*)(data + step.p[0]*pt.y))[pt.x];
 -}
 -
 -template<typename _Tp> inline _Tp& Mat::at(int i0)
 -{
 -    CV_DbgAssert( dims <= 2 && data &&
 -                 (unsigned)i0 < (unsigned)(size.p[0]*size.p[1]) &&
 -                 elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
 -    if( isContinuous() || size.p[0] == 1 )
 -        return ((_Tp*)data)[i0];
 -    if( size.p[1] == 1 )
 -        return *(_Tp*)(data + step.p[0]*i0);
 -    int i = i0/cols, j = i0 - i*cols;
 -    return ((_Tp*)(data + step.p[0]*i))[j];
 -}
 -
 -template<typename _Tp> inline const _Tp& Mat::at(int i0) const
 -{
 -    CV_DbgAssert( dims <= 2 && data &&
 -                 (unsigned)i0 < (unsigned)(size.p[0]*size.p[1]) &&
 -                 elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
 -    if( isContinuous() || size.p[0] == 1 )
 -        return ((const _Tp*)data)[i0];
 -    if( size.p[1] == 1 )
 -        return *(const _Tp*)(data + step.p[0]*i0);
 -    int i = i0/cols, j = i0 - i*cols;
 -    return ((const _Tp*)(data + step.p[0]*i))[j];
 -}
 -
 -template<typename _Tp> inline _Tp& Mat::at(int i0, int i1, int i2)
 -{
 -    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
 -    return *(_Tp*)ptr(i0, i1, i2);
 -}
 -template<typename _Tp> inline const _Tp& Mat::at(int i0, int i1, int i2) const
 -{
 -    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
 -    return *(const _Tp*)ptr(i0, i1, i2);
 -}
 -template<typename _Tp> inline _Tp& Mat::at(const int* idx)
 -{
 -    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
 -    return *(_Tp*)ptr(idx);
 -}
 -template<typename _Tp> inline const _Tp& Mat::at(const int* idx) const
 -{
 -    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
 -    return *(const _Tp*)ptr(idx);
 -}
 -template<typename _Tp, int n> _Tp& Mat::at(const Vec<int, n>& idx)
 -{
 -    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
 -    return *(_Tp*)ptr(idx.val);
 -}
 -template<typename _Tp, int n> inline const _Tp& Mat::at(const Vec<int, n>& idx) const
 -{
 -    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
 -    return *(const _Tp*)ptr(idx.val);
 -}
 -
 -
 -template<typename _Tp> inline MatConstIterator_<_Tp> Mat::begin() const
 -{
 -    CV_DbgAssert( elemSize() == sizeof(_Tp) );
 -    return MatConstIterator_<_Tp>((const Mat_<_Tp>*)this);
 -}
 -
 -template<typename _Tp> inline MatConstIterator_<_Tp> Mat::end() const
 -{
 -    CV_DbgAssert( elemSize() == sizeof(_Tp) );
 -    MatConstIterator_<_Tp> it((const Mat_<_Tp>*)this);
 -    it += total();
 -    return it;
 -}
 -
 -template<typename _Tp> inline MatIterator_<_Tp> Mat::begin()
 -{
 -    CV_DbgAssert( elemSize() == sizeof(_Tp) );
 -    return MatIterator_<_Tp>((Mat_<_Tp>*)this);
 -}
 +        MStep();
 +        MStep(size_t s);
 +        const size_t& operator[](int i) const;
 +        size_t& operator[](int i);
 +        operator size_t() const;
 +        MStep& operator = (size_t s);
 +
 +        size_t* p;
 +        size_t buf[2];
 +    protected:
 +        MStep& operator = (const MStep&);
 +    };
 +
 +    MSize size;
 +    MStep step;
 +
 +protected:
 +};
  
 -template<typename _Tp> inline MatIterator_<_Tp> Mat::end()
 -{
 -    CV_DbgAssert( elemSize() == sizeof(_Tp) );
 -    MatIterator_<_Tp> it((Mat_<_Tp>*)this);
 -    it += total();
 -    return it;
 -}
  
 -template<typename _Tp> inline Mat::operator vector<_Tp>() const
 -{
 -    vector<_Tp> v;
 -    copyTo(v);
 -    return v;
 -}
 +///////////////////////////////// Mat_<_Tp> ////////////////////////////////////
  
 -template<typename _Tp, int n> inline Mat::operator Vec<_Tp, n>() const
 +/*!
 + Template matrix class derived from Mat
 +
 + The class Mat_ is a "thin" template wrapper on top of cv::Mat. It does not have any extra data fields,
 + nor it or cv::Mat have any virtual methods and thus references or pointers to these two classes
 + can be safely converted one to another. But do it with care, for example:
 +
 + \code
 + // create 100x100 8-bit matrix
 + Mat M(100,100,CV_8U);
 + // this will compile fine. no any data conversion will be done.
 + Mat_<float>& M1 = (Mat_<float>&)M;
 + // the program will likely crash at the statement below
 + M1(99,99) = 1.f;
 + \endcode
 +
 + While cv::Mat is sufficient in most cases, cv::Mat_ can be more convenient if you use a lot of element
 + access operations and if you know matrix type at compile time.
 + Note that cv::Mat::at<_Tp>(int y, int x) and cv::Mat_<_Tp>::operator ()(int y, int x) do absolutely the
 + same thing and run at the same speed, but the latter is certainly shorter:
 +
 + \code
 + Mat_<double> M(20,20);
 + for(int i = 0; i < M.rows; i++)
 +    for(int j = 0; j < M.cols; j++)
 +       M(i,j) = 1./(i+j+1);
 + Mat E, V;
 + eigen(M,E,V);
 + cout << E.at<double>(0,0)/E.at<double>(M.rows-1,0);
 + \endcode
 +
 + It is easy to use Mat_ for multi-channel images/matrices - just pass cv::Vec as cv::Mat_ template parameter:
 +
 + \code
 + // allocate 320x240 color image and fill it with green (in RGB space)
 + Mat_<Vec3b> img(240, 320, Vec3b(0,255,0));
 + // now draw a diagonal white line
 + for(int i = 0; i < 100; i++)
 +     img(i,i)=Vec3b(255,255,255);
 + // and now modify the 2nd (red) channel of each pixel
 + for(int i = 0; i < img.rows; i++)
 +    for(int j = 0; j < img.cols; j++)
 +       img(i,j)[2] ^= (uchar)(i ^ j); // img(y,x)[c] accesses c-th channel of the pixel (x,y)
 + \endcode
 +*/
 +template<typename _Tp> class CV_EXPORTS Mat_ : public Mat
  {
 -    CV_Assert( data && dims <= 2 && (rows == 1 || cols == 1) &&
 -               rows + cols - 1 == n && channels() == 1 );
 -
 -    if( isContinuous() && type() == DataType<_Tp>::type )
 -        return Vec<_Tp, n>((_Tp*)data);
 -    Vec<_Tp, n> v; Mat tmp(rows, cols, DataType<_Tp>::type, v.val);
 -    convertTo(tmp, tmp.type());
 -    return v;
 -}
 +public:
 +    typedef _Tp value_type;
 +    typedef typename DataType<_Tp>::channel_type channel_type;
 +    typedef MatIterator_<_Tp> iterator;
 +    typedef MatConstIterator_<_Tp> const_iterator;
 +
 +    //! default constructor
 +    Mat_();
 +    //! equivalent to Mat(_rows, _cols, DataType<_Tp>::type)
 +    Mat_(int _rows, int _cols);
 +    //! constructor that sets each matrix element to specified value
 +    Mat_(int _rows, int _cols, const _Tp& value);
 +    //! equivalent to Mat(_size, DataType<_Tp>::type)
 +    explicit Mat_(Size _size);
 +    //! constructor that sets each matrix element to specified value
 +    Mat_(Size _size, const _Tp& value);
 +    //! n-dim array constructor
 +    Mat_(int _ndims, const int* _sizes);
 +    //! n-dim array constructor that sets each matrix element to specified value
 +    Mat_(int _ndims, const int* _sizes, const _Tp& value);
 +    //! copy/conversion contructor. If m is of different type, it's converted
 +    Mat_(const Mat& m);
 +    //! copy constructor
 +    Mat_(const Mat_& m);
 +    //! constructs a matrix on top of user-allocated data. step is in bytes(!!!), regardless of the type
 +    Mat_(int _rows, int _cols, _Tp* _data, size_t _step=AUTO_STEP);
 +    //! constructs n-dim matrix on top of user-allocated data. steps are in bytes(!!!), regardless of the type
 +    Mat_(int _ndims, const int* _sizes, _Tp* _data, const size_t* _steps=0);
 +    //! selects a submatrix
 +    Mat_(const Mat_& m, const Range& rowRange, const Range& colRange=Range::all());
 +    //! selects a submatrix
 +    Mat_(const Mat_& m, const Rect& roi);
 +    //! selects a submatrix, n-dim version
 +    Mat_(const Mat_& m, const Range* ranges);
 +    //! from a matrix expression
 +    explicit Mat_(const MatExpr& e);
 +    //! makes a matrix out of Vec, std::vector, Point_ or Point3_. The matrix will have a single column
 +    explicit Mat_(const std::vector<_Tp>& vec, bool copyData=false);
 +    template<int n> explicit Mat_(const Vec<typename DataType<_Tp>::channel_type, n>& vec, bool copyData=true);
 +    template<int m, int n> explicit Mat_(const Matx<typename DataType<_Tp>::channel_type, m, n>& mtx, bool copyData=true);
 +    explicit Mat_(const Point_<typename DataType<_Tp>::channel_type>& pt, bool copyData=true);
 +    explicit Mat_(const Point3_<typename DataType<_Tp>::channel_type>& pt, bool copyData=true);
 +    explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer);
 +
 +    Mat_& operator = (const Mat& m);
 +    Mat_& operator = (const Mat_& m);
 +    //! set all the elements to s.
 +    Mat_& operator = (const _Tp& s);
 +    //! assign a matrix expression
 +    Mat_& operator = (const MatExpr& e);
 +
 +    //! iterators; they are smart enough to skip gaps in the end of rows
 +    iterator begin();
 +    iterator end();
 +    const_iterator begin() const;
 +    const_iterator end() const;
 +
 +    //! equivalent to Mat::create(_rows, _cols, DataType<_Tp>::type)
 +    void create(int _rows, int _cols);
 +    //! equivalent to Mat::create(_size, DataType<_Tp>::type)
 +    void create(Size _size);
 +    //! equivalent to Mat::create(_ndims, _sizes, DatType<_Tp>::type)
 +    void create(int _ndims, const int* _sizes);
 +    //! cross-product
 +    Mat_ cross(const Mat_& m) const;
 +    //! data type conversion
 +    template<typename T2> operator Mat_<T2>() const;
 +    //! overridden forms of Mat::row() etc.
 +    Mat_ row(int y) const;
 +    Mat_ col(int x) const;
 +    Mat_ diag(int d=0) const;
 +    Mat_ clone() const;
 +
 +    //! overridden forms of Mat::elemSize() etc.
 +    size_t elemSize() const;
 +    size_t elemSize1() const;
 +    int type() const;
 +    int depth() const;
 +    int channels() const;
 +    size_t step1(int i=0) const;
 +    //! returns step()/sizeof(_Tp)
 +    size_t stepT(int i=0) const;
 +
 +    //! overridden forms of Mat::zeros() etc. Data type is omitted, of course
 +    static MatExpr zeros(int rows, int cols);
 +    static MatExpr zeros(Size size);
 +    static MatExpr zeros(int _ndims, const int* _sizes);
 +    static MatExpr ones(int rows, int cols);
 +    static MatExpr ones(Size size);
 +    static MatExpr ones(int _ndims, const int* _sizes);
 +    static MatExpr eye(int rows, int cols);
 +    static MatExpr eye(Size size);
 +
 +    //! some more overriden methods
 +    Mat_& adjustROI( int dtop, int dbottom, int dleft, int dright );
 +    Mat_ operator()( const Range& rowRange, const Range& colRange ) const;
 +    Mat_ operator()( const Rect& roi ) const;
 +    Mat_ operator()( const Range* ranges ) const;
 +
 +    //! more convenient forms of row and element access operators
 +    _Tp* operator [](int y);
 +    const _Tp* operator [](int y) const;
 +
 +    //! returns reference to the specified element
 +    _Tp& operator ()(const int* idx);
 +    //! returns read-only reference to the specified element
 +    const _Tp& operator ()(const int* idx) const;
 +
 +    //! returns reference to the specified element
 +    template<int n> _Tp& operator ()(const Vec<int, n>& idx);
 +    //! returns read-only reference to the specified element
 +    template<int n> const _Tp& operator ()(const Vec<int, n>& idx) const;
 +
 +    //! returns reference to the specified element (1D case)
 +    _Tp& operator ()(int idx0);
 +    //! returns read-only reference to the specified element (1D case)
 +    const _Tp& operator ()(int idx0) const;
 +    //! returns reference to the specified element (2D case)
 +    _Tp& operator ()(int idx0, int idx1);
 +    //! returns read-only reference to the specified element (2D case)
 +    const _Tp& operator ()(int idx0, int idx1) const;
 +    //! returns reference to the specified element (3D case)
 +    _Tp& operator ()(int idx0, int idx1, int idx2);
 +    //! returns read-only reference to the specified element (3D case)
 +    const _Tp& operator ()(int idx0, int idx1, int idx2) const;
 +
 +    _Tp& operator ()(Point pt);
 +    const _Tp& operator ()(Point pt) const;
 +
 +    //! conversion to vector.
 +    operator std::vector<_Tp>() const;
 +    //! conversion to Vec
 +    template<int n> operator Vec<typename DataType<_Tp>::channel_type, n>() const;
 +    //! conversion to Matx
 +    template<int m, int n> operator Matx<typename DataType<_Tp>::channel_type, m, n>() const;
 +};
  
 -template<typename _Tp, int m, int n> inline Mat::operator Matx<_Tp, m, n>() const
 +typedef Mat_<uchar> Mat1b;
 +typedef Mat_<Vec2b> Mat2b;
 +typedef Mat_<Vec3b> Mat3b;
 +typedef Mat_<Vec4b> Mat4b;
 +
 +typedef Mat_<short> Mat1s;
 +typedef Mat_<Vec2s> Mat2s;
 +typedef Mat_<Vec3s> Mat3s;
 +typedef Mat_<Vec4s> Mat4s;
 +
 +typedef Mat_<ushort> Mat1w;
 +typedef Mat_<Vec2w> Mat2w;
 +typedef Mat_<Vec3w> Mat3w;
 +typedef Mat_<Vec4w> Mat4w;
 +
 +typedef Mat_<int>   Mat1i;
 +typedef Mat_<Vec2i> Mat2i;
 +typedef Mat_<Vec3i> Mat3i;
 +typedef Mat_<Vec4i> Mat4i;
 +
 +typedef Mat_<float> Mat1f;
 +typedef Mat_<Vec2f> Mat2f;
 +typedef Mat_<Vec3f> Mat3f;
 +typedef Mat_<Vec4f> Mat4f;
 +
 +typedef Mat_<double> Mat1d;
 +typedef Mat_<Vec2d> Mat2d;
 +typedef Mat_<Vec3d> Mat3d;
 +typedef Mat_<Vec4d> Mat4d;
 +
 +
 +
 +/////////////////////////// multi-dimensional sparse matrix //////////////////////////
 +
 +/*!
 + Sparse matrix class.
 +
 + The class represents multi-dimensional sparse numerical arrays. Such a sparse array can store elements
 + of any type that cv::Mat is able to store. "Sparse" means that only non-zero elements
 + are stored (though, as a result of some operations on a sparse matrix, some of its stored elements
 + can actually become 0. It's user responsibility to detect such elements and delete them using cv::SparseMat::erase().
 + The non-zero elements are stored in a hash table that grows when it's filled enough,
 + so that the search time remains O(1) in average. Elements can be accessed using the following methods:
 +
 + <ol>
 + <li>Query operations: cv::SparseMat::ptr() and the higher-level cv::SparseMat::ref(),
 +      cv::SparseMat::value() and cv::SparseMat::find, for example:
 + \code
 + const int dims = 5;
 + int size[] = {10, 10, 10, 10, 10};
 + SparseMat sparse_mat(dims, size, CV_32F);
 + for(int i = 0; i < 1000; i++)
 + {
 +     int idx[dims];
 +     for(int k = 0; k < dims; k++)
 +        idx[k] = rand()%sparse_mat.size(k);
 +     sparse_mat.ref<float>(idx) += 1.f;
 + }
 + \endcode
 +
 + <li>Sparse matrix iterators. Like cv::Mat iterators and unlike cv::Mat iterators, the sparse matrix iterators are STL-style,
 + that is, the iteration is done as following:
 + \code
 + // prints elements of a sparse floating-point matrix and the sum of elements.
 + SparseMatConstIterator_<float>
 +        it = sparse_mat.begin<float>(),
 +        it_end = sparse_mat.end<float>();
 + double s = 0;
 + int dims = sparse_mat.dims();
 + for(; it != it_end; ++it)
 + {
 +     // print element indices and the element value
 +     const Node* n = it.node();
 +     printf("(")
 +     for(int i = 0; i < dims; i++)
 +        printf("%3d%c", n->idx[i], i < dims-1 ? ',' : ')');
 +     printf(": %f\n", *it);
 +     s += *it;
 + }
 + printf("Element sum is %g\n", s);
 + \endcode
 + If you run this loop, you will notice that elements are enumerated
 + in no any logical order (lexicographical etc.),
 + they come in the same order as they stored in the hash table, i.e. semi-randomly.
 +
 + You may collect pointers to the nodes and sort them to get the proper ordering.
 + Note, however, that pointers to the nodes may become invalid when you add more
 + elements to the matrix; this is because of possible buffer reallocation.
 +
 + <li>A combination of the above 2 methods when you need to process 2 or more sparse
 + matrices simultaneously, e.g. this is how you can compute unnormalized
 + cross-correlation of the 2 floating-point sparse matrices:
 + \code
 + double crossCorr(const SparseMat& a, const SparseMat& b)
 + {
 +     const SparseMat *_a = &a, *_b = &b;
 +     // if b contains less elements than a,
 +     // it's faster to iterate through b
 +     if(_a->nzcount() > _b->nzcount())
 +        std::swap(_a, _b);
 +     SparseMatConstIterator_<float> it = _a->begin<float>(),
 +                                    it_end = _a->end<float>();
 +     double ccorr = 0;
 +     for(; it != it_end; ++it)
 +     {
 +         // take the next element from the first matrix
 +         float avalue = *it;
 +         const Node* anode = it.node();
 +         // and try to find element with the same index in the second matrix.
 +         // since the hash value depends only on the element index,
 +         // we reuse hashvalue stored in the node
 +         float bvalue = _b->value<float>(anode->idx,&anode->hashval);
 +         ccorr += avalue*bvalue;
 +     }
 +     return ccorr;
 + }
 + \endcode
 + </ol>
 +*/
 +class CV_EXPORTS SparseMat
  {
 -    CV_Assert( data && dims <= 2 && rows == m && cols == n && channels() == 1 );
 -
 -    if( isContinuous() && type() == DataType<_Tp>::type )
 -        return Matx<_Tp, m, n>((_Tp*)data);
 -    Matx<_Tp, m, n> mtx; Mat tmp(rows, cols, DataType<_Tp>::type, mtx.val);
 -    convertTo(tmp, tmp.type());
 -    return mtx;
 -}
 +public:
 +    typedef SparseMatIterator iterator;
 +    typedef SparseMatConstIterator const_iterator;
  
 +    enum { MAGIC_VAL=0x42FD0000, MAX_DIM=32, HASH_SCALE=0x5bd1e995, HASH_BIT=0x80000000 };
  
 -template<typename _Tp> inline void Mat::push_back(const _Tp& elem)
 -{
 -    if( !data )
 +    //! the sparse matrix header
 +    struct CV_EXPORTS Hdr
      {
 -        *this = Mat(1, 1, DataType<_Tp>::type, (void*)&elem).clone();
 -        return;
 -    }
 -    CV_Assert(DataType<_Tp>::type == type() && cols == 1
 -              /* && dims == 2 (cols == 1 implies dims == 2) */);
 -    uchar* tmp = dataend + step[0];
 -    if( !isSubmatrix() && isContinuous() && tmp <= datalimit )
 +        Hdr(int _dims, const int* _sizes, int _type);
 +        void clear();
 +        int refcount;
 +        int dims;
 +        int valueOffset;
 +        size_t nodeSize;
 +        size_t nodeCount;
 +        size_t freeList;
 +        std::vector<uchar> pool;
 +        std::vector<size_t> hashtab;
 +        int size[MAX_DIM];
 +    };
 +
 +    //! sparse matrix node - element of a hash table
 +    struct CV_EXPORTS Node
      {
 -        *(_Tp*)(data + (size.p[0]++)*step.p[0]) = elem;
 -        dataend = tmp;
 -    }
 -    else
 -        push_back_(&elem);
 -}
 -
 -template<typename _Tp> inline void Mat::push_back(const Mat_<_Tp>& m)
 -{
 -    push_back((const Mat&)m);
 -}
 -
 -inline Mat::MSize::MSize(int* _p) : p(_p) {}
 -inline Size Mat::MSize::operator()() const
 -{
 -    CV_DbgAssert(p[-1] <= 2);
 -    return Size(p[1], p[0]);
 -}
 -inline const int& Mat::MSize::operator[](int i) const { return p[i]; }
 -inline int& Mat::MSize::operator[](int i) { return p[i]; }
 -inline Mat::MSize::operator const int*() const { return p; }
 -
 -inline bool Mat::MSize::operator == (const MSize& sz) const
 -{
 -    int d = p[-1], dsz = sz.p[-1];
 -    if( d != dsz )
 -        return false;
 -    if( d == 2 )
 -        return p[0] == sz.p[0] && p[1] == sz.p[1];
 -
 -    for( int i = 0; i < d; i++ )
 -        if( p[i] != sz.p[i] )
 -            return false;
 -    return true;
 -}
 -
 -inline bool Mat::MSize::operator != (const MSize& sz) const
 -{
 -    return !(*this == sz);
 -}
 -
 -inline Mat::MStep::MStep() { p = buf; p[0] = p[1] = 0; }
 -inline Mat::MStep::MStep(size_t s) { p = buf; p[0] = s; p[1] = 0; }
 -inline const size_t& Mat::MStep::operator[](int i) const { return p[i]; }
 -inline size_t& Mat::MStep::operator[](int i) { return p[i]; }
 -inline Mat::MStep::operator size_t() const
 -{
 -    CV_DbgAssert( p == buf );
 -    return buf[0];
 -}
 -inline Mat::MStep& Mat::MStep::operator = (size_t s)
 -{
 -    CV_DbgAssert( p == buf );
 -    buf[0] = s;
 -    return *this;
 -}
 -
 -static inline Mat cvarrToMatND(const CvArr* arr, bool copyData=false, int coiMode=0)
 -{
 -    return cvarrToMat(arr, copyData, true, coiMode);
 -}
 -
 -///////////////////////////////////////////// SVD //////////////////////////////////////////////////////
 -
 -inline SVD::SVD() {}
 -inline SVD::SVD( InputArray m, int flags ) { operator ()(m, flags); }
 -inline void SVD::solveZ( InputArray m, OutputArray _dst )
 -{
 -    Mat mtx = m.getMat();
 -    SVD svd(mtx, (mtx.rows >= mtx.cols ? 0 : SVD::FULL_UV));
 -    _dst.create(svd.vt.cols, 1, svd.vt.type());
 -    Mat dst = _dst.getMat();
 -    svd.vt.row(svd.vt.rows-1).reshape(1,svd.vt.cols).copyTo(dst);
 -}
 -
 -template<typename _Tp, int m, int n, int nm> inline void
 -    SVD::compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt )
 -{
 -    assert( nm == MIN(m, n));
 -    Mat _a(a, false), _u(u, false), _w(w, false), _vt(vt, false);
 -    SVD::compute(_a, _w, _u, _vt);
 -    CV_Assert(_w.data == (uchar*)&w.val[0] && _u.data == (uchar*)&u.val[0] && _vt.data == (uchar*)&vt.val[0]);
 -}
 -
 -template<typename _Tp, int m, int n, int nm> inline void
 -SVD::compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w )
 -{
 -    assert( nm == MIN(m, n));
 -    Mat _a(a, false), _w(w, false);
 -    SVD::compute(_a, _w);
 -    CV_Assert(_w.data == (uchar*)&w.val[0]);
 -}
 -
 -template<typename _Tp, int m, int n, int nm, int nb> inline void
 -SVD::backSubst( const Matx<_Tp, nm, 1>& w, const Matx<_Tp, m, nm>& u,
 -                const Matx<_Tp, n, nm>& vt, const Matx<_Tp, m, nb>& rhs,
 -                Matx<_Tp, n, nb>& dst )
 -{
 -    assert( nm == MIN(m, n));
 -    Mat _u(u, false), _w(w, false), _vt(vt, false), _rhs(rhs, false), _dst(dst, false);
 -    SVD::backSubst(_w, _u, _vt, _rhs, _dst);
 -    CV_Assert(_dst.data == (uchar*)&dst.val[0]);
 -}
 -
 -///////////////////////////////// Mat_<_Tp> ////////////////////////////////////
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_()
 -    : Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; }
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols)
 -    : Mat(_rows, _cols, DataType<_Tp>::type) {}
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value)
 -    : Mat(_rows, _cols, DataType<_Tp>::type) { *this = value; }
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(Size _sz)
 -    : Mat(_sz.height, _sz.width, DataType<_Tp>::type) {}
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(Size _sz, const _Tp& value)
 -    : Mat(_sz.height, _sz.width, DataType<_Tp>::type) { *this = value; }
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(int _dims, const int* _sz)
 -    : Mat(_dims, _sz, DataType<_Tp>::type) {}
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(int _dims, const int* _sz, const _Tp& _s)
 -    : Mat(_dims, _sz, DataType<_Tp>::type, Scalar(_s)) {}
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_<_Tp>& m, const Range* ranges)
 -    : Mat(m, ranges) {}
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat& m)
 -    : Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; *this = m; }
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_& m)
 -    : Mat(m) {}
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t steps)
 -    : Mat(_rows, _cols, DataType<_Tp>::type, _data, steps) {}
 -
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_& m, const Range& _rowRange, const Range& _colRange)
 -    : Mat(m, _rowRange, _colRange) {}
 +        //! hash value
 +        size_t hashval;
 +        //! index of the next node in the same hash table entry
 +        size_t next;
 +        //! index of the matrix element
 +        int idx[MAX_DIM];
 +    };
 +
 +    //! default constructor
 +    SparseMat();
 +    //! creates matrix of the specified size and type
 +    SparseMat(int dims, const int* _sizes, int _type);
 +    //! copy constructor
 +    SparseMat(const SparseMat& m);
 +    //! converts dense 2d matrix to the sparse form
 +    /*!
 +     \param m the input matrix
-      \param try1d if true and m is a single-column matrix (Nx1),
-             then the sparse matrix will be 1-dimensional.
 +    */
 +    explicit SparseMat(const Mat& m);
 +    //! converts old-style sparse matrix to the new-style. All the data is copied
 +    //SparseMat(const CvSparseMat* m);
 +    //! the destructor
 +    ~SparseMat();
 +
 +    //! assignment operator. This is O(1) operation, i.e. no data is copied
 +    SparseMat& operator = (const SparseMat& m);
 +    //! equivalent to the corresponding constructor
 +    SparseMat& operator = (const Mat& m);
 +
 +    //! creates full copy of the matrix
 +    SparseMat clone() const;
 +
 +    //! copies all the data to the destination matrix. All the previous content of m is erased
 +    void copyTo( SparseMat& m ) const;
 +    //! converts sparse matrix to dense matrix.
 +    void copyTo( Mat& m ) const;
 +    //! multiplies all the matrix elements by the specified scale factor alpha and converts the results to the specified data type
 +    void convertTo( SparseMat& m, int rtype, double alpha=1 ) const;
 +    //! converts sparse matrix to dense n-dim matrix with optional type conversion and scaling.
 +    /*!
 +      \param rtype The output matrix data type. When it is =-1, the output array will have the same data type as (*this)
 +      \param alpha The scale factor
 +      \param beta The optional delta added to the scaled values before the conversion
 +    */
 +    void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const;
 +
 +    // not used now
 +    void assignTo( SparseMat& m, int type=-1 ) const;
 +
 +    //! reallocates sparse matrix.
 +    /*!
 +        If the matrix already had the proper size and type,
 +        it is simply cleared with clear(), otherwise,
 +        the old matrix is released (using release()) and the new one is allocated.
 +    */
 +    void create(int dims, const int* _sizes, int _type);
 +    //! sets all the sparse matrix elements to 0, which means clearing the hash table.
 +    void clear();
 +    //! manually increments the reference counter to the header.
 +    void addref();
 +    // decrements the header reference counter. When the counter reaches 0, the header and all the underlying data are deallocated.
 +    void release();
 +
 +    //! converts sparse matrix to the old-style representation; all the elements are copied.
 +    //operator CvSparseMat*() const;
 +    //! returns the size of each element in bytes (not including the overhead - the space occupied by SparseMat::Node elements)
 +    size_t elemSize() const;
 +    //! returns elemSize()/channels()
 +    size_t elemSize1() const;
 +
 +    //! returns type of sparse matrix elements
 +    int type() const;
 +    //! returns the depth of sparse matrix elements
 +    int depth() const;
 +    //! returns the number of channels
 +    int channels() const;
 +
 +    //! returns the array of sizes, or NULL if the matrix is not allocated
 +    const int* size() const;
 +    //! returns the size of i-th matrix dimension (or 0)
 +    int size(int i) const;
 +    //! returns the matrix dimensionality
 +    int dims() const;
 +    //! returns the number of non-zero elements (=the number of hash table nodes)
 +    size_t nzcount() const;
 +
 +    //! computes the element hash value (1D case)
 +    size_t hash(int i0) const;
 +    //! computes the element hash value (2D case)
 +    size_t hash(int i0, int i1) const;
 +    //! computes the element hash value (3D case)
 +    size_t hash(int i0, int i1, int i2) const;
 +    //! computes the element hash value (nD case)
 +    size_t hash(const int* idx) const;
 +
 +    //@{
 +    /*!
 +     specialized variants for 1D, 2D, 3D cases and the generic_type one for n-D case.
 +
 +     return pointer to the matrix element.
 +     <ul>
 +      <li>if the element is there (it's non-zero), the pointer to it is returned
 +      <li>if it's not there and createMissing=false, NULL pointer is returned
 +      <li>if it's not there and createMissing=true, then the new element
 +        is created and initialized with 0. Pointer to it is returned
 +      <li>if the optional hashval pointer is not NULL, the element hash value is
 +      not computed, but *hashval is taken instead.
 +     </ul>
 +    */
 +    //! returns pointer to the specified element (1D case)
 +    uchar* ptr(int i0, bool createMissing, size_t* hashval=0);
 +    //! returns pointer to the specified element (2D case)
 +    uchar* ptr(int i0, int i1, bool createMissing, size_t* hashval=0);
 +    //! returns pointer to the specified element (3D case)
 +    uchar* ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval=0);
 +    //! returns pointer to the specified element (nD case)
 +    uchar* ptr(const int* idx, bool createMissing, size_t* hashval=0);
 +    //@}
 +
 +    //@{
 +    /*!
 +     return read-write reference to the specified sparse matrix element.
 +
 +     ref<_Tp>(i0,...[,hashval]) is equivalent to *(_Tp*)ptr(i0,...,true[,hashval]).
 +     The methods always return a valid reference.
 +     If the element did not exist, it is created and initialiazed with 0.
 +    */
 +    //! returns reference to the specified element (1D case)
 +    template<typename _Tp> _Tp& ref(int i0, size_t* hashval=0);
 +    //! returns reference to the specified element (2D case)
 +    template<typename _Tp> _Tp& ref(int i0, int i1, size_t* hashval=0);
 +    //! returns reference to the specified element (3D case)
 +    template<typename _Tp> _Tp& ref(int i0, int i1, int i2, size_t* hashval=0);
 +    //! returns reference to the specified element (nD case)
 +    template<typename _Tp> _Tp& ref(const int* idx, size_t* hashval=0);
 +    //@}
 +
 +    //@{
 +    /*!
 +     return value of the specified sparse matrix element.
 +
 +     value<_Tp>(i0,...[,hashval]) is equivalent
 +
 +     \code
 +     { const _Tp* p = find<_Tp>(i0,...[,hashval]); return p ? *p : _Tp(); }
 +     \endcode
 +
 +     That is, if the element did not exist, the methods return 0.
 +     */
 +    //! returns value of the specified element (1D case)
 +    template<typename _Tp> _Tp value(int i0, size_t* hashval=0) const;
 +    //! returns value of the specified element (2D case)
 +    template<typename _Tp> _Tp value(int i0, int i1, size_t* hashval=0) const;
 +    //! returns value of the specified element (3D case)
 +    template<typename _Tp> _Tp value(int i0, int i1, int i2, size_t* hashval=0) const;
 +    //! returns value of the specified element (nD case)
 +    template<typename _Tp> _Tp value(const int* idx, size_t* hashval=0) const;
 +    //@}
 +
 +    //@{
 +    /*!
 +     Return pointer to the specified sparse matrix element if it exists
 +
 +     find<_Tp>(i0,...[,hashval]) is equivalent to (_const Tp*)ptr(i0,...false[,hashval]).
 +
 +     If the specified element does not exist, the methods return NULL.
 +    */
 +    //! returns pointer to the specified element (1D case)
 +    template<typename _Tp> const _Tp* find(int i0, size_t* hashval=0) const;
 +    //! returns pointer to the specified element (2D case)
 +    template<typename _Tp> const _Tp* find(int i0, int i1, size_t* hashval=0) const;
 +    //! returns pointer to the specified element (3D case)
 +    template<typename _Tp> const _Tp* find(int i0, int i1, int i2, size_t* hashval=0) const;
 +    //! returns pointer to the specified element (nD case)
 +    template<typename _Tp> const _Tp* find(const int* idx, size_t* hashval=0) const;
 +
 +    //! erases the specified element (2D case)
 +    void erase(int i0, int i1, size_t* hashval=0);
 +    //! erases the specified element (3D case)
 +    void erase(int i0, int i1, int i2, size_t* hashval=0);
 +    //! erases the specified element (nD case)
 +    void erase(const int* idx, size_t* hashval=0);
 +
 +    //@{
 +    /*!
 +       return the sparse matrix iterator pointing to the first sparse matrix element
 +    */
 +    //! returns the sparse matrix iterator at the matrix beginning
 +    SparseMatIterator begin();
 +    //! returns the sparse matrix iterator at the matrix beginning
 +    template<typename _Tp> SparseMatIterator_<_Tp> begin();
 +    //! returns the read-only sparse matrix iterator at the matrix beginning
 +    SparseMatConstIterator begin() const;
 +    //! returns the read-only sparse matrix iterator at the matrix beginning
 +    template<typename _Tp> SparseMatConstIterator_<_Tp> begin() const;
 +    //@}
 +    /*!
 +       return the sparse matrix iterator pointing to the element following the last sparse matrix element
 +    */
 +    //! returns the sparse matrix iterator at the matrix end
 +    SparseMatIterator end();
 +    //! returns the read-only sparse matrix iterator at the matrix end
 +    SparseMatConstIterator end() const;
 +    //! returns the typed sparse matrix iterator at the matrix end
 +    template<typename _Tp> SparseMatIterator_<_Tp> end();
 +    //! returns the typed read-only sparse matrix iterator at the matrix end
 +    template<typename _Tp> SparseMatConstIterator_<_Tp> end() const;
 +
 +    //! returns the value stored in the sparse martix node
 +    template<typename _Tp> _Tp& value(Node* n);
 +    //! returns the value stored in the sparse martix node
 +    template<typename _Tp> const _Tp& value(const Node* n) const;
 +
 +    ////////////// some internal-use methods ///////////////
 +    Node* node(size_t nidx);
 +    const Node* node(size_t nidx) const;
 +
 +    uchar* newNode(const int* idx, size_t hashval);
 +    void removeNode(size_t hidx, size_t nidx, size_t previdx);
 +    void resizeHashTab(size_t newsize);
  
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_& m, const Rect& roi)
 -    : Mat(m, roi) {}
 +    int flags;
 +    Hdr* hdr;
 +};
  
 -template<typename _Tp> template<int n> inline
 -    Mat_<_Tp>::Mat_(const Vec<typename DataType<_Tp>::channel_type, n>& vec, bool copyData)
 -    : Mat(n/DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&vec)
 -{
 -    CV_Assert(n%DataType<_Tp>::channels == 0);
 -    if( copyData )
 -        *this = clone();
 -}
 -
 -template<typename _Tp> template<int m, int n> inline
 -    Mat_<_Tp>::Mat_(const Matx<typename DataType<_Tp>::channel_type,m,n>& M, bool copyData)
 -    : Mat(m, n/DataType<_Tp>::channels, DataType<_Tp>::type, (void*)&M)
 -{
 -    CV_Assert(n % DataType<_Tp>::channels == 0);
 -    if( copyData )
 -        *this = clone();
 -}
  
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(const Point_<typename DataType<_Tp>::channel_type>& pt, bool copyData)
 -    : Mat(2/DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt)
 -{
 -    CV_Assert(2 % DataType<_Tp>::channels == 0);
 -    if( copyData )
 -        *this = clone();
 -}
  
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(const Point3_<typename DataType<_Tp>::channel_type>& pt, bool copyData)
 -    : Mat(3/DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt)
 -{
 -    CV_Assert(3 % DataType<_Tp>::channels == 0);
 -    if( copyData )
 -        *this = clone();
 -}
 +///////////////////////////////// SparseMat_<_Tp> ////////////////////////////////////
  
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(const MatCommaInitializer_<_Tp>& commaInitializer)
 -    : Mat(commaInitializer) {}
 +/*!
 + The Template Sparse Matrix class derived from cv::SparseMat
  
 -template<typename _Tp> inline Mat_<_Tp>::Mat_(const vector<_Tp>& vec, bool copyData)
 -    : Mat(vec, copyData) {}
 + The class provides slightly more convenient operations for accessing elements.
  
 -template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m)
 -{
 -    if( DataType<_Tp>::type == m.type() )
 -    {
 -        Mat::operator = (m);
 -        return *this;
 -    }
 -    if( DataType<_Tp>::depth == m.depth() )
 -    {
 -        return (*this = m.reshape(DataType<_Tp>::channels, m.dims, 0));
 -    }
 -    CV_DbgAssert(DataType<_Tp>::channels == m.channels());
 -    m.convertTo(*this, type());
 -    return *this;
 -}
 -
 -template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat_& m)
 + \code
 + SparseMat m;
 + ...
 + SparseMat_<int> m_ = (SparseMat_<int>&)m;
 + m_.ref(1)++; // equivalent to m.ref<int>(1)++;
 + m_.ref(2) += m_(3); // equivalent to m.ref<int>(2) += m.value<int>(3);
 + \endcode
 +*/
 +template<typename _Tp> class CV_EXPORTS SparseMat_ : public SparseMat
  {
 -    Mat::operator=(m);
 -    return *this;
 -}
 +public:
 +    typedef SparseMatIterator_<_Tp> iterator;
 +    typedef SparseMatConstIterator_<_Tp> const_iterator;
 +
 +    //! the default constructor
 +    SparseMat_();
 +    //! the full constructor equivelent to SparseMat(dims, _sizes, DataType<_Tp>::type)
 +    SparseMat_(int dims, const int* _sizes);
 +    //! the copy constructor. If DataType<_Tp>.type != m.type(), the m elements are converted
 +    SparseMat_(const SparseMat& m);
 +    //! the copy constructor. This is O(1) operation - no data is copied
 +    SparseMat_(const SparseMat_& m);
 +    //! converts dense matrix to the sparse form
 +    SparseMat_(const Mat& m);
 +    //! converts the old-style sparse matrix to the C++ class. All the elements are copied
 +    //SparseMat_(const CvSparseMat* m);
 +    //! the assignment operator. If DataType<_Tp>.type != m.type(), the m elements are converted
 +    SparseMat_& operator = (const SparseMat& m);
 +    //! the assignment operator. This is O(1) operation - no data is copied
 +    SparseMat_& operator = (const SparseMat_& m);
 +    //! converts dense matrix to the sparse form
 +    SparseMat_& operator = (const Mat& m);
 +
 +    //! makes full copy of the matrix. All the elements are duplicated
 +    SparseMat_ clone() const;
 +    //! equivalent to cv::SparseMat::create(dims, _sizes, DataType<_Tp>::type)
 +    void create(int dims, const int* _sizes);
 +    //! converts sparse matrix to the old-style CvSparseMat. All the elements are copied
 +    //operator CvSparseMat*() const;
 +
 +    //! returns type of the matrix elements
 +    int type() const;
 +    //! returns depth of the matrix elements
 +    int depth() const;
 +    //! returns the number of channels in each matrix element
 +    int channels() const;
 +
 +    //! equivalent to SparseMat::ref<_Tp>(i0, hashval)
 +    _Tp& ref(int i0, size_t* hashval=0);
 +    //! equivalent to SparseMat::ref<_Tp>(i0, i1, hashval)
 +    _Tp& ref(int i0, int i1, size_t* hashval=0);
 +    //! equivalent to SparseMat::ref<_Tp>(i0, i1, i2, hashval)
 +    _Tp& ref(int i0, int i1, int i2, size_t* hashval=0);
 +    //! equivalent to SparseMat::ref<_Tp>(idx, hashval)
 +    _Tp& ref(const int* idx, size_t* hashval=0);
 +
 +    //! equivalent to SparseMat::value<_Tp>(i0, hashval)
 +    _Tp operator()(int i0, size_t* hashval=0) const;
 +    //! equivalent to SparseMat::value<_Tp>(i0, i1, hashval)
 +    _Tp operator()(int i0, int i1, size_t* hashval=0) const;
 +    //! equivalent to SparseMat::value<_Tp>(i0, i1, i2, hashval)
 +    _Tp operator()(int i0, int i1, int i2, size_t* hashval=0) const;
 +    //! equivalent to SparseMat::value<_Tp>(idx, hashval)
 +    _Tp operator()(const int* idx, size_t* hashval=0) const;
 +
 +    //! returns sparse matrix iterator pointing to the first sparse matrix element
 +    SparseMatIterator_<_Tp> begin();
 +    //! returns read-only sparse matrix iterator pointing to the first sparse matrix element
 +    SparseMatConstIterator_<_Tp> begin() const;
 +    //! returns sparse matrix iterator pointing to the element following the last sparse matrix element
 +    SparseMatIterator_<_Tp> end();
 +    //! returns read-only sparse matrix iterator pointing to the element following the last sparse matrix element
 +    SparseMatConstIterator_<_Tp> end() const;
 +};
  
 -template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::operator = (const _Tp& s)
 -{
 -    typedef typename DataType<_Tp>::vec_type VT;
 -    Mat::operator=(Scalar((const VT&)s));
 -    return *this;
 -}
  
 -template<typename _Tp> inline void Mat_<_Tp>::create(int _rows, int _cols)
 -{
 -    Mat::create(_rows, _cols, DataType<_Tp>::type);
 -}
  
 -template<typename _Tp> inline void Mat_<_Tp>::create(Size _sz)
 -{
 -    Mat::create(_sz, DataType<_Tp>::type);
 -}
 +////////////////////////////////// MatConstIterator //////////////////////////////////
  
 -template<typename _Tp> inline void Mat_<_Tp>::create(int _dims, const int* _sz)
 +class CV_EXPORTS MatConstIterator
  {
 -    Mat::create(_dims, _sz, DataType<_Tp>::type);
 -}
 +public:
 +    typedef uchar* value_type;
 +    typedef ptrdiff_t difference_type;
 +    typedef const uchar** pointer;
 +    typedef uchar* reference;
  
 +#ifndef OPENCV_NOSTL
 +    typedef std::random_access_iterator_tag iterator_category;
 +#endif
  
 -template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::cross(const Mat_& m) const
 -{ return Mat_<_Tp>(Mat::cross(m)); }
 +    //! default constructor
 +    MatConstIterator();
 +    //! constructor that sets the iterator to the beginning of the matrix
 +    MatConstIterator(const Mat* _m);
 +    //! constructor that sets the iterator to the specified element of the matrix
 +    MatConstIterator(const Mat* _m, int _row, int _col=0);
 +    //! constructor that sets the iterator to the specified element of the matrix
 +    MatConstIterator(const Mat* _m, Point _pt);
 +    //! constructor that sets the iterator to the specified element of the matrix
 +    MatConstIterator(const Mat* _m, const int* _idx);
 +    //! copy constructor
 +    MatConstIterator(const MatConstIterator& it);
 +
 +    //! copy operator
 +    MatConstIterator& operator = (const MatConstIterator& it);
 +    //! returns the current matrix element
 +    uchar* operator *() const;
 +    //! returns the i-th matrix element, relative to the current
 +    uchar* operator [](ptrdiff_t i) const;
 +
 +    //! shifts the iterator forward by the specified number of elements
 +    MatConstIterator& operator += (ptrdiff_t ofs);
 +    //! shifts the iterator backward by the specified number of elements
 +    MatConstIterator& operator -= (ptrdiff_t ofs);
 +    //! decrements the iterator
 +    MatConstIterator& operator --();
 +    //! decrements the iterator
 +    MatConstIterator operator --(int);
 +    //! increments the iterator
 +    MatConstIterator& operator ++();
 +    //! increments the iterator
 +    MatConstIterator operator ++(int);
 +    //! returns the current iterator position
 +    Point pos() const;
 +    //! returns the current iterator position
 +    void pos(int* _idx) const;
 +
 +    ptrdiff_t lpos() const;
 +    void seek(ptrdiff_t ofs, bool relative = false);
 +    void seek(const int* _idx, bool relative = false);
 +
 +    const Mat* m;
 +    size_t elemSize;
 +    uchar* ptr;
 +    uchar* sliceStart;
 +    uchar* sliceEnd;
 +};
  
 -template<typename _Tp> template<typename T2> inline Mat_<_Tp>::operator Mat_<T2>() const
 -{ return Mat_<T2>(*this); }
  
 -template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::row(int y) const
 -{ return Mat_(*this, Range(y, y+1), Range::all()); }
 -template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::col(int x) const
 -{ return Mat_(*this, Range::all(), Range(x, x+1)); }
 -template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::diag(int d) const
 -{ return Mat_(Mat::diag(d)); }
 -template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::clone() const
 -{ return Mat_(Mat::clone()); }
  
 -template<typename _Tp> inline size_t Mat_<_Tp>::elemSize() const
 -{
 -    CV_DbgAssert( Mat::elemSize() == sizeof(_Tp) );
 -    return sizeof(_Tp);
 -}
 +////////////////////////////////// MatConstIterator_ /////////////////////////////////
  
 -template<typename _Tp> inline size_t Mat_<_Tp>::elemSize1() const
 +/*!
 + Matrix read-only iterator
 + */
 +template<typename _Tp>
 +class MatConstIterator_ : public MatConstIterator
  {
 -    CV_DbgAssert( Mat::elemSize1() == sizeof(_Tp)/DataType<_Tp>::channels );
 -    return sizeof(_Tp)/DataType<_Tp>::channels;
 -}
 -template<typename _Tp> inline int Mat_<_Tp>::type() const
 -{
 -    CV_DbgAssert( Mat::type() == DataType<_Tp>::type );
 -    return DataType<_Tp>::type;
 -}
 -template<typename _Tp> inline int Mat_<_Tp>::depth() const
 -{
 -    CV_DbgAssert( Mat::depth() == DataType<_Tp>::depth );
 -    return DataType<_Tp>::depth;
 -}
 -template<typename _Tp> inline int Mat_<_Tp>::channels() const
 -{
 -    CV_DbgAssert( Mat::channels() == DataType<_Tp>::channels );
 -    return DataType<_Tp>::channels;
 -}
 -template<typename _Tp> inline size_t Mat_<_Tp>::stepT(int i) const { return step.p[i]/elemSize(); }
 -template<typename _Tp> inline size_t Mat_<_Tp>::step1(int i) const { return step.p[i]/elemSize1(); }
 +public:
 +    typedef _Tp value_type;
 +    typedef ptrdiff_t difference_type;
 +    typedef const _Tp* pointer;
 +    typedef const _Tp& reference;
  
 -template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::adjustROI( int dtop, int dbottom, int dleft, int dright )
 -{ return (Mat_<_Tp>&)(Mat::adjustROI(dtop, dbottom, dleft, dright));  }
 +#ifndef OPENCV_NOSTL
 +    typedef std::random_access_iterator_tag iterator_category;
 +#endif
  
 -template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range& _rowRange, const Range& _colRange ) const
 -{ return Mat_<_Tp>(*this, _rowRange, _colRange); }
 +    //! default constructor
 +    MatConstIterator_();
 +    //! constructor that sets the iterator to the beginning of the matrix
 +    MatConstIterator_(const Mat_<_Tp>* _m);
 +    //! constructor that sets the iterator to the specified element of the matrix
 +    MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col=0);
 +    //! constructor that sets the iterator to the specified element of the matrix
 +    MatConstIterator_(const Mat_<_Tp>* _m, Point _pt);
 +    //! constructor that sets the iterator to the specified element of the matrix
 +    MatConstIterator_(const Mat_<_Tp>* _m, const int* _idx);
 +    //! copy constructor
 +    MatConstIterator_(const MatConstIterator_& it);
 +
 +    //! copy operator
 +    MatConstIterator_& operator = (const MatConstIterator_& it);
 +    //! returns the current matrix element
 +    _Tp operator *() const;
 +    //! returns the i-th matrix element, relative to the current
 +    _Tp operator [](ptrdiff_t i) const;
 +
 +    //! shifts the iterator forward by the specified number of elements
 +    MatConstIterator_& operator += (ptrdiff_t ofs);
 +    //! shifts the iterator backward by the specified number of elements
 +    MatConstIterator_& operator -= (ptrdiff_t ofs);
 +    //! decrements the iterator
 +    MatConstIterator_& operator --();
 +    //! decrements the iterator
 +    MatConstIterator_ operator --(int);
 +    //! increments the iterator
 +    MatConstIterator_& operator ++();
 +    //! increments the iterator
 +    MatConstIterator_ operator ++(int);
 +    //! returns the current iterator position
 +    Point pos() const;
 +};
  
 -template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::operator()( const Rect& roi ) const
 -{ return Mat_<_Tp>(*this, roi); }
  
 -template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range* ranges ) const
 -{ return Mat_<_Tp>(*this, ranges); }
  
 -template<typename _Tp> inline _Tp* Mat_<_Tp>::operator [](int y)
 -{ return (_Tp*)ptr(y); }
 -template<typename _Tp> inline const _Tp* Mat_<_Tp>::operator [](int y) const
 -{ return (const _Tp*)ptr(y); }
 +//////////////////////////////////// MatIterator_ ////////////////////////////////////
  
 -template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1)
 -{
 -    CV_DbgAssert( dims <= 2 && data &&
 -                  (unsigned)i0 < (unsigned)size.p[0] &&
 -                  (unsigned)i1 < (unsigned)size.p[1] &&
 -                  type() == DataType<_Tp>::type );
 -    return ((_Tp*)(data + step.p[0]*i0))[i1];
 -}
 -
 -template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(int i0, int i1) const
 -{
 -    CV_DbgAssert( dims <= 2 && data &&
 -                  (unsigned)i0 < (unsigned)size.p[0] &&
 -                  (unsigned)i1 < (unsigned)size.p[1] &&
 -                  type() == DataType<_Tp>::type );
 -    return ((const _Tp*)(data + step.p[0]*i0))[i1];
 -}
 -
 -template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(Point pt)
 +/*!
 + Matrix read-write iterator
 +*/
 +template<typename _Tp>
 +class MatIterator_ : public MatConstIterator_<_Tp>
  {
 -    CV_DbgAssert( dims <= 2 && data &&
 -                  (unsigned)pt.y < (unsigned)size.p[0] &&
 -                  (unsigned)pt.x < (unsigned)size.p[1] &&
 -                  type() == DataType<_Tp>::type );
 -    return ((_Tp*)(data + step.p[0]*pt.y))[pt.x];
 -}
 -
 -template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(Point pt) const
 -{
 -    CV_DbgAssert( dims <= 2 && data &&
 -                  (unsigned)pt.y < (unsigned)size.p[0] &&
 -                  (unsigned)pt.x < (unsigned)size.p[1] &&
 -                 type() == DataType<_Tp>::type );
 -    return ((const _Tp*)(data + step.p[0]*pt.y))[pt.x];
 -}
 -
 -template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(const int* idx)
 -{
 -    return Mat::at<_Tp>(idx);
 -}
 +public:
 +    typedef _Tp* pointer;
 +    typedef _Tp& reference;
  
 -template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(const int* idx) const
 -{
 -    return Mat::at<_Tp>(idx);
 -}
 +#ifndef OPENCV_NOSTL
 +    typedef std::random_access_iterator_tag iterator_category;
 +#endif
  
 -template<typename _Tp> template<int n> inline _Tp& Mat_<_Tp>::operator ()(const Vec<int, n>& idx)
 -{
 -    return Mat::at<_Tp>(idx);
 -}
 +    //! the default constructor
 +    MatIterator_();
 +    //! constructor that sets the iterator to the beginning of the matrix
 +    MatIterator_(Mat_<_Tp>* _m);
 +    //! constructor that sets the iterator to the specified element of the matrix
 +    MatIterator_(Mat_<_Tp>* _m, int _row, int _col=0);
 +    //! constructor that sets the iterator to the specified element of the matrix
 +    MatIterator_(const Mat_<_Tp>* _m, Point _pt);
 +    //! constructor that sets the iterator to the specified element of the matrix
 +    MatIterator_(const Mat_<_Tp>* _m, const int* _idx);
 +    //! copy constructor
 +    MatIterator_(const MatIterator_& it);
 +    //! copy operator
 +    MatIterator_& operator = (const MatIterator_<_Tp>& it );
 +
 +    //! returns the current matrix element
 +    _Tp& operator *() const;
 +    //! returns the i-th matrix element, relative to the current
 +    _Tp& operator [](ptrdiff_t i) const;
 +
 +    //! shifts the iterator forward by the specified number of elements
 +    MatIterator_& operator += (ptrdiff_t ofs);
 +    //! shifts the iterator backward by the specified number of elements
 +    MatIterator_& operator -= (ptrdiff_t ofs);
 +    //! decrements the iterator
 +    MatIterator_& operator --();
 +    //! decrements the iterator
 +    MatIterator_ operator --(int);
 +    //! increments the iterator
 +    MatIterator_& operator ++();
 +    //! increments the iterator
 +    MatIterator_ operator ++(int);
 +};
  
 -template<typename _Tp> template<int n> inline const _Tp& Mat_<_Tp>::operator ()(const Vec<int, n>& idx) const
 -{
 -    return Mat::at<_Tp>(idx);
 -}
  
 -template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int i0)
 -{
 -    return this->at<_Tp>(i0);
 -}
  
 -template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(int i0) const
 -{
 -    return this->at<_Tp>(i0);
 -}
 +/////////////////////////////// SparseMatConstIterator ///////////////////////////////
  
 -template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2)
 -{
 -    return this->at<_Tp>(i0, i1, i2);
 -}
 +/*!
 + Read-Only Sparse Matrix Iterator.
 + Here is how to use the iterator to compute the sum of floating-point sparse matrix elements:
  
 -template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) const
 + \code
 + SparseMatConstIterator it = m.begin(), it_end = m.end();
 + double s = 0;
 + CV_Assert( m.type() == CV_32F );
 + for( ; it != it_end; ++it )
 +    s += it.value<float>();
 + \endcode
 +*/
 +class CV_EXPORTS SparseMatConstIterator
  {
 -    return this->at<_Tp>(i0, i1, i2);
 -}
 +public:
 +    //! the default constructor
 +    SparseMatConstIterator();
 +    //! the full constructor setting the iterator to the first sparse matrix element
 +    SparseMatConstIterator(const SparseMat* _m);
 +    //! the copy constructor
 +    SparseMatConstIterator(const SparseMatConstIterator& it);
 +
 +    //! the assignment operator
 +    SparseMatConstIterator& operator = (const SparseMatConstIterator& it);
 +
 +    //! template method returning the current matrix element
 +    template<typename _Tp> const _Tp& value() const;
 +    //! returns the current node of the sparse matrix. it.node->idx is the current element index
 +    const SparseMat::Node* node() const;
 +
 +    //! moves iterator to the previous element
 +    SparseMatConstIterator& operator --();
 +    //! moves iterator to the previous element
 +    SparseMatConstIterator operator --(int);
 +    //! moves iterator to the next element
 +    SparseMatConstIterator& operator ++();
 +    //! moves iterator to the next element
 +    SparseMatConstIterator operator ++(int);
 +
 +    //! moves iterator to the element after the last element
 +    void seekEnd();
 +
 +    const SparseMat* m;
 +    size_t hashidx;
 +    uchar* ptr;
 +};
  
  
 -template<typename _Tp> inline Mat_<_Tp>::operator vector<_Tp>() const
 -{
 -    vector<_Tp> v;
 -    copyTo(v);
 -    return v;
 -}
  
 -template<typename _Tp> template<int n> inline Mat_<_Tp>::operator Vec<typename DataType<_Tp>::channel_type, n>() const
 -{
 -    CV_Assert(n % DataType<_Tp>::channels == 0);
 -    return this->Mat::operator Vec<typename DataType<_Tp>::channel_type, n>();
 -}
 +////////////////////////////////// SparseMatIterator /////////////////////////////////
  
 -template<typename _Tp> template<int m, int n> inline Mat_<_Tp>::operator Matx<typename DataType<_Tp>::channel_type, m, n>() const
 -{
 -    CV_Assert(n % DataType<_Tp>::channels == 0);
 -    return this->Mat::operator Matx<typename DataType<_Tp>::channel_type, m, n>();
 -}
 +/*!
 + Read-write Sparse Matrix Iterator
  
 -template<typename T1, typename T2, typename Op> inline void
 -process( const Mat_<T1>& m1, Mat_<T2>& m2, Op op )
 + The class is similar to cv::SparseMatConstIterator,
 + but can be used for in-place modification of the matrix elements.
 +*/
 +class CV_EXPORTS SparseMatIterator : public SparseMatConstIterator
  {
 -    int y, x, rows = m1.rows, cols = m1.cols;
 +public:
 +    //! the default constructor
 +    SparseMatIterator();
 +    //! the full constructor setting the iterator to the first sparse matrix element
 +    SparseMatIterator(SparseMat* _m);
 +    //! the full constructor setting the iterator to the specified sparse matrix element
 +    SparseMatIterator(SparseMat* _m, const int* idx);
 +    //! the copy constructor
 +    SparseMatIterator(const SparseMatIterator& it);
 +
 +    //! the assignment operator
 +    SparseMatIterator& operator = (const SparseMatIterator& it);
 +    //! returns read-write reference to the current sparse matrix element
 +    template<typename _Tp> _Tp& value() const;
 +    //! returns pointer to the current sparse matrix node. it.node->idx is the index of the current element (do not modify it!)
 +    SparseMat::Node* node() const;
 +
 +    //! moves iterator to the next element
 +    SparseMatIterator& operator ++();
 +    //! moves iterator to the next element
 +    SparseMatIterator operator ++(int);
 +};
  
 -    CV_DbgAssert( m1.size() == m2.size() );
  
 -    for( y = 0; y < rows; y++ )
 -    {
 -        const T1* src = m1[y];
 -        T2* dst = m2[y];
  
 -        for( x = 0; x < cols; x++ )
 -            dst[x] = op(src[x]);
 -    }
 -}
 +/////////////////////////////// SparseMatConstIterator_ //////////////////////////////
  
 -template<typename T1, typename T2, typename T3, typename Op> inline void
 -process( const Mat_<T1>& m1, const Mat_<T2>& m2, Mat_<T3>& m3, Op op )
 -{
 -    int y, x, rows = m1.rows, cols = m1.cols;
 +/*!
 + Template Read-Only Sparse Matrix Iterator Class.
  
 -    CV_DbgAssert( m1.size() == m2.size() );
 + This is the derived from SparseMatConstIterator class that
 + introduces more convenient operator *() for accessing the current element.
 +*/
 +template<typename _Tp> class SparseMatConstIterator_ : public SparseMatConstIterator
 +{
 +public:
  
 -    for( y = 0; y < rows; y++ )
 -    {
 -        const T1* src1 = m1[y];
 -        const T2* src2 = m2[y];
 -        T3* dst = m3[y];
 +#ifndef OPENCV_NOSTL
 +    typedef std::forward_iterator_tag iterator_category;
 +#endif
  
 -        for( x = 0; x < cols; x++ )
 -            dst[x] = op( src1[x], src2[x] );
 -    }
 -}
 +    //! the default constructor
 +    SparseMatConstIterator_();
 +    //! the full constructor setting the iterator to the first sparse matrix element
 +    SparseMatConstIterator_(const SparseMat_<_Tp>* _m);
 +    SparseMatConstIterator_(const SparseMat* _m);
 +    //! the copy constructor
 +    SparseMatConstIterator_(const SparseMatConstIterator_& it);
 +
 +    //! the assignment operator
 +    SparseMatConstIterator_& operator = (const SparseMatConstIterator_& it);
 +    //! the element access operator
 +    const _Tp& operator *() const;
 +
 +    //! moves iterator to the next element
 +    SparseMatConstIterator_& operator ++();
 +    //! moves iterator to the next element
 +    SparseMatConstIterator_ operator ++(int);
 +};
  
  
 -/////////////////////////////// Input/Output Arrays /////////////////////////////////
  
 -template<typename _Tp> inline _InputArray::_InputArray(const vector<_Tp>& vec)
 -    : flags(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {}
 +///////////////////////////////// SparseMatIterator_ /////////////////////////////////
  
 -template<typename _Tp> inline _InputArray::_InputArray(const vector<vector<_Tp> >& vec)
 -    : flags(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {}
 +/*!
 + Template Read-Write Sparse Matrix Iterator Class.
  
 -template<typename _Tp> inline _InputArray::_InputArray(const vector<Mat_<_Tp> >& vec)
 -    : flags(FIXED_TYPE + STD_VECTOR_MAT + DataType<_Tp>::type), obj((void*)&vec) {}
 + This is the derived from cv::SparseMatConstIterator_ class that
 + introduces more convenient operator *() for accessing the current element.
 +*/
 +template<typename _Tp> class CV_EXPORTS SparseMatIterator_ : public SparseMatConstIterator_<_Tp>
 +{
 +public:
  
 -template<typename _Tp, int m, int n> inline _InputArray::_InputArray(const Matx<_Tp, m, n>& mtx)
 -    : flags(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type), obj((void*)&mtx), sz(n, m) {}
 +#ifndef OPENCV_NOSTL
 +    typedef std::forward_iterator_tag iterator_category;
 +#endif
  
 -template<typename _Tp> inline _InputArray::_InputArray(const _Tp* vec, int n)
 -    : flags(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type), obj((void*)vec), sz(n, 1) {}
 +    //! the default constructor
 +    SparseMatIterator_();
 +    //! the full constructor setting the iterator to the first sparse matrix element
 +    SparseMatIterator_(SparseMat_<_Tp>* _m);
 +    SparseMatIterator_(SparseMat* _m);
 +    //! the copy constructor
 +    SparseMatIterator_(const SparseMatIterator_& it);
 +
 +    //! the assignment operator
 +    SparseMatIterator_& operator = (const SparseMatIterator_& it);
 +    //! returns the reference to the current element
 +    _Tp& operator *() const;
 +
 +    //! moves the iterator to the next element
 +    SparseMatIterator_& operator ++();
 +    //! moves the iterator to the next element
 +    SparseMatIterator_ operator ++(int);
 +};
  
 -inline _InputArray::_InputArray(const Scalar& s)
 -    : flags(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F), obj((void*)&s), sz(1, 4) {}
  
 -template<typename _Tp> inline _InputArray::_InputArray(const Mat_<_Tp>& m)
 -    : flags(FIXED_TYPE + MAT + DataType<_Tp>::type), obj((void*)&m) {}
  
 -template<typename _Tp> inline _OutputArray::_OutputArray(vector<_Tp>& vec)
 -    : _InputArray(vec) {}
 -template<typename _Tp> inline _OutputArray::_OutputArray(vector<vector<_Tp> >& vec)
 -    : _InputArray(vec) {}
 -template<typename _Tp> inline _OutputArray::_OutputArray(vector<Mat_<_Tp> >& vec)
 -    : _InputArray(vec) {}
 -template<typename _Tp> inline _OutputArray::_OutputArray(Mat_<_Tp>& m)
 -    : _InputArray(m) {}
 -template<typename _Tp, int m, int n> inline _OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx)
 -    : _InputArray(mtx) {}
 -template<typename _Tp> inline _OutputArray::_OutputArray(_Tp* vec, int n)
 -    : _InputArray(vec, n) {}
 +/////////////////////////////////// NAryMatIterator //////////////////////////////////
 +
 +/*!
 + n-Dimensional Dense Matrix Iterator Class.
 +
 + The class cv::NAryMatIterator is used for iterating over one or more n-dimensional dense arrays (cv::Mat's).
 +
 + The iterator is completely different from cv::Mat_ and cv::SparseMat_ iterators.
 + It iterates through the slices (or planes), not the elements, where "slice" is a continuous part of the arrays.
 +
 + Here is the example on how the iterator can be used to normalize 3D histogram:
 +
 + \code
 + void normalizeColorHist(Mat& hist)
 + {
 + #if 1
 +     // intialize iterator (the style is different from STL).
 +     // after initialization the iterator will contain
 +     // the number of slices or planes
 +     // the iterator will go through
 +     Mat* arrays[] = { &hist, 0 };
 +     Mat planes[1];
 +     NAryMatIterator it(arrays, planes);
 +     double s = 0;
 +     // iterate through the matrix. on each iteration
 +     // it.planes[i] (of type Mat) will be set to the current plane of
 +     // i-th n-dim matrix passed to the iterator constructor.
 +     for(int p = 0; p < it.nplanes; p++, ++it)
 +        s += sum(it.planes[0])[0];
 +     it = NAryMatIterator(hist);
 +     s = 1./s;
 +     for(int p = 0; p < it.nplanes; p++, ++it)
 +        it.planes[0] *= s;
 + #elif 1
 +     // this is a shorter implementation of the above
 +     // using built-in operations on Mat
 +     double s = sum(hist)[0];
 +     hist.convertTo(hist, hist.type(), 1./s, 0);
 + #else
 +     // and this is even shorter one
 +     // (assuming that the histogram elements are non-negative)
 +     normalize(hist, hist, 1, 0, NORM_L1);
 + #endif
 + }
 + \endcode
 +
 + You can iterate through several matrices simultaneously as long as they have the same geometry
 + (dimensionality and all the dimension sizes are the same), which is useful for binary
 + and n-ary operations on such matrices. Just pass those matrices to cv::MatNDIterator.
 + Then, during the iteration it.planes[0], it.planes[1], ... will
 + be the slices of the corresponding matrices
 +*/
 +class CV_EXPORTS NAryMatIterator
 +{
 +public:
 +    //! the default constructor
 +    NAryMatIterator();
 +    //! the full constructor taking arbitrary number of n-dim matrices
 +    NAryMatIterator(const Mat** arrays, uchar** ptrs, int narrays=-1);
 +    //! the full constructor taking arbitrary number of n-dim matrices
 +    NAryMatIterator(const Mat** arrays, Mat* planes, int narrays=-1);
 +    //! the separate iterator initialization method
 +    void init(const Mat** arrays, Mat* planes, uchar** ptrs, int narrays=-1);
 +
 +    //! proceeds to the next plane of every iterated matrix
 +    NAryMatIterator& operator ++();
 +    //! proceeds to the next plane of every iterated matrix (postfix increment operator)
 +    NAryMatIterator operator ++(int);
 +
 +    //! the iterated arrays
 +    const Mat** arrays;
 +    //! the current planes
 +    Mat* planes;
 +    //! data pointers
 +    uchar** ptrs;
 +    //! the number of arrays
 +    int narrays;
 +    //! the number of hyper-planes that the iterator steps through
 +    size_t nplanes;
 +    //! the size of each segment (in elements)
 +    size_t size;
 +protected:
 +    int iterdepth;
 +    size_t idx;
 +};
  
 -template<typename _Tp> inline _OutputArray::_OutputArray(const vector<_Tp>& vec)
 -    : _InputArray(vec) {flags |= FIXED_SIZE;}
 -template<typename _Tp> inline _OutputArray::_OutputArray(const vector<vector<_Tp> >& vec)
 -    : _InputArray(vec) {flags |= FIXED_SIZE;}
 -template<typename _Tp> inline _OutputArray::_OutputArray(const vector<Mat_<_Tp> >& vec)
 -    : _InputArray(vec) {flags |= FIXED_SIZE;}
  
 -template<typename _Tp> inline _OutputArray::_OutputArray(const Mat_<_Tp>& m)
 -    : _InputArray(m) {flags |= FIXED_SIZE;}
 -template<typename _Tp, int m, int n> inline _OutputArray::_OutputArray(const Matx<_Tp, m, n>& mtx)
 -    : _InputArray(mtx) {}
 -template<typename _Tp> inline _OutputArray::_OutputArray(const _Tp* vec, int n)
 -    : _InputArray(vec, n) {}
  
 -//////////////////////////////////// Matrix Expressions /////////////////////////////////////////
 +///////////////////////////////// Matrix Expressions /////////////////////////////////
  
  class CV_EXPORTS MatOp
  {
index 6d3cd9b,0000000..c81efaf
mode 100644,000000..100644
--- /dev/null
@@@ -1,388 -1,0 +1,368 @@@
- #ifdef _OPENMP
- #  define HAVE_OPENMP
- #endif
- #ifdef __APPLE__
- #  define HAVE_GCD
- #endif
- #if defined _MSC_VER && _MSC_VER >= 1600
- #  define HAVE_CONCURRENCY
- #endif
- #if defined HAVE_TBB
- #  define CV_PARALLEL_FRAMEWORK "tbb"
- #elif defined HAVE_CSTRIPES
- #  define CV_PARALLEL_FRAMEWORK "cstripes"
- #elif defined HAVE_OPENMP
- #  define CV_PARALLEL_FRAMEWORK "openmp"
- #elif defined HAVE_GCD
- #  define CV_PARALLEL_FRAMEWORK "gcd"
- #elif defined HAVE_CONCURRENCY
- #  define CV_PARALLEL_FRAMEWORK "ms-concurrency"
- #endif
 +/*M///////////////////////////////////////////////////////////////////////////////////////
 +//
 +//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 +//
 +//  By downloading, copying, installing or using the software you agree to this license.
 +//  If you do not agree to this license, do not download, install,
 +//  copy or use the software.
 +//
 +//
 +//                          License Agreement
 +//                For Open Source Computer Vision Library
 +//
 +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
 +// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
 +// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
 +// Third party copyrights are property of their respective owners.
 +//
 +// Redistribution and use in source and binary forms, with or without modification,
 +// are permitted provided that the following conditions are met:
 +//
 +//   * Redistribution's of source code must retain the above copyright notice,
 +//     this list of conditions and the following disclaimer.
 +//
 +//   * Redistribution's in binary form must reproduce the above copyright notice,
 +//     this list of conditions and the following disclaimer in the documentation
 +//     and/or other materials provided with the distribution.
 +//
 +//   * The name of the copyright holders may not be used to endorse or promote products
 +//     derived from this software without specific prior written permission.
 +//
 +// This software is provided by the copyright holders and contributors "as is" and
 +// any express or implied warranties, including, but not limited to, the implied
 +// warranties of merchantability and fitness for a particular purpose are disclaimed.
 +// In no event shall the Intel Corporation or contributors be liable for any direct,
 +// indirect, incidental, special, exemplary, or consequential damages
 +// (including, but not limited to, procurement of substitute goods or services;
 +// loss of use, data, or profits; or business interruption) however caused
 +// and on any theory of liability, whether in contract, strict liability,
 +// or tort (including negligence or otherwise) arising in any way out of
 +// the use of this software, even if advised of the possibility of such damage.
 +//
 +//M*/
 +
 +#ifndef __OPENCV_CORE_PRIVATE_HPP__
 +#define __OPENCV_CORE_PRIVATE_HPP__
 +
 +#ifndef __OPENCV_BUILD
 +#  error this is a private header which should not be used from outside of the OpenCV library
 +#endif
 +
 +#include "opencv2/core.hpp"
 +#include "cvconfig.h"
 +
 +#ifdef HAVE_EIGEN
 +#  if defined __GNUC__ && defined __APPLE__
 +#    pragma GCC diagnostic ignored "-Wshadow"
 +#  endif
 +#  include <Eigen/Core>
 +#  include "opencv2/core/eigen.hpp"
 +#endif
 +
 +#ifdef HAVE_TBB
 +#  include "tbb/tbb_stddef.h"
 +#  if TBB_VERSION_MAJOR*100 + TBB_VERSION_MINOR >= 202
 +#    include "tbb/tbb.h"
 +#    include "tbb/task.h"
 +#    undef min
 +#    undef max
 +#  else
 +#    undef HAVE_TBB
 +#  endif
 +#endif
 +
 +namespace cv
 +{
 +#ifdef HAVE_TBB
 +
 +    typedef tbb::blocked_range<int> BlockedRange;
 +
 +    template<typename Body> static inline
 +    void parallel_for( const BlockedRange& range, const Body& body )
 +    {
 +        tbb::parallel_for(range, body);
 +    }
 +
 +    typedef tbb::split Split;
 +
 +    template<typename Body> static inline
 +    void parallel_reduce( const BlockedRange& range, Body& body )
 +    {
 +        tbb::parallel_reduce(range, body);
 +    }
 +
 +    typedef tbb::concurrent_vector<Rect> ConcurrentRectVector;
 +#else
 +    class BlockedRange
 +    {
 +    public:
 +        BlockedRange() : _begin(0), _end(0), _grainsize(0) {}
 +        BlockedRange(int b, int e, int g=1) : _begin(b), _end(e), _grainsize(g) {}
 +        int begin() const { return _begin; }
 +        int end() const { return _end; }
 +        int grainsize() const { return _grainsize; }
 +
 +    protected:
 +        int _begin, _end, _grainsize;
 +    };
 +
 +    template<typename Body> static inline
 +    void parallel_for( const BlockedRange& range, const Body& body )
 +    {
 +        body(range);
 +    }
 +    typedef std::vector<Rect> ConcurrentRectVector;
 +
 +    class Split {};
 +
 +    template<typename Body> static inline
 +    void parallel_reduce( const BlockedRange& range, Body& body )
 +    {
 +        body(range);
 +    }
 +#endif
++
++    // Returns a static string if there is a parallel framework,
++    // NULL otherwise.
++    CV_EXPORTS const char* currentParallelFramework();
 +} //namespace cv
 +
 +#define CV_INIT_ALGORITHM(classname, algname, memberinit) \
 +    static ::cv::Algorithm* create##classname##_hidden() \
 +    { \
 +        return new classname; \
 +    } \
 +    \
 +    static ::cv::AlgorithmInfo& classname##_info() \
 +    { \
 +        static ::cv::AlgorithmInfo classname##_info_var(algname, create##classname##_hidden); \
 +        return classname##_info_var; \
 +    } \
 +    \
 +    static ::cv::AlgorithmInfo& classname##_info_auto = classname##_info(); \
 +    \
 +    ::cv::AlgorithmInfo* classname::info() const \
 +    { \
 +        static volatile bool initialized = false; \
 +        \
 +        if( !initialized ) \
 +        { \
 +            initialized = true; \
 +            classname obj; \
 +            memberinit; \
 +        } \
 +        return &classname##_info(); \
 +    }
 +
 +
 +
 +/****************************************************************************************\
 +*                                  Common declarations                                   *
 +\****************************************************************************************/
 +
 +/* the alignment of all the allocated buffers */
 +#define  CV_MALLOC_ALIGN    16
 +
 +#ifdef __GNUC__
 +#  define CV_DECL_ALIGNED(x) __attribute__ ((aligned (x)))
 +#elif defined _MSC_VER
 +#  define CV_DECL_ALIGNED(x) __declspec(align(x))
 +#else
 +#  define CV_DECL_ALIGNED(x)
 +#endif
 +
 +/* IEEE754 constants and macros */
 +#define  CV_TOGGLE_FLT(x) ((x)^((int)(x) < 0 ? 0x7fffffff : 0))
 +#define  CV_TOGGLE_DBL(x) ((x)^((int64)(x) < 0 ? CV_BIG_INT(0x7fffffffffffffff) : 0))
 +
 +static inline void* cvAlignPtr( const void* ptr, int align = 32 )
 +{
 +    CV_DbgAssert ( (align & (align-1)) == 0 );
 +    return (void*)( ((size_t)ptr + align - 1) & ~(size_t)(align-1) );
 +}
 +
 +static inline int cvAlign( int size, int align )
 +{
 +    CV_DbgAssert( (align & (align-1)) == 0 && size < INT_MAX );
 +    return (size + align - 1) & -align;
 +}
 +
 +#ifdef IPL_DEPTH_8U
 +static inline cv::Size cvGetMatSize( const CvMat* mat )
 +{
 +    return cv::Size(mat->cols, mat->rows);
 +}
 +#endif
 +
 +namespace cv
 +{
 +CV_EXPORTS void scalarToRawData(const cv::Scalar& s, void* buf, int type, int unroll_to = 0);
 +}
 +
 +
 +/****************************************************************************************\
 +*                     Structures and macros for integration with IPP                     *
 +\****************************************************************************************/
 +
 +#ifdef HAVE_IPP
 +#  include "ipp.h"
 +
 +static inline IppiSize ippiSize(int width, int height)
 +{
 +    IppiSize size = { width, height };
 +    return size;
 +}
 +#endif
 +
 +#ifndef IPPI_CALL
 +#  define IPPI_CALL(func) CV_Assert((func) >= 0)
 +#endif
 +
 +/* IPP-compatible return codes */
 +typedef enum CvStatus
 +{
 +    CV_BADMEMBLOCK_ERR          = -113,
 +    CV_INPLACE_NOT_SUPPORTED_ERR= -112,
 +    CV_UNMATCHED_ROI_ERR        = -111,
 +    CV_NOTFOUND_ERR             = -110,
 +    CV_BADCONVERGENCE_ERR       = -109,
 +
 +    CV_BADDEPTH_ERR             = -107,
 +    CV_BADROI_ERR               = -106,
 +    CV_BADHEADER_ERR            = -105,
 +    CV_UNMATCHED_FORMATS_ERR    = -104,
 +    CV_UNSUPPORTED_COI_ERR      = -103,
 +    CV_UNSUPPORTED_CHANNELS_ERR = -102,
 +    CV_UNSUPPORTED_DEPTH_ERR    = -101,
 +    CV_UNSUPPORTED_FORMAT_ERR   = -100,
 +
 +    CV_BADARG_ERR               = -49,  //ipp comp
 +    CV_NOTDEFINED_ERR           = -48,  //ipp comp
 +
 +    CV_BADCHANNELS_ERR          = -47,  //ipp comp
 +    CV_BADRANGE_ERR             = -44,  //ipp comp
 +    CV_BADSTEP_ERR              = -29,  //ipp comp
 +
 +    CV_BADFLAG_ERR              =  -12,
 +    CV_DIV_BY_ZERO_ERR          =  -11, //ipp comp
 +    CV_BADCOEF_ERR              =  -10,
 +
 +    CV_BADFACTOR_ERR            =  -7,
 +    CV_BADPOINT_ERR             =  -6,
 +    CV_BADSCALE_ERR             =  -4,
 +    CV_OUTOFMEM_ERR             =  -3,
 +    CV_NULLPTR_ERR              =  -2,
 +    CV_BADSIZE_ERR              =  -1,
 +    CV_NO_ERR                   =   0,
 +    CV_OK                       =   CV_NO_ERR
 +}
 +CvStatus;
 +
 +
 +
 +/****************************************************************************************\
 +*                                  Auxiliary algorithms                                  *
 +\****************************************************************************************/
 +
 +namespace cv
 +{
 +
 +// This function splits the input sequence or set into one or more equivalence classes and
 +// returns the vector of labels - 0-based class indexes for each element.
 +// predicate(a,b) returns true if the two sequence elements certainly belong to the same class.
 +//
 +// The algorithm is described in "Introduction to Algorithms"
 +// by Cormen, Leiserson and Rivest, the chapter "Data structures for disjoint sets"
 +template<typename _Tp, class _EqPredicate> int
 +partition( const std::vector<_Tp>& _vec, std::vector<int>& labels,
 +           _EqPredicate predicate=_EqPredicate())
 +{
 +    int i, j, N = (int)_vec.size();
 +    const _Tp* vec = &_vec[0];
 +
 +    const int PARENT=0;
 +    const int RANK=1;
 +
 +    std::vector<int> _nodes(N*2);
 +    int (*nodes)[2] = (int(*)[2])&_nodes[0];
 +
 +    // The first O(N) pass: create N single-vertex trees
 +    for(i = 0; i < N; i++)
 +    {
 +        nodes[i][PARENT]=-1;
 +        nodes[i][RANK] = 0;
 +    }
 +
 +    // The main O(N^2) pass: merge connected components
 +    for( i = 0; i < N; i++ )
 +    {
 +        int root = i;
 +
 +        // find root
 +        while( nodes[root][PARENT] >= 0 )
 +            root = nodes[root][PARENT];
 +
 +        for( j = 0; j < N; j++ )
 +        {
 +            if( i == j || !predicate(vec[i], vec[j]))
 +                continue;
 +            int root2 = j;
 +
 +            while( nodes[root2][PARENT] >= 0 )
 +                root2 = nodes[root2][PARENT];
 +
 +            if( root2 != root )
 +            {
 +                // unite both trees
 +                int rank = nodes[root][RANK], rank2 = nodes[root2][RANK];
 +                if( rank > rank2 )
 +                    nodes[root2][PARENT] = root;
 +                else
 +                {
 +                    nodes[root][PARENT] = root2;
 +                    nodes[root2][RANK] += rank == rank2;
 +                    root = root2;
 +                }
 +                CV_Assert( nodes[root][PARENT] < 0 );
 +
 +                int k = j, parent;
 +
 +                // compress the path from node2 to root
 +                while( (parent = nodes[k][PARENT]) >= 0 )
 +                {
 +                    nodes[k][PARENT] = root;
 +                    k = parent;
 +                }
 +
 +                // compress the path from node to root
 +                k = i;
 +                while( (parent = nodes[k][PARENT]) >= 0 )
 +                {
 +                    nodes[k][PARENT] = root;
 +                    k = parent;
 +                }
 +            }
 +        }
 +    }
 +
 +    // Final O(N) pass: enumerate classes
 +    labels.resize(N);
 +    int nclasses = 0;
 +
 +    for( i = 0; i < N; i++ )
 +    {
 +        int root = i;
 +        while( nodes[root][PARENT] >= 0 )
 +            root = nodes[root][PARENT];
 +        // re-use the rank as the class label
 +        if( nodes[root][RANK] >= 0 )
 +            nodes[root][RANK] = ~nclasses++;
 +        labels[i] = ~nodes[root][RANK];
 +    }
 +
 +    return nclasses;
 +}
 +
 +} // namespace cv
 +
 +#endif // __OPENCV_CORE_PRIVATE_HPP__
Simple merge
@@@ -9,8 -9,17 +9,17 @@@ using std::tr1::make_tuple
  using std::tr1::get;
  
  
 -typedef perf::TestBaseWithParam<String> VideoCapture_Reading;
 +typedef perf::TestBaseWithParam<std::string> VideoCapture_Reading;
  
+ #if defined(HAVE_MSMF)
+ // MPEG2 is not supported by Media Foundation yet
+ // http://social.msdn.microsoft.com/Forums/en-US/mediafoundationdevelopment/thread/39a36231-8c01-40af-9af5-3c105d684429
+ PERF_TEST_P(VideoCapture_Reading, ReadFile, testing::Values( "highgui/video/big_buck_bunny.avi",
+                                                "highgui/video/big_buck_bunny.mov",
+                                                "highgui/video/big_buck_bunny.mp4",
+                                                "highgui/video/big_buck_bunny.wmv" ) )
+ #else
  PERF_TEST_P(VideoCapture_Reading, ReadFile, testing::Values( "highgui/video/big_buck_bunny.avi",
                                                 "highgui/video/big_buck_bunny.mov",
                                                 "highgui/video/big_buck_bunny.mp4",
@@@ -22,13 -22,19 +22,19 @@@ PERF_TEST_P(VideoWriter_Writing, WriteF
  {
    string filename = getDataPath(get<0>(GetParam()));
    bool isColor = get<1>(GetParam());
 -  VideoWriter writer(cv::tempfile(".wmv"), CV_FOURCC('W', 'M', 'V', '3'),
+   Mat image = imread(filename, 1);
+ #if defined(HAVE_MSMF) && !defined(HAVE_VFW) && !defined(HAVE_FFMPEG) // VFW has greater priority
 -  VideoWriter writer(cv::tempfile(".avi"), CV_FOURCC('X', 'V', 'I', 'D'),
++  VideoWriter writer(cv::tempfile(".wmv"), VideoWriter::fourcc('W', 'M', 'V', '3'),
+                             25, cv::Size(image.cols, image.rows), isColor);
+ #else
++  VideoWriter writer(cv::tempfile(".avi"), VideoWriter::fourcc('X', 'V', 'I', 'D'),
+                             25, cv::Size(image.cols, image.rows), isColor);
+ #endif
  
-   VideoWriter writer(cv::tempfile(".avi"), VideoWriter::fourcc('X', 'V', 'I', 'D'), 25, cv::Size(640, 480), isColor);
-   TEST_CYCLE() { Mat image = imread(filename, 1); writer << image; }
+   TEST_CYCLE() { image = imread(filename, 1); writer << image; }
  
    bool dummy = writer.isOpened();
    SANITY_CHECK(dummy);
  }
  
--#endif // BUILD_WITH_VIDEO_OUTPUT_SUPPORT
++#endif // BUILD_WITH_VIDEO_OUTPUT_SUPPORT
Simple merge
Simple merge
@@@ -209,15 -209,11 +209,11 @@@ CvCapture* cvCreateFileCapture_FFMPEG_p
      if( result->open( filename ))
          return result;
      delete result;
- #ifdef HAVE_VFW
-     return cvCreateFileCapture_VFW(filename);
- #else
      return 0;
- #endif
  }
  
 -class CvVideoWriter_FFMPEG_proxy : 
 -      public CvVideoWriter
 +class CvVideoWriter_FFMPEG_proxy :
 +    public CvVideoWriter
  {
  public:
      CvVideoWriter_FFMPEG_proxy() { ffmpegWriter = 0; }
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -54,19 -54,48 +54,48 @@@ string fourccToString(int fourcc
      return format("%c%c%c%c", fourcc & 255, (fourcc >> 8) & 255, (fourcc >> 16) & 255, (fourcc >> 24) & 255);
  }
  
+ #ifdef HAVE_MSMF
+ const VideoFormat g_specific_fmt_list[] =
+ {
+         /*VideoFormat("wmv", CV_FOURCC_MACRO('d', 'v', '2', '5')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('d', 'v', '5', '0')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('d', 'v', 'c', ' ')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('d', 'v', 'h', '1')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('d', 'v', 'h', 'd')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('d', 'v', 's', 'd')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('d', 'v', 's', 'l')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('H', '2', '6', '3')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('M', '4', 'S', '2')),
+         VideoFormat("avi", CV_FOURCC_MACRO('M', 'J', 'P', 'G')),
+         VideoFormat("mp4", CV_FOURCC_MACRO('M', 'P', '4', 'S')),
+         VideoFormat("mp4", CV_FOURCC_MACRO('M', 'P', '4', 'V')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('M', 'P', '4', '3')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('M', 'P', 'G', '1')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('M', 'S', 'S', '1')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('M', 'S', 'S', '2')),*/
+ #if !defined(_M_ARM)
+         VideoFormat("wmv", CV_FOURCC_MACRO('W', 'M', 'V', '1')),
+         VideoFormat("wmv", CV_FOURCC_MACRO('W', 'M', 'V', '2')),
+ #endif
+         VideoFormat("wmv", CV_FOURCC_MACRO('W', 'M', 'V', '3')),
+         VideoFormat("avi", CV_FOURCC_MACRO('H', '2', '6', '4')),
+         //VideoFormat("wmv", CV_FOURCC_MACRO('W', 'V', 'C', '1')),
+         VideoFormat()
+ };
+ #else
  const VideoFormat g_specific_fmt_list[] =
  {
 -    VideoFormat("avi", CV_FOURCC('X', 'V', 'I', 'D')),
 -    VideoFormat("avi", CV_FOURCC('M', 'P', 'E', 'G')),
 -    VideoFormat("avi", CV_FOURCC('M', 'J', 'P', 'G')),
 -    //VideoFormat("avi", CV_FOURCC('I', 'Y', 'U', 'V')),
 -    VideoFormat("mkv", CV_FOURCC('X', 'V', 'I', 'D')),
 -    VideoFormat("mkv", CV_FOURCC('M', 'P', 'E', 'G')),
 -    VideoFormat("mkv", CV_FOURCC('M', 'J', 'P', 'G')),
 -    VideoFormat("mov", CV_FOURCC('m', 'p', '4', 'v')),
 +    VideoFormat("avi", VideoWriter::fourcc('X', 'V', 'I', 'D')),
 +    VideoFormat("avi", VideoWriter::fourcc('M', 'P', 'E', 'G')),
 +    VideoFormat("avi", VideoWriter::fourcc('M', 'J', 'P', 'G')),
 +    //VideoFormat("avi", VideoWriter::fourcc('I', 'Y', 'U', 'V')),
 +    VideoFormat("mkv", VideoWriter::fourcc('X', 'V', 'I', 'D')),
 +    VideoFormat("mkv", VideoWriter::fourcc('M', 'P', 'E', 'G')),
 +    VideoFormat("mkv", VideoWriter::fourcc('M', 'J', 'P', 'G')),
 +    VideoFormat("mov", VideoWriter::fourcc('m', 'p', '4', 'v')),
      VideoFormat()
  };
+ #endif
  
  }
  
@@@ -247,14 -276,14 +276,14 @@@ void CV_HighGuiTest::VideoTest(const st
          if (!img)
              break;
  
 -        frames.push_back(Mat(img).clone());
 +        frames.push_back(cv::cvarrToMat(img, true));
  
-         if (writer == 0)
+         if (writer == NULL)
          {
              writer = cvCreateVideoWriter(tmp_name.c_str(), fmt.fourcc, 24, cvGetSize(img));
-             if (writer == 0)
+             if (writer == NULL)
              {
-                 ts->printf(ts->LOG, "can't create writer (with fourcc : %d)\n",
+                 ts->printf(ts->LOG, "can't create writer (with fourcc : %s)\n",
                             cvtest::fourccToString(fmt.fourcc).c_str());
                  cvReleaseCapture( &cap );
                  ts->set_failed_test_info(ts->FAIL_MISMATCH);
Simple merge
index a59aae1,0000000..3da9352
mode 100644,000000..100644
--- /dev/null
@@@ -1,1795 -1,0 +1,1819 @@@
-         // compiled OpenCL program to be cached to the path automatically as "path/*.clb" 
-         // binary file, which will be reused when the OpenCV executable is started again. 
 +/*M///////////////////////////////////////////////////////////////////////////////////////
 +//
 +//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 +//
 +//  By downloading, copying, installing or using the software you agree to this license.
 +//  If you do not agree to this license, do not download, install,
 +//  copy or use the software.
 +//
 +//
 +//                           License Agreement
 +//                For Open Source Computer Vision Library
 +//
 +// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
 +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
 +// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
 +// Third party copyrights are property of their respective owners.
 +//
 +// Redistribution and use in source and binary forms, with or without modification,
 +// are permitted provided that the following conditions are met:
 +//
 +//   * Redistribution's of source code must retain the above copyright notice,
 +//     this list of conditions and the following disclaimer.
 +//
 +//   * Redistribution's in binary form must reproduce the above copyright notice,
 +//     this list of conditions and the following disclaimer in the documentation
 +//     and/or other oclMaterials provided with the distribution.
 +//
 +//   * The name of the copyright holders may not be used to endorse or promote products
 +//     derived from this software without specific prior written permission.
 +//
 +// This software is provided by the copyright holders and contributors "as is" and
 +// any express or implied warranties, including, but not limited to, the implied
 +// warranties of merchantability and fitness for a particular purpose are disclaimed.
 +// In no event shall the Intel Corporation or contributors be liable for any direct,
 +// indirect, incidental, special, exemplary, or consequential damages
 +// (including, but not limited to, procurement of substitute goods or services;
 +// loss of use, data, or profits; or business interruption) however caused
 +// and on any theory of liability, whether in contract, strict liability,
 +// or tort (including negligence or otherwise) arising in any way out of
 +// the use of this software, even if advised of the possibility of such damage.
 +//
 +//M*/
 +
 +#ifndef __OPENCV_OCL_HPP__
 +#define __OPENCV_OCL_HPP__
 +
 +#include <memory>
 +#include <vector>
 +
 +#include "opencv2/core.hpp"
 +#include "opencv2/imgproc.hpp"
 +#include "opencv2/objdetect.hpp"
 +
 +namespace cv
 +{
 +    namespace ocl
 +    {
 +        enum
 +        {
 +            CVCL_DEVICE_TYPE_DEFAULT     = (1 << 0),
 +            CVCL_DEVICE_TYPE_CPU         = (1 << 1),
 +            CVCL_DEVICE_TYPE_GPU         = (1 << 2),
 +            CVCL_DEVICE_TYPE_ACCELERATOR = (1 << 3),
 +            //CVCL_DEVICE_TYPE_CUSTOM      = (1 << 4)
 +            CVCL_DEVICE_TYPE_ALL         = 0xFFFFFFFF
 +        };
 +
 +        enum DevMemRW
 +        {
 +            DEVICE_MEM_R_W = 0,
 +            DEVICE_MEM_R_ONLY,
 +            DEVICE_MEM_W_ONLY
 +        };
 +
 +        enum DevMemType
 +        {
 +            DEVICE_MEM_DEFAULT = 0,
 +            DEVICE_MEM_AHP,         //alloc host pointer
 +            DEVICE_MEM_UHP,         //use host pointer
 +            DEVICE_MEM_CHP,         //copy host pointer
 +            DEVICE_MEM_PM           //persistent memory
 +        };
 +
 +        //Get the global device memory and read/write type
 +        //return 1 if unified memory system supported, otherwise return 0
 +        CV_EXPORTS int getDevMemType(DevMemRW& rw_type, DevMemType& mem_type);
 +
 +        //Set the global device memory and read/write type,
 +        //the newly generated oclMat will all use this type
 +        //return -1 if the target type is unsupported, otherwise return 0
 +        CV_EXPORTS int setDevMemType(DevMemRW rw_type = DEVICE_MEM_R_W, DevMemType mem_type = DEVICE_MEM_DEFAULT);
 +
 +        //this class contains ocl runtime information
 +        class CV_EXPORTS Info
 +        {
 +        public:
 +            struct Impl;
 +            Impl *impl;
 +
 +            Info();
 +            Info(const Info &m);
 +            ~Info();
 +            void release();
 +            Info &operator = (const Info &m);
 +            std::vector<String> DeviceName;
 +            String PlatformName;
 +        };
 +        //////////////////////////////// Initialization & Info ////////////////////////
 +        //this function may be obsoleted
 +        //CV_EXPORTS cl_device_id getDevice();
 +        //the function must be called before any other cv::ocl::functions, it initialize ocl runtime
 +        //each Info relates to an OpenCL platform
 +        //there is one or more devices in each platform, each one has a separate name
 +        CV_EXPORTS int getDevice(std::vector<Info> &oclinfo, int devicetype = CVCL_DEVICE_TYPE_GPU);
 +
 +        //set device you want to use, optional function after getDevice be called
 +        //the devnum is the index of the selected device in DeviceName vector of INfo
 +        CV_EXPORTS void setDevice(Info &oclinfo, int devnum = 0);
 +
 +        //The two functions below enable other opencl program to use ocl module's cl_context and cl_command_queue
 +        //returns cl_context *
 +        CV_EXPORTS void* getoclContext();
 +        //returns cl_command_queue *
 +        CV_EXPORTS void* getoclCommandQueue();
 +
 +        //explicit call clFinish. The global command queue will be used.
 +        CV_EXPORTS void finish();
 +
 +        //this function enable ocl module to use customized cl_context and cl_command_queue
 +        //getDevice also need to be called before this function
 +        CV_EXPORTS void setDeviceEx(Info &oclinfo, void *ctx, void *qu, int devnum = 0);
 +
 +        //returns true when global OpenCL context is initialized
 +        CV_EXPORTS bool initialized();
 +
 +        //////////////////////////////// OpenCL context ////////////////////////
 +        //This is a global singleton class used to represent a OpenCL context.
 +        class CV_EXPORTS Context
 +        {
 +        protected:
 +            Context();
 +            friend class std::auto_ptr<Context>;
 +            friend bool initialized();
 +        private:
 +            static std::auto_ptr<Context> clCxt;
 +            static int val;
 +        public:
 +            ~Context();
 +            void release();
 +            Info::Impl* impl;
 +
 +            static Context *getContext();
 +            static void setContext(Info &oclinfo);
 +
 +            enum {CL_DOUBLE, CL_UNIFIED_MEM, CL_VER_1_2};
 +            bool supportsFeature(int ftype);
 +            size_t computeUnits();
 +            size_t maxWorkGroupSize();
 +            void* oclContext();
 +            void* oclCommandQueue();
 +        };
 +
 +        //! Calls a kernel, by string. Pass globalThreads = NULL, and cleanUp = true, to finally clean-up without executing.
 +        CV_EXPORTS double openCLExecuteKernelInterop(Context *clCxt ,
 +                                                        const char **source, String kernelName,
 +                                                        size_t globalThreads[3], size_t localThreads[3],
 +                                                        std::vector< std::pair<size_t, const void *> > &args,
 +                                                        int channels, int depth, const char *build_options,
 +                                                        bool finish = true, bool measureKernelTime = false,
 +                                                        bool cleanUp = true);
 +
 +        //! Calls a kernel, by file. Pass globalThreads = NULL, and cleanUp = true, to finally clean-up without executing.
 +        CV_EXPORTS double openCLExecuteKernelInterop(Context *clCxt ,
 +                                                        const char **fileName, const int numFiles, String kernelName,
 +                                                        size_t globalThreads[3], size_t localThreads[3],
 +                                                        std::vector< std::pair<size_t, const void *> > &args,
 +                                                        int channels, int depth, const char *build_options,
 +                                                        bool finish = true, bool measureKernelTime = false,
 +                                                        bool cleanUp = true);
 +
 +        //! Enable or disable OpenCL program binary caching onto local disk
 +        // After a program (*.cl files in opencl/ folder) is built at runtime, we allow the
-         //! set where binary cache to be saved to 
++        // compiled OpenCL program to be cached to the path automatically as "path/*.clb"
++        // binary file, which will be reused when the OpenCV executable is started again.
 +        //
 +        // Caching mode is controlled by the following enums
 +        // Notes
 +        //   1. the feature is by default enabled when OpenCV is built in release mode.
 +        //   2. the CACHE_DEBUG / CACHE_RELEASE flags only effectively work with MSVC compiler;
 +        //      for GNU compilers, the function always treats the build as release mode (enabled by default).
 +        enum
 +        {
 +            CACHE_NONE    = 0,        // do not cache OpenCL binary
 +            CACHE_DEBUG   = 0x1 << 0, // cache OpenCL binary when built in debug mode (only work with MSVC)
 +            CACHE_RELEASE = 0x1 << 1, // default behavior, only cache when built in release mode (only work with MSVC)
 +            CACHE_ALL     = CACHE_DEBUG | CACHE_RELEASE, // always cache opencl binary
 +            CACHE_UPDATE  = 0x1 << 2  // if the binary cache file with the same name is already on the disk, it will be updated.
 +        };
 +        CV_EXPORTS void setBinaryDiskCache(int mode = CACHE_RELEASE, cv::String path = "./");
 +
-         
-         //! only 8UC1 is supported now
-         class CV_EXPORTS CLAHE
-         {
-         public:
-             virtual void apply(const oclMat &src, oclMat &dst) = 0;
++        //! set where binary cache to be saved to
 +        CV_EXPORTS void setBinpath(const char *path);
 +
 +        class CV_EXPORTS oclMatExpr;
 +        //////////////////////////////// oclMat ////////////////////////////////
 +        class CV_EXPORTS oclMat
 +        {
 +        public:
 +            //! default constructor
 +            oclMat();
 +            //! constructs oclMatrix of the specified size and type (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
 +            oclMat(int rows, int cols, int type);
 +            oclMat(Size size, int type);
 +            //! constucts oclMatrix and fills it with the specified value _s.
 +            oclMat(int rows, int cols, int type, const Scalar &s);
 +            oclMat(Size size, int type, const Scalar &s);
 +            //! copy constructor
 +            oclMat(const oclMat &m);
 +
 +            //! constructor for oclMatrix headers pointing to user-allocated data
 +            oclMat(int rows, int cols, int type, void *data, size_t step = Mat::AUTO_STEP);
 +            oclMat(Size size, int type, void *data, size_t step = Mat::AUTO_STEP);
 +
 +            //! creates a matrix header for a part of the bigger matrix
 +            oclMat(const oclMat &m, const Range &rowRange, const Range &colRange);
 +            oclMat(const oclMat &m, const Rect &roi);
 +
 +            //! builds oclMat from Mat. Perfom blocking upload to device.
 +            explicit oclMat (const Mat &m);
 +
 +            //! destructor - calls release()
 +            ~oclMat();
 +
 +            //! assignment operators
 +            oclMat &operator = (const oclMat &m);
 +            //! assignment operator. Perfom blocking upload to device.
 +            oclMat &operator = (const Mat &m);
 +            oclMat &operator = (const oclMatExpr& expr);
 +
 +            //! pefroms blocking upload data to oclMat.
 +            void upload(const cv::Mat &m);
 +
 +
 +            //! downloads data from device to host memory. Blocking calls.
 +            operator Mat() const;
 +            void download(cv::Mat &m) const;
 +
 +            //! convert to _InputArray
 +            operator _InputArray();
 +
 +            //! convert to _OutputArray
 +            operator _OutputArray();
 +
 +            //! returns a new oclMatrix header for the specified row
 +            oclMat row(int y) const;
 +            //! returns a new oclMatrix header for the specified column
 +            oclMat col(int x) const;
 +            //! ... for the specified row span
 +            oclMat rowRange(int startrow, int endrow) const;
 +            oclMat rowRange(const Range &r) const;
 +            //! ... for the specified column span
 +            oclMat colRange(int startcol, int endcol) const;
 +            oclMat colRange(const Range &r) const;
 +
 +            //! returns deep copy of the oclMatrix, i.e. the data is copied
 +            oclMat clone() const;
 +            //! copies the oclMatrix content to "m".
 +            // It calls m.create(this->size(), this->type()).
 +            // It supports any data type
 +            void copyTo( oclMat &m ) const;
 +            //! copies those oclMatrix elements to "m" that are marked with non-zero mask elements.
 +            //It supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4
 +            void copyTo( oclMat &m, const oclMat &mask ) const;
 +            //! converts oclMatrix to another datatype with optional scalng. See cvConvertScale.
 +            //It supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4
 +            void convertTo( oclMat &m, int rtype, double alpha = 1, double beta = 0 ) const;
 +
 +            void assignTo( oclMat &m, int type = -1 ) const;
 +
 +            //! sets every oclMatrix element to s
 +            //It supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4
 +            oclMat& operator = (const Scalar &s);
 +            //! sets some of the oclMatrix elements to s, according to the mask
 +            //It supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4
 +            oclMat& setTo(const Scalar &s, const oclMat &mask = oclMat());
 +            //! creates alternative oclMatrix header for the same data, with different
 +            // number of channels and/or different number of rows. see cvReshape.
 +            oclMat reshape(int cn, int rows = 0) const;
 +
 +            //! allocates new oclMatrix data unless the oclMatrix already has specified size and type.
 +            // previous data is unreferenced if needed.
 +            void create(int rows, int cols, int type);
 +            void create(Size size, int type);
 +
 +            //! allocates new oclMatrix with specified device memory type.
 +            void createEx(int rows, int cols, int type,
 +                          DevMemRW rw_type, DevMemType mem_type, void* hptr = 0);
 +            void createEx(Size size, int type, DevMemRW rw_type,
 +                          DevMemType mem_type, void* hptr = 0);
 +
 +            //! decreases reference counter;
 +            // deallocate the data when reference counter reaches 0.
 +            void release();
 +
 +            //! swaps with other smart pointer
 +            void swap(oclMat &mat);
 +
 +            //! locates oclMatrix header within a parent oclMatrix. See below
 +            void locateROI( Size &wholeSize, Point &ofs ) const;
 +            //! moves/resizes the current oclMatrix ROI inside the parent oclMatrix.
 +            oclMat& adjustROI( int dtop, int dbottom, int dleft, int dright );
 +            //! extracts a rectangular sub-oclMatrix
 +            // (this is a generalized form of row, rowRange etc.)
 +            oclMat operator()( Range rowRange, Range colRange ) const;
 +            oclMat operator()( const Rect &roi ) const;
 +
 +            oclMat& operator+=( const oclMat& m );
 +            oclMat& operator-=( const oclMat& m );
 +            oclMat& operator*=( const oclMat& m );
 +            oclMat& operator/=( const oclMat& m );
 +
 +            //! returns true if the oclMatrix data is continuous
 +            // (i.e. when there are no gaps between successive rows).
 +            // similar to CV_IS_oclMat_CONT(cvoclMat->type)
 +            bool isContinuous() const;
 +            //! returns element size in bytes,
 +            // similar to CV_ELEM_SIZE(cvMat->type)
 +            size_t elemSize() const;
 +            //! returns the size of element channel in bytes.
 +            size_t elemSize1() const;
 +            //! returns element type, similar to CV_MAT_TYPE(cvMat->type)
 +            int type() const;
 +            //! returns element type, i.e. 8UC3 returns 8UC4 because in ocl
 +            //! 3 channels element actually use 4 channel space
 +            int ocltype() const;
 +            //! returns element type, similar to CV_MAT_DEPTH(cvMat->type)
 +            int depth() const;
 +            //! returns element type, similar to CV_MAT_CN(cvMat->type)
 +            int channels() const;
 +            //! returns element type, return 4 for 3 channels element,
 +            //!becuase 3 channels element actually use 4 channel space
 +            int oclchannels() const;
 +            //! returns step/elemSize1()
 +            size_t step1() const;
 +            //! returns oclMatrix size:
 +            // width == number of columns, height == number of rows
 +            Size size() const;
 +            //! returns true if oclMatrix data is NULL
 +            bool empty() const;
 +
 +            //! returns pointer to y-th row
 +            uchar* ptr(int y = 0);
 +            const uchar *ptr(int y = 0) const;
 +
 +            //! template version of the above method
 +            template<typename _Tp> _Tp *ptr(int y = 0);
 +            template<typename _Tp> const _Tp *ptr(int y = 0) const;
 +
 +            //! matrix transposition
 +            oclMat t() const;
 +
 +            /*! includes several bit-fields:
 +              - the magic signature
 +              - continuity flag
 +              - depth
 +              - number of channels
 +              */
 +            int flags;
 +            //! the number of rows and columns
 +            int rows, cols;
 +            //! a distance between successive rows in bytes; includes the gap if any
 +            size_t step;
 +            //! pointer to the data(OCL memory object)
 +            uchar *data;
 +
 +            //! pointer to the reference counter;
 +            // when oclMatrix points to user-allocated data, the pointer is NULL
 +            int *refcount;
 +
 +            //! helper fields used in locateROI and adjustROI
 +            //datastart and dataend are not used in current version
 +            uchar *datastart;
 +            uchar *dataend;
 +
 +            //! OpenCL context associated with the oclMat object.
 +            Context *clCxt;
 +            //add offset for handle ROI, calculated in byte
 +            int offset;
 +            //add wholerows and wholecols for the whole matrix, datastart and dataend are no longer used
 +            int wholerows;
 +            int wholecols;
 +        };
 +
 +        // convert InputArray/OutputArray to oclMat references
 +        CV_EXPORTS oclMat& getOclMatRef(InputArray src);
 +        CV_EXPORTS oclMat& getOclMatRef(OutputArray src);
 +
 +        ///////////////////// mat split and merge /////////////////////////////////
 +        //! Compose a multi-channel array from several single-channel arrays
 +        // Support all types
 +        CV_EXPORTS void merge(const oclMat *src, size_t n, oclMat &dst);
 +        CV_EXPORTS void merge(const std::vector<oclMat> &src, oclMat &dst);
 +
 +        //! Divides multi-channel array into several single-channel arrays
 +        // Support all types
 +        CV_EXPORTS void split(const oclMat &src, oclMat *dst);
 +        CV_EXPORTS void split(const oclMat &src, std::vector<oclMat> &dst);
 +
 +        ////////////////////////////// Arithmetics ///////////////////////////////////
 +        //#if defined DOUBLE_SUPPORT
 +        //typedef double F;
 +        //#else
 +        //typedef float F;
 +        //#endif
 +        //    CV_EXPORTS void addWeighted(const oclMat& a,F  alpha, const oclMat& b,F beta,F gama, oclMat& c);
 +        CV_EXPORTS void addWeighted(const oclMat &a, double  alpha, const oclMat &b, double beta, double gama, oclMat &c);
 +        //! adds one matrix to another (c = a + b)
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void add(const oclMat &a, const oclMat &b, oclMat &c);
 +        //! adds one matrix to another (c = a + b)
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void add(const oclMat &a, const oclMat &b, oclMat &c, const oclMat &mask);
 +        //! adds scalar to a matrix (c = a + s)
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void add(const oclMat &a, const Scalar &sc, oclMat &c, const oclMat &mask = oclMat());
 +        //! subtracts one matrix from another (c = a - b)
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void subtract(const oclMat &a, const oclMat &b, oclMat &c);
 +        //! subtracts one matrix from another (c = a - b)
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void subtract(const oclMat &a, const oclMat &b, oclMat &c, const oclMat &mask);
 +        //! subtracts scalar from a matrix (c = a - s)
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void subtract(const oclMat &a, const Scalar &sc, oclMat &c, const oclMat &mask = oclMat());
 +        //! subtracts scalar from a matrix (c = a - s)
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void subtract(const Scalar &sc, const oclMat &a, oclMat &c, const oclMat &mask = oclMat());
 +        //! computes element-wise product of the two arrays (c = a * b)
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void multiply(const oclMat &a, const oclMat &b, oclMat &c, double scale = 1);
 +        //! multiplies matrix to a number (dst = scalar * src)
 +        // supports CV_32FC1 only
 +        CV_EXPORTS void multiply(double scalar, const oclMat &src, oclMat &dst);
 +        //! computes element-wise quotient of the two arrays (c = a / b)
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void divide(const oclMat &a, const oclMat &b, oclMat &c, double scale = 1);
 +        //! computes element-wise quotient of the two arrays (c = a / b)
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void divide(double scale, const oclMat &b, oclMat &c);
 +
 +        //! compares elements of two arrays (c = a <cmpop> b)
 +        // supports except CV_8SC1,CV_8SC2,CV8SC3,CV_8SC4 types
 +        CV_EXPORTS void compare(const oclMat &a, const oclMat &b, oclMat &c, int cmpop);
 +
 +        //! transposes the matrix
 +        // supports  CV_8UC1, 8UC4, 8SC4, 16UC2, 16SC2, 32SC1 and 32FC1.(the same as cuda)
 +        CV_EXPORTS void transpose(const oclMat &src, oclMat &dst);
 +
 +        //! computes element-wise absolute difference of two arrays (c = abs(a - b))
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void absdiff(const oclMat &a, const oclMat &b, oclMat &c);
 +        //! computes element-wise absolute difference of array and scalar (c = abs(a - s))
 +        // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
 +        CV_EXPORTS void absdiff(const oclMat &a, const Scalar &s, oclMat &c);
 +
 +        //! computes mean value and standard deviation of all or selected array elements
 +        // supports except CV_32F,CV_64F
 +        CV_EXPORTS void meanStdDev(const oclMat &mtx, Scalar &mean, Scalar &stddev);
 +
 +        //! computes norm of array
 +        // supports NORM_INF, NORM_L1, NORM_L2
 +        // supports only CV_8UC1 type
 +        CV_EXPORTS double norm(const oclMat &src1, int normType = NORM_L2);
 +
 +        //! computes norm of the difference between two arrays
 +        // supports NORM_INF, NORM_L1, NORM_L2
 +        // supports only CV_8UC1 type
 +        CV_EXPORTS double norm(const oclMat &src1, const oclMat &src2, int normType = NORM_L2);
 +
 +        //! reverses the order of the rows, columns or both in a matrix
 +        // supports all types
 +        CV_EXPORTS void flip(const oclMat &a, oclMat &b, int flipCode);
 +
 +        //! computes sum of array elements
 +        // disabled until fix crash
 +        // support all types
 +        CV_EXPORTS Scalar sum(const oclMat &m);
 +        CV_EXPORTS Scalar absSum(const oclMat &m);
 +        CV_EXPORTS Scalar sqrSum(const oclMat &m);
 +
 +        //! finds global minimum and maximum array elements and returns their values
 +        // support all C1 types
 +
 +        CV_EXPORTS void minMax(const oclMat &src, double *minVal, double *maxVal = 0, const oclMat &mask = oclMat());
 +        CV_EXPORTS void minMax_buf(const oclMat &src, double *minVal, double *maxVal, const oclMat &mask, oclMat& buf);
 +
 +        //! finds global minimum and maximum array elements and returns their values with locations
 +        // support all C1 types
 +
 +        CV_EXPORTS void minMaxLoc(const oclMat &src, double *minVal, double *maxVal = 0, Point *minLoc = 0, Point *maxLoc = 0,
 +                                  const oclMat &mask = oclMat());
 +
 +        //! counts non-zero array elements
 +        // support all types
 +        CV_EXPORTS int countNonZero(const oclMat &src);
 +
 +        //! transforms 8-bit unsigned integers using lookup table: dst(i)=lut(src(i))
 +        // destination array will have the depth type as lut and the same channels number as source
 +        //It supports 8UC1 8UC4 only
 +        CV_EXPORTS void LUT(const oclMat &src, const oclMat &lut, oclMat &dst);
 +
 +        //! only 8UC1 and 256 bins is supported now
 +        CV_EXPORTS void calcHist(const oclMat &mat_src, oclMat &mat_hist);
 +        //! only 8UC1 and 256 bins is supported now
 +        CV_EXPORTS void equalizeHist(const oclMat &mat_src, oclMat &mat_dst);
-             virtual void setClipLimit(double clipLimit) = 0;
-             virtual double getClipLimit() const = 0;
-             virtual void setTilesGridSize(Size tileGridSize) = 0;
-             virtual Size getTilesGridSize() const = 0;
-             virtual void collectGarbage() = 0;
 +
-             virtual ~CLAHE() {}
-         };
-         CV_EXPORTS Ptr<cv::ocl::CLAHE> createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8));
-         
++        //! only 8UC1 is supported now
++        CV_EXPORTS Ptr<cv::CLAHE> createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8));
 +
 +        //! bilateralFilter
 +        // supports 8UC1 8UC4
 +        CV_EXPORTS void bilateralFilter(const oclMat& src, oclMat& dst, int d, double sigmaColor, double sigmaSpave, int borderType=BORDER_DEFAULT);
 +        //! computes exponent of each matrix element (b = e**a)
 +        // supports only CV_32FC1 type
 +        CV_EXPORTS void exp(const oclMat &a, oclMat &b);
 +
 +        //! computes natural logarithm of absolute value of each matrix element: b = log(abs(a))
 +        // supports only CV_32FC1 type
 +        CV_EXPORTS void log(const oclMat &a, oclMat &b);
 +
 +        //! computes magnitude of each (x(i), y(i)) vector
 +        // supports only CV_32F CV_64F type
 +        CV_EXPORTS void magnitude(const oclMat &x, const oclMat &y, oclMat &magnitude);
 +        CV_EXPORTS void magnitudeSqr(const oclMat &x, const oclMat &y, oclMat &magnitude);
 +
 +        CV_EXPORTS void magnitudeSqr(const oclMat &x, oclMat &magnitude);
 +
 +        //! computes angle (angle(i)) of each (x(i), y(i)) vector
 +        // supports only CV_32F CV_64F type
 +        CV_EXPORTS void phase(const oclMat &x, const oclMat &y, oclMat &angle, bool angleInDegrees = false);
 +
 +        //! the function raises every element of tne input array to p
 +        //! support only CV_32F CV_64F type
 +        CV_EXPORTS void pow(const oclMat &x, double p, oclMat &y);
 +
 +        //! converts Cartesian coordinates to polar
 +        // supports only CV_32F CV_64F type
 +        CV_EXPORTS void cartToPolar(const oclMat &x, const oclMat &y, oclMat &magnitude, oclMat &angle, bool angleInDegrees = false);
 +
 +        //! converts polar coordinates to Cartesian
 +        // supports only CV_32F CV_64F type
 +        CV_EXPORTS void polarToCart(const oclMat &magnitude, const oclMat &angle, oclMat &x, oclMat &y, bool angleInDegrees = false);
 +
 +        //! perfroms per-elements bit-wise inversion
 +        // supports all types
 +        CV_EXPORTS void bitwise_not(const oclMat &src, oclMat &dst);
 +        //! calculates per-element bit-wise disjunction of two arrays
 +        // supports all types
 +        CV_EXPORTS void bitwise_or(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat());
 +        CV_EXPORTS void bitwise_or(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat());
 +        //! calculates per-element bit-wise conjunction of two arrays
 +        // supports all types
 +        CV_EXPORTS void bitwise_and(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat());
 +        CV_EXPORTS void bitwise_and(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat());
 +        //! calculates per-element bit-wise "exclusive or" operation
 +        // supports all types
 +        CV_EXPORTS void bitwise_xor(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat());
 +        CV_EXPORTS void bitwise_xor(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat());
 +
 +        //! Logical operators
 +        CV_EXPORTS oclMat operator ~ (const oclMat &);
 +        CV_EXPORTS oclMat operator | (const oclMat &, const oclMat &);
 +        CV_EXPORTS oclMat operator & (const oclMat &, const oclMat &);
 +        CV_EXPORTS oclMat operator ^ (const oclMat &, const oclMat &);
 +
 +
 +        //! Mathematics operators
 +        CV_EXPORTS oclMatExpr operator + (const oclMat &src1, const oclMat &src2);
 +        CV_EXPORTS oclMatExpr operator - (const oclMat &src1, const oclMat &src2);
 +        CV_EXPORTS oclMatExpr operator * (const oclMat &src1, const oclMat &src2);
 +        CV_EXPORTS oclMatExpr operator / (const oclMat &src1, const oclMat &src2);
 +
 +        struct CV_EXPORTS ConvolveBuf
 +        {
 +            Size result_size;
 +            Size block_size;
 +            Size user_block_size;
 +            Size dft_size;
 +
 +            oclMat image_spect, templ_spect, result_spect;
 +            oclMat image_block, templ_block, result_data;
 +
 +            void create(Size image_size, Size templ_size);
 +            static Size estimateBlockSize(Size result_size, Size templ_size);
 +        };
 +
 +        //! computes convolution of two images, may use discrete Fourier transform
 +        //! support only CV_32FC1 type
 +        CV_EXPORTS void convolve(const oclMat &image, const oclMat &temp1, oclMat &result, bool ccorr = false);
 +        CV_EXPORTS void convolve(const oclMat &image, const oclMat &temp1, oclMat &result, bool ccorr, ConvolveBuf& buf);
 +
 +        //! Performs a per-element multiplication of two Fourier spectrums.
 +        //! Only full (not packed) CV_32FC2 complex spectrums in the interleaved format are supported for now.
 +        //! support only CV_32FC2 type
 +        CV_EXPORTS void mulSpectrums(const oclMat &a, const oclMat &b, oclMat &c, int flags, float scale, bool conjB = false);
 +
 +        CV_EXPORTS void cvtColor(const oclMat &src, oclMat &dst, int code , int dcn = 0);
 +
 +        //////////////////////////////// Filter Engine ////////////////////////////////
 +
 +        /*!
 +          The Base Class for 1D or Row-wise Filters
 +
 +          This is the base class for linear or non-linear filters that process 1D data.
 +          In particular, such filters are used for the "horizontal" filtering parts in separable filters.
 +          */
 +        class CV_EXPORTS BaseRowFilter_GPU
 +        {
 +        public:
 +            BaseRowFilter_GPU(int ksize_, int anchor_, int bordertype_) : ksize(ksize_), anchor(anchor_), bordertype(bordertype_) {}
 +            virtual ~BaseRowFilter_GPU() {}
 +            virtual void operator()(const oclMat &src, oclMat &dst) = 0;
 +            int ksize, anchor, bordertype;
 +        };
 +
 +        /*!
 +          The Base Class for Column-wise Filters
 +
 +          This is the base class for linear or non-linear filters that process columns of 2D arrays.
 +          Such filters are used for the "vertical" filtering parts in separable filters.
 +          */
 +        class CV_EXPORTS BaseColumnFilter_GPU
 +        {
 +        public:
 +            BaseColumnFilter_GPU(int ksize_, int anchor_, int bordertype_) : ksize(ksize_), anchor(anchor_), bordertype(bordertype_) {}
 +            virtual ~BaseColumnFilter_GPU() {}
 +            virtual void operator()(const oclMat &src, oclMat &dst) = 0;
 +            int ksize, anchor, bordertype;
 +        };
 +
 +        /*!
 +          The Base Class for Non-Separable 2D Filters.
 +
 +          This is the base class for linear or non-linear 2D filters.
 +          */
 +        class CV_EXPORTS BaseFilter_GPU
 +        {
 +        public:
 +            BaseFilter_GPU(const Size &ksize_, const Point &anchor_, const int &borderType_)
 +                : ksize(ksize_), anchor(anchor_), borderType(borderType_) {}
 +            virtual ~BaseFilter_GPU() {}
 +            virtual void operator()(const oclMat &src, oclMat &dst) = 0;
 +            Size ksize;
 +            Point anchor;
 +            int borderType;
 +        };
 +
 +        /*!
 +          The Base Class for Filter Engine.
 +
 +          The class can be used to apply an arbitrary filtering operation to an image.
 +          It contains all the necessary intermediate buffers.
 +          */
 +        class CV_EXPORTS FilterEngine_GPU
 +        {
 +        public:
 +            virtual ~FilterEngine_GPU() {}
 +
 +            virtual void apply(const oclMat &src, oclMat &dst, Rect roi = Rect(0, 0, -1, -1)) = 0;
 +        };
 +
 +        //! returns the non-separable filter engine with the specified filter
 +        CV_EXPORTS Ptr<FilterEngine_GPU> createFilter2D_GPU(const Ptr<BaseFilter_GPU> filter2D);
 +
 +        //! returns the primitive row filter with the specified kernel
 +        CV_EXPORTS Ptr<BaseRowFilter_GPU> getLinearRowFilter_GPU(int srcType, int bufType, const Mat &rowKernel,
 +                int anchor = -1, int bordertype = BORDER_DEFAULT);
 +
 +        //! returns the primitive column filter with the specified kernel
 +        CV_EXPORTS Ptr<BaseColumnFilter_GPU> getLinearColumnFilter_GPU(int bufType, int dstType, const Mat &columnKernel,
 +                int anchor = -1, int bordertype = BORDER_DEFAULT, double delta = 0.0);
 +
 +        //! returns the separable linear filter engine
 +        CV_EXPORTS Ptr<FilterEngine_GPU> createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat &rowKernel,
 +                const Mat &columnKernel, const Point &anchor = Point(-1, -1), double delta = 0.0, int bordertype = BORDER_DEFAULT);
 +
 +        //! returns the separable filter engine with the specified filters
 +        CV_EXPORTS Ptr<FilterEngine_GPU> createSeparableFilter_GPU(const Ptr<BaseRowFilter_GPU> &rowFilter,
 +                const Ptr<BaseColumnFilter_GPU> &columnFilter);
 +
 +        //! returns the Gaussian filter engine
 +        CV_EXPORTS Ptr<FilterEngine_GPU> createGaussianFilter_GPU(int type, Size ksize, double sigma1, double sigma2 = 0, int bordertype = BORDER_DEFAULT);
 +
 +        //! returns filter engine for the generalized Sobel operator
 +        CV_EXPORTS Ptr<FilterEngine_GPU> createDerivFilter_GPU( int srcType, int dstType, int dx, int dy, int ksize, int borderType = BORDER_DEFAULT );
 +
 +        //! applies Laplacian operator to the image
 +        // supports only ksize = 1 and ksize = 3 8UC1 8UC4 32FC1 32FC4 data type
 +        CV_EXPORTS void Laplacian(const oclMat &src, oclMat &dst, int ddepth, int ksize = 1, double scale = 1);
 +
 +        //! returns 2D box filter
 +        // supports CV_8UC1 and CV_8UC4 source type, dst type must be the same as source type
 +        CV_EXPORTS Ptr<BaseFilter_GPU> getBoxFilter_GPU(int srcType, int dstType,
 +                const Size &ksize, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
 +
 +        //! returns box filter engine
 +        CV_EXPORTS Ptr<FilterEngine_GPU> createBoxFilter_GPU(int srcType, int dstType, const Size &ksize,
 +                const Point &anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
 +
 +        //! returns 2D filter with the specified kernel
 +        // supports CV_8UC1 and CV_8UC4 types
 +        CV_EXPORTS Ptr<BaseFilter_GPU> getLinearFilter_GPU(int srcType, int dstType, const Mat &kernel, const Size &ksize,
 +                Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
 +
 +        //! returns the non-separable linear filter engine
 +        CV_EXPORTS Ptr<FilterEngine_GPU> createLinearFilter_GPU(int srcType, int dstType, const Mat &kernel,
 +                const Point &anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
 +
 +        //! smooths the image using the normalized box filter
 +        // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
 +        // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101,BORDER_WRAP
 +        CV_EXPORTS void boxFilter(const oclMat &src, oclMat &dst, int ddepth, Size ksize,
 +                                  Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
 +
 +        //! returns 2D morphological filter
 +        //! only MORPH_ERODE and MORPH_DILATE are supported
 +        // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types
 +        // kernel must have CV_8UC1 type, one rows and cols == ksize.width * ksize.height
 +        CV_EXPORTS Ptr<BaseFilter_GPU> getMorphologyFilter_GPU(int op, int type, const Mat &kernel, const Size &ksize,
 +                Point anchor = Point(-1, -1));
 +
 +        //! returns morphological filter engine. Only MORPH_ERODE and MORPH_DILATE are supported.
 +        CV_EXPORTS Ptr<FilterEngine_GPU> createMorphologyFilter_GPU(int op, int type, const Mat &kernel,
 +                const Point &anchor = Point(-1, -1), int iterations = 1);
 +
 +        //! a synonym for normalized box filter
 +        // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
 +        // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101
 +        static inline void blur(const oclMat &src, oclMat &dst, Size ksize, Point anchor = Point(-1, -1),
 +                                int borderType = BORDER_CONSTANT)
 +        {
 +            boxFilter(src, dst, -1, ksize, anchor, borderType);
 +        }
 +
 +        //! applies non-separable 2D linear filter to the image
 +        //  Note, at the moment this function only works when anchor point is in the kernel center
 +        //  and kernel size supported is either 3x3 or 5x5; otherwise the function will fail to output valid result
 +        CV_EXPORTS void filter2D(const oclMat &src, oclMat &dst, int ddepth, const Mat &kernel,
 +                                 Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
 +
 +        //! applies separable 2D linear filter to the image
 +        CV_EXPORTS void sepFilter2D(const oclMat &src, oclMat &dst, int ddepth, const Mat &kernelX, const Mat &kernelY,
 +                                    Point anchor = Point(-1, -1), double delta = 0.0, int bordertype = BORDER_DEFAULT);
 +
 +        //! applies generalized Sobel operator to the image
 +        // dst.type must equalize src.type
 +        // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
 +        // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101
 +        CV_EXPORTS void Sobel(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT);
 +
 +        //! applies the vertical or horizontal Scharr operator to the image
 +        // dst.type must equalize src.type
 +        // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
 +        // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101
 +        CV_EXPORTS void Scharr(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT);
 +
 +        //! smooths the image using Gaussian filter.
 +        // dst.type must equalize src.type
 +        // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
 +        // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101
 +        CV_EXPORTS void GaussianBlur(const oclMat &src, oclMat &dst, Size ksize, double sigma1, double sigma2 = 0, int bordertype = BORDER_DEFAULT);
 +
 +        //! erodes the image (applies the local minimum operator)
 +        // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
 +        CV_EXPORTS void erode( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1,
 +
 +                               int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue());
 +
 +
 +        //! dilates the image (applies the local maximum operator)
 +        // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
 +        CV_EXPORTS void dilate( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1,
 +
 +                                int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue());
 +
 +
 +        //! applies an advanced morphological operation to the image
 +        CV_EXPORTS void morphologyEx( const oclMat &src, oclMat &dst, int op, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1,
 +
 +                                      int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue());
 +
 +
 +        ////////////////////////////// Image processing //////////////////////////////
 +        //! Does mean shift filtering on GPU.
 +        CV_EXPORTS void meanShiftFiltering(const oclMat &src, oclMat &dst, int sp, int sr,
 +                                           TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1));
 +
 +        //! Does mean shift procedure on GPU.
 +        CV_EXPORTS void meanShiftProc(const oclMat &src, oclMat &dstr, oclMat &dstsp, int sp, int sr,
 +                                      TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1));
 +
 +        //! Does mean shift segmentation with elimiation of small regions.
 +        CV_EXPORTS void meanShiftSegmentation(const oclMat &src, Mat &dst, int sp, int sr, int minsize,
 +                                              TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1));
 +
 +        //! applies fixed threshold to the image.
 +        // supports CV_8UC1 and CV_32FC1 data type
 +        // supports threshold type: THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV
 +        CV_EXPORTS double threshold(const oclMat &src, oclMat &dst, double thresh, double maxVal, int type = THRESH_TRUNC);
 +
 +        //! resizes the image
 +        // Supports INTER_NEAREST, INTER_LINEAR
 +        // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types
 +        CV_EXPORTS void resize(const oclMat &src, oclMat &dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR);
 +
 +        //! Applies a generic geometrical transformation to an image.
 +
 +        // Supports INTER_NEAREST, INTER_LINEAR.
 +
 +        // Map1 supports CV_16SC2, CV_32FC2  types.
 +
 +        // Src supports CV_8UC1, CV_8UC2, CV_8UC4.
 +
 +        CV_EXPORTS void remap(const oclMat &src, oclMat &dst, oclMat &map1, oclMat &map2, int interpolation, int bordertype, const Scalar &value = Scalar());
 +
 +        //! copies 2D array to a larger destination array and pads borders with user-specifiable constant
 +        // supports CV_8UC1, CV_8UC4, CV_32SC1 types
 +        CV_EXPORTS void copyMakeBorder(const oclMat &src, oclMat &dst, int top, int bottom, int left, int right, int boardtype, const Scalar &value = Scalar());
 +
 +        //! Smoothes image using median filter
 +        // The source 1- or 4-channel image. When m is 3 or 5, the image depth should be CV 8U or CV 32F.
 +        CV_EXPORTS void medianFilter(const oclMat &src, oclMat &dst, int m);
 +
 +        //! warps the image using affine transformation
 +        // Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC
 +        // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types
 +        CV_EXPORTS void warpAffine(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR);
 +
 +        //! warps the image using perspective transformation
 +        // Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC
 +        // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types
 +        CV_EXPORTS void warpPerspective(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR);
 +
 +        //! computes the integral image and integral for the squared image
 +        // sum will have CV_32S type, sqsum - CV32F type
 +        // supports only CV_8UC1 source type
 +        CV_EXPORTS void integral(const oclMat &src, oclMat &sum, oclMat &sqsum);
 +        CV_EXPORTS void integral(const oclMat &src, oclMat &sum);
 +        CV_EXPORTS void cornerHarris(const oclMat &src, oclMat &dst, int blockSize, int ksize, double k, int bordertype = cv::BORDER_DEFAULT);
 +        CV_EXPORTS void cornerHarris_dxdy(const oclMat &src, oclMat &dst, oclMat &Dx, oclMat &Dy,
 +            int blockSize, int ksize, double k, int bordertype = cv::BORDER_DEFAULT);
 +        CV_EXPORTS void cornerMinEigenVal(const oclMat &src, oclMat &dst, int blockSize, int ksize, int bordertype = cv::BORDER_DEFAULT);
 +        CV_EXPORTS void cornerMinEigenVal_dxdy(const oclMat &src, oclMat &dst, oclMat &Dx, oclMat &Dy,
 +            int blockSize, int ksize, int bordertype = cv::BORDER_DEFAULT);
 +
 +        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +        ///////////////////////////////////////////CascadeClassifier//////////////////////////////////////////////////////////////////
 +        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +
 +#if 0
 +        class CV_EXPORTS OclCascadeClassifier : public  cv::CascadeClassifier
 +        {
 +        public:
 +            OclCascadeClassifier() {};
 +            ~OclCascadeClassifier() {};
 +
 +            CvSeq* oclHaarDetectObjects(oclMat &gimg, CvMemStorage *storage, double scaleFactor,
 +                                        int minNeighbors, int flags, CvSize minSize = cvSize(0, 0), CvSize maxSize = cvSize(0, 0));
 +        };
 +#endif
 +
 +#if 0
 +        class CV_EXPORTS OclCascadeClassifierBuf : public  cv::CascadeClassifier
 +        {
 +        public:
 +            OclCascadeClassifierBuf() :
 +                m_flags(0), initialized(false), m_scaleFactor(0), buffers(NULL) {}
 +
 +            ~OclCascadeClassifierBuf() { release(); }
 +
 +            void detectMultiScale(oclMat &image, CV_OUT std::vector<cv::Rect>& faces,
 +                                  double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0,
 +                                  Size minSize = Size(), Size maxSize = Size());
 +            void release();
 +
 +        private:
 +            void Init(const int rows, const int cols, double scaleFactor, int flags,
 +                      const int outputsz, const size_t localThreads[],
 +                      Size minSize, Size maxSize);
 +            void CreateBaseBufs(const int datasize, const int totalclassifier, const int flags, const int outputsz);
 +            void CreateFactorRelatedBufs(const int rows, const int cols, const int flags,
 +                                         const double scaleFactor, const size_t localThreads[],
 +                                         Size minSize, Size maxSize);
 +            void GenResult(CV_OUT std::vector<cv::Rect>& faces, const std::vector<cv::Rect> &rectList, const std::vector<int> &rweights);
 +
 +            int m_rows;
 +            int m_cols;
 +            int m_flags;
 +            int m_loopcount;
 +            int m_nodenum;
 +            bool findBiggestObject;
 +            bool initialized;
 +            double m_scaleFactor;
 +            Size m_minSize;
 +            Size m_maxSize;
 +            std::vector<Size> sizev;
 +            std::vector<float> scalev;
 +            oclMat gimg1, gsum, gsqsum;
 +            void * buffers;
 +        };
 +#endif
 +
 +        /////////////////////////////// Pyramid /////////////////////////////////////
 +        CV_EXPORTS void pyrDown(const oclMat &src, oclMat &dst);
 +
 +        //! upsamples the source image and then smoothes it
 +        CV_EXPORTS void pyrUp(const oclMat &src, oclMat &dst);
 +
 +        //! performs linear blending of two images
 +        //! to avoid accuracy errors sum of weigths shouldn't be very close to zero
 +        // supports only CV_8UC1 source type
 +        CV_EXPORTS void blendLinear(const oclMat &img1, const oclMat &img2, const oclMat &weights1, const oclMat &weights2, oclMat &result);
 +
 +        //! computes vertical sum, supports only CV_32FC1 images
 +        CV_EXPORTS void columnSum(const oclMat &src, oclMat &sum);
 +
 +        ///////////////////////////////////////// match_template /////////////////////////////////////////////////////////////
 +        struct CV_EXPORTS MatchTemplateBuf
 +        {
 +            Size user_block_size;
 +            oclMat imagef, templf;
 +            std::vector<oclMat> images;
 +            std::vector<oclMat> image_sums;
 +            std::vector<oclMat> image_sqsums;
 +        };
 +
 +        //! computes the proximity map for the raster template and the image where the template is searched for
 +        // Supports TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED for type 8UC1 and 8UC4
 +        // Supports TM_SQDIFF, TM_CCORR for type 32FC1 and 32FC4
 +        CV_EXPORTS void matchTemplate(const oclMat &image, const oclMat &templ, oclMat &result, int method);
 +
 +        //! computes the proximity map for the raster template and the image where the template is searched for
 +        // Supports TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED for type 8UC1 and 8UC4
 +        // Supports TM_SQDIFF, TM_CCORR for type 32FC1 and 32FC4
 +        CV_EXPORTS void matchTemplate(const oclMat &image, const oclMat &templ, oclMat &result, int method, MatchTemplateBuf &buf);
 +
 +
 +
 +        ///////////////////////////////////////////// Canny /////////////////////////////////////////////
 +        struct CV_EXPORTS CannyBuf;
 +
 +        //! compute edges of the input image using Canny operator
 +        // Support CV_8UC1 only
 +        CV_EXPORTS void Canny(const oclMat &image, oclMat &edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
 +        CV_EXPORTS void Canny(const oclMat &image, CannyBuf &buf, oclMat &edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
 +        CV_EXPORTS void Canny(const oclMat &dx, const oclMat &dy, oclMat &edges, double low_thresh, double high_thresh, bool L2gradient = false);
 +        CV_EXPORTS void Canny(const oclMat &dx, const oclMat &dy, CannyBuf &buf, oclMat &edges, double low_thresh, double high_thresh, bool L2gradient = false);
 +
 +        struct CV_EXPORTS CannyBuf
 +        {
 +            CannyBuf() : counter(NULL) {}
 +            ~CannyBuf()
 +            {
 +                release();
 +            }
 +            explicit CannyBuf(const Size &image_size, int apperture_size = 3) : counter(NULL)
 +            {
 +                create(image_size, apperture_size);
 +            }
 +            CannyBuf(const oclMat &dx_, const oclMat &dy_);
 +            void create(const Size &image_size, int apperture_size = 3);
 +            void release();
 +
 +            oclMat dx, dy;
 +            oclMat dx_buf, dy_buf;
 +            oclMat magBuf, mapBuf;
 +            oclMat trackBuf1, trackBuf2;
 +            void *counter;
 +            Ptr<FilterEngine_GPU> filterDX, filterDY;
 +        };
 +
 +        ///////////////////////////////////////// Hough Transform /////////////////////////////////////////
 +        //! HoughCircles
 +        struct HoughCirclesBuf
 +        {
 +            oclMat edges;
 +            oclMat accum;
 +            oclMat srcPoints;
 +            oclMat centers;
 +            CannyBuf cannyBuf;
 +        };
 +
 +        CV_EXPORTS void HoughCircles(const oclMat& src, oclMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096);
 +        CV_EXPORTS void HoughCircles(const oclMat& src, oclMat& circles, HoughCirclesBuf& buf, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096);
 +        CV_EXPORTS void HoughCirclesDownload(const oclMat& d_circles, OutputArray h_circles);
 +
 +
 +        ///////////////////////////////////////// clAmdFft related /////////////////////////////////////////
 +        //! Performs a forward or inverse discrete Fourier transform (1D or 2D) of floating point matrix.
 +        //! Param dft_size is the size of DFT transform.
 +        //!
 +        //! For complex-to-real transform it is assumed that the source matrix is packed in CLFFT's format.
 +        // support src type of CV32FC1, CV32FC2
 +        // support flags: DFT_INVERSE, DFT_REAL_OUTPUT, DFT_COMPLEX_OUTPUT, DFT_ROWS
 +        // dft_size is the size of original input, which is used for transformation from complex to real.
 +        // dft_size must be powers of 2, 3 and 5
 +        // real to complex dft requires at least v1.8 clAmdFft
 +        // real to complex dft output is not the same with cpu version
 +        // real to complex and complex to real does not support DFT_ROWS
 +        CV_EXPORTS void dft(const oclMat &src, oclMat &dst, Size dft_size = Size(0, 0), int flags = 0);
 +
 +        //! implements generalized matrix product algorithm GEMM from BLAS
 +        // The functionality requires clAmdBlas library
 +        // only support type CV_32FC1
 +        // flag GEMM_3_T is not supported
 +        CV_EXPORTS void gemm(const oclMat &src1, const oclMat &src2, double alpha,
 +                             const oclMat &src3, double beta, oclMat &dst, int flags = 0);
 +
 +        //////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector //////////////
 +
 +        struct CV_EXPORTS HOGDescriptor
 +
 +        {
 +
 +            enum { DEFAULT_WIN_SIGMA = -1 };
 +
 +            enum { DEFAULT_NLEVELS = 64 };
 +
 +            enum { DESCR_FORMAT_ROW_BY_ROW, DESCR_FORMAT_COL_BY_COL };
 +
 +
 +
 +            HOGDescriptor(Size win_size = Size(64, 128), Size block_size = Size(16, 16),
 +
 +                          Size block_stride = Size(8, 8), Size cell_size = Size(8, 8),
 +
 +                          int nbins = 9, double win_sigma = DEFAULT_WIN_SIGMA,
 +
 +                          double threshold_L2hys = 0.2, bool gamma_correction = true,
 +
 +                          int nlevels = DEFAULT_NLEVELS);
 +
 +
 +
 +            size_t getDescriptorSize() const;
 +
 +            size_t getBlockHistogramSize() const;
 +
 +
 +
 +            void setSVMDetector(const std::vector<float> &detector);
 +
 +
 +
 +            static std::vector<float> getDefaultPeopleDetector();
 +
 +            static std::vector<float> getPeopleDetector48x96();
 +
 +            static std::vector<float> getPeopleDetector64x128();
 +
 +
 +
 +            void detect(const oclMat &img, std::vector<Point> &found_locations,
 +
 +                        double hit_threshold = 0, Size win_stride = Size(),
 +
 +                        Size padding = Size());
 +
 +
 +
 +            void detectMultiScale(const oclMat &img, std::vector<Rect> &found_locations,
 +
 +                                  double hit_threshold = 0, Size win_stride = Size(),
 +
 +                                  Size padding = Size(), double scale0 = 1.05,
 +
 +                                  int group_threshold = 2);
 +
 +
 +
 +            void getDescriptors(const oclMat &img, Size win_stride,
 +
 +                                oclMat &descriptors,
 +
 +                                int descr_format = DESCR_FORMAT_COL_BY_COL);
 +
 +
 +
 +            Size win_size;
 +
 +            Size block_size;
 +
 +            Size block_stride;
 +
 +            Size cell_size;
 +
 +            int nbins;
 +
 +            double win_sigma;
 +
 +            double threshold_L2hys;
 +
 +            bool gamma_correction;
 +
 +            int nlevels;
 +
 +
 +
 +        protected:
 +
 +            // initialize buffers; only need to do once in case of multiscale detection
 +
 +            void init_buffer(const oclMat &img, Size win_stride);
 +
 +
 +
 +            void computeBlockHistograms(const oclMat &img);
 +
 +            void computeGradient(const oclMat &img, oclMat &grad, oclMat &qangle);
 +
 +
 +
 +            double getWinSigma() const;
 +
 +            bool checkDetectorSize() const;
 +
 +
 +
 +            static int numPartsWithin(int size, int part_size, int stride);
 +
 +            static Size numPartsWithin(Size size, Size part_size, Size stride);
 +
 +
 +
 +            // Coefficients of the separating plane
 +
 +            float free_coef;
 +
 +            oclMat detector;
 +
 +
 +
 +            // Results of the last classification step
 +
 +            oclMat labels;
 +
 +            Mat labels_host;
 +
 +
 +
 +            // Results of the last histogram evaluation step
 +
 +            oclMat block_hists;
 +
 +
 +
 +            // Gradients conputation results
 +
 +            oclMat grad, qangle;
 +
 +
 +
 +            // scaled image
 +
 +            oclMat image_scale;
 +
 +
 +
 +            // effect size of input image (might be different from original size after scaling)
 +
 +            Size effect_size;
 +
 +        };
 +
 +
 +        ////////////////////////feature2d_ocl/////////////////
 +        /****************************************************************************************\
 +        *                                      Distance                                          *
 +        \****************************************************************************************/
 +        template<typename T>
 +        struct CV_EXPORTS Accumulator
 +        {
 +            typedef T Type;
 +        };
 +        template<> struct Accumulator<unsigned char>
 +        {
 +            typedef float Type;
 +        };
 +        template<> struct Accumulator<unsigned short>
 +        {
 +            typedef float Type;
 +        };
 +        template<> struct Accumulator<char>
 +        {
 +            typedef float Type;
 +        };
 +        template<> struct Accumulator<short>
 +        {
 +            typedef float Type;
 +        };
 +
 +        /*
 +         * Manhattan distance (city block distance) functor
 +         */
 +        template<class T>
 +        struct CV_EXPORTS L1
 +        {
 +            enum { normType = NORM_L1 };
 +            typedef T ValueType;
 +            typedef typename Accumulator<T>::Type ResultType;
 +
 +            ResultType operator()( const T *a, const T *b, int size ) const
 +            {
 +                return normL1<ValueType, ResultType>(a, b, size);
 +            }
 +        };
 +
 +        /*
 +         * Euclidean distance functor
 +         */
 +        template<class T>
 +        struct CV_EXPORTS L2
 +        {
 +            enum { normType = NORM_L2 };
 +            typedef T ValueType;
 +            typedef typename Accumulator<T>::Type ResultType;
 +
 +            ResultType operator()( const T *a, const T *b, int size ) const
 +            {
 +                return (ResultType)std::sqrt((double)normL2Sqr<ValueType, ResultType>(a, b, size));
 +            }
 +        };
 +
 +        /*
 +         * Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor
 +         * bit count of A exclusive XOR'ed with B
 +         */
 +        struct CV_EXPORTS Hamming
 +        {
 +            enum { normType = NORM_HAMMING };
 +            typedef unsigned char ValueType;
 +            typedef int ResultType;
 +
 +            /** this will count the bits in a ^ b
 +             */
 +            ResultType operator()( const unsigned char *a, const unsigned char *b, int size ) const
 +            {
 +                return normHamming(a, b, size);
 +            }
 +        };
 +
 +        ////////////////////////////////// BruteForceMatcher //////////////////////////////////
 +
 +        class CV_EXPORTS BruteForceMatcher_OCL_base
 +        {
 +        public:
 +            enum DistType {L1Dist = 0, L2Dist, HammingDist};
 +            explicit BruteForceMatcher_OCL_base(DistType distType = L2Dist);
 +
 +            // Add descriptors to train descriptor collection
 +            void add(const std::vector<oclMat> &descCollection);
 +
 +            // Get train descriptors collection
 +            const std::vector<oclMat> &getTrainDescriptors() const;
 +
 +            // Clear train descriptors collection
 +            void clear();
 +
 +            // Return true if there are not train descriptors in collection
 +            bool empty() const;
 +
 +            // Return true if the matcher supports mask in match methods
 +            bool isMaskSupported() const;
 +
 +            // Find one best match for each query descriptor
 +            void matchSingle(const oclMat &query, const oclMat &train,
 +                             oclMat &trainIdx, oclMat &distance,
 +                             const oclMat &mask = oclMat());
 +
 +            // Download trainIdx and distance and convert it to CPU vector with DMatch
 +            static void matchDownload(const oclMat &trainIdx, const oclMat &distance, std::vector<DMatch> &matches);
 +            // Convert trainIdx and distance to vector with DMatch
 +            static void matchConvert(const Mat &trainIdx, const Mat &distance, std::vector<DMatch> &matches);
 +
 +            // Find one best match for each query descriptor
 +            void match(const oclMat &query, const oclMat &train, std::vector<DMatch> &matches, const oclMat &mask = oclMat());
 +
 +            // Make gpu collection of trains and masks in suitable format for matchCollection function
 +            void makeGpuCollection(oclMat &trainCollection, oclMat &maskCollection, const std::vector<oclMat> &masks = std::vector<oclMat>());
 +
 +            // Find one best match from train collection for each query descriptor
 +            void matchCollection(const oclMat &query, const oclMat &trainCollection,
 +                                 oclMat &trainIdx, oclMat &imgIdx, oclMat &distance,
 +                                 const oclMat &masks = oclMat());
 +
 +            // Download trainIdx, imgIdx and distance and convert it to vector with DMatch
 +            static void matchDownload(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance, std::vector<DMatch> &matches);
 +            // Convert trainIdx, imgIdx and distance to vector with DMatch
 +            static void matchConvert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, std::vector<DMatch> &matches);
 +
 +            // Find one best match from train collection for each query descriptor.
 +            void match(const oclMat &query, std::vector<DMatch> &matches, const std::vector<oclMat> &masks = std::vector<oclMat>());
 +
 +            // Find k best matches for each query descriptor (in increasing order of distances)
 +            void knnMatchSingle(const oclMat &query, const oclMat &train,
 +                                oclMat &trainIdx, oclMat &distance, oclMat &allDist, int k,
 +                                const oclMat &mask = oclMat());
 +
 +            // Download trainIdx and distance and convert it to vector with DMatch
 +            // compactResult is used when mask is not empty. If compactResult is false matches
 +            // vector will have the same size as queryDescriptors rows. If compactResult is true
 +            // matches vector will not contain matches for fully masked out query descriptors.
 +            static void knnMatchDownload(const oclMat &trainIdx, const oclMat &distance,
 +                                         std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
 +            // Convert trainIdx and distance to vector with DMatch
 +            static void knnMatchConvert(const Mat &trainIdx, const Mat &distance,
 +                                        std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
 +
 +            // Find k best matches for each query descriptor (in increasing order of distances).
 +            // compactResult is used when mask is not empty. If compactResult is false matches
 +            // vector will have the same size as queryDescriptors rows. If compactResult is true
 +            // matches vector will not contain matches for fully masked out query descriptors.
 +            void knnMatch(const oclMat &query, const oclMat &train,
 +                          std::vector< std::vector<DMatch> > &matches, int k, const oclMat &mask = oclMat(),
 +                          bool compactResult = false);
 +
 +            // Find k best matches from train collection for each query descriptor (in increasing order of distances)
 +            void knnMatch2Collection(const oclMat &query, const oclMat &trainCollection,
 +                                     oclMat &trainIdx, oclMat &imgIdx, oclMat &distance,
 +                                     const oclMat &maskCollection = oclMat());
 +
 +            // Download trainIdx and distance and convert it to vector with DMatch
 +            // compactResult is used when mask is not empty. If compactResult is false matches
 +            // vector will have the same size as queryDescriptors rows. If compactResult is true
 +            // matches vector will not contain matches for fully masked out query descriptors.
 +            static void knnMatch2Download(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance,
 +                                          std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
 +            // Convert trainIdx and distance to vector with DMatch
 +            static void knnMatch2Convert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance,
 +                                         std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
 +
 +            // Find k best matches  for each query descriptor (in increasing order of distances).
 +            // compactResult is used when mask is not empty. If compactResult is false matches
 +            // vector will have the same size as queryDescriptors rows. If compactResult is true
 +            // matches vector will not contain matches for fully masked out query descriptors.
 +            void knnMatch(const oclMat &query, std::vector< std::vector<DMatch> > &matches, int k,
 +                          const std::vector<oclMat> &masks = std::vector<oclMat>(), bool compactResult = false);
 +
 +            // Find best matches for each query descriptor which have distance less than maxDistance.
 +            // nMatches.at<int>(0, queryIdx) will contain matches count for queryIdx.
 +            // carefully nMatches can be greater than trainIdx.cols - it means that matcher didn't find all matches,
 +            // because it didn't have enough memory.
 +            // If trainIdx is empty, then trainIdx and distance will be created with size nQuery x max((nTrain / 100), 10),
 +            // otherwize user can pass own allocated trainIdx and distance with size nQuery x nMaxMatches
 +            // Matches doesn't sorted.
 +            void radiusMatchSingle(const oclMat &query, const oclMat &train,
 +                                   oclMat &trainIdx, oclMat &distance, oclMat &nMatches, float maxDistance,
 +                                   const oclMat &mask = oclMat());
 +
 +            // Download trainIdx, nMatches and distance and convert it to vector with DMatch.
 +            // matches will be sorted in increasing order of distances.
 +            // compactResult is used when mask is not empty. If compactResult is false matches
 +            // vector will have the same size as queryDescriptors rows. If compactResult is true
 +            // matches vector will not contain matches for fully masked out query descriptors.
 +            static void radiusMatchDownload(const oclMat &trainIdx, const oclMat &distance, const oclMat &nMatches,
 +                                            std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
 +            // Convert trainIdx, nMatches and distance to vector with DMatch.
 +            static void radiusMatchConvert(const Mat &trainIdx, const Mat &distance, const Mat &nMatches,
 +                                           std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
 +
 +            // Find best matches for each query descriptor which have distance less than maxDistance
 +            // in increasing order of distances).
 +            void radiusMatch(const oclMat &query, const oclMat &train,
 +                             std::vector< std::vector<DMatch> > &matches, float maxDistance,
 +                             const oclMat &mask = oclMat(), bool compactResult = false);
 +
 +            // Find best matches for each query descriptor which have distance less than maxDistance.
 +            // If trainIdx is empty, then trainIdx and distance will be created with size nQuery x max((nQuery / 100), 10),
 +            // otherwize user can pass own allocated trainIdx and distance with size nQuery x nMaxMatches
 +            // Matches doesn't sorted.
 +            void radiusMatchCollection(const oclMat &query, oclMat &trainIdx, oclMat &imgIdx, oclMat &distance, oclMat &nMatches, float maxDistance,
 +                                       const std::vector<oclMat> &masks = std::vector<oclMat>());
 +
 +            // Download trainIdx, imgIdx, nMatches and distance and convert it to vector with DMatch.
 +            // matches will be sorted in increasing order of distances.
 +            // compactResult is used when mask is not empty. If compactResult is false matches
 +            // vector will have the same size as queryDescriptors rows. If compactResult is true
 +            // matches vector will not contain matches for fully masked out query descriptors.
 +            static void radiusMatchDownload(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance, const oclMat &nMatches,
 +                                            std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
 +            // Convert trainIdx, nMatches and distance to vector with DMatch.
 +            static void radiusMatchConvert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, const Mat &nMatches,
 +                                           std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
 +
 +            // Find best matches from train collection for each query descriptor which have distance less than
 +            // maxDistance (in increasing order of distances).
 +            void radiusMatch(const oclMat &query, std::vector< std::vector<DMatch> > &matches, float maxDistance,
 +                             const std::vector<oclMat> &masks = std::vector<oclMat>(), bool compactResult = false);
 +
 +            DistType distType;
 +
 +        private:
 +            std::vector<oclMat> trainDescCollection;
 +        };
 +
 +        template <class Distance>
 +        class CV_EXPORTS BruteForceMatcher_OCL;
 +
 +        template <typename T>
 +        class CV_EXPORTS BruteForceMatcher_OCL< L1<T> > : public BruteForceMatcher_OCL_base
 +        {
 +        public:
 +            explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(L1Dist) {}
 +            explicit BruteForceMatcher_OCL(L1<T> /*d*/) : BruteForceMatcher_OCL_base(L1Dist) {}
 +        };
 +        template <typename T>
 +        class CV_EXPORTS BruteForceMatcher_OCL< L2<T> > : public BruteForceMatcher_OCL_base
 +        {
 +        public:
 +            explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(L2Dist) {}
 +            explicit BruteForceMatcher_OCL(L2<T> /*d*/) : BruteForceMatcher_OCL_base(L2Dist) {}
 +        };
 +        template <> class CV_EXPORTS BruteForceMatcher_OCL< Hamming > : public BruteForceMatcher_OCL_base
 +        {
 +        public:
 +            explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(HammingDist) {}
 +            explicit BruteForceMatcher_OCL(Hamming /*d*/) : BruteForceMatcher_OCL_base(HammingDist) {}
 +        };
 +
 +        class CV_EXPORTS BFMatcher_OCL : public BruteForceMatcher_OCL_base
 +        {
 +        public:
 +            explicit BFMatcher_OCL(int norm = NORM_L2) : BruteForceMatcher_OCL_base(norm == NORM_L1 ? L1Dist : norm == NORM_L2 ? L2Dist : HammingDist) {}
 +        };
 +
 +        class CV_EXPORTS GoodFeaturesToTrackDetector_OCL
 +        {
 +        public:
 +            explicit GoodFeaturesToTrackDetector_OCL(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0,
 +                int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04);
 +
 +            //! return 1 rows matrix with CV_32FC2 type
 +            void operator ()(const oclMat& image, oclMat& corners, const oclMat& mask = oclMat());
 +            //! download points of type Point2f to a vector. the vector's content will be erased
 +            void downloadPoints(const oclMat &points, std::vector<Point2f> &points_v);
 +
 +            int maxCorners;
 +            double qualityLevel;
 +            double minDistance;
 +
 +            int blockSize;
 +            bool useHarrisDetector;
 +            double harrisK;
 +            void releaseMemory()
 +            {
 +                Dx_.release();
 +                Dy_.release();
 +                eig_.release();
 +                minMaxbuf_.release();
 +                tmpCorners_.release();
 +            }
 +        private:
 +            oclMat Dx_;
 +            oclMat Dy_;
 +            oclMat eig_;
 +            oclMat minMaxbuf_;
 +            oclMat tmpCorners_;
 +        };
 +
 +        inline GoodFeaturesToTrackDetector_OCL::GoodFeaturesToTrackDetector_OCL(int maxCorners_, double qualityLevel_, double minDistance_,
 +            int blockSize_, bool useHarrisDetector_, double harrisK_)
 +        {
 +            maxCorners = maxCorners_;
 +            qualityLevel = qualityLevel_;
 +            minDistance = minDistance_;
 +            blockSize = blockSize_;
 +            useHarrisDetector = useHarrisDetector_;
 +            harrisK = harrisK_;
 +        }
 +
 +        /////////////////////////////// PyrLKOpticalFlow /////////////////////////////////////
 +
 +        class CV_EXPORTS PyrLKOpticalFlow
 +        {
 +        public:
 +            PyrLKOpticalFlow()
 +            {
 +                winSize = Size(21, 21);
 +                maxLevel = 3;
 +                iters = 30;
 +                derivLambda = 0.5;
 +                useInitialFlow = false;
 +                minEigThreshold = 1e-4f;
 +                getMinEigenVals = false;
 +                isDeviceArch11_ = false;
 +            }
 +
 +            void sparse(const oclMat &prevImg, const oclMat &nextImg, const oclMat &prevPts, oclMat &nextPts,
 +                        oclMat &status, oclMat *err = 0);
 +
 +            void dense(const oclMat &prevImg, const oclMat &nextImg, oclMat &u, oclMat &v, oclMat *err = 0);
 +
 +            Size winSize;
 +            int maxLevel;
 +            int iters;
 +            double derivLambda;
 +            bool useInitialFlow;
 +            float minEigThreshold;
 +            bool getMinEigenVals;
 +
 +            void releaseMemory()
 +            {
 +                dx_calcBuf_.release();
 +                dy_calcBuf_.release();
 +
 +                prevPyr_.clear();
 +                nextPyr_.clear();
 +
 +                dx_buf_.release();
 +                dy_buf_.release();
 +            }
 +
 +        private:
 +            void calcSharrDeriv(const oclMat &src, oclMat &dx, oclMat &dy);
 +
 +            void buildImagePyramid(const oclMat &img0, std::vector<oclMat> &pyr, bool withBorder);
 +
 +            oclMat dx_calcBuf_;
 +            oclMat dy_calcBuf_;
 +
 +            std::vector<oclMat> prevPyr_;
 +            std::vector<oclMat> nextPyr_;
 +
 +            oclMat dx_buf_;
 +            oclMat dy_buf_;
 +
 +            oclMat uPyr_[2];
 +            oclMat vPyr_[2];
 +
 +            bool isDeviceArch11_;
 +        };
++
++        class CV_EXPORTS FarnebackOpticalFlow
++        {
++        public:
++            FarnebackOpticalFlow();
++
++            int numLevels;
++            double pyrScale;
++            bool fastPyramids;
++            int winSize;
++            int numIters;
++            int polyN;
++            double polySigma;
++            int flags;
++
++            void operator ()(const oclMat &frame0, const oclMat &frame1, oclMat &flowx, oclMat &flowy);
++
++            void releaseMemory();
++
++        private:
++            void prepareGaussian(
++                int n, double sigma, float *g, float *xg, float *xxg,
++                double &ig11, double &ig03, double &ig33, double &ig55);
++
++            void setPolynomialExpansionConsts(int n, double sigma);
++
++            void updateFlow_boxFilter(
++                const oclMat& R0, const oclMat& R1, oclMat& flowx, oclMat &flowy,
++                oclMat& M, oclMat &bufM, int blockSize, bool updateMatrices);
++
++            void updateFlow_gaussianBlur(
++                const oclMat& R0, const oclMat& R1, oclMat& flowx, oclMat& flowy,
++                oclMat& M, oclMat &bufM, int blockSize, bool updateMatrices);
++
++            oclMat frames_[2];
++            oclMat pyrLevel_[2], M_, bufM_, R_[2], blurredFrame_[2];
++            std::vector<oclMat> pyramid0_, pyramid1_;
++        };
++
 +        //////////////// build warping maps ////////////////////
 +        //! builds plane warping maps
 +        CV_EXPORTS void buildWarpPlaneMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, const Mat &T, float scale, oclMat &map_x, oclMat &map_y);
 +        //! builds cylindrical warping maps
 +        CV_EXPORTS void buildWarpCylindricalMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, float scale, oclMat &map_x, oclMat &map_y);
 +        //! builds spherical warping maps
 +        CV_EXPORTS void buildWarpSphericalMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, float scale, oclMat &map_x, oclMat &map_y);
 +        //! builds Affine warping maps
 +        CV_EXPORTS void buildWarpAffineMaps(const Mat &M, bool inverse, Size dsize, oclMat &xmap, oclMat &ymap);
 +
 +        //! builds Perspective warping maps
 +        CV_EXPORTS void buildWarpPerspectiveMaps(const Mat &M, bool inverse, Size dsize, oclMat &xmap, oclMat &ymap);
 +
 +        ///////////////////////////////////// interpolate frames //////////////////////////////////////////////
 +        //! Interpolate frames (images) using provided optical flow (displacement field).
 +        //! frame0   - frame 0 (32-bit floating point images, single channel)
 +        //! frame1   - frame 1 (the same type and size)
 +        //! fu       - forward horizontal displacement
 +        //! fv       - forward vertical displacement
 +        //! bu       - backward horizontal displacement
 +        //! bv       - backward vertical displacement
 +        //! pos      - new frame position
 +        //! newFrame - new frame
 +        //! buf      - temporary buffer, will have width x 6*height size, CV_32FC1 type and contain 6 oclMat;
 +        //!            occlusion masks            0, occlusion masks            1,
 +        //!            interpolated forward flow  0, interpolated forward flow  1,
 +        //!            interpolated backward flow 0, interpolated backward flow 1
 +        //!
 +        CV_EXPORTS void interpolateFrames(const oclMat &frame0, const oclMat &frame1,
 +                                          const oclMat &fu, const oclMat &fv,
 +                                          const oclMat &bu, const oclMat &bv,
 +                                          float pos, oclMat &newFrame, oclMat &buf);
 +
 +        //! computes moments of the rasterized shape or a vector of points
 +        CV_EXPORTS Moments ocl_moments(InputArray _array, bool binaryImage);
 +
 +        class CV_EXPORTS StereoBM_OCL
 +        {
 +        public:
 +            enum { BASIC_PRESET = 0, PREFILTER_XSOBEL = 1 };
 +
 +            enum { DEFAULT_NDISP = 64, DEFAULT_WINSZ = 19 };
 +
 +            //! the default constructor
 +            StereoBM_OCL();
 +            //! the full constructor taking the camera-specific preset, number of disparities and the SAD window size. ndisparities must be multiple of 8.
 +            StereoBM_OCL(int preset, int ndisparities = DEFAULT_NDISP, int winSize = DEFAULT_WINSZ);
 +
 +            //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair
 +            //! Output disparity has CV_8U type.
 +            void operator() ( const oclMat &left, const oclMat &right, oclMat &disparity);
 +
 +            //! Some heuristics that tries to estmate
 +            // if current GPU will be faster then CPU in this algorithm.
 +            // It queries current active device.
 +            static bool checkIfGpuCallReasonable();
 +
 +            int preset;
 +            int ndisp;
 +            int winSize;
 +
 +            // If avergeTexThreshold  == 0 => post procesing is disabled
 +            // If avergeTexThreshold != 0 then disparity is set 0 in each point (x,y) where for left image
 +            // SumOfHorizontalGradiensInWindow(x, y, winSize) < (winSize * winSize) * avergeTexThreshold
 +            // i.e. input left image is low textured.
 +            float avergeTexThreshold;
 +        private:
 +            oclMat minSSD, leBuf, riBuf;
 +        };
 +
 +        class CV_EXPORTS StereoBeliefPropagation
 +        {
 +        public:
 +            enum { DEFAULT_NDISP  = 64 };
 +            enum { DEFAULT_ITERS  = 5  };
 +            enum { DEFAULT_LEVELS = 5  };
 +            static void estimateRecommendedParams(int width, int height, int &ndisp, int &iters, int &levels);
 +            explicit StereoBeliefPropagation(int ndisp  = DEFAULT_NDISP,
 +                                             int iters  = DEFAULT_ITERS,
 +                                             int levels = DEFAULT_LEVELS,
 +                                             int msg_type = CV_16S);
 +            StereoBeliefPropagation(int ndisp, int iters, int levels,
 +                                    float max_data_term, float data_weight,
 +                                    float max_disc_term, float disc_single_jump,
 +                                    int msg_type = CV_32F);
 +            void operator()(const oclMat &left, const oclMat &right, oclMat &disparity);
 +            void operator()(const oclMat &data, oclMat &disparity);
 +            int ndisp;
 +            int iters;
 +            int levels;
 +            float max_data_term;
 +            float data_weight;
 +            float max_disc_term;
 +            float disc_single_jump;
 +            int msg_type;
 +        private:
 +            oclMat u, d, l, r, u2, d2, l2, r2;
 +            std::vector<oclMat> datas;
 +            oclMat out;
 +        };
 +
 +        class CV_EXPORTS StereoConstantSpaceBP
 +        {
 +        public:
 +            enum { DEFAULT_NDISP    = 128 };
 +            enum { DEFAULT_ITERS    = 8   };
 +            enum { DEFAULT_LEVELS   = 4   };
 +            enum { DEFAULT_NR_PLANE = 4   };
 +            static void estimateRecommendedParams(int width, int height, int &ndisp, int &iters, int &levels, int &nr_plane);
 +            explicit StereoConstantSpaceBP(
 +                int ndisp    = DEFAULT_NDISP,
 +                int iters    = DEFAULT_ITERS,
 +                int levels   = DEFAULT_LEVELS,
 +                int nr_plane = DEFAULT_NR_PLANE,
 +                int msg_type = CV_32F);
 +            StereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane,
 +                float max_data_term, float data_weight, float max_disc_term, float disc_single_jump,
 +                int min_disp_th = 0,
 +                int msg_type = CV_32F);
 +            void operator()(const oclMat &left, const oclMat &right, oclMat &disparity);
 +            int ndisp;
 +            int iters;
 +            int levels;
 +            int nr_plane;
 +            float max_data_term;
 +            float data_weight;
 +            float max_disc_term;
 +            float disc_single_jump;
 +            int min_disp_th;
 +            int msg_type;
 +            bool use_local_init_data_cost;
 +        private:
 +            oclMat u[2], d[2], l[2], r[2];
 +            oclMat disp_selected_pyr[2];
 +            oclMat data_cost;
 +            oclMat data_cost_selected;
 +            oclMat temp;
 +            oclMat out;
 +        };
 +
 +        // Implementation of the Zach, Pock and Bischof Dual TV-L1 Optical Flow method
 +        //
 +        // see reference:
 +        //   [1] C. Zach, T. Pock and H. Bischof, "A Duality Based Approach for Realtime TV-L1 Optical Flow".
 +        //   [2] Javier Sanchez, Enric Meinhardt-Llopis and Gabriele Facciolo. "TV-L1 Optical Flow Estimation".
 +        class CV_EXPORTS OpticalFlowDual_TVL1_OCL
 +        {
 +        public:
 +            OpticalFlowDual_TVL1_OCL();
 +
 +            void operator ()(const oclMat& I0, const oclMat& I1, oclMat& flowx, oclMat& flowy);
 +
 +            void collectGarbage();
 +
 +            /**
 +            * Time step of the numerical scheme.
 +            */
 +            double tau;
 +
 +            /**
 +            * Weight parameter for the data term, attachment parameter.
 +            * This is the most relevant parameter, which determines the smoothness of the output.
 +            * The smaller this parameter is, the smoother the solutions we obtain.
 +            * It depends on the range of motions of the images, so its value should be adapted to each image sequence.
 +            */
 +            double lambda;
 +
 +            /**
 +            * Weight parameter for (u - v)^2, tightness parameter.
 +            * It serves as a link between the attachment and the regularization terms.
 +            * In theory, it should have a small value in order to maintain both parts in correspondence.
 +            * The method is stable for a large range of values of this parameter.
 +            */
 +            double theta;
 +
 +            /**
 +            * Number of scales used to create the pyramid of images.
 +            */
 +            int nscales;
 +
 +            /**
 +            * Number of warpings per scale.
 +            * Represents the number of times that I1(x+u0) and grad( I1(x+u0) ) are computed per scale.
 +            * This is a parameter that assures the stability of the method.
 +            * It also affects the running time, so it is a compromise between speed and accuracy.
 +            */
 +            int warps;
 +
 +            /**
 +            * Stopping criterion threshold used in the numerical scheme, which is a trade-off between precision and running time.
 +            * A small value will yield more accurate solutions at the expense of a slower convergence.
 +            */
 +            double epsilon;
 +
 +            /**
 +            * Stopping criterion iterations number used in the numerical scheme.
 +            */
 +            int iterations;
 +
 +            bool useInitialFlow;
 +
 +        private:
 +            void procOneScale(const oclMat& I0, const oclMat& I1, oclMat& u1, oclMat& u2);
 +
 +            std::vector<oclMat> I0s;
 +            std::vector<oclMat> I1s;
 +            std::vector<oclMat> u1s;
 +            std::vector<oclMat> u2s;
 +
 +            oclMat I1x_buf;
 +            oclMat I1y_buf;
 +
 +            oclMat I1w_buf;
 +            oclMat I1wx_buf;
 +            oclMat I1wy_buf;
 +
 +            oclMat grad_buf;
 +            oclMat rho_c_buf;
 +
 +            oclMat p11_buf;
 +            oclMat p12_buf;
 +            oclMat p21_buf;
 +            oclMat p22_buf;
 +
 +            oclMat diff_buf;
 +            oclMat norm_buf;
 +        };
 +    }
 +}
 +#if defined _MSC_VER && _MSC_VER >= 1200
 +#  pragma warning( push)
 +#  pragma warning( disable: 4267)
 +#endif
 +#include "opencv2/ocl/matrix_operations.hpp"
 +#if defined _MSC_VER && _MSC_VER >= 1200
 +#  pragma warning( pop)
 +#endif
 +
 +#endif /* __OPENCV_OCL_HPP__ */
  
  #include "precomp.hpp"
  
- int main(int argc, const char *argv[])
++static int cvErrorCallback(int /*status*/, const char * /*func_name*/,
++    const char *err_msg, const char * /*file_name*/,
++    int /*line*/, void * /*userdata*/)
 +{
-     vector<ocl::Info> oclinfo;
-     int num_devices = getDevice(oclinfo);
-     if (num_devices < 1)
-     {
-         cerr << "no device found\n";
-         return -1;
-     }
-     // set this to overwrite binary cache every time the test starts
-     ocl::setBinaryDiskCache(ocl::CACHE_UPDATE);
-     int devidx = 0;
-     for (size_t i = 0; i < oclinfo.size(); i++)
-     {
-         for (size_t j = 0; j < oclinfo[i].DeviceName.size(); j++)
-         {
-             printf("device %d: %s\n", devidx++, oclinfo[i].DeviceName[j].c_str());
-         }
-     }
++    TestSystem::instance().printError(err_msg);
++    return 0;
++}
 +
+ int main(int argc, const char *argv[])
+ {
      const char *keys =
 -        "{ h | help    | false | print help message }"
 -        "{ f | filter  |       | filter for test }"
 -        "{ w | workdir |       | set working directory }"
 -        "{ l | list    | false | show all tests }"
 -        "{ d | device  | 0     | device id }"
 -        "{ c | cpu_ocl | false | use cpu as ocl device}"
 -        "{ i | iters   | 10    | iteration count }"
 -        "{ m | warmup  | 1     | gpu warm up iteration count}"
 -        "{ t | xtop    | 1.1   | xfactor top boundary}"
 -        "{ b | xbottom | 0.9   | xfactor bottom boundary}"
 -        "{ v | verify  | false | only run gpu once to verify if problems occur}";
 +        "{ h help    | false | print help message }"
 +        "{ f filter  |       | filter for test }"
 +        "{ w workdir |       | set working directory }"
 +        "{ l list    | false | show all tests }"
 +        "{ d device  | 0     | device id }"
++        "{ c cpu_ocl | false | use cpu as ocl device}"
 +        "{ i iters   | 10    | iteration count }"
 +        "{ m warmup  | 1     | gpu warm up iteration count}"
-         "{ t xtop    | 1.1      | xfactor top boundary}"
-         "{ b xbottom | 0.9      | xfactor bottom boundary}"
++        "{ t xtop    | 1.1     | xfactor top boundary}"
++        "{ b xbottom | 0.9     | xfactor bottom boundary}"
 +        "{ v verify  | false | only run gpu once to verify if problems occur}";
  
+     redirectError(cvErrorCallback);
      CommandLineParser cmd(argc, argv, keys);
 -    if (cmd.get<bool>("help"))
 +    if (cmd.has("help"))
      {
          cout << "Avaible options:" << endl;
 -        cmd.printParams();
 +        cmd.printMessage();
          return 0;
      }
  
          return -1;
      }
  
 -    
+     // set this to overwrite binary cache every time the test starts
+     ocl::setBinaryDiskCache(ocl::CACHE_UPDATE);
++
      if (cmd.get<bool>("verify"))
      {
          TestSystem::instance().setNumIters(1);
@@@ -156,4 -161,4 +169,4 @@@ END_DEV
      TestSystem::instance().run();
  
      return 0;
--}
++}
Simple merge
Simple merge
Simple merge
@@@ -1796,33 -1800,39 +1796,39 @@@ void cv::ocl::device::hog::normalize_hi
          localThreads[0] = nthreads;
  
          if ((nthreads < 32) || (nthreads > 512) )
 -            cv::ocl::error("normalize_hists: histogram's size is too small or too big", 
 -                __FILE__, __LINE__, "normalize_hists");
 +            cv::error(Error::StsBadArg, "normalize_hists: histogram's size is too small or too big",
 +                "normalize_hists", __FILE__, __LINE__);
  
 -        args.push_back( make_pair( sizeof(cl_int), (void *)&nthreads));
 -        args.push_back( make_pair( sizeof(cl_int), (void *)&block_hist_size));
 -        args.push_back( make_pair( sizeof(cl_int), (void *)&img_block_width));
 +        args.push_back( std::make_pair( sizeof(cl_int), (void *)&nthreads));
 +        args.push_back( std::make_pair( sizeof(cl_int), (void *)&block_hist_size));
 +        args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_block_width));
      }
  
 -    args.push_back( make_pair( sizeof(cl_mem), (void *)&block_hists.data));
 -    args.push_back( make_pair( sizeof(cl_float), (void *)&threshold));
 -    args.push_back( make_pair( nthreads * sizeof(float), (void *)NULL));
 +    args.push_back( std::make_pair( sizeof(cl_mem), (void *)&block_hists.data));
 +    args.push_back( std::make_pair( sizeof(cl_float), (void *)&threshold));
 +    args.push_back( std::make_pair( nthreads * sizeof(float), (void *)NULL));
  
      if(hog_device_cpu)
 -        openCLExecuteKernel(clCxt, &objdetect_hog, kernelName, globalThreads, 
 +        openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads,
                               localThreads, args, -1, -1, "-D CPU");
      else
 -        openCLExecuteKernel(clCxt, &objdetect_hog, kernelName, globalThreads, 
+     {
+         cl_kernel kernel = openCLGetKernelFromSource(clCxt, &objdetect_hog, kernelName);
+         int wave_size = queryDeviceInfo<WAVEFRONT_SIZE, int>(kernel);
+         char opt[32] = {0};
+         sprintf(opt, "-D WAVE_SIZE=%d", wave_size);
-                              localThreads, args, -1, -1);
 +        openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads,
+                              localThreads, args, -1, -1, opt);
+     }
  }
  
 -void cv::ocl::device::hog::classify_hists(int win_height, int win_width, 
 -                                          int block_stride_y, int block_stride_x, 
 -                                          int win_stride_y, int win_stride_x, 
 -                                          int height, int width, 
 -                                          const cv::ocl::oclMat &block_hists, 
 -                                          const cv::ocl::oclMat &coefs, 
 -                                          float free_coef, float threshold, 
 +void cv::ocl::device::hog::classify_hists(int win_height, int win_width,
 +                                          int block_stride_y, int block_stride_x,
 +                                          int win_stride_y, int win_stride_x,
 +                                          int height, int width,
 +                                          const cv::ocl::oclMat &block_hists,
 +                                          const cv::ocl::oclMat &coefs,
 +                                          float free_coef, float threshold,
                                            cv::ocl::oclMat &labels)
  {
      Context *clCxt = Context::getContext();
  
      size_t globalThreads[3] = { img_win_width * nthreads, img_win_height, 1 };
      size_t localThreads[3] = { nthreads, 1, 1 };
 -    args.push_back( make_pair( sizeof(cl_int), (void *)&cblock_hist_size));
 -    args.push_back( make_pair( sizeof(cl_int), (void *)&img_win_width));
 -    args.push_back( make_pair( sizeof(cl_int), (void *)&img_block_width));
 -    args.push_back( make_pair( sizeof(cl_int), (void *)&win_block_stride_x));
 -    args.push_back( make_pair( sizeof(cl_int), (void *)&win_block_stride_y));
 -    args.push_back( make_pair( sizeof(cl_mem), (void *)&block_hists.data));
 -    args.push_back( make_pair( sizeof(cl_mem), (void *)&coefs.data));
 -    args.push_back( make_pair( sizeof(cl_float), (void *)&free_coef));
 -    args.push_back( make_pair( sizeof(cl_float), (void *)&threshold));
 -    args.push_back( make_pair( sizeof(cl_mem), (void *)&labels.data));
 +    args.push_back( std::make_pair( sizeof(cl_int), (void *)&cblock_hist_size));
 +    args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_win_width));
 +    args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_block_width));
 +    args.push_back( std::make_pair( sizeof(cl_int), (void *)&win_block_stride_x));
 +    args.push_back( std::make_pair( sizeof(cl_int), (void *)&win_block_stride_y));
 +    args.push_back( std::make_pair( sizeof(cl_mem), (void *)&block_hists.data));
 +    args.push_back( std::make_pair( sizeof(cl_mem), (void *)&coefs.data));
 +    args.push_back( std::make_pair( sizeof(cl_float), (void *)&free_coef));
 +    args.push_back( std::make_pair( sizeof(cl_float), (void *)&threshold));
 +    args.push_back( std::make_pair( sizeof(cl_mem), (void *)&labels.data));
  
      if(hog_device_cpu)
 -        openCLExecuteKernel(clCxt, &objdetect_hog, kernelName, globalThreads, 
 +        openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads,
                               localThreads, args, -1, -1, "-D CPU");
      else
 -        openCLExecuteKernel(clCxt, &objdetect_hog, kernelName, globalThreads, 
+     {
+         cl_kernel kernel = openCLGetKernelFromSource(clCxt, &objdetect_hog, kernelName);
+         int wave_size = queryDeviceInfo<WAVEFRONT_SIZE, int>(kernel);
+         char opt[32] = {0};
+         sprintf(opt, "-D WAVE_SIZE=%d", wave_size);
-                              localThreads, args, -1, -1);
 +        openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads,
+                              localThreads, args, -1, -1, opt);
+     }
  }
  
 -void cv::ocl::device::hog::extract_descrs_by_rows(int win_height, int win_width, 
 +void cv::ocl::device::hog::extract_descrs_by_rows(int win_height, int win_width,
                                                    int block_stride_y, int block_stride_x,
 -                                                  int win_stride_y, int win_stride_x, 
 +                                                  int win_stride_y, int win_stride_x,
                                                    int height, int width,
 -                                                  const cv::ocl::oclMat &block_hists, 
 +                                                  const cv::ocl::oclMat &block_hists,
                                                    cv::ocl::oclMat &descriptors)
  {
      Context *clCxt = Context::getContext();
Simple merge
@@@ -171,6 -167,16 +165,16 @@@ namespace c
              void releaseResources();
          };
  
 -        static int enable_disk_cache = 
+         // global variables to hold binary cache properties
++        static int enable_disk_cache =
+ #ifdef _DEBUG
+             false;
+ #else
+             true;
+ #endif
+         static int update_disk_cache = false;
+         static String binpath = "";
          Info::Impl::Impl()
              :oclplatform(0),
              oclcontext(0),
              return openCLGetKernelFromSource(clCxt, source, kernelName, NULL);
          }
  
-         void setBinaryDiskCacheImpl(int mode, String path, Info::Impl * impl)
+         void setBinaryDiskCache(int mode, String path)
          {
-             impl->update_disk_cache = (mode & CACHE_UPDATE) == CACHE_UPDATE;
-             impl->enable_disk_cache = 
- #ifdef _DEBUG 
+             if(mode == CACHE_NONE)
+             {
+                 update_disk_cache = 0;
+                 enable_disk_cache = 0;
+                 return;
+             }
+             update_disk_cache |= (mode & CACHE_UPDATE) == CACHE_UPDATE;
 -            enable_disk_cache |= 
 -#ifdef _DEBUG 
++            enable_disk_cache |=
++#ifdef _DEBUG
                  (mode & CACHE_DEBUG)   == CACHE_DEBUG;
  #else
                  (mode & CACHE_RELEASE) == CACHE_RELEASE;
  
          bool initialized()
          {
--            return *((volatile int*)&Context::val) != 0 && 
--                Context::clCxt->impl->clCmdQueue != NULL&& 
++            return *((volatile int*)&Context::val) != 0 &&
++                Context::clCxt->impl->clCmdQueue != NULL&&
                  Context::clCxt->impl->oclcontext != NULL;
          }
  
Simple merge
@@@ -286,51 -283,46 +286,46 @@@ static void ocl_cvMoments( const void* 
      int tile_height = std::min(size.height,TILE_SIZE);
      size_t localThreads[3]  = { tile_height, 1, 1};
      size_t globalThreads[3] = { size.height, blockx, 1};
 -    vector<pair<size_t , const void *> > args,args_sum;
 -    args.push_back( make_pair( sizeof(cl_mem) , (void *)&src.data ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&src.rows ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&src.cols ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&src.step ));
 -    args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst_m.data ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&dst_m.cols ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&dst_m.step ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&blocky ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&depth ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&cn ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&coi ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&binary ));
 -    args.push_back( make_pair( sizeof(cl_int) , (void *)&TILE_SIZE ));
 +    std::vector<std::pair<size_t , const void *> > args,args_sum;
 +    args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.rows ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.cols ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step ));
-     args.push_back( std::make_pair( sizeof(cl_int) , (void *)&tileSize.width ));
-     args.push_back( std::make_pair( sizeof(cl_int) , (void *)&tileSize.height ));
 +    args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst_m.data ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_m.cols ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_m.step ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&blocky ));
-     args.push_back( std::make_pair( sizeof(cl_int) , (void *)&type ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&depth ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&cn ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&coi ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&binary ));
 +    args.push_back( std::make_pair( sizeof(cl_int) , (void *)&TILE_SIZE ));
-     openCLExecuteKernel(dst_m.clCxt, &moments, "CvMoments", globalThreads, localThreads, args, -1, depth);
+     openCLExecuteKernel(Context::getContext(), &moments, "CvMoments", globalThreads, localThreads, args, -1, depth);
  
      size_t localThreadss[3]  = { 128, 1, 1};
      size_t globalThreadss[3] = { 128, 1, 1};
 -    args_sum.push_back( make_pair( sizeof(cl_int) , (void *)&src.rows ));
 -    args_sum.push_back( make_pair( sizeof(cl_int) , (void *)&src.cols ));
 -    args_sum.push_back( make_pair( sizeof(cl_int) , (void *)&tile_height ));
 -    args_sum.push_back( make_pair( sizeof(cl_int) , (void *)&tile_width ));
 -    args_sum.push_back( make_pair( sizeof(cl_int) , (void *)&TILE_SIZE ));
 -    args_sum.push_back( make_pair( sizeof(cl_mem) , (void *)&sum.data ));
 -    args_sum.push_back( make_pair( sizeof(cl_mem) , (void *)&dst_m.data ));
 -    args_sum.push_back( make_pair( sizeof(cl_int) , (void *)&dst_m.step ));
 +    args_sum.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.rows ));
 +    args_sum.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.cols ));
 +    args_sum.push_back( std::make_pair( sizeof(cl_int) , (void *)&tile_height ));
 +    args_sum.push_back( std::make_pair( sizeof(cl_int) , (void *)&tile_width ));
 +    args_sum.push_back( std::make_pair( sizeof(cl_int) , (void *)&TILE_SIZE ));
 +    args_sum.push_back( std::make_pair( sizeof(cl_mem) , (void *)&sum ));
 +    args_sum.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst_m.data ));
 +    args_sum.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_m.step ));
-     openCLExecuteKernel(dst_m.clCxt, &moments, "dst_sum", globalThreadss, localThreadss, args_sum, -1, -1);
-     double* dstsum = new double[10];
-     memset(dstsum,0,10*sizeof(double));
-     openCLReadBuffer(dst_m.clCxt,sum,(void *)dstsum,10*sizeof(double));
+     openCLExecuteKernel(Context::getContext(), &moments, "dst_sum", globalThreadss, localThreadss, args_sum, -1, -1);
+     Mat dstsum(sum);
 -    mom->m00 = dstsum.at<double>(0, 0);
 -    mom->m10 = dstsum.at<double>(0, 1);
 -    mom->m01 = dstsum.at<double>(0, 2);
 -    mom->m20 = dstsum.at<double>(0, 3);
 -    mom->m11 = dstsum.at<double>(0, 4);
 -    mom->m02 = dstsum.at<double>(0, 5);
 -    mom->m30 = dstsum.at<double>(0, 6);
 -    mom->m21 = dstsum.at<double>(0, 7);
 -    mom->m12 = dstsum.at<double>(0, 8);
 -    mom->m03 = dstsum.at<double>(0, 9);
 +    mom->m00 = dstsum[0];
 +    mom->m10 = dstsum[1];
 +    mom->m01 = dstsum[2];
 +    mom->m20 = dstsum[3];
 +    mom->m11 = dstsum[4];
 +    mom->m02 = dstsum[5];
 +    mom->m30 = dstsum[6];
 +    mom->m21 = dstsum[7];
 +    mom->m12 = dstsum[8];
 +    mom->m03 = dstsum[9];
-     delete [] dstsum;
-     openCLSafeCall(clReleaseMemObject(sum));
      icvCompleteMomentState( mom );
  }
  
Simple merge
@@@ -222,11 -224,12 +224,12 @@@ __kernel void compute_hists_kernel
          barrier(CLK_LOCAL_MEM_FENCE);
  #endif
          if (cell_thread_x == 0)
 -            final_hist[(cell_x * 2 + cell_y) * cnbins + bin_id] = 
 +            final_hist[(cell_x * 2 + cell_y) * cnbins + bin_id] =
                  hist_[0] + hist_[1] + hist_[2];
      }
+ #ifdef CPU
      barrier(CLK_LOCAL_MEM_FENCE);
+ #endif
      int tid = (cell_y * CELLS_PER_BLOCK_Y + cell_x) * 12 + cell_thread_x;
      if ((tid < cblock_hist_size) && (gid < blocks_total))
      {
@@@ -117,7 -117,9 +117,9 @@@ int main(int argc, char **argv
      }
  
      setDevice(oclinfo[pid], device);
 -
+     setBinaryDiskCache(CACHE_UPDATE);
 +    cout << "Platform name:" << oclinfo[pid].PlatformName << endl;
      cout << "Device type:" << type << endl << "Device name:" << oclinfo[pid].DeviceName[device] << endl;
      return RUN_ALL_TESTS();
  }
Simple merge
@@@ -44,13 -45,13 +44,13 @@@ TEST_P(MomentsTest, Mat
      {
          if(test_contours)
          {
-             Mat src = imread( workdir + "../cpp/pic3.png", 1 );
-             Mat src_gray, canny_output;
-             cvtColor( src, src_gray, COLOR_BGR2GRAY );
+             Mat src = imread( workdir + "../cpp/pic3.png", IMREAD_GRAYSCALE );
+             ASSERT_FALSE(src.empty());
+             Mat canny_output;
              vector<vector<Point> > contours;
              vector<Vec4i> hierarchy;
-             Canny( src_gray, canny_output, 100, 200, 3 );
+             Canny( src, canny_output, 100, 200, 3 );
 -            findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
 +            findContours( canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
              for( size_t i = 0; i < contours.size(); i++ )
              {
                  Moments m = moments( contours[i], false );
Simple merge
@@@ -1,6 -1,6 +1,6 @@@
- #include "opencv2/ts.hpp"
 -#include "opencv2/core/core_c.h"
 -#include "opencv2/core/internal.hpp"
 -#include "opencv2/ts/ts.hpp"
 +#include "opencv2/core/utility.hpp"
 +#include "opencv2/core/private.hpp"
++#include "opencv2/ts.hpp"
  
  #ifdef GTEST_LINKED_AS_SHARED_LIBRARY
  #error ts module should not have GTEST_LINKED_AS_SHARED_LIBRARY defined
Simple merge
@@@ -642,15 -626,54 +622,53 @@@ performance_metrics::performance_metric
  
  void TestBase::Init(int argc, const char* const argv[])
  {
 -        "{   |perf_max_outliers           |8        |percent of allowed outliers}"
 -        "{   |perf_min_samples            |10       |minimal required numer of samples}"
 -        "{   |perf_force_samples          |100      |force set maximum number of samples for all tests}"
 -        "{   |perf_seed                   |809564   |seed for random numbers generator}"
 -        "{   |perf_threads                |-1       |the number of worker threads, if parallel execution is enabled}"
 -        "{   |perf_write_sanity           |false    |create new records for sanity checks}"
 -        "{   |perf_verify_sanity          |false    |fail tests having no regression data for sanity checks}"
 -        "{   |perf_impl                   |" + available_impls[0] +
 -                                                   "|the implementation variant of functions under test}"
 -        "{   |perf_list_impls             |false    |list available implementation variants and exit}"
 -        "{   |perf_run_cpu                |false    |deprecated, equivalent to --perf_impl=plain}"
+     std::vector<std::string> plain_only;
+     plain_only.push_back("plain");
+     TestBase::Init(plain_only, argc, argv);
+ }
+ void TestBase::Init(const std::vector<std::string> & availableImpls,
+                  int argc, const char* const argv[])
+ {
+     available_impls = availableImpls;
+     const std::string command_line_keys =
 -        "{   |perf_time_limit             |6.0      |default time limit for a single test (in seconds)}"
 -        "{   |perf_affinity_mask          |0        |set affinity mask for the main thread}"
 -        "{   |perf_log_power_checkpoints  |         |additional xml logging for power measurement}"
++        "{   perf_max_outliers           |8        |percent of allowed outliers}"
++        "{   perf_min_samples            |10       |minimal required numer of samples}"
++        "{   perf_force_samples          |100      |force set maximum number of samples for all tests}"
++        "{   perf_seed                   |809564   |seed for random numbers generator}"
++        "{   perf_threads                |-1       |the number of worker threads, if parallel execution is enabled}"
++        "{   perf_write_sanity           |false    |create new records for sanity checks}"
++        "{   perf_verify_sanity          |false    |fail tests having no regression data for sanity checks}"
++        "{   perf_impl                   |" + available_impls[0] +
++                                                  "|the implementation variant of functions under test}"
++        "{   perf_list_impls             |false    |list available implementation variants and exit}"
++        "{   perf_run_cpu                |false    |deprecated, equivalent to --perf_impl=plain}"
+ #ifdef ANDROID
 -        "{   |perf_time_limit             |3.0      |default time limit for a single test (in seconds)}"
++        "{   perf_time_limit             |6.0      |default time limit for a single test (in seconds)}"
++        "{   perf_affinity_mask          |0        |set affinity mask for the main thread}"
++        "{   perf_log_power_checkpoints  |         |additional xml logging for power measurement}"
+ #else
 -        "{   |perf_max_deviation          |1.0      |}"
 -        "{h  |help                        |false    |print help info}"
++        "{   perf_time_limit             |3.0      |default time limit for a single test (in seconds)}"
+ #endif
 -        "{   |perf_cuda_device            |0        |run GPU test suite onto specific CUDA capable device}"
 -        "{   |perf_cuda_info_only         |false    |print an information about system and an available CUDA devices and then exit.}"
++        "{   perf_max_deviation          |1.0      |}"
++        "{   help h                      |false    |print help info}"
+ #ifdef HAVE_CUDA
 -    cv::CommandLineParser args(argc, argv, command_line_keys.c_str());
 -    if (args.get<bool>("help"))
++        "{   perf_cuda_device            |0        |run GPU test suite onto specific CUDA capable device}"
++        "{   perf_cuda_info_only         |false    |print an information about system and an available CUDA devices and then exit.}"
+ #endif
+     ;
 +    cv::CommandLineParser args(argc, argv, command_line_keys);
 +    if (args.has("help"))
      {
 -        args.printParams();
 -        printf("\n\n");
 +        args.printMessage();
          return;
      }
  
      ::testing::AddGlobalTestEnvironment(new PerfEnvironment);
  
 -    param_impl          = args.get<bool>("perf_run_cpu") ? "plain" : args.get<std::string>("perf_impl");
++    param_impl          = args.has("perf_run_cpu") ? "plain" : args.get<std::string>("perf_impl");
      param_max_outliers  = std::min(100., std::max(0., args.get<double>("perf_max_outliers")));
      param_min_samples   = std::max(1u, args.get<unsigned int>("perf_min_samples"));
      param_max_deviation = std::max(0., args.get<double>("perf_max_deviation"));
      param_threads  = args.get<int>("perf_threads");
  #ifdef ANDROID
      param_affinity_mask   = args.get<int>("perf_affinity_mask");
 -    log_power_checkpoints = args.get<bool>("perf_log_power_checkpoints");
 +    log_power_checkpoints = args.has("perf_log_power_checkpoints");
  #endif
  
 -    bool param_list_impls = args.get<bool>("perf_list_impls");
++    bool param_list_impls = args.has("perf_list_impls");
+     if (param_list_impls)
+     {
+         fputs("Available implementation variants:", stdout);
+         for (size_t i = 0; i < available_impls.size(); ++i) {
+             putchar(' ');
+             fputs(available_impls[i].c_str(), stdout);
+         }
+         putchar('\n');
+         exit(0);
+     }
+     if (std::find(available_impls.begin(), available_impls.end(), param_impl) == available_impls.end())
+     {
+         printf("No such implementation: %s\n", param_impl.c_str());
+         exit(1);
+     }
  #ifdef HAVE_CUDA
  
 -    bool printOnly        = args.get<bool>("perf_cuda_info_only");
 +    bool printOnly        = args.has("perf_cuda_info_only");
  
      if (printOnly)
          exit(0);
@@@ -1365,4 -1418,4 +1413,3 @@@ void PrintTo(const Size& sz, ::std::ost
  }
  
  }  // namespace cv
--
Simple merge
Simple merge
Simple merge
index 0000000,72fc2fb..b3d2ebd
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,108 +1,109 @@@
 -        "{ i | input   |                    | specify input image }"
 -        "{ c | camera  |    0               | specify camera id   }"
 -        "{ s | use_cpu |    false           | use cpu algorithm   }"
 -        "{ o | output  | clahe_output.jpg   | specify output save path}";
+ #include <iostream>
+ #include "opencv2/core/core.hpp"
++#include "opencv2/core/utility.hpp"
+ #include "opencv2/imgproc/imgproc.hpp"
+ #include "opencv2/highgui/highgui.hpp"
+ #include "opencv2/ocl/ocl.hpp"
+ using namespace cv;
+ using namespace std;
+ Ptr<CLAHE> pFilter;
+ int tilesize;
+ int cliplimit;
+ string outfile;
+ static void TSize_Callback(int pos)
+ {
+     if(pos==0)
+     {
+         pFilter->setTilesGridSize(Size(1,1));
+     }
+     pFilter->setTilesGridSize(Size(tilesize,tilesize));
+ }
+ static void Clip_Callback(int)
+ {
+     pFilter->setClipLimit(cliplimit);
+ }
+ int main(int argc, char** argv)
+ {
+     const char* keys =
 -    CvCapture* capture = 0;
++        "{ i input   |                    | specify input image }"
++        "{ c camera  |    0               | specify camera id   }"
++        "{ s use_cpu |    false           | use cpu algorithm   }"
++        "{ o output  | clahe_output.jpg   | specify output save path}";
+     CommandLineParser cmd(argc, argv, keys);
+     string infile = cmd.get<string>("i");
+     outfile = cmd.get<string>("o");
+     int camid = cmd.get<int>("c");
+     bool use_cpu = cmd.get<bool>("s");
 -    
++    VideoCapture capture;
+     bool running = true;
+     namedWindow("CLAHE");
+     createTrackbar("Tile Size", "CLAHE", &tilesize, 32, (TrackbarCallback)TSize_Callback);
+     createTrackbar("Clip Limit", "CLAHE", &cliplimit, 20, (TrackbarCallback)Clip_Callback);
+     Mat frame, outframe;
+     ocl::oclMat d_outframe;
 -        capture = cvCaptureFromCAM(camid);
++
+     int cur_clip;
+     Size cur_tilesize;
+     if(use_cpu)
+     {
+         pFilter = createCLAHE();
+     }
+     else
+     {
+         pFilter = ocl::createCLAHE();
+     }
+     cur_clip = (int)pFilter->getClipLimit();
+     cur_tilesize = pFilter->getTilesGridSize();
+     setTrackbarPos("Tile Size", "CLAHE", cur_tilesize.width);
+     setTrackbarPos("Clip Limit", "CLAHE", cur_clip);
+     if(infile != "")
+     {
+         frame = imread(infile);
+         if(frame.empty())
+         {
+             cout << "error read image: " << infile << endl;
+             return -1;
+         }
+     }
+     else
+     {
 -        if(capture)
 -            frame = cvQueryFrame(capture);
++        capture.open(camid);
+     }
+     cout << "\nControls:\n"
+          << "\to - save output image\n"
+          << "\tESC - exit\n";
+     while(running)
+     {
 -        char key = (char)cvWaitKey(3);
++        if(capture.isOpened())
++            capture.read(frame);
+         else
+             frame = imread(infile);
+         if(frame.empty())
+         {
+             continue;
+         }
+         if(use_cpu)
+         {
+             cvtColor(frame, frame, COLOR_BGR2GRAY);
+             pFilter->apply(frame, outframe);
+         }
+         else
+         {
+             ocl::oclMat d_frame(frame);
+             ocl::cvtColor(d_frame, d_outframe, COLOR_BGR2GRAY);
+             pFilter->apply(d_outframe, d_outframe);
+             d_outframe.download(outframe);
+         }
+         imshow("CLAHE", outframe);
++        char key = (char)waitKey(3);
+         if(key == 'o') imwrite(outfile, outframe);
+         else if(key == 27) running = false;
+     }
+     return 0;
+ }
Simple merge
Simple merge
@@@ -380,5 -380,11 +382,9 @@@ void App::handleKey(char key
              cout << "level_count: " << csbp.levels << endl;
          }
          break;
+     case 'o':
+     case 'O':
+         write_once = true;
+         break;
      }
  }
 -
 -