Merge branch 'master' into cuda-dev

This commit is contained in:
Vladislav Vinogradov
2012-12-24 13:48:33 +04:00
66 changed files with 3506 additions and 1452 deletions

View File

@@ -459,7 +459,7 @@ if(BUILD_EXAMPLES OR BUILD_ANDROID_EXAMPLES OR INSTALL_PYTHON_EXAMPLES)
add_subdirectory(samples) add_subdirectory(samples)
endif() endif()
if(BUILD_ANDROID_SERVICE) if(ANDROID)
add_subdirectory(android/service) add_subdirectory(android/service)
endif() endif()

View File

@@ -280,6 +280,9 @@
# - November 2012 # - November 2012
# [+] updated for NDK r8c # [+] updated for NDK r8c
# [+] added support for clang compiler # [+] added support for clang compiler
# - December 2012
# [~] fixed ccache full path search
# [+] updated for NDK r8d
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
cmake_minimum_required( VERSION 2.6.3 ) cmake_minimum_required( VERSION 2.6.3 )
@@ -302,7 +305,7 @@ set( CMAKE_SYSTEM_VERSION 1 )
# rpath makes low sence for Android # rpath makes low sence for Android
set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." )
set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS) if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS)
if( CMAKE_HOST_WIN32 ) if( CMAKE_HOST_WIN32 )
file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS )
@@ -962,7 +965,11 @@ if( BUILD_WITH_ANDROID_NDK )
set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" ) set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" )
set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" ) set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" )
elseif( ANDROID_STL MATCHES "stlport" ) elseif( ANDROID_STL MATCHES "stlport" )
set( ANDROID_EXCEPTIONS OFF ) if( NOT ANDROID_NDK_RELEASE STRLESS "r8d" )
set( ANDROID_EXCEPTIONS ON )
else()
set( ANDROID_EXCEPTIONS OFF )
endif()
if( ANDROID_NDK_RELEASE STRLESS "r7" ) if( ANDROID_NDK_RELEASE STRLESS "r7" )
set( ANDROID_RTTI OFF ) set( ANDROID_RTTI OFF )
else() else()
@@ -974,7 +981,13 @@ if( BUILD_WITH_ANDROID_NDK )
set( ANDROID_EXCEPTIONS ON ) set( ANDROID_EXCEPTIONS ON )
set( ANDROID_RTTI ON ) set( ANDROID_RTTI ON )
if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" )
# gnustl binary for 4.7 compiler is buggy :(
# TODO: look for right fix
set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" )
else()
set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
endif()
else() else()
set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" ) set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" )
endif() endif()
@@ -1031,6 +1044,9 @@ endif()
# ccache support # ccache support
__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE ) __INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE )
if( _ndk_ccache ) if( _ndk_ccache )
if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE )
unset( NDK_CCACHE CACHE )
endif()
find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary") find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary")
else() else()
unset( NDK_CCACHE CACHE ) unset( NDK_CCACHE CACHE )
@@ -1260,7 +1276,7 @@ endif()
if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" ) if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" )
if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE STRGREATER "r8b") AND (ARMEABI OR ARMEABI_V7A OR X86) ) if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE STRGREATER "r8b") AND (ARMEABI OR ARMEABI_V7A OR X86) )
set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" ) set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" )
elseif( ANDROID_NDK_RELEASE STREQUAL "r8c") elseif( ANDROID_NDK_RELEASE STRGREATER "r8b")
set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" ) set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" )
elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE ) elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE )
message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342 message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342
@@ -1520,7 +1536,7 @@ endif()
# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used # BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used
# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform # ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform
# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86" or "mips" depending on ANDROID_ABI # ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86" or "mips" depending on ANDROID_ABI
# ANDROID_NDK_RELEASE : one of r5, r5b, r5c, r6, r6b, r7, r7b, r7c, r8, r8b, r8c; set only for NDK # ANDROID_NDK_RELEASE : one of r5, r5b, r5c, r6, r6b, r7, r7b, r7c, r8, r8b, r8c, r8d; set only for NDK
# ANDROID_ARCH_NAME : "arm" or "x86" or "mips" depending on ANDROID_ABI # ANDROID_ARCH_NAME : "arm" or "x86" or "mips" depending on ANDROID_ABI
# ANDROID_SYSROOT : path to the compiler sysroot # ANDROID_SYSROOT : path to the compiler sysroot
# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform # TOOL_OS_SUFFIX : "" or ".exe" depending on host platform

View File

@@ -1,2 +1,6 @@
add_subdirectory(engine) if(BUILD_ANDROID_SERVICE)
#add_subdirectory(engine_test) add_subdirectory(engine)
#add_subdirectory(engine_test)
endif()
install(FILES "readme.txt" DESTINATION "apk/" COMPONENT main)

View File

@@ -1,22 +0,0 @@
***************
Package Content
***************
The package provides new OpenCV SDK that uses OpenCV Manager for library initialization. OpenCV Manager provides the following benefits:
* Less memory usage. All apps use the same binaries from service and do not keep native libs inside them self;
* Hardware specific optimizations for all supported platforms;
* Trusted OpenCV library source. All packages with OpenCV are published on Google Play service;
* Regular updates and bug fixes;
Package consists from Library Project for Java development with Eclipse, C++ headers and libraries for native application development, javadoc samples and prebuilt binaries for ARM and X86 platforms.
To try new SDK on serial device with Google Play just install sample package and follow application messages (Google Play service access will be needed).
TO start example on device without Google Play you need to install OpenCV manager package and OpenCV binary pack for your platform from apk folder before.
See docs/doc/tutorials/introduction/android_binary_package/android_binary_package.html and docs/android/refmain.html for details about service.
On-line documentation will be available at address: http://docs.opencv.org/trunk
********
Contacts
********
Please send all feedback to Alexander Smorkalov mailto: alexander.smorkalov@itseez.com

View File

@@ -1,6 +1,40 @@
*******************************************
Manager Workflow Manager Workflow
******************************************* ****************
.. _manager_selection:
OpenCV Manager selection
------------------------
Since version 1.7 several packages of OpenCV Manager is built. Every package includes OpenCV library
for package target platform. The internal library is used for most cases, except the rare one, when
arm-v7a without NEON instruction set processor is detected. In this case additional binary package
for arm-v7a is used. The new package selection logic in most cases simplifies OpenCV installation
on end user devices. In most cases OpenCV Manager may be installed automatically from Google Play.
For such case, when Google Play is not available, i.e. emulator, developer board, etc, you can
install it manually using adb tool.
.. code-block:: sh
:linenos:
adb install OpenCV-2.4.3-android-sdk/apk/OpenCV_2.4.3_Manager_2.0_<platform_name>.apk
Use table to determine right OpenCV Manager package:
+----------------------------+-----------------+-----------------------------------------------------+
| Hardware Platform | Android version | Package name |
+============================+=================+=====================================================+
| Intel x86 | >= 2.3 | OpenCV_2.4.3_Manager_2.0_x86.apk |
+----------------------------+-----------------+-----------------------------------------------------+
| MIPS | >= 2.3 | OpenCV_2.4.3_Manager_2.0_mips.apk |
+----------------------------+-----------------+-----------------------------------------------------+
| armeabi (arm-v5, arm-v6) | >= 2.3 | OpenCV_2.4.3_Manager_2.0_armeabi.apk |
+----------------------------+-----------------+-----------------------------------------------------+
| armeabi-v7a (arm-v7a-NEON) | >= 2.3 | OpenCV_2.4.3_Manager_2.0_armv7a-neon.apk |
+----------------------------+-----------------+-----------------------------------------------------+
| armeabi-v7a (arm-v7a-NEON) | 2.2 | OpenCV_2.4.3.1_Manager_2.3_armv7a-neon-android8.apk |
+----------------------------+-----------------+-----------------------------------------------------+
First application start First application start
----------------------- -----------------------
@@ -9,10 +43,10 @@ There is no OpenCV Manager or OpenCV libraries:
.. image:: img/NoService.png .. image:: img/NoService.png
Aditional library package installation Additional library package installation
-------------------------------------- ---------------------------------------
There is an OpenCV Manager service, but there is no apropriate OpenCV library. There is an OpenCV Manager service, but it does not contain appropriate OpenCV library.
If OpenCV library installation has been approved\: If OpenCV library installation has been approved\:
.. image:: img/LibInstallAproved.png .. image:: img/LibInstallAproved.png

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.opencv.engine" package="org.opencv.engine"
android:versionCode="23@ANDROID_PLATFORM_VERSION_CODE@" android:versionCode="24@ANDROID_PLATFORM_VERSION_CODE@"
android:versionName="2.3" > android:versionName="2.4" >
<uses-sdk android:minSdkVersion="@ANDROID_NATIVE_API_LEVEL@" /> <uses-sdk android:minSdkVersion="@ANDROID_NATIVE_API_LEVEL@" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/> <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>

View File

@@ -130,7 +130,7 @@ android::String16 OpenCVEngine::GetLibraryList(android::String16 version)
LOGD("Trying to load info library \"%s\"", tmp.c_str()); LOGD("Trying to load info library \"%s\"", tmp.c_str());
void* handle; void* handle;
const char* (*info_func)(); InfoFunctionType info_func;
handle = dlopen(tmp.c_str(), RTLD_LAZY); handle = dlopen(tmp.c_str(), RTLD_LAZY);
if (handle) if (handle)
@@ -138,7 +138,7 @@ android::String16 OpenCVEngine::GetLibraryList(android::String16 version)
const char* error; const char* error;
dlerror(); dlerror();
*(void **) (&info_func) = dlsym(handle, "GetLibraryList"); info_func = (InfoFunctionType)dlsym(handle, "GetLibraryList");
if ((error = dlerror()) == NULL) if ((error = dlerror()) == NULL)
{ {
result = String16((*info_func)()); result = String16((*info_func)());

View File

@@ -24,12 +24,12 @@ JNIEXPORT jlong JNICALL Java_org_opencv_engine_OpenCVLibraryInfo_open
JNIEXPORT jstring JNICALL Java_org_opencv_engine_OpenCVLibraryInfo_getPackageName JNIEXPORT jstring JNICALL Java_org_opencv_engine_OpenCVLibraryInfo_getPackageName
(JNIEnv* env, jobject, jlong handle) (JNIEnv* env, jobject, jlong handle)
{ {
const char* (*info_func)(); InfoFunctionType info_func;
const char* result; const char* result;
const char* error; const char* error;
dlerror(); dlerror();
*(void **) (&info_func) = dlsym((void*)handle, "GetPackageName"); info_func = (InfoFunctionType)dlsym((void*)handle, "GetPackageName");
if ((error = dlerror()) == NULL) if ((error = dlerror()) == NULL)
result = (*info_func)(); result = (*info_func)();
else else
@@ -44,12 +44,12 @@ JNIEXPORT jstring JNICALL Java_org_opencv_engine_OpenCVLibraryInfo_getPackageNam
JNIEXPORT jstring JNICALL Java_org_opencv_engine_OpenCVLibraryInfo_getLibraryList JNIEXPORT jstring JNICALL Java_org_opencv_engine_OpenCVLibraryInfo_getLibraryList
(JNIEnv* env, jobject, jlong handle) (JNIEnv* env, jobject, jlong handle)
{ {
const char* (*info_func)(); InfoFunctionType info_func;
const char* result; const char* result;
const char* error; const char* error;
dlerror(); dlerror();
*(void **) (&info_func) = dlsym((void*)handle, "GetLibraryList"); info_func = (InfoFunctionType)dlsym((void*)handle, "GetLibraryList");
if ((error = dlerror()) == NULL) if ((error = dlerror()) == NULL)
result = (*info_func)(); result = (*info_func)();
else else
@@ -64,12 +64,12 @@ JNIEXPORT jstring JNICALL Java_org_opencv_engine_OpenCVLibraryInfo_getLibraryLis
JNIEXPORT jstring JNICALL Java_org_opencv_engine_OpenCVLibraryInfo_getVersionName JNIEXPORT jstring JNICALL Java_org_opencv_engine_OpenCVLibraryInfo_getVersionName
(JNIEnv* env, jobject, jlong handle) (JNIEnv* env, jobject, jlong handle)
{ {
const char* (*info_func)(); InfoFunctionType info_func;
const char* result; const char* result;
const char* error; const char* error;
dlerror(); dlerror();
*(void **) (&info_func) = dlsym((void*)handle, "GetRevision"); info_func = (InfoFunctionType)dlsym((void*)handle, "GetRevision");
if ((error = dlerror()) == NULL) if ((error = dlerror()) == NULL)
result = (*info_func)(); result = (*info_func)();
else else

View File

@@ -134,7 +134,7 @@ bool CommonPackageManager::IsVersionCompatible(const std::string& target_version
// major version is the same and minor package version is above or the same as target. // major version is the same and minor package version is above or the same as target.
if ((package_version[0] == target_version[0]) && (package_version[1] == target_version[1]) && (package_version[2] >= target_version[2])) if ((package_version[0] == target_version[0]) && (package_version[1] == target_version[1]) && (package_version[2] >= target_version[2]))
{ {
result = true; result = true;
} }
return result; return result;
@@ -144,13 +144,21 @@ int CommonPackageManager::GetHardwareRating(int platform, int cpu_id, const std:
{ {
int result = -1; int result = -1;
for (size_t i = 0; i < group.size(); i++) if ((cpu_id & ARCH_X86) || (cpu_id & ARCH_X64) || (cpu_id & ARCH_MIPS))
// Note: No raiting for x86, x64 and MIPS
// only one package is used
result = 0;
else
{ {
if (group[i] == std::pair<int, int>(platform, cpu_id)) // Calculate rating for Arm
{ for (size_t i = 0; i < group.size(); i++)
result = i; {
break; if (group[i] == std::pair<int, int>(platform, cpu_id))
} {
result = i;
break;
}
}
} }
return result; return result;

View File

@@ -342,8 +342,8 @@ InstallPath(install_path)
LOGD("Trying to load info library \"%s\"", tmp.c_str()); LOGD("Trying to load info library \"%s\"", tmp.c_str());
void* handle; void* handle;
const char* (*name_func)(); InfoFunctionType name_func;
const char* (*revision_func)(); InfoFunctionType revision_func;
handle = dlopen(tmp.c_str(), RTLD_LAZY); handle = dlopen(tmp.c_str(), RTLD_LAZY);
if (handle) if (handle)
@@ -351,8 +351,8 @@ InstallPath(install_path)
const char* error; const char* error;
dlerror(); dlerror();
*(void **) (&name_func) = dlsym(handle, "GetPackageName"); name_func = (InfoFunctionType)dlsym(handle, "GetPackageName");
*(void **) (&revision_func) = dlsym(handle, "GetRevision"); revision_func = (InfoFunctionType)dlsym(handle, "GetRevision");
error = dlerror(); error = dlerror();
if (!error && revision_func && name_func) if (!error && revision_func && name_func)

View File

@@ -17,4 +17,6 @@
// Class name of OpenCV engine binder object. Is needned for connection to service // Class name of OpenCV engine binder object. Is needned for connection to service
#define OPECV_ENGINE_CLASSNAME "org.opencv.engine.OpenCVEngineInterface" #define OPECV_ENGINE_CLASSNAME "org.opencv.engine.OpenCVEngineInterface"
typedef const char* (*InfoFunctionType)();
#endif #endif

View File

@@ -358,6 +358,8 @@ public class ManagerActivity extends Activity
else else
{ {
temp.put("Activity", "n"); temp.put("Activity", "n");
if (!PublicName.equals("Built-in OpenCV library"))
Tags = "safe to remove";
} }
} }
else else

View File

@@ -0,0 +1,28 @@
OpenCV Manager selection
========================
Since version 1.7 several packages of OpenCV Manager is built. Every package includes OpenCV library
for package target platform. The internal library is used for most cases, except the rare one, when
arm-v7a without NEON instruction set processor is detected. In this case additional binary package
for arm-v7a is used. The new package selection logic in most cases simplifies OpenCV installation
on end user devices. In most cases OpenCV Manager may be installed automatically from Google Play.
For such case, when Google Play is not available, i.e. emulator, developer board, etc, you can
install it manually using adb tool:
adb install OpenCV-2.4.3-android-sdk/apk/OpenCV_2.4.3.2_Manager_2.4_<platform_name>.apk
Use table to determine right OpenCV Manager package:
+----------------------------+-----------------+-----------------------------------------------------+
| Hardware Platform | Android version | Package name |
+============================+=================+=====================================================+
| Intel x86 | >= 2.3 | OpenCV_2.4.3.2_Manager_2.4_x86.apk |
+----------------------------+-----------------+-----------------------------------------------------+
| MIPS | >= 2.3 | OpenCV_2.4.3.2_Manager_2.4_mips.apk |
+----------------------------+-----------------+-----------------------------------------------------+
| armeabi (arm-v5, arm-v6) | >= 2.3 | OpenCV_2.4.3.2_Manager_2.4_armeabi.apk |
+----------------------------+-----------------+-----------------------------------------------------+
| armeabi-v7a (arm-v7a-NEON) | >= 2.3 | OpenCV_2.4.3.2_Manager_2.4_armv7a-neon.apk |
+----------------------------+-----------------+-----------------------------------------------------+
| armeabi-v7a (arm-v7a-NEON) | 2.2 | OpenCV_2.4.3.2_Manager_2.4_armv7a-neon-android8.apk |
+----------------------------+-----------------+-----------------------------------------------------+

View File

@@ -61,7 +61,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
add_extra_compiler_option(-W) add_extra_compiler_option(-W)
add_extra_compiler_option(-Wall) add_extra_compiler_option(-Wall)
add_extra_compiler_option(-Werror=return-type) add_extra_compiler_option(-Werror=return-type)
#add_extra_compiler_option(-Werror=non-virtual-dtor) add_extra_compiler_option(-Werror=non-virtual-dtor)
add_extra_compiler_option(-Werror=address) add_extra_compiler_option(-Werror=address)
add_extra_compiler_option(-Werror=sequence-point) add_extra_compiler_option(-Werror=sequence-point)
add_extra_compiler_option(-Wformat) add_extra_compiler_option(-Wformat)

View File

@@ -19,7 +19,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX)
ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion
OUTPUT_VARIABLE gcc_compiler_version) OUTPUT_VARIABLE gcc_compiler_version)
#MESSAGE("GCC Version: ${gcc_compiler_version}") #MESSAGE("GCC Version: ${gcc_compiler_version}")
IF(gcc_compiler_version MATCHES "4\\.[0,2-9]\\.[0-9x]") IF(gcc_compiler_version VERSION_GREATER "4.2.-1")
SET(PCHSupport_FOUND TRUE) SET(PCHSupport_FOUND TRUE)
ENDIF() ENDIF()

View File

@@ -2,8 +2,6 @@
# CMake file for OpenCV docs # CMake file for OpenCV docs
# #
file(GLOB FILES_DOC *.htm *.txt *.jpg *.png *.pdf)
file(GLOB FILES_DOC_VS vidsurv/*.doc)
file(GLOB FILES_TEX *.tex *.sty *.bib) file(GLOB FILES_TEX *.tex *.sty *.bib)
file(GLOB FILES_TEX_PICS pics/*.png pics/*.jpg) file(GLOB FILES_TEX_PICS pics/*.png pics/*.jpg)
@@ -11,6 +9,14 @@ if(BUILD_DOCS AND HAVE_SPHINX)
project(opencv_docs) project(opencv_docs)
set(DOC_LIST "${OpenCV_SOURCE_DIR}/doc/opencv-logo.png" "${OpenCV_SOURCE_DIR}/doc/opencv-logo2.png"
"${OpenCV_SOURCE_DIR}/doc/opencv-logo-white.png" "${OpenCV_SOURCE_DIR}/doc/opencv.ico"
"${OpenCV_SOURCE_DIR}/doc/haartraining.htm" "${OpenCV_SOURCE_DIR}/doc/license.txt"
"${OpenCV_SOURCE_DIR}/doc/pattern.png" "${OpenCV_SOURCE_DIR}/doc/acircles_pattern.png")
set(OPTIONAL_DOC_LIST "")
set(OPENCV2_BASE_MODULES core imgproc highgui video calib3d features2d objdetect ml flann gpu photo stitching nonfree contrib legacy) set(OPENCV2_BASE_MODULES core imgproc highgui video calib3d features2d objdetect ml flann gpu photo stitching nonfree contrib legacy)
# build lists of modules to be documented # build lists of modules to be documented
@@ -81,6 +87,9 @@ if(BUILD_DOCS AND HAVE_SPHINX)
COMMENT "Generating the PDF Manuals" COMMENT "Generating the PDF Manuals"
) )
LIST(APPEND OPTIONAL_DOC_LIST "${CMAKE_BINARY_DIR}/doc/opencv2refman.pdf" "${CMAKE_BINARY_DIR}/doc/opencv2manager.pdf"
"${CMAKE_BINARY_DIR}/doc/opencv_user.pdf" "${CMAKE_BINARY_DIR}/doc/opencv_tutorials.pdf" "${CMAKE_BINARY_DIR}/doc/opencv_cheatsheet.pdf")
if(ENABLE_SOLUTION_FOLDERS) if(ENABLE_SOLUTION_FOLDERS)
set_target_properties(docs PROPERTIES FOLDER "documentation") set_target_properties(docs PROPERTIES FOLDER "documentation")
endif() endif()
@@ -97,7 +106,13 @@ if(BUILD_DOCS AND HAVE_SPHINX)
if(ENABLE_SOLUTION_FOLDERS) if(ENABLE_SOLUTION_FOLDERS)
set_target_properties(html_docs PROPERTIES FOLDER "documentation") set_target_properties(html_docs PROPERTIES FOLDER "documentation")
endif() endif()
endif()
install(FILES ${FILES_DOC} DESTINATION "${OPENCV_DOC_INSTALL_PATH}" COMPONENT main) foreach(f ${DOC_LIST})
install(FILES ${FILES_DOC_VS} DESTINATION "${OPENCV_DOC_INSTALL_PATH}/vidsurv" COMPONENT main) install(FILES "${f}" DESTINATION "${OPENCV_DOC_INSTALL_PATH}" COMPONENT main)
endforeach()
foreach(f ${OPTIONAL_DOC_LIST})
install(FILES "${f}" DESTINATION "${OPENCV_DOC_INSTALL_PATH}" OPTIONAL)
endforeach()
endif()

View File

@@ -85,7 +85,7 @@ This tutorial code's is shown lines below. You can also download it from `here <
for( int i = 0; i < contours.size(); i++ ) for( int i = 0; i < contours.size(); i++ )
{ approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true ); { approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
boundRect[i] = boundingRect( Mat(contours_poly[i]) ); boundRect[i] = boundingRect( Mat(contours_poly[i]) );
minEnclosingCircle( contours_poly[i], center[i], radius[i] ); minEnclosingCircle( (Mat)contours_poly[i], center[i], radius[i] );
} }

View File

@@ -50,8 +50,8 @@ The structure of package contents looks as follows:
OpenCV-2.4.3-android-sdk OpenCV-2.4.3-android-sdk
|_ apk |_ apk
| |_ OpenCV_2.4.3_binary_pack_XXX.apk | |_ OpenCV_2.4.3_binary_pack_armv7a.apk
| |_ OpenCV_2.4.3_Manager.apk | |_ OpenCV_2.4.3_Manager_2.0_XXX.apk
| |
|_ doc |_ doc
|_ samples |_ samples
@@ -85,8 +85,8 @@ The structure of package contents looks as follows:
On production devices that have access to Google Play Market (and Internet) these packages will be On production devices that have access to Google Play Market (and Internet) these packages will be
installed from Market on the first start of an application using OpenCV Manager API. installed from Market on the first start of an application using OpenCV Manager API.
But devkits without Market or Internet connection require this packages to be installed manually. But devkits without Market or Internet connection require this packages to be installed manually.
Install the `Manager.apk` and the corresponding `binary_pack.apk` depending on the device CPU, Install the `Manager.apk` and optional `binary_pack.apk` if it needed.
the Manager GUI provides this info. Below you'll see exact commands on how to do this. See :ref:`manager_selection` for details.
.. note:: Installation from Internet is the preferable way since OpenCV team may publish updated .. note:: Installation from Internet is the preferable way since OpenCV team may publish updated
versions of this packages on the Market. versions of this packages on the Market.
@@ -280,21 +280,7 @@ Well, running samples from Eclipse is very simple:
To get rid of the message you will need to install `OpenCV Manager` and the appropriate `OpenCV binary pack`. To get rid of the message you will need to install `OpenCV Manager` and the appropriate `OpenCV binary pack`.
Simply tap :menuselection:`Yes` if you have *Google Play Market* installed on your device/emulator. It will redirect you to the corresponding page on *Google Play Market*. Simply tap :menuselection:`Yes` if you have *Google Play Market* installed on your device/emulator. It will redirect you to the corresponding page on *Google Play Market*.
If you have no access to the *Market*, which is often the case with emulators - you will need to install the packages from OpenCV4Android SDK folder manually. Open the console/terminal and type in the following two commands: If you have no access to the *Market*, which is often the case with emulators - you will need to install the packages from OpenCV4Android SDK folder manually. See :ref:`manager_selection` for details.
.. code-block:: sh
:linenos:
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.3_Manager.apk
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.3_binary_pack_armv7a.apk
If you're running Windows, that will probably look like this:
.. image:: images/install_opencv_manager_with_adb.png
:alt: Run these commands in the console to install OpenCV Manager
:align: center
When done, you will be able to run OpenCV samples on your device/emulator seamlessly.
* Here is ``Tutorial 2 - Use OpenCV Camera`` sample, running on top of stock camera-preview of the emulator. * Here is ``Tutorial 2 - Use OpenCV Camera`` sample, running on top of stock camera-preview of the emulator.

View File

@@ -54,20 +54,8 @@ Using async initialization is a **recommended** way for application development.
:alt: Add dependency from OpenCV library :alt: Add dependency from OpenCV library
:align: center :align: center
To run OpenCV Manager-based application for the first time you need to install package with the `OpenCV Manager` for your platform. Armeabi, Armeabi-v7a with NEON, x86 and MIPS achitectures supported. In most cases OpenCV Manager may be installed automatically from Google Play. For such case, when Google Play is not available, i.e. emulator, developer board, etc, you can
You can do it using Google Play Market or manually with ``adb`` tool: install it manually using adb tool. See :ref:`manager_selection` for details.
.. code-block:: sh
:linenos:
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.3_Manager.apk
For rare cases if NEON instruction set is not supported you need to install aditional OpenCV Library package:
.. code-block:: sh
:linenos:
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.3_binary_pack_armv7a.apk
There is a very base code snippet implementing the async initialization. It shows basic principles. See the "15-puzzle" OpenCV sample for details. There is a very base code snippet implementing the async initialization. It shows basic principles. See the "15-puzzle" OpenCV sample for details.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -71,7 +71,9 @@ There are functions in OpenCV, especially from calib3d module, such as ``project
//... fill the array //... fill the array
Mat pointsMat = Mat(points); Mat pointsMat = Mat(points);
One can access a point in this matrix using the same method \texttt{Mat::at}: :: One can access a point in this matrix using the same method ``Mat::at`` :
::
Point2f point = pointsMat.at<Point2f>(i, 0); Point2f point = pointsMat.at<Point2f>(i, 0);
@@ -109,7 +111,7 @@ Selecting a region of interest: ::
Rect r(10, 10, 100, 100); Rect r(10, 10, 100, 100);
Mat smallImg = img(r); Mat smallImg = img(r);
A convertion from \texttt{Mat} to C API data structures: :: A convertion from ``Mat`` to C API data structures: ::
Mat img = imread("image.jpg"); Mat img = imread("image.jpg");
IplImage img1 = img; IplImage img1 = img;
@@ -150,7 +152,7 @@ A call to ``waitKey()`` starts a message passing cycle that waits for a key stro
double minVal, maxVal; double minVal, maxVal;
minMaxLoc(sobelx, &minVal, &maxVal); //find minimum and maximum intensities minMaxLoc(sobelx, &minVal, &maxVal); //find minimum and maximum intensities
Mat draw; Mat draw;
sobelx.convertTo(draw, CV_8U, 255.0/(maxVal - minVal), -minVal); sobelx.convertTo(draw, CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal));
namedWindow("image", CV_WINDOW_AUTOSIZE); namedWindow("image", CV_WINDOW_AUTOSIZE);
imshow("image", draw); imshow("image", draw);

View File

@@ -16,7 +16,7 @@ typedef perf::TestBaseWithParam<int> PointsNum;
PERF_TEST_P(PointsNum_Algo, solvePnP, PERF_TEST_P(PointsNum_Algo, solvePnP,
testing::Combine( testing::Combine(
testing::Values(4, 3*9, 7*13), testing::Values(/*4,*/ 3*9, 7*13), //TODO: find why results on 4 points are too unstable
testing::Values((int)CV_ITERATIVE, (int)CV_EPNP) testing::Values((int)CV_ITERATIVE, (int)CV_EPNP)
) )
) )

View File

@@ -109,13 +109,6 @@ template<typename _Tp> class CV_EXPORTS MatIterator_;
template<typename _Tp> class CV_EXPORTS MatConstIterator_; template<typename _Tp> class CV_EXPORTS MatConstIterator_;
template<typename _Tp> class CV_EXPORTS MatCommaInitializer_; template<typename _Tp> class CV_EXPORTS MatCommaInitializer_;
#if !defined(ANDROID) || (defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_WCHAR_T)
typedef std::basic_string<wchar_t> WString;
CV_EXPORTS string fromUtf16(const WString& str);
CV_EXPORTS WString toUtf16(const string& str);
#endif
CV_EXPORTS string format( const char* fmt, ... ); CV_EXPORTS string format( const char* fmt, ... );
CV_EXPORTS string tempfile( const char* suffix CV_DEFAULT(0)); CV_EXPORTS string tempfile( const char* suffix CV_DEFAULT(0));
@@ -1284,6 +1277,8 @@ public:
operator _Tp* (); operator _Tp* ();
operator const _Tp*() const; operator const _Tp*() const;
bool operator==(const Ptr<_Tp>& ptr) const;
_Tp* obj; //< the object pointer. _Tp* obj; //< the object pointer.
int* refcount; //< the associated reference counter int* refcount; //< the associated reference counter
}; };
@@ -1345,7 +1340,7 @@ public:
virtual int channels(int i=-1) const; virtual int channels(int i=-1) const;
virtual bool empty() const; virtual bool empty() const;
/*virtual*/ ~_InputArray(); virtual ~_InputArray();
int flags; int flags;
void* obj; void* obj;
@@ -1413,7 +1408,7 @@ public:
virtual void release() const; virtual void release() const;
virtual void clear() const; virtual void clear() const;
/*virtual*/ ~_OutputArray(); virtual ~_OutputArray();
}; };
typedef const _InputArray& InputArray; typedef const _InputArray& InputArray;

