Merge pull request #2000 from apavlenko:license_copyright
authorAndrey Pavlenko <andrey.pavlenko@itseez.com>
Wed, 18 Dec 2013 15:35:04 +0000 (19:35 +0400)
committerOpenCV Buildbot <buildbot@opencv.org>
Wed, 18 Dec 2013 15:35:04 +0000 (19:35 +0400)
88 files changed:
CMakeLists.txt
cmake/OpenCVDetectDirectX.cmake [new file with mode: 0644]
cmake/checks/directx.cpp [new file with mode: 0644]
cmake/templates/cvconfig.h.in
doc/tutorials/definitions/tocDefinitions.rst
doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.rst [new file with mode: 0644]
doc/tutorials/introduction/clojure_dev_intro/images/blurred.png [new file with mode: 0644]
doc/tutorials/introduction/clojure_dev_intro/images/lena.png [new file with mode: 0644]
doc/tutorials/introduction/table_of_content_introduction/images/clojure-logo.png [new file with mode: 0644]
doc/tutorials/introduction/table_of_content_introduction/table_of_content_introduction.rst
modules/core/include/opencv2/core.hpp
modules/core/include/opencv2/core/base.hpp
modules/core/include/opencv2/core/directx.hpp [new file with mode: 0644]
modules/core/include/opencv2/core/mat.inl.hpp
modules/core/include/opencv2/core/ocl.hpp
modules/core/include/opencv2/core/utility.hpp
modules/core/src/directx.cpp [new file with mode: 0644]
modules/core/src/directx.inc.hpp [new file with mode: 0644]
modules/core/src/matmul.cpp
modules/core/src/matrix.cpp
modules/core/src/ocl.cpp
modules/core/src/opencl/convert.cl [new file with mode: 0644]
modules/core/src/opencl/reduce.cl
modules/core/src/precomp.hpp
modules/core/src/rand.cpp
modules/core/src/stat.cpp
modules/core/src/system.cpp
modules/core/src/umatrix.cpp
modules/core/test/ocl/test_arithm.cpp
modules/core/test/ocl/test_gemm.cpp [new file with mode: 0644]
modules/core/test/ocl/test_matrix_operation.cpp [new file with mode: 0644]
modules/core/test/test_umat.cpp
modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst
modules/features2d/doc/object_categorization.rst
modules/features2d/include/opencv2/features2d.hpp
modules/features2d/src/bagofwords.cpp
modules/features2d/src/brief.cpp
modules/features2d/src/brisk.cpp
modules/features2d/src/descriptors.cpp
modules/features2d/src/freak.cpp
modules/features2d/src/orb.cpp
modules/features2d/test/test_rotation_and_scale_invariance.cpp
modules/imgproc/src/opencl/boxFilter.cl [new file with mode: 0644]
modules/imgproc/src/opencl/medianFilter.cl [new file with mode: 0644]
modules/imgproc/src/smooth.cpp
modules/imgproc/test/ocl/test_boxfilter.cpp [new file with mode: 0644]
modules/imgproc/test/ocl/test_medianfilter.cpp [new file with mode: 0644]
modules/legacy/doc/common_interfaces_of_descriptor_extractors.rst
modules/legacy/include/opencv2/legacy.hpp
modules/nonfree/include/opencv2/nonfree/cuda.hpp
modules/nonfree/include/opencv2/nonfree/features2d.hpp
modules/nonfree/include/opencv2/nonfree/ocl.hpp
modules/nonfree/src/sift.cpp
modules/nonfree/src/surf.cpp
modules/nonfree/src/surf.cuda.cpp
modules/nonfree/src/surf.ocl.cpp
modules/nonfree/test/test_features2d.cpp
modules/nonfree/test/test_surf.cuda.cpp
modules/nonfree/test/test_surf.ocl.cpp
modules/ocl/CMakeLists.txt
modules/ocl/doc/structures_and_utility_functions.rst
modules/ocl/include/opencv2/ocl.hpp
modules/ocl/include/opencv2/ocl/matrix_operations.hpp
modules/ocl/src/cl_context.cpp
modules/ocl/test/test_api.cpp
samples/CMakeLists.txt
samples/c/find_obj_calonder.cpp
samples/cpp/bagofwords_classification.cpp
samples/cpp/brief_match_test.cpp
samples/cpp/detector_descriptor_evaluation.cpp
samples/cpp/freak_demo.cpp
samples/cpp/matcher_simple.cpp
samples/cpp/shape_transformation.cpp
samples/cpp/stereo_match.cpp
samples/cpp/tutorial_code/features2D/SURF_descriptor.cpp
samples/cpp/video_homography.cpp
samples/directx/CMakeLists.txt [new file with mode: 0644]
samples/directx/d3d10_interop.cpp [new file with mode: 0644]
samples/directx/d3d11_interop.cpp [new file with mode: 0644]
samples/directx/d3d9_interop.cpp [new file with mode: 0644]
samples/directx/d3d9ex_interop.cpp [new file with mode: 0644]
samples/directx/d3d_base.inl.hpp [new file with mode: 0644]
samples/gpu/surf_keypoint_matcher.cpp
samples/java/clojure/simple-sample/.gitignore [new file with mode: 0644]
samples/java/clojure/simple-sample/project.clj [new file with mode: 0644]
samples/java/clojure/simple-sample/resources/images/lena.png [new file with mode: 0644]
samples/java/clojure/simple-sample/src/simple_sample/core.clj [new file with mode: 0644]
samples/java/clojure/simple-sample/test/simple_sample/core_test.clj [new file with mode: 0644]