View File

@@ -64,7 +64,7 @@
#endif #endif
#elif __GNUC__*10 + __GNUC_MINOR__ >= 42 #elif __GNUC__*10 + __GNUC_MINOR__ >= 42
#if !defined WIN32 && (defined __i486__ || defined __i586__ || \ #if !(defined WIN32 || defined _WIN32) && (defined __i486__ || defined __i586__ || \
defined __i686__ || defined __MMX__ || defined __SSE__ || defined __ppc__) defined __i686__ || defined __MMX__ || defined __SSE__ || defined __ppc__)
#define CV_XADD __sync_fetch_and_add #define CV_XADD __sync_fetch_and_add
#else #else
@@ -2690,6 +2690,11 @@ template<typename _Tp> template<typename _Tp2> inline const Ptr<_Tp2> Ptr<_Tp>::
return p; return p;
} }
template<typename _Tp> inline bool Ptr<_Tp>::operator==(const Ptr<_Tp>& _ptr) const
{
return refcount == _ptr.refcount;
}
//// specializied implementations of Ptr::delete_obj() for classic OpenCV types //// specializied implementations of Ptr::delete_obj() for classic OpenCV types
template<> CV_EXPORTS void Ptr<CvMat>::delete_obj(); template<> CV_EXPORTS void Ptr<CvMat>::delete_obj();

View File

@@ -45,7 +45,6 @@
#include <ctype.h> #include <ctype.h>
#include <deque> #include <deque>
#include <iterator> #include <iterator>
#include <wchar.h>
#define USE_ZLIB 1 #define USE_ZLIB 1
@@ -156,35 +155,6 @@ cv::string cv::FileStorage::getDefaultObjectName(const string& _filename)
return cv::string(name); return cv::string(name);
} }
namespace cv
{
#if !defined(ANDROID) || (defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_WCHAR_T)
string fromUtf16(const WString& str)
{
cv::AutoBuffer<char> _buf(str.size()*4 + 1);
char* buf = _buf;
size_t sz = wcstombs(buf, str.c_str(), str.size());
if( sz == (size_t)-1 )
return string();
buf[sz] = '\0';
return string(buf);
}
WString toUtf16(const string& str)
{
cv::AutoBuffer<wchar_t> _buf(str.size() + 1);
wchar_t* buf = _buf;
size_t sz = mbstowcs(buf, str.c_str(), str.size());
if( sz == (size_t)-1 )
return WString();
buf[sz] = '\0';
return WString(buf);
}
#endif
}
typedef struct CvGenericHash typedef struct CvGenericHash
{ {
CV_SET_FIELDS() CV_SET_FIELDS()
@@ -5200,6 +5170,7 @@ void FileStorage::release()
string FileStorage::releaseAndGetString() string FileStorage::releaseAndGetString()
{ {
string buf; string buf;
buf.reserve(16); // HACK: Work around for compiler bug
if( fs.obj && fs.obj->outbuf ) if( fs.obj && fs.obj->outbuf )
icvClose(fs.obj, &buf); icvClose(fs.obj, &buf);

View File

@@ -359,26 +359,24 @@ string format( const char* fmt, ... )
string tempfile( const char* suffix ) string tempfile( const char* suffix )
{ {
const char *temp_dir = getenv("OPENCV_TEMP_PATH");
string fname;
#if defined WIN32 || defined _WIN32 #if defined WIN32 || defined _WIN32
char temp_dir[MAX_PATH + 1] = { 0 }; char temp_dir2[MAX_PATH + 1] = { 0 };
char temp_file[MAX_PATH + 1] = { 0 }; char temp_file[MAX_PATH + 1] = { 0 };
::GetTempPathA(sizeof(temp_dir), temp_dir); if (temp_dir == 0 || temp_dir[0] == 0)
{
::GetTempPathA(sizeof(temp_dir2), temp_dir2);
temp_dir = temp_dir2;
}
if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file)) if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
return string(); return string();
DeleteFileA(temp_file); DeleteFileA(temp_file);
string name = temp_file; fname = temp_file;
if(suffix)
{
if (suffix[0] != '.')
return name + "." + suffix;
else
return name + suffix;
}
else
return name;
# else # else
# ifdef ANDROID # ifdef ANDROID
//char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX"; //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
@@ -387,9 +385,7 @@ string tempfile( const char* suffix )
char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX"; char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
# endif # endif
string fname; if (temp_dir == 0 || temp_dir[0] == 0)
const char *temp_dir = getenv("OPENCV_TEMP_PATH");
if(temp_dir == 0 || temp_dir[0] == 0)
fname = defaultTemplate; fname = defaultTemplate;
else else
{ {
@@ -401,19 +397,20 @@ string tempfile( const char* suffix )
} }
const int fd = mkstemp((char*)fname.c_str()); const int fd = mkstemp((char*)fname.c_str());
if(fd == -1) return ""; if (fd == -1) return string();
close(fd); close(fd);
remove(fname.c_str()); remove(fname.c_str());
# endif
if(suffix) if (suffix)
{ {
if (suffix[0] != '.') if (suffix[0] != '.')
fname = fname + "." + suffix; return fname + "." + suffix;
else else
fname += suffix; return fname + suffix;
} }
return fname; return fname;
# endif
} }
static CvErrorCallback customErrorCallback = 0; static CvErrorCallback customErrorCallback = 0;

View File

@@ -31,7 +31,7 @@ PERF_TEST_P(fast, detect, testing::Combine(
declare.in(frame); declare.in(frame);
Ptr<FeatureDetector> fd = Algorithm::create<FeatureDetector>("Feature2D.FAST"); Ptr<FeatureDetector> fd = Algorithm::create<FeatureDetector>("Feature2D.FAST");
ASSERT_FALSE( fd == 0 ); ASSERT_FALSE( fd.empty() );
fd->set("threshold", 20); fd->set("threshold", 20);
fd->set("nonmaxSuppression", true); fd->set("nonmaxSuppression", true);
fd->set("type", type); fd->set("type", type);

View File

@@ -531,7 +531,7 @@ void FlannBasedMatcher::train()
void FlannBasedMatcher::read( const FileNode& fn) void FlannBasedMatcher::read( const FileNode& fn)
{ {
if (indexParams == 0) if (indexParams.empty())
indexParams = new flann::IndexParams(); indexParams = new flann::IndexParams();
FileNode ip = fn["indexParams"]; FileNode ip = fn["indexParams"];
@@ -570,7 +570,7 @@ void FlannBasedMatcher::read( const FileNode& fn)
}; };
} }
if (searchParams == 0) if (searchParams.empty())
searchParams = new flann::SearchParams(); searchParams = new flann::SearchParams();
FileNode sp = fn["searchParams"]; FileNode sp = fn["searchParams"];

View File

@@ -23,7 +23,7 @@ PERF_TEST_P(VideoWriter_Writing, WriteFrame,
string filename = getDataPath(get<0>(GetParam())); string filename = getDataPath(get<0>(GetParam()));
bool isColor = get<1>(GetParam()); bool isColor = get<1>(GetParam());
VideoWriter writer("perf_writer.avi", CV_FOURCC('X', 'V', 'I', 'D'), 25, cv::Size(640, 480), isColor); VideoWriter writer(cv::tempfile(".avi"), CV_FOURCC('X', 'V', 'I', 'D'), 25, cv::Size(640, 480), isColor);
TEST_CYCLE() { Mat image = imread(filename, 1); writer << image; } TEST_CYCLE() { Mat image = imread(filename, 1); writer << image; }

View File

@@ -399,12 +399,12 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
gst_app_sink_set_max_buffers (GST_APP_SINK(sink), 1); gst_app_sink_set_max_buffers (GST_APP_SINK(sink), 1);
gst_app_sink_set_drop (GST_APP_SINK(sink), stream); gst_app_sink_set_drop (GST_APP_SINK(sink), stream);
caps = gst_caps_new_simple("video/x-raw-rgb",
gst_app_sink_set_caps(GST_APP_SINK(sink), gst_caps_new_simple("video/x-raw-rgb", "red_mask", G_TYPE_INT, 0x0000FF,
"red_mask", G_TYPE_INT, 0x0000FF, "green_mask", G_TYPE_INT, 0x00FF00,
"green_mask", G_TYPE_INT, 0x00FF00, "blue_mask", G_TYPE_INT, 0xFF0000,
"blue_mask", G_TYPE_INT, 0xFF0000, NULL);
NULL)); gst_app_sink_set_caps(GST_APP_SINK(sink), caps);
gst_caps_unref(caps); gst_caps_unref(caps);
if(gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_READY) == if(gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_READY) ==

View File

@@ -661,7 +661,7 @@ Applies a fixed-level threshold to each array element.
:param dst: output array of the same size and type as ``src``. :param dst: output array of the same size and type as ``src``.
:param thresh: treshold value. :param thresh: threshold value.
:param maxval: maximum value to use with the ``THRESH_BINARY`` and ``THRESH_BINARY_INV`` thresholding types. :param maxval: maximum value to use with the ``THRESH_BINARY`` and ``THRESH_BINARY_INV`` thresholding types.

View File

@@ -137,7 +137,7 @@ Finds contours in a binary image.
:param contours: Detected contours. Each contour is stored as a vector of points. :param contours: Detected contours. Each contour is stored as a vector of points.
:param hierarchy: Optional output vector containing information about the image topology. It has as many elements as the number of contours. For each contour ``contours[i]`` , the elements ``hierarchy[i][0]`` , ``hiearchy[i][1]`` , ``hiearchy[i][2]`` , and ``hiearchy[i][3]`` are set to 0-based indices in ``contours`` of the next and previous contours at the same hierarchical level: the first child contour and the parent contour, respectively. If for a contour ``i`` there are no next, previous, parent, or nested contours, the corresponding elements of ``hierarchy[i]`` will be negative. :param hierarchy: Optional output vector, containing information about the image topology. It has as many elements as the number of contours. For each i-th contour ``contours[i]`` , the elements ``hierarchy[i][0]`` , ``hiearchy[i][1]`` , ``hiearchy[i][2]`` , and ``hiearchy[i][3]`` are set to 0-based indices in ``contours`` of the next and previous contours at the same hierarchical level, the first child contour and the parent contour, respectively. If for the contour ``i`` there are no next, previous, parent, or nested contours, the corresponding elements of ``hierarchy[i]`` will be negative.
:param mode: Contour retrieval mode (if you use Python see also a note below). :param mode: Contour retrieval mode (if you use Python see also a note below).

View File

@@ -1048,7 +1048,18 @@ enum
COLOR_RGBA2mRGBA = 125, COLOR_RGBA2mRGBA = 125,
COLOR_mRGBA2RGBA = 126, COLOR_mRGBA2RGBA = 126,
COLOR_COLORCVT_MAX = 127 // Edge-Aware Demosaicing
COLOR_BayerBG2BGR_EA = 127,
COLOR_BayerGB2BGR_EA = 128,
COLOR_BayerRG2BGR_EA = 129,
COLOR_BayerGR2BGR_EA = 130,
COLOR_BayerBG2RGB_EA = COLOR_BayerRG2BGR_EA,
COLOR_BayerGB2RGB_EA = COLOR_BayerGR2BGR_EA,
COLOR_BayerRG2RGB_EA = COLOR_BayerBG2BGR_EA,
COLOR_BayerGR2RGB_EA = COLOR_BayerGB2BGR_EA,
COLOR_COLORCVT_MAX = 131
}; };
@@ -1252,6 +1263,9 @@ protected:
Point2f bottomRight; Point2f bottomRight;
}; };
// main function for all demosaicing procceses
CV_EXPORTS_W void demosaicing(InputArray _src, OutputArray _dst, int code, int dcn = 0);
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@@ -310,7 +310,18 @@ enum
CV_RGBA2mRGBA = 125, CV_RGBA2mRGBA = 125,
CV_mRGBA2RGBA = 126, CV_mRGBA2RGBA = 126,
CV_COLORCVT_MAX = 127 // Edge-Aware Demosaicing
CV_BayerBG2BGR_EA = 127,
CV_BayerGB2BGR_EA = 128,
CV_BayerRG2BGR_EA = 129,
CV_BayerGR2BGR_EA = 130,
CV_BayerBG2RGB_EA = CV_BayerRG2BGR_EA,
CV_BayerGB2RGB_EA = CV_BayerGR2BGR_EA,
CV_BayerRG2RGB_EA = CV_BayerBG2BGR_EA,
CV_BayerGR2RGB_EA = CV_BayerGB2BGR_EA,
CV_COLORCVT_MAX = 131
}; };

View File