index 856a4d4..4fff2d6 100644 (file)
@@ -155,6 +155,7 @@ OCV_OPTION(WITH_CLP            "Include Clp support (EPL)"                   OFF
 OCV_OPTION(WITH_OPENCL         "Include OpenCL Runtime support"              ON   IF (NOT IOS) )
 OCV_OPTION(WITH_OPENCLAMDFFT   "Include AMD OpenCL FFT library support"      ON   IF (NOT ANDROID AND NOT IOS) )
 OCV_OPTION(WITH_OPENCLAMDBLAS  "Include AMD OpenCL BLAS library support"     ON   IF (NOT ANDROID AND NOT IOS) )
+OCV_OPTION(WITH_DIRECTX        "Include DirectX support"                     ON   IF WIN32 )
 
 
 # OpenCV build components
@@ -428,6 +429,11 @@ if(WITH_OPENCL)
   include(cmake/OpenCVDetectOpenCL.cmake)
 endif()
 
+# --- DirectX ---
+if(WITH_DIRECTX)
+  include(cmake/OpenCVDetectDirectX.cmake)
+endif()
+
 # --- Matlab/Octave ---
 include(cmake/OpenCVFindMatlab.cmake)
 
diff --git a/cmake/OpenCVDetectDirectX.cmake b/cmake/OpenCVDetectDirectX.cmake
new file mode 100644 (file)
index 0000000..9136986
--- /dev/null
@@ -0,0 +1,14 @@
+if(WIN32)
+  try_compile(__VALID_DIRECTX
+    "${OpenCV_BINARY_DIR}"
+    "${OpenCV_SOURCE_DIR}/cmake/checks/directx.cpp"
+    OUTPUT_VARIABLE TRY_OUT
+  )
+  if(NOT __VALID_DIRECTX)
+    return()
+  endif()
+  set(HAVE_DIRECTX ON)
+  set(HAVE_D3D11 ON)
+  set(HAVE_D3D10 ON)
+  set(HAVE_D3D9 ON)
+endif()
diff --git a/cmake/checks/directx.cpp b/cmake/checks/directx.cpp
new file mode 100644 (file)
index 0000000..452a885
--- /dev/null
@@ -0,0 +1,70 @@
+#include <windows.h>
+
+#include <d3d11.h>
+#pragma comment (lib, "d3d11.lib")
+
+HINSTANCE g_hInst = NULL;
+D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
+D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
+ID3D11Device* g_pd3dDevice = NULL;
+ID3D11DeviceContext* g_pImmediateContext = NULL;
+IDXGISwapChain* g_pSwapChain = NULL;
+
+static HRESULT InitDevice()
+{
+    HRESULT hr = S_OK;
+
+    UINT width = 640;
+    UINT height = 480;
+
+    UINT createDeviceFlags = 0;
+
+    D3D_DRIVER_TYPE driverTypes[] =
+    {
+        D3D_DRIVER_TYPE_HARDWARE,
+        D3D_DRIVER_TYPE_WARP,
+        D3D_DRIVER_TYPE_REFERENCE,
+    };
+    UINT numDriverTypes = ARRAYSIZE(driverTypes);
+
+    D3D_FEATURE_LEVEL featureLevels[] =
+    {
+        D3D_FEATURE_LEVEL_11_0,
+        D3D_FEATURE_LEVEL_10_1,
+        D3D_FEATURE_LEVEL_10_0,
+    };
+    UINT numFeatureLevels = ARRAYSIZE(featureLevels);
+
+    DXGI_SWAP_CHAIN_DESC sd;
+    ZeroMemory( &sd, sizeof( sd ) );
+    sd.BufferCount = 1;
+    sd.BufferDesc.Width = width;
+    sd.BufferDesc.Height = height;
+    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+    sd.BufferDesc.RefreshRate.Numerator = 60;
+    sd.BufferDesc.RefreshRate.Denominator = 1;
+    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+    sd.OutputWindow = NULL; //g_hWnd;
+    sd.SampleDesc.Count = 1;
+    sd.SampleDesc.Quality = 0;
+    sd.Windowed = TRUE;
+
+    for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
+    {
+        g_driverType = driverTypes[driverTypeIndex];
+        hr = D3D11CreateDeviceAndSwapChain(NULL, g_driverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,
+                D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext);
+        if (SUCCEEDED(hr))
+            break;
+    }
+    if (FAILED(hr))
+        return hr;
+
+    return S_OK;
+}
+
+int main(int /*argc*/, char** /*argv*/)
+{
+    InitDevice();
+    return 0;
+}
index 211362a..554b91c 100644 (file)
 /* IEEE1394 capturing support - libdc1394 v2.x */
 #cmakedefine HAVE_DC1394_2
 
+/* DirectX */
+#cmakedefine HAVE_DIRECTX
+#cmakedefine HAVE_D3D11
+#cmakedefine HAVE_D3D10
+#cmakedefine HAVE_D3D9
+
 /* DirectShow Video Capture library */
 #cmakedefine HAVE_DSHOW
 
index c036b0b..52d5e5b 100644 (file)
@@ -11,5 +11,6 @@
 .. |Author_EricCh| unicode:: Eric U+0020 Christiansen
 .. |Author_AndreyP| unicode:: Andrey U+0020 Pavlenko
 .. |Author_AlexS| unicode:: Alexander U+0020 Smorkalov
+.. |Author_MimmoC| unicode:: Mimmo U+0020 Cosenza
 .. |Author_BarisD| unicode:: Bar U+0131 U+015F U+0020 Evrim U+0020 Demir U+00F6 z
 .. |Author_DomenicoB| unicode:: Domenico U+0020 Daniele U+0020 Bloisi
diff --git a/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.rst b/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.rst
new file mode 100644 (file)
index 0000000..248abdf
--- /dev/null
@@ -0,0 +1,728 @@
+.. _clojure_dev_intro:
+
+Introduction to OpenCV Development with Clojure
+***********************************************
+
+As of OpenCV 2.4.4, OpenCV supports desktop Java development using
+nearly the same interface as for Android development.
+
+`Clojure <http://clojure.org/>`_ is a contemporary LISP dialect hosted
+by the Java Virtual Machine and it offers a complete interoperability
+with the underlying JVM. This means that we should even be able to use
+the Clojure REPL (Read Eval Print Loop) as and interactive programmable
+interface to the underlying OpenCV engine.
+
+What we'll do in this tutorial
+==============================
+
+This tutorial will help you in setting up a basic Clojure environment
+for interactively learning OpenCV within the fully programmable
+CLojure REPL.
+
+Tutorial source code
+--------------------
+
+You can find a runnable source code of the sample in the
+:file:`samples/java/clojure/simple-sample` folder of the OpenCV
+repository. After having installed OpenCV and Clojure as explained in
+the tutorial, issue the following command to run the sample from the
+command line.
+
+.. code:: bash
+
+    cd path/to/samples/java/clojure/simple-sample
+    lein run
+
+Preamble
+========
+
+For detailed instruction on installing OpenCV with desktop Java support
+refer to the `corresponding tutorial <http://docs.opencv.org/2.4.4-beta/doc/tutorials/introduction/desktop_java/java_dev_intro.html>`_.
+
+If you are in hurry, here is a minimum quick start guide to install
+OpenCV on Mac OS X:
+
+    NOTE 1: I'm assuming you already installed
+    `xcode <https://developer.apple.com/xcode/>`_,
+    `jdk <http://www.oracle.com/technetwork/java/javase/downloads/index.html>`_
+    and `Cmake <http://www.cmake.org/cmake/resources/software.html>`_.
+
+.. code:: bash
+
+    cd ~/
+    mkdir opt
+    git clone https://github.com/Itseez/opencv.git
+    cd opencv
+    git checkout 2.4
+    mkdir build
+    cd build
+    cmake -DBUILD_SHARED_LIBS=OFF ..
+    ...
+    ...
+    make -j8
+    # optional
+    # make install
+
+Install Leiningen
+=================
+
+Once you installed OpenCV with desktop java support the only other
+requirement is to install
+`Leiningeng <https://github.com/technomancy/leiningen>`_ which allows
+you to manage the entire life cycle of your CLJ projects.
+
+The available `installation guide <https://github.com/technomancy/leiningen#installation>`_ is very easy to be followed:
+
+1. `Download the script <https://raw.github.com/technomancy/leiningen/stable/bin/lein>`_
+2. Place it on your ``$PATH`` (cf. ``~/bin`` is a good choice if it is
+   on your ``path``.)
+3. Set the script to be executable. (i.e. ``chmod 755 ~/bin/lein``).
+
+If you work on Windows, follow `this instruction <https://github.com/technomancy/leiningen#windows>`_
+
+You now have both the OpenCV library and a fully installed basic Clojure
+environment. What is now needed is to configure the Clojure environment
+to interact with the OpenCV library.
+
+Install the localrepo Leiningen plugin
+=======================================
+
+The set of commands (tasks in Leiningen parlance) natively supported by
+Leiningen can be very easily extended by various plugins. One of them is
+the `lein-localrepo <https://github.com/kumarshantanu/lein-localrepo>`_
+plugin which allows to install any jar lib as an artifact in the local
+maven repository of your machine (typically in the ``~/.m2/repository``
+directory of your username).
+
+We're going to use this ``lein`` plugin to add to the local maven
+repository the opencv components needed by Java and Clojure to use the
+opencv lib.
+
+Generally speaking, if you want to use a plugin on project base only, it
+can be added directly to a CLJ project created by ``lein``.
+
+Instead, when you want a plugin to be available to any CLJ project in
+your username space, you can add it to the ``profiles.clj`` in the
+``~/.lein/`` directory.
+
+The ``lein-localrepo`` plugin will be useful to me in other CLJ
+projects where I need to call native libs wrapped by a Java interface.
+So I decide to make it available to any CLJ project:
+
+.. code:: bash
+
+    mkdir ~/.lein
+
+Create a file named ``profiles.clj`` in the ``~/.lein`` directory and
+copy into it the following content:
+
+.. code:: clojure
+
+    {:user {:plugins [[lein-localrepo "0.5.2"]]}}
+
+Here we're saying that the version release ``"0.5.2"`` of the
+``lein-localrepo`` plugin will be available to the ``:user`` profile for
+any CLJ project created by ``lein``.
+
+You do not need to do anything else to install the plugin because it
+will be automatically downloaded from a remote repository the very first
+time you issue any ``lein`` task.
+
+Install the java specific libs as local repository
+==================================================
+
+If you followed the standard documentation for installing OpenCV on your
+computer, you should find the following two libs under the directory
+where you built OpenCV:
+
+-  the ``build/bin/opencv-247.jar`` java lib
+-  the ``build/lib/libopencv_java247.dylib`` native lib (or ``.so`` in
+   you built OpenCV a GNU/Linux OS)
+
+They are the only opencv libs needed by the JVM to interact with OpenCV.
+
+Take apart the needed opencv libs
+---------------------------------
+
+Create a new directory to store in the above two libs. Start by copying
+into it the ``opencv-247.jar`` lib.
+
+.. code:: bash
+
+    cd ~/opt
+    mkdir clj-opencv
+    cd clj-opencv
+    cp ~/opt/opencv/build/bin/opencv-247.jar .
+
+First lib done.
+
+Now, to be able to add the ``libopencv_java247.dylib`` shared native lib
+to the local maven repository, we first need to package it as a jar
+file.
+
+The native lib has to be copied into a directories layout which mimics
+the names of your operating system and architecture. I'm using a Mac OS
+X with a X86 64 bit architecture. So my layout will be the following:
+
+.. code:: bash
+
+    mkdir -p native/macosx/x86_64
+
+Copy into the ``x86_64`` directory the ``libopencv_java247.dylib`` lib.
+
+.. code:: bash
+
+    cp ~/opt/opencv/build/lib/libopencv_java247.dylib native/macosx/x86_64/
+
+If you're running OpenCV from a different OS/Architecture pair, here
+is a summary of the mapping you can choose from.
+
+.. code:: bash
+
+        OS
+
+        Mac OS X -> macosx
+        Windows  -> windows
+        Linux    -> linux
+        SunOS    -> solaris
+
+        Architectures
+
+        amd64    -> x86_64
+        x86_64   -> x86_64
+        x86      -> x86
+        i386     -> x86
+        arm      -> arm
+        sparc    -> sparc
+
+Package the native lib as a jar
+-------------------------------
+
+Next you need to package the native lib in a jar file by using the
+``jar`` command to create a new jar file from a directory.
+
+.. code:: bash
+
+    jar -cMf opencv-native-247.jar native
+
+Note that ehe ``M`` option instructs the ``jar`` command to not create
+a MANIFEST file for the artifact.
+
+Your directories layout should look like the following:
+
+.. code:: bash
+
+    tree
+    .
+    |__ native
+    |   |__ macosx
+    |       |__ x86_64
+    |           |__ libopencv_java247.dylib
+    |
+    |__ opencv-247.jar
+    |__ opencv-native-247.jar
+
+    3 directories, 3 files
+
+Locally install the jars
+------------------------
+
+We are now ready to add the two jars as artifacts to the local maven
+repository with the help of the ``lein-localrepo`` plugin.
+
+.. code:: bash
+
+    lein localrepo install opencv-247.jar opencv/opencv 2.4.7
+
+Here the ``localrepo install`` task creates the ``2.4.7.`` release of
+the ``opencv/opencv`` maven artifact from the ``opencv-247.jar`` lib and
+then installs it into the local maven repository. The ``opencv/opencv``
+artifact will then be available to any maven compliant project
+(Leiningen is internally based on maven).
+
+Do the same thing with the native lib previously wrapped in a new jar
+file.
+
+.. code:: bash
+
+    lein localrepo install opencv-native-247.jar opencv/opencv-native 2.4.7
+
+Note that the groupId, ``opencv``, of the two artifacts is the same. We
+are now ready to create a new CLJ project to start interacting with
+OpenCV.
+
+Create a project
+----------------
+
+Create a new CLJ project by using the ``lein new`` task from the
+terminal.
+
+.. code:: bash
+
+    # cd in the directory where you work with your development projects (e.g. ~/devel)
+    lein new simple-sample
+    Generating a project called simple-sample based on the 'default' template.
+    To see other templates (app, lein plugin, etc), try `lein help new`.
+
+The above task creates the following ``simple-sample`` directories
+layout:
+
+.. code:: bash
+
+    tree simple-sample/
+    simple-sample/
+    |__ LICENSE
+    |__ README.md
+    |__ doc
+    |   |__ intro.md
+    |
+    |__ project.clj
+    |__ resources
+    |__ src
+    |   |__ simple_sample
+    |       |__ core.clj
+    |__ test
+        |__ simple_sample
+            |__ core_test.clj
+
+    6 directories, 6 files
+
+We need to add the two ``opencv`` artifacts as dependencies of the newly
+created project. Open the ``project.clj`` and modify its dependencies
+section as follows:
+
+.. code:: bash
+
+    (defproject simple-sample "0.1.0-SNAPSHOT"
+      :description "FIXME: write description"
+      :url "http://example.com/FIXME"
+      :license {:name "Eclipse Public License"
+                :url "http://www.eclipse.org/legal/epl-v10.html"}
+      :dependencies [[org.clojure/clojure "1.5.1"]
+                     [opencv/opencv "2.4.7"] ; added line
+                     [opencv/opencv-native "2.4.7"]]) ;added line
+
+
+Note that The Clojure Programming Language is a jar artifact too. This
+is why Clojure is called an hosted language.
+
+To verify that everything went right issue the ``lein deps`` task. The
+very first time you run a ``lein`` task it will take sometime to
+download all the required dependencies before executing the task
+itself.
+
+.. code:: bash
+
+    cd simple-sample
+    lein deps
+    ...
+
+The ``deps`` task reads and merges from the ``project.clj`` and the
+``~/.lein/profiles.clj`` files all the dependencies of the
+``simple-sample`` project and verifies if they have already been
+cached in the local maven repository. If the task returns without
+messages about not being able to retrieve the two new artifacts your
+installation is correct, otherwise go back and double check that you
+did everything right.
+
+REPLing with OpenCV
+-------------------
+
+Now ``cd`` in the ``simple-sample`` directory and issue the following
+``lein`` task:
+
+.. code:: bash
+
+    cd simple-sample
+    lein repl
+    ...
+    ...
+    nREPL server started on port 50907 on host 127.0.0.1
+    REPL-y 0.3.0
+    Clojure 1.5.1
+        Docs: (doc function-name-here)
+              (find-doc "part-of-name-here")
+      Source: (source function-name-here)
+     Javadoc: (javadoc java-object-or-class-here)
+        Exit: Control+D or (exit) or (quit)
+     Results: Stored in vars *1, *2, *3, an exception in *e
+
+    user=>
+
+You can immediately interact with the REPL by issuing any CLJ expression
+to be evaluated.
+
+.. code:: clojure
+
+    user=> (+ 41 1)
+    42
+    user=> (println "Hello, OpenCV!")
+    Hello, OpenCV!
+    nil
+    user=> (defn foo [] (str "bar"))
+    #'user/foo
+    user=> (foo)
+    "bar"
+
+When ran from the home directory of a lein based project, even if the
+``lein repl`` task automatically loads all the project dependencies, you
+still need to load the opencv native library to be able to interact with
+the OpenCV.
+
+.. code:: clojure
+
+    user=> (clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)
+    nil
+
+Then you can start interacting with OpenCV by just referencing the fully
+qualified names of its classes.
+
+    NOTE 2: `Here <http://docs.opencv.org/java/>`_ you can find the
+    full OpenCV Java API.
+
+.. code:: clojure
+
+    user=> (org.opencv.core.Point. 0 0)
+    #<Point {0.0, 0.0}>
+
+Here we created a two dimensions opencv ``Point`` instance. Even if all
+the java packages included within the java interface to OpenCV are
+immediately available from the CLJ REPL, it's very annoying to prefix
+the ``Point.`` instance constructors with the fully qualified package
+name.
+
+Fortunately CLJ offer a very easy way to overcome this annoyance by
+directly importing the ``Point`` class.
+
+.. code:: clojure
+
+    user=> (import 'org.opencv.core.Point)
+    org.opencv.core.Point
+    user=> (def p1 (Point. 0 0))
+    #'user/p1
+    user=> p1
+    #<Point {0.0, 0.0}>
+    user=> (def p2 (Point. 100 100))
+    #'user/p2
+
+We can even inspect the class of an instance and verify if the value of
+a symbol is an instance of a ``Point`` java class.
+
+.. code:: clojure
+
+    user=> (class p1)
+    org.opencv.core.Point
+    user=> (instance? org.opencv.core.Point p1)
+    true
+
+If we now want to use the opencv ``Rect`` class to create a rectangle,
+we again have to fully qualify its constructor even if it leaves in
+the same ``org.opencv.core`` package of the ``Point`` class.
+
+.. code:: clojure
+
+    user=> (org.opencv.core.Rect. p1 p2)
+    #<Rect {0, 0, 100x100}>
+
+Again, the CLJ importing facilities is very handy and let you to map
+more symbols in one shot.
+
+.. code:: clojure
+
+    user=> (import '[org.opencv.core Point Rect Size])
+    org.opencv.core.Size
+    user=> (def r1 (Rect. p1 p2))
+    #'user/r1
+    user=> r1
+    #<Rect {0, 0, 100x100}>
+    user=> (class r1)
+    org.opencv.core.Rect
+    user=> (instance? org.opencv.core.Rect r1)
+    true
+    user=> (Size. 100 100)
+    #<Size 100x100>
+    user=> (def sq-100 (Size. 100 100))
+    #'user/sq-100
+    user=> (class sq-100)
+    org.opencv.core.Size
+    user=> (instance? org.opencv.core.Size sq-100)
+    true
+
+Obviously you can call methods on instances as well.
+
+.. code:: clojure
+
+    user=> (.area r1)
+    10000.0
+    user=> (.area sq-100)
+    10000.0
+
+Or modify the value of a member field.
+
+.. code:: clojure
+
+    user=> (set! (.x p1) 10)
+    10
+    user=> p1
+    #<Point {10.0, 0.0}>
+    user=> (set! (.width sq-100) 10)
+    10
+    user=> (set! (.height sq-100) 10)
+    10
+    user=> (.area sq-100)
+    100.0
+
+If you find yourself not remembering a OpenCV class behavior, the
+REPL gives you the opportunity to easily search the corresponding
+javadoc documention:
+
+.. code:: clojure
+
+    user=> (javadoc Rect)
+    "http://www.google.com/search?btnI=I%27m%20Feeling%20Lucky&q=allinurl:org/opencv/core/Rect.html"
+
+Mimic the OpenCV Java Tutorial Sample in the REPL
+-------------------------------------------------
+
+Let's now try to port to Clojure the `opencv java tutorial sample <http://docs.opencv.org/2.4.4-beta/doc/tutorials/introduction/desktop_java/java_dev_intro.html>`_.
+Instead of writing it in a source file we're going to evaluate it at the
+REPL.
+
+Following is the original Java source code of the cited sample.
+
+.. code:: java
+
+    import org.opencv.core.Mat;
+    import org.opencv.core.CvType;
+    import org.opencv.core.Scalar;
+
+    class SimpleSample {
+
+      static{ System.loadLibrary("opencv_java244"); }
+
+      public static void main(String[] args) {
+        Mat m = new Mat(5, 10, CvType.CV_8UC1, new Scalar(0));
+        System.out.println("OpenCV Mat: " + m);
+        Mat mr1 = m.row(1);
+        mr1.setTo(new Scalar(1));
+        Mat mc5 = m.col(5);
+        mc5.setTo(new Scalar(5));
+        System.out.println("OpenCV Mat data:\n" + m.dump());
+      }
+
+    }
+
+Add injections to the project
+-----------------------------
+
+Before start coding, we'd like to eliminate the boring need of
+interactively loading the native opencv lib any time we start a new REPL
+to interact with it.
+
+First, stop the REPL by evaluating the ``(exit)`` expression at the REPL
+prompt.
+
+.. code:: clojure
+
+    user=> (exit)
+    Bye for now!
+
+Then open your ``project.clj`` file and edit it as follows:
+
+.. code:: clojure
+
+    (defproject simple-sample "0.1.0-SNAPSHOT"
+      ...
+      :injections [(clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)])
+
+Here we're saying to load the opencv native lib anytime we run the REPL
+in such a way that we have not anymore to remember to manually do it.
+
+Rerun the ``lein repl`` task
+
+.. code:: bash
+
+    lein repl
+    nREPL server started on port 51645 on host 127.0.0.1
+    REPL-y 0.3.0
+    Clojure 1.5.1
+        Docs: (doc function-name-here)
+              (find-doc "part-of-name-here")
+      Source: (source function-name-here)
+     Javadoc: (javadoc java-object-or-class-here)
+        Exit: Control+D or (exit) or (quit)
+     Results: Stored in vars *1, *2, *3, an exception in *e
+
+    user=>
+
+Import the interested OpenCV java interfaces.
+
+.. code:: clojure
+
+    user=> (import '[org.opencv.core Mat CvType Scalar])
+    org.opencv.core.Scalar
+
+We're going to mimic almost verbatim the original OpenCV java tutorial
+to:
+
+-  create a 5x10 matrix with all its elements intialized to 0
+-  change the value of every element of the second row to 1
+-  change the value of every element of the 6th column to 5
+-  print the content of the obtained matrix
+
+.. code:: clojure
+
+    user=> (def m (Mat. 5 10 CvType/CV_8UC1 (Scalar. 0 0)))
+    #'user/m
+    user=> (def mr1 (.row m 1))
+    #'user/mr1
+    user=> (.setTo mr1 (Scalar. 1 0))
+    #<Mat Mat [ 1*10*CV_8UC1, isCont=true, isSubmat=true, nativeObj=0x7fc9dac49880, dataAddr=0x7fc9d9c98d5a ]>
+    user=> (def mc5 (.col m 5))
+    #'user/mc5
+    user=> (.setTo mc5 (Scalar. 5 0))
+    #<Mat Mat [ 5*1*CV_8UC1, isCont=false, isSubmat=true, nativeObj=0x7fc9d9c995a0, dataAddr=0x7fc9d9c98d55 ]>
+    user=> (println (.dump m))
+    [0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
+      1, 1, 1, 1, 1, 5, 1, 1, 1, 1;
+      0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
+      0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
+      0, 0, 0, 0, 0, 5, 0, 0, 0, 0]
+    nil
+
+If you are accustomed to a functional language all those abused and
+mutating nouns are going to irritate your preference for verbs. Even
+if the CLJ interop syntax is very handy and complete, there is still
+an impedance mismatch between any OOP language and any FP language
+(bein Scala a mixed paradigms programming language).
+
+To exit the REPL type ``(exit)``, ``ctr-D`` or ``(quit)`` at the REPL
+prompt.
+
+.. code:: clojure
+
+    user=> (exit)
+    Bye for now!
+
+Interactively load and blur an image
+------------------------------------
+
+In the next sample you will learn how to interactively load and blur and
+image from the REPL by using the following OpenCV methods:
+
+-  the ``imread`` static method from the ``Highgui`` class to read an
+   image from a file
+-  the ``imwrite`` static method from the ``Highgui`` class to write an
+   image to a file
+-  the ``GaussianBlur`` static method from the ``Imgproc`` class to
+   apply to blur the original image
+
+We're also going to use the ``Mat`` class which is returned from the
+``imread`` method and accpeted as the main argument to both the
+``GaussianBlur`` and the ``imwrite`` methods.
+
+Add an image to the project
+---------------------------
+
+First we want to add an image file to a newly create directory for
+storing static resources of the project.
+
+.. image:: images/lena.png
+   :alt: Original Image
+   :align: center
+
+.. code:: bash
+
+    mkdir -p resources/images
+    cp ~/opt/opencv/doc/tutorials/introduction/desktop_java/images/lena.png resource/images/
+
+Read the image
+--------------
+
+Now launch the REPL as usual and start by importing all the OpenCV
+classes we're going to use:
+
+.. code:: clojure
+
+    lein repl
+    nREPL server started on port 50624 on host 127.0.0.1
+    REPL-y 0.3.0
+    Clojure 1.5.1
+        Docs: (doc function-name-here)
+              (find-doc "part-of-name-here")
+      Source: (source function-name-here)
+     Javadoc: (javadoc java-object-or-class-here)
+        Exit: Control+D or (exit) or (quit)
+     Results: Stored in vars *1, *2, *3, an exception in *e
+
+    user=> (import '[org.opencv.core Mat Size CvType]
+                   '[org.opencv.highgui Highgui]
+                   '[org.opencv.imgproc Imgproc])
+    org.opencv.imgproc.Imgproc
+
+Now read the image from the ``resources/images/lena.png`` file.
+
+.. code:: clojure
+
+    user=> (def lena (Highgui/imread "resources/images/lena.png"))
+    #'user/lena
+    user=> lena
+    #<Mat Mat [ 512*512*CV_8UC3, isCont=true, isSubmat=false, nativeObj=0x7f9ab3054c40, dataAddr=0x19fea9010 ]>
+
+As you see, by simply evaluating the ``lena`` symbol we know that
+``lena.png`` is a ``512x512`` matrix of ``CV_8UC3`` elements type. Let's
+create a new ``Mat`` instance of the same dimensions and elements type.
+
+.. code:: clojure
+
+    user=> (def blurred (Mat. 512 512 CvType/CV_8UC3))
+    #'user/blurred
+    user=>
+
+Now apply a ``GaussianBlur`` filter using ``lena`` as the source matrix
+and ``blurred`` as the destination matrix.
+
+.. code:: clojure
+
+    user=> (Imgproc/GaussianBlur lena blurred (Size. 5 5) 3 3)
+    nil
+
+As a last step just save the ``blurred`` matrix in a new image file.
+
+.. code:: clojure
+
+    user=> (Highgui/imwrite "resources/images/blurred.png" blurred)
+    true
+    user=> (exit)
+    Bye for now!
+
+Following is the new blurred image of Lena.
+
+.. image:: images/blurred.png
+   :alt: Blurred Image
+   :align: center
+
+Next Steps
+==========
+
+This tutorial only introduces the very basic environment set up to be
+able to interact with OpenCV in a CLJ REPL.
+
+I recommend any Clojure newbie to read the `Clojure Java Interop chapter <http://clojure.org/java_interop>`_ to get all you need to know
+to interoperate with any plain java lib that has not been wrapped in
+Clojure to make it usable in a more idiomatic and functional way within
+Clojure.
+
+The OpenCV Java API does not wrap the ``highgui`` module
+functionalities depending on ``Qt`` (e.g. ``namedWindow`` and
+``imshow``. If you want to create windows and show images into them
+while interacting with OpenCV from the REPL, at the moment you're left
+at your own. You could use Java Swing to fill the gap.
+
+
+License
+-------
+
+Copyright Â© 2013 Giacomo (Mimmo) Cosenza aka Magomimmo
+
+Distributed under the BSD 3-clause License, the same of OpenCV.
diff --git a/doc/tutorials/introduction/clojure_dev_intro/images/blurred.png b/doc/tutorials/introduction/clojure_dev_intro/images/blurred.png
new file mode 100644 (file)
index 0000000..c8aeea8
Binary files /dev/null and b/doc/tutorials/introduction/clojure_dev_intro/images/blurred.png differ
diff --git a/doc/tutorials/introduction/clojure_dev_intro/images/lena.png b/doc/tutorials/introduction/clojure_dev_intro/images/lena.png
new file mode 100644 (file)
index 0000000..68342fa
Binary files /dev/null and b/doc/tutorials/introduction/clojure_dev_intro/images/lena.png differ
diff --git a/doc/tutorials/introduction/table_of_content_introduction/images/clojure-logo.png b/doc/tutorials/introduction/table_of_content_introduction/images/clojure-logo.png
new file mode 100644 (file)
index 0000000..f8a29b9
Binary files /dev/null and b/doc/tutorials/introduction/table_of_content_introduction/images/clojure-logo.png differ
index ee8dd67..ba67fb6 100644 (file)
@@ -156,6 +156,21 @@ world of the OpenCV.
                         :height: 90pt
                         :width:  90pt
 
+  ================ =================================================
+  |ClojureLogo|    **Title:** :ref:`clojure_dev_intro`
+
+                   *Compatibility:* > OpenCV 2.4.4
+
+                   *Author:* |Author_MimmoC|
+
+                   A tutorial on how to interactively use OpenCV from the Clojure REPL.
+
+  ================ =================================================
+
+     .. |ClojureLogo| image:: images/clojure-logo.png
+                        :height: 90pt
+                        :width:  90pt
+
 * **Android**
 
   .. tabularcolumns:: m{100pt} m{300pt}
@@ -314,6 +329,7 @@ world of the OpenCV.
    ../windows_visual_studio_image_watch/windows_visual_studio_image_watch
    ../desktop_java/java_dev_intro
    ../java_eclipse/java_eclipse
+   ../clojure_dev_intro/clojure_dev_intro
    ../android_binary_package/android_dev_intro
    ../android_binary_package/O4A_SDK
    ../android_binary_package/dev_with_OCV_on_Android
index 87263fa..5e72764 100644 (file)
@@ -1262,5 +1262,4 @@ template<> struct ParamType<uchar>
 #include "opencv2/core/operations.hpp"
 #include "opencv2/core/cvstd.inl.hpp"
 
-
 #endif /*__OPENCV_CORE_HPP__*/
index 18a996b..6e78300 100644 (file)
@@ -223,19 +223,26 @@ enum {
 CV_EXPORTS void error(int _code, const String& _err, const char* _func, const char* _file, int _line);
 
 #ifdef __GNUC__
-#  if defined __clang__ || defined __APPLE__
-#    pragma GCC diagnostic push
-#    pragma GCC diagnostic ignored "-Winvalid-noreturn"
-#  endif
+# if defined __clang__ || defined __APPLE__
+#   pragma GCC diagnostic push
+#   pragma GCC diagnostic ignored "-Winvalid-noreturn"
+# endif
 #endif
 CV_INLINE CV_NORETURN void errorNoReturn(int _code, const String& _err, const char* _func, const char* _file, int _line)
 {
     error(_code, _err, _func, _file, _line);
+#ifdef __GNUC__
+# if !defined __clang__ && !defined __APPLE__
+    // this suppresses this warning: "noreturn" function does return [enabled by default]
+    __builtin_trap();
+    // or use infinite loop: for (;;) {}
+# endif
+#endif
 }
 #ifdef __GNUC__
-#  if defined __clang__ || defined __APPLE__
-#    pragma GCC diagnostic pop
-#  endif
+# if defined __clang__ || defined __APPLE__
+#   pragma GCC diagnostic pop
+# endif
 #endif
 
 
diff --git a/modules/core/include/opencv2/core/directx.hpp b/modules/core/include/opencv2/core/directx.hpp
new file mode 100644 (file)
index 0000000..2a8991a
--- /dev/null
@@ -0,0 +1,95 @@
+/*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-2013, Advanced Micro Devices, 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 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 copyright holders 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_DIRECTX_HPP__
+#define __OPENCV_CORE_DIRECTX_HPP__
+
+#include "mat.hpp"
+#include "ocl.hpp"
+
+#if !defined(__d3d11_h__)
+struct ID3D11Device;
+struct ID3D11Texture2D;
+#endif
+
+#if !defined(__d3d10_h__)
+struct ID3D10Device;
+struct ID3D10Texture2D;
+#endif
+
+#if !defined(_D3D9_H_)
+struct IDirect3DDevice9;
+struct IDirect3DDevice9Ex;
+struct IDirect3DSurface9;
+#endif
+
+namespace cv { namespace directx {
+
+namespace ocl {
+using namespace cv::ocl;
+
+// TODO static functions in the Context class
+CV_EXPORTS Context2& initializeContextFromD3D11Device(ID3D11Device* pD3D11Device);
+CV_EXPORTS Context2& initializeContextFromD3D10Device(ID3D10Device* pD3D10Device);
+CV_EXPORTS Context2& initializeContextFromDirect3DDevice9Ex(IDirect3DDevice9Ex* pDirect3DDevice9Ex);
+CV_EXPORTS Context2& initializeContextFromDirect3DDevice9(IDirect3DDevice9* pDirect3DDevice9);
+
+} // namespace cv::directx::ocl
+
+CV_EXPORTS void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D);
+CV_EXPORTS void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst);
+
+CV_EXPORTS void convertToD3D10Texture2D(InputArray src, ID3D10Texture2D* pD3D10Texture2D);
+CV_EXPORTS void convertFromD3D10Texture2D(ID3D10Texture2D* pD3D10Texture2D, OutputArray dst);
+
+CV_EXPORTS void convertToDirect3DSurface9(InputArray src, IDirect3DSurface9* pDirect3DSurface9, void* surfaceSharedHandle = NULL);
+CV_EXPORTS void convertFromDirect3DSurface9(IDirect3DSurface9* pDirect3DSurface9, OutputArray dst, void* surfaceSharedHandle = NULL);
+
+// Get OpenCV type from DirectX type, return -1 if there is no equivalent
+CV_EXPORTS int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT); // enum DXGI_FORMAT for D3D10/D3D11
+
+// Get OpenCV type from DirectX type, return -1 if there is no equivalent
+CV_EXPORTS int getTypeFromD3DFORMAT(const int iD3DFORMAT); // enum D3DTYPE for D3D9
+
+
+} } // namespace cv::directx
+
+#endif // __OPENCV_CORE_DIRECTX_HPP__
index 8a0a6a6..9c2f595 100644 (file)
@@ -617,9 +617,9 @@ inline void Mat::release()
 {
     if( u && CV_XADD(&u->refcount, -1) == 1 )
         deallocate();
+    u = NULL;
     data = datastart = dataend = datalimit = 0;
     size.p[0] = 0;
-    u = 0;
 }
 
 inline
index f253594..cb72c25 100644 (file)
@@ -48,6 +48,7 @@ namespace cv { namespace ocl {
 
 CV_EXPORTS bool haveOpenCL();
 CV_EXPORTS bool useOpenCL();
+CV_EXPORTS bool haveAmdBlas();
 CV_EXPORTS void setUseOpenCL(bool flag);
 CV_EXPORTS void finish2();
 
@@ -214,10 +215,33 @@ public:
     Program getProg(const ProgramSource2& prog,
                     const String& buildopt, String& errmsg);
 
-    static Context2& getDefault();
+    static Context2& getDefault(bool initialize = true);
     void* ptr() const;
+
+    struct Impl;
+    inline struct Impl* _getImpl() const { return p; };
 protected:
+    Impl* p;
+};
+
+
+// TODO Move to internal header
+void initializeContextFromHandle(Context2& ctx, void* platform, void* context, void* device);
+
+class CV_EXPORTS Platform
+{
+public:
+    Platform();
+    ~Platform();
+    Platform(const Platform& p);
+    Platform& operator = (const Platform& p);
+
+    void* ptr() const;
+    static Platform& getDefault();
+
     struct Impl;
+    inline struct Impl* _getImpl() const { return p; };
+protected:
     Impl* p;
 };
 
index dae3828..2d7d313 100644 (file)
@@ -305,6 +305,32 @@ private:
     AutoLock& operator = (const AutoLock&);
 };
 
+class CV_EXPORTS TLSDataContainer
+{
+private:
+    int key_;
+protected:
+    TLSDataContainer();
+    virtual ~TLSDataContainer();
+public:
+    virtual void* createDataInstance() const = 0;
+    virtual void deleteDataInstance(void* data) const = 0;
+
+    void* getData() const;
+};
+
+template <typename T>
+class TLSData : protected TLSDataContainer
+{
+public:
+    inline TLSData() {}
+    inline ~TLSData() {}
+    inline T* get() const { return (T*)getData(); }
+private:
+    virtual void* createDataInstance() const { return new T; }
+    virtual void deleteDataInstance(void* data) const { delete (T*)data; }
+};
+
 // The CommandLineParser class is designed for command line arguments parsing
 
 class CV_EXPORTS CommandLineParser
diff --git a/modules/core/src/directx.cpp b/modules/core/src/directx.cpp
new file mode 100644 (file)
index 0000000..071df03
--- /dev/null
@@ -0,0 +1,1134 @@
+/*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-2013, Advanced Micro Devices, 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 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 copyright holders 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*/
+
+#include "precomp.hpp"
+
+#include "opencv2/core.hpp"
+#include "opencv2/core/ocl.hpp"
+#include "opencv2/core/directx.hpp"
+
+#ifdef HAVE_DIRECTX
+#include <vector>
+# include "directx.inc.hpp"
+#else // HAVE_DIRECTX
+#define NO_DIRECTX_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without DirectX support")
+#endif
+
+#ifndef HAVE_OPENCL
+# define NO_OPENCL_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without OpenCL support")
+#endif // HAVE_OPENCL
+
+namespace cv { namespace directx {
+
+int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT)
+{
+    (void)iDXGI_FORMAT;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#else
+    const int errorType = -1;
+    switch ((enum DXGI_FORMAT)iDXGI_FORMAT)
+    {
+    //case DXGI_FORMAT_UNKNOWN:
+    //case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+    case DXGI_FORMAT_R32G32B32A32_FLOAT: return CV_32FC4;
+    case DXGI_FORMAT_R32G32B32A32_UINT:
+    case DXGI_FORMAT_R32G32B32A32_SINT:  return CV_32SC4;
+    //case DXGI_FORMAT_R32G32B32_TYPELESS:
+    case DXGI_FORMAT_R32G32B32_FLOAT: return CV_32FC3;
+    case DXGI_FORMAT_R32G32B32_UINT:
+    case DXGI_FORMAT_R32G32B32_SINT: return CV_32SC3;
+    //case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+    //case DXGI_FORMAT_R16G16B16A16_FLOAT:
+    case DXGI_FORMAT_R16G16B16A16_UNORM:
+    case DXGI_FORMAT_R16G16B16A16_UINT: return CV_16UC4;
+    case DXGI_FORMAT_R16G16B16A16_SNORM:
+    case DXGI_FORMAT_R16G16B16A16_SINT: return CV_16SC4;
+    //case DXGI_FORMAT_R32G32_TYPELESS:
+    //case DXGI_FORMAT_R32G32_FLOAT:
+    //case DXGI_FORMAT_R32G32_UINT:
+    //case DXGI_FORMAT_R32G32_SINT:
+    //case DXGI_FORMAT_R32G8X24_TYPELESS:
+    //case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+    //case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+    //case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+    //case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+    //case DXGI_FORMAT_R10G10B10A2_UNORM:
+    //case DXGI_FORMAT_R10G10B10A2_UINT:
+    //case DXGI_FORMAT_R11G11B10_FLOAT:
+    //case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+    case DXGI_FORMAT_R8G8B8A8_UNORM:
+    case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+    case DXGI_FORMAT_R8G8B8A8_UINT: return CV_8UC4;
+    case DXGI_FORMAT_R8G8B8A8_SNORM:
+    case DXGI_FORMAT_R8G8B8A8_SINT: return CV_8SC4;
+    //case DXGI_FORMAT_R16G16_TYPELESS:
+    //case DXGI_FORMAT_R16G16_FLOAT:
+    case DXGI_FORMAT_R16G16_UNORM:
+    case DXGI_FORMAT_R16G16_UINT: return CV_16UC2;
+    case DXGI_FORMAT_R16G16_SNORM:
+    case DXGI_FORMAT_R16G16_SINT: return CV_16SC2;
+    //case DXGI_FORMAT_R32_TYPELESS:
+    //case DXGI_FORMAT_D32_FLOAT:
+    case DXGI_FORMAT_R32_FLOAT: return CV_32FC1;
+    case DXGI_FORMAT_R32_UINT:
+    case DXGI_FORMAT_R32_SINT: return CV_32SC1;
+    //case DXGI_FORMAT_R24G8_TYPELESS:
+    //case DXGI_FORMAT_D24_UNORM_S8_UINT:
+    //case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+    //case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+    //case DXGI_FORMAT_R8G8_TYPELESS:
+    case DXGI_FORMAT_R8G8_UNORM:
+    case DXGI_FORMAT_R8G8_UINT: return CV_8UC2;
+    case DXGI_FORMAT_R8G8_SNORM:
+    case DXGI_FORMAT_R8G8_SINT: return CV_8SC2;
+    //case DXGI_FORMAT_R16_TYPELESS:
+    //case DXGI_FORMAT_R16_FLOAT:
+    case DXGI_FORMAT_D16_UNORM:
+    case DXGI_FORMAT_R16_UNORM:
+    case DXGI_FORMAT_R16_UINT: return CV_16UC1;
+    case DXGI_FORMAT_R16_SNORM:
+    case DXGI_FORMAT_R16_SINT: return CV_16SC1;
+    //case DXGI_FORMAT_R8_TYPELESS:
+    case DXGI_FORMAT_R8_UNORM:
+    case DXGI_FORMAT_R8_UINT: return CV_8UC1;
+    case DXGI_FORMAT_R8_SNORM:
+    case DXGI_FORMAT_R8_SINT: return CV_8SC1;
+    case DXGI_FORMAT_A8_UNORM: return CV_8UC1;
+    //case DXGI_FORMAT_R1_UNORM:
+    //case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+    //case DXGI_FORMAT_R8G8_B8G8_UNORM:
+    //case DXGI_FORMAT_G8R8_G8B8_UNORM:
+    //case DXGI_FORMAT_BC1_TYPELESS:
+    //case DXGI_FORMAT_BC1_UNORM:
+    //case DXGI_FORMAT_BC1_UNORM_SRGB:
+    //case DXGI_FORMAT_BC2_TYPELESS:
+    //case DXGI_FORMAT_BC2_UNORM:
+    //case DXGI_FORMAT_BC2_UNORM_SRGB:
+    //case DXGI_FORMAT_BC3_TYPELESS:
+    //case DXGI_FORMAT_BC3_UNORM:
+    //case DXGI_FORMAT_BC3_UNORM_SRGB:
+    //case DXGI_FORMAT_BC4_TYPELESS:
+    //case DXGI_FORMAT_BC4_UNORM:
+    //case DXGI_FORMAT_BC4_SNORM:
+    //case DXGI_FORMAT_BC5_TYPELESS:
+    //case DXGI_FORMAT_BC5_UNORM:
+    //case DXGI_FORMAT_BC5_SNORM:
+    //case DXGI_FORMAT_B5G6R5_UNORM:
+    //case DXGI_FORMAT_B5G5R5A1_UNORM:
+    case DXGI_FORMAT_B8G8R8A8_UNORM:
+    case DXGI_FORMAT_B8G8R8X8_UNORM: return CV_8UC4;
+    //case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+    //case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+    case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return CV_8UC4;
+    //case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+    case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return CV_8UC4;
+    //case DXGI_FORMAT_BC6H_TYPELESS:
+    //case DXGI_FORMAT_BC6H_UF16:
+    //case DXGI_FORMAT_BC6H_SF16:
+    //case DXGI_FORMAT_BC7_TYPELESS:
+    //case DXGI_FORMAT_BC7_UNORM:
+    //case DXGI_FORMAT_BC7_UNORM_SRGB:
+    default: break;
+    }
+    return errorType;
+#endif
+}
+
+int getTypeFromD3DFORMAT(const int iD3DFORMAT)
+{
+    (void)iD3DFORMAT;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#else
+    const int errorType = -1;
+    switch ((enum _D3DFORMAT)iD3DFORMAT)
+    {
+    //case D3DFMT_UNKNOWN:
+    case D3DFMT_R8G8B8: return CV_8UC3;
+    case D3DFMT_A8R8G8B8:
+    case D3DFMT_X8R8G8B8: return CV_8UC4;
+    //case D3DFMT_R5G6B5:
+    //case D3DFMT_X1R5G5B5:
+    //case D3DFMT_A1R5G5B5:
+    //case D3DFMT_A4R4G4B4:
+    //case D3DFMT_R3G3B2:
+    case D3DFMT_A8: return CV_8UC1;
+    //case D3DFMT_A8R3G3B2:
+    //case D3DFMT_X4R4G4B4:
+    //case D3DFMT_A2B10G10R10:
+    case D3DFMT_A8B8G8R8:
+    case D3DFMT_X8B8G8R8: return CV_8UC4;
+    //case D3DFMT_G16R16:
+    //case D3DFMT_A2R10G10B10:
+    //case D3DFMT_A16B16G16R16:
+
+    case D3DFMT_A8P8: return CV_8UC2;
+    case D3DFMT_P8: return CV_8UC1;
+
+    case D3DFMT_L8: return CV_8UC1;
+    case D3DFMT_A8L8: return CV_8UC2;
+    //case D3DFMT_A4L4:
+
+    case D3DFMT_V8U8: return CV_8UC2;
+    //case D3DFMT_L6V5U5:
+    case D3DFMT_X8L8V8U8:
+    case D3DFMT_Q8W8V8U8: return CV_8UC4;
+    case D3DFMT_V16U16: return CV_16UC4; // TODO 16SC4 ?
+    //case D3DFMT_A2W10V10U10:
+
+    case D3DFMT_D16_LOCKABLE: return CV_16UC1;
+    case D3DFMT_D32: return CV_32SC1;
+    //case D3DFMT_D15S1:
+    //case D3DFMT_D24S8:
+    //case D3DFMT_D24X8:
+    //case D3DFMT_D24X4S4:
+    case D3DFMT_D16: return CV_16UC1;
+
+    case D3DFMT_D32F_LOCKABLE: return CV_32FC1;
+    default: break;
+    }
+    return errorType;
+#endif
+}
+
+namespace ocl {
+
+#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+static bool g_isDirect3DDevice9Ex = false; // Direct3DDevice9Ex or Direct3DDevice9 was used
+#endif
+
+Context2& initializeContextFromD3D11Device(ID3D11Device* pD3D11Device)
+{
+    (void)pD3D11Device;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif !defined(HAVE_OPENCL)
+    NO_OPENCL_SUPPORT_ERROR;
+#else
+    cl_uint numPlatforms;
+    cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+    if (numPlatforms == 0)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
+
+    std::vector<cl_platform_id> platforms(numPlatforms);
+    status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+
+    // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
+
+    int found = -1;
+    cl_device_id device = NULL;
+    cl_uint numDevices = 0;
+    cl_context context = NULL;
+
+    // try with CL_PREFERRED_DEVICES_FOR_D3D11_KHR
+    for (int i = 0; i < (int)numPlatforms; i++)
+    {
+        clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
+        if (!clGetDeviceIDsFromD3D11KHR)
+            continue;
+
+        device = NULL;
+        numDevices = 0;
+        status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
+                CL_PREFERRED_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
+        if (status != CL_SUCCESS)
+            continue;
+        if (numDevices > 0)
+        {
+            cl_context_properties properties[] = {
+                    CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                    CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
+                    CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                    NULL, NULL
+            };
+            context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+            if (status != CL_SUCCESS)
+            {
+                clReleaseDevice(device);
+            }
+            else
+            {
+                found = i;
+                break;
+            }
+        }
+    }
+    if (found < 0)
+    {
+        // try with CL_ALL_DEVICES_FOR_D3D11_KHR
+        for (int i = 0; i < (int)numPlatforms; i++)
+        {
+            clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
+                    clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
+            if (!clGetDeviceIDsFromD3D11KHR)
+                continue;
+
+            device = NULL;
+            numDevices = 0;
+            status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
+                    CL_ALL_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
+            if (status != CL_SUCCESS)
+                continue;
+            if (numDevices > 0)
+            {
+                cl_context_properties properties[] = {
+                        CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                        CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
+                        CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                        NULL, NULL
+                };
+                context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+                if (status != CL_SUCCESS)
+                {
+                    clReleaseDevice(device);
+                }
+                else
+                {
+                    found = i;
+                    break;
+                }
+            }
+        }
+        if (found < 0)
+            CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
+    }
+
+
+    Context2& ctx = Context2::getDefault(false);
+    initializeContextFromHandle(ctx, platforms[found], context, device);
+    return ctx;
+#endif
+}
+
+Context2& initializeContextFromD3D10Device(ID3D10Device* pD3D10Device)
+{
+    (void)pD3D10Device;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif !defined(HAVE_OPENCL)
+    NO_OPENCL_SUPPORT_ERROR;
+#else
+    cl_uint numPlatforms;
+    cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+    if (numPlatforms == 0)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
+
+    std::vector<cl_platform_id> platforms(numPlatforms);
+    status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+
+    // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
+
+    int found = -1;
+    cl_device_id device = NULL;
+    cl_uint numDevices = 0;
+    cl_context context = NULL;
+
+    // try with CL_PREFERRED_DEVICES_FOR_D3D10_KHR
+    for (int i = 0; i < (int)numPlatforms; i++)
+    {
+        clGetDeviceIDsFromD3D10KHR_fn clGetDeviceIDsFromD3D10KHR = (clGetDeviceIDsFromD3D10KHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D10KHR");
+        if (!clGetDeviceIDsFromD3D10KHR)
+            continue;
+
+        device = NULL;
+        numDevices = 0;
+        status = clGetDeviceIDsFromD3D10KHR(platforms[i], CL_D3D10_DEVICE_KHR, pD3D10Device,
+                CL_PREFERRED_DEVICES_FOR_D3D10_KHR, 1, &device, &numDevices);
+        if (status != CL_SUCCESS)
+            continue;
+        if (numDevices > 0)
+        {
+            cl_context_properties properties[] = {
+                    CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                    CL_CONTEXT_D3D10_DEVICE_KHR, (cl_context_properties)(pD3D10Device),
+                    CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                    NULL, NULL
+            };
+            context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+            if (status != CL_SUCCESS)
+            {
+                clReleaseDevice(device);
+            }
+            else
+            {
+                found = i;
+                break;
+            }
+        }
+    }
+    if (found < 0)
+    {
+        // try with CL_ALL_DEVICES_FOR_D3D10_KHR
+        for (int i = 0; i < (int)numPlatforms; i++)
+        {
+            clGetDeviceIDsFromD3D10KHR_fn clGetDeviceIDsFromD3D10KHR = (clGetDeviceIDsFromD3D10KHR_fn)
+                    clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D10KHR");
+            if (!clGetDeviceIDsFromD3D10KHR)
+                continue;
+
+            device = NULL;
+            numDevices = 0;
+            status = clGetDeviceIDsFromD3D10KHR(platforms[i], CL_D3D10_DEVICE_KHR, pD3D10Device,
+                    CL_ALL_DEVICES_FOR_D3D10_KHR, 1, &device, &numDevices);
+            if (status != CL_SUCCESS)
+                continue;
+            if (numDevices > 0)
+            {
+                cl_context_properties properties[] = {
+                        CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                        CL_CONTEXT_D3D10_DEVICE_KHR, (cl_context_properties)(pD3D10Device),
+                        CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                        NULL, NULL
+                };
+                context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+                if (status != CL_SUCCESS)
+                {
+                    clReleaseDevice(device);
+                }
+                else
+                {
+                    found = i;
+                    break;
+                }
+            }
+        }
+        if (found < 0)
+            CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
+    }
+
+
+    Context2& ctx = Context2::getDefault(false);
+    initializeContextFromHandle(ctx, platforms[found], context, device);
+    return ctx;
+#endif
+}
+
+Context2& initializeContextFromDirect3DDevice9Ex(IDirect3DDevice9Ex* pDirect3DDevice9Ex)
+{
+    (void)pDirect3DDevice9Ex;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif !defined(HAVE_OPENCL)
+    NO_OPENCL_SUPPORT_ERROR;
+#else
+    cl_uint numPlatforms;
+    cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+    if (numPlatforms == 0)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
+
+    std::vector<cl_platform_id> platforms(numPlatforms);
+    status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+
+    // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
+
+    int found = -1;
+    cl_device_id device = NULL;
+    cl_uint numDevices = 0;
+    cl_context context = NULL;
+
+    // try with CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
+    for (int i = 0; i < (int)numPlatforms; i++)
+    {
+        clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
+        if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
+            continue;
+
+        device = NULL;
+        numDevices = 0;
+        cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9EX_KHR;
+        status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9Ex,
+                CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
+        if (status != CL_SUCCESS)
+            continue;
+        if (numDevices > 0)
+        {
+            cl_context_properties properties[] = {
+                    CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                    CL_CONTEXT_ADAPTER_D3D9EX_KHR, (cl_context_properties)(pDirect3DDevice9Ex),
+                    CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                    NULL, NULL
+            };
+            context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+            if (status != CL_SUCCESS)
+            {
+                clReleaseDevice(device);
+            }
+            else
+            {
+                found = i;
+                break;
+            }
+        }
+    }
+    if (found < 0)
+    {
+        // try with CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
+        for (int i = 0; i < (int)numPlatforms; i++)
+        {
+            clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
+                    clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
+            if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
+                continue;
+
+            device = NULL;
+            numDevices = 0;
+            cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9EX_KHR;
+            status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9Ex,
+                    CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
+            if (status != CL_SUCCESS)
+                continue;
+            if (numDevices > 0)
+            {
+                cl_context_properties properties[] = {
+                        CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                        CL_CONTEXT_ADAPTER_D3D9EX_KHR, (cl_context_properties)(pDirect3DDevice9Ex),
+                        CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                        NULL, NULL
+                };
+                context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+                if (status != CL_SUCCESS)
+                {
+                    clReleaseDevice(device);
+                }
+                else
+                {
+                    found = i;
+                    break;
+                }
+            }
+        }
+        if (found < 0)
+            CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
+    }
+
+    Context2& ctx = Context2::getDefault(false);
+    initializeContextFromHandle(ctx, platforms[found], context, device);
+    g_isDirect3DDevice9Ex = true;
+    return ctx;
+#endif
+}
+
+Context2& initializeContextFromDirect3DDevice9(IDirect3DDevice9* pDirect3DDevice9)
+{
+    (void)pDirect3DDevice9;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif !defined(HAVE_OPENCL)
+    NO_OPENCL_SUPPORT_ERROR;
+#else
+    cl_uint numPlatforms;
+    cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+    if (numPlatforms == 0)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
+
+    std::vector<cl_platform_id> platforms(numPlatforms);
+    status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+
+    // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
+
+    int found = -1;
+    cl_device_id device = NULL;
+    cl_uint numDevices = 0;
+    cl_context context = NULL;
+
+    // try with CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
+    for (int i = 0; i < (int)numPlatforms; i++)
+    {
+        clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
+        if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
+            continue;
+
+        device = NULL;
+        numDevices = 0;
+        cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9_KHR;
+        status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9,
+                CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
+        if (status != CL_SUCCESS)
+            continue;
+        if (numDevices > 0)
+        {
+            cl_context_properties properties[] = {
+                    CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                    CL_CONTEXT_ADAPTER_D3D9_KHR, (cl_context_properties)(pDirect3DDevice9),
+                    CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                    NULL, NULL
+            };
+            context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+            if (status != CL_SUCCESS)
+            {
+                clReleaseDevice(device);
+            }
+            else
+            {
+                found = i;
+                break;
+            }
+        }
+    }
+    if (found < 0)
+    {
+        // try with CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
+        for (int i = 0; i < (int)numPlatforms; i++)
+        {
+            clGetDeviceIDsFromDX9MediaAdapterKHR_fn clGetDeviceIDsFromDX9MediaAdapterKHR = (clGetDeviceIDsFromDX9MediaAdapterKHR_fn)
+                    clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromDX9MediaAdapterKHR");
+            if (!clGetDeviceIDsFromDX9MediaAdapterKHR)
+                continue;
+
+            device = NULL;
+            numDevices = 0;
+            cl_dx9_media_adapter_type_khr type = CL_ADAPTER_D3D9_KHR;
+            status = clGetDeviceIDsFromDX9MediaAdapterKHR(platforms[i], 1, &type, &pDirect3DDevice9,
+                    CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1, &device, &numDevices);
+            if (status != CL_SUCCESS)
+                continue;
+            if (numDevices > 0)
+            {
+                cl_context_properties properties[] = {
+                        CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+                        CL_CONTEXT_ADAPTER_D3D9_KHR, (cl_context_properties)(pDirect3DDevice9),
+                        CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+                        NULL, NULL
+                };
+                context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+                if (status != CL_SUCCESS)
+                {
+                    clReleaseDevice(device);
+                }
+                else
+                {
+                    found = i;
+                    break;
+                }
+            }
+        }
+        if (found < 0)
+            CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
+    }
+
+    Context2& ctx = Context2::getDefault(false);
+    initializeContextFromHandle(ctx, platforms[found], context, device);
+    g_isDirect3DDevice9Ex = false;
+    return ctx;
+#endif
+}
+
+} // namespace cv::ocl
+
+#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+clCreateFromD3D11Texture2DKHR_fn clCreateFromD3D11Texture2DKHR = NULL;
+clEnqueueAcquireD3D11ObjectsKHR_fn clEnqueueAcquireD3D11ObjectsKHR = NULL;
+clEnqueueReleaseD3D11ObjectsKHR_fn clEnqueueReleaseD3D11ObjectsKHR = NULL;
+
+static void __OpenCLinitializeD3D11()
+{
+    using namespace cv::ocl;
+    static cl_platform_id initializedPlatform = NULL;
+    cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
+    if (initializedPlatform != platform)
+    {
+        clCreateFromD3D11Texture2DKHR = (clCreateFromD3D11Texture2DKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D11Texture2DKHR");
+        clEnqueueAcquireD3D11ObjectsKHR = (clEnqueueAcquireD3D11ObjectsKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D11ObjectsKHR");
+        clEnqueueReleaseD3D11ObjectsKHR = (clEnqueueReleaseD3D11ObjectsKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D11ObjectsKHR");
+        initializedPlatform = platform;
+    }
+    if (!clCreateFromD3D11Texture2DKHR || !clEnqueueAcquireD3D11ObjectsKHR || !clEnqueueReleaseD3D11ObjectsKHR)
+    {
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D11");
+    }
+}
+#endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+
+void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
+{
+    (void)src; (void)pD3D11Texture2D;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D11();
+
+    D3D11_TEXTURE2D_DESC desc = { 0 };
+    pD3D11Texture2D->GetDesc(&desc);
+
+    int srcType = src.type();
+    int textureType = getTypeFromDXGI_FORMAT(desc.Format);
+    CV_Assert(textureType == srcType);
+
+    Size srcSize = src.size();
+    CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    UMat u = src.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_mem clImage = clCreateFromD3D11Texture2DKHR(context, CL_MEM_WRITE_ONLY, pD3D11Texture2D, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsKHR failed");
+    size_t offset = 0; // TODO
+    size_t dst_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
+    status = clEnqueueReleaseD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO memcpy
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
+{
+    (void)pD3D11Texture2D; (void)dst;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D11();
+
+    D3D11_TEXTURE2D_DESC desc = { 0 };
+    pD3D11Texture2D->GetDesc(&desc);
+
+    int textureType = getTypeFromDXGI_FORMAT(desc.Format);
+    CV_Assert(textureType >= 0);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
+    dst.create(Size(desc.Width, desc.Height), textureType);
+    UMat u = dst.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_mem clImage = clCreateFromD3D11Texture2DKHR(context, CL_MEM_READ_ONLY, pD3D11Texture2D, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsKHR failed");
+    size_t offset = 0; // TODO
+    size_t src_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
+    status = clEnqueueReleaseD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO memcpy
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+
+#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+clCreateFromD3D10Texture2DKHR_fn clCreateFromD3D10Texture2DKHR = NULL;
+clEnqueueAcquireD3D10ObjectsKHR_fn clEnqueueAcquireD3D10ObjectsKHR = NULL;
+clEnqueueReleaseD3D10ObjectsKHR_fn clEnqueueReleaseD3D10ObjectsKHR = NULL;
+
+static void __OpenCLinitializeD3D10()
+{
+    using namespace cv::ocl;
+    static cl_platform_id initializedPlatform = NULL;
+    cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
+    if (initializedPlatform != platform)
+    {
+        clCreateFromD3D10Texture2DKHR = (clCreateFromD3D10Texture2DKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D10Texture2DKHR");
+        clEnqueueAcquireD3D10ObjectsKHR = (clEnqueueAcquireD3D10ObjectsKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D10ObjectsKHR");
+        clEnqueueReleaseD3D10ObjectsKHR = (clEnqueueReleaseD3D10ObjectsKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D10ObjectsKHR");
+        initializedPlatform = platform;
+    }
+    if (!clCreateFromD3D10Texture2DKHR || !clEnqueueAcquireD3D10ObjectsKHR || !clEnqueueReleaseD3D10ObjectsKHR)
+    {
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D10");
+    }
+}
+#endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+
+void convertToD3D10Texture2D(InputArray src, ID3D10Texture2D* pD3D10Texture2D)
+{
+    (void)src; (void)pD3D10Texture2D;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D10();
+
+    D3D10_TEXTURE2D_DESC desc = { 0 };
+    pD3D10Texture2D->GetDesc(&desc);
+
+    int srcType = src.type();
+    int textureType = getTypeFromDXGI_FORMAT(desc.Format);
+    CV_Assert(textureType == srcType);
+
+    Size srcSize = src.size();
+    CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    UMat u = src.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_mem clImage = clCreateFromD3D10Texture2DKHR(context, CL_MEM_WRITE_ONLY, pD3D10Texture2D, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D10Texture2DKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D10ObjectsKHR failed");
+    size_t offset = 0; // TODO
+    size_t dst_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
+    status = clEnqueueReleaseD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D10ObjectsKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO memcpy
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+void convertFromD3D10Texture2D(ID3D10Texture2D* pD3D10Texture2D, OutputArray dst)
+{
+    (void)pD3D10Texture2D; (void)dst;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D10();
+
+    D3D10_TEXTURE2D_DESC desc = { 0 };
+    pD3D10Texture2D->GetDesc(&desc);
+
+    int textureType = getTypeFromDXGI_FORMAT(desc.Format);
+    CV_Assert(textureType >= 0);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
+    dst.create(Size(desc.Width, desc.Height), textureType);
+    UMat u = dst.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_mem clImage = clCreateFromD3D10Texture2DKHR(context, CL_MEM_READ_ONLY, pD3D10Texture2D, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D10Texture2DKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D10ObjectsKHR failed");
+    size_t offset = 0; // TODO
+    size_t src_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
+    status = clEnqueueReleaseD3D10ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D10ObjectsKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO memcpy
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+
+#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+clCreateFromDX9MediaSurfaceKHR_fn clCreateFromDX9MediaSurfaceKHR = NULL;
+clEnqueueAcquireDX9MediaSurfacesKHR_fn clEnqueueAcquireDX9MediaSurfacesKHR = NULL;
+clEnqueueReleaseDX9MediaSurfacesKHR_fn clEnqueueReleaseDX9MediaSurfacesKHR = NULL;
+
+static void __OpenCLinitializeD3D9()
+{
+    using namespace cv::ocl;
+    static cl_platform_id initializedPlatform = NULL;
+    cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
+    if (initializedPlatform != platform)
+    {
+        clCreateFromDX9MediaSurfaceKHR = (clCreateFromDX9MediaSurfaceKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromDX9MediaSurfaceKHR");
+        clEnqueueAcquireDX9MediaSurfacesKHR = (clEnqueueAcquireDX9MediaSurfacesKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireDX9MediaSurfacesKHR");
+        clEnqueueReleaseDX9MediaSurfacesKHR = (clEnqueueReleaseDX9MediaSurfacesKHR_fn)
+                clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseDX9MediaSurfacesKHR");
+        initializedPlatform = platform;
+    }
+    if (!clCreateFromDX9MediaSurfaceKHR || !clEnqueueAcquireDX9MediaSurfacesKHR || !clEnqueueReleaseDX9MediaSurfacesKHR)
+    {
+        CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D9");
+    }
+}
+#endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+
+void convertToDirect3DSurface9(InputArray src, IDirect3DSurface9* pDirect3DSurface9, void* surfaceSharedHandle)
+{
+    (void)src; (void)pDirect3DSurface9; (void)surfaceSharedHandle;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D9();
+
+    D3DSURFACE_DESC desc;
+    if (FAILED(pDirect3DSurface9->GetDesc(&desc)))
+    {
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: Can't get D3D surface description");
+    }
+
+    int srcType = src.type();
+    int surfaceType = getTypeFromD3DFORMAT(desc.Format);
+    CV_Assert(surfaceType == srcType);
+
+    Size srcSize = src.size();
+    CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    UMat u = src.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_dx9_surface_info_khr surfaceInfo = {pDirect3DSurface9, (HANDLE)surfaceSharedHandle};
+    cl_mem clImage = clCreateFromDX9MediaSurfaceKHR(context, CL_MEM_WRITE_ONLY,
+            ocl::g_isDirect3DDevice9Ex ? CL_ADAPTER_D3D9EX_KHR : CL_ADAPTER_D3D9_KHR,
+            &surfaceInfo, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromDX9MediaSurfaceKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireDX9MediaSurfacesKHR failed");
+    size_t offset = 0; // TODO
+    size_t dst_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
+    status = clEnqueueReleaseDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseDX9MediaSurfacesKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO pDirect3DSurface9->LockRect() + memcpy + Unlock()
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+
+void convertFromDirect3DSurface9(IDirect3DSurface9* pDirect3DSurface9, OutputArray dst, void* surfaceSharedHandle)
+{
+    (void)pDirect3DSurface9; (void)dst; (void)surfaceSharedHandle;
+#if !defined(HAVE_DIRECTX)
+    NO_DIRECTX_SUPPORT_ERROR;
+#elif defined(HAVE_OPENCL)
+    __OpenCLinitializeD3D9();
+
+    D3DSURFACE_DESC desc;
+    if (FAILED(pDirect3DSurface9->GetDesc(&desc)))
+    {
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: Can't get D3D surface description");
+    }
+
+    int surfaceType = getTypeFromD3DFORMAT(desc.Format);
+    CV_Assert(surfaceType >= 0);
+
+    using namespace cv::ocl;
+    Context2& ctx = Context2::getDefault();
+    cl_context context = (cl_context)ctx.ptr();
+
+    // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
+    dst.create(Size(desc.Width, desc.Height), surfaceType);
+    UMat u = dst.getUMat();
+
+    // TODO Add support for roi
+    CV_Assert(u.offset == 0);
+    CV_Assert(u.isContinuous());
+
+    cl_int status = 0;
+    cl_dx9_surface_info_khr surfaceInfo = {pDirect3DSurface9, (HANDLE)surfaceSharedHandle};
+    cl_mem clImage = clCreateFromDX9MediaSurfaceKHR(context, CL_MEM_READ_ONLY,
+            ocl::g_isDirect3DDevice9Ex ? CL_ADAPTER_D3D9EX_KHR : CL_ADAPTER_D3D9_KHR,
+            &surfaceInfo, 0, &status);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromDX9MediaSurfaceKHR failed");
+
+    cl_mem clBuffer = (cl_mem)u.handle(ACCESS_WRITE);
+
+    cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+    status = clEnqueueAcquireDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireDX9MediaSurfacesKHR failed");
+    size_t offset = 0; // TODO
+    size_t src_origin[3] = {0, 0, 0};
+    size_t region[3] = {u.cols, u.rows, 1};
+    status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
+    status = clEnqueueReleaseDX9MediaSurfacesKHR(q, 1, &clImage, 0, NULL, NULL);
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseDX9MediaSurfacesKHR failed");
+
+    status = clFinish(q); // TODO Use events
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+    status = clReleaseMemObject(clImage); // TODO RAII
+    if (status != CL_SUCCESS)
+        CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+#else
+    // TODO pDirect3DSurface9->LockRect() + memcpy + Unlock()
+    NO_OPENCL_SUPPORT_ERROR;
+#endif
+}
+
+} } // namespace cv::directx
diff --git a/modules/core/src/directx.inc.hpp b/modules/core/src/directx.inc.hpp
new file mode 100644 (file)
index 0000000..a8e7a17
--- /dev/null
@@ -0,0 +1,55 @@
+/*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-2013, Advanced Micro Devices, 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 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 copyright holders 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*/
+
+#if defined(HAVE_DIRECTX)
+#include <d3d11.h>
+#include <d3d10.h>
+#include <d3d9.h>
+
+#ifdef HAVE_OPENCL
+#include "opencv2/core/opencl/runtime/opencl_core.hpp"
+
+#include <CL/cl_d3d11.h>
+#include <CL/cl_d3d10.h>
+#include <CL/cl_dx9_media_sharing.h>
+#endif // HAVE_OPENCL
+
+#endif // HAVE_DIRECTX
index 7d832cb..16eb6e0 100644 (file)
@@ -41,6 +41,7 @@
 //M*/
 
 #include "precomp.hpp"
+#include "opencv2/core/opencl/runtime/opencl_clamdblas.hpp"
 
 #ifdef HAVE_IPP
 #include "ippversion.h"
@@ -693,11 +694,102 @@ static void GEMMStore_64fc( const Complexd* c_data, size_t c_step,
     GEMMStore(c_data, c_step, d_buf, d_buf_step, d_data, d_step, d_size, alpha, beta, flags);
 }
 
+#ifdef HAVE_CLAMDBLAS
+
+static bool ocl_gemm( InputArray matA, InputArray matB, double alpha,
+                      InputArray matC, double beta, OutputArray matD, int flags )
+{
+    int type = matA.type(), esz = CV_ELEM_SIZE(type);
+    bool haveC = matC.kind() != cv::_InputArray::NONE;
+    Size sizeA = matA.size(), sizeB = matB.size(), sizeC = haveC ? matC.size() : Size(0, 0);
+    bool atrans = (flags & GEMM_1_T) != 0, btrans = (flags & GEMM_2_T) != 0, ctrans = (flags & GEMM_3_T) != 0;
+
+    if (atrans)
+        sizeA = Size(sizeA.height, sizeA.width);
+    if (btrans)
+        sizeB = Size(sizeB.height, sizeB.width);
+    if (haveC && ctrans)
+        sizeC = Size(sizeC.height, sizeC.width);
+
+    Size sizeD(sizeB.width, sizeA.height);
+
+    CV_Assert( matB.type() == type && (!haveC || matC.type() == type) );
+    CV_Assert( sizeA.width == sizeB.height && (!haveC || sizeC == sizeD) );
+
+    matD.create(sizeD, type);
+    if ( matA.offset() % esz != 0 || matA.step() % esz != 0 ||
+         matB.offset() % esz != 0 || matB.step() % esz != 0 ||
+         (haveC && (matC.offset() % esz != 0 || matC.step() % esz != 0)) )
+        return false;
+
+    UMat A = matA.getUMat(), B = matB.getUMat(), D = matD.getUMat();
+    if (haveC)
+        ctrans ? transpose(matC, D) : matC.getMat().copyTo(D); // TODO fix it as soon as .copyTo works as expected
+    else
+        D.setTo(Scalar::all(0));
+
+    int M = sizeD.height, N = sizeD.width, K = sizeA.width;
+    int lda = (int)A.step / esz, ldb = (int)B.step / esz, ldc = (int)D.step / esz;
+    int offa = (int)A.offset / esz, offb = (int)B.offset / esz, offc = (int)D.offset / esz;
+
+    cl_command_queue clq = (cl_command_queue)ocl::Queue::getDefault().ptr();
+    clAmdBlasTranspose transA = atrans ? clAmdBlasTrans : clAmdBlasNoTrans;
+    clAmdBlasTranspose transB = btrans ? clAmdBlasTrans : clAmdBlasNoTrans;
+    clAmdBlasOrder order = clAmdBlasRowMajor;
+    clAmdBlasStatus status = clAmdBlasSuccess;
+
+    if (type == CV_32FC1)
+        status = clAmdBlasSgemmEx(order, transA, transB, M, N, K,
+                                  (cl_float)alpha, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
+                                  (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
+                                  (cl_float)beta, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
+                                  1, &clq, 0, NULL, NULL);
+    else if (type == CV_64FC1)
+        status = clAmdBlasDgemmEx(order, transA, transB, M, N, K,
+                                  alpha, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
+                                  (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
+                                  beta, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
+                                  1, &clq, 0, NULL, NULL);
+    else if (type == CV_32FC2)
+    {
+         cl_float2 alpha_2 = { { (cl_float)alpha, 0 } };
+         cl_float2 beta_2  = { { (cl_float)beta, 0 } };
+         status = clAmdBlasCgemmEx(order, transA, transB, M, N, K,
+                                   alpha_2, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
+                                   (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
+                                   beta_2, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
+                                   1, &clq, 0, NULL, NULL);
+    }
+    else if (type == CV_64FC2)
+    {
+        cl_double2 alpha_2 = { { alpha, 0 } };
+        cl_double2 beta_2  = { { beta, 0 } };
+        status = clAmdBlasZgemmEx(order, transA, transB, M, N, K,
+                                  alpha_2, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
+                                  (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
+                                  beta_2, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
+                                  1, &clq, 0, NULL, NULL);
+    }
+    else
+        CV_Error(Error::StsUnsupportedFormat, "");
+
+    return status == clAmdBlasSuccess;
+}
+
+#endif
+
 }
 
 void cv::gemm( InputArray matA, InputArray matB, double alpha,
            InputArray matC, double beta, OutputArray _matD, int flags )
 {
+#ifdef HAVE_CLAMDBLAS
+    if (ocl::haveAmdBlas() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2 &&
+            ocl::useOpenCL() && _matD.isUMat() &&
+            ocl_gemm(matA, matB, alpha, matC, beta, _matD, flags))
+        return;
+#endif
+
     const int block_lin_size = 128;
     const int block_size = block_lin_size * block_lin_size;
 
index 871fb38..6f25804 100644 (file)
@@ -56,7 +56,10 @@ void MatAllocator::map(UMatData*, int) const
 void MatAllocator::unmap(UMatData* u) const
 {
     if(u->urefcount == 0 && u->refcount == 0)
+    {
         deallocate(u);
+        u = NULL;
+    }
 }
 
 void MatAllocator::download(UMatData* u, void* dstptr,
@@ -134,11 +137,11 @@ void MatAllocator::copy(UMatData* usrc, UMatData* udst, int dims, const size_t s
     {
         CV_Assert( sz[i] <= (size_t)INT_MAX );
         if( sz[i] == 0 )
-        return;
+            return;
         if( srcofs )
-        srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1);
+            srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1);
         if( dstofs )
-        dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1);
+            dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1);
         isz[i] = (int)sz[i];
     }
 
@@ -179,7 +182,6 @@ public:
         UMatData* u = new UMatData(this);
         u->data = u->origdata = data;
         u->size = total;
-        u->refcount = data0 == 0;
         if(data0)
             u->flags |= UMatData::USER_ALLOCATED;
 
@@ -195,6 +197,8 @@ public:
 
     void deallocate(UMatData* u) const
     {
+        CV_Assert(u->urefcount >= 0);
+        CV_Assert(u->refcount >= 0);
         if(u && u->refcount == 0)
         {
             if( !(u->flags & UMatData::USER_ALLOCATED) )
@@ -392,6 +396,7 @@ void Mat::create(int d, const int* _sizes, int _type)
         CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
     }
 
+    addref();
     finalizeHdr(*this);
 }
 
@@ -409,6 +414,7 @@ void Mat::deallocate()
 {
     if(u)
         (u->currAllocator ? u->currAllocator : allocator ? allocator : getStdAllocator())->unmap(u);
+    u = NULL;
 }
 
 Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange)
index 6681e81..cd01315 100644 (file)
@@ -42,6 +42,8 @@
 #include "precomp.hpp"
 #include <map>
 
+#include "opencv2/core/opencl/runtime/opencl_clamdblas.hpp"
+
 #ifdef HAVE_OPENCL
 #include "opencv2/core/opencl/runtime/opencl_core.hpp"
 #else
@@ -1309,36 +1311,30 @@ inline bool operator < (const HashKey& h1, const HashKey& h2)
     return h1.a < h2.a || (h1.a == h2.a && h1.b < h2.b);
 }
 
-static bool g_isInitialized = false;
+static bool g_isOpenCLInitialized = false;
 static bool g_isOpenCLAvailable = false;
+
 bool haveOpenCL()
 {
-    if (!g_isInitialized)
+    if (!g_isOpenCLInitialized)
     {
-        if (!g_isInitialized)
+        try
         {
-            try
-            {
-                cl_uint n = 0;
-                cl_int err = ::clGetPlatformIDs(0, NULL, &n);
-                if (err != CL_SUCCESS)
-                    g_isOpenCLAvailable = false;
-                else
-                    g_isOpenCLAvailable = true;
-            }
-            catch (...)
-            {
-                g_isOpenCLAvailable = false;
-            }
-            g_isInitialized = true;
+            cl_uint n = 0;
+            g_isOpenCLAvailable = ::clGetPlatformIDs(0, NULL, &n) == CL_SUCCESS;
         }
+        catch (...)
+        {
+            g_isOpenCLAvailable = false;
+        }
+        g_isOpenCLInitialized = true;
     }
     return g_isOpenCLAvailable;
 }
 
 bool useOpenCL()
 {
-    TLSData* data = TLSData::get();
+    CoreTLSData* data = coreTlsData.get();
     if( data->useOpenCL < 0 )
         data->useOpenCL = (int)haveOpenCL();
     return data->useOpenCL > 0;
@@ -1348,11 +1344,85 @@ void setUseOpenCL(bool flag)
 {
     if( haveOpenCL() )
     {
-        TLSData* data = TLSData::get();
+        CoreTLSData* data = coreTlsData.get();
         data->useOpenCL = flag ? 1 : 0;
     }
 }
 
+#ifdef HAVE_CLAMDBLAS
+
+class AmdBlasHelper
+{
+public:
+    static AmdBlasHelper & getInstance()
+    {
+        static AmdBlasHelper amdBlas;
+        return amdBlas;
+    }
+
+    bool isAvailable() const
+    {
+        return g_isAmdBlasAvailable;
+    }
+
+    ~AmdBlasHelper()
+    {
+        try
+        {
+            clAmdBlasTeardown();
+        }
+        catch (...) { }
+    }
+
+protected:
+    AmdBlasHelper()
+    {
+        if (!g_isAmdBlasInitialized)
+        {
+            AutoLock lock(m);
+
+            if (!g_isAmdBlasInitialized && haveOpenCL())
+            {
+                try
+                {
+                    g_isAmdBlasAvailable = clAmdBlasSetup() == clAmdBlasSuccess;
+                }
+                catch (...)
+                {
+                    g_isAmdBlasAvailable = false;
+                }
+            }
+            else
+                g_isAmdBlasAvailable = false;
+
+            g_isAmdBlasInitialized = true;
+        }
+    }
+
+private:
+    static Mutex m;
+    static bool g_isAmdBlasInitialized;
+    static bool g_isAmdBlasAvailable;
+};
+
+bool AmdBlasHelper::g_isAmdBlasAvailable = false;
+bool AmdBlasHelper::g_isAmdBlasInitialized = false;
+Mutex AmdBlasHelper::m;
+
+bool haveAmdBlas()
+{
+    return AmdBlasHelper::getInstance().isAvailable();
+}
+
+#else
+
+bool haveAmdBlas()
+{
+    return false;
+}
+
+#endif
+
 void finish2()
 {
     Queue::getDefault().finish();
@@ -1363,21 +1433,6 @@ void finish2()
     void release() { if( CV_XADD(&refcount, -1) == 1 ) delete this; } \
     int refcount
 
-class Platform
-{
-public:
-    Platform();
-    ~Platform();
-    Platform(const Platform& p);
-    Platform& operator = (const Platform& p);
-
-    void* ptr() const;
-    static Platform& getDefault();
-protected:
-    struct Impl;
-    Impl* p;
-};
-
 struct Platform::Impl
 {
     Impl()
@@ -1469,6 +1524,7 @@ struct Device::Impl
     Impl(void* d)
     {
         handle = (cl_device_id)d;
+        refcount = 1;
     }
 
     template<typename _TpCL, typename _TpOut>
@@ -1765,7 +1821,7 @@ size_t Device::profilingTimerResolution() const
 const Device& Device::getDefault()
 {
     const Context2& ctx = Context2::getDefault();
-    int idx = TLSData::get()->device;
+    int idx = coreTlsData.get()->device;
     return ctx.device(idx);
 }
 
@@ -1773,6 +1829,12 @@ const Device& Device::getDefault()
 
 struct Context2::Impl
 {
+    Impl()
+    {
+        refcount = 1;
+        handle = 0;
+    }
+
     Impl(int dtype0)
     {
         refcount = 1;
@@ -1855,7 +1917,6 @@ struct Context2::Impl
 
     cl_context handle;
     std::vector<Device> devices;
-    bool initialized;
 
     typedef ProgramSource2::hash_t hash_t;
 
@@ -1937,22 +1998,29 @@ const Device& Context2::device(size_t idx) const
     return !p || idx >= p->devices.size() ? dummy : p->devices[idx];
 }
 
-Context2& Context2::getDefault()
+Context2& Context2::getDefault(bool initialize)
 {
     static Context2 ctx;
-    if( !ctx.p && haveOpenCL() )
+    if(!ctx.p && haveOpenCL())
     {
-        // do not create new Context2 right away.
-        // First, try to retrieve existing context of the same type.
-        // In its turn, Platform::getContext() may call Context2::create()
-        // if there is no such context.
-        ctx.create(Device::TYPE_ACCELERATOR);
-        if(!ctx.p)
-            ctx.create(Device::TYPE_DGPU);
-        if(!ctx.p)
-            ctx.create(Device::TYPE_IGPU);
-        if(!ctx.p)
-            ctx.create(Device::TYPE_CPU);
+        if (initialize)
+        {
+            // do not create new Context2 right away.
+            // First, try to retrieve existing context of the same type.
+            // In its turn, Platform::getContext() may call Context2::create()
+            // if there is no such context.
+            ctx.create(Device::TYPE_ACCELERATOR);
+            if(!ctx.p)
+                ctx.create(Device::TYPE_DGPU);
+            if(!ctx.p)
+                ctx.create(Device::TYPE_IGPU);
+            if(!ctx.p)
+                ctx.create(Device::TYPE_CPU);
+        }
+        else
+        {
+            ctx.p = new Impl();
+        }
     }
 
     return ctx;
@@ -1964,6 +2032,30 @@ Program Context2::getProg(const ProgramSource2& prog,
     return p ? p->getProg(prog, buildopts, errmsg) : Program();
 }
 
+void initializeContextFromHandle(Context2& ctx, void* platform, void* _context, void* _device)
+{
+    cl_context context = (cl_context)_context;
+    cl_device_id device = (cl_device_id)_device;
+
+    // cleanup old context
+    Context2::Impl* impl = ctx._getImpl();
+    if (impl->handle)
+    {
+        cl_int status = clReleaseContext(impl->handle);
+        (void)status;
+    }
+    impl->devices.clear();
+
+    impl->handle = context;
+    impl->devices.resize(1);
+    impl->devices[0].set(device);
+
+    Platform& p = Platform::getDefault();
+    Platform::Impl* pImpl = p._getImpl();
+    pImpl->handle = (cl_platform_id)platform;
+}
+
+
 struct Queue::Impl
 {
     Impl(const Context2& c, const Device& d)
@@ -2059,7 +2151,7 @@ void* Queue::ptr() const
 
 Queue& Queue::getDefault()
 {
-    Queue& q = TLSData::get()->oclQueue;
+    Queue& q = coreTlsData.get()->oclQueue;
     if( !q.p && haveOpenCL() )
         q.create(Context2::getDefault());
     return q;
@@ -2693,8 +2785,6 @@ public:
     UMatData* defaultAllocate(int dims, const int* sizes, int type, void* data, size_t* step, int flags) const
     {
         UMatData* u = matStdAllocator->allocate(dims, sizes, type, data, step, flags);
-        u->urefcount = 1;
-        u->refcount = 0;
         return u;
     }
 
@@ -2736,7 +2826,6 @@ public:
         u->data = 0;
         u->size = total;
         u->handle = handle;
-        u->urefcount = 1;
         u->flags = flags0;
 
         return u;
@@ -2775,7 +2864,6 @@ public:
         }
         if(accessFlags & ACCESS_WRITE)
             u->markHostCopyObsolete(true);
-        CV_XADD(&u->urefcount, 1);
         return true;
     }
 
@@ -2814,6 +2902,9 @@ public:
         if(!u)
             return;
 
+        CV_Assert(u->urefcount >= 0);
+        CV_Assert(u->refcount >= 0);
+
         // TODO: !!! when we add Shared Virtual Memory Support,
         // this function (as well as the others) should be corrected
         CV_Assert(u->handle != 0 && u->urefcount == 0);
diff --git a/modules/core/src/opencl/convert.cl b/modules/core/src/opencl/convert.cl
new file mode 100644 (file)
index 0000000..6c2d16c
--- /dev/null
@@ -0,0 +1,71 @@
+/*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) 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 copyright holders 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*/
+
+#ifdef DOUBLE_SUPPORT
+#ifdef cl_amd_fp64
+#pragma OPENCL EXTENSION cl_amd_fp64:enable
+#elif defined (cl_khr_fp64)
+#pragma OPENCL EXTENSION cl_khr_fp64:enable
+#endif
+#endif
+
+#define noconvert
+
+__kernel void convertTo(__global const uchar * srcptr, int src_step, int src_offset,
+                        __global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols,
+                        float alpha, float beta )
+{
+    int x = get_global_id(0);
+    int y = get_global_id(1);
+
+    if (x < dst_cols && y < dst_rows)
+    {
+        int src_index = mad24(y, src_step, src_offset + x * (int)sizeof(srcT) );
+        int dst_index = mad24(y, dst_step, dst_offset + x * (int)sizeof(dstT) );
+
+        __global const srcT * src = (__global const srcT *)(srcptr + src_index);
+        __global dstT * dst = (__global dstT *)(dstptr + dst_index);
+
+        dst[0] = convertToDT( src[0] * alpha + beta );
+    }
+}
index 526cc51..4f0d806 100644 (file)
@@ -51,6 +51,7 @@
 #endif
 
 #define noconvert
+#define EXTRA_PARAMS
 
 #if defined OP_SUM || defined OP_SUM_ABS || defined OP_SUM_SQR
 #if OP_SUM
 #elif OP_SUM_SQR
 #define FUNC(a, b) a += b * b
 #endif
+#define DECLARE_LOCAL_MEM \
+    __local dstT localmem[WGS2_ALIGNED]
 #define DEFINE_ACCUMULATOR \
     dstT accumulator = (dstT)(0)
 #define REDUCE_GLOBAL \
     dstT temp = convertToDT(src[0]); \
     FUNC(accumulator, temp)
+#define SET_LOCAL_1 \
+        localmem[lid] = accumulator
 #define REDUCE_LOCAL_1 \
     localmem[lid - WGS2_ALIGNED] += accumulator
 #define REDUCE_LOCAL_2 \
     localmem[lid] += localmem[lid2]
+#define CALC_RESULT \
+    __global dstT * dst = (__global dstT *)(dstptr + (int)sizeof(dstT) * gid); \
+    dst[0] = localmem[0]
 
 #elif defined OP_COUNT_NON_ZERO
 #define dstT int
+#define DECLARE_LOCAL_MEM \
+    __local dstT localmem[WGS2_ALIGNED]
 #define DEFINE_ACCUMULATOR \
     dstT accumulator = (dstT)(0); \
     srcT zero = (srcT)(0), one = (srcT)(1)
 #define REDUCE_GLOBAL \
     accumulator += src[0] == zero ? zero : one
+#define SET_LOCAL_1 \
+        localmem[lid] = accumulator
 #define REDUCE_LOCAL_1 \
     localmem[lid - WGS2_ALIGNED] += accumulator
 #define REDUCE_LOCAL_2 \
     localmem[lid] += localmem[lid2]
+#define CALC_RESULT \
+    __global dstT * dst = (__global dstT *)(dstptr + (int)sizeof(dstT) * gid); \
+    dst[0] = localmem[0]
+
+#elif defined OP_MIN_MAX_LOC || defined OP_MIN_MAX_LOC_MASK
+
+#if defined (DEPTH_0)
+#define srcT uchar
+#define MIN_VAL 0
+#define MAX_VAL 255
+#endif
+#if defined (DEPTH_1)
+#define srcT char
+#define MIN_VAL -128
+#define MAX_VAL 127
+#endif
+#if defined (DEPTH_2)
+#define srcT ushort
+#define MIN_VAL 0
+#define MAX_VAL 65535
+#endif
+#if defined (DEPTH_3)
+#define srcT short
+#define MIN_VAL -32768
+#define MAX_VAL 32767
+#endif
+#if defined (DEPTH_4)
+#define srcT int
+#define MIN_VAL INT_MIN
+#define MAX_VAL INT_MAX
+#endif
+#if defined (DEPTH_5)
+#define srcT float
+#define MIN_VAL (-FLT_MAX)
+#define MAX_VAL FLT_MAX
+#endif
+#if defined (DEPTH_6)
+#define srcT double
+#define MIN_VAL (-DBL_MAX)
+#define MAX_VAL DBL_MAX
+#endif
+
+#define DECLARE_LOCAL_MEM \
+    __local srcT localmem_min[WGS2_ALIGNED]; \
+    __local srcT localmem_max[WGS2_ALIGNED]; \
+    __local int localmem_minloc[WGS2_ALIGNED]; \
+    __local int localmem_maxloc[WGS2_ALIGNED]
+#define DEFINE_ACCUMULATOR \
+    srcT minval = MAX_VAL; \
+    srcT maxval = MIN_VAL; \
+    int negative = -1; \
+    int minloc = negative; \
+    int maxloc = negative; \
+    srcT temp; \
+    int temploc
+#define REDUCE_GLOBAL \
+    temp = src[0]; \
+    temploc = id; \
+    srcT temp_minval = minval, temp_maxval = maxval; \
+    minval = min(minval, temp); \
+    maxval = max(maxval, temp); \
+    minloc = (minval == temp_minval) ? (temp_minval == MAX_VAL) ? temploc : minloc : temploc; \
+    maxloc = (maxval == temp_maxval) ? (temp_maxval == MIN_VAL) ? temploc : maxloc : temploc
+#define SET_LOCAL_1 \
+    localmem_min[lid] = minval; \
+    localmem_max[lid] = maxval; \
+    localmem_minloc[lid] = minloc; \
+    localmem_maxloc[lid] = maxloc
+#define REDUCE_LOCAL_1 \
+    srcT oldmin = localmem_min[lid-WGS2_ALIGNED]; \
+    srcT oldmax = localmem_max[lid-WGS2_ALIGNED]; \
+    localmem_min[lid - WGS2_ALIGNED] = min(minval,localmem_min[lid-WGS2_ALIGNED]); \
+    localmem_max[lid - WGS2_ALIGNED] = max(maxval,localmem_max[lid-WGS2_ALIGNED]); \
+    srcT minv = localmem_min[lid - WGS2_ALIGNED], maxv = localmem_max[lid - WGS2_ALIGNED]; \
+    localmem_minloc[lid - WGS2_ALIGNED] = (minv == minval) ? (minv == oldmin) ? \
+        min(minloc, localmem_minloc[lid-WGS2_ALIGNED]) : minloc : localmem_minloc[lid-WGS2_ALIGNED]; \
+    localmem_maxloc[lid - WGS2_ALIGNED] = (maxv == maxval) ? (maxv == oldmax) ? \
+        min(maxloc, localmem_maxloc[lid-WGS2_ALIGNED]) : maxloc : localmem_maxloc[lid-WGS2_ALIGNED]
+#define REDUCE_LOCAL_2 \
+    srcT oldmin = localmem_min[lid]; \
+    srcT oldmax = localmem_max[lid]; \
+    localmem_min[lid] = min(localmem_min[lid], localmem_min[lid2]); \
+    localmem_max[lid] = max(localmem_max[lid], localmem_max[lid2]); \
+    srcT min1 = localmem_min[lid], min2 = localmem_min[lid2]; \
+    localmem_minloc[lid] = (localmem_minloc[lid] == negative) ? localmem_minloc[lid2] : (localmem_minloc[lid2] == negative) ? \
+        localmem_minloc[lid] : (min1 == min2) ? (min1 == oldmin) ? min(localmem_minloc[lid2],localmem_minloc[lid]) : \
+        localmem_minloc[lid2] : localmem_minloc[lid]; \
+    srcT max1 = localmem_max[lid], max2 = localmem_max[lid2]; \
+    localmem_maxloc[lid] = (localmem_maxloc[lid] == negative) ? localmem_maxloc[lid2] : (localmem_maxloc[lid2] == negative) ? \
+        localmem_maxloc[lid] : (max1 == max2) ? (max1 == oldmax) ? min(localmem_maxloc[lid2],localmem_maxloc[lid]) : \
+        localmem_maxloc[lid2] : localmem_maxloc[lid]
+#define CALC_RESULT \
+    __global srcT * dstminval = (__global srcT *)(dstptr + (int)sizeof(srcT) * gid); \
+    __global srcT * dstmaxval = (__global srcT *)(dstptr2 + (int)sizeof(srcT) * gid); \
+    dstminval[0] = localmem_min[0]; \
+    dstmaxval[0] = localmem_max[0]; \
+    dstlocptr[gid] = localmem_minloc[0]; \
+    dstlocptr2[gid] = localmem_maxloc[0]
+
+#if defined OP_MIN_MAX_LOC_MASK
+#undef DEFINE_ACCUMULATOR
+#define DEFINE_ACCUMULATOR \
+    srcT minval = MAX_VAL; \
+    srcT maxval = MIN_VAL; \
+    int negative = -1; \
+    int minloc = negative; \
+    int maxloc = negative; \
+    srcT temp, temp_mask, zeroVal = (srcT)(0); \
+    int temploc
+#undef REDUCE_GLOBAL
+#define REDUCE_GLOBAL \
+    temp = src[0]; \
+    temploc = id; \
+    int mask_index = mad24(id / cols, mask_step, mask_offset + (id % cols) * (int)sizeof(uchar)); \
+    __global const uchar * mask = (__global const uchar *)(maskptr + mask_index); \
+    temp_mask = mask[0]; \
+    srcT temp_minval = minval, temp_maxval = maxval; \
+    minval = (temp_mask == zeroVal) ? minval : min(minval, temp); \
+    maxval = (temp_mask == zeroVal) ? maxval : max(maxval, temp); \
+    minloc = (temp_mask == zeroVal) ? minloc : (minval == temp_minval) ? (temp_minval == MAX_VAL) ? temploc : minloc : temploc; \
+    maxloc = (temp_mask == zeroVal) ? maxloc : (maxval == temp_maxval) ? (temp_maxval == MIN_VAL) ? temploc : maxloc : temploc
+#endif
 
 #else
 #error "No operation"
+#endif
 
+#if defined OP_MIN_MAX_LOC
+#undef EXTRA_PARAMS
+#define EXTRA_PARAMS , __global uchar * dstptr2, __global int * dstlocptr, __global int * dstlocptr2
+#endif
+#if defined OP_MIN_MAX_LOC_MASK
+#undef EXTRA_PARAMS
+#define EXTRA_PARAMS , __global uchar * dstptr2, __global int * dstlocptr, __global int * dstlocptr2, \
+    __global const uchar * maskptr, int mask_step, int mask_offset, __global int * test
 #endif
 
 __kernel void reduce(__global const uchar * srcptr, int step, int offset, int cols,
-                     int total, int groupnum, __global uchar * dstptr)
+                     int total, int groupnum, __global uchar * dstptr EXTRA_PARAMS)
 {
     int lid = get_local_id(0);
     int gid = get_group_id(0);
     int  id = get_global_id(0);
 
-    __local dstT localmem[WGS2_ALIGNED];
+    DECLARE_LOCAL_MEM;
     DEFINE_ACCUMULATOR;
 
     for (int grain = groupnum * WGS; id < total; id += grain)
@@ -105,11 +248,15 @@ __kernel void reduce(__global const uchar * srcptr, int step, int offset, int co
     }
 
     if (lid < WGS2_ALIGNED)
-        localmem[lid] = accumulator;
+    {
+        SET_LOCAL_1;
+    }
     barrier(CLK_LOCAL_MEM_FENCE);
 
-    if (lid >= WGS2_ALIGNED)
+    if (lid >= WGS2_ALIGNED && total >= WGS2_ALIGNED)
+    {
         REDUCE_LOCAL_1;
+    }
     barrier(CLK_LOCAL_MEM_FENCE);
 
     for (int lsize = WGS2_ALIGNED >> 1; lsize > 0; lsize >>= 1)
@@ -124,7 +271,6 @@ __kernel void reduce(__global const uchar * srcptr, int step, int offset, int co
 
     if (lid == 0)
     {
-        __global dstT * dst = (__global dstT *)(dstptr + (int)sizeof(dstT) * gid);
-        dst[0] = localmem[0];
+        CALC_RESULT;
     }
 }
index 47d6fdc..3727b2f 100644 (file)
@@ -43,6 +43,9 @@
 #ifndef __OPENCV_PRECOMP_H__
 #define __OPENCV_PRECOMP_H__
 
+#include "opencv2/opencv_modules.hpp"
+#include "cvconfig.h"
+
 #include "opencv2/core/utility.hpp"
 #include "opencv2/core/core_c.h"
 #include "opencv2/core/cuda.hpp"
@@ -106,7 +109,6 @@ extern const uchar g_Saturate8u[];
 
 #if defined WIN32 || defined _WIN32
 void deleteThreadAllocData();
-void deleteThreadData();
 #endif
 
 template<typename T1, typename T2=T1, typename T3=T1> struct OpAdd
@@ -233,17 +235,19 @@ inline bool checkScalar(InputArray sc, int atype, int sckind, int akind)
 
 void convertAndUnrollScalar( const Mat& sc, int buftype, uchar* scbuf, size_t blocksize );
 
-struct TLSData
+struct CoreTLSData
 {
-    TLSData();
+    CoreTLSData() : device(0), useOpenCL(-1)
+    {}
+
     RNG rng;
     int device;
     ocl::Queue oclQueue;
     int useOpenCL; // 1 - use, 0 - do not use, -1 - auto/not initialized
-
-    static TLSData* get();
 };
 
+extern TLSData<CoreTLSData> coreTlsData;
+
 #if defined(BUILD_SHARED_LIBS)
 #if defined WIN32 || defined _WIN32 || defined WINCE
 #define CL_RUNTIME_EXPORT __declspec(dllexport)
index 75942d4..727bbfc 100644 (file)
@@ -731,7 +731,7 @@ void RNG::fill( InputOutputArray _mat, int disttype,
 
 cv::RNG& cv::theRNG()
 {
-    return TLSData::get()->rng;
+    return coreTlsData.get()->rng;
 }
 
 void cv::randu(InputOutputArray dst, InputArray low, InputArray high)
index d04857c..2806efe 100644 (file)
@@ -1159,16 +1159,137 @@ static void ofs2idx(const Mat& a, size_t ofs, int* idx)
 
 }
 
+namespace cv
+{
+
+template <typename T>
+void getMinMaxRes(const Mat &minv, const Mat &maxv, const Mat &minl, const Mat &maxl, double* minVal,
+                  double* maxVal, int* minLoc, int* maxLoc, const int groupnum, const int cn, const int cols)
+{
+    T min = std::numeric_limits<T>::max();
+    T max = std::numeric_limits<T>::min() > 0 ? -std::numeric_limits<T>::max() : std::numeric_limits<T>::min();
+    int minloc = INT_MAX, maxloc = INT_MAX;
+    for( int i = 0; i < groupnum; i++)
+    {
+        T current_min = minv.at<T>(0,i);
+        T current_max = maxv.at<T>(0,i);
+        T oldmin = min, oldmax = max;
+        min = std::min(min, current_min);
+        max = std::max(max, current_max);
+        if (cn == 1)
+        {
+            int current_minloc = minl.at<int>(0,i);
+            int current_maxloc = maxl.at<int>(0,i);
+            if(current_minloc < 0 || current_maxloc < 0) continue;
+            minloc = (oldmin == current_min) ? std::min(minloc, current_minloc) : (oldmin < current_min) ? minloc : current_minloc;
+            maxloc = (oldmax == current_max) ? std::min(maxloc, current_maxloc) : (oldmax > current_max) ? maxloc : current_maxloc;
+        }
+    }
+    bool zero_mask = (maxloc == INT_MAX) || (minloc == INT_MAX);
+    if(minVal)
+        *minVal = zero_mask ? 0 : (double)min;
+    if(maxVal)
+        *maxVal = zero_mask ? 0 : (double)max;
+    if(minLoc)
+    {
+        minLoc[0] = zero_mask ? -1 : minloc/cols;
+        minLoc[1] = zero_mask ? -1 : minloc%cols;
+    }
+    if(maxLoc)
+    {
+        maxLoc[0] = zero_mask ? -1 : maxloc/cols;
+        maxLoc[1] = zero_mask ? -1 : maxloc%cols;
+    }
+}
+
+typedef void (*getMinMaxResFunc)(const Mat &minv, const Mat &maxv, const Mat &minl, const Mat &maxl, double *minVal,
+                                 double *maxVal, int *minLoc, int *maxLoc, const int gropunum, const int cn, const int cols);
+
+static bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* minLoc, int* maxLoc, InputArray _mask)
+{
+    CV_Assert( (_src.channels() == 1 && (_mask.empty() || _mask.type() == CV_8U)) ||
+        (_src.channels() >= 1 && _mask.empty() && !minLoc && !maxLoc) );
+
+    int type = _src.type(), depth = CV_MAT_DEPTH(type);
+    bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
+
+    if (depth == CV_64F && !doubleSupport)
+        return false;
+
+    int groupnum = ocl::Device::getDefault().maxComputeUnits();
+    size_t wgs = ocl::Device::getDefault().maxWorkGroupSize();
+
+    int wgs2_aligned = 1;
+    while (wgs2_aligned < (int)wgs)
+        wgs2_aligned <<= 1;
+    wgs2_aligned >>= 1;
+
+    String opts = format("-D DEPTH_%d -D OP_MIN_MAX_LOC%s -D WGS=%d -D WGS2_ALIGNED=%d %s",
+        depth, _mask.empty() ? "" : "_MASK", (int)wgs, wgs2_aligned, doubleSupport ? "-D DOUBLE_SUPPORT" : "");
+
+    ocl::Kernel k("reduce", ocl::core::reduce_oclsrc, opts);
+    if (k.empty())
+        return false;
+
+    UMat src = _src.getUMat(), minval(1, groupnum, src.type()),
+        maxval(1, groupnum, src.type()), minloc( 1, groupnum, CV_32SC1),
+        maxloc( 1, groupnum, CV_32SC1), mask;
+    if(!_mask.empty())
+        mask = _mask.getUMat();
+
+    if(src.channels()>1)
+        src = src.reshape(1);
+
+    if(mask.empty())
+        k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(),
+            groupnum, ocl::KernelArg::PtrWriteOnly(minval), ocl::KernelArg::PtrWriteOnly(maxval),
+            ocl::KernelArg::PtrWriteOnly(minloc), ocl::KernelArg::PtrWriteOnly(maxloc));
+    else
+        k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(), groupnum,
+            ocl::KernelArg::PtrWriteOnly(minval), ocl::KernelArg::PtrWriteOnly(maxval),
+            ocl::KernelArg::PtrWriteOnly(minloc), ocl::KernelArg::PtrWriteOnly(maxloc), ocl::KernelArg::ReadOnlyNoSize(mask));
+
+    size_t globalsize = groupnum * wgs;
+    if (!k.run(1, &globalsize, &wgs, true))
+        return false;
+
+    Mat minv = minval.getMat(ACCESS_READ), maxv = maxval.getMat(ACCESS_READ),
+        minl = minloc.getMat(ACCESS_READ), maxl = maxloc.getMat(ACCESS_READ);
+
+    static getMinMaxResFunc functab[7] =
+    {
+        getMinMaxRes<uchar>,
+        getMinMaxRes<char>,
+        getMinMaxRes<ushort>,
+        getMinMaxRes<short>,
+        getMinMaxRes<int>,
+        getMinMaxRes<float>,
+        getMinMaxRes<double>
+    };
+
+    getMinMaxResFunc func;
+
+    func = functab[depth];
+    func(minv, maxv, minl, maxl, minVal, maxVal, minLoc, maxLoc, groupnum, src.channels(), src.cols);
+
+    return true;
+}
+}
+
 void cv::minMaxIdx(InputArray _src, double* minVal,
                    double* maxVal, int* minIdx, int* maxIdx,
                    InputArray _mask)
 {
+    CV_Assert( (_src.channels() == 1 && (_mask.empty() || _mask.type() == CV_8U)) ||
+        (_src.channels() >= 1 && _mask.empty() && !minIdx && !maxIdx) );
+
+     if( ocl::useOpenCL() && _src.isUMat() && _src.dims() <= 2  && ( _mask.empty() || _src.size() == _mask.size() )
+         && ocl_minMaxIdx(_src, minVal, maxVal, minIdx, maxIdx, _mask) )
+        return;
+
     Mat src = _src.getMat(), mask = _mask.getMat();
     int depth = src.depth(), cn = src.channels();
 
-    CV_Assert( (cn == 1 && (mask.empty() || mask.type() == CV_8U)) ||
-               (cn >= 1 && mask.empty() && !minIdx && !maxIdx) );
-
 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
     size_t total_size = src.total();
     int rows = src.size[0], cols = (int)(total_size/rows);
@@ -1289,8 +1410,7 @@ void cv::minMaxIdx(InputArray _src, double* minVal,
 void cv::minMaxLoc( InputArray _img, double* minVal, double* maxVal,
                     Point* minLoc, Point* maxLoc, InputArray mask )
 {
-    Mat img = _img.getMat();
-    CV_Assert(img.dims <= 2);
+    CV_Assert(_img.dims() <= 2);
 
     minMaxIdx(_img, minVal, maxVal, (int*)minLoc, (int*)maxLoc, mask);
     if( minLoc )
index 2786597..1b25106 100644 (file)
@@ -738,26 +738,6 @@ namespace cv {
 bool __termination = false;
 }
 
-#if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
-#ifdef HAVE_WINRT
-    #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
-#endif
-
-BOOL WINAPI DllMain( HINSTANCE, DWORD, LPVOID );
-
-BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID lpReserved )
-{
-    if( fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH )
-    {
-        if (lpReserved != NULL) // called after ExitProcess() call
-            cv::__termination = true;
-        cv::deleteThreadAllocData();
-        cv::deleteThreadData();
-    }
-    return TRUE;
-}
-#endif
-
 namespace cv
 {
 
@@ -841,36 +821,54 @@ void Mutex::lock() { impl->lock(); }
 void Mutex::unlock() { impl->unlock(); }
 bool Mutex::trylock() { return impl->trylock(); }
 
-}
 
 //////////////////////////////// thread-local storage ////////////////////////////////
 
-namespace cv
+class TLSStorage
 {
+    std::vector<void*> tlsData_;
+public:
+    TLSStorage() { tlsData_.reserve(16); }
+    ~TLSStorage();
+    inline void* getData(int key) const
+    {
+        CV_DbgAssert(key >= 0);
+        return (key < (int)tlsData_.size()) ? tlsData_[key] : NULL;
+    }
+    inline void setData(int key, void* data)
+    {
+        CV_DbgAssert(key >= 0);
+        if (key >= (int)tlsData_.size())
+        {
+            tlsData_.resize(key + 1, NULL);
+        }
+        tlsData_[key] = data;
+    }
 
-TLSData::TLSData()
-{
-    device = 0;
-    useOpenCL = -1;
-}
+    inline static TLSStorage* get();
+};
 
 #ifdef WIN32
+#pragma warning(disable:4505) // unreferenced local function has been removed
 
 #ifdef HAVE_WINRT
     // using C++11 thread attribute for local thread data
-    static __declspec( thread ) TLSData* g_tlsdata = NULL;
+    static __declspec( thread ) TLSStorage* g_tlsdata = NULL;
 
-    static void deleteThreadRNGData()
+    static void deleteThreadData()
     {
         if (g_tlsdata)
+        {
             delete g_tlsdata;
+            g_tlsdata = NULL;
+        }
     }
 
-    TLSData* TLSData::get()
+    inline TLSStorage* TLSStorage::get()
     {
         if (!g_tlsdata)
         {
-            g_tlsdata = new TLSData;
+            g_tlsdata = new TLSStorage;
         }
         return g_tlsdata;
     }
@@ -880,55 +878,169 @@ TLSData::TLSData()
 #endif
     static DWORD tlsKey = TLS_OUT_OF_INDEXES;
 
-    void deleteThreadData()
+    static void deleteThreadData()
     {
-        if( tlsKey != TLS_OUT_OF_INDEXES )
-            delete (TLSData*)TlsGetValue( tlsKey );
+        if(tlsKey != TLS_OUT_OF_INDEXES)
+        {
+            delete (TLSStorage*)TlsGetValue(tlsKey);
+            TlsSetValue(tlsKey, NULL);
+        }
     }
 
-    TLSData* TLSData::get()
+    inline TLSStorage* TLSStorage::get()
     {
-        if( tlsKey == TLS_OUT_OF_INDEXES )
+        if (tlsKey == TLS_OUT_OF_INDEXES)
         {
             tlsKey = TlsAlloc();
             CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
         }
-        TLSData* d = (TLSData*)TlsGetValue( tlsKey );
-        if( !d )
+        TLSStorage* d = (TLSStorage*)TlsGetValue(tlsKey);
+        if (!d)
         {
-            d = new TLSData;
-            TlsSetValue( tlsKey, d );
+            d = new TLSStorage;
+            TlsSetValue(tlsKey, d);
         }
         return d;
     }
 #endif //HAVE_WINRT
+
+#if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
+#ifdef HAVE_WINRT
+    #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
+#endif
+
+BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID);
+
+BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved)
+{
+    if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
+    {
+        if (lpReserved != NULL) // called after ExitProcess() call
+            cv::__termination = true;
+        cv::deleteThreadAllocData();
+        cv::deleteThreadData();
+    }
+    return TRUE;
+}
+#endif
+
 #else
     static pthread_key_t tlsKey = 0;
     static pthread_once_t tlsKeyOnce = PTHREAD_ONCE_INIT;
 
-    static void deleteTLSData(void* data)
+    static void deleteTLSStorage(void* data)
     {
-        delete (TLSData*)data;
+        delete (TLSStorage*)data;
     }
 
     static void makeKey()
     {
-        int errcode = pthread_key_create(&tlsKey, deleteTLSData);
+        int errcode = pthread_key_create(&tlsKey, deleteTLSStorage);
         CV_Assert(errcode == 0);
     }
 
-    TLSData* TLSData::get()
+    inline TLSStorage* TLSStorage::get()
     {
         pthread_once(&tlsKeyOnce, makeKey);
-        TLSData* d = (TLSData*)pthread_getspecific(tlsKey);
+        TLSStorage* d = (TLSStorage*)pthread_getspecific(tlsKey);
         if( !d )
         {
-            d = new TLSData;
+            d = new TLSStorage;
             pthread_setspecific(tlsKey, d);
         }
         return d;
     }
 #endif
+
+class TLSContainerStorage
+{
+    cv::Mutex mutex_;
+    std::vector<TLSDataContainer*> tlsContainers_;
+public:
+    TLSContainerStorage() { }
+    ~TLSContainerStorage()
+    {
+        for (size_t i = 0; i < tlsContainers_.size(); i++)
+        {
+            CV_DbgAssert(tlsContainers_[i] == NULL); // not all keys released
+            tlsContainers_[i] = NULL;
+        }
+    }
+
+    int allocateKey(TLSDataContainer* pContainer)
+    {
+        cv::AutoLock lock(mutex_);
+        tlsContainers_.push_back(pContainer);
+        return (int)tlsContainers_.size() - 1;
+    }
+    void releaseKey(int id, TLSDataContainer* pContainer)
+    {
+        cv::AutoLock lock(mutex_);
+        CV_Assert(tlsContainers_[id] == pContainer);
+        tlsContainers_[id] = NULL;
+        // currently, we don't go into thread's TLSData and release data for this key
+    }
+
+    void destroyData(int key, void* data)
+    {
+        cv::AutoLock lock(mutex_);
+        TLSDataContainer* k = tlsContainers_[key];
+        if (!k)
+            return;
+        try
+        {
+            k->deleteDataInstance(data);
+        }
+        catch (...)
+        {
+            CV_DbgAssert(k == NULL); // Debug this!
+        }
+    }
+};
+static TLSContainerStorage tlsContainerStorage;
+
+TLSDataContainer::TLSDataContainer()
+    : key_(-1)
+{
+    key_ = tlsContainerStorage.allocateKey(this);
+}
+
+TLSDataContainer::~TLSDataContainer()
+{
+    tlsContainerStorage.releaseKey(key_, this);
+    key_ = -1;
+}
+
+void* TLSDataContainer::getData() const
+{
+    CV_Assert(key_ >= 0);
+    TLSStorage* tlsData = TLSStorage::get();
+    void* data = tlsData->getData(key_);
+    if (!data)
+    {
+        data = this->createDataInstance();
+        CV_DbgAssert(data != NULL);
+        tlsData->setData(key_, data);
+    }
+    return data;
 }
 
+TLSStorage::~TLSStorage()
+{
+    for (int i = 0; i < (int)tlsData_.size(); i++)
+    {
+        void*& data = tlsData_[i];
+        if (data)
+        {
+            tlsContainerStorage.destroyData(i, data);
+            data = NULL;
+        }
+    }
+    tlsData_.clear();
+}
+
+TLSData<CoreTLSData> coreTlsData;
+
+} // namespace cv
+
 /* End of file. */
index 2d97a04..0b61374 100644 (file)
@@ -217,6 +217,7 @@ UMat Mat::getUMat(int accessFlags) const
         if(!a)
             a = a0;
         temp_u = a->allocate(dims, size.p, type(), data, step.p, accessFlags);
+        temp_u->refcount = 1;
     }
     UMat::getStdAllocator()->allocate(temp_u, accessFlags);
     hdr.flags = flags;
@@ -224,6 +225,7 @@ UMat Mat::getUMat(int accessFlags) const
     finalizeHdr(hdr);
     hdr.u = temp_u;
     hdr.offset = data - datastart;
+    hdr.addref();
     return hdr;
 }
 
@@ -271,6 +273,7 @@ void UMat::create(int d, const int* _sizes, int _type)
     }
 
     finalizeHdr(*this);
+    addref();
 }
 
 void UMat::copySize(const UMat& m)
@@ -294,6 +297,7 @@ UMat::~UMat()
 void UMat::deallocate()
 {
     u->currAllocator->deallocate(u);
+    u = NULL;
 }
 
 
@@ -643,11 +647,10 @@ void UMat::copyTo(OutputArray _dst) const
     if( _dst.kind() == _InputArray::UMAT )
     {
         UMat dst = _dst.getUMat();
-        void* srchandle = handle(ACCESS_READ);
-        void* dsthandle = dst.handle(ACCESS_WRITE);
-        if( srchandle == dsthandle && dst.offset == offset )
+        if( u == dst.u && dst.offset == offset )
             return;
         dst.ndoffset(dstofs);
+        dstofs[dims-1] *= esz;
         CV_Assert(u->currAllocator == dst.u->currAllocator);
         u->currAllocator->copy(u, dst.u, dims, sz, srcofs, step.p, dstofs, dst.step.p, false);
     }
@@ -658,16 +661,56 @@ void UMat::copyTo(OutputArray _dst) const
     }
 }
 
-void UMat::convertTo(OutputArray, int, double, double) const
+void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const
 {
-    CV_Error(Error::StsNotImplemented, "");
+    bool noScale = std::fabs(alpha - 1) < DBL_EPSILON && std::fabs(beta) < DBL_EPSILON;
+    int stype = type(), cn = CV_MAT_CN(stype);
+
+    if( _type < 0 )
+        _type = _dst.fixedType() ? _dst.type() : stype;
+    else
+        _type = CV_MAKETYPE(CV_MAT_DEPTH(_type), cn);
+
+    int sdepth = CV_MAT_DEPTH(stype), ddepth = CV_MAT_DEPTH(_type);
+    if( sdepth == ddepth && noScale )
+    {
+        copyTo(_dst);
+        return;
+    }
+
+    bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
+    bool needDouble = sdepth == CV_64F || ddepth == CV_64F;
+    if( dims <= 2 && cn && _dst.isUMat() && ocl::useOpenCL() &&
+            ((needDouble && doubleSupport) || !needDouble) )
+    {
+        char cvt[40];
+        ocl::Kernel k("convertTo", ocl::core::convert_oclsrc,
+                      format("-D srcT=%s -D dstT=%s -D convertToDT=%s%s", ocl::typeToStr(sdepth),
+                             ocl::typeToStr(ddepth), ocl::convertTypeStr(CV_32F, ddepth, 1, cvt),
+                             doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
+        if (!k.empty())
+        {
+            _dst.create( size(), _type );
+            UMat dst = _dst.getUMat();
+
+            float alphaf = (float)alpha, betaf = (float)beta;
+            k.args(ocl::KernelArg::ReadOnlyNoSize(*this), ocl::KernelArg::WriteOnly(dst, cn), alphaf, betaf);
+
+            size_t globalsize[2] = { dst.cols * cn, dst.rows };
+            if (k.run(2, globalsize, NULL, false))
+                return;
+        }
+    }
+
+    Mat m = getMat(ACCESS_READ);
+    m.convertTo(_dst, _type, alpha, beta);
 }
 
 UMat& UMat::setTo(InputArray _value, InputArray _mask)
 {
     bool haveMask = !_mask.empty();
     int tp = type(), cn = CV_MAT_CN(tp);
-    if( dims <= 2 && cn <= 4 && ocl::useOpenCL() )
+    if( dims <= 2 && cn <= 4 && cn != 3 && ocl::useOpenCL() )
     {
         Mat value = _value.getMat();
         CV_Assert( checkScalar(value, type(), _value.kind(), _InputArray::UMAT) );
@@ -707,9 +750,9 @@ UMat& UMat::setTo(InputArray _value, InputArray _mask)
     return *this;
 }
 
-UMat& UMat::operator = (const Scalar&)
+UMat& UMat::operator = (const Scalar& s)
 {
-    CV_Error(Error::StsNotImplemented, "");
+    setTo(s);
     return *this;
 }
 
index 42fc347..7a24f31 100644 (file)
@@ -999,6 +999,67 @@ OCL_TEST_P(Flip, BOTH)
         Near(0);
     }
 }
+//////////////////////////////////////// minMaxIdx /////////////////////////////////////////
+
+typedef ArithmTestBase MinMaxIdx;
+
+OCL_TEST_P(MinMaxIdx, Mat)
+{
+    for (int j = 0; j < test_loop_times; j++)
+    {
+        generateTestData();
+
+        int p1[2], p2[2], up1[2], up2[2];
+        double minv, maxv, uminv, umaxv;
+
+        if(src1_roi.channels() > 1)
+        {
+            OCL_OFF(cv::minMaxIdx(src2_roi, &minv, &maxv) );
+            OCL_ON(cv::minMaxIdx(usrc2_roi, &uminv, &umaxv));
+
+            EXPECT_DOUBLE_EQ(minv, uminv);
+            EXPECT_DOUBLE_EQ(maxv, umaxv);
+        }
+        else
+        {
+            OCL_OFF(cv::minMaxIdx(src2_roi, &minv, &maxv, p1, p2, noArray()));
+            OCL_ON(cv::minMaxIdx(usrc2_roi, &uminv, &umaxv, up1, up2, noArray()));
+
+            EXPECT_DOUBLE_EQ(minv, uminv);
+            EXPECT_DOUBLE_EQ(maxv, umaxv);
+            for( int i = 0; i < 2; i++)
+            {
+                EXPECT_EQ(p1[i], up1[i]);
+                EXPECT_EQ(p2[i], up2[i]);
+            }
+        }
+    }
+}
+
+typedef ArithmTestBase MinMaxIdx_Mask;
+
+OCL_TEST_P(MinMaxIdx_Mask, Mat)
+{
+    for (int j = 0; j < test_loop_times; j++)
+    {
+        generateTestData();
+
+        int p1[2], p2[2], up1[2], up2[2];
+        double minv, maxv, uminv, umaxv;
+
+        OCL_OFF(cv::minMaxIdx(src2_roi, &minv, &maxv, p1, p2, mask_roi));
+        OCL_ON(cv::minMaxIdx(usrc2_roi, &uminv, &umaxv, up1, up2, umask_roi));
+
+        EXPECT_DOUBLE_EQ(minv, uminv);
+        EXPECT_DOUBLE_EQ(maxv, umaxv);
+        for( int i = 0; i < 2; i++)
+        {
+            EXPECT_EQ(p1[i], up1[i]);
+            EXPECT_EQ(p2[i], up2[i]);
+        }
+
+    }
+}
 
 //////////////////////////////// Norm /////////////////////////////////////////////////
 
@@ -1149,6 +1210,8 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Exp, Combine(::testing::Values(CV_32F, CV_64
 OCL_INSTANTIATE_TEST_CASE_P(Arithm, Phase, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool()));
 OCL_INSTANTIATE_TEST_CASE_P(Arithm, Magnitude, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool()));
 OCL_INSTANTIATE_TEST_CASE_P(Arithm, Flip, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
+OCL_INSTANTIATE_TEST_CASE_P(Arithm, MinMaxIdx, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
+OCL_INSTANTIATE_TEST_CASE_P(Arithm, MinMaxIdx_Mask, Combine(OCL_ALL_DEPTHS, ::testing::Values(Channels(1)), Bool()));
 OCL_INSTANTIATE_TEST_CASE_P(Arithm, Norm, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
 OCL_INSTANTIATE_TEST_CASE_P(Arithm, Sqrt, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool()));
 
diff --git a/modules/core/test/ocl/test_gemm.cpp b/modules/core/test/ocl/test_gemm.cpp
new file mode 100644 (file)
index 0000000..4d453f3
--- /dev/null
@@ -0,0 +1,149 @@
+/*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, Multicoreware, Inc., all rights reserved.
+// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// @Authors
+//    Peng Xiao, pengxiao@multicorewareinc.com
+// 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*/
+
+#include "test_precomp.hpp"
+#include "opencv2/ts/ocl_test.hpp"
+
+#ifdef HAVE_OPENCL
+
+namespace cvtest {
+namespace ocl {
+
+////////////////////////////////////////////////////////////////////////////
+// GEMM
+
+PARAM_TEST_CASE(Gemm,
+                MatType,
+                bool, // GEMM_1_T
+                bool, // GEMM_2_T
+                bool, // GEMM_3_T
+                bool // ROI
+                )
+{
+    bool use_roi;
+    int type, flags;
+    bool atrans, btrans, ctrans;
+
+    double alpha, beta;
+
+    TEST_DECLARE_INPUT_PARAMETER(A)
+    TEST_DECLARE_INPUT_PARAMETER(B)
+    TEST_DECLARE_INPUT_PARAMETER(C)
+    TEST_DECLARE_OUTPUT_PARAMETER(D)
+
+    virtual void SetUp()
+    {
+        atrans = btrans = ctrans = false;
+
+        type = GET_PARAM(0);
+        use_roi = GET_PARAM(4);
+
+        flags = 0;
+        if (GET_PARAM(1))
+            flags |= GEMM_1_T, atrans = true;
+        if (GET_PARAM(2))
+            flags |= GEMM_2_T, btrans = true;
+        if (GET_PARAM(3))
+            flags |= GEMM_3_T, ctrans = true;
+    }
+
+    void generateTestData()
+    {
+        Size ARoiSize = randomSize(1, MAX_VALUE);
+        Border ABorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
+        randomSubMat(A, A_roi, ARoiSize, ABorder, type, -11, 11);
+
+        if (atrans)
+            ARoiSize = Size(ARoiSize.height, ARoiSize.width);
+
+        Size BRoiSize = randomSize(1, MAX_VALUE);
+        if (btrans)
+            BRoiSize.width = ARoiSize.width;
+        else
+            BRoiSize.height = ARoiSize.width;
+
+        Border BBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
+        randomSubMat(B, B_roi, BRoiSize, BBorder, type, -11, 11);
+
+        if (btrans)
+            BRoiSize = Size(BRoiSize.height, BRoiSize.width);
+
+        Size DRoiSize = Size(BRoiSize.width, ARoiSize.height), CRoiSizeT(DRoiSize.height, DRoiSize.width);
+        Border CBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
+        randomSubMat(C, C_roi, ctrans ? CRoiSizeT : DRoiSize, CBorder, type, -11, 11);
+
+        Border DBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
+        randomSubMat(D, D_roi, DRoiSize, DBorder, type, -11, 11);
+
+        alpha = randomDouble(-4, 4);
+        beta = randomDouble(-4, 4);
+
+        UMAT_UPLOAD_INPUT_PARAMETER(A)
+        UMAT_UPLOAD_INPUT_PARAMETER(B)
+        UMAT_UPLOAD_INPUT_PARAMETER(C)
+        UMAT_UPLOAD_OUTPUT_PARAMETER(D)
+    }
+};
+
+OCL_TEST_P(Gemm, Accuracy)
+{
+    for (int i = 0; i < test_loop_times; ++i)
+    {
+        generateTestData();
+
+        OCL_OFF(cv::gemm(A_roi, B_roi, alpha, C_roi, beta, D_roi, flags));
+        OCL_ON(cv::gemm(uA_roi, uB_roi, alpha, uC_roi, beta, uD_roi, flags));
+
+        double eps = D_roi.size().area() * 1e-4;
+        OCL_EXPECT_MATS_NEAR(D, eps);
+    }
+}
+
+OCL_INSTANTIATE_TEST_CASE_P(Core, Gemm, ::testing::Combine(
+                            testing::Values(CV_32FC1, CV_32FC2, CV_64FC1, CV_64FC2),
+                            Bool(), Bool(), Bool(), Bool()));
+
+} } // namespace cvtest::ocl
+
+#endif // HAVE_OPENCL
diff --git a/modules/core/test/ocl/test_matrix_operation.cpp b/modules/core/test/ocl/test_matrix_operation.cpp
new file mode 100644 (file)
index 0000000..aabbb3f
--- /dev/null
@@ -0,0 +1,129 @@
+/*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.
+//
+// @Authors
+//    Jia Haipeng, jiahaipeng95@gmail.com
+//
+// 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*/
+
+#include "test_precomp.hpp"
+#include "opencv2/ts/ocl_test.hpp"
+
+#ifdef HAVE_OPENCL
+
+namespace cvtest {
+namespace ocl {
+
+////////////////////////////////converto/////////////////////////////////////////////////
+
+PARAM_TEST_CASE(MatrixTestBase, MatDepth, MatDepth, Channels, bool)
+{
+    int src_depth, cn, dstType;
+    bool use_roi;
+
+    TEST_DECLARE_INPUT_PARAMETER(src)
+    TEST_DECLARE_OUTPUT_PARAMETER(dst)
+
+    virtual void SetUp()
+    {
+        src_depth = GET_PARAM(0);
+        cn = GET_PARAM(2);
+        dstType = CV_MAKE_TYPE(GET_PARAM(1), cn);
+
+        use_roi = GET_PARAM(3);
+    }
+
+    virtual void generateTestData()
+    {
+        Size roiSize = randomSize(1, MAX_VALUE);
+        Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
+        randomSubMat(src, src_roi, roiSize, srcBorder, CV_MAKE_TYPE(src_depth, cn), -MAX_VALUE, MAX_VALUE);
+
+        Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
+        randomSubMat(dst, dst_roi, roiSize, dstBorder, dstType, 5, 16);
+
+        UMAT_UPLOAD_INPUT_PARAMETER(src)
+        UMAT_UPLOAD_OUTPUT_PARAMETER(dst)
+    }
+};
+
+typedef MatrixTestBase ConvertTo;
+
+OCL_TEST_P(ConvertTo, Accuracy)
+{
+    for (int j = 0; j < test_loop_times; j++)
+    {
+        generateTestData();
+
+        double alpha = randomDouble(-4, 4), beta = randomDouble(-4, 4);
+
+        OCL_OFF(src_roi.convertTo(dst_roi, dstType, alpha, beta));
+        OCL_ON(usrc_roi.convertTo(udst_roi, dstType, alpha, beta));
+
+        double eps = src_depth >= CV_32F || CV_MAT_DEPTH(dstType) >= CV_32F ? 1e-4 : 1;
+        OCL_EXPECT_MATS_NEAR(dst, eps);
+    }
+}
+
+typedef MatrixTestBase CopyTo;
+
+OCL_TEST_P(CopyTo, Accuracy)
+{
+    for (int j = 0; j < test_loop_times; j++)
+    {
+        generateTestData();
+
+        OCL_OFF(src_roi.copyTo(dst_roi));
+        OCL_ON(usrc_roi.copyTo(udst_roi));
+
+        OCL_EXPECT_MATS_NEAR(dst, 0);
+    }
+}
+
+OCL_INSTANTIATE_TEST_CASE_P(MatrixOperation, ConvertTo, Combine(
+                            OCL_ALL_DEPTHS, OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
+
+OCL_INSTANTIATE_TEST_CASE_P(MatrixOperation, CopyTo, Combine(
+                                OCL_ALL_DEPTHS, Values((MatDepth)0), OCL_ALL_CHANNELS, Bool()));
+
+} } // namespace cvtest::ocl
+
+#endif
index 653dc49..1dfe1d7 100644 (file)
 
 #include <string>
 #include <iostream>
-#include <fstream>
-#include <iterator>
-#include <limits>
-#include <numeric>
 #include "opencv2/core/ocl.hpp"
 
 using namespace cv;
 using namespace std;
 
-class CV_UMatTest : public cvtest::BaseTest
+class CV_UMatTest :
+        public cvtest::BaseTest
 {
 public:
     CV_UMatTest() {}
@@ -204,37 +201,37 @@ TEST(Core_UMat, base) { CV_UMatTest test; test.safe_run(); }
 TEST(Core_UMat, getUMat)
 {
     {
-    int a[3] = { 1, 2, 3 };
-    Mat m = Mat(1, 1, CV_32SC3, a);
-    UMat u = m.getUMat(ACCESS_READ);
-    EXPECT_NE((void*)NULL, u.u);
+        int a[3] = { 1, 2, 3 };
+        Mat m = Mat(1, 1, CV_32SC3, a);
+        UMat u = m.getUMat(ACCESS_READ);
+        EXPECT_NE((void*)NULL, u.u);
     }
 
     {
-    Mat m(10, 10, CV_8UC1), ref;
-    for (int y = 0; y < m.rows; ++y)
-    {
-        uchar * const ptr = m.ptr<uchar>(y);
-        for (int x = 0; x < m.cols; ++x)
-            ptr[x] = (uchar)(x + y * 2);
-    }
+        Mat m(10, 10, CV_8UC1), ref;
+        for (int y = 0; y < m.rows; ++y)
+        {
+            uchar * const ptr = m.ptr<uchar>(y);
+            for (int x = 0; x < m.cols; ++x)
+                ptr[x] = (uchar)(x + y * 2);
+        }
 
-    ref = m.clone();
-    Rect r(1, 1, 8, 8);
-    ref(r).setTo(17);
+        ref = m.clone();
+        Rect r(1, 1, 8, 8);
+        ref(r).setTo(17);
 
-    {
-        UMat um = m(r).getUMat(ACCESS_WRITE);
-        um.setTo(17);
-    }
+        {
+            UMat um = m(r).getUMat(ACCESS_WRITE);
+            um.setTo(17);
+        }
 
-    double err = norm(m, ref, NORM_INF);
-    if(err > 0)
-    {
-        std::cout << "m: " << m << std::endl;
-        std::cout << "ref: " << ref << std::endl;
-    }
-    EXPECT_EQ(err, 0.);
+        double err = norm(m, ref, NORM_INF);
+        if (err > 0)
+        {
+            std::cout << "m: " << std::endl << m << std::endl;
+            std::cout << "ref: " << std::endl << ref << std::endl;
+        }
+        EXPECT_EQ(0., err);
     }
 }
 
index 83688c0..bf84ed0 100644 (file)
@@ -35,6 +35,7 @@ Abstract base class for computing descriptors for image keypoints. ::
 
         virtual int descriptorSize() const = 0;
         virtual int descriptorType() const = 0;
+        virtual int defaultNorm() const = 0;
 
         static Ptr<DescriptorExtractor> create( const String& descriptorExtractorType );
 
@@ -114,6 +115,7 @@ them into a single color descriptor. ::
         virtual void write( FileStorage& ) const;
         virtual int descriptorSize() const;
         virtual int descriptorType() const;
+        virtual int defaultNorm() const;
     protected:
         ...
     };
@@ -141,6 +143,7 @@ Strecha C., Fua P. *BRIEF: Binary Robust Independent Elementary Features* ,
         virtual void write( FileStorage& ) const;
         virtual int descriptorSize() const;
         virtual int descriptorType() const;
+        virtual int defaultNorm() const;
     protected:
         ...
     };
index 644634f..8269195 100644 (file)
@@ -27,7 +27,7 @@ Lixin Fan, Jutta Willamowski, Cedric Bray, 2004. ::
 
         void add( const Mat& descriptors );
         const vector<Mat>& getDescriptors() const;
-        int descripotorsCount() const;
+        int descriptorsCount() const;
 
         virtual void clear();
 
@@ -56,11 +56,11 @@ Returns a training set of descriptors.
 
 
 
-BOWTrainer::descripotorsCount
+BOWTrainer::descriptorsCount
 ---------------------------------
 Returns the count of all descriptors stored in the training set.
 
-.. ocv:function:: int BOWTrainer::descripotorsCount() const
+.. ocv:function:: int BOWTrainer::descriptorsCount() const
 
 
 
index 9cbae22..3655ab8 100644 (file)
@@ -169,6 +169,7 @@ public:
 
     CV_WRAP virtual int descriptorSize() const = 0;
     CV_WRAP virtual int descriptorType() const = 0;
+    CV_WRAP virtual int defaultNorm() const = 0;
 
     CV_WRAP virtual bool empty() const;
 
@@ -226,6 +227,8 @@ public:
     int descriptorSize() const;
     // returns the descriptor type
     int descriptorType() const;
+    // returns the default norm type
+    int defaultNorm() const;
 
     // Compute the BRISK features on an image
     void operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const;
@@ -320,6 +323,8 @@ public:
     int descriptorSize() const;
     // returns the descriptor type
     int descriptorType() const;
+    // returns the default norm type
+    int defaultNorm() const;
 
     // Compute the ORB features and descriptors on an image
     void operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const;
@@ -377,6 +382,9 @@ public:
     /** returns the descriptor type */
     virtual int descriptorType() const;
 
+    /** returns the default norm type */
+    virtual int defaultNorm() const;
+
     /** select the 512 "best description pairs"
          * @param images grayscale images set
          * @param keypoints set of detected keypoints
@@ -837,6 +845,7 @@ public:
 
     virtual int descriptorSize() const;
     virtual int descriptorType() const;
+    virtual int defaultNorm() const;
 
     virtual bool empty() const;
 
@@ -863,6 +872,7 @@ public:
 
     virtual int descriptorSize() const;
     virtual int descriptorType() const;
+    virtual int defaultNorm() const;
 
     /// @todo read and write for brief
 
@@ -1453,7 +1463,7 @@ public:
 
     void add( const Mat& descriptors );
     const std::vector<Mat>& getDescriptors() const;
-    int descripotorsCount() const;
+    int descriptorsCount() const;
 
     virtual void clear();
 
index a257f6c..a3cfb60 100644 (file)
@@ -72,7 +72,7 @@ const std::vector<Mat>& BOWTrainer::getDescriptors() const
     return descriptors;
 }
 
-int BOWTrainer::descripotorsCount() const
+int BOWTrainer::descriptorsCount() const
 {
     return descriptors.empty() ? 0 : size;
 }
index a429451..2521919 100644 (file)
@@ -125,6 +125,11 @@ int BriefDescriptorExtractor::descriptorType() const
     return CV_8UC1;
 }
 
+int BriefDescriptorExtractor::defaultNorm() const
+{
+    return NORM_HAMMING;
+}
+
 void BriefDescriptorExtractor::read( const FileNode& fn)
 {
     int dSize = fn["descriptorSize"];
index 76bded6..a3c5d7e 100644 (file)
@@ -712,6 +712,12 @@ BRISK::descriptorType() const
   return CV_8U;
 }
 
+int
+BRISK::defaultNorm() const
+{
+  return NORM_HAMMING;
+}
+
 BRISK::~BRISK()
 {
   delete[] patternPoints_;
index b79768a..9e0ac5c 100644 (file)
@@ -247,6 +247,11 @@ int OpponentColorDescriptorExtractor::descriptorType() const
     return descriptorExtractor->descriptorType();
 }
 
+int OpponentColorDescriptorExtractor::defaultNorm() const
+{
+    return descriptorExtractor->defaultNorm();
+}
+
 bool OpponentColorDescriptorExtractor::empty() const
 {
     return !descriptorExtractor || descriptorExtractor->empty();
index 086a2e2..35ff97f 100644 (file)
@@ -54,8 +54,9 @@ static const int FREAK_NB_SCALES = FREAK::NB_SCALES;
 static const int FREAK_NB_PAIRS = FREAK::NB_PAIRS;
 static const int FREAK_NB_ORIENPAIRS = FREAK::NB_ORIENPAIRS;
 
+// default pairs
 static const int FREAK_DEF_PAIRS[FREAK::NB_PAIRS] =
-{ // default pairs
+{
      404,431,818,511,181,52,311,874,774,543,719,230,417,205,11,
      560,149,265,39,306,165,857,250,8,61,15,55,717,44,412,
      592,134,761,695,660,782,625,487,549,516,271,665,762,392,178,
@@ -92,15 +93,17 @@ static const int FREAK_DEF_PAIRS[FREAK::NB_PAIRS] =
      670,249,36,581,389,605,331,518,442,822
 };
 
+// used to sort pairs during pairs selection
 struct PairStat
-{ // used to sort pairs during pairs selection
+{
     double mean;
     int idx;
 };
 
 struct sortMean
 {
-    bool operator()( const PairStat& a, const PairStat& b ) const {
+    bool operator()( const PairStat& a, const PairStat& b ) const
+    {
         return a.mean < b.mean;
     }
 };
@@ -130,17 +133,21 @@ void FREAK::buildPattern()
                              radius[6]/2.0, radius[6]/2.0
                             };
     // fill the lookup table
-    for( int scaleIdx=0; scaleIdx < FREAK_NB_SCALES; ++scaleIdx ) {
+    for( int scaleIdx=0; scaleIdx < FREAK_NB_SCALES; ++scaleIdx )
+    {
         patternSizes[scaleIdx] = 0; // proper initialization
         scalingFactor = std::pow(scaleStep,scaleIdx); //scale of the pattern, scaleStep ^ scaleIdx
 
-        for( int orientationIdx = 0; orientationIdx < FREAK_NB_ORIENTATION; ++orientationIdx ) {
+        for( int orientationIdx = 0; orientationIdx < FREAK_NB_ORIENTATION; ++orientationIdx )
+        {
             theta = double(orientationIdx)* 2*CV_PI/double(FREAK_NB_ORIENTATION); // orientation of the pattern
             int pointIdx = 0;
 
             PatternPoint* patternLookupPtr = &patternLookup[0];
-            for( size_t i = 0; i < 8; ++i ) {
-                for( int k = 0 ; k < n[i]; ++k ) {
+            for( size_t i = 0; i < 8; ++i )
+            {
+                for( int k = 0 ; k < n[i]; ++k )
+                {
                     beta = CV_PI/n[i] * (i%2); // orientation offset so that groups of points on each circles are staggered
                     alpha = double(k)* 2*CV_PI/double(n[i])+beta+theta;
 
@@ -182,7 +189,8 @@ void FREAK::buildPattern()
     orientationPairs[39].i=30; orientationPairs[39].j=33; orientationPairs[40].i=31; orientationPairs[40].j=34; orientationPairs[41].i=32; orientationPairs[41].j=35;
     orientationPairs[42].i=36; orientationPairs[42].j=39; orientationPairs[43].i=37; orientationPairs[43].j=40; orientationPairs[44].i=38; orientationPairs[44].j=41;
 
-    for( unsigned m = FREAK_NB_ORIENPAIRS; m--; ) {
+    for( unsigned m = FREAK_NB_ORIENPAIRS; m--; )
+    {
         const float dx = patternLookup[orientationPairs[m].i].x-patternLookup[orientationPairs[m].j].x;
         const float dy = patternLookup[orientationPairs[m].i].y-patternLookup[orientationPairs[m].j].y;
         const float norm_sq = (dx*dx+dy*dy);
@@ -192,30 +200,37 @@ void FREAK::buildPattern()
 
     // build the list of description pairs
     std::vector<DescriptionPair> allPairs;
-    for( unsigned int i = 1; i < (unsigned int)FREAK_NB_POINTS; ++i ) {
+    for( unsigned int i = 1; i < (unsigned int)FREAK_NB_POINTS; ++i )
+    {
         // (generate all the pairs)
-        for( unsigned int j = 0; (unsigned int)j < i; ++j ) {
+        for( unsigned int j = 0; (unsigned int)j < i; ++j )
+        {
             DescriptionPair pair = {(uchar)i,(uchar)j};
             allPairs.push_back(pair);
         }
     }
     // Input vector provided
-    if( !selectedPairs0.empty() ) {
-        if( (int)selectedPairs0.size() == FREAK_NB_PAIRS ) {
+    if( !selectedPairs0.empty() )
+    {
+        if( (int)selectedPairs0.size() == FREAK_NB_PAIRS )
+        {
             for( int i = 0; i < FREAK_NB_PAIRS; ++i )
                  descriptionPairs[i] = allPairs[selectedPairs0.at(i)];
         }
-        else {
+        else
+        {
             CV_Error(Error::StsVecLengthErr, "Input vector does not match the required size");
         }
     }
-    else { // default selected pairs
+    else // default selected pairs
+    {
         for( int i = 0; i < FREAK_NB_PAIRS; ++i )
              descriptionPairs[i] = allPairs[FREAK_DEF_PAIRS[i]];
     }
 }
 
-void FREAK::computeImpl( const Mat& image, std::vector<KeyPoint>& keypoints, Mat& descriptors ) const {
+void FREAK::computeImpl( const Mat& image, std::vector<KeyPoint>& keypoints, Mat& descriptors ) const
+{
 
     if( image.empty() )
         return;
@@ -236,8 +251,10 @@ void FREAK::computeImpl( const Mat& image, std::vector<KeyPoint>& keypoints, Mat
     int direction1;
 
     // compute the scale index corresponding to the keypoint size and remove keypoints close to the border
-    if( scaleNormalized ) {
-        for( size_t k = keypoints.size(); k--; ) {
+    if( scaleNormalized )
+    {
+        for( size_t k = keypoints.size(); k--; )
+        {
             //Is k non-zero? If so, decrement it and continue"
             kpScaleIdx[k] = std::max( (int)(std::log(keypoints[k].size/FREAK_SMALLEST_KP_SIZE)*sizeCst+0.5) ,0);
             if( kpScaleIdx[k] >= FREAK_NB_SCALES )
@@ -247,24 +264,29 @@ void FREAK::computeImpl( const Mat& image, std::vector<KeyPoint>& keypoints, Mat
                  keypoints[k].pt.y <= patternSizes[kpScaleIdx[k]] ||
                  keypoints[k].pt.x >= image.cols-patternSizes[kpScaleIdx[k]] ||
                  keypoints[k].pt.y >= image.rows-patternSizes[kpScaleIdx[k]]
-               ) {
+               )
+            {
                 keypoints.erase(kpBegin+k);
                 kpScaleIdx.erase(ScaleIdxBegin+k);
             }
         }
     }
-    else {
+    else
+    {
         const int scIdx = std::max( (int)(1.0986122886681*sizeCst+0.5) ,0);
-        for( size_t k = keypoints.size(); k--; ) {
+        for( size_t k = keypoints.size(); k--; )
+        {
             kpScaleIdx[k] = scIdx; // equivalent to the formule when the scale is normalized with a constant size of keypoints[k].size=3*SMALLEST_KP_SIZE
-            if( kpScaleIdx[k] >= FREAK_NB_SCALES ) {
+            if( kpScaleIdx[k] >= FREAK_NB_SCALES )
+            {
                 kpScaleIdx[k] = FREAK_NB_SCALES-1;
             }
             if( keypoints[k].pt.x <= patternSizes[kpScaleIdx[k]] ||
                 keypoints[k].pt.y <= patternSizes[kpScaleIdx[k]] ||
                 keypoints[k].pt.x >= image.cols-patternSizes[kpScaleIdx[k]] ||
                 keypoints[k].pt.y >= image.rows-patternSizes[kpScaleIdx[k]]
-               ) {
+               )
+            {
                 keypoints.erase(kpBegin+k);
                 kpScaleIdx.erase(ScaleIdxBegin+k);
             }
@@ -272,7 +294,8 @@ void FREAK::computeImpl( const Mat& image, std::vector<KeyPoint>& keypoints, Mat
     }
 
     // allocate descriptor memory, estimate orientations, extract descriptors
-    if( !extAll ) {
+    if( !extAll )
+    {
         // extract the best comparisons only
         descriptors = cv::Mat::zeros((int)keypoints.size(), FREAK_NB_PAIRS/8, CV_8U);
 #if CV_SSE2
@@ -280,20 +303,25 @@ void FREAK::computeImpl( const Mat& image, std::vector<KeyPoint>& keypoints, Mat
 #else
         std::bitset<FREAK_NB_PAIRS>* ptr = (std::bitset<FREAK_NB_PAIRS>*) (descriptors.data+(keypoints.size()-1)*descriptors.step[0]);
 #endif
-        for( size_t k = keypoints.size(); k--; ) {
+        for( size_t k = keypoints.size(); k--; )
+        {
             // estimate orientation (gradient)
-            if( !orientationNormalized ) {
+            if( !orientationNormalized )
+            {
                 thetaIdx = 0; // assign 0° to all keypoints
                 keypoints[k].angle = 0.0;
             }
-            else {
+            else
+            {
                 // get the points intensity value in the un-rotated pattern
-                for( int i = FREAK_NB_POINTS; i--; ) {
+                for( int i = FREAK_NB_POINTS; i--; )
+                {
                     pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], 0, i);
                 }
                 direction0 = 0;
                 direction1 = 0;
-                for( int m = 45; m--; ) {
+                for( int m = 45; m--; )
+                {
                     //iterate through the orientation pairs
                     const int delta = (pointsValue[ orientationPairs[m].i ]-pointsValue[ orientationPairs[m].j ]);
                     direction0 += delta*(orientationPairs[m].weight_dx)/2048;
@@ -309,7 +337,8 @@ void FREAK::computeImpl( const Mat& image, std::vector<KeyPoint>& keypoints, Mat
                     thetaIdx -= FREAK_NB_ORIENTATION;
             }
             // extract descriptor at the computed orientation
-            for( int i = FREAK_NB_POINTS; i--; ) {
+            for( int i = FREAK_NB_POINTS; i--; )
+            {
                 pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], thetaIdx, i);
             }
 #if CV_SSE2
@@ -384,24 +413,29 @@ void FREAK::computeImpl( const Mat& image, std::vector<KeyPoint>& keypoints, Mat
 #endif
         }
     }
-    else { // extract all possible comparisons for selection
+    else // extract all possible comparisons for selection
+    {
         descriptors = cv::Mat::zeros((int)keypoints.size(), 128, CV_8U);
         std::bitset<1024>* ptr = (std::bitset<1024>*) (descriptors.data+(keypoints.size()-1)*descriptors.step[0]);
 
-        for( size_t k = keypoints.size(); k--; ) {
+        for( size_t k = keypoints.size(); k--; )
+        {
             //estimate orientation (gradient)
-            if( !orientationNormalized ) {
+            if( !orientationNormalized )
+            {
                 thetaIdx = 0;//assign 0° to all keypoints
                 keypoints[k].angle = 0.0;
             }
-            else {
+            else
+            {
                 //get the points intensity value in the un-rotated pattern
                 for( int i = FREAK_NB_POINTS;i--; )
                     pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], 0, i);
 
                 direction0 = 0;
                 direction1 = 0;
-                for( int m = 45; m--; ) {
+                for( int m = 45; m--; )
+                {
                     //iterate through the orientation pairs
                     const int delta = (pointsValue[ orientationPairs[m].i ]-pointsValue[ orientationPairs[m].j ]);
                     direction0 += delta*(orientationPairs[m].weight_dx)/2048;
@@ -418,15 +452,18 @@ void FREAK::computeImpl( const Mat& image, std::vector<KeyPoint>& keypoints, Mat
                     thetaIdx -= FREAK_NB_ORIENTATION;
             }
             // get the points intensity value in the rotated pattern
-            for( int i = FREAK_NB_POINTS; i--; ) {
+            for( int i = FREAK_NB_POINTS; i--; )
+            {
                 pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,
                                              keypoints[k].pt.y, kpScaleIdx[k], thetaIdx, i);
             }
 
             int cnt(0);
-            for( int i = 1; i < FREAK_NB_POINTS; ++i ) {
+            for( int i = 1; i < FREAK_NB_POINTS; ++i )
+            {
                 //(generate all the pairs)
-                for( int j = 0; j < i; ++j ) {
+                for( int j = 0; j < i; ++j )
+                {
                     ptr->set(cnt, pointsValue[i] >= pointsValue[j] );
                     ++cnt;
                 }
@@ -442,7 +479,8 @@ uchar FREAK::meanIntensity( const cv::Mat& image, const cv::Mat& integral,
                             const float kp_y,
                             const unsigned int scale,
                             const unsigned int rot,
-                            const unsigned int point) const {
+                            const unsigned int point) const
+{
     // get point position in image
     const PatternPoint& FreakPoint = patternLookup[scale*FREAK_NB_ORIENTATION*FREAK_NB_POINTS + rot*FREAK_NB_POINTS + point];
     const float xf = FreakPoint.x+kp_x;
@@ -455,7 +493,8 @@ uchar FREAK::meanIntensity( const cv::Mat& image, const cv::Mat& integral,
     const float radius = FreakPoint.sigma;
 
     // calculate output:
-    if( radius < 0.5 ) {
+    if( radius < 0.5 )
+    {
         // interpolation multipliers:
         const int r_x = static_cast<int>((xf-x)*1024);
         const int r_y = static_cast<int>((yf-y)*1024);
@@ -507,7 +546,8 @@ std::vector<int> FREAK::selectPairs(const std::vector<Mat>& images
     if( verbose )
         std::cout << "Number of images: " << images.size() << std::endl;
 
-    for( size_t i = 0;i < images.size(); ++i ) {
+    for( size_t i = 0;i < images.size(); ++i )
+    {
         Mat descriptorsTmp;
         computeImpl(images[i],keypoints[i],descriptorsTmp);
         descriptors.push_back(descriptorsTmp);
@@ -520,8 +560,10 @@ std::vector<int> FREAK::selectPairs(const std::vector<Mat>& images
     Mat descriptorsFloat = Mat::zeros(descriptors.rows, 903, CV_32F);
 
     std::bitset<1024>* ptr = (std::bitset<1024>*) (descriptors.data+(descriptors.rows-1)*descriptors.step[0]);
-    for( int m = descriptors.rows; m--; ) {
-        for( int n = 903; n--; ) {
+    for( int m = descriptors.rows; m--; )
+    {
+        for( int n = 903; n--; )
+        {
             if( ptr->test(n) == true )
                 descriptorsFloat.at<float>(m,n)=1.0f;
         }
@@ -529,7 +571,8 @@ std::vector<int> FREAK::selectPairs(const std::vector<Mat>& images
     }
 
     std::vector<PairStat> pairStat;
-    for( int n = 903; n--; ) {
+    for( int n = 903; n--; )
+    {
         // the higher the variance, the better --> mean = 0.5
         PairStat tmp = { fabs( mean(descriptorsFloat.col(n))[0]-0.5 ) ,n};
         pairStat.push_back(tmp);
@@ -538,19 +581,22 @@ std::vector<int> FREAK::selectPairs(const std::vector<Mat>& images
     std::sort( pairStat.begin(),pairStat.end(), sortMean() );
 
     std::vector<PairStat> bestPairs;
-    for( int m = 0; m < 903; ++m ) {
+    for( int m = 0; m < 903; ++m )
+    {
         if( verbose )
             std::cout << m << ":" << bestPairs.size() << " " << std::flush;
         double corrMax(0);
 
-        for( size_t n = 0; n < bestPairs.size(); ++n ) {
+        for( size_t n = 0; n < bestPairs.size(); ++n )
+        {
             int idxA = bestPairs[n].idx;
             int idxB = pairStat[m].idx;
             double corr(0);
             // compute correlation between 2 pairs
             corr = fabs(compareHist(descriptorsFloat.col(idxA), descriptorsFloat.col(idxB), HISTCMP_CORREL));
 
-            if( corr > corrMax ) {
+            if( corr > corrMax )
+            {
                 corrMax = corr;
                 if( corrMax >= corrTresh )
                     break;
@@ -560,7 +606,8 @@ std::vector<int> FREAK::selectPairs(const std::vector<Mat>& images
         if( corrMax < corrTresh/*0.7*/ )
             bestPairs.push_back(pairStat[m]);
 
-        if( bestPairs.size() >= 512 ) {
+        if( bestPairs.size() >= 512 )
+        {
             if( verbose )
                 std::cout << m << std::endl;
             break;
@@ -568,11 +615,13 @@ std::vector<int> FREAK::selectPairs(const std::vector<Mat>& images
     }
 
     std::vector<int> idxBestPairs;
-    if( (int)bestPairs.size() >= FREAK_NB_PAIRS ) {
+    if( (int)bestPairs.size() >= FREAK_NB_PAIRS )
+    {
         for( int i = 0; i < FREAK_NB_PAIRS; ++i )
             idxBestPairs.push_back(bestPairs[i].idx);
     }
-    else {
+    else
+    {
         if( verbose )
             std::cout << "correlation threshold too small (restrictive)" << std::endl;
         CV_Error(Error::StsError, "correlation threshold too small (restrictive)");
@@ -583,11 +632,13 @@ std::vector<int> FREAK::selectPairs(const std::vector<Mat>& images
 
 
 /*
+// create an image showing the brisk pattern
 void FREAKImpl::drawPattern()
-{ // create an image showing the brisk pattern
+{
     Mat pattern = Mat::zeros(1000, 1000, CV_8UC3) + Scalar(255,255,255);
     int sFac = 500 / patternScale;
-    for( int n = 0; n < kNB_POINTS; ++n ) {
+    for( int n = 0; n < kNB_POINTS; ++n )
+    {
         PatternPoint& pt = patternLookup[n];
         circle(pattern, Point( pt.x*sFac,pt.y*sFac)+Point(500,500), pt.sigma*sFac, Scalar(0,0,255),2);
         // rectangle(pattern, Point( (pt.x-pt.sigma)*sFac,(pt.y-pt.sigma)*sFac)+Point(500,500), Point( (pt.x+pt.sigma)*sFac,(pt.y+pt.sigma)*sFac)+Point(500,500), Scalar(0,0,255),2);
@@ -615,12 +666,19 @@ FREAK::~FREAK()
 {
 }
 
-int FREAK::descriptorSize() const {
+int FREAK::descriptorSize() const
+{
     return FREAK_NB_PAIRS / 8; // descriptor length in bytes
 }
 
-int FREAK::descriptorType() const {
+int FREAK::descriptorType() const
+{
     return CV_8U;
 }
 
+int FREAK::defaultNorm() const
+{
+    return NORM_HAMMING;
+}
+
 } // END NAMESPACE CV
index 263c273..be06c69 100644 (file)
@@ -575,6 +575,11 @@ int ORB::descriptorType() const
     return CV_8U;
 }
 
+int ORB::defaultNorm() const
+{
+    return NORM_HAMMING;
+}
+
 /** Compute the ORB features and descriptors on an image
  * @param img the image to compute the features and descriptors on
  * @param mask the mask to apply
index adfe428..2fe59ca 100644 (file)
@@ -616,8 +616,8 @@ TEST(Features2d_RotationInvariance_Detector_ORB, regression)
 TEST(Features2d_RotationInvariance_Descriptor_BRISK, regression)
 {
     DescriptorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"),
-                      Algorithm::create<DescriptorExtractor>("Feature2D.BRISK"),
-                        NORM_HAMMING,
+                                          Algorithm::create<DescriptorExtractor>("Feature2D.BRISK"),
+                                          Algorithm::create<DescriptorExtractor>("Feature2D.BRISK")->defaultNorm(),
                                           0.99f);
     test.safe_run();
 }
@@ -626,7 +626,7 @@ TEST(Features2d_RotationInvariance_Descriptor_ORB, regression)
 {
     DescriptorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"),
                                           Algorithm::create<DescriptorExtractor>("Feature2D.ORB"),
-                                          NORM_HAMMING,
+                                          Algorithm::create<DescriptorExtractor>("Feature2D.ORB")->defaultNorm(),
                                           0.99f);
     test.safe_run();
 }
@@ -635,7 +635,7 @@ TEST(Features2d_RotationInvariance_Descriptor_ORB, regression)
 //{
 //    DescriptorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"),
 //                                          Algorithm::create<DescriptorExtractor>("Feature2D.FREAK"),
-//                                          NORM_HAMMING,
+//                                          Algorithm::create<DescriptorExtractor>("Feature2D.FREAK")->defaultNorm(),
 //                                          0.f);
 //    test.safe_run();
 //}
@@ -667,26 +667,26 @@ TEST(Features2d_ScaleInvariance_Detector_BRISK, regression)
 //TEST(Features2d_ScaleInvariance_Descriptor_BRISK, regression)
 //{
 //    DescriptorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"),
-//                   Algorithm::create<DescriptorExtractor>("Feature2D.BRISK"),
-//                   NORM_HAMMING,
-//                                     0.99f);
+//                                       Algorithm::create<DescriptorExtractor>("Feature2D.BRISK"),
+//                                       Algorithm::create<DescriptorExtractor>("Feature2D.BRISK")->defaultNorm(),
+//                                       0.99f);
 //    test.safe_run();
 //}
 
 //TEST(Features2d_ScaleInvariance_Descriptor_ORB, regression)
 //{
 //    DescriptorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"),
-//                                                                      Algorithm::create<DescriptorExtractor>("Feature2D.ORB"),
-//                                                                      NORM_HAMMING,
-//                                     0.01f);
+//                                       Algorithm::create<DescriptorExtractor>("Feature2D.ORB"),
+//                                       Algorithm::create<DescriptorExtractor>("Feature2D.ORB")->defaultNorm(),
+//                                       0.01f);
 //    test.safe_run();
 //}
 
 //TEST(Features2d_ScaleInvariance_Descriptor_FREAK, regression)
 //{
 //    DescriptorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"),
-//                                     Algorithm::create<DescriptorExtractor>("Feature2D.FREAK"),
-//                                     NORM_HAMMING,
-//                                     0.01f);
+//                                       Algorithm::create<DescriptorExtractor>("Feature2D.FREAK"),
+//                                       Algorithm::create<DescriptorExtractor>("Feature2D.FREAK")->defaultNorm(),
+//                                       0.01f);
 //    test.safe_run();
 //}
diff --git a/modules/imgproc/src/opencl/boxFilter.cl b/modules/imgproc/src/opencl/boxFilter.cl
new file mode 100644 (file)
index 0000000..b65934a
--- /dev/null
@@ -0,0 +1,378 @@
+/*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-2013, Advanced Micro Devices, 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 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*/
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////Macro for border type////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef BORDER_REPLICATE
+//BORDER_REPLICATE:     aaaaaa|abcdefgh|hhhhhhh
+#define ADDR_L(i, l_edge, r_edge)  ((i) <  (l_edge) ? (l_edge)   : (i))
+#define ADDR_R(i, r_edge, addr)    ((i) >= (r_edge) ? (r_edge)-1 : (addr))
+#define ADDR_H(i, t_edge, b_edge)  ((i) <  (t_edge) ? (t_edge)   :(i))
+#define ADDR_B(i, b_edge, addr)    ((i) >= (b_edge) ? (b_edge)-1 :(addr))
+#endif
+
+#ifdef BORDER_REFLECT
+//BORDER_REFLECT:       fedcba|abcdefgh|hgfedcb
+#define ADDR_L(i, l_edge, r_edge)  ((i) <  (l_edge) ? -(i)-1               : (i))
+#define ADDR_R(i, r_edge, addr)    ((i) >= (r_edge) ? -(i)-1+((r_edge)<<1) : (addr))
+#define ADDR_H(i, t_edge, b_edge)  ((i) <  (t_edge) ? -(i)-1 : (i))
+#define ADDR_B(i, b_edge, addr)    ((i) >= (b_edge) ? -(i)-1+((b_edge)<<1) : (addr))
+#endif
+
+#ifdef BORDER_REFLECT_101
+//BORDER_REFLECT_101:   gfedcb|abcdefgh|gfedcba
+#define ADDR_L(i, l_edge, r_edge)  ((i) <  (l_edge) ? -(i)                 : (i))
+#define ADDR_R(i, r_edge, addr)    ((i) >= (r_edge) ? -(i)-2+((r_edge)<<1) : (addr))
+#define ADDR_H(i, t_edge, b_edge)  ((i) <  (t_edge) ? -(i)                 : (i))
+#define ADDR_B(i, b_edge, addr)    ((i) >= (b_edge) ? -(i)-2+((b_edge)<<1) : (addr))
+#endif
+
+//blur function does not support BORDER_WRAP
+#ifdef BORDER_WRAP
+//BORDER_WRAP:          cdefgh|abcdefgh|abcdefg
+#define ADDR_L(i, l_edge, r_edge)  ((i) <  (l_edge) ? (i)+(r_edge) : (i))
+#define ADDR_R(i, r_edge, addr)    ((i) >= (r_edge) ? (i)-(r_edge) : (addr))
+#define ADDR_H(i, t_edge, b_edge)  ((i) <  (t_edge) ? (i)+(b_edge) : (i))
+#define ADDR_B(i, b_edge, addr)    ((i) >= (b_edge) ? (i)-(b_edge) : (addr))
+#endif
+
+#ifdef EXTRA_EXTRAPOLATION // border > src image size
+#ifdef BORDER_CONSTANT
+// None
+#elif defined BORDER_REPLICATE
+#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \
+    { \
+        x = max(min(x, maxX - 1), minX); \
+        y = max(min(y, maxY - 1), minY); \
+    }
+#elif defined BORDER_WRAP
+#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \
+    { \
+        if (x < minX) \
+            x -= ((x - maxX + 1) / maxX) * maxX; \
+        if (x >= maxX) \
+            x %= maxX; \
+        if (y < minY) \
+            y -= ((y - maxY + 1) / maxY) * maxY; \
+        if (y >= maxY) \
+            y %= maxY; \
+    }
+#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101)
+#define EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, delta) \
+    { \
+        if (maxX - minX == 1) \
+            x = minX; \
+        else \
+            do \
+            { \
+                if (x < minX) \
+                    x = minX - (x - minX) - 1 + delta; \
+                else \
+                    x = maxX - 1 - (x - maxX) - delta; \
+            } \
+            while (x >= maxX || x < minX); \
+        \
+        if (maxY - minY == 1) \
+            y = minY; \
+        else \
+            do \
+            { \
+                if (y < minY) \
+                    y = minY - (y - minY) - 1 + delta; \
+                else \
+                    y = maxY - 1 - (y - maxY) - delta; \
+            } \
+            while (y >= maxY || y < minY); \
+    }
+#ifdef BORDER_REFLECT
+#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 0)
+#elif defined(BORDER_REFLECT_101)
+#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 1)
+#endif
+#else
+#error No extrapolation method
+#endif
+#else
+#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \
+    { \
+        int _row = y - minY, _col = x - minX; \
+        _row = ADDR_H(_row, 0, maxY - minY); \
+        _row = ADDR_B(_row, maxY - minY, _row); \
+        y = _row + minY; \
+        \
+        _col = ADDR_L(_col, 0, maxX - minX); \
+        _col = ADDR_R(_col, maxX - minX, _col); \
+        x = _col + minX; \
+    }
+#endif
+
+#if USE_DOUBLE
+#ifdef cl_amd_fp64
+#pragma OPENCL EXTENSION cl_amd_fp64:enable
+#elif defined (cl_khr_fp64)
+#pragma OPENCL EXTENSION cl_khr_fp64:enable
+#endif
+#define FPTYPE double
+#define CONVERT_TO_FPTYPE CAT(convert_double, VEC_SIZE)
+#else
+#define FPTYPE float
+#define CONVERT_TO_FPTYPE CAT(convert_float, VEC_SIZE)
+#endif
+
+#if DATA_DEPTH == 0
+#define BASE_TYPE uchar
+#elif DATA_DEPTH == 1
+#define BASE_TYPE char
+#elif DATA_DEPTH == 2
+#define BASE_TYPE ushort
+#elif DATA_DEPTH == 3
+#define BASE_TYPE short
+#elif DATA_DEPTH == 4
+#define BASE_TYPE int
+#elif DATA_DEPTH == 5
+#define BASE_TYPE float
+#elif DATA_DEPTH == 6
+#define BASE_TYPE double
+#else
+#error data_depth
+#endif
+
+#define __CAT(x, y) x##y
+#define CAT(x, y) __CAT(x, y)
+
+#define uchar1 uchar
+#define char1 char
+#define ushort1 ushort
+#define short1 short
+#define int1 int
+#define float1 float
+#define double1 double
+
+#define convert_uchar1_sat_rte convert_uchar_sat_rte
+#define convert_char1_sat_rte convert_char_sat_rte
+#define convert_ushort1_sat_rte convert_ushort_sat_rte
+#define convert_short1_sat_rte convert_short_sat_rte
+#define convert_int1_sat_rte convert_int_sat_rte
+#define convert_float1
+#define convert_double1
+
+#if DATA_DEPTH == 5 || DATA_DEPTH == 6
+#define CONVERT_TO_TYPE CAT(CAT(convert_, BASE_TYPE), VEC_SIZE)
+#else
+#define CONVERT_TO_TYPE CAT(CAT(CAT(convert_, BASE_TYPE), VEC_SIZE), _sat_rte)
+#endif
+
+#define VEC_SIZE DATA_CHAN
+
+#define VEC_TYPE CAT(BASE_TYPE, VEC_SIZE)
+#define TYPE VEC_TYPE
+
+#define SCALAR_TYPE CAT(FPTYPE, VEC_SIZE)
+
+#define INTERMEDIATE_TYPE CAT(FPTYPE, VEC_SIZE)
+
+#define TYPE_SIZE   (VEC_SIZE*sizeof(BASE_TYPE))
+
+struct RectCoords
+{
+    int x1, y1, x2, y2;
+};
+
+//#define DEBUG
+#ifdef DEBUG
+#define DEBUG_ONLY(x) x
+#define ASSERT(condition) do { if (!(condition)) { printf("BUG in boxFilter kernel (global=%d,%d): " #condition "\n", get_global_id(0), get_global_id(1)); } } while (0)
+#else
+#define DEBUG_ONLY(x)
+#define ASSERT(condition)
+#endif
+
+
+inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global const uchar* srcptr, int srcstep, const struct RectCoords srcCoords
+#ifdef BORDER_CONSTANT
+               , SCALAR_TYPE borderValue
+#endif
+    )
+{
+#ifdef BORDER_ISOLATED
+    if(pos.x >= srcCoords.x1 && pos.y >= srcCoords.y1 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2)
+#else
+    if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2)
+#endif
+    {
+        __global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + pos.x * sizeof(TYPE));
+        return CONVERT_TO_FPTYPE(*ptr);
+    }
+    else
+    {
+#ifdef BORDER_CONSTANT
+        return borderValue;
+#else
+        int selected_col = pos.x;
+        int selected_row = pos.y;
+
+        EXTRAPOLATE(selected_col, selected_row,
+#ifdef BORDER_ISOLATED
+                srcCoords.x1, srcCoords.y1,
+#else
+                0, 0,
+#endif
+                srcCoords.x2, srcCoords.y2
+         );
+
+        // debug border mapping
+        //printf("pos=%d,%d --> %d, %d\n", pos.x, pos.y, selected_col, selected_row);
+
+        pos = (int2)(selected_col, selected_row);
+        if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2)
+        {
+            __global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + pos.x * sizeof(TYPE));
+            return CONVERT_TO_FPTYPE(*ptr);
+        }
+        else
+        {
+            // for debug only
+            DEBUG_ONLY(printf("BUG in boxFilter kernel\n"));
+            return (FPTYPE)(0.0f);
+        }
+#endif
+    }
+}
+
+// INPUT PARAMETER: BLOCK_SIZE_Y (via defines)
+
+__kernel
+__attribute__((reqd_work_group_size(LOCAL_SIZE, 1, 1)))
+void boxFilter(__global const uchar* srcptr, int srcstep, int srcOffsetX, int srcOffsetY, int srcEndX, int srcEndY,
+                __global uchar* dstptr, int dststep, int dstoffset,
+               int rows, int cols,
+#ifdef BORDER_CONSTANT
+               SCALAR_TYPE borderValue,
+#endif
+               FPTYPE alpha
+               )
+{
+    const struct RectCoords srcCoords = {srcOffsetX, srcOffsetY, srcEndX, srcEndY}; // for non-isolated border: offsetX, offsetY, wholeX, wholeY
+
+    const int x = get_local_id(0) + (LOCAL_SIZE - (KERNEL_SIZE_X - 1)) * get_group_id(0) - ANCHOR_X;
+    const int y = get_global_id(1) * BLOCK_SIZE_Y;
+
+    const int local_id = get_local_id(0);
+
+    INTERMEDIATE_TYPE data[KERNEL_SIZE_Y];
+    __local INTERMEDIATE_TYPE sumOfCols[LOCAL_SIZE];
+
+    int2 srcPos = (int2)(srcCoords.x1 + x, srcCoords.y1 + y - ANCHOR_Y);
+    for(int sy = 0; sy < KERNEL_SIZE_Y; sy++, srcPos.y++)
+    {
+        data[sy] = readSrcPixel(srcPos, srcptr, srcstep, srcCoords
+#ifdef BORDER_CONSTANT
+                , borderValue
+#endif
+                );
+    }
+
+    INTERMEDIATE_TYPE tmp_sum = 0;
+    for(int sy = 0; sy < KERNEL_SIZE_Y; sy++)
+    {
+        tmp_sum += (data[sy]);
+    }
+
+    sumOfCols[local_id] = tmp_sum;
+    barrier(CLK_LOCAL_MEM_FENCE);
+
+    int2 pos = (int2)(x, y);
+    __global TYPE* dstPtr = (__global TYPE*)(dstptr + pos.y * dststep + dstoffset + pos.x * TYPE_SIZE/*sizeof(TYPE)*/); // Pointer can be out of bounds!
+
+    int sy_index = 0; // current index in data[] array
+    int stepsY = min(rows - pos.y, BLOCK_SIZE_Y);
+    ASSERT(stepsY > 0);
+    for (; ;)
+    {
+        ASSERT(pos.y < rows);
+
+        if(local_id >= ANCHOR_X && local_id < LOCAL_SIZE - (KERNEL_SIZE_X - 1 - ANCHOR_X) &&
+            pos.x >= 0 && pos.x < cols)
+        {
+            ASSERT(pos.y >= 0 && pos.y < rows);
+
+            INTERMEDIATE_TYPE total_sum = 0;
+#pragma unroll
+            for (int sx = 0; sx < KERNEL_SIZE_X; sx++)
+            {
+                total_sum += sumOfCols[local_id + sx - ANCHOR_X];
+            }
+            *dstPtr = CONVERT_TO_TYPE(((INTERMEDIATE_TYPE)alpha) * total_sum);
+        }
+
+#if BLOCK_SIZE_Y == 1
+        break;
+#else
+        if (--stepsY == 0)
+            break;
+
+        barrier(CLK_LOCAL_MEM_FENCE);
+
+        tmp_sum = sumOfCols[local_id]; // TODO FIX IT: workaround for BUG in OpenCL compiler
+        // only works with scalars: ASSERT(fabs(tmp_sum - sumOfCols[local_id]) < (INTERMEDIATE_TYPE)1e-6);
+        tmp_sum -= data[sy_index];
+
+        data[sy_index] = readSrcPixel(srcPos, srcptr, srcstep, srcCoords
+#ifdef BORDER_CONSTANT
+                , borderValue
+#endif
+                );
+        srcPos.y++;
+
+        tmp_sum += data[sy_index];
+        sumOfCols[local_id] = tmp_sum;
+
+        sy_index = (sy_index + 1 < KERNEL_SIZE_Y) ? sy_index + 1 : 0;
+
+        barrier(CLK_LOCAL_MEM_FENCE);
+
+        // next line
+        DEBUG_ONLY(pos.y++);
+        dstPtr = (__global TYPE*)((__global char*)dstPtr + dststep); // Pointer can be out of bounds!
+#endif // BLOCK_SIZE_Y == 1
+    }
+}
diff --git a/modules/imgproc/src/opencl/medianFilter.cl b/modules/imgproc/src/opencl/medianFilter.cl
new file mode 100644 (file)
index 0000000..6aed88e
--- /dev/null
@@ -0,0 +1,167 @@
+//                           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.
+// 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.
+
+#define DATA_TYPE type
+
+#define scnbytes ((int)sizeof(type))
+
+#define op(a,b) {    mid=a; a=min(a,b); b=max(mid,b);}
+
+__kernel void medianFilter3(__global const uchar* srcptr, int srcStep, int srcOffset,
+                            __global uchar* dstptr, int dstStep, int dstOffset,
+                            int rows, int cols)
+{
+    __local DATA_TYPE data[18][18];
+
+    int x = get_local_id(0);
+    int y = get_local_id(1);
+
+    int gx= get_global_id(0);
+    int gy= get_global_id(1);
+
+    int dx = gx - x - 1;
+    int dy = gy - y - 1;
+
+    const int id = min((int)(x*16+y), 9*18-1);
+
+    int dr = id / 18;
+    int dc = id % 18;
+
+    int c = clamp(dx+dc, 0, cols-1);
+
+    int r = clamp(dy+dr, 0, rows-1);
+    int index1 = mad24(r, srcStep, srcOffset + c*scnbytes);
+
+    r = clamp(dy+dr+9, 0, rows-1);
+    int index9 = mad24(r, srcStep, srcOffset + c*scnbytes);
+
+    __global DATA_TYPE * src = (__global DATA_TYPE *)(srcptr + index1);
+    data[dr][dc] = src[0];
+
+    src = (__global DATA_TYPE *)(srcptr + index9);
+    data[dr+9][dc] = src[0];
+
+    barrier(CLK_LOCAL_MEM_FENCE);
+
+    DATA_TYPE p0=data[y][x], p1=data[y][(x+1)], p2=data[y][(x+2)];
+    DATA_TYPE p3=data[y+1][x], p4=data[y+1][(x+1)], p5=data[y+1][(x+2)];
+    DATA_TYPE p6=data[y+2][x], p7=data[y+2][(x+1)], p8=data[y+2][(x+2)];
+    DATA_TYPE mid;
+
+    op(p1, p2); op(p4, p5); op(p7, p8); op(p0, p1);
+    op(p3, p4); op(p6, p7); op(p1, p2); op(p4, p5);
+    op(p7, p8); op(p0, p3); op(p5, p8); op(p4, p7);
+    op(p3, p6); op(p1, p4); op(p2, p5); op(p4, p7);
+    op(p4, p2); op(p6, p4); op(p4, p2);
+
+    int dst_index = mad24( gy, dstStep, dstOffset + gx * scnbytes);
+
+    if( gy < rows && gx < cols)
+    {
+        __global DATA_TYPE* dst = (__global DATA_TYPE *)(dstptr + dst_index);
+        dst[0] = p4;
+    }
+}
+
+__kernel void medianFilter5(__global const uchar* srcptr, int srcStep, int srcOffset,
+                            __global uchar* dstptr, int dstStep, int dstOffset,
+                            int rows, int cols)
+{
+    __local DATA_TYPE data[20][20];
+
+    int x =get_local_id(0);
+    int y =get_local_id(1);
+
+    int gx=get_global_id(0);
+    int gy=get_global_id(1);
+
+    int dx = gx - x - 2;
+    int dy = gy - y - 2;
+
+    const int id = min((int)(x*16+y), 10*20-1);
+
+    int dr=id/20;
+    int dc=id%20;
+
+    int c=clamp(dx+dc, 0, cols-1);
+
+    int r = clamp(dy+dr, 0, rows-1);
+    int index1 = mad24(r, srcStep, srcOffset + c*scnbytes);
+
+    r = clamp(dy+dr+10, 0, rows-1);
+    int index10 = mad24(r, srcStep, srcOffset + c*scnbytes);
+
+    __global DATA_TYPE * src = (__global DATA_TYPE *)(srcptr + index1);
+    data[dr][dc] = src[0];
+    src = (__global DATA_TYPE *)(srcptr + index10);
+    data[dr+10][dc] = src[0];
+
+    barrier(CLK_LOCAL_MEM_FENCE);
+
+    DATA_TYPE p0=data[y][x], p1=data[y][x+1], p2=data[y][x+2], p3=data[y][x+3], p4=data[y][x+4];
+    DATA_TYPE p5=data[y+1][x], p6=data[y+1][x+1], p7=data[y+1][x+2], p8=data[y+1][x+3], p9=data[y+1][x+4];
+    DATA_TYPE p10=data[y+2][x], p11=data[y+2][x+1], p12=data[y+2][x+2], p13=data[y+2][x+3], p14=data[y+2][x+4];
+    DATA_TYPE p15=data[y+3][x], p16=data[y+3][x+1], p17=data[y+3][x+2], p18=data[y+3][x+3], p19=data[y+3][x+4];
+    DATA_TYPE p20=data[y+4][x], p21=data[y+4][x+1], p22=data[y+4][x+2], p23=data[y+4][x+3], p24=data[y+4][x+4];
+    DATA_TYPE mid;
+
+    op(p1, p2); op(p0, p1); op(p1, p2); op(p4, p5); op(p3, p4);
+    op(p4, p5); op(p0, p3); op(p2, p5); op(p2, p3); op(p1, p4);
+    op(p1, p2); op(p3, p4); op(p7, p8); op(p6, p7); op(p7, p8);
+    op(p10, p11); op(p9, p10); op(p10, p11); op(p6, p9); op(p8, p11);
+    op(p8, p9); op(p7, p10); op(p7, p8); op(p9, p10); op(p0, p6);
+    op(p4, p10); op(p4, p6); op(p2, p8); op(p2, p4); op(p6, p8);
+    op(p1, p7); op(p5, p11); op(p5, p7); op(p3, p9); op(p3, p5);
+    op(p7, p9); op(p1, p2); op(p3, p4); op(p5, p6); op(p7, p8);
+    op(p9, p10); op(p13, p14); op(p12, p13); op(p13, p14); op(p16, p17);
+    op(p15, p16); op(p16, p17); op(p12, p15); op(p14, p17); op(p14, p15);
+    op(p13, p16); op(p13, p14); op(p15, p16); op(p19, p20); op(p18, p19);
+    op(p19, p20); op(p21, p22); op(p23, p24); op(p21, p23); op(p22, p24);
+    op(p22, p23); op(p18, p21); op(p20, p23); op(p20, p21); op(p19, p22);
+    op(p22, p24); op(p19, p20); op(p21, p22); op(p23, p24); op(p12, p18);
+    op(p16, p22); op(p16, p18); op(p14, p20); op(p20, p24); op(p14, p16);
+    op(p18, p20); op(p22, p24); op(p13, p19); op(p17, p23); op(p17, p19);
+    op(p15, p21); op(p15, p17); op(p19, p21); op(p13, p14); op(p15, p16);
+    op(p17, p18); op(p19, p20); op(p21, p22); op(p23, p24); op(p0, p12);
+    op(p8, p20); op(p8, p12); op(p4, p16); op(p16, p24); op(p12, p16);
+    op(p2, p14); op(p10, p22); op(p10, p14); op(p6, p18); op(p6, p10);
+    op(p10, p12); op(p1, p13); op(p9, p21); op(p9, p13); op(p5, p17);
+    op(p13, p17); op(p3, p15); op(p11, p23); op(p11, p15); op(p7, p19);
+    op(p7, p11); op(p11, p13); op(p11, p12);
+
+    int dst_index = mad24( gy, dstStep, dstOffset + gx * scnbytes);
+
+    if( gy < rows && gx < cols)
+    {
+        __global DATA_TYPE* dst = (__global DATA_TYPE *)(dstptr + dst_index);
+        dst[0] = p12;
+    }
+}
\ No newline at end of file
index 9d280c9..727aa08 100644 (file)
@@ -611,9 +611,158 @@ template<> struct ColumnSum<int, ushort> : public BaseColumnFilter
     std::vector<int> sum;
 };
 
+#define DIVUP(total, grain) ((total + grain - 1) / (grain))
+
+static bool ocl_boxFilter( InputArray _src, OutputArray _dst, int ddepth,
+                           Size ksize, Point anchor, int borderType )
+{
+    int type = _src.type();
+    int cn = CV_MAT_CN(type);
+    if ((1 != cn) && (2 != cn) && (4 != cn))
+        return false;//TODO
+
+    int sdepth = CV_MAT_DEPTH(type);
+    if( ddepth < 0 )
+        ddepth = sdepth;
+    else if (ddepth != sdepth)
+        return false;
+    if( anchor.x < 0 )
+        anchor.x = ksize.width / 2;
+    if( anchor.y < 0 )
+        anchor.y = ksize.height / 2;
+
+    ocl::Kernel kernel;
+
+    //Normalize the result by default
+    float alpha = 1.0f / (ksize.height * ksize.width);
+    bool isIsolatedBorder = (borderType & BORDER_ISOLATED) != 0;
+    bool useDouble = (CV_64F == sdepth);
+    const cv::ocl::Device &device = cv::ocl::Device::getDefault();
+    int doubleFPConfig = device.doubleFPConfig();
+    if (useDouble && (0 == doubleFPConfig))
+        return false;// may be we have to check is  (0 != (CL_FP_SOFT_FLOAT & doubleFPConfig)) ?
+
+    const char* btype = NULL;
+    switch (borderType & ~BORDER_ISOLATED)
+    {
+    case BORDER_CONSTANT:
+        btype = "BORDER_CONSTANT";
+        break;
+    case BORDER_REPLICATE:
+        btype = "BORDER_REPLICATE";
+        break;
+    case BORDER_REFLECT:
+        btype = "BORDER_REFLECT";
+        break;
+    case BORDER_WRAP:
+        //CV_Error(CV_StsUnsupportedFormat, "BORDER_WRAP is not supported!");
+        return false;
+    case BORDER_REFLECT101:
+        btype = "BORDER_REFLECT_101";
+        break;
+    }
+
+    cv::Size sz = _src.size();
+
+    size_t globalsize[2] = {sz.width, sz.height};
+    size_t localsize[2] = {0, 1};
+
+    UMat src; Size wholeSize;
+    if (!isIsolatedBorder)
+    {
+        src = _src.getUMat();
+        Point ofs;
+        src.locateROI(wholeSize, ofs);
+    }
+
+    size_t maxWorkItemSizes[32]; device.maxWorkItemSizes(maxWorkItemSizes);
+    size_t tryWorkItems = maxWorkItemSizes[0];
+    for (;;)
+    {
+        size_t BLOCK_SIZE = tryWorkItems;
+        while (BLOCK_SIZE > 32 && BLOCK_SIZE >= (size_t)ksize.width * 2 && BLOCK_SIZE > (size_t)sz.width * 2)
+            BLOCK_SIZE /= 2;
+        size_t BLOCK_SIZE_Y = 8; // TODO Check heuristic value on devices
+        while (BLOCK_SIZE_Y < BLOCK_SIZE / 8 && BLOCK_SIZE_Y * device.maxComputeUnits() * 32 < (size_t)sz.height)
+            BLOCK_SIZE_Y *= 2;
+
+        if ((size_t)ksize.width > BLOCK_SIZE)
+            return false;
+
+        int requiredTop = anchor.y;
+        int requiredLeft = (int)BLOCK_SIZE; // not this: anchor.x;
+        int requiredBottom = ksize.height - 1 - anchor.y;
+        int requiredRight = (int)BLOCK_SIZE; // not this: ksize.width - 1 - anchor.x;
+        int h = isIsolatedBorder ? sz.height : wholeSize.height;
+        int w = isIsolatedBorder ? sz.width : wholeSize.width;
+
+        bool extra_extrapolation = h < requiredTop || h < requiredBottom || w < requiredLeft || w < requiredRight;
+
+        if ((w < ksize.width) || (h < ksize.height))
+            return false;
+
+        char build_options[1024];
+        sprintf(build_options, "-D LOCAL_SIZE=%d -D BLOCK_SIZE_Y=%d -D DATA_DEPTH=%d -D DATA_CHAN=%d -D USE_DOUBLE=%d -D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d -D %s -D %s -D %s",
+                (int)BLOCK_SIZE, (int)BLOCK_SIZE_Y,
+                sdepth, cn, useDouble ? 1 : 0,
+                anchor.x, anchor.y, ksize.width, ksize.height,
+                btype,
+                extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION",
+                isIsolatedBorder ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED");
+
+        localsize[0] = BLOCK_SIZE;
+        globalsize[0] = DIVUP(sz.width, BLOCK_SIZE - (ksize.width - 1)) * BLOCK_SIZE;
+        globalsize[1] = DIVUP(sz.height, BLOCK_SIZE_Y);
+
+        cv::String errmsg;
+        kernel.create("boxFilter", cv::ocl::imgproc::boxFilter_oclsrc, build_options);
+
+        size_t kernelWorkGroupSize = kernel.workGroupSize();
+        if (localsize[0] <= kernelWorkGroupSize)
+            break;
+
+        if (BLOCK_SIZE < kernelWorkGroupSize)
+            return false;
+        tryWorkItems = kernelWorkGroupSize;
+    }
+
+    _dst.create(sz, CV_MAKETYPE(ddepth, cn));
+    UMat dst = _dst.getUMat();
+    if (src.empty())
+        src = _src.getUMat();
+    int idxArg = 0;
+    idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(src));
+    idxArg = kernel.set(idxArg, (int)src.step);
+    int srcOffsetX = (int)((src.offset % src.step) / src.elemSize());
+    int srcOffsetY = (int)(src.offset / src.step);
+    int srcEndX = (isIsolatedBorder ? (srcOffsetX + sz.width) : wholeSize.width);
+    int srcEndY = (isIsolatedBorder ? (srcOffsetY + sz.height) : wholeSize.height);
+    idxArg = kernel.set(idxArg, srcOffsetX);
+    idxArg = kernel.set(idxArg, srcOffsetY);
+    idxArg = kernel.set(idxArg, srcEndX);
+    idxArg = kernel.set(idxArg, srcEndY);
+    idxArg = kernel.set(idxArg, ocl::KernelArg::WriteOnly(dst));
+    float borderValue[4] = {0, 0, 0, 0};
+    double borderValueDouble[4] = {0, 0, 0, 0};
+    if ((borderType & ~BORDER_ISOLATED) == BORDER_CONSTANT)
+    {
+        int cnocl = (3 == cn) ? 4 : cn;
+        if (useDouble)
+            idxArg = kernel.set(idxArg, (void *)&borderValueDouble[0], sizeof(double) * cnocl);
+        else
+            idxArg = kernel.set(idxArg, (void *)&borderValue[0], sizeof(float) * cnocl);
+    }
+    if (useDouble)
+        idxArg = kernel.set(idxArg, (double)alpha);
+    else
+        idxArg = kernel.set(idxArg, (float)alpha);
+
+    return kernel.run(2, globalsize, localsize, true);
+}
 
 }
 
+
 cv::Ptr<cv::BaseRowFilter> cv::getRowSumFilter(int srcType, int sumType, int ksize, int anchor)
 {
     int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(sumType);
@@ -713,6 +862,10 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth,
                 Size ksize, Point anchor,
                 bool normalize, int borderType )
 {
+    bool use_opencl = ocl::useOpenCL() && _dst.isUMat() && normalize;
+    if( use_opencl && ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType) )
+        return;
+
     Mat src = _src.getMat();
     int sdepth = src.depth(), cn = src.channels();
     if( ddepth < 0 )
@@ -1661,19 +1814,59 @@ medianBlur_SortNet( const Mat& _src, Mat& _dst, int m )
 
 }
 
+namespace cv
+{
+    static bool ocl_medianFilter ( InputArray _src, OutputArray _dst, int m)
+    {
+        int type = _src.type();
+        int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
+
+        if (!((depth == CV_8U || depth == CV_16U || depth == CV_16S || depth == CV_32F) && (cn != 3 && cn <= 4)))
+            return false;
+
+        const char * kernelName;
+
+        if (m==3)
+            kernelName = "medianFilter3";
+        else if (m==5)
+            kernelName = "medianFilter5";
+        else
+            return false;
+
+        ocl::Kernel k(kernelName,ocl::imgproc::medianFilter_oclsrc,format("-D type=%s",ocl::typeToStr(type)));
+        if (k.empty())
+            return false;
+
+        _dst.create(_src.size(),type);
+        UMat src = _src.getUMat(), dst = _dst.getUMat();
+
+        size_t globalsize[2] = {(src.cols + 18) / 16 * 16, (src.rows + 15) / 16 * 16};
+        size_t localsize[2] = {16, 16};
+
+        return k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst)).run(2,globalsize,localsize,false);
+    }
+}
+
 void cv::medianBlur( InputArray _src0, OutputArray _dst, int ksize )
 {
-    Mat src0 = _src0.getMat();
-    _dst.create( src0.size(), src0.type() );
-    Mat dst = _dst.getMat();
+    CV_Assert( (ksize % 2 == 1) && (_src0.dims() <= 2 ));
 
     if( ksize <= 1 )
     {
+        Mat src0 = _src0.getMat();
+        _dst.create( src0.size(), src0.type() );
+        Mat dst = _dst.getMat();
         src0.copyTo(dst);
         return;
     }
 
-    CV_Assert( ksize % 2 == 1 );
+    bool use_opencl = ocl::useOpenCL() && _dst.isUMat();
+    if ( use_opencl && ocl_medianFilter(_src0,_dst, ksize))
+        return;
+
+    Mat src0 = _src0.getMat();
+    _dst.create( src0.size(), src0.type() );
+    Mat dst = _dst.getMat();
 
 #ifdef HAVE_TEGRA_OPTIMIZATION
     if (tegra::medianBlur(src0, dst, ksize))
diff --git a/modules/imgproc/test/ocl/test_boxfilter.cpp b/modules/imgproc/test/ocl/test_boxfilter.cpp
new file mode 100644 (file)
index 0000000..178aef4
--- /dev/null
@@ -0,0 +1,137 @@
+/*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 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*/
+
+#include "test_precomp.hpp"
+#include "opencv2/ts/ocl_test.hpp"
+
+#ifdef HAVE_OPENCL
+
+namespace cvtest {
+namespace ocl {
+
+enum
+{
+    noType = -1
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+// boxFilter
+PARAM_TEST_CASE(BoxFilter, MatDepth, Channels, BorderType, bool)
+{
+    static const int kernelMinSize = 2;
+    static const int kernelMaxSize = 10;
+
+    int type;
+    Size ksize;
+    Size dsize;
+    Point anchor;
+    int borderType;
+    bool useRoi;
+
+    TEST_DECLARE_INPUT_PARAMETER(src)
+    TEST_DECLARE_OUTPUT_PARAMETER(dst)
+
+    virtual void SetUp()
+    {
+        type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
+        borderType = GET_PARAM(2); // only not isolated border tested, because CPU module doesn't support isolated border case.
+        useRoi = GET_PARAM(3);
+    }
+
+    void random_roi()
+    {
+        dsize = randomSize(1, MAX_VALUE);
+
+        ksize = randomSize(kernelMinSize, kernelMaxSize);
+
+        Size roiSize = randomSize(ksize.width, MAX_VALUE, ksize.height, MAX_VALUE);
+        Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
+        randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
+
+        Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
+        randomSubMat(dst, dst_roi, dsize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
+
+        anchor.x = randomInt(-1, ksize.width);
+        anchor.y = randomInt(-1, ksize.height);
+
+        UMAT_UPLOAD_INPUT_PARAMETER(src)
+        UMAT_UPLOAD_OUTPUT_PARAMETER(dst)
+    }
+
+    void Near(double threshold = 0.0)
+    {
+        EXPECT_MAT_NEAR(dst, udst, threshold);
+        EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
+    }
+};
+
+OCL_TEST_P(BoxFilter, Mat)
+{
+    for (int j = 0; j < test_loop_times; j++)
+    {
+        random_roi();
+
+        OCL_OFF(cv::boxFilter(src_roi, dst_roi, -1, ksize, anchor, true, borderType));
+        OCL_ON(cv::boxFilter(usrc_roi, udst_roi, -1, ksize, anchor, true, borderType));
+
+        Near(1.0);
+    }
+}
+
+
+OCL_INSTANTIATE_TEST_CASE_P(ImageProc, BoxFilter,
+                            Combine(
+                                Values(CV_8U, CV_16U, CV_16S, CV_32S, CV_32F),
+                                Values(1, 2, 4),
+                                Values((BorderType)BORDER_CONSTANT,
+                                       (BorderType)BORDER_REPLICATE,
+                                       (BorderType)BORDER_REFLECT,
+                                       (BorderType)BORDER_REFLECT_101),
+                                Bool()  // ROI
+                                )
+                           );
+
+
+} } // namespace cvtest::ocl
+
+#endif // HAVE_OPENCL
diff --git a/modules/imgproc/test/ocl/test_medianfilter.cpp b/modules/imgproc/test/ocl/test_medianfilter.cpp
new file mode 100644 (file)
index 0000000..0116197
--- /dev/null
@@ -0,0 +1,111 @@
+/*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, Multicoreware, Inc., all rights reserved.
+// Copyright (C) 2010-2012, Advanced Micro Devices, 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 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*/
+
+#include "test_precomp.hpp"
+#include "opencv2/ts/ocl_test.hpp"
+
+#ifdef HAVE_OPENCL
+
+namespace cvtest {
+namespace ocl {
+
+/////////////////////////////////////////////medianFilter//////////////////////////////////////////////////////////
+
+PARAM_TEST_CASE(MedianFilter, MatDepth, Channels, int, bool)
+{
+    int type;
+    int ksize;
+    bool use_roi;
+
+    TEST_DECLARE_INPUT_PARAMETER(src)
+    TEST_DECLARE_OUTPUT_PARAMETER(dst)
+
+    virtual void SetUp()
+    {
+        type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
+        ksize = GET_PARAM(2);
+        use_roi = GET_PARAM(3);
+    }
+
+    virtual void generateTestData()
+    {
+        Size roiSize = randomSize(1, MAX_VALUE);
+        Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
+        randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
+
+        Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
+        randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
+
+        UMAT_UPLOAD_INPUT_PARAMETER(src)
+        UMAT_UPLOAD_OUTPUT_PARAMETER(dst)
+    }
+
+    void Near(double threshold = 0.0)
+    {
+        EXPECT_MAT_NEAR(dst, udst, threshold);
+        EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
+    }
+};
+
+OCL_TEST_P(MedianFilter, Mat)
+{
+    for (int j = 0; j < test_loop_times; j++)
+    {
+        generateTestData();
+
+        OCL_OFF(cv::medianBlur(src_roi, dst_roi, ksize));
+        OCL_ON(cv::medianBlur(usrc_roi, udst_roi, ksize));
+
+        Near(0);
+    }
+}
+
+OCL_INSTANTIATE_TEST_CASE_P(ImageProc, MedianFilter, Combine(
+                                Values(CV_8U, CV_16U, CV_16S, CV_32F),
+                                Values(1, 2, 4),
+                                Values(3, 5),
+                                Bool())
+                           );
+} } // namespace cvtest::ocl
+
+#endif
index 4f13385..2b59a4e 100644 (file)
@@ -28,6 +28,7 @@ Wrapping class for computing descriptors by using the
         virtual void write( FileStorage &fs ) const;
         virtual int descriptorSize() const;
         virtual int descriptorType() const;
+        virtual int defaultNorm() const;
     protected:
         ...
     }
index ed0ac9c..01f726b 100644 (file)
@@ -2765,6 +2765,7 @@ public:
 
     virtual int descriptorSize() const { return classifier_.classes(); }
     virtual int descriptorType() const { return DataType<T>::type; }
+    virtual int defaultNorm() const { return NORM_L1; }
 
     virtual bool empty() const;
 
index 1a5d3b9..0e1f8e5 100644 (file)
@@ -70,6 +70,8 @@ public:
 
     //! returns the descriptor size in float's (64 or 128)
     int descriptorSize() const;
+    //! returns the default norm type
+    int defaultNorm() const;
 
     //! upload host keypoints to device memory
     void uploadKeypoints(const std::vector<KeyPoint>& keypoints, GpuMat& keypointsGPU);
index 4acd747..88a1731 100644 (file)
@@ -66,6 +66,9 @@ public:
     //! returns the descriptor type
     CV_WRAP int descriptorType() const;
 
+    //! returns the default norm type
+    CV_WRAP int defaultNorm() const;
+
     //! finds the keypoints using SIFT algorithm
     void operator()(InputArray img, InputArray mask,
                     std::vector<KeyPoint>& keypoints) const;
@@ -118,6 +121,9 @@ public:
     //! returns the descriptor type
     CV_WRAP int descriptorType() const;
 
+    //! returns the descriptor type
+    CV_WRAP int defaultNorm() const;
+
     //! finds the keypoints using fast hessian detector used in SURF
     void operator()(InputArray img, InputArray mask,
                     CV_OUT std::vector<KeyPoint>& keypoints) const;
index 22b40ae..b06fa39 100644 (file)
@@ -76,6 +76,8 @@ namespace cv
 
             //! returns the descriptor size in float's (64 or 128)
             int descriptorSize() const;
+            //! returns the default norm type
+            int defaultNorm() const;
             //! upload host keypoints to device memory
             void uploadKeypoints(const std::vector<cv::KeyPoint> &keypoints, oclMat &keypointsocl);
             //! download keypoints from device to host memory
index e67138c..4a36c2d 100644 (file)
@@ -717,6 +717,11 @@ int SIFT::descriptorType() const
     return CV_32F;
 }
 
+int SIFT::defaultNorm() const
+{
+    return NORM_L2;
+}
+
 
 void SIFT::operator()(InputArray _image, InputArray _mask,
                       std::vector<KeyPoint>& keypoints) const
index 98d1449..be8d14d 100644 (file)
@@ -884,6 +884,7 @@ SURF::SURF(double _threshold, int _nOctaves, int _nOctaveLayers, bool _extended,
 
 int SURF::descriptorSize() const { return extended ? 128 : 64; }
 int SURF::descriptorType() const { return CV_32F; }
+int SURF::defaultNorm() const { return NORM_L2; }
 
 void SURF::operator()(InputArray imgarg, InputArray maskarg,
                       CV_OUT std::vector<KeyPoint>& keypoints) const
index 2912d04..4089b50 100644 (file)
@@ -265,6 +265,11 @@ int cv::cuda::SURF_CUDA::descriptorSize() const
     return extended ? 128 : 64;
 }
 
+int cv::cuda::SURF_CUDA::defaultNorm() const
+{
+    return NORM_L2;
+}
+
 void cv::cuda::SURF_CUDA::uploadKeypoints(const std::vector<KeyPoint>& keypoints, GpuMat& keypointsGPU)
 {
     if (keypoints.empty())
index 3b30663..5ade5e5 100644 (file)
@@ -299,6 +299,11 @@ int cv::ocl::SURF_OCL::descriptorSize() const
     return extended ? 128 : 64;
 }
 
+int cv::ocl::SURF_OCL::defaultNorm() const
+{
+    return NORM_L2;
+}
+
 void cv::ocl::SURF_OCL::uploadKeypoints(const std::vector<KeyPoint> &keypoints, oclMat &keypointsGPU)
 {
     if (keypoints.empty())
index 03041b0..3cc5b47 100644 (file)
@@ -1124,7 +1124,7 @@ protected:
             CV_Assert(kpt2[i].response > 0 );
 
         vector<DMatch> matches;
-        BFMatcher(NORM_L2, true).match(d1, d2, matches);
+        BFMatcher(f->defaultNorm(), true).match(d1, d2, matches);
 
         vector<Point2f> pt1, pt2;
         for( size_t i = 0; i < matches.size(); i++ ) {
index 360b798..4011f3c 100644 (file)
@@ -176,7 +176,7 @@ CUDA_TEST_P(SURF, Descriptor)
     cv::Mat descriptors_gold;
     surf_gold(image, cv::noArray(), keypoints, descriptors_gold, true);
 
-    cv::BFMatcher matcher(cv::NORM_L2);
+    cv::BFMatcher matcher(surf.defaultNorm());
     std::vector<cv::DMatch> matches;
     matcher.match(descriptors_gold, cv::Mat(descriptors), matches);
 
index c52b6e3..217460a 100644 (file)
@@ -195,7 +195,7 @@ TEST_P(SURF, DISABLED_Descriptor)
     cv::Mat descriptors_gold;
     surf_gold(image, cv::noArray(), keypoints, descriptors_gold, true);
 
-    cv::BFMatcher matcher(cv::NORM_L2);
+    cv::BFMatcher matcher(surf.defaultNorm());
     std::vector<cv::DMatch> matches;
     matcher.match(descriptors_gold, cv::Mat(descriptors), matches);
 
index 21e0b30..db9d64e 100644 (file)
@@ -5,4 +5,7 @@ endif()
 
 set(the_description "OpenCL-accelerated Computer Vision")
 ocv_define_module(ocl opencv_core opencv_imgproc opencv_features2d opencv_objdetect opencv_video opencv_calib3d opencv_ml "${OPENCL_LIBRARIES}")
+if(TARGET opencv_test_ocl)
+  target_link_libraries(opencv_test_ocl "${OPENCL_LIBRARIES}")
+endif()
 ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow)
index aec3f70..1d1265c 100644 (file)
@@ -25,12 +25,26 @@ Returns the list of devices
 
 ocl::setDevice
 --------------
-Returns void
+Initialize OpenCL computation context
 
 .. ocv:function:: void ocl::setDevice( const DeviceInfo* info )
 
     :param info: device info
 
+ocl::initializeContext
+--------------------------------
+Alternative way to initialize OpenCL computation context.
+
+.. ocv:function:: void ocl::initializeContext(void* pClPlatform, void* pClContext, void* pClDevice)
+
+    :param pClPlatform: selected ``platform_id`` (via pointer, parameter type is ``cl_platform_id*``)
+
+    :param pClContext: selected ``cl_context`` (via pointer, parameter type is ``cl_context*``)
+
+    :param pClDevice: selected ``cl_device_id`` (via pointer, parameter type is ``cl_device_id*``)
+
+This function can be used for context initialization with D3D/OpenGL interoperability.
+
 ocl::setBinaryPath
 ------------------
 Returns void
index 508014d..542dbeb 100644 (file)
@@ -84,6 +84,7 @@ namespace cv
             const PlatformInfo* platform;
 
             DeviceInfo();
+            ~DeviceInfo();
         };
 
         struct PlatformInfo
@@ -102,6 +103,7 @@ namespace cv
             std::vector<const DeviceInfo*> devices;
 
             PlatformInfo();
+            ~PlatformInfo();
         };
 
         //////////////////////////////// Initialization & Info ////////////////////////
@@ -117,6 +119,10 @@ namespace cv
         // set device you want to use
         CV_EXPORTS void setDevice(const DeviceInfo* info);
 
+        // Initialize from OpenCL handles directly.
+        // Argument types is (pointers): cl_platform_id*, cl_context*, cl_device_id*
+        CV_EXPORTS void initializeContext(void* pClPlatform, void* pClContext, void* pClDevice);
+
         enum FEATURE_TYPE
         {
             FEATURE_CL_DOUBLE = 1,
index ab1fe4f..410adbd 100644 (file)
@@ -175,6 +175,7 @@ namespace cv
             data = m.data;
             datastart = m.datastart;
             dataend = m.dataend;
+            clCxt = m.clCxt;
             wholerows = m.wholerows;
             wholecols = m.wholecols;
             offset = m.offset;
index 76e7eda..d6d081f 100644 (file)
 namespace cv {
 namespace ocl {
 
+using namespace cl_utils;
+
+#if defined(WIN32)
+static bool __termination = false;
+#endif
+
 struct __Module
 {
     __Module();
@@ -71,36 +77,10 @@ cv::Mutex& getInitializationMutex()
     return __module.initializationMutex;
 }
 
-
-struct PlatformInfoImpl
-{
-    cl_platform_id platform_id;
-
-    std::vector<int> deviceIDs;
-
-    PlatformInfo info;
-
-    PlatformInfoImpl()
-        : platform_id(NULL)
-    {
-    }
-};
-
-struct DeviceInfoImpl
+static cv::Mutex& getCurrentContextMutex()
 {
-    cl_platform_id platform_id;
-    cl_device_id device_id;
-
-    DeviceInfo info;
-
-    DeviceInfoImpl()
-        : platform_id(NULL), device_id(NULL)
-    {
-    }
-};
-
-static std::vector<PlatformInfoImpl> global_platforms;
-static std::vector<DeviceInfoImpl> global_devices;
+    return __module.currentContextMutex;
+}
 
 static bool parseOpenCLVersion(const std::string& versionStr, int& major, int& minor)
 {
@@ -131,6 +111,141 @@ static bool parseOpenCLVersion(const std::string& versionStr, int& major, int& m
     return true;
 }
 
+struct PlatformInfoImpl : public PlatformInfo
+{
+    cl_platform_id platform_id;
+
+    std::vector<int> deviceIDs;
+
+    PlatformInfoImpl()
+        : platform_id(NULL)
+    {
+    }
+
+    void init(int id, cl_platform_id platform)
+    {
+        CV_Assert(platform_id == NULL);
+
+        this->_id = id;
+        platform_id = platform;
+
+        openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_PROFILE, this->platformProfile));
+        openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_VERSION, this->platformVersion));
+        openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_NAME, this->platformName));
+        openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_VENDOR, this->platformVendor));
+        openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_EXTENSIONS, this->platformExtensons));
+
+        parseOpenCLVersion(this->platformVersion,
+                this->platformVersionMajor, this->platformVersionMinor);
+    }
+
+};
+
+struct DeviceInfoImpl: public DeviceInfo
+{
+    cl_platform_id platform_id;
+    cl_device_id device_id;
+
+    DeviceInfoImpl()
+        : platform_id(NULL), device_id(NULL)
+    {
+    }
+
+    void init(int id, PlatformInfoImpl& platformInfoImpl, cl_device_id device)
+    {
+        CV_Assert(device_id == NULL);
+
+        this->_id = id;
+        platform_id = platformInfoImpl.platform_id;
+        device_id = device;
+
+        this->platform = &platformInfoImpl;
+
+        cl_device_type type = cl_device_type(-1);
+        openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_TYPE, type));
+        this->deviceType = DeviceType(type);
+
+        openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_PROFILE, this->deviceProfile));
+        openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_VERSION, this->deviceVersion));
+        openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_NAME, this->deviceName));
+        openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_VENDOR, this->deviceVendor));
+        cl_uint vendorID = 0;
+        openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_VENDOR_ID, vendorID));
+        this->deviceVendorId = vendorID;
+        openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DRIVER_VERSION, this->deviceDriverVersion));
+        openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, this->deviceExtensions));
+
+        parseOpenCLVersion(this->deviceVersion,
+                this->deviceVersionMajor, this->deviceVersionMinor);
+
+        size_t maxWorkGroupSize = 0;
+        openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_WORK_GROUP_SIZE, maxWorkGroupSize));
+        this->maxWorkGroupSize = maxWorkGroupSize;
+
+        cl_uint maxDimensions = 0;
+        openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, maxDimensions));
+        std::vector<size_t> maxWorkItemSizes(maxDimensions);
+        openCLSafeCall(clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t) * maxDimensions,
+                (void *)&maxWorkItemSizes[0], 0));
+        this->maxWorkItemSizes = maxWorkItemSizes;
+
+        cl_uint maxComputeUnits = 0;
+        openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_COMPUTE_UNITS, maxComputeUnits));
+        this->maxComputeUnits = maxComputeUnits;
+
+        cl_ulong localMemorySize = 0;
+        openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_LOCAL_MEM_SIZE, localMemorySize));
+        this->localMemorySize = (size_t)localMemorySize;
+
+        cl_ulong maxMemAllocSize = 0;
+        openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, maxMemAllocSize));
+        this->maxMemAllocSize = (size_t)maxMemAllocSize;
+
+        cl_bool unifiedMemory = false;
+        openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_HOST_UNIFIED_MEMORY, unifiedMemory));
+        this->isUnifiedMemory = unifiedMemory != 0;
+
+        //initialize extra options for compilation. Currently only fp64 is included.
+        //Assume 4KB is enough to store all possible extensions.
+        openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, this->deviceExtensions));
+
+        size_t fp64_khr = this->deviceExtensions.find("cl_khr_fp64");
+        if(fp64_khr != std::string::npos)
+        {
+            this->compilationExtraOptions += "-D DOUBLE_SUPPORT";
+            this->haveDoubleSupport = true;
+        }
+        else
+        {
+            this->haveDoubleSupport = false;
+        }
+
+        size_t intel_platform = platformInfoImpl.platformVendor.find("Intel");
+        if(intel_platform != std::string::npos)
+        {
+            this->compilationExtraOptions += " -D INTEL_DEVICE";
+            this->isIntelDevice = true;
+        }
+        else
+        {
+            this->isIntelDevice = false;
+        }
+
+        if (id < 0)
+        {
+#ifdef CL_VERSION_1_2
+            if (this->deviceVersionMajor > 1 || (this->deviceVersionMajor == 1 && this->deviceVersionMinor >= 2))
+            {
+                ::clRetainDevice(device);
+            }
+#endif
+        }
+    }
+};
+
+static std::vector<PlatformInfoImpl> global_platforms;
+static std::vector<DeviceInfoImpl> global_devices;
+
 static void split(const std::string &s, char delim, std::vector<std::string> &elems) {
     std::stringstream ss(s);
     std::string item;
@@ -329,8 +444,6 @@ not_found:
 static bool __initialized = false;
 static int initializeOpenCLDevices()
 {
-    using namespace cl_utils;
-
     assert(!__initialized);
     __initialized = true;
 
@@ -351,19 +464,9 @@ static int initializeOpenCLDevices()
     for (size_t i = 0; i < platforms.size(); ++i)
     {
         PlatformInfoImpl& platformInfo = global_platforms[i];
-        platformInfo.info._id = i;
 
         cl_platform_id platform = platforms[i];
-
-        platformInfo.platform_id = platform;
-        openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_PROFILE, platformInfo.info.platformProfile));
-        openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_VERSION, platformInfo.info.platformVersion));
-        openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_NAME, platformInfo.info.platformName));
-        openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_VENDOR, platformInfo.info.platformVendor));
-        openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_EXTENSIONS, platformInfo.info.platformExtensons));
-
-        parseOpenCLVersion(platformInfo.info.platformVersion,
-                platformInfo.info.platformVersionMajor, platformInfo.info.platformVersionMinor);
+        platformInfo.init(i, platform);
 
         std::vector<cl_device_id> devices;
         cl_int status = getDevices(platform, CL_DEVICE_TYPE_ALL, devices);
@@ -375,89 +478,15 @@ static int initializeOpenCLDevices()
             int baseIndx = global_devices.size();
             global_devices.resize(baseIndx + devices.size());
             platformInfo.deviceIDs.resize(devices.size());
-            platformInfo.info.devices.resize(devices.size());
+            platformInfo.devices.resize(devices.size());
 
             for(size_t j = 0; j < devices.size(); ++j)
             {
                 cl_device_id device = devices[j];
 
                 DeviceInfoImpl& deviceInfo = global_devices[baseIndx + j];
-                deviceInfo.info._id = baseIndx + j;
-                deviceInfo.platform_id = platform;
-                deviceInfo.device_id = device;
-
-                deviceInfo.info.platform = &platformInfo.info;
-                platformInfo.deviceIDs[j] = deviceInfo.info._id;
-
-                cl_device_type type = cl_device_type(-1);
-                openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_TYPE, type));
-                deviceInfo.info.deviceType = DeviceType(type);
-
-                openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_PROFILE, deviceInfo.info.deviceProfile));
-                openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_VERSION, deviceInfo.info.deviceVersion));
-                openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_NAME, deviceInfo.info.deviceName));
-                openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_VENDOR, deviceInfo.info.deviceVendor));
-                cl_uint vendorID = 0;
-                openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_VENDOR_ID, vendorID));
-                deviceInfo.info.deviceVendorId = vendorID;
-                openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DRIVER_VERSION, deviceInfo.info.deviceDriverVersion));
-                openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, deviceInfo.info.deviceExtensions));
-
-                parseOpenCLVersion(deviceInfo.info.deviceVersion,
-                        deviceInfo.info.deviceVersionMajor, deviceInfo.info.deviceVersionMinor);
-
-                size_t maxWorkGroupSize = 0;
-                openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_WORK_GROUP_SIZE, maxWorkGroupSize));
-                deviceInfo.info.maxWorkGroupSize = maxWorkGroupSize;
-
-                cl_uint maxDimensions = 0;
-                openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, maxDimensions));
-                std::vector<size_t> maxWorkItemSizes(maxDimensions);
-                openCLSafeCall(clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t) * maxDimensions,
-                        (void *)&maxWorkItemSizes[0], 0));
-                deviceInfo.info.maxWorkItemSizes = maxWorkItemSizes;
-
-                cl_uint maxComputeUnits = 0;
-                openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_COMPUTE_UNITS, maxComputeUnits));
-                deviceInfo.info.maxComputeUnits = maxComputeUnits;
-
-                cl_ulong localMemorySize = 0;
-                openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_LOCAL_MEM_SIZE, localMemorySize));
-                deviceInfo.info.localMemorySize = (size_t)localMemorySize;
-
-                cl_ulong maxMemAllocSize = 0;
-                openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, maxMemAllocSize));
-                deviceInfo.info.maxMemAllocSize = (size_t)maxMemAllocSize;
-
-                cl_bool unifiedMemory = false;
-                openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_HOST_UNIFIED_MEMORY, unifiedMemory));
-                deviceInfo.info.isUnifiedMemory = unifiedMemory != 0;
-
-                //initialize extra options for compilation. Currently only fp64 is included.
-                //Assume 4KB is enough to store all possible extensions.
-                openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, deviceInfo.info.deviceExtensions));
-
-                size_t fp64_khr = deviceInfo.info.deviceExtensions.find("cl_khr_fp64");
-                if(fp64_khr != std::string::npos)
-                {
-                    deviceInfo.info.compilationExtraOptions += "-D DOUBLE_SUPPORT";
-                    deviceInfo.info.haveDoubleSupport = true;
-                }
-                else
-                {
-                    deviceInfo.info.haveDoubleSupport = false;
-                }
-
-                size_t intel_platform = platformInfo.info.platformVendor.find("Intel");
-                if(intel_platform != std::string::npos)
-                {
-                    deviceInfo.info.compilationExtraOptions += " -D INTEL_DEVICE";
-                    deviceInfo.info.isIntelDevice = true;
-                }
-                else
-                {
-                    deviceInfo.info.isIntelDevice = false;
-                }
+                platformInfo.deviceIDs[j] = baseIndx + j;
+                deviceInfo.init(baseIndx + j, platformInfo, device);
             }
         }
     }