@@ -276,3 +276,28 @@ PERF_TEST_P(Size_CvtMode2, cvtColorYUV420,
SANITY_CHECK(dst, 1); SANITY_CHECK(dst, 1);
} }
CV_ENUM(EdgeAwareBayerMode, COLOR_BayerBG2BGR_EA, COLOR_BayerGB2BGR_EA, COLOR_BayerRG2BGR_EA, COLOR_BayerGR2BGR_EA)
typedef std::tr1::tuple<Size, EdgeAwareBayerMode> EdgeAwareParams;
typedef perf::TestBaseWithParam<EdgeAwareParams> EdgeAwareDemosaicingTest;
PERF_TEST_P(EdgeAwareDemosaicingTest, demosaicingEA,
testing::Combine(
testing::Values(szVGA, sz720p, sz1080p, Size(130, 60)),
testing::ValuesIn(EdgeAwareBayerMode::all())
)
)
{
Size sz = get<0>(GetParam());
int mode = get<1>(GetParam());
Mat src(sz, CV_8UC1);
Mat dst(sz, CV_8UC3);
declare.in(src, WARMUP_RNG).out(dst);
TEST_CYCLE() cvtColor(src, dst, mode, 3);
SANITY_CHECK(dst, 1);
}

View File

@@ -70,7 +70,7 @@ PERF_TEST_P( Image_KernelSize, GaborFilter2d,
filter2D(sourceImage, filteredImage, CV_32F, gaborKernel); filter2D(sourceImage, filteredImage, CV_32F, gaborKernel);
} }
SANITY_CHECK(filteredImage); SANITY_CHECK(filteredImage, 1e-3);
} }

View File