@@ -468,7 +497,7 @@ static int initializeOpenCLDevices()
         for(size_t j = 0; j < platformInfo.deviceIDs.size(); ++j)
         {
             DeviceInfoImpl& deviceInfo = global_devices[platformInfo.deviceIDs[j]];
-            platformInfo.info.devices[j] = &deviceInfo.info;
+            platformInfo.devices[j] = &deviceInfo;
         }
     }
 
@@ -487,6 +516,8 @@ DeviceInfo::DeviceInfo()
     // nothing
 }
 
+DeviceInfo::~DeviceInfo() { }
+
 PlatformInfo::PlatformInfo()
     : _id(-1),
       platformVersionMajor(0), platformVersionMinor(0)
@@ -494,41 +525,136 @@ PlatformInfo::PlatformInfo()
     // nothing
 }
 
+PlatformInfo::~PlatformInfo() { }
+
+class ContextImpl;
+
+struct CommandQueue
+{
+    ContextImpl* context_;
+    cl_command_queue clQueue_;
+
+    CommandQueue() : context_(NULL), clQueue_(NULL) { }
+    ~CommandQueue() { release(); }
+
+    void create(ContextImpl* context_);
+    void release()
+    {
+#ifdef WIN32
+        // if process is on termination stage (ExitProcess was called and other threads were terminated)
+        // then disable command queue release because it may cause program hang
+        if (!__termination)
+#endif
+        {
+            if(clQueue_)
+            {
+                openCLSafeCall(clReleaseCommandQueue(clQueue_)); // some cleanup problems are here
+            }
+
+        }
+        clQueue_ = NULL;
+        context_ = NULL;
+    }
+};
+
+cv::TLSData<CommandQueue> commandQueueTLSData;
+
 //////////////////////////////// OpenCL context ////////////////////////
 //This is a global singleton class used to represent a OpenCL context.
 class ContextImpl : public Context
 {
 public:
-    const cl_device_id clDeviceID;
+    cl_device_id clDeviceID;
     cl_context clContext;
-    cl_command_queue clCmdQueue;
-    const DeviceInfo& deviceInfo;
+    const DeviceInfoImpl& deviceInfoImpl;
 
 protected:
-    ContextImpl(const DeviceInfo& deviceInfo, cl_device_id clDeviceID)
-        : clDeviceID(clDeviceID), clContext(NULL), clCmdQueue(NULL), deviceInfo(deviceInfo)
+    ContextImpl(const DeviceInfoImpl& _deviceInfoImpl, cl_context context)
+        : clDeviceID(_deviceInfoImpl.device_id), clContext(context), deviceInfoImpl(_deviceInfoImpl)
     {
-        // nothing
+#ifdef CL_VERSION_1_2
+        if (supportsFeature(FEATURE_CL_VER_1_2))
+        {
+            openCLSafeCall(clRetainDevice(clDeviceID));
+        }
+#endif
+        openCLSafeCall(clRetainContext(clContext));
+
+        ContextImpl* old = NULL;
+        {
+            cv::AutoLock lock(getCurrentContextMutex());
+            old = currentContext;
+            currentContext = this;
+        }
+        if (old != NULL)
+        {
+            delete old;
+        }
+    }
+    ~ContextImpl()
+    {
+        CV_Assert(this != currentContext);
+
+#ifdef CL_VERSION_1_2
+        if (supportsFeature(FEATURE_CL_VER_1_2))
+        {
+            openCLSafeCall(clReleaseDevice(clDeviceID));
+        }
+#endif
+        if (deviceInfoImpl._id < 0) // not in the global registry, so we should cleanup it
+        {
+#ifdef CL_VERSION_1_2
+            if (supportsFeature(FEATURE_CL_VER_1_2))
+            {
+                openCLSafeCall(clReleaseDevice(deviceInfoImpl.device_id));
+            }
+#endif
+            PlatformInfoImpl* platformImpl = (PlatformInfoImpl*)(deviceInfoImpl.platform);
+            delete platformImpl;
+            delete const_cast<DeviceInfoImpl*>(&deviceInfoImpl);
+        }
+        clDeviceID = NULL;
+
+#ifdef WIN32
+        // if process is on termination stage (ExitProcess was called and other threads were terminated)
+        // then disable command queue release because it may cause program hang
+        if (!__termination)
+#endif
+        {
+            if(clContext)
+            {
+                openCLSafeCall(clReleaseContext(clContext));
+            }
+        }
+        clContext = NULL;
     }
-    ~ContextImpl();
 public:
     static void setContext(const DeviceInfo* deviceInfo);
+    static void initializeContext(void* pClPlatform, void* pClContext, void* pClDevice);
 
     bool supportsFeature(FEATURE_TYPE featureType) const;
 
     static void cleanupContext(void);
 
+    static ContextImpl* getContext();
 private:
     ContextImpl(const ContextImpl&); // disabled
     ContextImpl& operator=(const ContextImpl&); // disabled
+
+    static ContextImpl* currentContext;
 };
 