@@ -9,14 +9,14 @@ using std::tr1::get;
typedef tr1::tuple<Size, MatType> Size_Source_t; typedef tr1::tuple<Size, MatType> Size_Source_t;
typedef TestBaseWithParam<Size_Source_t> Size_Source; typedef TestBaseWithParam<Size_Source_t> Size_Source;
typedef TestBaseWithParam<Size> MatSize; typedef TestBaseWithParam<Size> MatSize;
static const float rangeHight = 256.0f;
static const float rangeLow = 0.0f;
PERF_TEST_P(Size_Source, calcHist, PERF_TEST_P(Size_Source, calcHist1d,
testing::Combine(testing::Values(TYPICAL_MAT_SIZES), testing::Combine(testing::Values(sz3MP, sz5MP),
testing::Values(CV_8U, CV_32F) testing::Values(CV_8U, CV_16U, CV_32F) )
)
) )
{ {
Size size = get<0>(GetParam()); Size size = get<0>(GetParam());
@@ -28,10 +28,69 @@ PERF_TEST_P(Size_Source, calcHist,
int dims = 1; int dims = 1;
int numberOfImages = 1; int numberOfImages = 1;
const float r[] = {0.0f, 256.0f}; const float r[] = {rangeLow, rangeHight};
const float* ranges[] = {r}; const float* ranges[] = {r};
declare.in(source, WARMUP_RNG).time(20).iterations(1000); randu(source, rangeLow, rangeHight);
declare.in(source);
TEST_CYCLE()
{
calcHist(&source, numberOfImages, channels, Mat(), hist, dims, histSize, ranges);
}
SANITY_CHECK(hist);
}
PERF_TEST_P(Size_Source, calcHist2d,
testing::Combine(testing::Values(sz3MP, sz5MP),
testing::Values(CV_8UC2, CV_16UC2, CV_32FC2) )
)
{
Size size = get<0>(GetParam());
MatType type = get<1>(GetParam());
Mat source(size.height, size.width, type);
Mat hist;
int channels [] = {0, 1};
int histSize [] = {256, 256};
int dims = 2;
int numberOfImages = 1;
const float r[] = {rangeLow, rangeHight};
const float* ranges[] = {r, r};
randu(source, rangeLow, rangeHight);
declare.in(source);
TEST_CYCLE()
{
calcHist(&source, numberOfImages, channels, Mat(), hist, dims, histSize, ranges);
}
SANITY_CHECK(hist);
}
PERF_TEST_P(Size_Source, calcHist3d,
testing::Combine(testing::Values(sz3MP, sz5MP),
testing::Values(CV_8UC3, CV_16UC3, CV_32FC3) )
)
{
Size size = get<0>(GetParam());
MatType type = get<1>(GetParam());
Mat hist;
int channels [] = {0, 1, 2};
int histSize [] = {32, 32, 32};
int dims = 3;
int numberOfImages = 1;
Mat source(size.height, size.width, type);
const float r[] = {rangeLow, rangeHight};
const float* ranges[] = {r, r, r};
randu(source, rangeLow, rangeHight);
declare.in(source);
TEST_CYCLE() TEST_CYCLE()
{ {
calcHist(&source, numberOfImages, channels, Mat(), hist, dims, histSize, ranges); calcHist(&source, numberOfImages, channels, Mat(), hist, dims, histSize, ranges);

View File

@@ -71,7 +71,7 @@ typedef TestBaseWithParam<MatInfo_Size_Scale_t> MatInfo_Size_Scale;
PERF_TEST_P(MatInfo_Size_Scale, ResizeAreaFast, PERF_TEST_P(MatInfo_Size_Scale, ResizeAreaFast,
testing::Combine( testing::Combine(
testing::Values(CV_8UC1, CV_8UC4), testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_16UC1, CV_16UC3, CV_16UC4),
testing::Values(szVGA, szqHD, sz720p, sz1080p), testing::Values(szVGA, szqHD, sz720p, sz1080p),
testing::Values(2) testing::Values(2)
) )

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -165,11 +165,13 @@ static void histPrepareImages( const Mat* images, int nimages, const int* channe
deltas[dims*2 + 1] = (int)(mask.step/mask.elemSize1()); deltas[dims*2 + 1] = (int)(mask.step/mask.elemSize1());
} }
#ifndef HAVE_TBB
if( isContinuous ) if( isContinuous )
{ {
imsize.width *= imsize.height; imsize.width *= imsize.height;
imsize.height = 1; imsize.height = 1;
} }
#endif
if( !ranges ) if( !ranges )
{ {
@@ -207,6 +209,538 @@ static void histPrepareImages( const Mat* images, int nimages, const int* channe
////////////////////////////////// C A L C U L A T E H I S T O G R A M //////////////////////////////////// ////////////////////////////////// C A L C U L A T E H I S T O G R A M ////////////////////////////////////
#ifdef HAVE_TBB
enum {one = 1, two, three}; // array elements number
template<typename T>
class calcHist1D_Invoker
{
public:
calcHist1D_Invoker( const vector<uchar*>& _ptrs, const vector<int>& _deltas,
Mat& hist, const double* _uniranges, int sz, int dims,
Size& imageSize )
: mask_(_ptrs[dims]),
mstep_(_deltas[dims*2 + 1]),
imageWidth_(imageSize.width),
histogramSize_(hist.size()), histogramType_(hist.type()),
globalHistogram_((tbb::atomic<int>*)hist.data)
{
p_[0] = ((T**)&_ptrs[0])[0];
step_[0] = (&_deltas[0])[1];
d_[0] = (&_deltas[0])[0];
a_[0] = (&_uniranges[0])[0];
b_[0] = (&_uniranges[0])[1];
size_[0] = sz;
}
void operator()( const BlockedRange& range ) const
{
T* p0 = p_[0] + range.begin() * (step_[0] + imageWidth_*d_[0]);
uchar* mask = mask_ + range.begin()*mstep_;
for( int row = range.begin(); row < range.end(); row++, p0 += step_[0] )
{
if( !mask_ )
{
for( int x = 0; x < imageWidth_; x++, p0 += d_[0] )
{
int idx = cvFloor(*p0*a_[0] + b_[0]);
if( (unsigned)idx < (unsigned)size_[0] )
{
globalHistogram_[idx].fetch_and_add(1);
}
}
}
else
{
for( int x = 0; x < imageWidth_; x++, p0 += d_[0] )
{
if( mask[x] )
{
int idx = cvFloor(*p0*a_[0] + b_[0]);
if( (unsigned)idx < (unsigned)size_[0] )
{
globalHistogram_[idx].fetch_and_add(1);
}
}
}
mask += mstep_;
}
}
}
private:
T* p_[one];
uchar* mask_;
int step_[one];
int d_[one];
int mstep_;
double a_[one];
double b_[one];
int size_[one];
int imageWidth_;
Size histogramSize_;
int histogramType_;
tbb::atomic<int>* globalHistogram_;
};
template<typename T>
class calcHist2D_Invoker
{
public:
calcHist2D_Invoker( const vector<uchar*>& _ptrs, const vector<int>& _deltas,
Mat& hist, const double* _uniranges, const int* size,
int dims, Size& imageSize, size_t* hstep )
: mask_(_ptrs[dims]),
mstep_(_deltas[dims*2 + 1]),
imageWidth_(imageSize.width),
histogramSize_(hist.size()), histogramType_(hist.type()),
globalHistogram_(hist.data)
{
p_[0] = ((T**)&_ptrs[0])[0]; p_[1] = ((T**)&_ptrs[0])[1];
step_[0] = (&_deltas[0])[1]; step_[1] = (&_deltas[0])[3];
d_[0] = (&_deltas[0])[0]; d_[1] = (&_deltas[0])[2];
a_[0] = (&_uniranges[0])[0]; a_[1] = (&_uniranges[0])[2];
b_[0] = (&_uniranges[0])[1]; b_[1] = (&_uniranges[0])[3];
size_[0] = size[0]; size_[1] = size[1];
hstep_[0] = hstep[0];
}
void operator()(const BlockedRange& range) const
{
T* p0 = p_[0] + range.begin()*(step_[0] + imageWidth_*d_[0]);
T* p1 = p_[1] + range.begin()*(step_[1] + imageWidth_*d_[1]);
uchar* mask = mask_ + range.begin()*mstep_;
for( int row = range.begin(); row < range.end(); row++, p0 += step_[0], p1 += step_[1] )
{
if( !mask_ )
{
for( int x = 0; x < imageWidth_; x++, p0 += d_[0], p1 += d_[1] )
{
int idx0 = cvFloor(*p0*a_[0] + b_[0]);
int idx1 = cvFloor(*p1*a_[1] + b_[1]);
if( (unsigned)idx0 < (unsigned)size_[0] && (unsigned)idx1 < (unsigned)size_[1] )
( (tbb::atomic<int>*)(globalHistogram_ + hstep_[0]*idx0) )[idx1].fetch_and_add(1);
}
}
else
{
for( int x = 0; x < imageWidth_; x++, p0 += d_[0], p1 += d_[1] )
{
if( mask[x] )
{
int idx0 = cvFloor(*p0*a_[0] + b_[0]);
int idx1 = cvFloor(*p1*a_[1] + b_[1]);
if( (unsigned)idx0 < (unsigned)size_[0] && (unsigned)idx1 < (unsigned)size_[1] )
((tbb::atomic<int>*)(globalHistogram_ + hstep_[0]*idx0))[idx1].fetch_and_add(1);
}
}
mask += mstep_;
}
}
}
private:
T* p_[two];
uchar* mask_;
int step_[two];
int d_[two];
int mstep_;
double a_[two];
double b_[two];
int size_[two];
const int imageWidth_;
size_t hstep_[one];
Size histogramSize_;
int histogramType_;
uchar* globalHistogram_;
};
template<typename T>
class calcHist3D_Invoker
{
public:
calcHist3D_Invoker( const vector<uchar*>& _ptrs, const vector<int>& _deltas,
Size imsize, Mat& hist, const double* uniranges, int _dims,
size_t* hstep, int* size )
: mask_(_ptrs[_dims]),
mstep_(_deltas[_dims*2 + 1]),
imageWidth_(imsize.width),
globalHistogram_(hist.data)
{
p_[0] = ((T**)&_ptrs[0])[0]; p_[1] = ((T**)&_ptrs[0])[1]; p_[2] = ((T**)&_ptrs[0])[2];
step_[0] = (&_deltas[0])[1]; step_[1] = (&_deltas[0])[3]; step_[2] = (&_deltas[0])[5];
d_[0] = (&_deltas[0])[0]; d_[1] = (&_deltas[0])[2]; d_[2] = (&_deltas[0])[4];
a_[0] = uniranges[0]; a_[1] = uniranges[2]; a_[2] = uniranges[4];
b_[0] = uniranges[1]; b_[1] = uniranges[3]; b_[2] = uniranges[5];
size_[0] = size[0]; size_[1] = size[1]; size_[2] = size[2];
hstep_[0] = hstep[0]; hstep_[1] = hstep[1];
}
void operator()( const BlockedRange& range ) const
{
T* p0 = p_[0] + range.begin()*(imageWidth_*d_[0] + step_[0]);
T* p1 = p_[1] + range.begin()*(imageWidth_*d_[1] + step_[1]);
T* p2 = p_[2] + range.begin()*(imageWidth_*d_[2] + step_[2]);
uchar* mask = mask_ + range.begin()*mstep_;
for( int i = range.begin(); i < range.end(); i++, p0 += step_[0], p1 += step_[1], p2 += step_[2] )
{
if( !mask_ )
{
for( int x = 0; x < imageWidth_; x++, p0 += d_[0], p1 += d_[1], p2 += d_[2] )
{
int idx0 = cvFloor(*p0*a_[0] + b_[0]);
int idx1 = cvFloor(*p1*a_[1] + b_[1]);
int idx2 = cvFloor(*p2*a_[2] + b_[2]);
if( (unsigned)idx0 < (unsigned)size_[0] &&
(unsigned)idx1 < (unsigned)size_[1] &&
(unsigned)idx2 < (unsigned)size_[2] )
{
( (tbb::atomic<int>*)(globalHistogram_ + hstep_[0]*idx0 + hstep_[1]*idx1) )[idx2].fetch_and_add(1);
}
}
}
else
{
for( int x = 0; x < imageWidth_; x++, p0 += d_[0], p1 += d_[1], p2 += d_[2] )
{
if( mask[x] )
{
int idx0 = cvFloor(*p0*a_[0] + b_[0]);
int idx1 = cvFloor(*p1*a_[1] + b_[1]);
int idx2 = cvFloor(*p2*a_[2] + b_[2]);
if( (unsigned)idx0 < (unsigned)size_[0] &&
(unsigned)idx1 < (unsigned)size_[1] &&
(unsigned)idx2 < (unsigned)size_[2] )
{
( (tbb::atomic<int>*)(globalHistogram_ + hstep_[0]*idx0 + hstep_[1]*idx1) )[idx2].fetch_and_add(1);
}
}
}
mask += mstep_;
}
}
}
static bool isFit( const Mat& histogram, const Size imageSize )
{
return ( imageSize.width * imageSize.height >= 320*240
&& histogram.total() >= 8*8*8 );
}
private:
T* p_[three];
uchar* mask_;
int step_[three];
int d_[three];
const int mstep_;
double a_[three];
double b_[three];
int size_[three];
int imageWidth_;
size_t hstep_[two];
uchar* globalHistogram_;
};
class CalcHist1D_8uInvoker
{
public:
CalcHist1D_8uInvoker( const vector<uchar*>& ptrs, const vector<int>& deltas,
Size imsize, Mat& hist, int dims, const vector<size_t>& tab,
tbb::mutex* lock )
: mask_(ptrs[dims]),
mstep_(deltas[dims*2 + 1]),
imageWidth_(imsize.width),
imageSize_(imsize),
histSize_(hist.size()), histType_(hist.type()),
tab_((size_t*)&tab[0]),
histogramWriteLock_(lock),
globalHistogram_(hist.data)
{
p_[0] = (&ptrs[0])[0];
step_[0] = (&deltas[0])[1];
d_[0] = (&deltas[0])[0];
}
void operator()( const BlockedRange& range ) const
{
int localHistogram[256] = { 0, };
uchar* mask = mask_;
uchar* p0 = p_[0];
int x;
tbb::mutex::scoped_lock lock;
if( !mask_ )
{
int n = (imageWidth_ - 4) / 4 + 1;
int tail = imageWidth_ - n*4;
int xN = 4*n;
p0 += (xN*d_[0] + tail*d_[0] + step_[0]) * range.begin();
}
else
{
p0 += (imageWidth_*d_[0] + step_[0]) * range.begin();
mask += mstep_*range.begin();
}
for( int i = range.begin(); i < range.end(); i++, p0 += step_[0] )
{
if( !mask_ )
{
if( d_[0] == 1 )
{
for( x = 0; x <= imageWidth_ - 4; x += 4 )
{
int t0 = p0[x], t1 = p0[x+1];
localHistogram[t0]++; localHistogram[t1]++;
t0 = p0[x+2]; t1 = p0[x+3];
localHistogram[t0]++; localHistogram[t1]++;
}
p0 += x;
}
else
{
for( x = 0; x <= imageWidth_ - 4; x += 4 )
{
int t0 = p0[0], t1 = p0[d_[0]];
localHistogram[t0]++; localHistogram[t1]++;
p0 += d_[0]*2;
t0 = p0[0]; t1 = p0[d_[0]];
localHistogram[t0]++; localHistogram[t1]++;
p0 += d_[0]*2;
}
}
for( ; x < imageWidth_; x++, p0 += d_[0] )
{
localHistogram[*p0]++;
}
}
else
{
for( x = 0; x < imageWidth_; x++, p0 += d_[0] )
{
if( mask[x] )
{
localHistogram[*p0]++;
}
}
mask += mstep_;
}
}
lock.acquire(*histogramWriteLock_);
for(int i = 0; i < 256; i++ )
{
size_t hidx = tab_[i];
if( hidx < OUT_OF_RANGE )
{
*(int*)((globalHistogram_ + hidx)) += localHistogram[i];
}
}
lock.release();
}
static bool isFit( const Mat& histogram, const Size imageSize )
{
return ( histogram.total() >= 8
&& imageSize.width * imageSize.height >= 160*120 );
}
private:
uchar* p_[one];
uchar* mask_;
int mstep_;
int step_[one];
int d_[one];
int imageWidth_;
Size imageSize_;
Size histSize_;
int histType_;
size_t* tab_;
tbb::mutex* histogramWriteLock_;
uchar* globalHistogram_;
};
class CalcHist2D_8uInvoker
{
public:
CalcHist2D_8uInvoker( const vector<uchar*>& _ptrs, const vector<int>& _deltas,
Size imsize, Mat& hist, int dims, const vector<size_t>& _tab,
tbb::mutex* lock )
: mask_(_ptrs[dims]),
mstep_(_deltas[dims*2 + 1]),
imageWidth_(imsize.width),
histSize_(hist.size()), histType_(hist.type()),
tab_((size_t*)&_tab[0]),
histogramWriteLock_(lock),
globalHistogram_(hist.data)
{
p_[0] = (uchar*)(&_ptrs[0])[0]; p_[1] = (uchar*)(&_ptrs[0])[1];
step_[0] = (&_deltas[0])[1]; step_[1] = (&_deltas[0])[3];
d_[0] = (&_deltas[0])[0]; d_[1] = (&_deltas[0])[2];
}
void operator()( const BlockedRange& range ) const
{
uchar* p0 = p_[0] + range.begin()*(step_[0] + imageWidth_*d_[0]);
uchar* p1 = p_[1] + range.begin()*(step_[1] + imageWidth_*d_[1]);
uchar* mask = mask_ + range.begin()*mstep_;
Mat localHist = Mat::zeros(histSize_, histType_);
uchar* localHistData = localHist.data;
tbb::mutex::scoped_lock lock;
for(int i = range.begin(); i < range.end(); i++, p0 += step_[0], p1 += step_[1])
{
if( !mask_ )
{
for( int x = 0; x < imageWidth_; x++, p0 += d_[0], p1 += d_[1] )
{
size_t idx = tab_[*p0] + tab_[*p1 + 256];
if( idx < OUT_OF_RANGE )
{
++*(int*)(localHistData + idx);
}
}
}
else
{
for( int x = 0; x < imageWidth_; x++, p0 += d_[0], p1 += d_[1] )
{
size_t idx;
if( mask[x] && (idx = tab_[*p0] + tab_[*p1 + 256]) < OUT_OF_RANGE )
{
++*(int*)(localHistData + idx);
}
}
mask += mstep_;
}
}
lock.acquire(*histogramWriteLock_);
for(int i = 0; i < histSize_.width*histSize_.height; i++)
{
((int*)globalHistogram_)[i] += ((int*)localHistData)[i];
}
lock.release();
}
static bool isFit( const Mat& histogram, const Size imageSize )
{
return ( (histogram.total() > 4*4 && histogram.total() <= 116*116
&& imageSize.width * imageSize.height >= 320*240)
|| (histogram.total() > 116*116 && imageSize.width * imageSize.height >= 1280*720) );
}
private:
uchar* p_[two];
uchar* mask_;
int step_[two];
int d_[two];
int mstep_;
int imageWidth_;
Size histSize_;
int histType_;
size_t* tab_;
tbb::mutex* histogramWriteLock_;
uchar* globalHistogram_;
};
class CalcHist3D_8uInvoker
{
public:
CalcHist3D_8uInvoker( const vector<uchar*>& _ptrs, const vector<int>& _deltas,
Size imsize, Mat& hist, int dims, const vector<size_t>& tab )
: mask_(_ptrs[dims]),
mstep_(_deltas[dims*2 + 1]),
histogramSize_(hist.size.p), histogramType_(hist.type()),
imageWidth_(imsize.width),
tab_((size_t*)&tab[0]),
globalHistogram_(hist.data)
{
p_[0] = (uchar*)(&_ptrs[0])[0]; p_[1] = (uchar*)(&_ptrs[0])[1]; p_[2] = (uchar*)(&_ptrs[0])[2];
step_[0] = (&_deltas[0])[1]; step_[1] = (&_deltas[0])[3]; step_[2] = (&_deltas[0])[5];
d_[0] = (&_deltas[0])[0]; d_[1] = (&_deltas[0])[2]; d_[2] = (&_deltas[0])[4];
}
void operator()( const BlockedRange& range ) const
{
uchar* p0 = p_[0] + range.begin()*(step_[0] + imageWidth_*d_[0]);
uchar* p1 = p_[1] + range.begin()*(step_[1] + imageWidth_*d_[1]);
uchar* p2 = p_[2] + range.begin()*(step_[2] + imageWidth_*d_[2]);
uchar* mask = mask_ + range.begin()*mstep_;
for(int i = range.begin(); i < range.end(); i++, p0 += step_[0], p1 += step_[1], p2 += step_[2] )
{
if( !mask_ )
{
for( int x = 0; x < imageWidth_; x++, p0 += d_[0], p1 += d_[1], p2 += d_[2] )
{
size_t idx = tab_[*p0] + tab_[*p1 + 256] + tab_[*p2 + 512];
if( idx < OUT_OF_RANGE )
{
( *(tbb::atomic<int>*)(globalHistogram_ + idx) ).fetch_and_add(1);
}
}
}
else
{
for( int x = 0; x < imageWidth_; x++, p0 += d_[0], p1 += d_[1], p2 += d_[2] )
{
size_t idx;
if( mask[x] && (idx = tab_[*p0] + tab_[*p1 + 256] + tab_[*p2 + 512]) < OUT_OF_RANGE )
{
(*(tbb::atomic<int>*)(globalHistogram_ + idx)).fetch_and_add(1);
}
}
mask += mstep_;
}
}
}
static bool isFit( const Mat& histogram, const Size imageSize )
{
return ( histogram.total() >= 128*128*128
&& imageSize.width * imageSize.width >= 320*240 );
}
private:
uchar* p_[three];
uchar* mask_;
int mstep_;
int step_[three];
int d_[three];
int* histogramSize_;
int histogramType_;
int imageWidth_;
size_t* tab_;
uchar* globalHistogram_;
};
static void
callCalcHist2D_8u( vector<uchar*>& _ptrs, const vector<int>& _deltas,
Size imsize, Mat& hist, int dims, vector<size_t>& _tab )
{
int grainSize = imsize.height / tbb::task_scheduler_init::default_num_threads();
tbb::mutex histogramWriteLock;
CalcHist2D_8uInvoker body(_ptrs, _deltas, imsize, hist, dims, _tab, &histogramWriteLock);
parallel_for(BlockedRange(0, imsize.height, grainSize), body);
}
static void
callCalcHist3D_8u( vector<uchar*>& _ptrs, const vector<int>& _deltas,
Size imsize, Mat& hist, int dims, vector<size_t>& _tab )
{
CalcHist3D_8uInvoker body(_ptrs, _deltas, imsize, hist, dims, _tab);
parallel_for(BlockedRange(0, imsize.height), body);
}
#endif
template<typename T> static void template<typename T> static void
calcHist_( vector<uchar*>& _ptrs, const vector<int>& _deltas, calcHist_( vector<uchar*>& _ptrs, const vector<int>& _deltas,
@@ -234,6 +768,11 @@ calcHist_( vector<uchar*>& _ptrs, const vector<int>& _deltas,
if( dims == 1 ) if( dims == 1 )
{ {
#ifdef HAVE_TBB
calcHist1D_Invoker<T> body(_ptrs, _deltas, hist, _uniranges, size[0], dims, imsize);
parallel_for(BlockedRange(0, imsize.height), body);
return;
#endif
double a = uniranges[0], b = uniranges[1]; double a = uniranges[0], b = uniranges[1];
int sz = size[0], d0 = deltas[0], step0 = deltas[1]; int sz = size[0], d0 = deltas[0], step0 = deltas[1];
const T* p0 = (const T*)ptrs[0]; const T* p0 = (const T*)ptrs[0];
@@ -259,6 +798,11 @@ calcHist_( vector<uchar*>& _ptrs, const vector<int>& _deltas,
} }
else if( dims == 2 ) else if( dims == 2 )
{ {
#ifdef HAVE_TBB
calcHist2D_Invoker<T> body(_ptrs, _deltas, hist, _uniranges, size, dims, imsize, hstep);
parallel_for(BlockedRange(0, imsize.height), body);
return;
#endif
double a0 = uniranges[0], b0 = uniranges[1], a1 = uniranges[2], b1 = uniranges[3]; double a0 = uniranges[0], b0 = uniranges[1], a1 = uniranges[2], b1 = uniranges[3];
int sz0 = size[0], sz1 = size[1]; int sz0 = size[0], sz1 = size[1];
int d0 = deltas[0], step0 = deltas[1], int d0 = deltas[0], step0 = deltas[1],
@@ -290,6 +834,14 @@ calcHist_( vector<uchar*>& _ptrs, const vector<int>& _deltas,
} }
else if( dims == 3 ) else if( dims == 3 )
{ {
#ifdef HAVE_TBB
if( calcHist3D_Invoker<T>::isFit(hist, imsize) )
{
calcHist3D_Invoker<T> body(_ptrs, _deltas, imsize, hist, uniranges, dims, hstep, size);
parallel_for(BlockedRange(0, imsize.height), body);
return;
}
#endif
double a0 = uniranges[0], b0 = uniranges[1], double a0 = uniranges[0], b0 = uniranges[1],
a1 = uniranges[2], b1 = uniranges[3], a1 = uniranges[2], b1 = uniranges[3],
a2 = uniranges[4], b2 = uniranges[5]; a2 = uniranges[4], b2 = uniranges[5];
@@ -441,8 +993,20 @@ calcHist_8u( vector<uchar*>& _ptrs, const vector<int>& _deltas,
if( dims == 1 ) if( dims == 1 )
{ {
#ifdef HAVE_TBB
if( CalcHist1D_8uInvoker::isFit(hist, imsize) )
{
int treadsNumber = tbb::task_scheduler_init::default_num_threads();
int grainSize = imsize.height/treadsNumber;
tbb::mutex histogramWriteLock;
CalcHist1D_8uInvoker body(_ptrs, _deltas, imsize, hist, dims, _tab, &histogramWriteLock);
parallel_for(BlockedRange(0, imsize.height, grainSize), body);
return;
}
#endif
int d0 = deltas[0], step0 = deltas[1]; int d0 = deltas[0], step0 = deltas[1];
int matH[256] = {0}; int matH[256] = { 0, };
const uchar* p0 = (const uchar*)ptrs[0]; const uchar* p0 = (const uchar*)ptrs[0];
for( ; imsize.height--; p0 += step0, mask += mstep ) for( ; imsize.height--; p0 += step0, mask += mstep )
@@ -489,6 +1053,13 @@ calcHist_8u( vector<uchar*>& _ptrs, const vector<int>& _deltas,
} }
else if( dims == 2 ) else if( dims == 2 )
{ {
#ifdef HAVE_TBB
if( CalcHist2D_8uInvoker::isFit(hist, imsize) )
{
callCalcHist2D_8u(_ptrs, _deltas, imsize, hist, dims, _tab);
return;
}
#endif
int d0 = deltas[0], step0 = deltas[1], int d0 = deltas[0], step0 = deltas[1],
d1 = deltas[2], step1 = deltas[3]; d1 = deltas[2], step1 = deltas[3];
const uchar* p0 = (const uchar*)ptrs[0]; const uchar* p0 = (const uchar*)ptrs[0];
@@ -514,6 +1085,13 @@ calcHist_8u( vector<uchar*>& _ptrs, const vector<int>& _deltas,
} }
else if( dims == 3 ) else if( dims == 3 )
{ {
#ifdef HAVE_TBB
if( CalcHist3D_8uInvoker::isFit(hist, imsize) )
{
callCalcHist3D_8u(_ptrs, _deltas, imsize, hist, dims, _tab);
return;
}
#endif
int d0 = deltas[0], step0 = deltas[1], int d0 = deltas[0], step0 = deltas[1],
d1 = deltas[2], step1 = deltas[3], d1 = deltas[2], step1 = deltas[3],
d2 = deltas[4], step2 = deltas[5]; d2 = deltas[4], step2 = deltas[5];
@@ -2404,61 +2982,206 @@ cvCalcProbDensity( const CvHistogram* hist, const CvHistogram* hist_mask,
} }
} }
class EqualizeHistCalcHist_Invoker
{
public:
enum {HIST_SZ = 256};
#ifdef HAVE_TBB
typedef tbb::mutex* MutextPtr;
#else
typedef void* MutextPtr;
#endif
EqualizeHistCalcHist_Invoker(cv::Mat& src, int* histogram, MutextPtr histogramLock)
: src_(src), globalHistogram_(histogram), histogramLock_(histogramLock)
{ }
void operator()( const cv::BlockedRange& rowRange ) const
{
int localHistogram[HIST_SZ] = {0, };
const size_t sstep = src_.step;
int width = src_.cols;
int height = rowRange.end() - rowRange.begin();
if (src_.isContinuous())
{
width *= height;
height = 1;
}
for (const uchar* ptr = src_.ptr<uchar>(rowRange.begin()); height--; ptr += sstep)
{
int x = 0;
for (; x <= width - 4; x += 4)
{
int t0 = ptr[x], t1 = ptr[x+1];
localHistogram[t0]++; localHistogram[t1]++;
t0 = ptr[x+2]; t1 = ptr[x+3];
localHistogram[t0]++; localHistogram[t1]++;
}
for (; x < width; ++x, ++ptr)
localHistogram[ptr[x]]++;
}
#ifdef HAVE_TBB
tbb::mutex::scoped_lock lock(*histogramLock_);
#endif
for( int i = 0; i < HIST_SZ; i++ )
globalHistogram_[i] += localHistogram[i];
}
static bool isWorthParallel( const cv::Mat& src )
{
#ifdef HAVE_TBB
return ( src.total() >= 640*480 );
#else
(void)src;
return false;
#endif
}
private:
EqualizeHistCalcHist_Invoker& operator=(const EqualizeHistCalcHist_Invoker&);
cv::Mat& src_;
int* globalHistogram_;
MutextPtr histogramLock_;
};
class EqualizeHistLut_Invoker
{
public:
EqualizeHistLut_Invoker( cv::Mat& src, cv::Mat& dst, int* lut )
: src_(src),
dst_(dst),
lut_(lut)
{ }
void operator()( const cv::BlockedRange& rowRange ) const
{
const size_t sstep = src_.step;
const size_t dstep = dst_.step;
int width = src_.cols;
int height = rowRange.end() - rowRange.begin();
int* lut = lut_;
if (src_.isContinuous() && dst_.isContinuous())
{
width *= height;
height = 1;
}
const uchar* sptr = src_.ptr<uchar>(rowRange.begin());
uchar* dptr = dst_.ptr<uchar>(rowRange.begin());
for (; height--; sptr += sstep, dptr += dstep)
{
int x = 0;
for (; x <= width - 4; x += 4)
{
int v0 = sptr[x];
int v1 = sptr[x+1];
int x0 = lut[v0];
int x1 = lut[v1];
dptr[x] = (uchar)x0;
dptr[x+1] = (uchar)x1;
v0 = sptr[x+2];
v1 = sptr[x+3];
x0 = lut[v0];
x1 = lut[v1];
dptr[x+2] = (uchar)x0;
dptr[x+3] = (uchar)x1;
}
for (; x < width; ++x)
dptr[x] = (uchar)lut[sptr[x]];
}
}
static bool isWorthParallel( const cv::Mat& src )
{
#ifdef HAVE_TBB
return ( src.total() >= 640*480 );
#else
(void)src;
return false;
#endif
}
private:
EqualizeHistLut_Invoker& operator=(const EqualizeHistLut_Invoker&);
cv::Mat& src_;
cv::Mat& dst_;
int* lut_;
};
CV_IMPL void cvEqualizeHist( const CvArr* srcarr, CvArr* dstarr ) CV_IMPL void cvEqualizeHist( const CvArr* srcarr, CvArr* dstarr )
{ {
CvMat sstub, *src = cvGetMat(srcarr, &sstub); cv::equalizeHist(cv::cvarrToMat(srcarr), cv::cvarrToMat(dstarr));
CvMat dstub, *dst = cvGetMat(dstarr, &dstub);
CV_Assert( CV_ARE_SIZES_EQ(src, dst) && CV_ARE_TYPES_EQ(src, dst) &&
CV_MAT_TYPE(src->type) == CV_8UC1 );
CvSize size = cvGetMatSize(src);
if( CV_IS_MAT_CONT(src->type & dst->type) )
{
size.width *= size.height;
size.height = 1;
}
int x, y;
const int hist_sz = 256;
int hist[hist_sz];
memset(hist, 0, sizeof(hist));
for( y = 0; y < size.height; y++ )
{
const uchar* sptr = src->data.ptr + src->step*y;
for( x = 0; x < size.width; x++ )
hist[sptr[x]]++;
}
float scale = 255.f/(size.width*size.height);
int sum = 0;
uchar lut[hist_sz+1];
for( int i = 0; i < hist_sz; i++ )
{
sum += hist[i];
int val = cvRound(sum*scale);
lut[i] = CV_CAST_8U(val);
}
lut[0] = 0;
for( y = 0; y < size.height; y++ )
{
const uchar* sptr = src->data.ptr + src->step*y;
uchar* dptr = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++ )
dptr[x] = lut[sptr[x]];
}
} }
void cv::equalizeHist( InputArray _src, OutputArray _dst ) void cv::equalizeHist( InputArray _src, OutputArray _dst )
{ {
Mat src = _src.getMat(); Mat src = _src.getMat();
CV_Assert( src.type() == CV_8UC1 );
_dst.create( src.size(), src.type() ); _dst.create( src.size(), src.type() );
Mat dst = _dst.getMat(); Mat dst = _dst.getMat();
CvMat _csrc = src, _cdst = dst;
cvEqualizeHist( &_csrc, &_cdst ); if(src.empty())
return;
#ifdef HAVE_TBB
tbb::mutex histogramLockInstance;
EqualizeHistCalcHist_Invoker::MutextPtr histogramLock = &histogramLockInstance;
#else
EqualizeHistCalcHist_Invoker::MutextPtr histogramLock = 0;
#endif
const int hist_sz = EqualizeHistCalcHist_Invoker::HIST_SZ;
int hist[hist_sz] = {0,};
int lut[hist_sz];
EqualizeHistCalcHist_Invoker calcBody(src, hist, histogramLock);
EqualizeHistLut_Invoker lutBody(src, dst, lut);
cv::BlockedRange heightRange(0, src.rows);
if(EqualizeHistCalcHist_Invoker::isWorthParallel(src))
parallel_for(heightRange, calcBody);
else
calcBody(heightRange);
int i = 0;
while (!hist[i]) ++i;
int total = (int)src.total();
if (hist[i] == total)
{
dst.setTo(i);
return;
}
float scale = (hist_sz - 1.f)/(total - hist[i]);
int sum = 0;
for (lut[i++] = 0; i < hist_sz; ++i)
{
sum += hist[i];
lut[i] = saturate_cast<uchar>(sum * scale);
}
if(EqualizeHistLut_Invoker::isWorthParallel(src))
parallel_for(heightRange, lutBody);
else
lutBody(heightRange);
} }
/* Implementation of RTTI and Generic Functions for CvHistogram */ /* Implementation of RTTI and Generic Functions for CvHistogram */

View File

@@ -1241,27 +1241,217 @@ static void resizeGeneric_( const Mat& src, Mat& dst,
template <typename T, typename WT> template <typename T, typename WT>
struct ResizeAreaFastNoVec struct ResizeAreaFastNoVec
{ {
ResizeAreaFastNoVec(int /*_scale_x*/, int /*_scale_y*/, ResizeAreaFastNoVec(int, int) { }
int /*_cn*/, int /*_step*//*, const int**/ /*_ofs*/) { } ResizeAreaFastNoVec(int, int, int, int) { }
int operator() (const T* /*S*/, T* /*D*/, int /*w*/) const { return 0; } int operator() (const T*, T*, int) const
{ return 0; }
}; };
template<typename T> #if CV_SSE2
class ResizeAreaFastVec_SIMD_8u
{
public:
ResizeAreaFastVec_SIMD_8u(int _cn, int _step) :
cn(_cn), step(_step)
{
use_simd = checkHardwareSupport(CV_CPU_SSE2);
}
int operator() (const uchar* S, uchar* D, int w) const
{
if (!use_simd)
return 0;
int dx = 0;
const uchar* S0 = S;
const uchar* S1 = S0 + step;
__m128i zero = _mm_setzero_si128();
__m128i delta2 = _mm_set1_epi16(2);
if (cn == 1)
{
__m128i masklow = _mm_set1_epi16(0x00ff);
for ( ; dx < w - 8; dx += 8, S0 += 16, S1 += 16, D += 8)
{
__m128i r0 = _mm_loadu_si128((const __m128i*)S0);
__m128i r1 = _mm_loadu_si128((const __m128i*)S1);
__m128i s0 = _mm_add_epi16(_mm_srli_epi16(r0, 8), _mm_and_si128(r0, masklow));
__m128i s1 = _mm_add_epi16(_mm_srli_epi16(r1, 8), _mm_and_si128(r1, masklow));
s0 = _mm_add_epi16(_mm_add_epi16(s0, s1), delta2);
s0 = _mm_packus_epi16(_mm_srli_epi16(s0, 2), zero);
_mm_storel_epi64((__m128i*)D, s0);
}
}
else if (cn == 3)
for ( ; dx < w - 6; dx += 6, S0 += 12, S1 += 12, D += 6)
{
__m128i r0 = _mm_loadu_si128((const __m128i*)S0);
__m128i r1 = _mm_loadu_si128((const __m128i*)S1);
__m128i r0_16l = _mm_unpacklo_epi8(r0, zero);
__m128i r0_16h = _mm_unpacklo_epi8(_mm_srli_si128(r0, 6), zero);
__m128i r1_16l = _mm_unpacklo_epi8(r1, zero);
__m128i r1_16h = _mm_unpacklo_epi8(_mm_srli_si128(r1, 6), zero);
__m128i s0 = _mm_add_epi16(r0_16l, _mm_srli_si128(r0_16l, 6));
__m128i s1 = _mm_add_epi16(r1_16l, _mm_srli_si128(r1_16l, 6));
s0 = _mm_add_epi16(s1, _mm_add_epi16(s0, delta2));
s0 = _mm_packus_epi16(_mm_srli_epi16(s0, 2), zero);
_mm_storel_epi64((__m128i*)D, s0);
s0 = _mm_add_epi16(r0_16h, _mm_srli_si128(r0_16h, 6));
s1 = _mm_add_epi16(r1_16h, _mm_srli_si128(r1_16h, 6));
s0 = _mm_add_epi16(s1, _mm_add_epi16(s0, delta2));
s0 = _mm_packus_epi16(_mm_srli_epi16(s0, 2), zero);
_mm_storel_epi64((__m128i*)(D+3), s0);
}
else
{
CV_Assert(cn == 4);
for ( ; dx < w - 8; dx += 8, S0 += 16, S1 += 16, D += 8)
{
__m128i r0 = _mm_loadu_si128((const __m128i*)S0);
__m128i r1 = _mm_loadu_si128((const __m128i*)S1);
__m128i r0_16l = _mm_unpacklo_epi8(r0, zero);
__m128i r0_16h = _mm_unpackhi_epi8(r0, zero);
__m128i r1_16l = _mm_unpacklo_epi8(r1, zero);
__m128i r1_16h = _mm_unpackhi_epi8(r1, zero);
__m128i s0 = _mm_add_epi16(r0_16l, _mm_srli_si128(r0_16l, 8));
__m128i s1 = _mm_add_epi16(r1_16l, _mm_srli_si128(r1_16l, 8));
s0 = _mm_add_epi16(s1, _mm_add_epi16(s0, delta2));
s0 = _mm_packus_epi16(_mm_srli_epi16(s0, 2), zero);
_mm_storel_epi64((__m128i*)D, s0);
s0 = _mm_add_epi16(r0_16h, _mm_srli_si128(r0_16h, 8));
s1 = _mm_add_epi16(r1_16h, _mm_srli_si128(r1_16h, 8));
s0 = _mm_add_epi16(s1, _mm_add_epi16(s0, delta2));
s0 = _mm_packus_epi16(_mm_srli_epi16(s0, 2), zero);
_mm_storel_epi64((__m128i*)(D+4), s0);
}
}
return dx;
}
private:
int cn;
bool use_simd;
int step;
};
class ResizeAreaFastVec_SIMD_16u
{
public:
ResizeAreaFastVec_SIMD_16u(int _cn, int _step) :
cn(_cn), step(_step)
{
use_simd = checkHardwareSupport(CV_CPU_SSE2);
}
int operator() (const ushort* S, ushort* D, int w) const
{
if (!use_simd)
return 0;
int dx = 0;
const ushort* S0 = (const ushort*)S;
const ushort* S1 = (const ushort*)((const uchar*)(S) + step);
__m128i masklow = _mm_set1_epi32(0x0000ffff);
__m128i zero = _mm_setzero_si128();
__m128i delta2 = _mm_set1_epi32(2);
#define _mm_packus_epi32(a, zero) _mm_packs_epi32(_mm_srai_epi32(_mm_slli_epi32(a, 16), 16), zero)
if (cn == 1)
{
for ( ; dx < w - 4; dx += 4, S0 += 8, S1 += 8, D += 4)
{
__m128i r0 = _mm_loadu_si128((const __m128i*)S0);
__m128i r1 = _mm_loadu_si128((const __m128i*)S1);
__m128i s0 = _mm_add_epi32(_mm_srli_epi32(r0, 16), _mm_and_si128(r0, masklow));
__m128i s1 = _mm_add_epi32(_mm_srli_epi32(r1, 16), _mm_and_si128(r1, masklow));
s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), delta2);
s0 = _mm_srli_epi32(s0, 2);
s0 = _mm_packus_epi32(s0, zero);
_mm_storel_epi64((__m128i*)D, s0);
}
}
else if (cn == 3)
for ( ; dx < w - 3; dx += 3, S0 += 6, S1 += 6, D += 3)
{
__m128i r0 = _mm_loadu_si128((const __m128i*)S0);
__m128i r1 = _mm_loadu_si128((const __m128i*)S1);
__m128i r0_16l = _mm_unpacklo_epi16(r0, zero);
__m128i r0_16h = _mm_unpacklo_epi16(_mm_srli_si128(r0, 6), zero);
__m128i r1_16l = _mm_unpacklo_epi16(r1, zero);
__m128i r1_16h = _mm_unpacklo_epi16(_mm_srli_si128(r1, 6), zero);
__m128i s0 = _mm_add_epi16(r0_16l, r0_16h);
__m128i s1 = _mm_add_epi16(r1_16l, r1_16h);
s0 = _mm_add_epi32(s1, _mm_add_epi32(s0, delta2));
s0 = _mm_packus_epi32(_mm_srli_epi32(s0, 2), zero);
_mm_storel_epi64((__m128i*)D, s0);
}
else
{
CV_Assert(cn == 4);
for ( ; dx < w - 4; dx += 4, S0 += 8, S1 += 8, D += 4)
{
__m128i r0 = _mm_loadu_si128((const __m128i*)S0);
__m128i r1 = _mm_loadu_si128((const __m128i*)S1);
__m128i r0_32l = _mm_unpacklo_epi16(r0, zero);
__m128i r0_32h = _mm_unpackhi_epi16(r0, zero);
__m128i r1_32l = _mm_unpacklo_epi16(r1, zero);
__m128i r1_32h = _mm_unpackhi_epi16(r1, zero);
__m128i s0 = _mm_add_epi32(r0_32l, r0_32h);
__m128i s1 = _mm_add_epi32(r1_32l, r1_32h);
s0 = _mm_add_epi32(s1, _mm_add_epi32(s0, delta2));
s0 = _mm_packus_epi32(_mm_srli_epi32(s0, 2), zero);
_mm_storel_epi64((__m128i*)D, s0);
}
}
#undef _mm_packus_epi32
return dx;
}
private:
int cn;
int step;
bool use_simd;
};
#else
typedef ResizeAreaFastNoVec<uchar, uchar> ResizeAreaFastVec_SIMD_8u;
typedef ResizeAreaFastNoVec<ushort, ushort> ResizeAreaFastVec_SIMD_16u;
#endif
template<typename T, typename SIMDVecOp>
struct ResizeAreaFastVec struct ResizeAreaFastVec
{ {
ResizeAreaFastVec(int _scale_x, int _scale_y, int _cn, int _step/*, const int* _ofs*/) : ResizeAreaFastVec(int _scale_x, int _scale_y, int _cn, int _step) :
scale_x(_scale_x), scale_y(_scale_y), cn(_cn), step(_step)/*, ofs(_ofs)*/ scale_x(_scale_x), scale_y(_scale_y), cn(_cn), step(_step), vecOp(_cn, _step)
{ {
fast_mode = scale_x == 2 && scale_y == 2 && (cn == 1 || cn == 3 || cn == 4); fast_mode = scale_x == 2 && scale_y == 2 && (cn == 1 || cn == 3 || cn == 4);
} }
int operator() (const T* S, T* D, int w) const int operator() (const T* S, T* D, int w) const
{ {
if( !fast_mode ) if (!fast_mode)
return 0; return 0;
const T* nextS = (const T*)((const uchar*)S + step); const T* nextS = (const T*)((const uchar*)S + step);
int dx = 0; int dx = vecOp(S, D, w);
if (cn == 1) if (cn == 1)
for( ; dx < w; ++dx ) for( ; dx < w; ++dx )
@@ -1279,7 +1469,7 @@ struct ResizeAreaFastVec
} }
else else
{ {
assert(cn == 4); CV_Assert(cn == 4);
for( ; dx < w; dx += 4 ) for( ; dx < w; dx += 4 )
{ {
int index = dx*2; int index = dx*2;
@@ -1298,6 +1488,7 @@ private:
int cn; int cn;
bool fast_mode; bool fast_mode;
int step; int step;
SIMDVecOp vecOp;
}; };
template <typename T, typename WT, typename VecOp> template <typename T, typename WT, typename VecOp>
@@ -1702,10 +1893,10 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
static ResizeAreaFastFunc areafast_tab[] = static ResizeAreaFastFunc areafast_tab[] =
{ {
resizeAreaFast_<uchar, int, ResizeAreaFastVec<uchar> >, resizeAreaFast_<uchar, int, ResizeAreaFastVec<uchar, ResizeAreaFastVec_SIMD_8u> >,
0, 0,
resizeAreaFast_<ushort, float, ResizeAreaFastVec<ushort> >, resizeAreaFast_<ushort, float, ResizeAreaFastVec<ushort, ResizeAreaFastVec_SIMD_16u> >,
resizeAreaFast_<short, float, ResizeAreaFastVec<short> >, resizeAreaFast_<short, float, ResizeAreaFastVec<short, ResizeAreaFastNoVec<short, float> > >,
0, 0,
resizeAreaFast_<float, float, ResizeAreaFastNoVec<float, float> >, resizeAreaFast_<float, float, ResizeAreaFastNoVec<float, float> >,
resizeAreaFast_<double, double, ResizeAreaFastNoVec<double, double> >, resizeAreaFast_<double, double, ResizeAreaFastNoVec<double, double> >,
@@ -1764,9 +1955,7 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
// in case of scale_x && scale_y is equal to 2 // in case of scale_x && scale_y is equal to 2
// INTER_AREA (fast) also is equal to INTER_LINEAR // INTER_AREA (fast) also is equal to INTER_LINEAR
if( interpolation == INTER_LINEAR && is_area_fast && iscale_x == 2 && iscale_y == 2 ) if( interpolation == INTER_LINEAR && is_area_fast && iscale_x == 2 && iscale_y == 2 )
{
interpolation = INTER_AREA; interpolation = INTER_AREA;
}
// true "area" interpolation is only implemented for the case (scale_x <= 1 && scale_y <= 1). // true "area" interpolation is only implemented for the case (scale_x <= 1 && scale_y <= 1).
// In other cases it is emulated using some variant of bilinear interpolation // In other cases it is emulated using some variant of bilinear interpolation

View File

@@ -1685,11 +1685,13 @@ TEST(Imgproc_ColorBayer, accuracy) { CV_ColorBayerTest test; test.safe_run(); }
TEST(Imgproc_ColorBayer, regression) TEST(Imgproc_ColorBayer, regression)
{ {
cvtest::TS& ts = *cvtest::TS::ptr(); cvtest::TS* ts = cvtest::TS::ptr();
Mat given = imread(string(ts.get_data_path()) + "/cvtcolor/bayer_input.png", CV_LOAD_IMAGE_GRAYSCALE); Mat given = imread(string(ts->get_data_path()) + "/cvtcolor/bayer_input.png", CV_LOAD_IMAGE_GRAYSCALE);
Mat gold = imread(string(ts.get_data_path()) + "/cvtcolor/bayer_gold.png", CV_LOAD_IMAGE_UNCHANGED); Mat gold = imread(string(ts->get_data_path()) + "/cvtcolor/bayer_gold.png", CV_LOAD_IMAGE_UNCHANGED);
Mat result; Mat result;
CV_Assert(given.data != NULL && gold.data != NULL);
cvtColor(given, result, CV_BayerBG2GRAY); cvtColor(given, result, CV_BayerBG2GRAY);
@@ -1705,10 +1707,10 @@ TEST(Imgproc_ColorBayer, regression)
TEST(Imgproc_ColorBayerVNG, regression) TEST(Imgproc_ColorBayerVNG, regression)
{ {
cvtest::TS& ts = *cvtest::TS::ptr(); cvtest::TS* ts = cvtest::TS::ptr();
Mat given = imread(string(ts.get_data_path()) + "/cvtcolor/bayer_input.png", CV_LOAD_IMAGE_GRAYSCALE); Mat given = imread(string(ts->get_data_path()) + "/cvtcolor/bayer_input.png", CV_LOAD_IMAGE_GRAYSCALE);
string goldfname = string(ts.get_data_path()) + "/cvtcolor/bayerVNG_gold.png"; string goldfname = string(ts->get_data_path()) + "/cvtcolor/bayerVNG_gold.png";
Mat gold = imread(goldfname, CV_LOAD_IMAGE_UNCHANGED); Mat gold = imread(goldfname, CV_LOAD_IMAGE_UNCHANGED);
Mat result; Mat result;
@@ -1731,91 +1733,94 @@ TEST(Imgproc_ColorBayerVNG, regression)
} }
} }
// creating Bayer pattern
template <typename T, int depth>
static void calculateBayerPattern(const Mat& src, Mat& bayer, const char* pattern)
{
Size ssize = src.size();
const int scn = 1;
bayer.create(ssize, CV_MAKETYPE(depth, scn));
if (!strcmp(pattern, "bg"))
{
for (int y = 0; y < ssize.height; ++y)
for (int x = 0; x < ssize.width; ++x)
{
if ((x + y) % 2)
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[1]);
else if (x % 2)
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[0]);
else
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[2]);
}
}
else if (!strcmp(pattern, "gb"))
{
for (int y = 0; y < ssize.height; ++y)
for (int x = 0; x < ssize.width; ++x)
{
if ((x + y) % 2 == 0)
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[1]);
else if (x % 2 == 0)
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[0]);
else
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[2]);
}
}
else if (!strcmp(pattern, "rg"))
{
for (int y = 0; y < ssize.height; ++y)
for (int x = 0; x < ssize.width; ++x)
{
if ((x + y) % 2)
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[1]);
else if (x % 2 == 0)
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[0]);
else
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[2]);
}
}
else
{
for (int y = 0; y < ssize.height; ++y)
for (int x = 0; x < ssize.width; ++x)
{
if ((x + y) % 2 == 0)
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[1]);
else if (x % 2)
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[0]);
else
bayer.at<T>(y, x) = static_cast<T>(src.at<Vec3b>(y, x)[2]);
}
}
}
TEST(Imgproc_ColorBayerVNG_Strict, regression) TEST(Imgproc_ColorBayerVNG_Strict, regression)
{ {
cvtest::TS& ts = *cvtest::TS::ptr(); cvtest::TS* ts = cvtest::TS::ptr();
const char pattern[][3] = { "bg", "gb", "rg", "gr" }; const char pattern[][3] = { "bg", "gb", "rg", "gr" };
const std::string image_name = "lena.png"; const std::string image_name = "lena.png";
const std::string parent_path = string(ts.get_data_path()) + "/cvtcolor_strict/"; const std::string parent_path = string(ts->get_data_path()) + "/cvtcolor_strict/";
Mat src, dst, bayer, reference; Mat src, dst, bayer, reference;
std::string full_path = parent_path + image_name; std::string full_path = parent_path + image_name;
src = imread(full_path, CV_LOAD_IMAGE_UNCHANGED); src = imread(full_path, CV_LOAD_IMAGE_UNCHANGED);
Size ssize = src.size();
if (src.data == NULL) if (src.data == NULL)
{ {
ts.set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA);
ts.printf(cvtest::TS::SUMMARY, "No input image\n"); ts->printf(cvtest::TS::SUMMARY, "No input image\n");
ts.set_gtest_status(); ts->set_gtest_status();
return; return;
} }
int type = -1;
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
// creating Bayer pattern calculateBayerPattern<uchar, CV_8U>(src, bayer, pattern[i]);
bayer.create(ssize, CV_MAKETYPE(src.depth(), 1)); CV_Assert(!bayer.empty() && bayer.type() == CV_8UC1);
if (!strcmp(pattern[i], "bg"))
{
for (int y = 0; y < ssize.height; ++y)
for (int x = 0; x < ssize.width; ++x)
{
if ((x + y) % 2)
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[1];
else if (x % 2)
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[0];
else
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[2];
}
type = CV_BayerBG2BGR_VNG;
}
else if (!strcmp(pattern[i], "gb"))
{
for (int y = 0; y < ssize.height; ++y)
for (int x = 0; x < ssize.width; ++x)
{
if ((x + y) % 2 == 0)
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[1];
else if (x % 2 == 0)
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[0];
else
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[2];
}
type = CV_BayerGB2BGR_VNG;
}
else if (!strcmp(pattern[i], "rg"))
{
for (int y = 0; y < ssize.height; ++y)
for (int x = 0; x < ssize.width; ++x)
{
if ((x + y) % 2)
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[1];
else if (x % 2 == 0)
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[0];
else
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[2];
}
type = CV_BayerRG2BGR_VNG;
}
else
{
for (int y = 0; y < ssize.height; ++y)
for (int x = 0; x < ssize.width; ++x)
{
if ((x + y) % 2 == 0)
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[1];
else if (x % 2)
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[0];
else
bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[2];
}
type = CV_BayerGR2BGR_VNG;
}
// calculating a dst image // calculating a dst image
cvtColor(bayer, dst, type); cvtColor(bayer, dst, CV_BayerBG2BGR_VNG + i);
// reading a reference image // reading a reference image
full_path = parent_path + pattern[i] + image_name; full_path = parent_path + pattern[i] + image_name;
@@ -1829,16 +1834,17 @@ TEST(Imgproc_ColorBayerVNG_Strict, regression)
if (reference.depth() != dst.depth() || reference.channels() != dst.channels() || if (reference.depth() != dst.depth() || reference.channels() != dst.channels() ||
reference.size() != dst.size()) reference.size() != dst.size())
{ {
ts.set_failed_test_info(cvtest::TS::FAIL_MISMATCH); std::cout << reference(Rect(0, 0, 5, 5)) << std::endl << std::endl << std::endl;
ts.printf(cvtest::TS::SUMMARY, "\nReference channels: %d\n" ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
ts->printf(cvtest::TS::SUMMARY, "\nReference channels: %d\n"
"Actual channels: %d\n", reference.channels(), dst.channels()); "Actual channels: %d\n", reference.channels(), dst.channels());
ts.printf(cvtest::TS::SUMMARY, "\nReference depth: %d\n" ts->printf(cvtest::TS::SUMMARY, "\nReference depth: %d\n"
"Actual depth: %d\n", reference.depth(), dst.depth()); "Actual depth: %d\n", reference.depth(), dst.depth());
ts.printf(cvtest::TS::SUMMARY, "\nReference rows: %d\n" ts->printf(cvtest::TS::SUMMARY, "\nReference rows: %d\n"
"Actual rows: %d\n", reference.rows, dst.rows); "Actual rows: %d\n", reference.rows, dst.rows);
ts.printf(cvtest::TS::SUMMARY, "\nReference cols: %d\n" ts->printf(cvtest::TS::SUMMARY, "\nReference cols: %d\n"
"Actual cols: %d\n", reference.cols, dst.cols); "Actual cols: %d\n", reference.cols, dst.cols);
ts.set_gtest_status(); ts->set_gtest_status();
return; return;
} }
@@ -1849,16 +1855,15 @@ TEST(Imgproc_ColorBayerVNG_Strict, regression)
int nonZero = countNonZero(diff.reshape(1) > 1); int nonZero = countNonZero(diff.reshape(1) > 1);
if (nonZero != 0) if (nonZero != 0)
{ {
ts.set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts.printf(cvtest::TS::SUMMARY, "\nCount non zero in absdiff: %d\n", nonZero); ts->printf(cvtest::TS::SUMMARY, "\nCount non zero in absdiff: %d\n", nonZero);
ts.set_gtest_status(); ts->set_gtest_status();
return; return;
} }
} }
} }
static void getTestMatrix(Mat& src)
void GetTestMatrix(Mat& src)
{ {
Size ssize(1000, 1000); Size ssize(1000, 1000);
src.create(ssize, CV_32FC3); src.create(ssize, CV_32FC3);
@@ -1883,7 +1888,7 @@ void GetTestMatrix(Mat& src)
} }
} }
void validate_result(const Mat& reference, const Mat& actual, const Mat& src = Mat(), int mode = -1) static void validateResult(const Mat& reference, const Mat& actual, const Mat& src = Mat(), int mode = -1)
{ {
cvtest::TS* ts = cvtest::TS::ptr(); cvtest::TS* ts = cvtest::TS::ptr();
Size ssize = reference.size(); Size ssize = reference.size();
@@ -1924,8 +1929,7 @@ void validate_result(const Mat& reference, const Mat& actual, const Mat& src = M
TEST(Imgproc_ColorLab_Full, accuracy) TEST(Imgproc_ColorLab_Full, accuracy)
{ {
Mat src; Mat src;
GetTestMatrix(src); getTestMatrix(src);
Mat reference(src.size(), CV_32FC3);
Size ssize = src.size(); Size ssize = src.size();
CV_Assert(ssize.width == ssize.height); CV_Assert(ssize.width == ssize.height);
@@ -1942,12 +1946,245 @@ TEST(Imgproc_ColorLab_Full, accuracy)
cv::Mat recons; cv::Mat recons;
cv::cvtColor(lab, recons, inverse_code); cv::cvtColor(lab, recons, inverse_code);
validate_result(src, recons, src, forward_code); validateResult(src, recons, src, forward_code);
}
// src *= 255.0f;
// recons *= 255.0f; static void test_Bayer2RGB_EdgeAware_8u(const Mat& src, Mat& dst, int code)
{
// imshow("Test", src); if (dst.empty())
// imshow("OpenCV", recons); dst.create(src.size(), CV_MAKETYPE(src.depth(), 3));
// waitKey(); Size size = src.size();
size.width -= 1;
size.height -= 1;
int dcn = dst.channels();
CV_Assert(dcn == 3);
int step = src.step;
const uchar* S = src.ptr<uchar>(1) + 1;
uchar* D = dst.ptr<uchar>(1) + dcn;
int start_with_green = code == CV_BayerGB2BGR_EA || code == CV_BayerGR2BGR_EA ? 1 : 0;
int blue = code == CV_BayerGB2BGR_EA || code == CV_BayerBG2BGR_EA ? 1 : 0;
for (int y = 1; y < size.height; ++y)
{
S = src.ptr<uchar>(y) + 1;
D = dst.ptr<uchar>(y) + dcn;
if (start_with_green)
{
for (int x = 1; x < size.width; x += 2, S += 2, D += 2*dcn)
{
// red
D[0] = (S[-1] + S[1]) / 2;
D[1] = S[0];
D[2] = (S[-step] + S[step]) / 2;
if (!blue)
std::swap(D[0], D[2]);
}
S = src.ptr<uchar>(y) + 2;
D = dst.ptr<uchar>(y) + 2*dcn;
for (int x = 2; x < size.width; x += 2, S += 2, D += 2*dcn)
{
// red
D[0] = S[0];
D[1] = (std::abs(S[-1] - S[1]) > std::abs(S[step] - S[-step]) ? (S[step] + S[-step] + 1) : (S[-1] + S[1] + 1)) / 2;
D[2] = ((S[-step-1] + S[-step+1] + S[step-1] + S[step+1] + 2) / 4);
if (!blue)
std::swap(D[0], D[2]);
}
}
else
{
for (int x = 1; x < size.width; x += 2, S += 2, D += 2*dcn)
{
D[0] = S[0];
D[1] = (std::abs(S[-1] - S[1]) > std::abs(S[step] - S[-step]) ? (S[step] + S[-step] + 1) : (S[-1] + S[1] + 1)) / 2;
D[2] = ((S[-step-1] + S[-step+1] + S[step-1] + S[step+1] + 2) / 4);
if (!blue)
std::swap(D[0], D[2]);
}
S = src.ptr<uchar>(y) + 2;
D = dst.ptr<uchar>(y) + 2*dcn;
for (int x = 2; x < size.width; x += 2, S += 2, D += 2*dcn)
{
D[0] = (S[-1] + S[1] + 1) / 2;
D[1] = S[0];
D[2] = (S[-step] + S[step] + 1) / 2;
if (!blue)
std::swap(D[0], D[2]);
}
}
D = dst.ptr<uchar>(y + 1) - dcn;
for (int i = 0; i < dcn; ++i)
{
D[i] = D[-dcn + i];
D[-static_cast<int>(dst.step)+dcn+i] = D[-static_cast<int>(dst.step)+(dcn<<1)+i];
}
start_with_green ^= 1;
blue ^= 1;
}
++size.width;
uchar* firstRow = dst.data, *lastRow = dst.data + size.height * dst.step;
size.width *= dcn;
for (int x = 0; x < size.width; ++x)
{
firstRow[x] = firstRow[dst.step + x];
lastRow[x] = lastRow[-static_cast<int>(dst.step)+x];
}
}
template <typename T>
static void checkData(const Mat& actual, const Mat& reference, cvtest::TS* ts, const char* type,
bool& next, const char* bayer_type)
{
EXPECT_EQ(actual.size(), reference.size());
EXPECT_EQ(actual.channels(), reference.channels());
EXPECT_EQ(actual.depth(), reference.depth());
Size size = reference.size();
int dcn = reference.channels();
size.width *= dcn;
for (int y = 0; y < size.height && next; ++y)
{
const T* A = reinterpret_cast<const T*>(actual.data + actual.step * y);
const T* R = reinterpret_cast<const T*>(reference.data + reference.step * y);
for (int x = 0; x < size.width && next; ++x)
if (std::abs(A[x] - R[x]) > 1)
{
#define SUM cvtest::TS::SUMMARY
ts->printf(SUM, "\nReference value: %d\n", static_cast<int>(R[x]));
ts->printf(SUM, "Actual value: %d\n", static_cast<int>(A[x]));
ts->printf(SUM, "(y, x): (%d, %d)\n", y, x / reference.channels());
ts->printf(SUM, "Channel pos: %d\n", x % reference.channels());
ts->printf(SUM, "Pattern: %s\n", type);
ts->printf(SUM, "Bayer image type: %s", bayer_type);
#undef SUM
Mat diff;
absdiff(actual, reference, diff);
EXPECT_EQ(countNonZero(diff.reshape(1) > 1), 0);
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts->set_gtest_status();
next = false;
}
}
}
TEST(ImgProc_BayerEdgeAwareDemosaicing, accuracy)
{
cvtest::TS* ts = cvtest::TS::ptr();
const std::string image_name = "lena.png";
const std::string parent_path = string(ts->get_data_path()) + "/cvtcolor_strict/";
Mat src, bayer;
std::string full_path = parent_path + image_name;
src = imread(full_path, CV_LOAD_IMAGE_UNCHANGED);
if (src.data == NULL)
{
ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA);
ts->printf(cvtest::TS::SUMMARY, "No input image\n");
ts->set_gtest_status();
return;
}
/*
COLOR_BayerBG2BGR_EA = 127,
COLOR_BayerGB2BGR_EA = 128,
COLOR_BayerRG2BGR_EA = 129,
COLOR_BayerGR2BGR_EA = 130,
*/
bool next = true;
const char* types[] = { "bg", "gb", "rg", "gr" };
for (int i = 0; i < 4 && next; ++i)
{
calculateBayerPattern<uchar, CV_8U>(src, bayer, types[i]);
Mat reference;
test_Bayer2RGB_EdgeAware_8u(bayer, reference, CV_BayerBG2BGR_EA + i);
for (int t = 0; t <= 1; ++t)
{
if (t == 1)
calculateBayerPattern<unsigned short int, CV_16U>(src, bayer, types[i]);
CV_Assert(!bayer.empty() && (bayer.type() == CV_8UC1 || bayer.type() == CV_16UC1));
Mat actual;
cv::demosaicing(bayer, actual, CV_BayerBG2BGR_EA + i);
if (t == 0)
checkData<unsigned char>(actual, reference, ts, types[i], next, "CV_8U");
else
{
Mat tmp;
reference.convertTo(tmp, CV_16U);
checkData<unsigned short int>(actual, tmp, ts, types[i], next, "CV_16U");
}
}
}
}
TEST(ImgProc_Bayer2RGBA, accuracy)
{
cvtest::TS* ts = cvtest::TS::ptr();
Mat raw = imread(string(ts->get_data_path()) + "/cvtcolor/bayer_input.png", CV_LOAD_IMAGE_GRAYSCALE);
Mat rgb, reference;
CV_Assert(raw.channels() == 1);
CV_Assert(raw.depth() == CV_8U);
CV_Assert(!raw.empty());
for (int code = CV_BayerBG2BGR; code <= CV_BayerGR2BGR; ++code)
{
cvtColor(raw, rgb, code);
cvtColor(rgb, reference, CV_BGR2BGRA);
Mat actual;
cvtColor(raw, actual, code, 4);
EXPECT_EQ(reference.size(), actual.size());
EXPECT_EQ(reference.depth(), actual.depth());
EXPECT_EQ(reference.channels(), actual.channels());
Size ssize = raw.size();
int cn = reference.channels();
ssize.width *= cn;
bool next = true;
for (int y = 0; y < ssize.height && next; ++y)
{
const uchar* rD = reference.ptr<uchar>(y);
const uchar* D = actual.ptr<uchar>(y);
for (int x = 0; x < ssize.width && next; ++x)
if (abs(rD[x] - D[x]) >= 1)
{
next = false;
ts->printf(cvtest::TS::SUMMARY, "Error in: (%d, %d)\n", x / cn, y);
ts->printf(cvtest::TS::SUMMARY, "Reference value: %d\n", rD[x]);
ts->printf(cvtest::TS::SUMMARY, "Actual value: %d\n", D[x]);
ts->printf(cvtest::TS::SUMMARY, "Src value: %d\n", raw.ptr<uchar>(y)[x]);
ts->printf(cvtest::TS::SUMMARY, "Size: (%d, %d)\n", reference.rows, reference.cols);
Mat diff;
absdiff(actual, reference, diff);
EXPECT_EQ(countNonZero(diff.reshape(1) > 1), 0);
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts->set_gtest_status();
}
}
}
} }

View File

@@ -3,6 +3,19 @@
import os, sys, re, string, glob import os, sys, re, string, glob
from optparse import OptionParser from optparse import OptionParser
# Black list for classes and methods that does not implemented in Java API
# Created to exclude referencies to them in @see tag
JAVADOC_ENTITY_BLACK_LIST = set(["org.opencv.core.Core#abs", \
"org.opencv.core.Core#theRNG", \
"org.opencv.core.Core#extractImageCOI", \
"org.opencv.core.PCA", \
"org.opencv.core.SVD", \
"org.opencv.core.RNG", \
"org.opencv.imgproc.Imgproc#createMorphologyFilter", \
"org.opencv.imgproc.Imgproc#createLinearFilter", \
"org.opencv.imgproc.Imgproc#createSeparableLinearFilter", \
"org.opencv.imgproc.FilterEngine"])
class JavadocGenerator(object): class JavadocGenerator(object):
def __init__(self, definitions = {}, modules= [], javadoc_marker = "//javadoc:"): def __init__(self, definitions = {}, modules= [], javadoc_marker = "//javadoc:"):
self.definitions = definitions self.definitions = definitions
@@ -214,9 +227,9 @@ class JavadocGenerator(object):
for see in decl["seealso"]: for see in decl["seealso"]:
seedecl = self.definitions.get(see,None) seedecl = self.definitions.get(see,None)
if seedecl: if seedecl:
doc += prefix + " * @see " + self.getJavaName(seedecl, "#") + "\n" javadoc_name = self.getJavaName(seedecl, "#")
else: if (javadoc_name not in JAVADOC_ENTITY_BLACK_LIST):
doc += prefix + " * @see " + see.replace("::",".") + "\n" doc += prefix + " * @see " + javadoc_name + "\n"
prefix = " *\n" prefix = " *\n"
#doc += prefix + " * File: " + decl["file"] + " (line " + str(decl["line"]) + ")\n" #doc += prefix + " * File: " + decl["file"] + " (line " + str(decl["line"]) + ")\n"

View File

@@ -344,7 +344,7 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac
* @param supportedSizes * @param supportedSizes
* @param surfaceWidth * @param surfaceWidth
* @param surfaceHeight * @param surfaceHeight
* @return * @return optimal frame size
*/ */
protected Size calculateCameraFrameSize(List<?> supportedSizes, ListItemAccessor accessor, int surfaceWidth, int surfaceHeight) { protected Size calculateCameraFrameSize(List<?> supportedSizes, ListItemAccessor accessor, int surfaceWidth, int surfaceHeight) {
int calcWidth = 0; int calcWidth = 0;

View File

@@ -31,7 +31,7 @@ public class OpenCVLoader
* @param Version OpenCV library version. * @param Version OpenCV library version.
* @param AppContext application context for connecting to the service. * @param AppContext application context for connecting to the service.
* @param Callback object, that implements LoaderCallbackInterface for handling the connection status. * @param Callback object, that implements LoaderCallbackInterface for handling the connection status.
* @return Returns true if initialization of OpenCV is successful. * @return Returns true if initialization of OpenCV is successful.
*/ */
public static boolean initAsync(String Version, Context AppContext, public static boolean initAsync(String Version, Context AppContext,
LoaderCallbackInterface Callback) LoaderCallbackInterface Callback)

View File

@@ -64,11 +64,11 @@ int CV_SLMLTest::run_test_case( int testCaseIdx )
if( code == cvtest::TS::OK ) if( code == cvtest::TS::OK )
{ {
get_error( testCaseIdx, CV_TEST_ERROR, &test_resps1 ); get_error( testCaseIdx, CV_TEST_ERROR, &test_resps1 );
fname1 = tempfile(); fname1 = tempfile(".yml.gz");
save( fname1.c_str() ); save( fname1.c_str() );
load( fname1.c_str() ); load( fname1.c_str() );
get_error( testCaseIdx, CV_TEST_ERROR, &test_resps2 ); get_error( testCaseIdx, CV_TEST_ERROR, &test_resps2 );
fname2 = tempfile(); fname2 = tempfile(".yml.gz");
save( fname2.c_str() ); save( fname2.c_str() );
} }
else else

View File

@@ -27,7 +27,7 @@ PERF_TEST_P(surf, detect, testing::Values(SURF_IMAGES))
TEST_CYCLE() detector(frame, mask, points); TEST_CYCLE() detector(frame, mask, points);
SANITY_CHECK_KEYPOINTS(points); SANITY_CHECK_KEYPOINTS(points, 1e-3);
} }
PERF_TEST_P(surf, extract, testing::Values(SURF_IMAGES)) PERF_TEST_P(surf, extract, testing::Values(SURF_IMAGES))
@@ -67,6 +67,6 @@ PERF_TEST_P(surf, full, testing::Values(SURF_IMAGES))
TEST_CYCLE() detector(frame, mask, points, descriptors, false); TEST_CYCLE() detector(frame, mask, points, descriptors, false);
SANITY_CHECK_KEYPOINTS(points); SANITY_CHECK_KEYPOINTS(points, 1e-3);
SANITY_CHECK(descriptors, 1e-4); SANITY_CHECK(descriptors, 1e-4);
} }

View File

@@ -534,12 +534,14 @@ public:
int shrinkage; int shrinkage;
}; };
enum { NO_REJECT = 1, DOLLAR = 2, /*PASCAL = 4,*/ DEFAULT = NO_REJECT};
// An empty cascade will be created. // An empty cascade will be created.
// Param minScale is a minimum scale relative to the original size of the image on which cascade will be applyed. // Param minScale is a minimum scale relative to the original size of the image on which cascade will be applyed.
// Param minScale is a maximum scale relative to the original size of the image on which cascade will be applyed. // Param minScale is a maximum scale relative to the original size of the image on which cascade will be applyed.
// Param scales is a number of scales from minScale to maxScale. // Param scales is a number of scales from minScale to maxScale.
// Param rejfactor is used for NMS. // Param rejCriteria is used for NMS.
CV_WRAP SCascade(const double minScale = 0.4, const double maxScale = 5., const int scales = 55, const int rejfactor = 1); CV_WRAP SCascade(const double minScale = 0.4, const double maxScale = 5., const int scales = 55, const int rejCriteria = 1);
CV_WRAP virtual ~SCascade(); CV_WRAP virtual ~SCascade();
@@ -571,7 +573,7 @@ private:
double maxScale; double maxScale;
int scales; int scales;
int rejfactor; int rejCriteria;
}; };
CV_EXPORTS bool initModule_objdetect(void); CV_EXPORTS bool initModule_objdetect(void);

View File

@@ -14,11 +14,7 @@ PERF_TEST_P(ImageName_MinSize, CascadeClassifierLBPFrontalFace,
testing::Combine(testing::Values( std::string("cv/shared/lena.png"), testing::Combine(testing::Values( std::string("cv/shared/lena.png"),
std::string("cv/shared/1_itseez-0000289.png"), std::string("cv/shared/1_itseez-0000289.png"),
std::string("cv/shared/1_itseez-0000492.png"), std::string("cv/shared/1_itseez-0000492.png"),
std::string("cv/shared/1_itseez-0000573.png"), std::string("cv/shared/1_itseez-0000573.png")),
std::string("cv/shared/1_itseez-0000892.png"),
std::string("cv/shared/1_itseez-0001238.png"),
std::string("cv/shared/1_itseez-0001438.png"),
std::string("cv/shared/1_itseez-0002524.png")),
testing::Values(24, 30, 40, 50, 60, 70, 80, 90) testing::Values(24, 30, 40, 50, 60, 70, 80, 90)
) )
) )