-static ContextImpl* currentContext = NULL;
+ContextImpl* ContextImpl::currentContext = NULL;
 
 static bool __deviceSelected = false;
 
 Context* Context::getContext()
 {
+    return ContextImpl::getContext();
+}
+
+ContextImpl* ContextImpl::getContext()
+{
     if (currentContext == NULL)
     {
         static bool defaultInitiaization = false;
@@ -571,7 +697,7 @@ bool Context::supportsFeature(FEATURE_TYPE featureType) const
 
 const DeviceInfo& Context::getDeviceInfo() const
 {
-    return ((ContextImpl*)this)->deviceInfo;
+    return ((ContextImpl*)this)->deviceInfoImpl;
 }
 
 const void* Context::getOpenCLContextPtr() const
@@ -581,7 +707,13 @@ const void* Context::getOpenCLContextPtr() const
 
 const void* Context::getOpenCLCommandQueuePtr() const
 {
-    return &(((ContextImpl*)this)->clCmdQueue);
+    ContextImpl* pThis = (ContextImpl*)this;
+    CommandQueue* commandQueue = commandQueueTLSData.get();
+    if (commandQueue->context_ != pThis)
+    {
+        commandQueue->create(pThis);
+    }
+    return &commandQueue->clQueue_;
 }
 
 const void* Context::getOpenCLDeviceIDPtr() const
@@ -595,44 +727,18 @@ bool ContextImpl::supportsFeature(FEATURE_TYPE featureType) const
     switch (featureType)
     {
     case FEATURE_CL_INTEL_DEVICE:
-        return deviceInfo.isIntelDevice;
+        return deviceInfoImpl.isIntelDevice;
     case FEATURE_CL_DOUBLE:
-        return deviceInfo.haveDoubleSupport;
+        return deviceInfoImpl.haveDoubleSupport;
     case FEATURE_CL_UNIFIED_MEM:
-        return deviceInfo.isUnifiedMemory;
+        return deviceInfoImpl.isUnifiedMemory;
     case FEATURE_CL_VER_1_2:
-        return deviceInfo.deviceVersionMajor > 1 || (deviceInfo.deviceVersionMajor == 1 && deviceInfo.deviceVersionMinor >= 2);
+        return deviceInfoImpl.deviceVersionMajor > 1 || (deviceInfoImpl.deviceVersionMajor == 1 && deviceInfoImpl.deviceVersionMinor >= 2);
     }
     CV_Error(CV_StsBadArg, "Invalid feature type");
     return false;
 }
 
-#if defined(WIN32)
-static bool __termination = false;
-#endif
-
-ContextImpl::~ContextImpl()
-{
-#ifdef WIN32
-    // if process is on termination stage (ExitProcess was called and other threads were terminated)
-    // then disable command queue release because it may cause program hang
-    if (!__termination)
-#endif
-    {
-        if(clCmdQueue)
-        {
-            openCLSafeCall(clReleaseCommandQueue(clCmdQueue)); // some cleanup problems are here
-        }
-
-        if(clContext)
-        {
-            openCLSafeCall(clReleaseContext(clContext));
-        }
-    }
-    clCmdQueue = NULL;
-    clContext = NULL;
-}
-
 void fft_teardown();
 void clBlasTeardown();
 
@@ -641,53 +747,69 @@ void ContextImpl::cleanupContext(void)
     fft_teardown();
     clBlasTeardown();
 
-    cv::AutoLock lock(__module.currentContextMutex);
+    cv::AutoLock lock(getCurrentContextMutex());
     if (currentContext)
-        delete currentContext;
-    currentContext = NULL;
+    {
+        ContextImpl* ctx = currentContext;
+        currentContext = NULL;
+        delete ctx;
+    }
 }
 
 void ContextImpl::setContext(const DeviceInfo* deviceInfo)
 {
-    CV_Assert(deviceInfo->_id >= 0 && deviceInfo->_id < (int)global_devices.size());
+    CV_Assert(deviceInfo->_id >= 0); // we can't specify custom devices
+    CV_Assert(deviceInfo->_id < (int)global_devices.size());
 
     {
-        cv::AutoLock lock(__module.currentContextMutex);
+        cv::AutoLock lock(getCurrentContextMutex());
         if (currentContext)
         {
-            if (currentContext->deviceInfo._id == deviceInfo->_id)
+            if (currentContext->deviceInfoImpl._id == deviceInfo->_id)
                 return;
         }
     }
 
     DeviceInfoImpl& infoImpl = global_devices[deviceInfo->_id];
-    CV_Assert(deviceInfo == &infoImpl.info);
+    CV_Assert(deviceInfo == &infoImpl);
 
     cl_int status = 0;
     cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(infoImpl.platform_id), 0 };
     cl_context clContext = clCreateContext(cps, 1, &infoImpl.device_id, NULL, NULL, &status);
     openCLVerifyCall(status);