View File

@@ -46,10 +46,10 @@ namespace cv
{ {
CV_INIT_ALGORITHM(SCascade, "CascadeDetector.SCascade", CV_INIT_ALGORITHM(SCascade, "CascadeDetector.SCascade",
obj.info()->addParam(obj, "minScale", obj.minScale); obj.info()->addParam(obj, "minScale", obj.minScale);
obj.info()->addParam(obj, "maxScale", obj.maxScale); obj.info()->addParam(obj, "maxScale", obj.maxScale);
obj.info()->addParam(obj, "scales", obj.scales); obj.info()->addParam(obj, "scales", obj.scales);
obj.info()->addParam(obj, "rejfactor", obj.rejfactor)); obj.info()->addParam(obj, "rejCriteria", obj.rejCriteria));
bool initModule_objdetect(void) bool initModule_objdetect(void)
{ {

View File

@@ -422,7 +422,7 @@ struct cv::SCascade::Fields
}; };
cv::SCascade::SCascade(const double mins, const double maxs, const int nsc, const int rej) cv::SCascade::SCascade(const double mins, const double maxs, const int nsc, const int rej)
: fields(0), minScale(mins), maxScale(maxs), scales(nsc), rejfactor(rej) {} : fields(0), minScale(mins), maxScale(maxs), scales(nsc), rejCriteria(rej) {}
cv::SCascade::~SCascade() { delete fields;} cv::SCascade::~SCascade() { delete fields;}
@@ -439,6 +439,57 @@ bool cv::SCascade::load(const FileNode& fn)
return fields->fill(fn); return fields->fill(fn);
} }
namespace {
typedef cv::SCascade::Detection Detection;
typedef std::vector<Detection> dvector;
struct ConfidenceGt
{
bool operator()(const Detection& a, const Detection& b) const
{
return a.confidence > b.confidence;
}
};
static float overlap(const cv::Rect &a, const cv::Rect &b)
{
int w = std::min(a.x + a.width, b.x + b.width) - std::max(a.x, b.x);
int h = std::min(a.y + a.height, b.y + b.height) - std::max(a.y, b.y);
return (w < 0 || h < 0)? 0.f : (float)(w * h);
}
void DollarNMS(dvector& objects)
{
static const float DollarThreshold = 0.65f;
std::sort(objects.begin(), objects.end(), ConfidenceGt());
for (dvector::iterator dIt = objects.begin(); dIt != objects.end(); ++dIt)
{
const Detection &a = *dIt;
for (dvector::iterator next = dIt + 1; next != objects.end(); )
{
const Detection &b = *next;
const float ovl = overlap(a.bb, b.bb) / std::min(a.bb.area(), b.bb.area());
if (ovl > DollarThreshold)
next = objects.erase(next);
else
++next;
}
}
}
static void suppress(int type, std::vector<Detection>& objects)
{
CV_Assert(type == cv::SCascade::DOLLAR);
DollarNMS(objects);
}
}
void cv::SCascade::detectNoRoi(const cv::Mat& image, std::vector<Detection>& objects) const void cv::SCascade::detectNoRoi(const cv::Mat& image, std::vector<Detection>& objects) const
{ {
Fields& fld = *fields; Fields& fld = *fields;
@@ -459,6 +510,8 @@ void cv::SCascade::detectNoRoi(const cv::Mat& image, std::vector<Detection>& obj
} }
} }
} }
if (rejCriteria != NO_REJECT) suppress(rejCriteria, objects);
} }
void cv::SCascade::detect(cv::InputArray _image, cv::InputArray _rois, std::vector<Detection>& objects) const void cv::SCascade::detect(cv::InputArray _image, cv::InputArray _rois, std::vector<Detection>& objects) const
@@ -506,6 +559,8 @@ void cv::SCascade::detect(cv::InputArray _image, cv::InputArray _rois, std::vect
} }
} }
} }
if (rejCriteria != NO_REJECT) suppress(rejCriteria, objects);
} }
void cv::SCascade::detect(InputArray _image, InputArray _rois, OutputArray _rects, OutputArray _confs) const void cv::SCascade::detect(InputArray _image, InputArray _rois, OutputArray _rects, OutputArray _confs) const