-#ifdef PRINT_KERNEL_RUN_TIME
-    cl_command_queue clCmdQueue = clCreateCommandQueue(clContext, infoImpl.device_id, CL_QUEUE_PROFILING_ENABLE, &status);
-#else /*PRINT_KERNEL_RUN_TIME*/
-    cl_command_queue clCmdQueue = clCreateCommandQueue(clContext, infoImpl.device_id, 0, &status);
-#endif /*PRINT_KERNEL_RUN_TIME*/
-    openCLVerifyCall(status);
 
-    ContextImpl* ctx = new ContextImpl(infoImpl.info, infoImpl.device_id);
-    ctx->clCmdQueue = clCmdQueue;
-    ctx->clContext = clContext;
+    ContextImpl* ctx = new ContextImpl(infoImpl, clContext);
+    clReleaseContext(clContext);
+    (void)ctx;
+}
 
-    ContextImpl* old = NULL;
-    {
-        cv::AutoLock lock(__module.currentContextMutex);
-        old = currentContext;
-        currentContext = ctx;
-    }
-    if (old != NULL)
-    {
-        delete old;
-    }
+void ContextImpl::initializeContext(void* pClPlatform, void* pClContext, void* pClDevice)
+{
+    CV_Assert(pClPlatform != NULL);
+    CV_Assert(pClContext != NULL);
+    CV_Assert(pClDevice != NULL);
+    cl_platform_id platform = *(cl_platform_id*)pClPlatform;
+    cl_context context = *(cl_context*)pClContext;
+    cl_device_id device = *(cl_device_id*)pClDevice;
+
+    PlatformInfoImpl* platformInfoImpl = new PlatformInfoImpl();
+    platformInfoImpl->init(-1, platform);
+    DeviceInfoImpl* deviceInfoImpl = new DeviceInfoImpl();
+    deviceInfoImpl->init(-1, *platformInfoImpl, device);
+
+    ContextImpl* ctx = new ContextImpl(*deviceInfoImpl, context);
+    (void)ctx;
+}
+
+void CommandQueue::create(ContextImpl* context)
+{
+    release();
+    cl_int status = 0;
+    // TODO add CL_QUEUE_PROFILING_ENABLE
+    cl_command_queue clCmdQueue = clCreateCommandQueue(context->clContext, context->clDeviceID, 0, &status);
+    openCLVerifyCall(status);
+    context_ = context;
+    clQueue_ = clCmdQueue;
 }
 
 int getOpenCLPlatforms(PlatformsInfo& platforms)