View File

@@ -19,7 +19,7 @@ typedef TestBaseWithParam<String> match;
typedef std::tr1::tuple<String, int> matchVector_t; typedef std::tr1::tuple<String, int> matchVector_t;
typedef TestBaseWithParam<matchVector_t> matchVector; typedef TestBaseWithParam<matchVector_t> matchVector;
#ifdef HAVE_OPENCV_NONFREE #ifdef HAVE_OPENCV_NONFREE_TODO_FIND_WHY_SURF_IS_NOT_ABLE_TO_STITCH_PANOS
#define TEST_DETECTORS testing::Values("surf", "orb") #define TEST_DETECTORS testing::Values("surf", "orb")
#else #else
#define TEST_DETECTORS testing::Values<String>("orb") #define TEST_DETECTORS testing::Values<String>("orb")
@@ -57,7 +57,11 @@ PERF_TEST_P(stitch, a123, TEST_DETECTORS)
stopTimer(); stopTimer();
} }
SANITY_CHECK(pano, 2); Mat pano_small;
if (!pano.empty())
resize(pano, pano_small, Size(320, 240), 0, 0, INTER_AREA);
SANITY_CHECK(pano_small, 5);
} }
PERF_TEST_P(stitch, b12, TEST_DETECTORS) PERF_TEST_P(stitch, b12, TEST_DETECTORS)
@@ -91,7 +95,11 @@ PERF_TEST_P(stitch, b12, TEST_DETECTORS)
stopTimer(); stopTimer();
} }
SANITY_CHECK(pano, 2); Mat pano_small;
if (!pano.empty())
resize(pano, pano_small, Size(320, 240), 0, 0, INTER_AREA);
SANITY_CHECK(pano_small, 5);
} }
PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS) PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS)
@@ -137,7 +145,11 @@ PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS)
matcher->collectGarbage(); matcher->collectGarbage();
} }
SANITY_CHECK_MATCHES(pairwise_matches.matches); std::vector<DMatch>& matches = pairwise_matches.matches;
if (GetParam() == "orb") matches.resize(0);
for(size_t q = 0; q < matches.size(); ++q)
if (matches[q].imgIdx < 0) { matches.resize(q); break;}
SANITY_CHECK_MATCHES(matches);
} }
PERF_TEST_P( matchVector, bestOf2NearestVectorFeatures, testing::Combine( PERF_TEST_P( matchVector, bestOf2NearestVectorFeatures, testing::Combine(
@@ -193,6 +205,8 @@ PERF_TEST_P( matchVector, bestOf2NearestVectorFeatures, testing::Combine(
} }
std::vector<DMatch>& matches = pairwise_matches[0].matches; std::vector<DMatch>& matches = pairwise_matches[detectorName == "surf" ? 1 : 0].matches;
for(size_t q = 0; q < matches.size(); ++q)
if (matches[q].imgIdx < 0) { matches.resize(q); break;}
SANITY_CHECK_MATCHES(matches); SANITY_CHECK_MATCHES(matches);
} }

View File

@@ -350,7 +350,7 @@ void SurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
Mat gray_image; Mat gray_image;
CV_Assert(image.type() == CV_8UC3); CV_Assert(image.type() == CV_8UC3);
cvtColor(image, gray_image, CV_BGR2GRAY); cvtColor(image, gray_image, CV_BGR2GRAY);
if (surf == 0) if (surf.empty())
{ {
detector_->detect(gray_image, features.keypoints); detector_->detect(gray_image, features.keypoints);
extractor_->compute(gray_image, features.keypoints, features.descriptors); extractor_->compute(gray_image, features.keypoints, features.descriptors);

View File

@@ -433,8 +433,8 @@
// Defines this to true iff Google Test can use POSIX regular expressions. // Defines this to true iff Google Test can use POSIX regular expressions.
#ifndef GTEST_HAS_POSIX_RE #ifndef GTEST_HAS_POSIX_RE
# if GTEST_OS_LINUX_ANDROID # if GTEST_OS_LINUX_ANDROID
// On Android, <regex.h> is only available starting with Gingerbread. // On Android, <regex.h> is only available starting with Froyo.
# define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9) # define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 8)
# else # else
# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) # define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
#endif #endif

View File

@@ -66,13 +66,13 @@ parse_patterns = (
{'name': "opencv_cxx_flags_debug", 'default': "", 'pattern': re.compile("^OPENCV_EXTRA_C_FLAGS_DEBUG:INTERNAL=(.*)$")}, {'name': "opencv_cxx_flags_debug", 'default': "", 'pattern': re.compile("^OPENCV_EXTRA_C_FLAGS_DEBUG:INTERNAL=(.*)$")},
{'name': "opencv_cxx_flags_release", 'default': "", 'pattern': re.compile("^OPENCV_EXTRA_C_FLAGS_RELEASE:INTERNAL=(.*)$")}, {'name': "opencv_cxx_flags_release", 'default': "", 'pattern': re.compile("^OPENCV_EXTRA_C_FLAGS_RELEASE:INTERNAL=(.*)$")},
{'name': "cxx_flags_android", 'default': None, 'pattern': re.compile("^ANDROID_CXX_FLAGS:INTERNAL=(.*)$")}, {'name': "cxx_flags_android", 'default': None, 'pattern': re.compile("^ANDROID_CXX_FLAGS:INTERNAL=(.*)$")},
{'name': "cxx_compiler_path", 'default': None, 'pattern': re.compile("^CMAKE_CXX_COMPILER:FILEPATH=(.*)$")},
{'name': "ndk_path", 'default': None, 'pattern': re.compile("^(?:ANDROID_NDK|ANDROID_STANDALONE_TOOLCHAIN)?:PATH=(.*)$")}, {'name': "ndk_path", 'default': None, 'pattern': re.compile("^(?:ANDROID_NDK|ANDROID_STANDALONE_TOOLCHAIN)?:PATH=(.*)$")},
{'name': "android_abi", 'default': None, 'pattern': re.compile("^ANDROID_ABI:STRING=(.*)$")}, {'name': "android_abi", 'default': None, 'pattern': re.compile("^ANDROID_ABI:STRING=(.*)$")},
{'name': "android_executable", 'default': None, 'pattern': re.compile("^ANDROID_EXECUTABLE:FILEPATH=(.*android.*)$")}, {'name': "android_executable", 'default': None, 'pattern': re.compile("^ANDROID_EXECUTABLE:FILEPATH=(.*android.*)$")},
{'name': "is_x64", 'default': "OFF", 'pattern': re.compile("^CUDA_64_BIT_DEVICE_CODE:BOOL=(ON)$")},#ugly( {'name': "is_x64", 'default': "OFF", 'pattern': re.compile("^CUDA_64_BIT_DEVICE_CODE:BOOL=(ON)$")},#ugly(
{'name': "cmake_generator", 'default': None, 'pattern': re.compile("^CMAKE_GENERATOR:INTERNAL=(.+)$")}, {'name': "cmake_generator", 'default': None, 'pattern': re.compile("^CMAKE_GENERATOR:INTERNAL=(.+)$")},
{'name': "cxx_compiler", 'default': None, 'pattern': re.compile("^CMAKE_CXX_COMPILER:FILEPATH=(.+)$")}, {'name': "cxx_compiler", 'default': None, 'pattern': re.compile("^CMAKE_CXX_COMPILER:FILEPATH=(.+)$")},
{'name': "cxx_compiler_arg1", 'default': None, 'pattern': re.compile("^CMAKE_CXX_COMPILER_ARG1:[A-Z]+=(.+)$")},
{'name': "with_cuda", 'default': "OFF", 'pattern': re.compile("^WITH_CUDA:BOOL=(ON)$")}, {'name': "with_cuda", 'default': "OFF", 'pattern': re.compile("^WITH_CUDA:BOOL=(ON)$")},
{'name': "cuda_library", 'default': None, 'pattern': re.compile("^CUDA_CUDA_LIBRARY:FILEPATH=(.+)$")}, {'name': "cuda_library", 'default': None, 'pattern': re.compile("^CUDA_CUDA_LIBRARY:FILEPATH=(.+)$")},
{'name': "core_dependencies", 'default': None, 'pattern': re.compile("^opencv_core_LIB_DEPENDS:STATIC=(.+)$")}, {'name': "core_dependencies", 'default': None, 'pattern': re.compile("^opencv_core_LIB_DEPENDS:STATIC=(.+)$")},
@@ -199,40 +199,51 @@ def getRunningProcessExePathByName(name):
except: except:
return None return None
class RunInfo(object): class TestSuite(object):
def setCallback(self, name, callback): def __init__(self, options, path = None):
setattr(self, name, callback)
def __init__(self, path, options):
self.options = options self.options = options
self.path = path self.path = path
self.error = None self.error = None
self.setUp = None self.setUp = None
self.tearDown = None self.tearDown = None
self.nameprefix = "opencv_" + options.mode + "_" self.adb = None
self.targetos = None
self.nameprefix = "opencv_" + self.options.mode + "_"
for p in parse_patterns: for p in parse_patterns:
setattr(self, p["name"], p["default"]) setattr(self, p["name"], p["default"])
cachefile = open(os.path.join(path, "CMakeCache.txt"), "rt")
try:
for l in cachefile.readlines():
ll = l.strip()
if not ll or ll.startswith("#"):
continue
for p in parse_patterns:
match = p["pattern"].match(ll)
if match:
value = match.groups()[0]
if value and not value.endswith("-NOTFOUND"):
setattr(self, p["name"], value)
except:
pass
cachefile.close()
if self.path:
cachefile = open(os.path.join(self.path, "CMakeCache.txt"), "rt")
try:
for l in cachefile.readlines():
ll = l.strip()
if not ll or ll.startswith("#"):
continue
for p in parse_patterns:
match = p["pattern"].match(ll)
if match:
value = match.groups()[0]
if value and not value.endswith("-NOTFOUND"):
setattr(self, p["name"], value)
except:
pass
cachefile.close()
# detect target platform
if self.android_executable or self.android_abi or self.ndk_path:
self.targetos = "android"
else:
self.targetos = hostos
self.initialize()
def initialize(self):
# fix empty tests dir # fix empty tests dir
if not self.tests_dir: if not self.tests_dir:
self.tests_dir = self.path self.tests_dir = self.path
self.tests_dir = os.path.normpath(self.tests_dir) self.tests_dir = os.path.normpath(self.tests_dir)
# add path to adb
# compute path to adb
if self.android_executable: if self.android_executable:
self.adb = os.path.join(os.path.dirname(os.path.dirname(self.android_executable)), ("platform-tools/adb","platform-tools/adb.exe")[hostos == 'nt']) self.adb = os.path.join(os.path.dirname(os.path.dirname(self.android_executable)), ("platform-tools/adb","platform-tools/adb.exe")[hostos == 'nt'])
if not os.path.isfile(self.adb) or not os.access(self.adb, os.X_OK): if not os.path.isfile(self.adb) or not os.access(self.adb, os.X_OK):
@@ -240,20 +251,14 @@ class RunInfo(object):
else: else:
self.adb = None self.adb = None
# detect target platform
if self.android_executable or self.android_abi or self.ndk_path:
self.targetos = "android"
else:
self.targetos = hostos
if self.targetos == "android": if self.targetos == "android":
# fix adb tool location # fix adb tool location
if not self.adb: if not self.adb:
self.adb = getRunningProcessExePathByName("adb") self.adb = getRunningProcessExePathByName("adb")
if not self.adb: if not self.adb:
self.adb = "adb" self.adb = "adb"
if options.adb_serial: if self.options.adb_serial:
self.adb = [self.adb, "-s", options.adb_serial] self.adb = [self.adb, "-s", self.options.adb_serial]
else: else:
self.adb = [self.adb] self.adb = [self.adb]
try: try:
@@ -261,7 +266,7 @@ class RunInfo(object):
except OSError: except OSError:
self.adb = [] self.adb = []
# remember current device serial. Needed if another device is connected while this script runs # remember current device serial. Needed if another device is connected while this script runs
if self.adb and not options.adb_serial: if self.adb and not self.options.adb_serial:
adb_res = self.runAdb("devices") adb_res = self.runAdb("devices")
if not adb_res: if not adb_res:
self.error = "Could not run adb command: %s (for %s)" % (self.error, self.path) self.error = "Could not run adb command: %s (for %s)" % (self.error, self.path)
@@ -276,13 +281,10 @@ class RunInfo(object):
self.error = "Too many (%s) devices are connected. Please specify single device using --serial option:\n\n" % (len(connected_devices)) + adb_res self.error = "Too many (%s) devices are connected. Please specify single device using --serial option:\n\n" % (len(connected_devices)) + adb_res
self.adb = [] self.adb = []
else: else:
options.adb_serial = connected_devices[0].split("\t")[0] self.options.adb_serial = connected_devices[0].split("\t")[0]
self.adb = self.adb + ["-s", options.adb_serial] self.adb = self.adb + ["-s", self.options.adb_serial]
if self.adb: if self.adb:
print "adb command:", " ".join(self.adb) # construct name for aapt tool
if self.adb:
#construct name for aapt tool
self.aapt = [os.path.join(os.path.dirname(self.adb[0]), ("aapt","aapt.exe")[hostos == 'nt'])] self.aapt = [os.path.join(os.path.dirname(self.adb[0]), ("aapt","aapt.exe")[hostos == 'nt'])]
# fix has_perf_tests param # fix has_perf_tests param
@@ -295,14 +297,17 @@ class RunInfo(object):
# fix test path # fix test path
if "Visual Studio" in self.cmake_generator: if "Visual Studio" in self.cmake_generator:
if options.configuration: if self.options.configuration:
self.tests_dir = os.path.join(self.tests_dir, options.configuration) self.tests_dir = os.path.join(self.tests_dir, self.options.configuration)
else: else:
self.tests_dir = os.path.join(self.tests_dir, self.build_type) self.tests_dir = os.path.join(self.tests_dir, self.build_type)
elif not self.is_x64 and self.cxx_compiler: elif not self.is_x64 and self.cxx_compiler:
#one more attempt to detect x64 compiler #one more attempt to detect x64 compiler
try: try:
output = Popen([self.cxx_compiler, "-v"], stdout=PIPE, stderr=PIPE).communicate() compiler = [self.cxx_compiler]
if self.cxx_compiler_arg1:
compiler.append(self.cxx_compiler_arg1)
output = Popen(compiler + ["-v"], stdout=PIPE, stderr=PIPE).communicate()
if not output[0] and "x86_64" in output[1]: if not output[0] and "x86_64" in output[1]:
self.is_x64 = True self.is_x64 = True
except OSError: except OSError:
@@ -499,9 +504,11 @@ class RunInfo(object):
fd = os.fdopen(tmpfile[0], "w+b") fd = os.fdopen(tmpfile[0], "w+b")
fd.write(SIMD_DETECTION_PROGRAM) fd.write(SIMD_DETECTION_PROGRAM)
fd.close(); fd.close();
options = [self.cxx_compiler_path] options = [self.cxx_compiler]
if self.cxx_compiler_arg1:
options.append(self.cxx_compiler_arg1)
cxx_flags = self.cxx_flags + " " + self.cxx_flags_release + " " + self.opencv_cxx_flags + " " + self.opencv_cxx_flags_release cxx_flags = self.cxx_flags + " " + self.cxx_flags_release + " " + self.opencv_cxx_flags + " " + self.opencv_cxx_flags_release
if self.targetos == "android": if self.targetos == "android" and self.cxx_flags_android:
cxx_flags = self.cxx_flags_android + " " + cxx_flags cxx_flags = self.cxx_flags_android + " " + cxx_flags
prev_option = None prev_option = None
@@ -634,21 +641,21 @@ class RunInfo(object):
logfile = userlog[0][userlog[0].find(":")+1:] logfile = userlog[0][userlog[0].find(":")+1:]
if self.targetos == "android" and exe.endswith(".apk"): if self.targetos == "android" and exe.endswith(".apk"):
print "running java tests:", exe print "Run java tests:", exe
try: try:
# get package info # get package info
output = Popen(self.aapt + ["dump", "xmltree", exe, "AndroidManifest.xml"], stdout=PIPE, stderr=_stderr).communicate() output = Popen(self.aapt + ["dump", "xmltree", exe, "AndroidManifest.xml"], stdout=PIPE, stderr=_stderr).communicate()
if not output[0]: if not output[0]:
print >> _stderr, "failed to get manifest info from", exe print >> _stderr, "fail to dump manifest from", exe
return return
tags = re.split(r"[ ]+E: ", output[0]) tags = re.split(r"[ ]+E: ", output[0])
#get package name # get package name
manifest_tag = [t for t in tags if t.startswith("manifest ")] manifest_tag = [t for t in tags if t.startswith("manifest ")]
if not manifest_tag: if not manifest_tag:
print >> _stderr, "failed to get manifest info from", exe print >> _stderr, "fail to read package name from", exe
return return
pkg_name = re.search(r"^[ ]+A: package=\"(?P<pkg>.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", manifest_tag[0], flags=re.MULTILINE).group("pkg") pkg_name = re.search(r"^[ ]+A: package=\"(?P<pkg>.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", manifest_tag[0], flags=re.MULTILINE).group("pkg")
#get test instrumentation info # get test instrumentation info
instrumentation_tag = [t for t in tags if t.startswith("instrumentation ")] instrumentation_tag = [t for t in tags if t.startswith("instrumentation ")]
if not instrumentation_tag: if not instrumentation_tag:
print >> _stderr, "can not find instrumentation detials in", exe print >> _stderr, "can not find instrumentation detials in", exe
@@ -663,7 +670,7 @@ class RunInfo(object):
pkg_target += self.options.junit_package pkg_target += self.options.junit_package
else: else:
pkg_target = self.options.junit_package pkg_target = self.options.junit_package
#uninstall already installed package # uninstall previously installed package
print >> _stderr, "Uninstalling old", pkg_name, "from device..." print >> _stderr, "Uninstalling old", pkg_name, "from device..."
Popen(self.adb + ["uninstall", pkg_name], stdout=PIPE, stderr=_stderr).communicate() Popen(self.adb + ["uninstall", pkg_name], stdout=PIPE, stderr=_stderr).communicate()
print >> _stderr, "Installing new", exe, "to device...", print >> _stderr, "Installing new", exe, "to device...",
@@ -675,10 +682,10 @@ class RunInfo(object):
print >> _stderr, "Failed to install", exe, "to device" print >> _stderr, "Failed to install", exe, "to device"
return return
print >> _stderr, "Running jUnit tests for ", pkg_target print >> _stderr, "Running jUnit tests for ", pkg_target
if self.setUp is not None: if self.setUp:
self.setUp() self.setUp()
Popen(self.adb + ["shell", "am instrument -w -e package " + pkg_target + " " + pkg_name + "/" + pkg_runner], stdout=_stdout, stderr=_stderr).wait() Popen(self.adb + ["shell", "am instrument -w -e package " + pkg_target + " " + pkg_name + "/" + pkg_runner], stdout=_stdout, stderr=_stderr).wait()
if self.tearDown is not None: if self.tearDown:
self.tearDown() self.tearDown()
except OSError: except OSError:
pass pass
@@ -693,27 +700,27 @@ class RunInfo(object):
andoidcwd = tempdir + getpass.getuser().replace(" ","") + "_" + self.options.mode +"/" andoidcwd = tempdir + getpass.getuser().replace(" ","") + "_" + self.options.mode +"/"
exename = os.path.basename(exe) exename = os.path.basename(exe)
androidexe = andoidcwd + exename androidexe = andoidcwd + exename
#upload # upload
_stderr.write("Uploading... ") _stderr.write("Uploading... ")
output = Popen(self.adb + ["push", exe, androidexe], stdout=_stdout, stderr=_stderr).wait() output = Popen(self.adb + ["push", exe, androidexe], stdout=_stdout, stderr=_stderr).wait()
if output != 0: if output != 0:
print >> _stderr, "adb finishes unexpectedly with error code", output print >> _stderr, "adb finishes unexpectedly with error code", output
return return
#chmod # chmod
output = Popen(self.adb + ["shell", "chmod 777 " + androidexe], stdout=_stdout, stderr=_stderr).wait() output = Popen(self.adb + ["shell", "chmod 777 " + androidexe], stdout=_stdout, stderr=_stderr).wait()
if output != 0: if output != 0:
print >> _stderr, "adb finishes unexpectedly with error code", output print >> _stderr, "adb finishes unexpectedly with error code", output
return return
#run # run
if self.options.help: if self.options.help:
command = exename + " --help" command = exename + " --help"
else: else:
command = exename + " " + " ".join(args) command = exename + " " + " ".join(args)
print >> _stderr, "Run command:", command print >> _stderr, "Run command:", command
if self.setUp is not None: if self.setUp:
self.setUp() self.setUp()
Popen(self.adb + ["shell", "export OPENCV_TEST_DATA_PATH=" + self.test_data_path + "&& cd " + andoidcwd + "&& ./" + command], stdout=_stdout, stderr=_stderr).wait() Popen(self.adb + ["shell", "export OPENCV_TEST_DATA_PATH=" + self.options.test_data_path + "&& cd " + andoidcwd + "&& ./" + command], stdout=_stdout, stderr=_stderr).wait()
if self.tearDown is not None: if self.tearDown:
self.tearDown() self.tearDown()
# try get log # try get log
if not self.options.help: if not self.options.help:
@@ -758,6 +765,7 @@ class RunInfo(object):
try: try:
shutil.rmtree(temp_path) shutil.rmtree(temp_path)
pass
except: except:
pass pass
@@ -767,8 +775,12 @@ class RunInfo(object):
return None return None
def runTests(self, tests, _stdout, _stderr, workingDir, args = []): def runTests(self, tests, _stdout, _stderr, workingDir, args = []):
if not self.isRunnable():
print >> _stderr, "Error:", self.error
if self.error: if self.error:
return [] return []
if self.adb and self.targetos == "android":
print "adb command:", " ".join(self.adb)
if not tests: if not tests:
tests = self.tests tests = self.tests
logs = [] logs = []
@@ -802,7 +814,6 @@ if __name__ == "__main__":
parser = OptionParser() parser = OptionParser()
parser.add_option("-t", "--tests", dest="tests", help="comma-separated list of modules to test", metavar="SUITS", default="") parser.add_option("-t", "--tests", dest="tests", help="comma-separated list of modules to test", metavar="SUITS", default="")
parser.add_option("-w", "--cwd", dest="cwd", help="working directory for tests", metavar="PATH", default=".") parser.add_option("-w", "--cwd", dest="cwd", help="working directory for tests", metavar="PATH", default=".")
parser.add_option("-a", "--accuracy", dest="accuracy", help="look for accuracy tests instead of performance tests", action="store_true", default=False) parser.add_option("-a", "--accuracy", dest="accuracy", help="look for accuracy tests instead of performance tests", action="store_true", default=False)
parser.add_option("-l", "--longname", dest="useLongNames", action="store_true", help="generate log files with long names", default=False) parser.add_option("-l", "--longname", dest="useLongNames", action="store_true", help="generate log files with long names", default=False)
@@ -812,6 +823,7 @@ if __name__ == "__main__":
parser.add_option("", "--package", dest="junit_package", help="Android: run jUnit tests for specified package", metavar="package", default="") parser.add_option("", "--package", dest="junit_package", help="Android: run jUnit tests for specified package", metavar="package", default="")
parser.add_option("", "--help-tests", dest="help", help="Show help for test executable", action="store_true", default=False) parser.add_option("", "--help-tests", dest="help", help="Show help for test executable", action="store_true", default=False)
parser.add_option("", "--check", dest="check", help="Shortcut for '--perf_min_samples=1 --perf_force_samples=1'", action="store_true", default=False) parser.add_option("", "--check", dest="check", help="Shortcut for '--perf_min_samples=1 --perf_force_samples=1'", action="store_true", default=False)
parser.add_option("", "--list", dest="list", help="List available tests", action="store_true", default=False)
(options, args) = parser.parse_args(argv) (options, args) = parser.parse_args(argv)
@@ -823,7 +835,7 @@ if __name__ == "__main__":
run_args = getRunArgs(args[1:] or ['.']) run_args = getRunArgs(args[1:] or ['.'])
if len(run_args) == 0: if len(run_args) == 0:
print >> sys.stderr, "Usage:\n", os.path.basename(sys.argv[0]), "<build_path>" print >> sys.stderr, "Usage:", os.path.basename(sys.argv[0]), "[options] [build_path]"
exit(1) exit(1)
tests = [s.strip() for s in options.tests.split(",") if s] tests = [s.strip() for s in options.tests.split(",") if s]
@@ -833,17 +845,25 @@ if __name__ == "__main__":
test_args = [a for a in test_args if not a.startswith("--gtest_output=")] test_args = [a for a in test_args if not a.startswith("--gtest_output=")]
if options.check: if options.check:
test_args.extend(["--perf_min_samples=1", "--perf_force_samples=1"]) if not [a for a in test_args if a.startswith("--perf_min_samples=")] :
test_args.extend(["--perf_min_samples=1"])
if not [a for a in test_args if a.startswith("--perf_force_samples=")] :
test_args.extend(["--perf_force_samples=1"])
if not [a for a in test_args if a.startswith("--perf_verify_sanity")] :
test_args.extend(["--perf_verify_sanity"])
logs = [] logs = []
test_list = []
for path in run_args: for path in run_args:
info = RunInfo(path, options) suite = TestSuite(options, path)
#print vars(info),"\n" #print vars(suite),"\n"
if not info.isRunnable(): if options.list:
print >> sys.stderr, "Error:", info.error test_list.extend(suite.tests)
else: else:
info.test_data_path = options.test_data_path logs.extend(suite.runTests(tests, sys.stdout, sys.stderr, options.cwd, test_args))
logs.extend(info.runTests(tests, sys.stdout, sys.stderr, options.cwd, test_args))
if options.list:
print os.linesep.join(test_list) or "No tests found"
if logs: if logs:
print >> sys.stderr, "Collected: ", " ".join(logs) print >> sys.stderr, "Collected: ", " ".join(logs)

View File

@@ -1340,6 +1340,7 @@ GTEST_API_ bool IsAsciiWhiteSpace(char ch);
GTEST_API_ bool IsAsciiWordChar(char ch); GTEST_API_ bool IsAsciiWordChar(char ch);
GTEST_API_ bool IsValidEscape(char ch); GTEST_API_ bool IsValidEscape(char ch);
GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
GTEST_API_ std::string FormatRegexSyntaxError(const char* regex, int index);
GTEST_API_ bool ValidateRegex(const char* regex); GTEST_API_ bool ValidateRegex(const char* regex);
GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
GTEST_API_ bool MatchRepetitionAndRegexAtHead( GTEST_API_ bool MatchRepetitionAndRegexAtHead(

View File

@@ -20,7 +20,8 @@ const std::string command_line_keys =
"{ perf_force_samples |100 |force set maximum number of samples for all tests}" "{ perf_force_samples |100 |force set maximum number of samples for all tests}"
"{ perf_seed |809564 |seed for random numbers generator}" "{ perf_seed |809564 |seed for random numbers generator}"
"{ perf_threads |-1 |the number of worker threads, if parallel execution is enabled}" "{ perf_threads |-1 |the number of worker threads, if parallel execution is enabled}"
"{ perf_write_sanity | |allow to create new records for sanity checks}" "{ perf_write_sanity | |create new records for sanity checks}"
"{ perf_verify_sanity | |fail tests having no regression data for sanity checks}"
#ifdef ANDROID #ifdef ANDROID
"{ perf_time_limit |6.0 |default time limit for a single test (in seconds)}" "{ perf_time_limit |6.0 |default time limit for a single test (in seconds)}"
"{ perf_affinity_mask |0 |set affinity mask for the main thread}" "{ perf_affinity_mask |0 |set affinity mask for the main thread}"
@@ -45,6 +46,7 @@ static uint64 param_seed;
static double param_time_limit; static double param_time_limit;
static int param_threads; static int param_threads;
static bool param_write_sanity; static bool param_write_sanity;
static bool param_verify_sanity;
#ifdef HAVE_CUDA #ifdef HAVE_CUDA
static bool param_run_cpu; static bool param_run_cpu;
static int param_cuda_device; static int param_cuda_device;
@@ -307,23 +309,25 @@ double Regression::getElem(cv::Mat& m, int y, int x, int cn)
void Regression::write(cv::Mat m) void Regression::write(cv::Mat m)
{ {
if (!m.empty() && m.dims < 2) return;
double min, max; double min, max;
cv::minMaxLoc(m, &min, &max); cv::minMaxIdx(m, &min, &max);
write() << "min" << min << "max" << max; write() << "min" << min << "max" << max;
write() << "last" << "{" << "x" << m.cols-1 << "y" << m.rows-1 write() << "last" << "{" << "x" << m.size.p[1] - 1 << "y" << m.size.p[0] - 1
<< "val" << getElem(m, m.rows-1, m.cols-1, m.channels()-1) << "}"; << "val" << getElem(m, m.size.p[0] - 1, m.size.p[1] - 1, m.channels() - 1) << "}";
int x, y, cn; int x, y, cn;
x = regRNG.uniform(0, m.cols); x = regRNG.uniform(0, m.size.p[1]);
y = regRNG.uniform(0, m.rows); y = regRNG.uniform(0, m.size.p[0]);
cn = regRNG.uniform(0, m.channels()); cn = regRNG.uniform(0, m.channels());
write() << "rng1" << "{" << "x" << x << "y" << y; write() << "rng1" << "{" << "x" << x << "y" << y;
if(cn > 0) write() << "cn" << cn; if(cn > 0) write() << "cn" << cn;
write() << "val" << getElem(m, y, x, cn) << "}"; write() << "val" << getElem(m, y, x, cn) << "}";
x = regRNG.uniform(0, m.cols); x = regRNG.uniform(0, m.size.p[1]);
y = regRNG.uniform(0, m.rows); y = regRNG.uniform(0, m.size.p[0]);
cn = regRNG.uniform(0, m.channels()); cn = regRNG.uniform(0, m.channels());
write() << "rng2" << "{" << "x" << x << "y" << y; write() << "rng2" << "{" << "x" << x << "y" << y;
if (cn > 0) write() << "cn" << cn; if (cn > 0) write() << "cn" << cn;
@@ -341,8 +345,10 @@ static double evalEps(double expected, double actual, double _eps, ERROR_TYPE er
void Regression::verify(cv::FileNode node, cv::Mat actual, double _eps, std::string argname, ERROR_TYPE err) void Regression::verify(cv::FileNode node, cv::Mat actual, double _eps, std::string argname, ERROR_TYPE err)
{ {
if (!actual.empty() && actual.dims < 2) return;
double actual_min, actual_max; double actual_min, actual_max;
cv::minMaxLoc(actual, &actual_min, &actual_max); cv::minMaxIdx(actual, &actual_min, &actual_max);
double expect_min = (double)node["min"]; double expect_min = (double)node["min"];
double eps = evalEps(expect_min, actual_min, _eps, err); double eps = evalEps(expect_min, actual_min, _eps, err);
@@ -355,12 +361,12 @@ void Regression::verify(cv::FileNode node, cv::Mat actual, double _eps, std::str
<< argname << " has unexpected maximal value" << std::endl; << argname << " has unexpected maximal value" << std::endl;
cv::FileNode last = node["last"]; cv::FileNode last = node["last"];
double actual_last = getElem(actual, actual.rows - 1, actual.cols - 1, actual.channels() - 1); double actual_last = getElem(actual, actual.size.p[0] - 1, actual.size.p[1] - 1, actual.channels() - 1);
int expect_cols = (int)last["x"] + 1; int expect_cols = (int)last["x"] + 1;
int expect_rows = (int)last["y"] + 1; int expect_rows = (int)last["y"] + 1;
ASSERT_EQ(expect_cols, actual.cols) ASSERT_EQ(expect_cols, actual.size.p[1])
<< argname << " has unexpected number of columns" << std::endl; << argname << " has unexpected number of columns" << std::endl;
ASSERT_EQ(expect_rows, actual.rows) ASSERT_EQ(expect_rows, actual.size.p[0])
<< argname << " has unexpected number of rows" << std::endl; << argname << " has unexpected number of rows" << std::endl;
double expect_last = (double)last["val"]; double expect_last = (double)last["val"];
@@ -374,6 +380,8 @@ void Regression::verify(cv::FileNode node, cv::Mat actual, double _eps, std::str
int cn1 = rng1["cn"]; int cn1 = rng1["cn"];
double expect_rng1 = (double)rng1["val"]; double expect_rng1 = (double)rng1["val"];
// it is safe to use x1 and y1 without checks here because we have already
// verified that mat size is the same as recorded
double actual_rng1 = getElem(actual, y1, x1, cn1); double actual_rng1 = getElem(actual, y1, x1, cn1);
eps = evalEps(expect_rng1, actual_rng1, _eps, err); eps = evalEps(expect_rng1, actual_rng1, _eps, err);
@@ -492,10 +500,10 @@ void Regression::verify(cv::FileNode node, cv::InputArray array, double eps, ERR
std::cout << " Expected: " << std::endl << expected << std::endl << " Actual:" << std::endl << actual << std::endl; std::cout << " Expected: " << std::endl << expected << std::endl << " Actual:" << std::endl << actual << std::endl;
double max; double max;
cv::minMaxLoc(diff.reshape(1), 0, &max); cv::minMaxIdx(diff.reshape(1), 0, &max);
FAIL() << " Absolute difference (=" << max << ") between argument \"" FAIL() << " Absolute difference (=" << max << ") between argument \""
<< node.name() << "[" << idx << "]\" and expected value is bugger than " << eps; << node.name() << "[" << idx << "]\" and expected value is greater than " << eps;
} }
} }
else if (err == ERROR_RELATIVE) else if (err == ERROR_RELATIVE)
@@ -505,7 +513,7 @@ void Regression::verify(cv::FileNode node, cv::InputArray array, double eps, ERR
if (violations > 0) if (violations > 0)
{ {
FAIL() << " Relative difference (" << maxv << " of " << maxa << " allowed) between argument \"" FAIL() << " Relative difference (" << maxv << " of " << maxa << " allowed) between argument \""
<< node.name() << "[" << idx << "]\" and expected value is bugger than " << eps << " in " << violations << " points"; << node.name() << "[" << idx << "]\" and expected value is greater than " << eps << " in " << violations << " points";
} }
} }
} }
@@ -546,10 +554,10 @@ void Regression::verify(cv::FileNode node, cv::InputArray array, double eps, ERR
std::cout << " Expected: " << std::endl << expected << std::endl << " Actual:" << std::endl << actual << std::endl; std::cout << " Expected: " << std::endl << expected << std::endl << " Actual:" << std::endl << actual << std::endl;
double max; double max;
cv::minMaxLoc(diff.reshape(1), 0, &max); cv::minMaxIdx(diff.reshape(1), 0, &max);
FAIL() << " Difference (=" << max << ") between argument1 \"" << node.name() FAIL() << " Difference (=" << max << ") between argument1 \"" << node.name()
<< "\" and expected value is bugger than " << eps; << "\" and expected value is greater than " << eps;
} }
} }
else if (err == ERROR_RELATIVE) else if (err == ERROR_RELATIVE)
@@ -559,7 +567,7 @@ void Regression::verify(cv::FileNode node, cv::InputArray array, double eps, ERR
if (violations > 0) if (violations > 0)
{ {
FAIL() << " Relative difference (" << maxv << " of " << maxa << " allowed) between argument \"" << node.name() FAIL() << " Relative difference (" << maxv << " of " << maxa << " allowed) between argument \"" << node.name()
<< "\" and expected value is bugger than " << eps << " in " << violations << " points"; << "\" and expected value is greater than " << eps << " in " << violations << " points";
} }
} }
} }
@@ -599,10 +607,15 @@ Regression& Regression::operator() (const std::string& name, cv::InputArray arra
write() << nodename << "{"; write() << nodename << "{";
} }
// TODO: verify that name is alphanumeric, current error message is useless
write() << name << "{"; write() << name << "{";
write(array); write(array);
write() << "}"; write() << "}";
} }
else if(param_verify_sanity)
{
ADD_FAILURE() << " No regression data for " << name << " argument";
}
} }
else else
{ {
@@ -660,6 +673,7 @@ void TestBase::Init(int argc, const char* const argv[])
param_time_limit = std::max(0., args.get<double>("perf_time_limit")); param_time_limit = std::max(0., args.get<double>("perf_time_limit"));
param_force_samples = args.get<unsigned int>("perf_force_samples"); param_force_samples = args.get<unsigned int>("perf_force_samples");
param_write_sanity = args.has("perf_write_sanity"); param_write_sanity = args.has("perf_write_sanity");
param_verify_sanity = args.has("perf_verify_sanity");
param_threads = args.get<int>("perf_threads"); param_threads = args.get<int>("perf_threads");
#ifdef ANDROID #ifdef ANDROID
param_affinity_mask = args.get<int>("perf_affinity_mask"); param_affinity_mask = args.get<int>("perf_affinity_mask");
@@ -974,7 +988,7 @@ void TestBase::validateMetrics()
if (m.gstddev > DBL_EPSILON) if (m.gstddev > DBL_EPSILON)
{ {
EXPECT_GT(/*m.gmean * */1., /*m.gmean * */ 2 * sinh(m.gstddev * param_max_deviation)) EXPECT_GT(/*m.gmean * */1., /*m.gmean * */ 2 * sinh(m.gstddev * param_max_deviation))
<< " Test results are not reliable ((mean-sigma,mean+sigma) deviation interval is bigger than measured time interval)."; << " Test results are not reliable ((mean-sigma,mean+sigma) deviation interval is greater than measured time interval).";
} }
EXPECT_LE(m.outliers, std::max((unsigned int)cvCeil(m.samples * param_max_outliers / 100.), 1u)) EXPECT_LE(m.outliers, std::max((unsigned int)cvCeil(m.samples * param_max_outliers / 100.), 1u))
@@ -1153,12 +1167,17 @@ void TestBase::RunPerfTestBody()
if (e.code == CV_GpuApiCallError) if (e.code == CV_GpuApiCallError)
cv::gpu::resetDevice(); cv::gpu::resetDevice();
#endif #endif
FAIL() << "Expected: PerfTestBody() doesn't throw an exception.\n Actual: it throws:\n " << e.what(); FAIL() << "Expected: PerfTestBody() doesn't throw an exception.\n Actual: it throws cv::Exception:\n " << e.what();
}
catch(std::exception e)
{
metrics.terminationReason = performance_metrics::TERM_EXCEPTION;
FAIL() << "Expected: PerfTestBody() doesn't throw an exception.\n Actual: it throws std::exception:\n " << e.what();
} }
catch(...) catch(...)
{ {
metrics.terminationReason = performance_metrics::TERM_EXCEPTION; metrics.terminationReason = performance_metrics::TERM_EXCEPTION;
FAIL() << "Expected: PerfTestBody() doesn't throw an exception.\n Actual: it throws."; FAIL() << "Expected: PerfTestBody() doesn't throw an exception.\n Actual: it throws...";
} }
} }