@@ -700,7 +822,7 @@ int getOpenCLPlatforms(PlatformsInfo& platforms)
     for (size_t id = 0; id < global_platforms.size(); ++id)
     {
         PlatformInfoImpl& impl = global_platforms[id];
-        platforms.push_back(&impl.info);
+        platforms.push_back(&impl);
     }
 
     return platforms.size();
@@ -730,9 +852,9 @@ int getOpenCLDevices(std::vector<const DeviceInfo*> &devices, int deviceType, co
         for (size_t id = 0; id < global_devices.size(); ++id)
         {
             DeviceInfoImpl& deviceInfo = global_devices[id];
-            if (((int)deviceInfo.info.deviceType & deviceType) != 0)
+            if (((int)deviceInfo.deviceType & deviceType) != 0)
             {
-                devices.push_back(&deviceInfo.info);
+                devices.push_back(&deviceInfo);
             }
         }
     }
@@ -765,6 +887,20 @@ void setDevice(const DeviceInfo* info)
     }
 }
 
+void initializeContext(void* pClPlatform, void* pClContext, void* pClDevice)
+{
+    try
+    {
+        ContextImpl::initializeContext(pClPlatform, pClContext, pClDevice);
+        __deviceSelected = true;
+    }
+    catch (...)
+    {
+        __deviceSelected = true;
+        throw;
+    }
+}
+
 bool supportsFeature(FEATURE_TYPE featureType)
 {
     return Context::getContext()->supportsFeature(featureType);
index fe8bc49..6ca4027 100644 (file)
@@ -40,7 +40,7 @@
 //M*/
 
 #include "test_precomp.hpp"
-#include "opencv2/core/opencl/runtime/opencl_core.hpp" // for OpenCL types: cl_mem
+#include "opencv2/core/opencl/runtime/opencl_core.hpp" // for OpenCL types & functions
 #include "opencv2/core/ocl.hpp"
 
 TEST(TestAPI, openCLExecuteKernelInterop)
@@ -127,3 +127,87 @@ TEST(OCL_TestTAPI, performance)
     t = (double)cv::getTickCount() - t;
     printf("cpu exec time = %gms per iter\n", t*1000./niters/cv::getTickFrequency());
 }
+
+// This test must be DISABLED by default!
+// (We can't restore original context for other tests)
+TEST(TestAPI, DISABLED_InitializationFromHandles)
+{
+#define MAX_PLATFORMS 16
+    cl_platform_id platforms[MAX_PLATFORMS] = { NULL };
+    cl_uint numPlatforms = 0;
+    cl_int status = ::clGetPlatformIDs(MAX_PLATFORMS, &platforms[0], &numPlatforms);
+    ASSERT_EQ(CL_SUCCESS, status) << "clGetPlatformIDs";
+    ASSERT_NE(0, (int)numPlatforms);
+
+    int selectedPlatform = 0;
+    cl_platform_id platform = platforms[selectedPlatform];
+
+    ASSERT_NE((void*)NULL, platform);
+
+    cl_device_id device = NULL;
+    status = ::clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, NULL);
+    ASSERT_EQ(CL_SUCCESS, status) << "clGetDeviceIDs";
+    ASSERT_NE((void*)NULL, device);
+
+    cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(platform), 0 };
+    cl_context context = ::clCreateContext(cps, 1, &device, NULL, NULL, &status);
+    ASSERT_EQ(CL_SUCCESS, status) << "clCreateContext";
+    ASSERT_NE((void*)NULL, context);
+
+    ASSERT_NO_THROW(cv::ocl::initializeContext(&platform, &context, &device));
+
+    status = ::clReleaseContext(context);
+    ASSERT_EQ(CL_SUCCESS, status) << "clReleaseContext";
+
+#ifdef CL_VERSION_1_2
+#if 1
+    {
+        cv::ocl::Context* ctx = cv::ocl::Context::getContext();
+        ASSERT_NE((void*)NULL, ctx);
+        if (ctx->supportsFeature(cv::ocl::FEATURE_CL_VER_1_2)) // device supports OpenCL 1.2+
+        {
+            status = ::clReleaseDevice(device);
+            ASSERT_EQ(CL_SUCCESS, status) << "clReleaseDevice";
+        }
+    }
+#else // code below doesn't work on Linux (SEGFAULTs on 1.1- devices are not handled via exceptions)
+    try
+    {
+        status = ::clReleaseDevice(device); // NOTE This works only with !DEVICES! that supports OpenCL 1.2
+        (void)status; // no check
+    }
+    catch (...)
+    {
+        // nothing, there is no problem
+    }
+#endif
+#endif
+
+    // print the name of current device
+    cv::ocl::Context* ctx = cv::ocl::Context::getContext();
+    ASSERT_NE((void*)NULL, ctx);
+    const cv::ocl::DeviceInfo& deviceInfo = ctx->getDeviceInfo();
+    std::cout << "Device name: " << deviceInfo.deviceName << std::endl;
+    std::cout << "Platform name: " << deviceInfo.platform->platformName << std::endl;
+
+    ASSERT_EQ(context, *(cl_context*)ctx->getOpenCLContextPtr());
+    ASSERT_EQ(device, *(cl_device_id*)ctx->getOpenCLDeviceIDPtr());
+
+    // do some calculations and check results
+    cv::RNG rng;
+    Size sz(100, 100);
+    cv::Mat srcMat = cvtest::randomMat(rng, sz, CV_32FC4, -10, 10, false);
+    cv::Mat dstMat;
+
+    cv::ocl::oclMat srcGpuMat(srcMat);
+    cv::ocl::oclMat dstGpuMat;
+
+    cv::Scalar v = cv::Scalar::all(1);
+    cv::add(srcMat, v, dstMat);
+    cv::ocl::add(srcGpuMat, v, dstGpuMat);
+
+    cv::Mat dstGpuMatMap;
+    dstGpuMat.download(dstGpuMatMap);
+
+    EXPECT_LE(checkNorm(dstMat, dstGpuMatMap), 1e-3);
+}
index 48a419d..9dd3df0 100644 (file)
@@ -15,6 +15,10 @@ add_subdirectory(cpp)
 add_subdirectory(gpu)
 add_subdirectory(ocl)
 
+if(WIN32 AND HAVE_DIRECTX)
+  add_subdirectory(directx)
+endif()
+
 if(ANDROID AND BUILD_ANDROID_EXAMPLES)
   add_subdirectory(android)
 endif()
@@ -62,6 +66,10 @@ add_subdirectory(cpp)
 add_subdirectory(ocl)
 # FIXIT: can't use cvconfig.h in samples: add_subdirectory(gpu)
 
+if(WIN32)
+  add_subdirectory(directx)
+endif()
+
 #
 # END OF BUILD CASE 2: Build samples with library binaries
 #
index cb65517..a7b01c8 100644 (file)
@@ -125,7 +125,7 @@ static void testCalonderClassifier( const string& classifierFilename, const stri
     Mat descriptors2;  de.compute( img2, keypoints2, descriptors2 );
 
     // Match descriptors
-    BFMatcher matcher(NORM_L1);
+    BFMatcher matcher(de.defaultNorm());
     vector<DMatch> matches;
     matcher.match( descriptors1, descriptors2, matches );
 
index 20ff1dc..c9d289e 100644 (file)
@@ -2146,12 +2146,12 @@ static Mat trainVocabulary( const string& filename, VocData& vocData, const Voca
 
         while( images.size() > 0 )
         {
-            if( bowTrainer.descripotorsCount() > maxDescCount )
+            if( bowTrainer.descriptorsCount() > maxDescCount )
             {
 #ifdef DEBUG_DESC_PROGRESS
-                cout << "Breaking due to full memory ( descriptors count = " << bowTrainer.descripotorsCount()
+                cout << "Breaking due to full memory ( descriptors count = " << bowTrainer.descriptorsCount()
                         << "; descriptor size in bytes = " << descByteSize << "; all used memory = "
-                        << bowTrainer.descripotorsCount()*descByteSize << endl;
+                        << bowTrainer.descriptorsCount()*descByteSize << endl;
 #endif
                 break;
             }
@@ -2182,7 +2182,7 @@ static Mat trainVocabulary( const string& filename, VocData& vocData, const Voca
 
                 for( int i = 0; i < descCount; i++ )
                 {
-                    if( usedMask[i] && bowTrainer.descripotorsCount() < maxDescCount )
+                    if( usedMask[i] && bowTrainer.descriptorsCount() < maxDescCount )
                         bowTrainer.add( imageDescriptors.row(i) );
                 }
             }
@@ -2190,7 +2190,7 @@ static Mat trainVocabulary( const string& filename, VocData& vocData, const Voca
 #ifdef DEBUG_DESC_PROGRESS
             cout << images.size() << " images left, " << images[randImgIdx].id << " processed - "
                     <</* descs_extracted << "/" << image_descriptors.rows << " extracted - " << */
-                    cvRound((static_cast<double>(bowTrainer.descripotorsCount())/static_cast<double>(maxDescCount))*100.0)
+                    cvRound((static_cast<double>(bowTrainer.descriptorsCount())/static_cast<double>(maxDescCount))*100.0)
                     << " % memory used" << ( imageDescriptors.empty() ? " -> no descriptors extracted, skipping" : "") << endl;
 #endif
 
@@ -2198,7 +2198,7 @@ static Mat trainVocabulary( const string& filename, VocData& vocData, const Voca
             images.erase( images.begin() + randImgIdx );
         }
 
-        cout << "Maximum allowed descriptor count: " << maxDescCount << ", Actual descriptor count: " << bowTrainer.descripotorsCount() << endl;
+        cout << "Maximum allowed descriptor count: " << maxDescCount << ", Actual descriptor count: " << bowTrainer.descriptorsCount() << endl;
 
         cout << "Training vocabulary..." << endl;
         vocabulary = bowTrainer.cluster();
index 1f12132..bf99ec7 100644 (file)
@@ -106,7 +106,7 @@ int main(int argc, const char ** argv)
 
   //Do matching using features2d
   cout << "matching with BruteForceMatcher<Hamming>" << endl;
-  BFMatcher matcher_popcount(NORM_HAMMING);
+  BFMatcher matcher_popcount(extractor.defaultNorm());
   vector<DMatch> matches_popcount;
   double pop_time = match(kpts_1, kpts_2, matcher_popcount, desc_1, desc_2, matches_popcount);
   cout << "done BruteForceMatcher<Hamming> matching. took " << pop_time << " seconds" << endl;
index dd3cd80..ccb8979 100644 (file)
@@ -881,9 +881,10 @@ public:
     virtual void readAlgorithm( )
     {
         string classifierFile = data_path + "/features2d/calonder_classifier.rtc";
+        Ptr<DescriptorExtractor> extractor = makePtr<CalonderDescriptorExtractor<float> >( classifierFile );
         defaultDescMatcher = makePtr<VectorDescriptorMatch>(
-            makePtr<CalonderDescriptorExtractor<float> >( classifierFile ),
-            makePtr<BFMatcher>(int(NORM_L2)));
+            extractor,
+            makePtr<BFMatcher>(extractor->defaultNorm()));
         specificDescMatcher = defaultDescMatcher;
     }
 };
index fa58d20..e6429ae 100644 (file)
@@ -96,7 +96,7 @@ int main( int argc, char** argv ) {
     // The standard Hamming distance can be used such as
     // BFMatcher matcher(NORM_HAMMING);
     // or the proposed cascade of hamming distance using SSSE3
-    BFMatcher matcher(NORM_HAMMING);
+    BFMatcher matcher(extractor.defaultNorm());
 
     // detect
     double t = (double)getTickCount();
index c1cd6e4..39d3620 100644 (file)
@@ -44,7 +44,7 @@ int main(int argc, char** argv)
     extractor.compute(img2, keypoints2, descriptors2);
 
     // matching descriptors
-    BFMatcher matcher(NORM_L2);
+    BFMatcher matcher(extractor.defaultNorm());
     vector<DMatch> matches;
     matcher.match(descriptors1, descriptors2, matches);
 
index abd7eab..5dac0a5 100644 (file)
@@ -45,7 +45,7 @@ int main(int argc, char** argv)
     extractor.compute(img2, keypoints2, descriptors2);
 
     // matching descriptors
-    BFMatcher matcher(NORM_L2);
+    BFMatcher matcher(extractor.defaultNorm());
     vector<DMatch> matches;
     matcher.match(descriptors1, descriptors2, matches);
 
index 6f0b9f3..2f6a8b9 100644 (file)
@@ -46,7 +46,7 @@ int main(int argc, char** argv)
     const char* algorithm_opt = "--algorithm=";
     const char* maxdisp_opt = "--max-disparity=";
     const char* blocksize_opt = "--blocksize=";
-    const char* nodisplay_opt = "--no-display=";
+    const char* nodisplay_opt = "--no-display";
     const char* scale_opt = "--scale=";
 
     if(argc < 3)
index 56067c8..89b60d4 100644 (file)
@@ -49,7 +49,7 @@ int main( int argc, char** argv )
   extractor.compute( img_2, keypoints_2, descriptors_2 );
 
   //-- Step 3: Matching descriptor vectors with a brute force matcher
-  BFMatcher matcher(NORM_L2);
+  BFMatcher matcher(extractor.defaultNorm());
   std::vector< DMatch > matches;
   matcher.match( descriptors_1, descriptors_2, matches );
 
index bf2559f..cefdc89 100644 (file)
@@ -140,7 +140,7 @@ int main(int ac, char ** av)
 
     vector<DMatch> matches;
 
-    BFMatcher desc_matcher(NORM_HAMMING);
+    BFMatcher desc_matcher(brief.defaultNorm());
 
     vector<Point2f> train_pts, query_pts;
     vector<KeyPoint> train_kpts, query_kpts;
diff --git a/samples/directx/CMakeLists.txt b/samples/directx/CMakeLists.txt
new file mode 100644 (file)
index 0000000..0bd7de9
--- /dev/null
@@ -0,0 +1,45 @@
+SET(OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_highgui)
+
+ocv_check_dependencies(${OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS})
+
+if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
+  set(project "directx")
+  string(TOUPPER "${project}" project_upper)
+
+  project("${project}_samples")
+
+  ocv_include_modules(${OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS})
+
+  # ---------------------------------------------
+  #      Define executable targets
+  # ---------------------------------------------
+  MACRO(OPENCV_DEFINE_DIRECTX_EXAMPLE name srcs)
+    set(the_target "example_${project}_${name}")
+    add_executable(${the_target} ${srcs})
+
+    target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS})
+
+    set_target_properties(${the_target} PROPERTIES
+      OUTPUT_NAME "${project}-example-${name}"
+      PROJECT_LABEL "(EXAMPLE_${project_upper}) ${name}")
+
+    if(ENABLE_SOLUTION_FOLDERS)
+      set_target_properties(${the_target} PROPERTIES FOLDER "samples//${project}")
+    endif()
+
+    if(WIN32)
+      if(MSVC AND NOT BUILD_SHARED_LIBS)
+        set_target_properties(${the_target} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG")
+      endif()
+      install(TARGETS ${the_target} RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/${project}" COMPONENT main)
+    endif()
+  ENDMACRO()
+
+  file(GLOB all_samples RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
+
+  foreach(sample_filename ${all_samples})
+    get_filename_component(sample ${sample_filename} NAME_WE)
+    file(GLOB sample_srcs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${sample}.*)
+    OPENCV_DEFINE_DIRECTX_EXAMPLE(${sample} ${sample_srcs})
+  endforeach()
+endif()
diff --git a/samples/directx/d3d10_interop.cpp b/samples/directx/d3d10_interop.cpp
new file mode 100644 (file)
index 0000000..a9eccdf
--- /dev/null
@@ -0,0 +1,138 @@
+#include <windows.h>
+#include <d3d10.h>
+#pragma comment (lib, "d3d10.lib")
+
+#define USE_D3D10
+#define WINDOW_NAME "OpenCV Direct3D 10 Sample"
+
+IDXGISwapChain *swapchain = NULL;
+ID3D10Device *dev = NULL;
+ID3D10Texture2D *pBackBufferTexture = NULL;
+ID3D10Texture2D *pCPUWriteTexture = NULL;
+ID3D10Texture2D *pInputTexture = NULL;
+ID3D10RenderTargetView *backbuffer = NULL;
+
+#include "d3d_base.inl.hpp"
+
+bool initDirect3D()
+{
+    DXGI_SWAP_CHAIN_DESC scd;
+
+    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
+
+    scd.BufferCount = 1;                                    // one back buffer
+    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
+    scd.BufferDesc.Width = WIDTH;                    // set the back buffer width
+    scd.BufferDesc.Height = HEIGHT;                  // set the back buffer height
+    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
+    scd.OutputWindow = hWnd;                                // the window to be used
+    scd.SampleDesc.Count = 1;                               // how many multisamples
+    scd.Windowed = TRUE;                                    // windowed/full-screen mode
+    scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;     // allow full-screen switching
+
+    if (FAILED(D3D10CreateDeviceAndSwapChain(
+            NULL,
+            D3D10_DRIVER_TYPE_HARDWARE,
+            NULL,
+            0,
+            D3D10_SDK_VERSION,
+            &scd,
+            &swapchain,
+            &dev)))
+    {
+        return false;
+    }
+
+    if (FAILED(swapchain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBufferTexture)))
+    {
+        return false;
+    }
+
+    if (FAILED(dev->CreateRenderTargetView(pBackBufferTexture, NULL, &backbuffer)))
+    {
+        return false;
+    }
+
+    dev->OMSetRenderTargets(1, &backbuffer, NULL);
+
+    D3D10_VIEWPORT viewport;
+    ZeroMemory(&viewport, sizeof(D3D10_VIEWPORT));
+    viewport.Width = WIDTH;
+    viewport.Height = HEIGHT;
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 0.0f;
+    dev->RSSetViewports(1, &viewport);
+
+    return true;
+}
+
+bool initDirect3DTextures()
+{
+    { // Create texture for demo 0
+        D3D10_TEXTURE2D_DESC desc = { 0 };
+        desc.Width = WIDTH;
+        desc.Height = HEIGHT;
+        desc.MipLevels = desc.ArraySize = 1;
+        desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+        desc.SampleDesc.Count = 1;
+        desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
+        desc.Usage = D3D10_USAGE_DYNAMIC;
+        desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
+        if (FAILED(dev->CreateTexture2D(&desc, NULL, &pCPUWriteTexture)))
+        {
+            std::cerr << "Can't create texture for CPU write sample" << std::endl;
+            return false;
+        }
+    }
+
+    { // Create Read-only texture
+        cv::Mat inputMat = getInputTexture();
+
+        D3D10_TEXTURE2D_DESC desc = { 0 };
+        desc.Width = inputMat.size().width;
+        desc.Height = inputMat.size().height;
+        desc.MipLevels = desc.ArraySize = 1;
+        desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+        desc.SampleDesc.Count = 1;
+        desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
+        desc.Usage = D3D10_USAGE_IMMUTABLE;
+        desc.CPUAccessFlags = cv::ocl::useOpenCL() ? 0 : D3D10_CPU_ACCESS_READ;
+
+        D3D10_SUBRESOURCE_DATA srInitData;
+        srInitData.pSysMem = inputMat.data;
+        srInitData.SysMemPitch = (UINT)inputMat.step[0];
+
+        if (FAILED(dev->CreateTexture2D(&desc, &srInitData, &pInputTexture)))
+        {
+            std::cerr << "Can't create texture with input image" << std::endl;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void cleanUp(void)
+{
+    if (swapchain) swapchain->SetFullscreenState(FALSE, NULL);    // switch to windowed mode
+
+    SAFE_RELEASE(swapchain);
+    SAFE_RELEASE(pCPUWriteTexture);
+    SAFE_RELEASE(pInputTexture);
+    SAFE_RELEASE(pBackBufferTexture);
+    SAFE_RELEASE(backbuffer);
+    SAFE_RELEASE(dev);
+}
+
+
+void render(void)
+{
+    // check to make sure you have a valid Direct3D device
+    CV_Assert(dev);
+
+    renderToD3DObject();
+
+    // switch the back buffer and the front buffer
+    swapchain->Present(0, 0);
+}
diff --git a/samples/directx/d3d11_interop.cpp b/samples/directx/d3d11_interop.cpp
new file mode 100644 (file)
index 0000000..9db9c31
--- /dev/null
@@ -0,0 +1,143 @@
+#include <windows.h>
+#include <d3d11.h>
+#pragma comment (lib, "d3d11.lib")
+
+#define USE_D3D11
+#define WINDOW_NAME "OpenCV Direct3D 11 Sample"
+
+IDXGISwapChain *swapchain = NULL;
+ID3D11Device *dev = NULL;
+ID3D11DeviceContext *devcon = NULL;
+ID3D11Texture2D *pBackBufferTexture = NULL;
+ID3D11Texture2D *pCPUWriteTexture = NULL;
+ID3D11Texture2D *pInputTexture = NULL;
+ID3D11RenderTargetView *backbuffer = NULL;
+
+#include "d3d_base.inl.hpp"
+
+bool initDirect3D()
+{
+    DXGI_SWAP_CHAIN_DESC scd;
+
+    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
+
+    scd.BufferCount = 1;                                    // one back buffer
+    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
+    scd.BufferDesc.Width = WIDTH;                    // set the back buffer width
+    scd.BufferDesc.Height = HEIGHT;                  // set the back buffer height
+    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
+    scd.OutputWindow = hWnd;                                // the window to be used
+    scd.SampleDesc.Count = 1;                               // how many multisamples
+    scd.Windowed = TRUE;                                    // windowed/full-screen mode
+    scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;     // allow full-screen switching
+
+    if (FAILED(D3D11CreateDeviceAndSwapChain(
+            NULL,
+            D3D_DRIVER_TYPE_HARDWARE,
+            NULL,
+            0,
+            NULL,
+            0,
+            D3D11_SDK_VERSION,
+            &scd,
+            &swapchain,
+            &dev,
+            NULL,
+            &devcon)))
+    {
+        return false;
+    }
+
+    if (FAILED(swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBufferTexture)))
+    {
+        return false;
+    }
+
+    if (FAILED(dev->CreateRenderTargetView(pBackBufferTexture, NULL, &backbuffer)))
+    {
+        return false;
+    }
+
+    devcon->OMSetRenderTargets(1, &backbuffer, NULL);
+
+    D3D11_VIEWPORT viewport = { 0 };
+    viewport.Width = WIDTH;
+    viewport.Height = HEIGHT;
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 0.0f;
+    devcon->RSSetViewports(1, &viewport);
+
+    return true;
+}
+
+bool initDirect3DTextures()
+{
+    { // Create texture for demo 0
+        D3D11_TEXTURE2D_DESC desc = { 0 };
+        desc.Width = WIDTH;
+        desc.Height = HEIGHT;
+        desc.MipLevels = desc.ArraySize = 1;
+        desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+        desc.SampleDesc.Count = 1;
+        desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+        desc.Usage = D3D11_USAGE_DYNAMIC;
+        desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+        if (FAILED(dev->CreateTexture2D(&desc, NULL, &pCPUWriteTexture)))
+        {
+            std::cerr << "Can't create texture for CPU write sample" << std::endl;
+            return false;
+        }
+    }
+
+    { // Create Read-only texture
+        cv::Mat inputMat = getInputTexture();
+
+        D3D11_TEXTURE2D_DESC desc = { 0 };
+        desc.Width = inputMat.size().width;
+        desc.Height = inputMat.size().height;
+        desc.MipLevels = desc.ArraySize = 1;
+        desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+        desc.SampleDesc.Count = 1;
+        desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+        desc.Usage = D3D11_USAGE_IMMUTABLE;
+        desc.CPUAccessFlags = cv::ocl::useOpenCL() ? 0 : D3D11_CPU_ACCESS_READ;
+
+        D3D11_SUBRESOURCE_DATA srInitData;
+        srInitData.pSysMem = inputMat.data;
+        srInitData.SysMemPitch = (UINT)inputMat.step[0];
+
+        if (FAILED(dev->CreateTexture2D(&desc, &srInitData, &pInputTexture)))
+        {
+            std::cerr << "Can't create texture with input image" << std::endl;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void cleanUp(void)
+{
+    if (swapchain) swapchain->SetFullscreenState(FALSE, NULL);    // switch to windowed mode
+
+    SAFE_RELEASE(swapchain);
+    SAFE_RELEASE(pCPUWriteTexture);
+    SAFE_RELEASE(pInputTexture);
+    SAFE_RELEASE(pBackBufferTexture);
+    SAFE_RELEASE(backbuffer);
+    SAFE_RELEASE(dev);
+    SAFE_RELEASE(devcon);
+}
+
+
+void render(void)
+{
+    // check to make sure you have a valid Direct3D device
+    CV_Assert(dev);
+
+    renderToD3DObject();
+
+    // switch the back buffer and the front buffer
+    swapchain->Present(0, 0);
+}
diff --git a/samples/directx/d3d9_interop.cpp b/samples/directx/d3d9_interop.cpp
new file mode 100644 (file)
index 0000000..fc9bdbd
--- /dev/null
@@ -0,0 +1,149 @@
+#include <windows.h>
+#include <d3d9.h>
+#pragma comment (lib, "d3d9.lib")
+
+#define USE_D3D9
+#define WINDOW_NAME "OpenCV Direct3D 9 Sample"
+
+IDirect3D9 *pD3D = NULL;
+IDirect3DDevice9 *dev = NULL;
+IDirect3DSurface9 *pBackBuffer = NULL;
+IDirect3DSurface9 *pCPUWriteSurface = NULL; // required name
+IDirect3DSurface9 *pReadOnlySurface = NULL; // required name
+HANDLE readOnlySurfaceShared = 0; // required name
+IDirect3DSurface9 *pSurface = NULL; // required name
+HANDLE surfaceShared = 0; // required name
+
+#include "d3d_base.inl.hpp"
+
+bool initDirect3D(void)
+{
+    if (NULL == (pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
+    {
+        return false;
+    }
+
+    D3DPRESENT_PARAMETERS d3dpp;
+    ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
+
+    DWORD flags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE | D3DCREATE_NOWINDOWCHANGES
+            | D3DCREATE_MULTITHREADED;
+
+    d3dpp.Windowed = true;
+    d3dpp.Flags = 0;
+    d3dpp.BackBufferCount = 0;
+    d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
+    d3dpp.BackBufferHeight = HEIGHT;
+    d3dpp.BackBufferWidth = WIDTH;
+    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
+    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    d3dpp.hDeviceWindow = hWnd;
+    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+    if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, flags, &d3dpp, &dev)))
+    {
+        return false;
+    }
+
+    if (FAILED(dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer)))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool initDirect3DTextures()
+{
+    // Note: sharing is not supported on some platforms
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface, NULL/*&surfaceShared*/)))
+    {
+        std::cerr << "Can't create surface for result" << std::endl;
+        return false;
+    }
+
+    // Note: sharing is not supported on some platforms
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pReadOnlySurface, NULL/*&readOnlySurfaceShared*/)))
+    {
+        std::cerr << "Can't create read only surface" << std::endl;
+        return false;
+    }
+    else
+    {
+        IDirect3DSurface9* pTmpSurface;
+        if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTmpSurface, NULL)))
+        {
+            std::cerr << "Can't create temp surface for CPU write" << std::endl;
+            return false;
+        }
+
+        D3DLOCKED_RECT memDesc = {0, NULL};
+        RECT rc = {0, 0, WIDTH, HEIGHT};
+        if (SUCCEEDED(pTmpSurface->LockRect(&memDesc, &rc, 0)))
+        {
+            cv::Mat m(cv::Size(WIDTH, HEIGHT), CV_8UC4, memDesc.pBits, (int)memDesc.Pitch);
+            getInputTexture().copyTo(m);
+            pTmpSurface->UnlockRect();
+            dev->StretchRect(pTmpSurface, NULL, pReadOnlySurface, NULL, D3DTEXF_NONE);
+        }
+        else
+        {
+            std::cerr << "Can't LockRect() on surface" << std::endl;
+        }
+        pTmpSurface->Release();
+    }
+
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pCPUWriteSurface, NULL)))
+    {
+        std::cerr << "Can't create surface for CPU write" << std::endl;
+        return false;
+    }
+
+    return true;
+}
+
+void render(void)
+{
+    // check to make sure you have a valid Direct3D device
+    CV_Assert(dev);
+
+    renderToD3DObject();
+
+    if (g_sampleType == 0)
+    {
+        // nothing
+    }
+    else if (g_sampleType == 1)
+    {
+        if (FAILED(dev->StretchRect(pCPUWriteSurface, NULL, pBackBuffer, NULL, D3DTEXF_NONE)))
+        {
+            std::cerr << "Can't StretchRect()" << std::endl;
+        }
+    }
+    else
+    {
+        if (FAILED(dev->StretchRect(pSurface, NULL, pBackBuffer, NULL, D3DTEXF_NONE)))
+        {
+            std::cerr << "Can't StretchRect()" << std::endl;
+        }
+    }
+
+    if (SUCCEEDED(dev -> BeginScene()))
+    {
+        // end the scene
+        dev -> EndScene();
+    }
+
+    // present the back buffer contents to the display
+    dev->Present(NULL, NULL, NULL, NULL);
+}
+
+void cleanUp (void)
+{
+    SAFE_RELEASE(pCPUWriteSurface);
+    SAFE_RELEASE(pReadOnlySurface);
+    SAFE_RELEASE(pSurface);
+    SAFE_RELEASE(pBackBuffer);
+    SAFE_RELEASE(dev);
+    SAFE_RELEASE(pD3D);}
diff --git a/samples/directx/d3d9ex_interop.cpp b/samples/directx/d3d9ex_interop.cpp
new file mode 100644 (file)
index 0000000..38d2300
--- /dev/null
@@ -0,0 +1,158 @@
+#include <windows.h>
+#include <d3d9.h>
+#pragma comment (lib, "d3d9.lib")
+
+#define USE_D3DEX
+#define WINDOW_NAME "OpenCV Direct3D 9 Ex Sample"
+
+IDirect3D9Ex *pD3D = NULL;
+IDirect3DDevice9Ex *dev = NULL;
+IDirect3DSurface9 *pBackBuffer = NULL;
+IDirect3DSurface9 *pCPUWriteSurface = NULL; // required name
+IDirect3DSurface9 *pReadOnlySurface = NULL; // required name
+HANDLE readOnlySurfaceShared = 0; // required name
+IDirect3DSurface9 *pSurface = NULL; // required name
+HANDLE surfaceShared = 0; // required name
+
+#include "d3d_base.inl.hpp"
+
+bool initDirect3D(void)
+{
+    if (FAILED(Direct3DCreate9Ex(D3D_SDK_VERSION, &pD3D)))
+    {
+        return false;
+    }
+
+    D3DDISPLAYMODEEX ddm;
+    ZeroMemory(&ddm, sizeof(ddm));
+    ddm.Size = sizeof(D3DDISPLAYMODEEX);
+    D3DDISPLAYROTATION rotation;
+    if (FAILED(pD3D->GetAdapterDisplayModeEx(D3DADAPTER_DEFAULT, &ddm, &rotation)))
+    {
+        return false;
+    }
+
+    D3DPRESENT_PARAMETERS d3dpp;
+    ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
+
+    DWORD flags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE | D3DCREATE_NOWINDOWCHANGES
+            | D3DCREATE_MULTITHREADED;
+
+    d3dpp.Windowed = true;
+    d3dpp.Flags = 0;
+    d3dpp.BackBufferCount = 0;
+    d3dpp.BackBufferFormat = ddm.Format;
+    d3dpp.BackBufferHeight = HEIGHT;
+    d3dpp.BackBufferWidth = WIDTH;
+    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
+    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    d3dpp.hDeviceWindow = hWnd;
+    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+    if (FAILED(pD3D->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, flags, &d3dpp, NULL, &dev)))
+    {
+        return false;
+    }
+
+    if (FAILED(dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer)))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool initDirect3DTextures()
+{
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface, &surfaceShared)))
+    {
+        std::cerr << "Can't create surface for result" << std::endl;
+        return false;
+    }
+
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pReadOnlySurface, &readOnlySurfaceShared)))
+    {
+        std::cerr << "Can't create read only surface" << std::endl;
+        return false;
+    }
+    else
+    {
+        IDirect3DSurface9* pTmpSurface;
+        if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTmpSurface, NULL)))
+        {
+            std::cerr << "Can't create temp surface for CPU write" << std::endl;
+            return false;
+        }
+
+        D3DLOCKED_RECT memDesc = {0, NULL};
+        RECT rc = {0, 0, WIDTH, HEIGHT};
+        if (SUCCEEDED(pTmpSurface->LockRect(&memDesc, &rc, 0)))
+        {
+            cv::Mat m(cv::Size(WIDTH, HEIGHT), CV_8UC4, memDesc.pBits, (int)memDesc.Pitch);
+            getInputTexture().copyTo(m);
+            pTmpSurface->UnlockRect();
+            dev->StretchRect(pTmpSurface, NULL, pReadOnlySurface, NULL, D3DTEXF_NONE);
+        }
+        else
+        {
+            std::cerr << "Can't LockRect() on surface" << std::endl;
+        }
+        pTmpSurface->Release();
+    }
+
+    if (FAILED(dev->CreateOffscreenPlainSurface(WIDTH, HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pCPUWriteSurface, NULL)))
+    {
+        std::cerr << "Can't create surface for CPU write" << std::endl;
+        return false;
+    }
+
+    return true;
+}
+
+
+void render(void)
+{
+    // check to make sure you have a valid Direct3D device
+    CV_Assert(dev);
+
+    renderToD3DObject();
+
+    if (g_sampleType == 0)
+    {
+        // nothing
+    }
+    else if (g_sampleType == 1)
+    {
+        if (FAILED(dev->StretchRect(pCPUWriteSurface, NULL, pBackBuffer, NULL, D3DTEXF_NONE)))
+        {
+            std::cerr << "Can't StretchRect()" << std::endl;
+        }
+    }
+    else
+    {
+        if (FAILED(dev->StretchRect(pSurface, NULL, pBackBuffer, NULL, D3DTEXF_NONE)))
+        {
+            std::cerr << "Can't StretchRect()" << std::endl;
+        }
+    }
+
+    if (SUCCEEDED(dev -> BeginScene()))
+    {
+        // end the scene
+        dev -> EndScene();
+    }
+
+    // present the back buffer contents to the display
+    dev->Present(NULL, NULL, NULL, NULL);
+}
+
+void cleanUp (void)
+{
+    SAFE_RELEASE(pCPUWriteSurface);
+    SAFE_RELEASE(pReadOnlySurface);
+    SAFE_RELEASE(pSurface);
+    SAFE_RELEASE(pBackBuffer);
+    SAFE_RELEASE(dev);
+    SAFE_RELEASE(pD3D);
+}
diff --git a/samples/directx/d3d_base.inl.hpp b/samples/directx/d3d_base.inl.hpp
new file mode 100644 (file)
index 0000000..6b6de30
--- /dev/null
@@ -0,0 +1,457 @@
+//
+// Don't use as a standalone file
+//
+
+#include "opencv2/core.hpp"
+#include "opencv2/core/utility.hpp" // cv::format
+#include "opencv2/imgproc.hpp" // cvtColor
+#include "opencv2/imgproc/types_c.h" // cvtColor
+#include "opencv2/highgui.hpp" // imread
+#include "opencv2/core/directx.hpp"
+
+#include <iostream>
+#include <queue>
+
+using namespace cv;
+using namespace cv::directx;
+static const int fontFace = cv::FONT_HERSHEY_DUPLEX;
+#if !defined(USE_D3D9) && !defined(USE_D3DEX)
+const cv::Scalar frameColor(255,128,0,255);
+#else
+const cv::Scalar frameColor(0,128,255,255); // BGRA for D3D9
+#endif
+
+#define SAFE_RELEASE(p) if (p) { p->Release(); p = NULL; }
+
+const int WIDTH = 1024;
+const int HEIGHT = 768;
+
+HINSTANCE hInstance;
+HWND hWnd;
+
+// external declaration
+bool initDirect3D(void);
+bool initDirect3DTextures(void);
+void render(void);
+void cleanUp (void);
+
+#define USAGE_DESCRIPTION_0 "1 - CPU write via LockRect/Map"
+#define USAGE_DESCRIPTION_1 "2* - Mat->D3D"
+#define USAGE_DESCRIPTION_2 "3* - D3D->UMat / change UMat / UMat->D3D"
+#define USAGE_DESCRIPTION_3 "0 - show input texture without any processing"
+#define USAGE_DESCRIPTION_SPACE "SPACE - toggle frame processing (only data transfers)"
+
+static int g_sampleType = 0;
+static int g_disableProcessing = false;
+
+// forward declaration
+static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+
+static bool initWindow()
+{
+    WNDCLASSEX wcex;
+
+    wcex.cbSize             = sizeof(WNDCLASSEX);
+    wcex.style              = CS_HREDRAW | CS_VREDRAW;
+    wcex.lpfnWndProc        = WndProc;
+    wcex.cbClsExtra         = 0;
+    wcex.cbWndExtra         = 0;
+    wcex.hInstance          = hInstance;
+    wcex.hIcon              = LoadIcon(0, IDI_APPLICATION);
+    wcex.hCursor            = LoadCursor(0, IDC_ARROW);
+    wcex.hbrBackground      = 0;
+    wcex.lpszMenuName       = 0L;
+    wcex.lpszClassName      = "OpenCVDirectX";
+    wcex.hIconSm            = 0;
+
+    RegisterClassEx(&wcex);
+
+    RECT rc = {0, 0, WIDTH, HEIGHT};
+    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
+    hWnd = CreateWindow("OpenCVDirectX", WINDOW_NAME,
+            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
+
+    if (!hWnd)
+        return false;
+
+    ShowWindow(hWnd, SW_SHOW);
+    UpdateWindow(hWnd);
+
+    return true;
+}
+
+static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    switch (message)
+    {
+        case WM_DESTROY:
+            PostQuitMessage(0);
+            return 0;
+
+        case WM_CHAR:
+            if (wParam >= '0' && wParam <= '3')
+            {
+                g_sampleType = (char)wParam - '0';
+                return 0;
+            }
+            else if (wParam == ' ')
+            {
+                g_disableProcessing = !g_disableProcessing;
+                return 0;
+            }
+            else if (wParam == VK_ESCAPE)
+            {
+                DestroyWindow(hWnd);
+                return 0;
+            }
+            break;
+    }
+    return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+static float getFps()
+{
+    static std::queue<int64> time_queue;
+
+    int64 now = cv::getTickCount(), then = 0;
+    time_queue.push(now);
+
+    if (time_queue.size() >= 2)
+        then = time_queue.front();
+
+    if (time_queue.size() >= 25)
+        time_queue.pop();
+
+    return time_queue.size() * (float)cv::getTickFrequency() / (now - then);
+}
+
+static int bgColor[4] = {0, 0, 0, 0};
+static cv::Mat* inputMat = NULL;
+
+static void renderToD3DObject(void)
+{
+    static int frame = 0;
+
+    const float fps = getFps();
+
+    String deviceName = cv::ocl::useOpenCL() ? cv::ocl::Context2::getDefault().device(0).name() : "No OpenCL device";
+
+    if ((frame % std::max(1, (int)(fps / 25))) == 0)
+    {
+        String msg = format("%s%s: %s, Sample %d, Frame %d, fps %g (%g ms)",
+                g_disableProcessing ? "(FRAME PROCESSING DISABLED) " : "",
+                WINDOW_NAME, deviceName.c_str(), g_sampleType,
+                frame, fps, (int(10 * 1000.0 / fps)) * 0.1);
+        SetWindowText(hWnd, msg.c_str());
+    }
+
+    // 0..255
+    int c[4] =
+    {
+        std::abs((frame & 0x1ff) - 0x100),
+        std::abs(((frame * 2) & 0x1ff) - 0x100),
+        std::abs(((frame / 2) & 0x1ff) - 0x100),
+        0
+    };
+
+    int c1 = c[0] / 2 - 0x40 - bgColor[0];
+    int c2 = c[1] / 2 - 0x40 - bgColor[1];
+    int c3 = c[2] / 2 - 0x40 - bgColor[2];
+
+    switch (g_sampleType)
+    {
+    case 0:
+#if defined(USE_D3D9) || defined (USE_D3DEX)
+        if (FAILED(dev->StretchRect(pReadOnlySurface, NULL, pBackBuffer, NULL, D3DTEXF_NONE)))
+        {
+            std::cerr << "Can't StretchRect()" << std::endl;
+        }
+#elif defined(USE_D3D10)
+        dev->CopyResource(pBackBufferTexture, pInputTexture);
+#elif defined(USE_D3D11)
+        devcon->CopyResource(pBackBufferTexture, pInputTexture);
+#else
+#error "Invalid USE_D3D value"
+#endif
+        break;
+
+    case 1:
+    {
+        int BOXSIZE = 50;
+        int x = std::abs(((frame * 1) % (2 * (WIDTH - BOXSIZE))) - (WIDTH - BOXSIZE));
+        int y = std::abs(((frame / 2) % (2 * (HEIGHT - BOXSIZE))) - (HEIGHT - BOXSIZE));
+        cv::Rect boxRect(x, y, BOXSIZE, BOXSIZE);
+#if defined(USE_D3D9) || defined (USE_D3DEX)
+        D3DLOCKED_RECT memDesc = {0, NULL};
+        RECT rc = {0, 0, WIDTH, HEIGHT};
+        if (SUCCEEDED(pCPUWriteSurface->LockRect(&memDesc, &rc, 0)))
+        {
+            if (!g_disableProcessing)
+            {
+                Mat m(Size(WIDTH, HEIGHT), CV_8UC4, memDesc.pBits, (int)memDesc.Pitch);
+                inputMat->copyTo(m);
+                m(boxRect).setTo(Scalar(c[0], c[1], c[2], 255));
+            }
+            pCPUWriteSurface->UnlockRect();
+        }
+        else
+        {
+            std::cerr << "Can't LockRect() on surface" << std::endl;
+        }
+#elif defined(USE_D3D10)
+        D3D10_MAPPED_TEXTURE2D mappedTex;
+        if (SUCCEEDED(pCPUWriteTexture->Map( D3D10CalcSubresource(0, 0, 1), D3D10_MAP_WRITE_DISCARD, 0, &mappedTex)))
+        {
+            if (!g_disableProcessing)
+            {
+                Mat m(Size(WIDTH, HEIGHT), CV_8UC4, mappedTex.pData, (int)mappedTex.RowPitch);
+                inputMat->copyTo(m);
+                m(boxRect).setTo(Scalar(c[0], c[1], c[2], 255));
+            }
+            pCPUWriteTexture->Unmap(D3D10CalcSubresource(0, 0, 1));
+            dev->CopyResource(pBackBufferTexture, pCPUWriteTexture);
+        }
+        else
+        {
+            std::cerr << "Can't Map() texture" << std::endl;
+        }
+#elif defined(USE_D3D11)
+        D3D11_MAPPED_SUBRESOURCE mappedTex;
+        if (SUCCEEDED(devcon->Map(pCPUWriteTexture, D3D11CalcSubresource(0, 0, 1), D3D11_MAP_WRITE_DISCARD, 0, &mappedTex)))
+        {
+            if (!g_disableProcessing)
+            {
+                Mat m(Size(WIDTH, HEIGHT), CV_8UC4, mappedTex.pData, (int)mappedTex.RowPitch);
+                inputMat->copyTo(m);
+                m(boxRect).setTo(Scalar(c[0], c[1], c[2], 255));
+            }
+            devcon->Unmap(pCPUWriteTexture, D3D11CalcSubresource(0, 0, 1));
+            devcon->CopyResource(pBackBufferTexture, pCPUWriteTexture);
+        }
+        else
+        {
+            std::cerr << "Can't Map() texture" << std::endl;
+        }
+#else
+#error "Invalid USE_D3D value"
+#endif
+        break;
+    }
+    case 2:
+    {
+        static Mat m;
+        if (!g_disableProcessing)
+        {
+#if 1
+            cv::add(*inputMat, Scalar(c1, c2, c3, 255), m);
+#else
+            inputMat->copyTo(m);
+#endif
+            cv::putText(m,
+                    cv::format("Frame %d, fps %g (%g ms)",
+                            frame, fps, (int(10 * 1000.0 / fps)) * 0.1),
+                    cv::Point(8, 80), fontFace, 1, frameColor, 2);
+        }
+        else
+        {
+            m.create(Size(WIDTH, HEIGHT), CV_8UC4);
+        }
+        try
+        {
+    #if defined(USE_D3D9) || defined (USE_D3DEX)
+            convertToDirect3DSurface9(m, pSurface, (void*)surfaceShared);
+    #elif defined(USE_D3D10)
+            convertToD3D10Texture2D(m, pBackBufferTexture);
+    #elif defined(USE_D3D11)
+            convertToD3D11Texture2D(m, pBackBufferTexture);
+    #else
+    #error "Invalid USE_D3D value"
+    #endif
+        }
+        catch (cv::Exception& e)
+        {
+            std::cerr << "Can't convert to D3D object: exception: " << e.what() << std::endl;
+        }
+        catch (...)
+        {
+            std::cerr << "Can't convert to D3D object" << std::endl;
+        }
+        break;
+    }
+    case 3:
+    {
+        static UMat tmp;
+        try
+        {
+#if defined(USE_D3D9) || defined (USE_D3DEX)
+            convertFromDirect3DSurface9(pReadOnlySurface, tmp, (void*)readOnlySurfaceShared);
+#elif defined(USE_D3D10)
+            convertFromD3D10Texture2D(pInputTexture, tmp);
+#elif defined(USE_D3D11)
+            convertFromD3D11Texture2D(pInputTexture, tmp);
+#else
+#error "Invalid USE_D3D value"
+#endif
+        }
+        catch (cv::Exception& e)
+        {
+            std::cerr << "Can't convert from D3D object: exception: " << e.what() << std::endl;
+        }
+        catch (...)
+        {
+            std::cerr << "Can't convert from D3D object" << std::endl;
+        }
+        static UMat res;
+        if (!g_disableProcessing)
+        {
+            cv::add(tmp, Scalar(c1, c2, c3, 255), res);
+        }
+        else
+        {
+            res = tmp;
+        }
+        try
+        {
+#if defined(USE_D3D9) || defined (USE_D3DEX)
+            convertToDirect3DSurface9(res, pSurface, (void*)surfaceShared);
+#elif defined(USE_D3D10)
+            convertToD3D10Texture2D(res, pBackBufferTexture);
+#elif defined(USE_D3D11)
+            convertToD3D11Texture2D(res, pBackBufferTexture);
+#else
+#error "Invalid USE_D3D value"
+#endif
+        }
+        catch (cv::Exception& e)
+        {
+            std::cerr << "Can't convert to D3D object: exception: " << e.what() << std::endl;
+        }
+        catch (...)
+        {
+            std::cerr << "Can't convert to D3D object" << std::endl;
+        }
+        break;
+    }
+    }
+    frame++;
+}
+
+
+static cv::Mat getInputTexture()
+{
+    cv::Mat inputMat = cv::imread("input.bmp", cv::IMREAD_COLOR);
+
+    if (inputMat.depth() != CV_8U)
+    {
+        inputMat.convertTo(inputMat, CV_8U);
+    }
+    if (inputMat.type() == CV_8UC3)
+    {
+        cv::cvtColor(inputMat, inputMat, CV_RGB2BGRA);
+    }
+    if (inputMat.type() != CV_8UC4 || inputMat.size().area() == 0)
+    {
+        std::cerr << "Invalid input image format. Generate other" << std::endl;
+        inputMat.create(cv::Size(WIDTH, HEIGHT), CV_8UC4);
+        inputMat.setTo(cv::Scalar(0, 0, 255, 255));
+        bgColor[0] = -128; bgColor[1] = -128; bgColor[2] = 127; bgColor[3] = -128;
+    }
+    if (inputMat.size().width != WIDTH || inputMat.size().height != HEIGHT)
+    {
+        cv::resize(inputMat, inputMat, cv::Size(WIDTH, HEIGHT));
+    }
+    String deviceName = cv::ocl::useOpenCL() ? cv::ocl::Context2::getDefault().device(0).name() : "No OpenCL device";
+    cv::Scalar color(64, 255, 64, 255);
+    cv::putText(inputMat,
+            cv::format("OpenCL Device name: %s", deviceName.c_str()),
+            cv::Point(8,32), fontFace, 1, color);
+    cv::putText(inputMat, WINDOW_NAME, cv::Point(50, HEIGHT - 32), fontFace, 1, color);
+    cv::putText(inputMat, USAGE_DESCRIPTION_0, cv::Point(30, 128), fontFace, 1, color);
+    cv::putText(inputMat, USAGE_DESCRIPTION_1, cv::Point(30, 192), fontFace, 1, color);
+    cv::putText(inputMat, USAGE_DESCRIPTION_2, cv::Point(30, 256), fontFace, 1, color);
+    cv::putText(inputMat, USAGE_DESCRIPTION_3, cv::Point(30, 320), fontFace, 1, color);
+    cv::putText(inputMat, USAGE_DESCRIPTION_SPACE, cv::Point(30, 448), fontFace, 1, color);
+
+#if defined(USE_D3D9) || defined (USE_D3DEX)
+    cv::cvtColor(inputMat, inputMat, CV_RGBA2BGRA);
+    std::swap(bgColor[0], bgColor[2]);
+#endif
+
+    // Make a global copy
+    ::inputMat = new cv::Mat(inputMat);
+
+    return inputMat;
+}
+
+static int mainLoop()
+{
+    hInstance = GetModuleHandle(NULL);
+
+    if (!initWindow())
+        CV_Error(cv::Error::StsError, "Can't create window");
+
+    if (!initDirect3D())
+        CV_Error(cv::Error::StsError, "Can't create D3D object");
+
+    if (cv::ocl::haveOpenCL())
+    {
+#if defined(USE_D3D9)
+        cv::ocl::Context2& ctx = cv::directx::ocl::initializeContextFromDirect3DDevice9(dev);
+#elif defined (USE_D3DEX)
+        cv::ocl::Context2& ctx = cv::directx::ocl::initializeContextFromDirect3DDevice9Ex(dev);
+#elif defined(USE_D3D10)
+        cv::ocl::Context2& ctx = cv::directx::ocl::initializeContextFromD3D10Device(dev);
+#elif defined(USE_D3D11)
+        cv::ocl::Context2& ctx = cv::directx::ocl::initializeContextFromD3D11Device(dev);
+#else
+#error "Invalid USE_D3D value"
+#endif
+        std::cout << "Selected device: " << ctx.device(0).name().c_str() << std::endl;
+        g_sampleType = 2;
+    }
+    else
+    {
+        std::cerr << "OpenCL is not available. DirectX - OpenCL interop will not work" << std::endl;
+    }
+
+    if (!initDirect3DTextures())
+        CV_Error(cv::Error::StsError, "Can't create D3D texture object");
+
+    MSG msg;
+    ZeroMemory(&msg, sizeof(msg));
+
+    while (msg.message != WM_QUIT)
+    {
+        if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
+        {
+            TranslateMessage(&msg);
+            DispatchMessage(&msg);
+        }
+        else
+        {
+            render();
+        }
+    }
+
+    cleanUp();
+
+    return static_cast<int>(msg.wParam);
+}
+
+int main(int /*argc*/, char ** /*argv*/)
+{
+    try
+    {
+        return mainLoop();
+    }
+    catch (cv::Exception& e)
+    {
+        std::cerr << "Exception: " << e.what() << std::endl;
+        return 10;
+    }
+    catch (...)
+    {
+        std::cerr << "FATAL ERROR: Unknown exception" << std::endl;
+        return 11;
+    }
+}
index ba5e364..c267dd4 100644 (file)
@@ -62,7 +62,7 @@ int main(int argc, char* argv[])
     cout << "FOUND " << keypoints2GPU.cols << " keypoints on second image" << endl;
 
     // matching descriptors
-    BFMatcher_CUDA matcher(NORM_L2);
+    BFMatcher_CUDA matcher(surf.defaultNorm());
     GpuMat trainIdx, distance;
     matcher.matchSingle(descriptors1GPU, descriptors2GPU, trainIdx, distance);
 
diff --git a/samples/java/clojure/simple-sample/.gitignore b/samples/java/clojure/simple-sample/.gitignore
new file mode 100644 (file)
index 0000000..e04714b
--- /dev/null
@@ -0,0 +1,9 @@
+/target
+/classes
+/checkouts
+pom.xml
+pom.xml.asc
+*.jar
+*.class
+/.lein-*
+/.nrepl-port
diff --git a/samples/java/clojure/simple-sample/project.clj b/samples/java/clojure/simple-sample/project.clj
new file mode 100644 (file)
index 0000000..2702b81
--- /dev/null
@@ -0,0 +1,14 @@
+(defproject simple-sample "0.1.0-SNAPSHOT"
+  :pom-addition [:developers [:developer {:id "magomimmo"}
+                              [:name "Mimmo Cosenza"]
+                              [:url "https://github.com/magomimmoo"]]]
+
+  :description "A simple project to start REPLing with OpenCV"
+  :url "http://example.com/FIXME"
+  :license {:name "BSD 3-Clause License"
+            :url "http://opensource.org/licenses/BSD-3-Clause"}
+  :dependencies [[org.clojure/clojure "1.5.1"]
+                 [opencv/opencv "2.4.7"]
+                 [opencv/opencv-native "2.4.7"]]
+  :main simple-sample.core
+  :injections [(clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)])
diff --git a/samples/java/clojure/simple-sample/resources/images/lena.png b/samples/java/clojure/simple-sample/resources/images/lena.png
new file mode 100644 (file)
index 0000000..68342fa
Binary files /dev/null and b/samples/java/clojure/simple-sample/resources/images/lena.png differ
diff --git a/samples/java/clojure/simple-sample/src/simple_sample/core.clj b/samples/java/clojure/simple-sample/src/simple_sample/core.clj
new file mode 100644 (file)
index 0000000..86a1b31
--- /dev/null
@@ -0,0 +1,16 @@
+;;; to run this code from the terminal: "$ lein run". It will save a
+;;; blurred image version of resources/images/lena.png as
+;;; resources/images/blurred.png
+
+(ns simple-sample.core
+  (:import [org.opencv.core Point Rect Mat CvType Size Scalar]
+           org.opencv.highgui.Highgui
+           org.opencv.imgproc.Imgproc))
+
+(defn -main [& args]
+  (let [lena (Highgui/imread "resources/images/lena.png")
+        blurred (Mat. 512 512 CvType/CV_8UC3)]
+    (print "Blurring...")
+    (Imgproc/GaussianBlur lena blurred (Size. 5 5) 3 3)
+    (Highgui/imwrite "resources/images/blurred.png" blurred)
+    (println "done!")))
diff --git a/samples/java/clojure/simple-sample/test/simple_sample/core_test.clj b/samples/java/clojure/simple-sample/test/simple_sample/core_test.clj
new file mode 100644 (file)
index 0000000..d84585e
--- /dev/null
@@ -0,0 +1,7 @@
+(ns simple-sample.core-test
+  (:require [clojure.test :refer :all]
+            [simple-sample.core :refer :all]))
+
+(deftest a-test
+  (testing "FIXME, I fail."
+    (is (= 0 1))))