View File

@@ -29,5 +29,5 @@ PERF_TEST_P(ImagePair, OpticalFlowDual_TVL1, testing::Values(impair("cv/optflow/
tvl1(frame1, frame2, flow); tvl1(frame1, frame2, flow);
} }
SANITY_CHECK(flow); SANITY_CHECK(flow, 0.5);
} }

View File

@@ -41,7 +41,7 @@ void CV_BackgroundSubtractorTest::run(int)
Algorithm::create<BackgroundSubtractorGMG>("BackgroundSubtractor.GMG"); Algorithm::create<BackgroundSubtractorGMG>("BackgroundSubtractor.GMG");
Mat fgmask; Mat fgmask;
if (fgbg == NULL) if (fgbg.empty())
CV_Error(CV_StsError,"Failed to create Algorithm\n"); CV_Error(CV_StsError,"Failed to create Algorithm\n");
/** /**

View File

@@ -107,10 +107,41 @@ namespace
} }
} }
} }
bool isFlowCorrect(Point2f u)
{
return !cvIsNaN(u.x) && !cvIsNaN(u.y) && (fabs(u.x) < 1e9) && (fabs(u.y) < 1e9);
}
double calcRMSE(const Mat_<Point2f>& flow1, const Mat_<Point2f>& flow2)
{
double sum = 0.0;
int counter = 0;
for (int i = 0; i < flow1.rows; ++i)
{
for (int j = 0; j < flow1.cols; ++j)
{
const Point2f u1 = flow1(i, j);
const Point2f u2 = flow2(i, j);
if (isFlowCorrect(u1) && isFlowCorrect(u2))
{
const Point2f diff = u1 - u2;
sum += diff.ddot(diff);
++counter;
}
}
}
return sqrt(sum / (1e-9 + counter));
}
} }
TEST(Video_calcOpticalFlowDual_TVL1, Regression) TEST(Video_calcOpticalFlowDual_TVL1, Regression)
{ {
const double MAX_RMSE = 0.02;
const string frame1_path = TS::ptr()->get_data_path() + "optflow/RubberWhale1.png"; const string frame1_path = TS::ptr()->get_data_path() + "optflow/RubberWhale1.png";
const string frame2_path = TS::ptr()->get_data_path() + "optflow/RubberWhale2.png"; const string frame2_path = TS::ptr()->get_data_path() + "optflow/RubberWhale2.png";
const string gold_flow_path = TS::ptr()->get_data_path() + "optflow/tvl1_flow.flo"; const string gold_flow_path = TS::ptr()->get_data_path() + "optflow/tvl1_flow.flo";
@@ -130,7 +161,11 @@ TEST(Video_calcOpticalFlowDual_TVL1, Regression)
#else #else
Mat_<Point2f> gold; Mat_<Point2f> gold;
readOpticalFlowFromFile(gold, gold_flow_path); readOpticalFlowFromFile(gold, gold_flow_path);
double err = norm(gold, flow, NORM_INF);
EXPECT_EQ(0.0f, err); ASSERT_EQ(gold.rows, flow.rows);
ASSERT_EQ(gold.cols, flow.cols);
const double err = calcRMSE(gold, flow);
EXPECT_LE(err, MAX_RMSE);
#endif #endif
} }

View File

@@ -1,5 +1,7 @@
package org.opencv.samples.tutorial5; package org.opencv.samples.tutorial5;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
@@ -9,23 +11,31 @@ import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat; import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener; import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener;
import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.hardware.Camera.Size;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.SubMenu;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.View; import android.view.View;
import android.view.View.OnTouchListener; import android.view.View.OnTouchListener;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Toast;
public class Sample5CameraControl extends Activity implements CvCameraViewListener, OnTouchListener { public class Sample5CameraControl extends Activity implements CvCameraViewListener, OnTouchListener {
private static final String TAG = "OCVSample::Activity"; private static final String TAG = "OCVSample::Activity";
private SampleJavaCameraView mOpenCvCameraView; private SampleJavaCameraView mOpenCvCameraView;
private List<Size> mResolutionList;
private MenuItem[] mEffectMenuItems; private MenuItem[] mEffectMenuItems;
private SubMenu mColorEffectsMenu;
private MenuItem[] mResolutionMenuItems;
private SubMenu mResolutionMenu;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override @Override
@@ -100,28 +110,68 @@ public class Sample5CameraControl extends Activity implements CvCameraViewListen
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
List<String> effects = mOpenCvCameraView.getEffectList(); List<String> effects = mOpenCvCameraView.getEffectList();
if (effects == null) {
Log.e(TAG, "Color effects are not supported by device!");
return true;
}
mColorEffectsMenu = menu.addSubMenu("Color Effect");
mEffectMenuItems = new MenuItem[effects.size()]; mEffectMenuItems = new MenuItem[effects.size()];
int idx = 0; int idx = 0;
ListIterator<String> itr = effects.listIterator(); ListIterator<String> effectItr = effects.listIterator();
while(itr.hasNext()) { while(effectItr.hasNext()) {
String element = itr.next(); String element = effectItr.next();
mEffectMenuItems[idx] = menu.add(element); mEffectMenuItems[idx] = mColorEffectsMenu.add(1, idx, Menu.NONE, element);
idx++; idx++;
} }
mResolutionMenu = menu.addSubMenu("Resolution");
mResolutionList = mOpenCvCameraView.getResolutionList();
mResolutionMenuItems = new MenuItem[mResolutionList.size()];
ListIterator<Size> resolutionItr = mResolutionList.listIterator();
idx = 0;
while(resolutionItr.hasNext()) {
Size element = resolutionItr.next();
mResolutionMenuItems[idx] = mResolutionMenu.add(2, idx, Menu.NONE,
Integer.valueOf(element.width).toString() + "x" + Integer.valueOf(element.height).toString());
idx++;
}
return true; return true;
} }
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item); Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
mOpenCvCameraView.setEffect((String) item.getTitle()); if (item.getGroupId() == 1)
{
mOpenCvCameraView.setEffect((String) item.getTitle());
Toast.makeText(this, mOpenCvCameraView.getEffect(), Toast.LENGTH_SHORT).show();
}
else if (item.getGroupId() == 2)
{
int id = item.getItemId();
Size resolution = mResolutionList.get(id);
mOpenCvCameraView.setResolution(resolution);
resolution = mOpenCvCameraView.getResolution();
String caption = Integer.valueOf(resolution.width).toString() + "x" + Integer.valueOf(resolution.height).toString();
Toast.makeText(this, caption, Toast.LENGTH_SHORT).show();
}
return true; return true;
} }
@SuppressLint("SimpleDateFormat")
@Override @Override
public boolean onTouch(View v, MotionEvent event) { public boolean onTouch(View v, MotionEvent event) {
Log.i(TAG,"onTouch event"); Log.i(TAG,"onTouch event");
mOpenCvCameraView.takePicture(Environment.getExternalStorageDirectory().getPath() + "/sample_picture.jpg"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
String currentDateandTime = sdf.format(new Date());
String fileName = Environment.getExternalStorageDirectory().getPath() +
"/sample_picture_" + currentDateandTime + ".jpg";
mOpenCvCameraView.takePicture(fileName);
Toast.makeText(this, fileName + " saved", Toast.LENGTH_SHORT).show();
return false; return false;
} }
} }

View File

@@ -10,6 +10,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.hardware.Camera; import android.hardware.Camera;
import android.hardware.Camera.PictureCallback; import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
@@ -25,16 +26,35 @@ public class SampleJavaCameraView extends JavaCameraView {
return mCamera.getParameters().getSupportedColorEffects(); return mCamera.getParameters().getSupportedColorEffects();
} }
public boolean isEffectSupported() {
return (mCamera.getParameters().getColorEffect() != null);
}
public String getEffect() { public String getEffect() {
return mCamera.getParameters().getColorEffect(); return mCamera.getParameters().getColorEffect();
} }
public void setEffect(String effect) { public void setEffect(String effect) {
Camera.Parameters params = mCamera.getParameters(); Camera.Parameters params = mCamera.getParameters();
params.setColorEffect(effect); params.setColorEffect(effect);
mCamera.setParameters(params); mCamera.setParameters(params);
} }
public List<Size> getResolutionList() {
return mCamera.getParameters().getSupportedPreviewSizes();
}
public void setResolution(Size resolution) {
disconnectCamera();
mMaxHeight = resolution.height;
mMaxWidth = resolution.width;
connectCamera(getWidth(), getHeight());
}
public Size getResolution() {
return mCamera.getParameters().getPreviewSize();
}
public void takePicture(final String fileName) { public void takePicture(final String fileName) {
Log.i(TAG, "Tacking picture"); Log.i(TAG, "Tacking picture");
PictureCallback callback = new PictureCallback() { PictureCallback callback = new PictureCallback() {
@@ -48,6 +68,7 @@ public class SampleJavaCameraView extends JavaCameraView {
try { try {
FileOutputStream out = new FileOutputStream(mPictureFileName); FileOutputStream out = new FileOutputStream(mPictureFileName);
picture.compress(Bitmap.CompressFormat.JPEG, 90, out); picture.compress(Bitmap.CompressFormat.JPEG, 90, out);
picture.recycle();
mCamera.startPreview(); mCamera.startPreview();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@@ -535,7 +535,7 @@ void DetectorQualityEvaluator::readAlgorithm ()
{ {
defaultDetector = FeatureDetector::create( algName ); defaultDetector = FeatureDetector::create( algName );
specificDetector = FeatureDetector::create( algName ); specificDetector = FeatureDetector::create( algName );
if( defaultDetector == 0 ) if( defaultDetector.empty() )
{ {
printf( "Algorithm can not be read\n" ); printf( "Algorithm can not be read\n" );
exit(-1); exit(-1);
@@ -769,14 +769,14 @@ void DescriptorQualityEvaluator::readAlgorithm( )
defaultDescMatcher = GenericDescriptorMatcher::create( algName ); defaultDescMatcher = GenericDescriptorMatcher::create( algName );
specificDescMatcher = GenericDescriptorMatcher::create( algName ); specificDescMatcher = GenericDescriptorMatcher::create( algName );
if( defaultDescMatcher == 0 ) if( defaultDescMatcher.empty() )
{ {
Ptr<DescriptorExtractor> extractor = DescriptorExtractor::create( algName ); Ptr<DescriptorExtractor> extractor = DescriptorExtractor::create( algName );
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create( matcherName ); Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create( matcherName );
defaultDescMatcher = new VectorDescriptorMatch( extractor, matcher ); defaultDescMatcher = new VectorDescriptorMatch( extractor, matcher );
specificDescMatcher = new VectorDescriptorMatch( extractor, matcher ); specificDescMatcher = new VectorDescriptorMatch( extractor, matcher );
if( extractor == 0 || matcher == 0 ) if( extractor.empty() || matcher.empty() )
{ {
printf("Algorithm can not be read\n"); printf("Algorithm can not be read\n");
exit(-1); exit(-1);

View File

@@ -32,7 +32,7 @@ int main(int argc, char** argv)
std::string params_filename = std::string(argv[4]); std::string params_filename = std::string(argv[4]);
Ptr<GenericDescriptorMatcher> descriptorMatcher = GenericDescriptorMatcher::create(alg_name, params_filename); Ptr<GenericDescriptorMatcher> descriptorMatcher = GenericDescriptorMatcher::create(alg_name, params_filename);
if( descriptorMatcher == 0 ) if( descriptorMatcher.empty() )
{ {
printf ("Cannot create descriptor\n"); printf ("Cannot create descriptor\n");
return 0; return 0;

View File

@@ -55,7 +55,7 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
endforeach() endforeach()
endif() endif()
if (NOT WIN32) if (INSTALL_C_EXAMPLES AND NOT WIN32)
file(GLOB install_list *.c *.cpp *.jpg *.png *.data makefile.* build_all.sh *.dsp *.cmd ) file(GLOB install_list *.c *.cpp *.jpg *.png *.data makefile.* build_all.sh *.dsp *.cmd )
install(FILES ${install_list} install(FILES ${install_list}
DESTINATION share/opencv/samples/${project} DESTINATION share/opencv/samples/${project}