chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:06:04 +08:00
commit 86c9b1c39f
7743 changed files with 3316339 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
if(OPENCV_INITIAL_PASS)
# generator for JNI/JAR source code and documentation signatures
add_subdirectory(generator)
endif()
if(APPLE_FRAMEWORK OR WINRT
OR NOT PYTHON_DEFAULT_AVAILABLE
OR NOT (ANT_EXECUTABLE OR Java_FOUND OR ANDROID_PROJECTS_BUILD_TYPE STREQUAL "GRADLE")
OR NOT (JNI_FOUND OR (ANDROID AND (NOT DEFINED ANDROID_NATIVE_API_LEVEL OR ANDROID_NATIVE_API_LEVEL GREATER 7)))
OR BUILD_opencv_world
)
ocv_module_disable(java)
endif()
set(the_description "The java bindings")
ocv_add_module(java BINDINGS opencv_core opencv_imgproc PRIVATE_REQUIRED opencv_java_bindings_generator)
include(${CMAKE_CURRENT_SOURCE_DIR}/common.cmake)
# UTILITY: glob specific sources and append them to list (type is in H, CPP, JAVA)
macro(glob_more_specific_sources _type _root _output)
unset(_masks)
if(${_type} STREQUAL "H")
set(_masks "${_root}/cpp/*.h" "${_root}/cpp/*.hpp")
elseif(${_type} STREQUAL "CPP")
set(_masks "${_root}/cpp/*.cpp")
elseif(${_type} STREQUAL "JAVA")
set(_masks "${_root}/java/*.java" "${_root}/java/*.java.in")
endif()
if (_masks)
file(GLOB _result ${_masks})
list(APPEND ${_output} ${_result})
else()
message(WARNING "Bad argument passed to macro: skipped")
endif()
endmacro()
# UTILITY: copy common java test files and add them to _deps
# copy_common_tests(<source-folder> <destination-folder> <variable-to-store-deps>)
macro(copy_common_tests _src_location _dst_location _deps)
set(_src ${_src_location})
set(_dst ${_dst_location})
file(GLOB_RECURSE _files RELATIVE "${_src}" "${_src}/res/*" "${_src}/src/*")
foreach(f ${_files})
add_custom_command(
OUTPUT "${_dst}/${f}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_src}/${f}" "${_dst}/${f}"
MAIN_DEPENDENCY "${_src}/${f}"
COMMENT "Copying ${f}")
list(APPEND ${_deps} "${_src}/${f}" "${_dst}/${f}")
endforeach()
unset(_files)
unset(_src)
unset(_dst)
endmacro()
add_subdirectory(jni) # generates ${the_module} target (${the_module}_jni doesn't work properly with Android non-gradle samples)
if(ANDROID)
add_subdirectory(android_sdk) # generates ${the_module}_android target
else()
add_subdirectory(jar) # generates ${the_module}_jar target
endif()
if(BUILD_TESTS)
if(ANDROID)
add_subdirectory(test/android_test)
else()
add_subdirectory(test/pure_test)
endif()
endif()
+242
View File
@@ -0,0 +1,242 @@
project(${the_module}_android)
if(ANDROID_EXECUTABLE)
set(OPENCV_JAVA_DIR "${OpenCV_BINARY_DIR}/android_sdk" CACHE INTERNAL "")
else() # gradle
set(OPENCV_JAVA_DIR "${ANDROID_BUILD_BASE_DIR}/opencv" CACHE INTERNAL "")
endif()
set(OPENCV_ANDROID_LIB_DIR "${OPENCV_JAVA_DIR}" CACHE INTERNAL "") # for OpenCV samples
file(REMOVE_RECURSE "${OPENCV_JAVA_DIR}")
file(MAKE_DIRECTORY "${OPENCV_JAVA_DIR}/bin")
set(java_src_dir "${OPENCV_JAVA_DIR}/src")
file(MAKE_DIRECTORY "${java_src_dir}")
ocv_copyfiles_append_dir(JAVA_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/java" "${java_src_dir}")
set(SOURSE_SETS_JNI_LIBS_SRC_DIRS "'native/libs'")
set(SOURSE_SETS_JAVA_SRC_DIRS "'java/src'")
set(SOURSE_SETS_RES_SRC_DIRS "'java/res'")
set(SOURSE_SETS_MANIFEST_SRC_FILE "'java/AndroidManifest.xml'")
set(BUILD_GRADLE_COMPILE_OPTIONS "
android {
buildFeatures {
buildConfig true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_${ANDROID_GRADLE_JAVA_VERSION_INIT}
targetCompatibility JavaVersion.VERSION_${ANDROID_GRADLE_JAVA_VERSION_INIT}
}
")
set(MAVEN_PUBLISH_PLUGIN_DECLARATION "apply plugin: 'maven-publish'")
set(BUILD_GRADLE_ANDROID_PUBLISHING_CONFIG "
buildFeatures {
prefabPublishing true
buildConfig true
}
prefab {
opencv_jni_shared {
headers 'native/jni/include'
}
}
publishing {
singleVariant('release') {
withSourcesJar()
withJavadocJar()
}
}
")
set(BUILD_GRADLE_PUBLISHING_CONFIG "
publishing {
publications {
release(MavenPublication) {
groupId = 'org.opencv'
artifactId = 'opencv'
version = '${OPENCV_VERSION_PLAIN}'
afterEvaluate {
from components.release
}
}
}
repositories {
maven {
name = 'myrepo'
url = \"\${project.buildDir}/repo\"
}
}
}
")
if(ANDROID_EXECUTABLE)
ocv_assert(ANDROID_TOOLS_Pkg_Revision GREATER 13)
ocv_copyfiles_append_dir(JAVA_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/android/java" "${java_src_dir}")
# calc default SDK Target
android_get_compatible_target(ANDROID_SDK_COMPATIBLE_TARGET ${ANDROID_NATIVE_API_LEVEL} ${ANDROID_SDK_TARGET} 14)
if(ANDROID_SDK_COMPATIBLE_TARGET)
set(ANDROID_SDK_COMPATIBLE_TARGET "${ANDROID_SDK_COMPATIBLE_TARGET}" CACHE INTERNAL "")
endif()
string(REGEX REPLACE "android-" "" android_sdk_target_num ${ANDROID_SDK_COMPATIBLE_TARGET})
if( (ANDROID_SDK_TARGET AND ANDROID_SDK_TARGET LESS 21) OR (android_sdk_target_num LESS 21) )
message(STATUS "[OpenCV for Android SDK]: A new OpenGL Camera Bridge (CameraGLSurfaceView, CameraGLRendererBase, CameraRenderer, Camera2Renderer) is disabled, because ANDROID_SDK_TARGET (${android_sdk_target_num}) < 21")
else()
ocv_copyfiles_append_dir(JAVA_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/android-21/java" "${java_src_dir}")
endif()
if( (ANDROID_SDK_TARGET AND ANDROID_SDK_TARGET LESS 24) OR (android_sdk_target_num LESS 24) )
message(STATUS "[OpenCV for Android SDK]: An experiemntal Native Camera is disabled, because ANDROID_SDK_TARGET (${android_sdk_target_num}) < 24")
else()
ocv_copyfiles_append_dir(JAVA_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/android-24/java" "${java_src_dir}")
endif()
# copy boilerplate
file(GLOB_RECURSE seed_project_files_rel RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/android_lib/" "${CMAKE_CURRENT_SOURCE_DIR}/android_lib/*")
list(REMOVE_ITEM seed_project_files_rel "${ANDROID_MANIFEST_FILE}")
foreach(file ${seed_project_files_rel})
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/android_lib/${file}" "${OPENCV_JAVA_DIR}/${file}" @ONLY)
list(APPEND depends "${CMAKE_CURRENT_SOURCE_DIR}/android_lib/${file}")
get_filename_component(install_subdir "${file}" PATH)
install(FILES "${OPENCV_JAVA_DIR}/${file}" DESTINATION "${JAVA_INSTALL_ROOT}/${install_subdir}" COMPONENT java)
endforeach()
list(APPEND depends gen_opencv_java_source "${OPENCV_DEPHELPER}/gen_opencv_java_source")
ocv_copyfiles_add_target(${the_module}_android_source_copy JAVA_SRC_COPY "Copy Java(Android SDK) source files" ${depends})
file(REMOVE "${OPENCV_DEPHELPER}/${the_module}_android_source_copy") # force rebuild after CMake run
set(depends ${the_module}_android_source_copy "${OPENCV_DEPHELPER}/${the_module}_android_source_copy")
# generate Android library project
set(android_sdk_project_files ${ANDROID_LIB_PROJECT_FILES}) # build.xml;local.properties;proguard-project.txt;project.properties
ocv_list_add_prefix(android_sdk_project_files "${OPENCV_JAVA_DIR}/")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/android_lib/${ANDROID_MANIFEST_FILE}" "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" @ONLY)
add_custom_command(
OUTPUT ${android_sdk_project_files} "${OPENCV_JAVA_DIR}/${ANDROID_MANIFEST_FILE}"
COMMAND ${CMAKE_COMMAND} -E remove ${android_sdk_project_files}
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" "${OPENCV_JAVA_DIR}/${ANDROID_MANIFEST_FILE}"
COMMAND ${ANDROID_EXECUTABLE} --silent create lib-project --path \"${OPENCV_JAVA_DIR}\" --target \"${ANDROID_SDK_COMPATIBLE_TARGET}\" --name OpenCV --package org.opencv 2>\"${CMAKE_CURRENT_BINARY_DIR}/create_lib_project.log\"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" "${OPENCV_JAVA_DIR}/${ANDROID_MANIFEST_FILE}"
WORKING_DIRECTORY "${OPENCV_JAVA_DIR}"
MAIN_DEPENDENCY "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}"
DEPENDS ${depends}
COMMENT "Generating OpenCV Android library project. SDK target: ${lib_target_sdk_target}"
)
list(APPEND depends ${android_sdk_project_files} "${OPENCV_JAVA_DIR}/${ANDROID_MANIFEST_FILE}")
install(DIRECTORY "${OPENCV_JAVA_DIR}/src" DESTINATION "${JAVA_INSTALL_ROOT}" COMPONENT java)
install(FILES "${OPENCV_JAVA_DIR}/${ANDROID_PROJECT_PROPERTIES_FILE}" DESTINATION ${JAVA_INSTALL_ROOT} COMPONENT java)
install(FILES "${OPENCV_JAVA_DIR}/${ANDROID_MANIFEST_FILE}" DESTINATION ${JAVA_INSTALL_ROOT} COMPONENT java)
# build jar
set(JAR_FILE "${OpenCV_BINARY_DIR}/bin/classes.jar")
# build the library project
# normally we should do this after a native part, but for a library project we can build the java part first
add_custom_command(
OUTPUT "${JAR_FILE}" "${OPENCV_DEPHELPER}/${the_module}_android"
COMMAND ${ANT_EXECUTABLE} -q -noinput -k debug -Djava.target=1.6 -Djava.source=1.6
COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/${the_module}_android"
WORKING_DIRECTORY "${OPENCV_JAVA_DIR}"
DEPENDS ${depends}
COMMENT "Building OpenCV Android library project"
)
add_custom_target(${the_module}_android DEPENDS "${OPENCV_DEPHELPER}/${the_module}_android" SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/android_lib/${ANDROID_MANIFEST_FILE}")
add_dependencies(${the_module} ${the_module}_android)
# empty 'gen' and 'res' folders
install(CODE "
FILE(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${JAVA_INSTALL_ROOT}/gen\")
FILE(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${JAVA_INSTALL_ROOT}/res\")
" COMPONENT java)
ocv_update(ANDROID_COMPILE_SDK_VERSION "27")
ocv_update(ANDROID_MIN_SDK_VERSION "14")
if(ANDROID_NATIVE_API_LEVEL GREATER 21)
ocv_update(ANDROID_TARGET_SDK_VERSION "${ANDROID_NATIVE_API_LEVEL}")
else()
ocv_update(ANDROID_TARGET_SDK_VERSION "21")
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.gradle.in" "${CMAKE_CURRENT_BINARY_DIR}/build.gradle" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/build.gradle" DESTINATION ${JAVA_INSTALL_ROOT}/.. COMPONENT java)
else() # gradle build
#
# Android Gradle-based project
#
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.gradle.in" "${ANDROID_TMP_INSTALL_BASE_DIR}/opencv/build.gradle" @ONLY)
#TODO: INSTALL ONLY
ocv_copyfiles_append_dir(JAVA_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/android/java" "${java_src_dir}")
ocv_copyfiles_append_dir(JAVA_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/android-21/java" "${java_src_dir}")
ocv_copyfiles_append_dir(JAVA_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/android-24/java" "${java_src_dir}")
# copy boilerplate
set(SOURSE_SETS_JNI_LIBS_SRC_DIRS "'../../jni'")
set(SOURSE_SETS_JAVA_SRC_DIRS "'src'")
set(SOURSE_SETS_RES_SRC_DIRS "'${OpenCV_SOURCE_DIR}/modules/java/android_sdk/android_gradle_lib/res'")
set(SOURSE_SETS_MANIFEST_SRC_FILE "'AndroidManifest.xml'")
set(MAVEN_PUBLISH_PLUGIN_DECLARATION "")
set(BUILD_GRADLE_ANDROID_PUBLISHING_CONFIG "")
set(BUILD_GRADLE_PUBLISHING_CONFIG "")
set(__base_dir "${CMAKE_CURRENT_SOURCE_DIR}/android_gradle_lib/")
file(GLOB_RECURSE seed_project_files_rel RELATIVE "${__base_dir}/" "${__base_dir}/*")
list(REMOVE_ITEM seed_project_files_rel "${ANDROID_MANIFEST_FILE}")
foreach(file ${seed_project_files_rel})
configure_file("${__base_dir}/${file}" "${OPENCV_JAVA_DIR}/${file}" @ONLY)
list(APPEND depends "${__base_dir}/${file}")
get_filename_component(install_subdir "${file}" PATH)
if(NOT file STREQUAL "build.gradle")
install(FILES "${OPENCV_JAVA_DIR}/${file}" DESTINATION "${JAVA_INSTALL_ROOT}/${install_subdir}" COMPONENT java)
endif()
endforeach()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.gradle.in" "${OPENCV_JAVA_DIR}/build.gradle" @ONLY)
# copy libcxx_helper
set(__base_dir "${CMAKE_CURRENT_SOURCE_DIR}/")
file(GLOB_RECURSE __files_rel RELATIVE "${__base_dir}/" "${__base_dir}/libcxx_helper/*")
foreach(file ${__files_rel})
configure_file("${__base_dir}/${file}" "${OPENCV_JAVA_DIR}/${file}" @ONLY)
list(APPEND depends "${__base_dir}/${file}")
get_filename_component(install_subdir "${file}" PATH)
install(FILES "${OPENCV_JAVA_DIR}/${file}" DESTINATION "${JAVA_INSTALL_ROOT}/../${install_subdir}" COMPONENT java)
endforeach()
list(APPEND depends gen_opencv_java_source "${OPENCV_DEPHELPER}/gen_opencv_java_source")
ocv_copyfiles_add_target(${the_module}_android_source_copy JAVA_SRC_COPY "Copy Java(Android SDK) source files" ${depends})
file(REMOVE "${OPENCV_DEPHELPER}/${the_module}_android_source_copy") # force rebuild after CMake run
set(depends ${the_module}_android_source_copy "${OPENCV_DEPHELPER}/${the_module}_android_source_copy")
# build jar
set(AAR_FILE "${OPENCV_JAVA_DIR}/build/outputs/aar/opencv-release.aar")
add_custom_command(
OUTPUT "${AAR_FILE}" "${OPENCV_DEPHELPER}/${the_module}_android"
COMMAND ./gradlew ${OPENCV_GRADLE_VERBOSE_OPTIONS} "opencv:assemble"
COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/${the_module}_android"
WORKING_DIRECTORY "${ANDROID_BUILD_BASE_DIR}"
DEPENDS ${depends} ${the_module}
COMMENT "Building OpenCV Android library project"
)
file(REMOVE "${OPENCV_DEPHELPER}/${the_module}_android") # force rebuild after CMake run
add_custom_target(${the_module}_android ALL DEPENDS "${OPENCV_DEPHELPER}/${the_module}_android" SOURCES "${__base_dir}/${ANDROID_MANIFEST_FILE}")
install(FILES "${ANDROID_TMP_INSTALL_BASE_DIR}/opencv/build.gradle" DESTINATION ${JAVA_INSTALL_ROOT}/.. COMPONENT java)
install(DIRECTORY "${java_src_dir}" DESTINATION "${JAVA_INSTALL_ROOT}" COMPONENT java)
endif() # gradle build
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.opencv" >
</manifest>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name = "CameraBridgeViewBase" >
<attr name="show_fps" format="boolean"/>
<attr name="camera_id" format="integer" >
<enum name="any" value="-1" />
<enum name="back" value="99" />
<enum name="front" value="98" />
</attr>
</declare-styleable>
</resources>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.opencv">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" />
</manifest>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="InlinedApi">
<ignore path="src\org\opencv\android\JavaCameraView.java" />
</issue>
<issue id="NewApi">
<ignore path="src\org\opencv\android\JavaCameraView.java" />
</issue>
</lint>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name = "CameraBridgeViewBase" >
<attr name="show_fps" format="boolean"/>
<attr name="camera_id" format="integer" >
<enum name="any" value="-1" />
<enum name="back" value="99" />
<enum name="front" value="98" />
</attr>
</declare-styleable>
</resources>
+157
View File
@@ -0,0 +1,157 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Notes about integration OpenCV into existed Android Studio application project are below (application 'app' module should exist).
//
// This file is located in <OpenCV-android-sdk>/sdk directory (near 'etc', 'java', 'native' subdirectories)
//
// Add module into Android Studio application project:
//
// - Android Studio way:
// (will copy almost all OpenCV Android SDK into your project, ~200Mb)
//
// Import module: Menu -> "File" -> "New" -> "Module" -> "Import Gradle project":
// Source directory: select this "sdk" directory
// Module name: ":opencv"
//
// - or attach library module from OpenCV Android SDK
// (without copying into application project directory, allow to share the same module between projects)
//
// Edit "settings.gradle" and add these lines:
//
// def opencvsdk='<path_to_opencv_android_sdk_rootdir>'
// // You can put declaration above into gradle.properties file instead (including file in HOME directory),
// // but without 'def' and apostrophe symbols ('): opencvsdk=<path_to_opencv_android_sdk_rootdir>
// include ':opencv'
// project(':opencv').projectDir = new File(opencvsdk + '/sdk')
//
//
//
// Add dependency into application module:
//
// - Android Studio way:
// "Open Module Settings" (F4) -> "Dependencies" tab
//
// - or add "project(':opencv')" dependency into app/build.gradle:
//
// dependencies {
// implementation fileTree(dir: 'libs', include: ['*.jar'])
// ...
// implementation project(':opencv')
// }
//
//
//
// Load OpenCV native library before using:
//
// - avoid using of "OpenCVLoader.initAsync()" approach - it is deprecated
// It may load library with different version (from OpenCV Android Manager, which is installed separatelly on device)
//
// - use "System.loadLibrary("opencv_java4")" or "OpenCVLoader.initDebug()"
// TODO: Add accurate API to load OpenCV native library
//
//
//
// Native C++ support (necessary to use OpenCV in native code of application only):
//
// - Use find_package() in app/CMakeLists.txt:
//
// find_package(OpenCV @OPENCV_VERSION_MAJOR@.@OPENCV_VERSION_MINOR@ REQUIRED java)
// ...
// target_link_libraries(native-lib ${OpenCV_LIBRARIES})
//
// - Add "OpenCV_DIR" and enable C++ exceptions/RTTI support via app/build.gradle
// Documentation about CMake options: https://developer.android.com/ndk/guides/cmake.html
//
// defaultConfig {
// ...
// externalNativeBuild {
// cmake {
// cppFlags "-std=c++11 -frtti -fexceptions"
// arguments "-DOpenCV_DIR=" + opencvsdk + "/sdk/native/jni" // , "-DANDROID_ARM_NEON=TRUE"
// }
// }
// }
//
// - (optional) Limit/filter ABIs to build ('android' scope of 'app/build.gradle'):
// Useful information: https://developer.android.com/studio/build/gradle-tips.html (Configure separate APKs per ABI)
//
// splits {
// abi {
// enable true
// universalApk false
// reset()
// include 'armeabi-v7a' // , 'x86', 'x86_64', 'arm64-v8a'
// }
// }
//
apply plugin: 'com.android.library'
@MAVEN_PUBLISH_PLUGIN_DECLARATION@
try {
@KOTLIN_PLUGIN_DECLARATION@
println "Configure OpenCV with Kotlin"
} catch (Exception e) {
println "Configure OpenCV without Kotlin"
}
def openCVersionName = "@OPENCV_VERSION@"
def openCVersionCode = ((@OPENCV_VERSION_MAJOR@ * 100 + @OPENCV_VERSION_MINOR@) * 100 + @OPENCV_VERSION_PATCH@) * 10 + 0
println "OpenCV: " +openCVersionName + " " + project.buildscript.sourceFile
android {
@OPENCV_ANDROID_NAMESPACE_DECLARATION@
compileSdkVersion @ANDROID_COMPILE_SDK_VERSION@
defaultConfig {
minSdkVersion @ANDROID_MIN_SDK_VERSION@
targetSdkVersion @ANDROID_TARGET_SDK_VERSION@
versionCode openCVersionCode
versionName openCVersionName
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=@ANDROID_STL@"
targets "opencv_jni_shared"
}
}
}
@BUILD_GRADLE_COMPILE_OPTIONS@
buildTypes {
debug {
packagingOptions {
doNotStrip '**/*.so' // controlled by OpenCV CMake scripts
}
}
release {
packagingOptions {
doNotStrip '**/*.so' // controlled by OpenCV CMake scripts
}
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
sourceSets {
main {
jniLibs.srcDirs = [@SOURSE_SETS_JNI_LIBS_SRC_DIRS@]
java.srcDirs = [@SOURSE_SETS_JAVA_SRC_DIRS@]
res.srcDirs = [@SOURSE_SETS_RES_SRC_DIRS@]
manifest.srcFile @SOURSE_SETS_MANIFEST_SRC_FILE@
}
}
externalNativeBuild {
cmake {
path (project.projectDir.toString() + '/libcxx_helper/CMakeLists.txt')
}
}
@BUILD_GRADLE_ANDROID_PUBLISHING_CONFIG@
}
@BUILD_GRADLE_PUBLISHING_CONFIG@
dependencies {
}
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.6)
project(opencv_jni_shared)
# dummy target to bring libc++_shared.so into packages
add_library(opencv_jni_shared STATIC dummy.cpp)
@@ -0,0 +1 @@
// empty
+165
View File
@@ -0,0 +1,165 @@
#!/usr/bin/env python
from __future__ import print_function
import sys, os, re
classes_ignore_list = (
'OpenCV(Test)?Case',
'OpenCV(Test)?Runner',
'CvException',
)
funcs_ignore_list = (
'\w+--HashCode',
'Mat--MatLong',
'\w+--Equals',
'Core--MinMaxLocResult',
)
class JavaParser:
def __init__(self):
self.clear()
def clear(self):
self.mdict = {}
self.tdict = {}
self.mwhere = {}
self.twhere = {}
self.empty_stubs_cnt = 0
self.r1 = re.compile("\s*public\s+(?:static\s+)?(\w+)\(([^)]*)\)") # c-tor
self.r2 = re.compile("\s*(?:(?:public|static|final)\s+){1,3}\S+\s+(\w+)\(([^)]*)\)")
self.r3 = re.compile('\s*fail\("Not yet implemented"\);') # empty test stub
def dict2set(self, d):
s = set()
for f in d.keys():
if len(d[f]) == 1:
s.add(f)
else:
s |= set(d[f])
return s
def get_tests_count(self):
return len(self.tdict)
def get_empty_stubs_count(self):
return self.empty_stubs_cnt
def get_funcs_count(self):
return len(self.dict2set(self.mdict)), len(self.mdict)
def get_not_tested(self):
mset = self.dict2set(self.mdict)
tset = self.dict2set(self.tdict)
nottested = mset - tset
out = set()
for name in nottested:
out.add(name + " " + self.mwhere[name])
return out
def parse(self, path):
if ".svn" in path:
return
if os.path.isfile(path):
if path.endswith("FeatureDetector.java"):
for prefix1 in ("", "Grid", "Pyramid", "Dynamic"):
for prefix2 in ("FAST", "STAR", "MSER", "ORB", "SIFT", "SURF", "GFTT", "HARRIS", "SIMPLEBLOB", "DENSE", "AKAZE", "KAZE", "BRISK", "AGAST"):
parser.parse_file(path,prefix1+prefix2)
elif path.endswith("DescriptorExtractor.java"):
for prefix1 in ("", "Opponent"):
for prefix2 in ("BRIEF", "ORB", "SIFT", "SURF", "AKAZE", "KAZE", "BEBLID", "DAISY", "FREAK", "LUCID", "LATCH"):
parser.parse_file(path,prefix1+prefix2)
elif path.endswith("GenericDescriptorMatcher.java"):
for prefix in ("OneWay", "Fern"):
parser.parse_file(path,prefix)
elif path.endswith("DescriptorMatcher.java"):
for prefix in ("BruteForce", "BruteForceHamming", "BruteForceHammingLUT", "BruteForceL1", "FlannBased", "BruteForceSL2"):
parser.parse_file(path,prefix)
else:
parser.parse_file(path)
elif os.path.isdir(path):
for x in os.listdir(path):
self.parse(path + "/" + x)
return
def parse_file(self, fname, prefix = ""):
istest = fname.endswith("Test.java")
clsname = os.path.basename(fname).replace("Test", "").replace(".java", "")
clsname = prefix + clsname[0].upper() + clsname[1:]
for cls in classes_ignore_list:
if re.match(cls, clsname):
return
f = open(fname, "rt")
linenum = 0
for line in f:
linenum += 1
m1 = self.r1.match(line)
m2 = self.r2.match(line)
m3 = self.r3.match(line)
func = ''
args_str = ''
if m1:
func = m1.group(1)
args_str = m1.group(2)
elif m2:
if "public" not in line:
continue
func = m2.group(1)
args_str = m2.group(2)
elif m3:
self.empty_stubs_cnt += 1
continue
else:
#if "public" in line:
#print "UNRECOGNIZED: " + line
continue
d = (self.mdict, self.tdict)[istest]
w = (self.mwhere, self.twhere)[istest]
func = re.sub(r"^test", "", func)
func = clsname + "--" + func[0].upper() + func[1:]
args_str = args_str.replace("[]", "Array").replace("...", "Array ")
args_str = re.sub(r"List<(\w+)>", "ListOf\g<1>", args_str)
args_str = re.sub(r"List<(\w+)>", "ListOf\g<1>", args_str)
args = [a.split()[0] for a in args_str.split(",") if a]
func_ex = func + "".join([a[0].upper() + a[1:] for a in args])
func_loc = fname + " (line: " + str(linenum) + ")"
skip = False
for fi in funcs_ignore_list:
if re.match(fi, func_ex):
skip = True
break
if skip:
continue
if func in d:
d[func].append(func_ex)
else:
d[func] = [func_ex]
w[func_ex] = func_loc
w[func] = func_loc
f.close()
return
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage:\n", \
os.path.basename(sys.argv[0]), \
"<Classes/Tests dir1/file1> [<Classes/Tests dir2/file2> ...]\n", "Not tested methods are loggedto stdout.")
exit(0)
parser = JavaParser()
for x in sys.argv[1:]:
parser.parse(x)
funcs = parser.get_not_tested()
if funcs:
print ('{} {}'.format("NOT TESTED methods:\n\t", "\n\t".join(sorted(funcs))))
print ("Total methods found: %i (%i)" % parser.get_funcs_count())
print ('{} {}'.format("Not tested methods found:", len(funcs)))
print ('{} {}'.format("Total tests found:", parser.get_tests_count()))
print ('{} {}'.format("Empty test stubs found:", parser.get_empty_stubs_count()))
+22
View File
@@ -0,0 +1,22 @@
if(ANDROID)
ocv_update(OPENCV_JAVA_LIB_NAME_SUFFIX "${OPENCV_VERSION_MAJOR}")
ocv_update(JAVA_INSTALL_ROOT "sdk/java")
else()
ocv_update(OPENCV_JAVA_LIB_NAME_SUFFIX "${OPENCV_VERSION_MAJOR}${OPENCV_VERSION_MINOR}${OPENCV_VERSION_PATCH}")
endif()
if(MSVC)
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4996)
else()
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wdeprecated-declarations)
endif()
# get list of modules to wrap
# message(STATUS "Wrapped in java:")
set(OPENCV_JAVA_MODULES)
foreach(m ${OPENCV_MODULES_BUILD})
if (";${OPENCV_MODULE_${m}_WRAPPERS};" MATCHES ";java;" AND HAVE_${m})
list(APPEND OPENCV_JAVA_MODULES ${m})
#message(STATUS "\t${m}")
endif()
endforeach()
+132
View File
@@ -0,0 +1,132 @@
set(MODULE_NAME "java_bindings_generator")
set(OPENCV_MODULE_IS_PART_OF_WORLD FALSE)
ocv_add_module(${MODULE_NAME} INTERNAL)
set(OPENCV_JAVA_SIGNATURES_FILE "${CMAKE_CURRENT_BINARY_DIR}/opencv_java_signatures.json" CACHE INTERNAL "")
set(OPENCV_JAVA_BINDINGS_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE INTERNAL "")
file(REMOVE_RECURSE "${OPENCV_JAVA_BINDINGS_DIR}/gen")
file(REMOVE "${OPENCV_DEPHELPER}/gen_opencv_java_source") # force re-run after CMake
# This file is included from a subdirectory
set(JAVA_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
include(${JAVA_SOURCE_DIR}/common.cmake)
set(__remap_config "") # list of remapped ".in" files (configure_file)
set(__remap_targets "")
macro(ocv_remap_files files_list_var)
set(target_dir "${OpenCV_BINARY_DIR}/configured")
foreach(f ${${files_list_var}})
if(NOT "${f}" MATCHES "^(.*)\\.in$")
#continue() # since CMake 3.2+
else()
set(f_ "${CMAKE_MATCH_1}")
file(RELATIVE_PATH rel_path0 "${OpenCV_SOURCE_DIR}" "${f}")
file(RELATIVE_PATH rel_path1 "${OpenCV_SOURCE_DIR}" "${f_}")
set(__target_file "${target_dir}/${rel_path1}")
configure_file("${f}" "${__target_file}" @ONLY)
if(__remap_config)
set(__remap_config "${__remap_config},\n")
endif()
set(__remap_config "${__remap_config} { \"src\": \"${rel_path0}\", \"target\": \"${__target_file}\" }")
list(APPEND __remap_targets "${__target_file}")
endif()
endforeach()
endmacro()
# common files
file(GLOB_RECURSE deps "${CMAKE_CURRENT_SOURCE_DIR}/src/*" "${CMAKE_CURRENT_SOURCE_DIR}/android*/*" "${CMAKE_CURRENT_SOURCE_DIR}/templates/*")
ocv_remap_files(deps)
set(__modules_config "") # list of OpenCV modules
foreach(m ${OPENCV_JAVA_MODULES})
set(module_java_dir "${OPENCV_MODULE_${m}_LOCATION}/misc/java")
list(APPEND deps ${OPENCV_MODULE_${m}_HEADERS})
file(GLOB_RECURSE misc_files "${module_java_dir}/*")
list(APPEND deps ${misc_files})
string(REGEX REPLACE "^opencv_" "" m_ "${m}")
if(__modules_config)
set(__modules_config "${__modules_config},\n")
endif()
file(RELATIVE_PATH rel_path "${OpenCV_SOURCE_DIR}" "${OPENCV_MODULE_${m}_LOCATION}")
set(__modules_config "${__modules_config} { \"name\": \"${m_}\", \"location\": \"${rel_path}\" }")
ocv_remap_files(misc_files)
endforeach(m)
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVBindingsPreprocessorDefinitions.cmake")
ocv_bindings_generator_populate_preprocessor_definitions(
OPENCV_MODULES_BUILD
opencv_preprocessor_defs
)
if(OPENCV_JAVA_CLEANING_API)
if(OPENCV_JAVA_CLEANING_API STREQUAL "finalize")
set(opencv_supported_cleaners "false")
elseif(OPENCV_JAVA_CLEANING_API STREQUAL "cleaner")
set(opencv_supported_cleaners "true")
else()
message(FATAL_ERROR "OPENCV_JAVA_CLEANING_API should be one of \"finalize\" or \"cleaner\"")
endif()
else()
if(ANDROID OR (Java_VERSION VERSION_LESS 9))
message(STATUS "Set Cleaners to False")
set(opencv_supported_cleaners "false")
else()
message(STATUS "Set Cleaners to True")
set(opencv_supported_cleaners "true")
endif()
endif(OPENCV_JAVA_CLEANING_API)
set(CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/gen_java.json")
set(__config_str
"{
\"rootdir\": \"${OpenCV_SOURCE_DIR}\",
\"modules\": [
${__modules_config}
],
\"preprocessor_definitions\": {
${opencv_preprocessor_defs}
},
\"files_remap\": [
${__remap_config}
],
\"support_cleaners\": ${opencv_supported_cleaners}
}
")
if(EXISTS "${CONFIG_FILE}")
file(READ "${CONFIG_FILE}" __content)
else()
set(__content "")
endif()
if(NOT "${__content}" STREQUAL "${__config_str}")
file(WRITE "${CONFIG_FILE}" "${__config_str}")
file(REMOVE "${OPENCV_DEPHELPER}/gen_opencv_java_source")
endif()
unset(__config_str)
set(java_generated_files
# "${OPENCV_JAVA_SIGNATURES_FILE}"
"${OPENCV_DEPHELPER}/gen_opencv_java_source"
)
add_custom_command(
OUTPUT ${java_generated_files}
COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${JAVA_SOURCE_DIR}/generator/gen_java.py" -p "${JAVA_SOURCE_DIR}/../python/src2/gen2.py" -c "${CONFIG_FILE}"
COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/gen_opencv_java_source"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPENDS "${JAVA_SOURCE_DIR}/generator/gen_java.py"
"${JAVA_SOURCE_DIR}/../python/src2/gen2.py"
"${JAVA_SOURCE_DIR}/../python/src2/hdr_parser.py"
# don't, result of file(WRITE): "${CMAKE_CURRENT_BINARY_DIR}/gen_java.json"
${deps} ${__remap_targets}
# not allowed (file(WRITE) result): "${CONFIG_FILE}"
COMMENT "Generate files for Java bindings"
)
add_custom_target(gen_opencv_java_source DEPENDS ${java_generated_files}
SOURCES "${JAVA_SOURCE_DIR}/generator/gen_java.py"
"${CMAKE_CURRENT_BINARY_DIR}/gen_java.json"
)
@@ -0,0 +1,302 @@
package org.opencv.android;
import java.util.Arrays;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
@TargetApi(21)
public class Camera2Renderer extends CameraGLRendererBase {
protected final String LOGTAG = "Camera2Renderer";
private CameraDevice mCameraDevice;
private CameraCaptureSession mCaptureSession;
private CaptureRequest.Builder mPreviewRequestBuilder;
private String mCameraID;
private Size mPreviewSize = new Size(-1, -1);
private HandlerThread mBackgroundThread;
private Handler mBackgroundHandler;
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
Camera2Renderer(CameraGLSurfaceView view) {
super(view);
}
@Override
protected void doStart() {
Log.d(LOGTAG, "doStart");
startBackgroundThread();
super.doStart();
}
@Override
protected void doStop() {
Log.d(LOGTAG, "doStop");
super.doStop();
stopBackgroundThread();
}
boolean cacPreviewSize(final int width, final int height) {
Log.i(LOGTAG, "cacPreviewSize: "+width+"x"+height);
if(mCameraID == null) {
Log.e(LOGTAG, "Camera isn't initialized!");
return false;
}
CameraManager manager = (CameraManager) mView.getContext()
.getSystemService(Context.CAMERA_SERVICE);
try {
CameraCharacteristics characteristics = manager
.getCameraCharacteristics(mCameraID);
StreamConfigurationMap map = characteristics
.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
int bestWidth = 0, bestHeight = 0;
float aspect = (float)width / height;
for (Size psize : map.getOutputSizes(SurfaceTexture.class)) {
int w = psize.getWidth(), h = psize.getHeight();
Log.d(LOGTAG, "trying size: "+w+"x"+h);
if ( width >= w && height >= h &&
bestWidth <= w && bestHeight <= h &&
Math.abs(aspect - (float)w/h) < 0.2 ) {
bestWidth = w;
bestHeight = h;
}
}
Log.i(LOGTAG, "best size: "+bestWidth+"x"+bestHeight);
if( bestWidth == 0 || bestHeight == 0 ||
mPreviewSize.getWidth() == bestWidth &&
mPreviewSize.getHeight() == bestHeight )
return false;
else {
mPreviewSize = new Size(bestWidth, bestHeight);
return true;
}
} catch (CameraAccessException e) {
Log.e(LOGTAG, "cacPreviewSize - Camera Access Exception");
} catch (IllegalArgumentException e) {
Log.e(LOGTAG, "cacPreviewSize - Illegal Argument Exception");
} catch (SecurityException e) {
Log.e(LOGTAG, "cacPreviewSize - Security Exception");
}
return false;
}
@Override
protected void openCamera(int id) {
Log.i(LOGTAG, "openCamera");
CameraManager manager = (CameraManager) mView.getContext().getSystemService(Context.CAMERA_SERVICE);
try {
String camList[] = manager.getCameraIdList();
if(camList.length == 0) {
Log.e(LOGTAG, "Error: camera isn't detected.");
return;
}
if(id == CameraBridgeViewBase.CAMERA_ID_ANY) {
mCameraID = camList[0];
} else {
for (String cameraID : camList) {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraID);
if( id == CameraBridgeViewBase.CAMERA_ID_BACK &&
characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK ||
id == CameraBridgeViewBase.CAMERA_ID_FRONT &&
characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
mCameraID = cameraID;
break;
}
}
}
if(mCameraID != null) {
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
throw new RuntimeException(
"Time out waiting to lock camera opening.");
}
Log.i(LOGTAG, "Opening camera: " + mCameraID);
manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler);
}
} catch (CameraAccessException e) {
Log.e(LOGTAG, "OpenCamera - Camera Access Exception");
} catch (IllegalArgumentException e) {
Log.e(LOGTAG, "OpenCamera - Illegal Argument Exception");
} catch (SecurityException e) {
Log.e(LOGTAG, "OpenCamera - Security Exception");
} catch (InterruptedException e) {
Log.e(LOGTAG, "OpenCamera - Interrupted Exception");
}
}
@Override
protected void closeCamera() {
Log.i(LOGTAG, "closeCamera");
try {
mCameraOpenCloseLock.acquire();
if (null != mCaptureSession) {
mCaptureSession.close();
mCaptureSession = null;
}
if (null != mCameraDevice) {
mCameraDevice.close();
mCameraDevice = null;
}
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
} finally {
mCameraOpenCloseLock.release();
}
}
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
mCameraOpenCloseLock.release();
createCameraPreviewSession();
}
@Override
public void onDisconnected(CameraDevice cameraDevice) {
cameraDevice.close();
mCameraDevice = null;
mCameraOpenCloseLock.release();
}
@Override
public void onError(CameraDevice cameraDevice, int error) {
cameraDevice.close();
mCameraDevice = null;
mCameraOpenCloseLock.release();
}
};
private void createCameraPreviewSession() {
int w=mPreviewSize.getWidth(), h=mPreviewSize.getHeight();
Log.i(LOGTAG, "createCameraPreviewSession("+w+"x"+h+")");
if(w<0 || h<0)
return;
try {
mCameraOpenCloseLock.acquire();
if (null == mCameraDevice) {
mCameraOpenCloseLock.release();
Log.e(LOGTAG, "createCameraPreviewSession: camera isn't opened");
return;
}
if (null != mCaptureSession) {
mCameraOpenCloseLock.release();
Log.e(LOGTAG, "createCameraPreviewSession: mCaptureSession is already started");
return;
}
if(null == mSTexture) {
mCameraOpenCloseLock.release();
Log.e(LOGTAG, "createCameraPreviewSession: preview SurfaceTexture is null");
return;
}
mSTexture.setDefaultBufferSize(w, h);
Surface surface = new Surface(mSTexture);
mPreviewRequestBuilder = mCameraDevice
.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
mCameraDevice.createCaptureSession(Arrays.asList(surface),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured( CameraCaptureSession cameraCaptureSession) {
mCaptureSession = cameraCaptureSession;
try {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, mBackgroundHandler);
Log.i(LOGTAG, "CameraPreviewSession has been started");
} catch (CameraAccessException e) {
Log.e(LOGTAG, "createCaptureSession failed");
}
mCameraOpenCloseLock.release();
}
@Override
public void onConfigureFailed(
CameraCaptureSession cameraCaptureSession) {
Log.e(LOGTAG, "createCameraPreviewSession failed");
mCameraOpenCloseLock.release();
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
Log.e(LOGTAG, "createCameraPreviewSession");
} catch (InterruptedException e) {
throw new RuntimeException(
"Interrupted while createCameraPreviewSession", e);
}
finally {
//mCameraOpenCloseLock.release();
}
}
private void startBackgroundThread() {
Log.i(LOGTAG, "startBackgroundThread");
stopBackgroundThread();
mBackgroundThread = new HandlerThread("CameraBackground");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
private void stopBackgroundThread() {
Log.i(LOGTAG, "stopBackgroundThread");
if(mBackgroundThread == null)
return;
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
Log.e(LOGTAG, "stopBackgroundThread");
}
}
@Override
protected void setCameraPreviewSize(int width, int height) {
Log.i(LOGTAG, "setCameraPreviewSize("+width+"x"+height+")");
if(mMaxCameraWidth > 0 && mMaxCameraWidth < width) width = mMaxCameraWidth;
if(mMaxCameraHeight > 0 && mMaxCameraHeight < height) height = mMaxCameraHeight;
try {
mCameraOpenCloseLock.acquire();
boolean needReconfig = cacPreviewSize(width, height);
mCameraWidth = mPreviewSize.getWidth();
mCameraHeight = mPreviewSize.getHeight();
if( !needReconfig ) {
mCameraOpenCloseLock.release();
return;
}
if (null != mCaptureSession) {
Log.d(LOGTAG, "closing existing previewSession");
mCaptureSession.close();
mCaptureSession = null;
}
mCameraOpenCloseLock.release();
createCameraPreviewSession();
} catch (InterruptedException e) {
mCameraOpenCloseLock.release();
throw new RuntimeException("Interrupted while setCameraPreviewSize.", e);
}
}
}
@@ -0,0 +1,440 @@
package org.opencv.android;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import org.opencv.android.CameraGLSurfaceView.CameraTextureListener;
import android.annotation.TargetApi;
import android.graphics.SurfaceTexture;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.Log;
import android.view.View;
@TargetApi(15)
public abstract class CameraGLRendererBase implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
protected final String LOGTAG = "CameraGLRendererBase";
// shaders
private final String vss = ""
+ "attribute vec2 vPosition;\n"
+ "attribute vec2 vTexCoord;\n" + "varying vec2 texCoord;\n"
+ "void main() {\n" + " texCoord = vTexCoord;\n"
+ " gl_Position = vec4 ( vPosition.x, vPosition.y, 0.0, 1.0 );\n"
+ "}";
private final String fssOES = ""
+ "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "varying vec2 texCoord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}";
private final String fss2D = ""
+ "precision mediump float;\n"
+ "uniform sampler2D sTexture;\n"
+ "varying vec2 texCoord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}";
// coord-s
private final float vertices[] = {
-1, -1,
-1, 1,
1, -1,
1, 1 };
private final float texCoordOES[] = {
0, 1,
0, 0,
1, 1,
1, 0 };
private final float texCoord2D[] = {
0, 0,
0, 1,
1, 0,
1, 1 };
private int[] texCamera = {0}, texFBO = {0}, texDraw = {0};
private int[] FBO = {0};
private int progOES = -1, prog2D = -1;
private int vPosOES, vTCOES, vPos2D, vTC2D;
private FloatBuffer vert, texOES, tex2D;
protected int mCameraWidth = -1, mCameraHeight = -1;
protected int mFBOWidth = -1, mFBOHeight = -1;
protected int mMaxCameraWidth = -1, mMaxCameraHeight = -1;
protected int mCameraIndex = CameraBridgeViewBase.CAMERA_ID_ANY;
protected SurfaceTexture mSTexture;
protected boolean mHaveSurface = false;
protected boolean mHaveFBO = false;
protected boolean mUpdateST = false;
protected boolean mEnabled = true;
protected boolean mIsStarted = false;
protected CameraGLSurfaceView mView;
protected abstract void openCamera(int id);
protected abstract void closeCamera();
protected abstract void setCameraPreviewSize(int width, int height); // updates mCameraWidth & mCameraHeight
public CameraGLRendererBase(CameraGLSurfaceView view) {
mView = view;
int bytes = vertices.length * Float.SIZE / Byte.SIZE;
vert = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer();
texOES = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer();
tex2D = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer();
vert.put(vertices).position(0);
texOES.put(texCoordOES).position(0);
tex2D.put(texCoord2D).position(0);
}
@Override
public synchronized void onFrameAvailable(SurfaceTexture surfaceTexture) {
//Log.i(LOGTAG, "onFrameAvailable");
mUpdateST = true;
mView.requestRender();
}
@Override
public void onDrawFrame(GL10 gl) {
//Log.i(LOGTAG, "onDrawFrame start");
if (!mHaveFBO)
return;
synchronized(this) {
if (mUpdateST) {
mSTexture.updateTexImage();
mUpdateST = false;
}
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
CameraTextureListener texListener = mView.getCameraTextureListener();
if(texListener != null) {
//Log.d(LOGTAG, "haveUserCallback");
// texCamera(OES) -> texFBO
drawTex(texCamera[0], true, FBO[0]);
// call user code (texFBO -> texDraw)
boolean modified = texListener.onCameraTexture(texFBO[0], texDraw[0], mCameraWidth, mCameraHeight);
if(modified) {
// texDraw -> screen
drawTex(texDraw[0], false, 0);
} else {
// texFBO -> screen
drawTex(texFBO[0], false, 0);
}
} else {
Log.d(LOGTAG, "texCamera(OES) -> screen");
// texCamera(OES) -> screen
drawTex(texCamera[0], true, 0);
}
//Log.i(LOGTAG, "onDrawFrame end");
}
}
@Override
public void onSurfaceChanged(GL10 gl, int surfaceWidth, int surfaceHeight) {
Log.i(LOGTAG, "onSurfaceChanged("+surfaceWidth+"x"+surfaceHeight+")");
mHaveSurface = true;
updateState();
setPreviewSize(surfaceWidth, surfaceHeight);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.i(LOGTAG, "onSurfaceCreated");
initShaders();
}
private void initShaders() {
String strGLVersion = GLES20.glGetString(GLES20.GL_VERSION);
if (strGLVersion != null)
Log.i(LOGTAG, "OpenGL ES version: " + strGLVersion);
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
progOES = loadShader(vss, fssOES);
vPosOES = GLES20.glGetAttribLocation(progOES, "vPosition");
vTCOES = GLES20.glGetAttribLocation(progOES, "vTexCoord");
GLES20.glEnableVertexAttribArray(vPosOES);
GLES20.glEnableVertexAttribArray(vTCOES);
prog2D = loadShader(vss, fss2D);
vPos2D = GLES20.glGetAttribLocation(prog2D, "vPosition");
vTC2D = GLES20.glGetAttribLocation(prog2D, "vTexCoord");
GLES20.glEnableVertexAttribArray(vPos2D);
GLES20.glEnableVertexAttribArray(vTC2D);
}
private void initSurfaceTexture() {
Log.d(LOGTAG, "initSurfaceTexture");
deleteSurfaceTexture();
initTexOES(texCamera);
mSTexture = new SurfaceTexture(texCamera[0]);
mSTexture.setOnFrameAvailableListener(this);
}
private void deleteSurfaceTexture() {
Log.d(LOGTAG, "deleteSurfaceTexture");
if(mSTexture != null) {
mSTexture.release();
mSTexture = null;
deleteTex(texCamera);
}
}
private void initTexOES(int[] tex) {
if(tex.length == 1) {
GLES20.glGenTextures(1, tex, 0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
}
}
private static void deleteTex(int[] tex) {
if(tex.length == 1) {
GLES20.glDeleteTextures(1, tex, 0);
}
}
private static int loadShader(String vss, String fss) {
Log.d("CameraGLRendererBase", "loadShader");
int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vshader, vss);
GLES20.glCompileShader(vshader);
int[] status = new int[1];
GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, status, 0);
if (status[0] == 0) {
Log.e("CameraGLRendererBase", "Could not compile vertex shader: "+GLES20.glGetShaderInfoLog(vshader));
GLES20.glDeleteShader(vshader);
vshader = 0;
return 0;
}
int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fshader, fss);
GLES20.glCompileShader(fshader);
GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, status, 0);
if (status[0] == 0) {
Log.e("CameraGLRendererBase", "Could not compile fragment shader:"+GLES20.glGetShaderInfoLog(fshader));
GLES20.glDeleteShader(vshader);
GLES20.glDeleteShader(fshader);
fshader = 0;
return 0;
}
int program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vshader);
GLES20.glAttachShader(program, fshader);
GLES20.glLinkProgram(program);
GLES20.glDeleteShader(vshader);
GLES20.glDeleteShader(fshader);
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, status, 0);
if (status[0] == 0) {
Log.e("CameraGLRendererBase", "Could not link shader program: "+GLES20.glGetProgramInfoLog(program));
program = 0;
return 0;
}
GLES20.glValidateProgram(program);
GLES20.glGetProgramiv(program, GLES20.GL_VALIDATE_STATUS, status, 0);
if (status[0] == 0)
{
Log.e("CameraGLRendererBase", "Shader program validation error: "+GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
return 0;
}
Log.d("CameraGLRendererBase", "Shader program is built OK");
return program;
}
private void deleteFBO()
{
Log.d(LOGTAG, "deleteFBO("+mFBOWidth+"x"+mFBOHeight+")");
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glDeleteFramebuffers(1, FBO, 0);
deleteTex(texFBO);
deleteTex(texDraw);
mFBOWidth = mFBOHeight = 0;
}
private void initFBO(int width, int height)
{
Log.d(LOGTAG, "initFBO("+width+"x"+height+")");
deleteFBO();
GLES20.glGenTextures(1, texDraw, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texDraw[0]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glGenTextures(1, texFBO, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texFBO[0]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
//int hFBO;
GLES20.glGenFramebuffers(1, FBO, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, FBO[0]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texFBO[0], 0);
Log.d(LOGTAG, "initFBO error status: " + GLES20.glGetError());
int FBOstatus = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (FBOstatus != GLES20.GL_FRAMEBUFFER_COMPLETE)
Log.e(LOGTAG, "initFBO failed, status: " + FBOstatus);
mFBOWidth = width;
mFBOHeight = height;
}
// draw texture to FBO or to screen if fbo == 0
private void drawTex(int tex, boolean isOES, int fbo)
{
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo);
if(fbo == 0)
GLES20.glViewport(0, 0, mView.getWidth(), mView.getHeight());
else
GLES20.glViewport(0, 0, mFBOWidth, mFBOHeight);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
if(isOES) {
GLES20.glUseProgram(progOES);
GLES20.glVertexAttribPointer(vPosOES, 2, GLES20.GL_FLOAT, false, 4*2, vert);
GLES20.glVertexAttribPointer(vTCOES, 2, GLES20.GL_FLOAT, false, 4*2, texOES);
} else {
GLES20.glUseProgram(prog2D);
GLES20.glVertexAttribPointer(vPos2D, 2, GLES20.GL_FLOAT, false, 4*2, vert);
GLES20.glVertexAttribPointer(vTC2D, 2, GLES20.GL_FLOAT, false, 4*2, tex2D);
}
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
if(isOES) {
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex);
GLES20.glUniform1i(GLES20.glGetUniformLocation(progOES, "sTexture"), 0);
} else {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex);
GLES20.glUniform1i(GLES20.glGetUniformLocation(prog2D, "sTexture"), 0);
}
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glFlush();
}
public synchronized void enableView() {
Log.d(LOGTAG, "enableView");
mEnabled = true;
updateState();
}
public synchronized void disableView() {
Log.d(LOGTAG, "disableView");
mEnabled = false;
updateState();
}
protected void updateState() {
Log.d(LOGTAG, "updateState");
Log.d(LOGTAG, "mEnabled="+mEnabled+", mHaveSurface="+mHaveSurface);
boolean willStart = mEnabled && mHaveSurface && mView.getVisibility() == View.VISIBLE;
if (willStart != mIsStarted) {
if(willStart) doStart();
else doStop();
} else {
Log.d(LOGTAG, "keeping State unchanged");
}
Log.d(LOGTAG, "updateState end");
}
protected synchronized void doStart() {
Log.d(LOGTAG, "doStart");
initSurfaceTexture();
openCamera(mCameraIndex);
mIsStarted = true;
if(mCameraWidth>0 && mCameraHeight>0)
setPreviewSize(mCameraWidth, mCameraHeight); // start preview and call listener.onCameraViewStarted()
}
protected void doStop() {
Log.d(LOGTAG, "doStop");
synchronized(this) {
mUpdateST = false;
mIsStarted = false;
mHaveFBO = false;
closeCamera();
deleteSurfaceTexture();
}
CameraTextureListener listener = mView.getCameraTextureListener();
if(listener != null) listener.onCameraViewStopped();
}
protected void setPreviewSize(int width, int height) {
synchronized(this) {
mHaveFBO = false;
mCameraWidth = width;
mCameraHeight = height;
setCameraPreviewSize(width, height); // can change mCameraWidth & mCameraHeight
initFBO(mCameraWidth, mCameraHeight);
mHaveFBO = true;
}
CameraTextureListener listener = mView.getCameraTextureListener();
if(listener != null) listener.onCameraViewStarted(mCameraWidth, mCameraHeight);
}
public void setCameraIndex(int cameraIndex) {
disableView();
mCameraIndex = cameraIndex;
enableView();
}
public void setMaxCameraPreviewSize(int maxWidth, int maxHeight) {
disableView();
mMaxCameraWidth = maxWidth;
mMaxCameraHeight = maxHeight;
enableView();
}
public void onResume() {
Log.i(LOGTAG, "onResume");
}
public void onPause() {
Log.i(LOGTAG, "onPause");
mHaveSurface = false;
updateState();
mCameraWidth = mCameraHeight = -1;
}
}
@@ -0,0 +1,119 @@
package org.opencv.android;
import org.opencv.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
public class CameraGLSurfaceView extends GLSurfaceView {
private static final String LOGTAG = "CameraGLSurfaceView";
public interface CameraTextureListener {
/**
* This method is invoked when camera preview has started. After this method is invoked
* the frames will start to be delivered to client via the onCameraFrame() callback.
* @param width - the width of the frames that will be delivered
* @param height - the height of the frames that will be delivered
*/
public void onCameraViewStarted(int width, int height);
/**
* This method is invoked when camera preview has been stopped for some reason.
* No frames will be delivered via onCameraFrame() callback after this method is called.
*/
public void onCameraViewStopped();
/**
* This method is invoked when a new preview frame from Camera is ready.
* @param texIn - the OpenGL texture ID that contains frame in RGBA format
* @param texOut - the OpenGL texture ID that can be used to store modified frame image t display
* @param width - the width of the frame
* @param height - the height of the frame
* @return `true` if `texOut` should be displayed, `false` - to show `texIn`
*/
public boolean onCameraTexture(int texIn, int texOut, int width, int height);
};
private CameraTextureListener mTexListener;
private CameraGLRendererBase mRenderer;
public CameraGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs, R.styleable.CameraBridgeViewBase);
int cameraIndex = styledAttrs.getInt(R.styleable.CameraBridgeViewBase_camera_id, -1);
styledAttrs.recycle();
if(android.os.Build.VERSION.SDK_INT >= 21)
mRenderer = new Camera2Renderer(this);
else
mRenderer = new CameraRenderer(this);
setCameraIndex(cameraIndex);
setEGLContextClientVersion(2);
setRenderer(mRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
public void setCameraTextureListener(CameraTextureListener texListener)
{
mTexListener = texListener;
}
public CameraTextureListener getCameraTextureListener()
{
return mTexListener;
}
public void setCameraIndex(int cameraIndex) {
mRenderer.setCameraIndex(cameraIndex);
}
public void setMaxCameraPreviewSize(int maxWidth, int maxHeight) {
mRenderer.setMaxCameraPreviewSize(maxWidth, maxHeight);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
super.surfaceCreated(holder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mRenderer.mHaveSurface = false;
super.surfaceDestroyed(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
super.surfaceChanged(holder, format, w, h);
}
@Override
public void onResume() {
Log.i(LOGTAG, "onResume");
super.onResume();
mRenderer.onResume();
}
@Override
public void onPause() {
Log.i(LOGTAG, "onPause");
mRenderer.onPause();
super.onPause();
}
public void enableView() {
mRenderer.enableView();
}
public void disableView() {
mRenderer.disableView();
}
}
@@ -0,0 +1,166 @@
package org.opencv.android;
import java.io.IOException;
import java.util.List;
import android.annotation.TargetApi;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Build;
import android.util.Log;
@TargetApi(15)
@SuppressWarnings("deprecation")
public class CameraRenderer extends CameraGLRendererBase {
public static final String LOGTAG = "CameraRenderer";
private Camera mCamera;
private boolean mPreviewStarted = false;
CameraRenderer(CameraGLSurfaceView view) {
super(view);
}
@Override
protected synchronized void closeCamera() {
Log.i(LOGTAG, "closeCamera");
if(mCamera != null) {
mCamera.stopPreview();
mPreviewStarted = false;
mCamera.release();
mCamera = null;
}
}
@Override
protected synchronized void openCamera(int id) {
Log.i(LOGTAG, "openCamera");
closeCamera();
if (id == CameraBridgeViewBase.CAMERA_ID_ANY) {
Log.d(LOGTAG, "Trying to open camera with old open()");
try {
mCamera = Camera.open();
}
catch (Exception e){
Log.e(LOGTAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage());
}
if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
boolean connected = false;
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Log.d(LOGTAG, "Trying to open camera with new open(" + camIdx + ")");
try {
mCamera = Camera.open(camIdx);
connected = true;
} catch (RuntimeException e) {
Log.e(LOGTAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
}
if (connected) break;
}
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
int localCameraIndex = mCameraIndex;
if (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_BACK) {
Log.i(LOGTAG, "Trying to open BACK camera");
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Camera.getCameraInfo( camIdx, cameraInfo );
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
localCameraIndex = camIdx;
break;
}
}
} else if (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT) {
Log.i(LOGTAG, "Trying to open FRONT camera");
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Camera.getCameraInfo( camIdx, cameraInfo );
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
localCameraIndex = camIdx;
break;
}
}
}
if (localCameraIndex == CameraBridgeViewBase.CAMERA_ID_BACK) {
Log.e(LOGTAG, "Back camera not found!");
} else if (localCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT) {
Log.e(LOGTAG, "Front camera not found!");
} else {
Log.d(LOGTAG, "Trying to open camera with new open(" + localCameraIndex + ")");
try {
mCamera = Camera.open(localCameraIndex);
} catch (RuntimeException e) {
Log.e(LOGTAG, "Camera #" + localCameraIndex + "failed to open: " + e.getLocalizedMessage());
}
}
}
}
if(mCamera == null) {
Log.e(LOGTAG, "Error: can't open camera");
return;
}
Camera.Parameters params = mCamera.getParameters();
List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
{
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(params);
try {
mCamera.setPreviewTexture(mSTexture);
} catch (IOException ioe) {
Log.e(LOGTAG, "setPreviewTexture() failed: " + ioe.getMessage());
}
}
@Override
public synchronized void setCameraPreviewSize(int width, int height) {
Log.i(LOGTAG, "setCameraPreviewSize: "+width+"x"+height);
if(mCamera == null) {
Log.e(LOGTAG, "Camera isn't initialized!");
return;
}
if(mMaxCameraWidth > 0 && mMaxCameraWidth < width) width = mMaxCameraWidth;
if(mMaxCameraHeight > 0 && mMaxCameraHeight < height) height = mMaxCameraHeight;
Camera.Parameters param = mCamera.getParameters();
List<Size> psize = param.getSupportedPreviewSizes();
int bestWidth = 0, bestHeight = 0;
if (psize.size() > 0) {
float aspect = (float)width / height;
for (Size size : psize) {
int w = size.width, h = size.height;
Log.d(LOGTAG, "checking camera preview size: "+w+"x"+h);
if ( w <= width && h <= height &&
w >= bestWidth && h >= bestHeight &&
Math.abs(aspect - (float)w/h) < 0.2 ) {
bestWidth = w;
bestHeight = h;
}
}
if(bestWidth <= 0 || bestHeight <= 0) {
bestWidth = psize.get(0).width;
bestHeight = psize.get(0).height;
Log.e(LOGTAG, "Error: best size was not selected, using "+bestWidth+" x "+bestHeight);
} else {
Log.i(LOGTAG, "Selected best size: "+bestWidth+" x "+bestHeight);
}
if(mPreviewStarted) {
mCamera.stopPreview();
mPreviewStarted = false;
}
mCameraWidth = bestWidth;
mCameraHeight = bestHeight;
param.setPreviewSize(bestWidth, bestHeight);
}
param.set("orientation", "landscape");
mCamera.setParameters(param);
mCamera.startPreview();
mPreviewStarted = true;
}
}
@@ -0,0 +1,472 @@
package org.opencv.android;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.ViewGroup.LayoutParams;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
/**
* This class is an implementation of the Bridge View between OpenCV and Java Camera.
* This class relays on the functionality available in base class and only implements
* required functions:
* connectCamera - opens Java camera and sets the PreviewCallback to be delivered.
* disconnectCamera - closes the camera and stops preview.
* When frame is delivered via callback from Camera - it processed via OpenCV to be
* converted to RGBA32 and then passed to the external callback for modifications if required.
*/
@TargetApi(21)
public class JavaCamera2View extends CameraBridgeViewBase {
private static final String LOGTAG = "JavaCamera2View";
protected ImageReader mImageReader;
protected int mPreviewFormat = ImageFormat.YUV_420_888;
protected int mRequestTemplate = CameraDevice.TEMPLATE_PREVIEW;
private int mFrameRotation;
protected CameraDevice mCameraDevice;
protected CameraCaptureSession mCaptureSession;
protected CaptureRequest.Builder mPreviewRequestBuilder;
protected String mCameraID;
protected android.util.Size mPreviewSize = new android.util.Size(-1, -1);
private HandlerThread mBackgroundThread;
protected Handler mBackgroundHandler;
public JavaCamera2View(Context context, int cameraId) {
super(context, cameraId);
}
public JavaCamera2View(Context context, AttributeSet attrs) {
super(context, attrs);
}
private void startBackgroundThread() {
Log.i(LOGTAG, "startBackgroundThread");
stopBackgroundThread();
mBackgroundThread = new HandlerThread("OpenCVCameraBackground");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
private void stopBackgroundThread() {
Log.i(LOGTAG, "stopBackgroundThread");
if (mBackgroundThread == null)
return;
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
Log.e(LOGTAG, "stopBackgroundThread", e);
}
}
protected boolean selectCamera() {
Log.i(LOGTAG, "selectCamera");
CameraManager manager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
try {
String camList[] = manager.getCameraIdList();
if (camList.length == 0) {
Log.e(LOGTAG, "Error: camera isn't detected.");
return false;
}
boolean chosen = false; // remember whether the camera ID is set.
if (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_ANY) {
mCameraID = camList[0];
chosen = true;
} else {
for (String cameraID : camList) {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraID);
if ((mCameraIndex == CameraBridgeViewBase.CAMERA_ID_BACK &&
characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) ||
(mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT &&
characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT)
) {
mCameraID = cameraID;
chosen = true;
break;
}
}
}
if (mCameraID == null || !chosen) { // make JavaCamera2View behaves in the same way as JavaCameraView
Log.i(LOGTAG, "Selecting camera by index (" + mCameraIndex + ")");
if (mCameraIndex < camList.length) {
mCameraID = camList[mCameraIndex];
} else {
// CAMERA_DISCONNECTED is used when the camera id is no longer valid
throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED);
}
}
return true;
} catch (CameraAccessException e) {
Log.e(LOGTAG, "selectCamera - Camera Access Exception", e);
} catch (IllegalArgumentException e) {
Log.e(LOGTAG, "selectCamera - Illegal Argument Exception", e);
} catch (SecurityException e) {
Log.e(LOGTAG, "selectCamera - Security Exception", e);
}
return false;
}
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
createCameraPreviewSession();
}
@Override
public void onDisconnected(CameraDevice cameraDevice) {
cameraDevice.close();
mCameraDevice = null;
}
@Override
public void onError(CameraDevice cameraDevice, int error) {
cameraDevice.close();
mCameraDevice = null;
}
};
protected CameraCaptureSession.StateCallback allocateSessionStateCallback() {
return new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
Log.i(LOGTAG, "createCaptureSession::onConfigured");
if (null == mCameraDevice) {
return; // camera is already closed
}
mCaptureSession = cameraCaptureSession;
try {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, mBackgroundHandler);
Log.i(LOGTAG, "CameraPreviewSession has been started");
} catch (Exception e) {
Log.e(LOGTAG, "createCaptureSession failed", e);
}
}
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
Log.e(LOGTAG, "createCameraPreviewSession failed");
}
};
}
private void createCameraPreviewSession() {
final int w = mPreviewSize.getWidth(), h = mPreviewSize.getHeight();
Log.i(LOGTAG, "createCameraPreviewSession(" + w + "x" + h + ")");
if (w < 0 || h < 0)
return;
try {
if (null == mCameraDevice) {
Log.e(LOGTAG, "createCameraPreviewSession: camera isn't opened");
return;
}
if (null != mCaptureSession) {
Log.e(LOGTAG, "createCameraPreviewSession: mCaptureSession is already started");
return;
}
mImageReader = ImageReader.newInstance(w, h, mPreviewFormat, 2);
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
if (image == null)
return;
// sanity checks - 3 planes
Image.Plane[] planes = image.getPlanes();
assert (planes.length == 3);
assert (image.getFormat() == mPreviewFormat);
RotatedCameraFrame tempFrame = new RotatedCameraFrame(new JavaCamera2Frame(image), mFrameRotation);
deliverAndDrawFrame(tempFrame);
tempFrame.mFrame.release();
tempFrame.release();
image.close();
}
}, mBackgroundHandler);
Surface surface = mImageReader.getSurface();
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(mRequestTemplate);
mPreviewRequestBuilder.addTarget(surface);
mCameraDevice.createCaptureSession(Arrays.asList(surface),
allocateSessionStateCallback(), null);
} catch (CameraAccessException e) {
Log.e(LOGTAG, "createCameraPreviewSession", e);
}
}
@Override
protected void disconnectCamera() {
Log.i(LOGTAG, "close camera");
try {
CameraDevice c = mCameraDevice;
mCameraDevice = null;
if (null != mCaptureSession) {
mCaptureSession.close();
mCaptureSession = null;
}
if (null != c) {
c.close();
}
} finally {
stopBackgroundThread();
if (null != mImageReader) {
mImageReader.close();
mImageReader = null;
}
}
Log.i(LOGTAG, "camera closed!");
}
public static class JavaCameraSizeAccessor implements ListItemAccessor {
@Override
public int getWidth(Object obj) {
android.util.Size size = (android.util.Size)obj;
return size.getWidth();
}
@Override
public int getHeight(Object obj) {
android.util.Size size = (android.util.Size)obj;
return size.getHeight();
}
}
boolean calcPreviewSize(final int width, final int height) {
Log.i(LOGTAG, "calcPreviewSize: " + width + "x" + height);
if (mCameraID == null) {
Log.e(LOGTAG, "Camera isn't initialized!");
return false;
}
CameraManager manager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
try {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraID);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
android.util.Size[] sizes = map.getOutputSizes(ImageReader.class);
List<android.util.Size> sizes_list = Arrays.asList(sizes);
Size frameSize = calculateCameraFrameSize(sizes_list, new JavaCameraSizeAccessor(), width, height);
Log.i(LOGTAG, "Selected preview size to " + Integer.valueOf((int)frameSize.width) + "x" + Integer.valueOf((int)frameSize.height));
assert(!(frameSize.width == 0 || frameSize.height == 0));
if (mPreviewSize.getWidth() == frameSize.width && mPreviewSize.getHeight() == frameSize.height)
return false;
else {
mPreviewSize = new android.util.Size((int)frameSize.width, (int)frameSize.height);
return true;
}
} catch (CameraAccessException e) {
Log.e(LOGTAG, "calcPreviewSize - Camera Access Exception", e);
} catch (IllegalArgumentException e) {
Log.e(LOGTAG, "calcPreviewSize - Illegal Argument Exception", e);
} catch (SecurityException e) {
Log.e(LOGTAG, "calcPreviewSize - Security Exception", e);
}
return false;
}
@Override
protected boolean connectCamera(int width, int height) {
Log.i(LOGTAG, "setCameraPreviewSize(" + width + "x" + height + ")");
startBackgroundThread();
selectCamera();
try {
CameraManager manager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraID);
mFrameRotation = getFrameRotation(
characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT,
characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION));
boolean needReconfig = calcPreviewSize(width, height);
if (mFrameRotation % 180 == 0) {
mFrameWidth = mPreviewSize.getWidth();
mFrameHeight = mPreviewSize.getHeight();
} else {
mFrameWidth = mPreviewSize.getHeight();
mFrameHeight = mPreviewSize.getWidth();
}
if ((getLayoutParams().width == LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LayoutParams.MATCH_PARENT))
mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth);
else
mScale = 0;
AllocateCache();
if (needReconfig) {
if (null != mCaptureSession) {
Log.d(LOGTAG, "closing existing previewSession");
mCaptureSession.close();
mCaptureSession = null;
}
}
if (mFpsMeter != null) {
mFpsMeter.setResolution(mFrameWidth, mFrameHeight);
}
Log.i(LOGTAG, "Opening camera: " + mCameraID);
manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
Log.e(LOGTAG, "OpenCamera - Camera Access Exception", e);
} catch (RuntimeException e) {
throw new RuntimeException("Interrupted while setCameraPreviewSize.", e);
}
return true;
}
private class JavaCamera2Frame implements CvCameraViewFrame {
@Override
public Mat gray() {
Image.Plane[] planes = mImage.getPlanes();
int w = mImage.getWidth();
int h = mImage.getHeight();
assert(planes[0].getPixelStride() == 1);
ByteBuffer y_plane = planes[0].getBuffer();
int y_plane_step = planes[0].getRowStride();
mGray = new Mat(h, w, CvType.CV_8UC1, y_plane, y_plane_step);
return mGray;
}
@Override
public Mat rgba() {
Image.Plane[] planes = mImage.getPlanes();
int w = mImage.getWidth();
int h = mImage.getHeight();
int chromaPixelStride = planes[1].getPixelStride();
if (chromaPixelStride == 2) { // Chroma channels are interleaved
assert(planes[0].getPixelStride() == 1);
assert(planes[2].getPixelStride() == 2);
ByteBuffer y_plane = planes[0].getBuffer();
int y_plane_step = planes[0].getRowStride();
ByteBuffer uv_plane1 = planes[1].getBuffer();
int uv_plane1_step = planes[1].getRowStride();
ByteBuffer uv_plane2 = planes[2].getBuffer();
int uv_plane2_step = planes[2].getRowStride();
Mat y_mat = new Mat(h, w, CvType.CV_8UC1, y_plane, y_plane_step);
Mat uv_mat1 = new Mat(h / 2, w / 2, CvType.CV_8UC2, uv_plane1, uv_plane1_step);
Mat uv_mat2 = new Mat(h / 2, w / 2, CvType.CV_8UC2, uv_plane2, uv_plane2_step);
long addr_diff = uv_mat2.dataAddr() - uv_mat1.dataAddr();
if (addr_diff > 0) {
assert(addr_diff == 1);
Imgproc.cvtColorTwoPlane(y_mat, uv_mat1, mRgba, Imgproc.COLOR_YUV2RGBA_NV12);
} else {
assert(addr_diff == -1);
Imgproc.cvtColorTwoPlane(y_mat, uv_mat2, mRgba, Imgproc.COLOR_YUV2RGBA_NV21);
}
return mRgba;
} else { // Chroma channels are not interleaved
byte[] yuv_bytes = new byte[w*(h+h/2)];
ByteBuffer y_plane = planes[0].getBuffer();
ByteBuffer u_plane = planes[1].getBuffer();
ByteBuffer v_plane = planes[2].getBuffer();
int yuv_bytes_offset = 0;
int y_plane_step = planes[0].getRowStride();
if (y_plane_step == w) {
y_plane.get(yuv_bytes, 0, w*h);
yuv_bytes_offset = w*h;
} else {
int padding = y_plane_step - w;
for (int i = 0; i < h; i++){
y_plane.get(yuv_bytes, yuv_bytes_offset, w);
yuv_bytes_offset += w;
if (i < h - 1) {
y_plane.position(y_plane.position() + padding);
}
}
assert(yuv_bytes_offset == w * h);
}
int chromaRowStride = planes[1].getRowStride();
int chromaRowPadding = chromaRowStride - w/2;
if (chromaRowPadding == 0){
// When the row stride of the chroma channels equals their width, we can copy
// the entire channels in one go
u_plane.get(yuv_bytes, yuv_bytes_offset, w*h/4);
yuv_bytes_offset += w*h/4;
v_plane.get(yuv_bytes, yuv_bytes_offset, w*h/4);
} else {
// When not equal, we need to copy the channels row by row
for (int i = 0; i < h/2; i++){
u_plane.get(yuv_bytes, yuv_bytes_offset, w/2);
yuv_bytes_offset += w/2;
if (i < h/2-1){
u_plane.position(u_plane.position() + chromaRowPadding);
}
}
for (int i = 0; i < h/2; i++){
v_plane.get(yuv_bytes, yuv_bytes_offset, w/2);
yuv_bytes_offset += w/2;
if (i < h/2-1){
v_plane.position(v_plane.position() + chromaRowPadding);
}
}
}
Mat yuv_mat = new Mat(h+h/2, w, CvType.CV_8UC1);
yuv_mat.put(0, 0, yuv_bytes);
Imgproc.cvtColor(yuv_mat, mRgba, Imgproc.COLOR_YUV2RGBA_I420, 4);
return mRgba;
}
}
public JavaCamera2Frame(Image image) {
super();
mImage = image;
mRgba = new Mat();
mGray = new Mat();
}
@Override
public void release() {
mRgba.release();
mGray.release();
}
private Image mImage;
private Mat mRgba;
private Mat mGray;
};
}
@@ -0,0 +1,230 @@
package org.opencv.android;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.core.MatOfInt;
import org.opencv.imgproc.Imgproc;
import org.opencv.videoio.Videoio;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.VideoWriter;
import android.content.Context;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewGroup.LayoutParams;
/**
* This class is an implementation of a bridge between SurfaceView and OpenCV VideoCapture.
* The class is experimental implementation and not recoomended for production usage.
*/
public class NativeCameraView extends CameraBridgeViewBase {
public static final String TAG = "NativeCameraView";
private boolean mStopThread;
private Thread mThread;
protected VideoCapture mCamera;
protected RotatedCameraFrame mFrame;
public NativeCameraView(Context context, int cameraId) {
super(context, cameraId);
}
public NativeCameraView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean connectCamera(int width, int height) {
/* 1. We need to instantiate camera
* 2. We need to start thread which will be getting frames
*/
/* First step - initialize camera connection */
if (!initializeCamera(width, height))
return false;
/* now we can start update thread */
mThread = new Thread(new CameraWorker());
mThread.start();
return true;
}
@Override
protected void disconnectCamera() {
/* 1. We need to stop thread which updating the frames
* 2. Stop camera and release it
*/
if (mThread != null) {
try {
mStopThread = true;
mThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mThread = null;
mStopThread = false;
}
}
/* Now release camera */
releaseCamera();
}
public static class OpenCvSizeAccessor implements ListItemAccessor {
public int getWidth(Object obj) {
Size size = (Size)obj;
return (int)size.width;
}
public int getHeight(Object obj) {
Size size = (Size)obj;
return (int)size.height;
}
}
private boolean initializeCamera(int width, int height) {
synchronized (this) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
int localCameraIndex = mCameraIndex;
if (mCameraIndex == CAMERA_ID_ANY) {
Log.d(TAG, "Try to open default camera");
localCameraIndex = 0;
} else if (mCameraIndex == CAMERA_ID_BACK) {
Log.i(TAG, "Trying to open back camera");
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Camera.getCameraInfo( camIdx, cameraInfo );
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
localCameraIndex = camIdx;
break;
}
}
} else if (mCameraIndex == CAMERA_ID_FRONT) {
Log.i(TAG, "Trying to open front camera");
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Camera.getCameraInfo( camIdx, cameraInfo );
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
localCameraIndex = camIdx;
break;
}
}
}
if (localCameraIndex == CAMERA_ID_BACK) {
Log.e(TAG, "Back camera not found!");
return false;
} else if (localCameraIndex == CAMERA_ID_FRONT) {
Log.e(TAG, "Front camera not found!");
return false;
}
MatOfInt params = new MatOfInt(Videoio.CAP_PROP_FRAME_WIDTH, width,
Videoio.CAP_PROP_FRAME_HEIGHT, height);
Log.d(TAG, "Try to open camera with index " + localCameraIndex);
mCamera = new VideoCapture(localCameraIndex, Videoio.CAP_ANDROID, params);
if (mCamera == null)
return false;
if (mCamera.isOpened() == false)
return false;
if (mCameraIndex != CAMERA_ID_BACK && mCameraIndex != CAMERA_ID_FRONT)
Camera.getCameraInfo(localCameraIndex, cameraInfo);
int frameRotation = getFrameRotation(
cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT,
cameraInfo.orientation);
mFrame = new RotatedCameraFrame(new NativeCameraFrame(mCamera), frameRotation);
if (frameRotation % 180 == 0) {
mFrameWidth = (int) mCamera.get(Videoio.CAP_PROP_FRAME_WIDTH);
mFrameHeight = (int) mCamera.get(Videoio.CAP_PROP_FRAME_HEIGHT);
} else {
mFrameWidth = (int) mCamera.get(Videoio.CAP_PROP_FRAME_HEIGHT);
mFrameHeight = (int) mCamera.get(Videoio.CAP_PROP_FRAME_WIDTH);
}
if ((getLayoutParams().width == LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LayoutParams.MATCH_PARENT))
mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth);
else
mScale = 0;
if (mFpsMeter != null) {
mFpsMeter.setResolution(mFrameWidth, mFrameHeight);
}
AllocateCache();
}
Log.i(TAG, "Selected camera frame size = (" + mFrameWidth + ", " + mFrameHeight + ")");
return true;
}
private void releaseCamera() {
synchronized (this) {
if (mFrame != null) {
mFrame.mFrame.release();
mFrame.release();
}
if (mCamera != null) mCamera.release();
}
}
private static class NativeCameraFrame implements CvCameraViewFrame {
@Override
public Mat rgba() {
mCapture.set(Videoio.CAP_PROP_FOURCC, VideoWriter.fourcc('R','G','B','4'));
mCapture.retrieve(mRgba);
Log.d(TAG, "Retrieved frame with size " + mRgba.cols() + "x" + mRgba.rows() + " and channels: " + mRgba.channels());
return mRgba;
}
@Override
public Mat gray() {
mCapture.set(Videoio.CAP_PROP_FOURCC, VideoWriter.fourcc('G','R','E','Y'));
mCapture.retrieve(mGray);
Log.d(TAG, "Retrieved frame with size " + mGray.cols() + "x" + mGray.rows() + " and channels: " + mGray.channels());
return mGray;
}
public NativeCameraFrame(VideoCapture capture) {
mCapture = capture;
mGray = new Mat();
mRgba = new Mat();
}
@Override
public void release() {
if (mGray != null) mGray.release();
if (mRgba != null) mRgba.release();
}
private VideoCapture mCapture;
private Mat mRgba;
private Mat mGray;
};
private class CameraWorker implements Runnable {
public void run() {
do {
if (!mCamera.grab()) {
Log.e(TAG, "Camera frame grab failed");
break;
}
deliverAndDrawFrame(mFrame);
} while (!mStopThread);
}
}
}
@@ -0,0 +1,60 @@
package org.opencv.android;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import static android.Manifest.permission.CAMERA;
public class CameraActivity extends Activity {
private static final int CAMERA_PERMISSION_REQUEST_CODE = 200;
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return new ArrayList<CameraBridgeViewBase>();
}
protected void onCameraPermissionGranted() {
List<? extends CameraBridgeViewBase> cameraViews = getCameraViewList();
if (cameraViews == null) {
return;
}
for (CameraBridgeViewBase cameraBridgeViewBase: cameraViews) {
if (cameraBridgeViewBase != null) {
cameraBridgeViewBase.setCameraPermissionGranted();
}
}
}
@Override
protected void onStart() {
super.onStart();
boolean havePermission = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
havePermission = false;
}
}
if (havePermission) {
onCameraPermissionGranted();
}
}
@Override
@TargetApi(Build.VERSION_CODES.M)
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == CAMERA_PERMISSION_REQUEST_CODE && grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
onCameraPermissionGranted();
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
@@ -0,0 +1,607 @@
package org.opencv.android;
import java.util.List;
import org.opencv.BuildConfig;
import org.opencv.R;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
/**
* This is a basic class, implementing the interaction with Camera and OpenCV library.
* The main responsibility of it - is to control when camera can be enabled, process the frame,
* call external listener to make any adjustments to the frame and then draw the resulting
* frame to the screen.
* The clients shall implement CvCameraViewListener.
*/
public abstract class CameraBridgeViewBase extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraBridge";
protected static final int MAX_UNSPECIFIED = -1;
private static final int STOPPED = 0;
private static final int STARTED = 1;
private int mState = STOPPED;
private Bitmap mCacheBitmap;
private CvCameraViewListener2 mListener;
private boolean mSurfaceExist;
private final Object mSyncObject = new Object();
protected int mFrameWidth;
protected int mFrameHeight;
protected int mMaxHeight;
protected int mMaxWidth;
protected float mScale = 0;
protected int mPreviewFormat = RGBA;
protected int mCameraIndex = CAMERA_ID_ANY;
protected boolean mEnabled;
protected boolean mCameraPermissionGranted = false;
protected FpsMeter mFpsMeter = null;
public static final int CAMERA_ID_ANY = -1;
public static final int CAMERA_ID_BACK = 99;
public static final int CAMERA_ID_FRONT = 98;
public static final int RGBA = 1;
public static final int GRAY = 2;
public CameraBridgeViewBase(Context context, int cameraId) {
super(context);
mCameraIndex = cameraId;
getHolder().addCallback(this);
mMaxWidth = MAX_UNSPECIFIED;
mMaxHeight = MAX_UNSPECIFIED;
}
public CameraBridgeViewBase(Context context, AttributeSet attrs) {
super(context, attrs);
int count = attrs.getAttributeCount();
Log.d(TAG, "Attr count: " + Integer.valueOf(count));
TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs, R.styleable.CameraBridgeViewBase);
if (styledAttrs.getBoolean(R.styleable.CameraBridgeViewBase_show_fps, false))
enableFpsMeter();
mCameraIndex = styledAttrs.getInt(R.styleable.CameraBridgeViewBase_camera_id, -1);
getHolder().addCallback(this);
mMaxWidth = MAX_UNSPECIFIED;
mMaxHeight = MAX_UNSPECIFIED;
styledAttrs.recycle();
}
/**
* Sets the camera index
* @param cameraIndex new camera index
*/
public void setCameraIndex(int cameraIndex) {
this.mCameraIndex = cameraIndex;
}
public interface CvCameraViewListener {
/**
* This method is invoked when camera preview has started. After this method is invoked
* the frames will start to be delivered to client via the onCameraFrame() callback.
* @param width - the width of the frames that will be delivered
* @param height - the height of the frames that will be delivered
*/
public void onCameraViewStarted(int width, int height);
/**
* This method is invoked when camera preview has been stopped for some reason.
* No frames will be delivered via onCameraFrame() callback after this method is called.
*/
public void onCameraViewStopped();
/**
* This method is invoked when delivery of the frame needs to be done.
* The returned values - is a modified frame which needs to be displayed on the screen.
* TODO: pass the parameters specifying the format of the frame (BPP, YUV or RGB and etc)
*/
public Mat onCameraFrame(Mat inputFrame);
}
public interface CvCameraViewListener2 {
/**
* This method is invoked when camera preview has started. After this method is invoked
* the frames will start to be delivered to client via the onCameraFrame() callback.
* @param width - the width of the frames that will be delivered
* @param height - the height of the frames that will be delivered
*/
public void onCameraViewStarted(int width, int height);
/**
* This method is invoked when camera preview has been stopped for some reason.
* No frames will be delivered via onCameraFrame() callback after this method is called.
*/
public void onCameraViewStopped();
/**
* This method is invoked when delivery of the frame needs to be done.
* The returned values - is a modified frame which needs to be displayed on the screen.
* TODO: pass the parameters specifying the format of the frame (BPP, YUV or RGB and etc)
*/
public Mat onCameraFrame(CvCameraViewFrame inputFrame);
};
protected class CvCameraViewListenerAdapter implements CvCameraViewListener2 {
public CvCameraViewListenerAdapter(CvCameraViewListener oldStypeListener) {
mOldStyleListener = oldStypeListener;
}
public void onCameraViewStarted(int width, int height) {
mOldStyleListener.onCameraViewStarted(width, height);
}
public void onCameraViewStopped() {
mOldStyleListener.onCameraViewStopped();
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
Mat result = null;
switch (mPreviewFormat) {
case RGBA:
result = mOldStyleListener.onCameraFrame(inputFrame.rgba());
break;
case GRAY:
result = mOldStyleListener.onCameraFrame(inputFrame.gray());
break;
default:
Log.e(TAG, "Invalid frame format! Only RGBA and Gray Scale are supported!");
};
return result;
}
public void setFrameFormat(int format) {
mPreviewFormat = format;
}
private int mPreviewFormat = RGBA;
private CvCameraViewListener mOldStyleListener;
};
/**
* This class interface is abstract representation of single frame from camera for onCameraFrame callback
* Attention: Do not use objects, that represents this interface out of onCameraFrame callback!
*/
public interface CvCameraViewFrame {
/**
* This method returns RGBA Mat with frame
*/
public Mat rgba();
/**
* This method returns single channel gray scale Mat with frame
*/
public Mat gray();
public void release();
};
public class RotatedCameraFrame implements CvCameraViewFrame {
@Override
public Mat gray() {
if (mRotation != 0) {
Core.rotate(mFrame.gray(), mGrayRotated, getCvRotationCode(mRotation));
return mGrayRotated;
} else {
return mFrame.gray();
}
}
@Override
public Mat rgba() {
if (mRotation != 0) {
Core.rotate(mFrame.rgba(), mRgbaRotated, getCvRotationCode(mRotation));
return mRgbaRotated;
} else {
return mFrame.rgba();
}
}
private int getCvRotationCode(int degrees) {
if (degrees == 90) {
return Core.ROTATE_90_CLOCKWISE;
} else if (degrees == 180) {
return Core.ROTATE_180;
} else {
return Core.ROTATE_90_COUNTERCLOCKWISE;
}
}
public RotatedCameraFrame(CvCameraViewFrame frame, int rotation) {
super();
mFrame = frame;
mRgbaRotated = new Mat();
mGrayRotated = new Mat();
mRotation = rotation;
}
@Override
public void release() {
mRgbaRotated.release();
mGrayRotated.release();
}
public CvCameraViewFrame mFrame;
private Mat mRgbaRotated;
private Mat mGrayRotated;
private int mRotation;
};
/**
* Calculates how to rotate camera frame to match current screen orientation
*/
protected int getFrameRotation(boolean cameraFacingFront, int cameraSensorOrientation) {
WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
int screenOrientation = windowManager.getDefaultDisplay().getRotation();
int screenRotation = 0;
switch (screenOrientation) {
case Surface.ROTATION_0:
screenRotation = 0;
break;
case Surface.ROTATION_90:
screenRotation = 90;
break;
case Surface.ROTATION_180:
screenRotation = 180;
break;
case Surface.ROTATION_270:
screenRotation = 270;
break;
}
int frameRotation;
if (cameraFacingFront) {
frameRotation = (cameraSensorOrientation + screenRotation) % 360;
} else {
frameRotation = (cameraSensorOrientation - screenRotation + 360) % 360;
}
return frameRotation;
}
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
Log.d(TAG, "call surfaceChanged event");
synchronized(mSyncObject) {
if (!mSurfaceExist) {
mSurfaceExist = true;
checkCurrentState();
} else {
/** Surface changed. We need to stop camera and restart with new parameters */
/* Pretend that old surface has been destroyed */
mSurfaceExist = false;
checkCurrentState();
/* Now use new surface. Say we have it now */
mSurfaceExist = true;
checkCurrentState();
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
/* Do nothing. Wait until surfaceChanged delivered */
}
public void surfaceDestroyed(SurfaceHolder holder) {
synchronized(mSyncObject) {
mSurfaceExist = false;
checkCurrentState();
}
}
/**
* This method is provided for clients, so they can signal camera permission has been granted.
* The actual onCameraViewStarted callback will be delivered only after setCameraPermissionGranted
* and enableView have been called and surface is available
*/
public void setCameraPermissionGranted() {
synchronized(mSyncObject) {
mCameraPermissionGranted = true;
checkCurrentState();
}
}
/**
* This method is provided for clients, so they can enable the camera connection.
* The actual onCameraViewStarted callback will be delivered only after setCameraPermissionGranted
* and enableView have been called and surface is available
*/
public void enableView() {
synchronized(mSyncObject) {
mEnabled = true;
checkCurrentState();
}
}
/**
* This method is provided for clients, so they can disable camera connection and stop
* the delivery of frames even though the surface view itself is not destroyed and still stays on the screen
*/
public void disableView() {
synchronized(mSyncObject) {
mEnabled = false;
checkCurrentState();
}
}
/**
* This method enables label with fps value on the screen
*/
public void enableFpsMeter() {
if (mFpsMeter == null) {
mFpsMeter = new FpsMeter();
mFpsMeter.setResolution(mFrameWidth, mFrameHeight);
}
}
public void disableFpsMeter() {
mFpsMeter = null;
}
/**
*
* @param listener
*/
public void setCvCameraViewListener(CvCameraViewListener2 listener) {
mListener = listener;
}
public void setCvCameraViewListener(CvCameraViewListener listener) {
CvCameraViewListenerAdapter adapter = new CvCameraViewListenerAdapter(listener);
adapter.setFrameFormat(mPreviewFormat);
mListener = adapter;
}
/**
* This method sets the maximum size that camera frame is allowed to be. When selecting
* size - the biggest size which less or equal the size set will be selected.
* As an example - we set setMaxFrameSize(200,200) and we have 176x152 and 320x240 sizes. The
* preview frame will be selected with 176x152 size.
* This method is useful when need to restrict the size of preview frame for some reason (for example for video recording)
* @param maxWidth - the maximum width allowed for camera frame.
* @param maxHeight - the maximum height allowed for camera frame
*/
public void setMaxFrameSize(int maxWidth, int maxHeight) {
mMaxWidth = maxWidth;
mMaxHeight = maxHeight;
}
public void SetCaptureFormat(int format)
{
mPreviewFormat = format;
if (mListener instanceof CvCameraViewListenerAdapter) {
CvCameraViewListenerAdapter adapter = (CvCameraViewListenerAdapter) mListener;
adapter.setFrameFormat(mPreviewFormat);
}
}
/**
* Called when mSyncObject lock is held
*/
private void checkCurrentState() {
Log.d(TAG, "call checkCurrentState");
int targetState;
if (mEnabled && mCameraPermissionGranted && mSurfaceExist && getVisibility() == VISIBLE) {
targetState = STARTED;
} else {
targetState = STOPPED;
}
if (targetState != mState) {
/* The state change detected. Need to exit the current state and enter target state */
processExitState(mState);
mState = targetState;
processEnterState(mState);
}
}
private void processEnterState(int state) {
Log.d(TAG, "call processEnterState: " + state);
switch(state) {
case STARTED:
onEnterStartedState();
if (mListener != null) {
mListener.onCameraViewStarted(mFrameWidth, mFrameHeight);
}
break;
case STOPPED:
onEnterStoppedState();
if (mListener != null) {
mListener.onCameraViewStopped();
}
break;
};
}
private void processExitState(int state) {
Log.d(TAG, "call processExitState: " + state);
switch(state) {
case STARTED:
onExitStartedState();
break;
case STOPPED:
onExitStoppedState();
break;
};
}
private void onEnterStoppedState() {
/* nothing to do */
}
private void onExitStoppedState() {
/* nothing to do */
}
// NOTE: The order of bitmap constructor and camera connection is important for android 4.1.x
// Bitmap must be constructed before surface
private void onEnterStartedState() {
Log.d(TAG, "call onEnterStartedState");
/* Connect camera */
if (!connectCamera(getWidth(), getHeight())) {
AlertDialog ad = new AlertDialog.Builder(getContext()).create();
ad.setCancelable(false); // This blocks the 'BACK' button
ad.setMessage("It seems that your device does not support camera (or it is locked). Application will be closed.");
ad.setButton(DialogInterface.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
((Activity) getContext()).finish();
}
});
ad.show();
}
}
private void onExitStartedState() {
disconnectCamera();
if (mCacheBitmap != null) {
mCacheBitmap.recycle();
}
}
/**
* This method shall be called by the subclasses when they have valid
* object and want it to be delivered to external client (via callback) and
* then displayed on the screen.
* @param frame - the current frame to be delivered
*/
protected void deliverAndDrawFrame(CvCameraViewFrame frame) {
Mat modified;
if (mListener != null) {
modified = mListener.onCameraFrame(frame);
} else {
modified = frame.rgba();
}
boolean bmpValid = true;
if (modified != null) {
try {
Utils.matToBitmap(modified, mCacheBitmap);
} catch(Exception e) {
Log.e(TAG, "Mat type: " + modified);
Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight());
Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
bmpValid = false;
}
}
if (bmpValid && mCacheBitmap != null) {
Canvas canvas = getHolder().lockCanvas();
if (canvas != null) {
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
if (BuildConfig.DEBUG)
Log.d(TAG, "mStretch value: " + mScale);
if (mScale != 0) {
canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
new Rect((int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2),
(int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2),
(int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2 + mScale*mCacheBitmap.getWidth()),
(int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2 + mScale*mCacheBitmap.getHeight())), null);
} else {
canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
new Rect((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,
(canvas.getHeight() - mCacheBitmap.getHeight()) / 2,
(canvas.getWidth() - mCacheBitmap.getWidth()) / 2 + mCacheBitmap.getWidth(),
(canvas.getHeight() - mCacheBitmap.getHeight()) / 2 + mCacheBitmap.getHeight()), null);
}
if (mFpsMeter != null) {
mFpsMeter.measure();
mFpsMeter.draw(canvas, 20, 30);
}
getHolder().unlockCanvasAndPost(canvas);
}
}
}
/**
* This method is invoked shall perform concrete operation to initialize the camera.
* CONTRACT: as a result of this method variables mFrameWidth and mFrameHeight MUST be
* initialized with the size of the Camera frames that will be delivered to external processor.
* @param width - the width of this SurfaceView
* @param height - the height of this SurfaceView
*/
protected abstract boolean connectCamera(int width, int height);
/**
* Disconnects and release the particular camera object being connected to this surface view.
* Called when syncObject lock is held
*/
protected abstract void disconnectCamera();
// NOTE: On Android 4.1.x the function must be called before SurfaceTexture constructor!
protected void AllocateCache()
{
mCacheBitmap = Bitmap.createBitmap(mFrameWidth, mFrameHeight, Bitmap.Config.ARGB_8888);
}
public interface ListItemAccessor {
public int getWidth(Object obj);
public int getHeight(Object obj);
};
/**
* This helper method can be called by subclasses to select camera preview size.
* It goes over the list of the supported preview sizes and selects the maximum one which
* fits both values set via setMaxFrameSize() and surface frame allocated for this view
* @param supportedSizes
* @param surfaceWidth
* @param surfaceHeight
* @return optimal frame size
*/
protected Size calculateCameraFrameSize(List<?> supportedSizes, ListItemAccessor accessor, int surfaceWidth, int surfaceHeight) {
int calcWidth = 0;
int calcHeight = 0;
int maxAllowedWidth = (mMaxWidth != MAX_UNSPECIFIED && mMaxWidth < surfaceWidth)? mMaxWidth : surfaceWidth;
int maxAllowedHeight = (mMaxHeight != MAX_UNSPECIFIED && mMaxHeight < surfaceHeight)? mMaxHeight : surfaceHeight;
for (Object size : supportedSizes) {
int width = accessor.getWidth(size);
int height = accessor.getHeight(size);
Log.d(TAG, "trying size: " + width + "x" + height);
if (width <= maxAllowedWidth && height <= maxAllowedHeight) {
if (width >= calcWidth && height >= calcHeight) {
calcWidth = (int) width;
calcHeight = (int) height;
}
}
}
if ((calcWidth == 0 || calcHeight == 0) && supportedSizes.size() > 0)
{
Log.i(TAG, "fallback to the first frame size");
Object size = supportedSizes.get(0);
calcWidth = accessor.getWidth(size);
calcHeight = accessor.getHeight(size);
}
return new Size(calcWidth, calcHeight);
}
}
@@ -0,0 +1,67 @@
package org.opencv.android;
import java.text.DecimalFormat;
import org.opencv.core.Core;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
public class FpsMeter {
private static final String TAG = "FpsMeter";
private static final int STEP = 20;
private static final DecimalFormat FPS_FORMAT = new DecimalFormat("0.00");
private int mFramesCounter;
private double mFrequency;
private long mprevFrameTime;
private String mStrfps;
Paint mPaint;
boolean mIsInitialized = false;
int mWidth = 0;
int mHeight = 0;
public void init() {
mFramesCounter = 0;
mFrequency = Core.getTickFrequency();
mprevFrameTime = Core.getTickCount();
mStrfps = "";
mPaint = new Paint();
mPaint.setColor(Color.BLUE);
mPaint.setTextSize(20);
}
public void measure() {
if (!mIsInitialized) {
init();
mIsInitialized = true;
} else {
mFramesCounter++;
if (mFramesCounter % STEP == 0) {
long time = Core.getTickCount();
double fps = STEP * mFrequency / (time - mprevFrameTime);
mprevFrameTime = time;
if (mWidth != 0 && mHeight != 0)
mStrfps = FPS_FORMAT.format(fps) + " FPS@" + Integer.valueOf(mWidth) + "x" + Integer.valueOf(mHeight);
else
mStrfps = FPS_FORMAT.format(fps) + " FPS";
Log.i(TAG, mStrfps);
}
}
}
public void setResolution(int width, int height) {
Log.d(TAG, "FpsMeter.setResolution " + Integer.valueOf(mWidth) + "x" + Integer.valueOf(mHeight));
mWidth = width;
mHeight = height;
}
public void draw(Canvas canvas, float offsetx, float offsety) {
Log.d(TAG, mStrfps);
canvas.drawText(mStrfps, offsetx, offsety, mPaint);
}
}
@@ -0,0 +1,391 @@
package org.opencv.android;
import java.util.List;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import org.opencv.BuildConfig;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
/**
* This class is an implementation of the Bridge View between OpenCV and Java Camera.
* This class relays on the functionality available in base class and only implements
* required functions:
* connectCamera - opens Java camera and sets the PreviewCallback to be delivered.
* disconnectCamera - closes the camera and stops preview.
* When frame is delivered via callback from Camera - it processed via OpenCV to be
* converted to RGBA32 and then passed to the external callback for modifications if required.
*/
public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallback {
private static final int MAGIC_TEXTURE_ID = 10;
private static final String TAG = "JavaCameraView";
private byte mBuffer[];
private Mat[] mFrameChain;
private int mChainIdx = 0;
private Thread mThread;
private boolean mStopThread;
protected Camera mCamera;
protected RotatedCameraFrame[] mCameraFrame;
private SurfaceTexture mSurfaceTexture;
private int mPreviewFormat = ImageFormat.NV21;
public static class JavaCameraSizeAccessor implements ListItemAccessor {
@Override
public int getWidth(Object obj) {
Camera.Size size = (Camera.Size) obj;
return size.width;
}
@Override
public int getHeight(Object obj) {
Camera.Size size = (Camera.Size) obj;
return size.height;
}
}
public JavaCameraView(Context context, int cameraId) {
super(context, cameraId);
}
public JavaCameraView(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected boolean initializeCamera(int width, int height) {
Log.d(TAG, "Initialize java camera");
boolean result = true;
synchronized (this) {
mCamera = null;
int cameraId = -1;
if (mCameraIndex == CAMERA_ID_ANY) {
boolean connected = false;
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(camIdx) + ")");
try {
mCamera = Camera.open(camIdx);
connected = true;
cameraId = camIdx;
} catch (RuntimeException e) {
Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
}
if (connected) break;
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
int localCameraIndex = mCameraIndex;
if (mCameraIndex == CAMERA_ID_BACK) {
Log.i(TAG, "Trying to open back camera");
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Camera.getCameraInfo( camIdx, cameraInfo );
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
localCameraIndex = camIdx;
break;
}
}
} else if (mCameraIndex == CAMERA_ID_FRONT) {
Log.i(TAG, "Trying to open front camera");
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Camera.getCameraInfo( camIdx, cameraInfo );
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
localCameraIndex = camIdx;
break;
}
}
}
if (localCameraIndex == CAMERA_ID_BACK) {
Log.e(TAG, "Back camera not found!");
} else if (localCameraIndex == CAMERA_ID_FRONT) {
Log.e(TAG, "Front camera not found!");
} else {
Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(localCameraIndex) + ")");
try {
mCamera = Camera.open(localCameraIndex);
cameraId = localCameraIndex;
} catch (RuntimeException e) {
Log.e(TAG, "Camera #" + localCameraIndex + "failed to open: " + e.getLocalizedMessage());
}
}
}
}
if (mCamera == null)
return false;
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int frameRotation = getFrameRotation(
info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT,
info.orientation);
/* Now set camera parameters */
try {
Camera.Parameters params = mCamera.getParameters();
Log.d(TAG, "getSupportedPreviewSizes()");
List<android.hardware.Camera.Size> sizes = params.getSupportedPreviewSizes();
if (sizes != null) {
/* Select the size that fits surface considering maximum size allowed */
Size frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height);
/* Image format NV21 causes issues in the Android emulators */
if (Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86")
|| Build.MANUFACTURER.contains("Genymotion")
|| (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
|| "google_sdk".equals(Build.PRODUCT))
params.setPreviewFormat(ImageFormat.YV12); // "generic" or "android" = android emulator
else
params.setPreviewFormat(ImageFormat.NV21);
mPreviewFormat = params.getPreviewFormat();
Log.d(TAG, "Set preview size to " + Integer.valueOf((int)frameSize.width) + "x" + Integer.valueOf((int)frameSize.height));
params.setPreviewSize((int)frameSize.width, (int)frameSize.height);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && !android.os.Build.MODEL.equals("GT-I9100"))
params.setRecordingHint(true);
List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
{
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(params);
params = mCamera.getParameters();
int rawFrameWidth = params.getPreviewSize().width;
int rawFrameHeight = params.getPreviewSize().height;
if (frameRotation % 180 == 0) {
mFrameWidth = params.getPreviewSize().width;
mFrameHeight = params.getPreviewSize().height;
} else {
mFrameWidth = params.getPreviewSize().height;
mFrameHeight = params.getPreviewSize().width;
}
if ((getLayoutParams().width == LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LayoutParams.MATCH_PARENT))
mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth);
else
mScale = 0;
if (mFpsMeter != null) {
mFpsMeter.setResolution(mFrameWidth, mFrameHeight);
}
int size = mFrameWidth * mFrameHeight;
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
mCamera.addCallbackBuffer(mBuffer);
mCamera.setPreviewCallbackWithBuffer(this);
mFrameChain = new Mat[2];
mFrameChain[0] = new Mat(rawFrameHeight + (rawFrameHeight/2), rawFrameWidth, CvType.CV_8UC1);
mFrameChain[1] = new Mat(rawFrameHeight + (rawFrameHeight/2), rawFrameWidth, CvType.CV_8UC1);
AllocateCache();
mCameraFrame = new RotatedCameraFrame[2];
mCameraFrame[0] = new RotatedCameraFrame(new JavaCameraFrame(mFrameChain[0], rawFrameWidth, rawFrameHeight), frameRotation);
mCameraFrame[1] = new RotatedCameraFrame(new JavaCameraFrame(mFrameChain[1], rawFrameWidth, rawFrameHeight), frameRotation);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
mCamera.setPreviewTexture(mSurfaceTexture);
} else
mCamera.setPreviewDisplay(null);
/* Finally we are ready to start the preview */
Log.d(TAG, "startPreview");
mCamera.startPreview();
}
else
result = false;
} catch (Exception e) {
result = false;
e.printStackTrace();
}
}
return result;
}
protected void releaseCamera() {
synchronized (this) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
}
mCamera = null;
if (mFrameChain != null) {
mFrameChain[0].release();
mFrameChain[1].release();
}
if (mCameraFrame != null) {
mCameraFrame[0].mFrame.release();
mCameraFrame[0].release();
mCameraFrame[1].mFrame.release();
mCameraFrame[1].release();
}
}
}
private boolean mCameraFrameReady = false;
@Override
protected boolean connectCamera(int width, int height) {
/* 1. We need to instantiate camera
* 2. We need to start thread which will be getting frames
*/
/* First step - initialize camera connection */
Log.d(TAG, "Connecting to camera");
if (!initializeCamera(width, height))
return false;
mCameraFrameReady = false;
/* now we can start update thread */
Log.d(TAG, "Starting processing thread");
mStopThread = false;
mThread = new Thread(new CameraWorker());
mThread.start();
return true;
}
@Override
protected void disconnectCamera() {
/* 1. We need to stop thread which updating the frames
* 2. Stop camera and release it
*/
Log.d(TAG, "Disconnecting from camera");
try {
mStopThread = true;
Log.d(TAG, "Notify thread");
synchronized (this) {
this.notify();
}
Log.d(TAG, "Waiting for thread");
if (mThread != null)
mThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mThread = null;
}
/* Now release camera */
releaseCamera();
mCameraFrameReady = false;
}
@Override
public void onPreviewFrame(byte[] frame, Camera arg1) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Preview Frame received. Frame size: " + frame.length);
synchronized (this) {
mFrameChain[mChainIdx].put(0, 0, frame);
mCameraFrameReady = true;
this.notify();
}
if (mCamera != null)
mCamera.addCallbackBuffer(mBuffer);
}
private class JavaCameraFrame implements CvCameraViewFrame {
@Override
public Mat gray() {
return mYuvFrameData.submat(0, mHeight, 0, mWidth);
}
@Override
public Mat rgba() {
if (mPreviewFormat == ImageFormat.NV21)
Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4);
else if (mPreviewFormat == ImageFormat.YV12)
Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGB_I420, 4); // COLOR_YUV2RGBA_YV12 produces inverted colors
else
throw new IllegalArgumentException("Preview Format can be NV21 or YV12");
return mRgba;
}
public JavaCameraFrame(Mat Yuv420sp, int width, int height) {
super();
mWidth = width;
mHeight = height;
mYuvFrameData = Yuv420sp;
mRgba = new Mat();
}
@Override
public void release() {
mRgba.release();
}
private Mat mYuvFrameData;
private Mat mRgba;
private int mWidth;
private int mHeight;
};
private class CameraWorker implements Runnable {
@Override
public void run() {
do {
boolean hasFrame = false;
synchronized (JavaCameraView.this) {
try {
while (!mCameraFrameReady && !mStopThread) {
JavaCameraView.this.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
if (mCameraFrameReady)
{
mChainIdx = 1 - mChainIdx;
mCameraFrameReady = false;
hasFrame = true;
}
}
if (!mStopThread && hasFrame) {
if (!mFrameChain[1 - mChainIdx].empty())
deliverAndDrawFrame(mCameraFrame[1 - mChainIdx]);
}
} while (!mStopThread);
Log.d(TAG, "Finish processing thread");
}
}
}
@@ -0,0 +1,44 @@
package org.opencv.android;
import android.content.Context;
/**
* Helper class provides common initialization methods for OpenCV library.
*/
public class OpenCVLoader
{
/**
* Current OpenCV Library version
*/
public static final String OPENCV_VERSION = "@OPENCV_VERSION_MAJOR@.@OPENCV_VERSION_MINOR@.@OPENCV_VERSION_PATCH@";
/**
* Synonym for initLocal. Deprecated.
*/
@Deprecated
public static boolean initDebug()
{
return StaticHelper.initOpenCV(false);
}
/**
* Loads and initializes OpenCV library from current application package. Roughly, it's an analog of system.loadLibrary("opencv_java").
* @return Returns true is initialization of OpenCV was successful.
*/
public static boolean initLocal()
{
return StaticHelper.initOpenCV(false);
}
/**
* Loads and initializes OpenCV library from current application package. Roughly, it's an analog of system.loadLibrary("opencv_java").
* @param InitCuda load and initialize CUDA runtime libraries.
* @return Returns true is initialization of OpenCV was successful.
*/
@Deprecated
public static boolean initDebug(boolean InitCuda)
{
return StaticHelper.initOpenCV(InitCuda);
}
}
@@ -0,0 +1,60 @@
package org.opencv.android;
import org.opencv.core.Core;
import java.util.StringTokenizer;
import android.util.Log;
class StaticHelper {
public static boolean initOpenCV(boolean InitCuda)
{
boolean result;
String libs = "";
if(InitCuda)
Log.w(TAG, "CUDA support was removed!");
Log.d(TAG, "First attempt to load libs");
if (loadLibrary("opencv_java4"))
{
Log.d(TAG, "First attempt to load libs is OK");
String eol = System.getProperty("line.separator");
for (String str : Core.getBuildInformation().split(eol))
Log.i(TAG, str);
result = true;
}
else
{
Log.d(TAG, "First attempt to load libs fails");
result = false;
}
return result;
}
private static boolean loadLibrary(String Name)
{
boolean result = true;
Log.d(TAG, "Trying to load library " + Name);
try
{
System.loadLibrary(Name);
Log.d(TAG, "Library " + Name + " loaded");
}
catch(UnsatisfiedLinkError e)
{
Log.d(TAG, "Cannot load library \"" + Name + "\"");
e.printStackTrace();
result = false;
}
return result;
}
private static final String TAG = "OpenCV/StaticHelper";
private static native String getLibraryList();
}
@@ -0,0 +1,138 @@
package org.opencv.android;
import android.content.Context;
import android.graphics.Bitmap;
import org.opencv.core.CvException;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class Utils {
public static String exportResource(Context context, int resourceId) {
return exportResource(context, resourceId, "OpenCV_data");
}
public static String exportResource(Context context, int resourceId, String dirname) {
String fullname = context.getResources().getString(resourceId);
String resName = fullname.substring(fullname.lastIndexOf("/") + 1);
try (InputStream is = context.getResources().openRawResource(resourceId)) {
File resDir = context.getDir(dirname, Context.MODE_PRIVATE);
File resFile = new File(resDir, resName);
try (FileOutputStream os = new FileOutputStream(resFile)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
}
return resFile.getAbsolutePath();
} catch (IOException e) {
throw new CvException("Failed to export resource " + resName
+ ". Exception thrown: " + e);
}
}
public static Mat loadResource(Context context, int resourceId) throws IOException
{
return loadResource(context, resourceId, -1);
}
public static Mat loadResource(Context context, int resourceId, int flags) throws IOException
{
byte[] data;
int dataLength;
try (InputStream is = context.getResources().openRawResource(resourceId);
ByteArrayOutputStream os = new ByteArrayOutputStream(is.available())) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
data = os.toByteArray();
dataLength = os.size();
}
Mat encoded = new Mat(1, dataLength, CvType.CV_8U);
encoded.put(0, 0, data);
Mat decoded = Imgcodecs.imdecode(encoded, flags);
encoded.release();
return decoded;
}
/**
* Converts Android Bitmap to OpenCV Mat.
* <p>
* This function converts an Android Bitmap image to the OpenCV Mat.
* <br>'ARGB_8888' and 'RGB_565' input Bitmap formats are supported.
* <br>The output Mat is always created of the same size as the input Bitmap and of the 'CV_8UC4' type,
* it keeps the image in RGBA format.
* <br>This function throws an exception if the conversion fails.
* @param bmp is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'.
* @param mat is a valid output Mat object, it will be reallocated if needed, so it may be empty.
* @param unPremultiplyAlpha is a flag, that determines, whether the bitmap needs to be converted from alpha premultiplied format (like Android keeps 'ARGB_8888' ones) to regular one; this flag is ignored for 'RGB_565' bitmaps.
*/
public static void bitmapToMat(Bitmap bmp, Mat mat, boolean unPremultiplyAlpha) {
if (bmp == null)
throw new IllegalArgumentException("bmp == null");
if (mat == null)
throw new IllegalArgumentException("mat == null");
nBitmapToMat2(bmp, mat.nativeObj, unPremultiplyAlpha);
}
/**
* Short form of the bitmapToMat(bmp, mat, unPremultiplyAlpha=false).
* @param bmp is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'.
* @param mat is a valid output Mat object, it will be reallocated if needed, so Mat may be empty.
*/
public static void bitmapToMat(Bitmap bmp, Mat mat) {
bitmapToMat(bmp, mat, false);
}
/**
* Converts OpenCV Mat to Android Bitmap.
* <p>
* <br>This function converts an image in the OpenCV Mat representation to the Android Bitmap.
* <br>The input Mat object has to be of the types 'CV_8UC1' (gray-scale), 'CV_8UC3' (RGB) or 'CV_8UC4' (RGBA).
* <br>The output Bitmap object has to be of the same size as the input Mat and of the types 'ARGB_8888' or 'RGB_565'.
* <br>This function throws an exception if the conversion fails.
*
* @param mat is a valid input Mat object of types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'.
* @param bmp is a valid Bitmap object of the same size as the Mat and of type 'ARGB_8888' or 'RGB_565'.
* @param premultiplyAlpha is a flag, that determines, whether the Mat needs to be converted to alpha premultiplied format (like Android keeps 'ARGB_8888' bitmaps); the flag is ignored for 'RGB_565' bitmaps.
*/
public static void matToBitmap(Mat mat, Bitmap bmp, boolean premultiplyAlpha) {
if (mat == null)
throw new IllegalArgumentException("mat == null");
if (bmp == null)
throw new IllegalArgumentException("bmp == null");
nMatToBitmap2(mat.nativeObj, bmp, premultiplyAlpha);
}
/**
* Short form of the <b>matToBitmap(mat, bmp, premultiplyAlpha=false)</b>
* @param mat is a valid input Mat object of the types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'.
* @param bmp is a valid Bitmap object of the same size as the Mat and of type 'ARGB_8888' or 'RGB_565'.
*/
public static void matToBitmap(Mat mat, Bitmap bmp) {
matToBitmap(mat, bmp, false);
}
private static native void nBitmapToMat2(Bitmap b, long m_addr, boolean unPremultiplyAlpha);
private static native void nMatToBitmap2(long m_addr, Bitmap b, boolean premultiplyAlpha);
}
+1568
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,28 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "opencv2/core.hpp"
#define LOG_TAG "org.opencv.core.CleanableMat"
#include "common.h"
#include <iostream>
using namespace cv;
extern "C" {
//
// native support for java finalize() or cleaners
// static void CleanableMat::n_delete( __int64 self )
//
JNIEXPORT void JNICALL Java_org_opencv_core_CleanableMat_n_1delete
(JNIEnv*, jclass, jlong self);
JNIEXPORT void JNICALL Java_org_opencv_core_CleanableMat_n_1delete
(JNIEnv*, jclass, jlong self)
{
// LOGD("CleanableMat.n_delete() called\n");
delete (Mat*) self;
}
}
File diff suppressed because it is too large Load Diff
+42
View File
@@ -0,0 +1,42 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#ifndef __OPENCV_JAVA_COMMON_H__
#define __OPENCV_JAVA_COMMON_H__
#include <stdexcept>
#include <string>
extern "C" {
#if !defined(__ppc__)
// to suppress warning from jni.h on OS X
# define TARGET_RT_MAC_CFM 0
#endif
#include <jni.h>
// make -fvisibility=hidden work with java 1.7
#if defined(__linux__) && !defined(__ANDROID__) && !defined (JNI_VERSION_1_8)
// adapted from jdk1.8/jni.h
#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
#undef JNIEXPORT
#define JNIEXPORT __attribute__((visibility("default")))
#undef JNIIMPORT
#define JNIIMPORT __attribute__((visibility("default")))
#endif
#endif
} // extern "C"
#include "opencv_java.hpp"
#include "opencv2/core/utility.hpp"
#include "converters.h"
#include "listconverters.hpp"
#ifdef _MSC_VER
# pragma warning(disable:4800 4244)
#endif
#endif //__OPENCV_JAVA_COMMON_H__
@@ -0,0 +1,378 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#define LOG_TAG "org.opencv.utils.Converters"
#include "common.h"
using namespace cv;
// vector_int
void Mat_to_vector_int(Mat& mat, std::vector<int>& v_int)
{
v_int.clear();
CHECK_MAT(mat.type()==CV_32SC1 && mat.cols==1);
v_int = (std::vector<int>) mat;
}
void vector_int_to_Mat(std::vector<int>& v_int, Mat& mat)
{
mat = Mat(v_int, true);
}
//vector_double
void Mat_to_vector_double(Mat& mat, std::vector<double>& v_double)
{
v_double.clear();
CHECK_MAT(mat.type()==CV_64FC1 && mat.cols==1);
v_double = (std::vector<double>) mat;
}
void vector_double_to_Mat(std::vector<double>& v_double, Mat& mat)
{
mat = Mat(v_double, true);
}
// vector_float
void Mat_to_vector_float(Mat& mat, std::vector<float>& v_float)
{
v_float.clear();
CHECK_MAT(mat.type()==CV_32FC1 && mat.cols==1);
v_float = (std::vector<float>) mat;
}
void vector_float_to_Mat(std::vector<float>& v_float, Mat& mat)
{
mat = Mat(v_float, true);
}
//vector_uchar
void Mat_to_vector_uchar(Mat& mat, std::vector<uchar>& v_uchar)
{
v_uchar.clear();
CHECK_MAT(mat.type()==CV_8UC1 && mat.cols==1);
v_uchar = (std::vector<uchar>) mat;
}
void vector_uchar_to_Mat(std::vector<uchar>& v_uchar, Mat& mat)
{
mat = Mat(v_uchar, true);
}
void Mat_to_vector_char(Mat& mat, std::vector<char>& v_char)
{
v_char.clear();
CHECK_MAT(mat.type()==CV_8SC1 && mat.cols==1);
v_char = (std::vector<char>) mat;
}
void vector_char_to_Mat(std::vector<char>& v_char, Mat& mat)
{
mat = Mat(v_char, true);
}
//vector_Rect
void Mat_to_vector_Rect(Mat& mat, std::vector<Rect>& v_rect)
{
v_rect.clear();
CHECK_MAT(mat.type()==CV_32SC4 && mat.cols==1);
v_rect = (std::vector<Rect>) mat;
}
void vector_Rect_to_Mat(std::vector<Rect>& v_rect, Mat& mat)
{
mat = Mat(v_rect, true);
}
//vector_Rect2d
void Mat_to_vector_Rect2d(Mat& mat, std::vector<Rect2d>& v_rect)
{
v_rect.clear();
CHECK_MAT(mat.type()==CV_64FC4 && mat.cols==1);
v_rect = (std::vector<Rect2d>) mat;
}
void vector_Rect2d_to_Mat(std::vector<Rect2d>& v_rect, Mat& mat)
{
mat = Mat(v_rect, true);
}
//vector_RotatedRect
void Mat_to_vector_RotatedRect(Mat& mat, std::vector<RotatedRect>& v_rect)
{
v_rect.clear();
CHECK_MAT(mat.type()==CV_32FC(5) && mat.cols==1);
v_rect = (std::vector<RotatedRect>) mat;
}
void vector_RotatedRect_to_Mat(std::vector<RotatedRect>& v_rect, Mat& mat)
{
mat = Mat(v_rect, true);
}
//vector_Point
void Mat_to_vector_Point(Mat& mat, std::vector<Point>& v_point)
{
v_point.clear();
CHECK_MAT(mat.type()==CV_32SC2 && mat.cols==1);
v_point = (std::vector<Point>) mat;
}
//vector_Point2f
void Mat_to_vector_Point2f(Mat& mat, std::vector<Point2f>& v_point)
{
v_point.clear();
CHECK_MAT(mat.type()==CV_32FC2 && mat.cols==1);
v_point = (std::vector<Point2f>) mat;
}
//vector_Point2d
void Mat_to_vector_Point2d(Mat& mat, std::vector<Point2d>& v_point)
{
v_point.clear();
CHECK_MAT(mat.type()==CV_64FC2 && mat.cols==1);
v_point = (std::vector<Point2d>) mat;
}
//vector_Point3i
void Mat_to_vector_Point3i(Mat& mat, std::vector<Point3i>& v_point)
{
v_point.clear();
CHECK_MAT(mat.type()==CV_32SC3 && mat.cols==1);
v_point = (std::vector<Point3i>) mat;
}
//vector_Point3f
void Mat_to_vector_Point3f(Mat& mat, std::vector<Point3f>& v_point)
{
v_point.clear();
CHECK_MAT(mat.type()==CV_32FC3 && mat.cols==1);
v_point = (std::vector<Point3f>) mat;
}
//vector_Point3d
void Mat_to_vector_Point3d(Mat& mat, std::vector<Point3d>& v_point)
{
v_point.clear();
CHECK_MAT(mat.type()==CV_64FC3 && mat.cols==1);
v_point = (std::vector<Point3d>) mat;
}
void vector_Point_to_Mat(std::vector<Point>& v_point, Mat& mat)
{
mat = Mat(v_point, true);
}
void vector_Point2f_to_Mat(std::vector<Point2f>& v_point, Mat& mat)
{
mat = Mat(v_point, true);
}
void vector_Point2d_to_Mat(std::vector<Point2d>& v_point, Mat& mat)
{
mat = Mat(v_point, true);
}
void vector_Point3i_to_Mat(std::vector<Point3i>& v_point, Mat& mat)
{
mat = Mat(v_point, true);
}
void vector_Point3f_to_Mat(std::vector<Point3f>& v_point, Mat& mat)
{
mat = Mat(v_point, true);
}
void vector_Point3d_to_Mat(std::vector<Point3d>& v_point, Mat& mat)
{
mat = Mat(v_point, true);
}
//vector_Mat
void Mat_to_vector_Mat(cv::Mat& mat, std::vector<cv::Mat>& v_mat)
{
v_mat.clear();
if(mat.type() == CV_32SC2 && mat.cols == 1)
{
v_mat.reserve(mat.rows);
for(int i=0; i<mat.rows; i++)
{
Vec<int, 2> a = mat.at< Vec<int, 2> >(i, 0);
long long addr = (((long long)a[0])<<32) | (a[1]&0xffffffff);
Mat& m = *( (Mat*) addr );
v_mat.push_back(m);
}
} else {
LOGD("Mat_to_vector_Mat() FAILED: mat.type() == CV_32SC2 && mat.cols == 1");
}
}
void vector_Mat_to_Mat(std::vector<cv::Mat>& v_mat, cv::Mat& mat)
{
int count = (int)v_mat.size();
mat.create(count, 1, CV_32SC2);
for(int i=0; i<count; i++)
{
long long addr = (long long) new Mat(v_mat[i]);
mat.at< Vec<int, 2> >(i, 0) = Vec<int, 2>(addr>>32, addr&0xffffffff);
}
}
void Mat_to_vector_vector_Mat(Mat& mat, std::vector< std::vector< Mat > >& vv_mat)
{
std::vector<Mat> vm;
vm.reserve( mat.rows );
Mat_to_vector_Mat(mat, vm);
for(size_t i=0; i<vm.size(); i++)
{
std::vector<Mat> vmat;
Mat_to_vector_Mat(vm[i], vmat);
vv_mat.push_back(vmat);
}
}
void vector_vector_Mat_to_Mat(std::vector< std::vector< Mat > >& vv_mat, Mat& mat)
{
std::vector<Mat> vm;
vm.reserve( vv_mat.size() );
for(size_t i=0; i<vv_mat.size(); i++)
{
Mat m;
vector_Mat_to_Mat(vv_mat[i], m);
vm.push_back(m);
}
vector_Mat_to_Mat(vm, mat);
}
void Mat_to_vector_vector_Point(Mat& mat, std::vector< std::vector< Point > >& vv_pt)
{
std::vector<Mat> vm;
vm.reserve( mat.rows );
Mat_to_vector_Mat(mat, vm);
for(size_t i=0; i<vm.size(); i++)
{
std::vector<Point> vpt;
Mat_to_vector_Point(vm[i], vpt);
vv_pt.push_back(vpt);
}
}
void Mat_to_vector_vector_Point2f(Mat& mat, std::vector< std::vector< Point2f > >& vv_pt)
{
std::vector<Mat> vm;
vm.reserve( mat.rows );
Mat_to_vector_Mat(mat, vm);
for(size_t i=0; i<vm.size(); i++)
{
std::vector<Point2f> vpt;
Mat_to_vector_Point2f(vm[i], vpt);
vv_pt.push_back(vpt);
}
}
void Mat_to_vector_vector_Point3f(Mat& mat, std::vector< std::vector< Point3f > >& vv_pt)
{
std::vector<Mat> vm;
vm.reserve( mat.rows );
Mat_to_vector_Mat(mat, vm);
for(size_t i=0; i<vm.size(); i++)
{
std::vector<Point3f> vpt;
Mat_to_vector_Point3f(vm[i], vpt);
vv_pt.push_back(vpt);
}
}
void Mat_to_vector_vector_char(Mat& mat, std::vector< std::vector< char > >& vv_ch)
{
std::vector<Mat> vm;
vm.reserve( mat.rows );
Mat_to_vector_Mat(mat, vm);
for(size_t i=0; i<vm.size(); i++)
{
std::vector<char> vch;
Mat_to_vector_char(vm[i], vch);
vv_ch.push_back(vch);
}
}
void vector_vector_char_to_Mat(std::vector< std::vector< char > >& vv_ch, Mat& mat)
{
std::vector<Mat> vm;
vm.reserve( vv_ch.size() );
for(size_t i=0; i<vv_ch.size(); i++)
{
Mat m;
vector_char_to_Mat(vv_ch[i], m);
vm.push_back(m);
}
vector_Mat_to_Mat(vm, mat);
}
void vector_vector_Point_to_Mat(std::vector< std::vector< Point > >& vv_pt, Mat& mat)
{
std::vector<Mat> vm;
vm.reserve( vv_pt.size() );
for(size_t i=0; i<vv_pt.size(); i++)
{
Mat m;
vector_Point_to_Mat(vv_pt[i], m);
vm.push_back(m);
}
vector_Mat_to_Mat(vm, mat);
}
void vector_vector_Point2f_to_Mat(std::vector< std::vector< Point2f > >& vv_pt, Mat& mat)
{
std::vector<Mat> vm;
vm.reserve( vv_pt.size() );
for(size_t i=0; i<vv_pt.size(); i++)
{
Mat m;
vector_Point2f_to_Mat(vv_pt[i], m);
vm.push_back(m);
}
vector_Mat_to_Mat(vm, mat);
}
void vector_vector_Point3f_to_Mat(std::vector< std::vector< Point3f > >& vv_pt, Mat& mat)
{
std::vector<Mat> vm;
vm.reserve( vv_pt.size() );
for(size_t i=0; i<vv_pt.size(); i++)
{
Mat m;
vector_Point3f_to_Mat(vv_pt[i], m);
vm.push_back(m);
}
vector_Mat_to_Mat(vm, mat);
}
void vector_Vec4i_to_Mat(std::vector<Vec4i>& v_vec, Mat& mat)
{
mat = Mat(v_vec, true);
}
void vector_Vec4f_to_Mat(std::vector<Vec4f>& v_vec, Mat& mat)
{
mat = Mat(v_vec, true);
}
void vector_Vec6f_to_Mat(std::vector<Vec6f>& v_vec, Mat& mat)
{
mat = Mat(v_vec, true);
}
@@ -0,0 +1,66 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "opencv2/opencv_modules.hpp"
#include "opencv2/core.hpp"
void Mat_to_vector_int(cv::Mat& mat, std::vector<int>& v_int);
void vector_int_to_Mat(std::vector<int>& v_int, cv::Mat& mat);
void Mat_to_vector_double(cv::Mat& mat, std::vector<double>& v_double);
void vector_double_to_Mat(std::vector<double>& v_double, cv::Mat& mat);
void Mat_to_vector_float(cv::Mat& mat, std::vector<float>& v_float);
void vector_float_to_Mat(std::vector<float>& v_float, cv::Mat& mat);
void Mat_to_vector_uchar(cv::Mat& mat, std::vector<uchar>& v_uchar);
void vector_uchar_to_Mat(std::vector<uchar>& v_uchar, cv::Mat& mat);
void Mat_to_vector_char(cv::Mat& mat, std::vector<char>& v_char);
void vector_char_to_Mat(std::vector<char>& v_char, cv::Mat& mat);
void Mat_to_vector_Rect(cv::Mat& mat, std::vector<cv::Rect>& v_rect);
void vector_Rect_to_Mat(std::vector<cv::Rect>& v_rect, cv::Mat& mat);
void Mat_to_vector_Rect2d(cv::Mat& mat, std::vector<cv::Rect2d>& v_rect);
void vector_Rect2d_to_Mat(std::vector<cv::Rect2d>& v_rect, cv::Mat& mat);
void Mat_to_vector_RotatedRect(cv::Mat& mat, std::vector<cv::RotatedRect>& v_rect);
void vector_RotatedRect_to_Mat(std::vector<cv::RotatedRect>& v_rect, cv::Mat& mat);
void Mat_to_vector_Point(cv::Mat& mat, std::vector<cv::Point>& v_point);
void Mat_to_vector_Point2f(cv::Mat& mat, std::vector<cv::Point2f>& v_point);
void Mat_to_vector_Point2d(cv::Mat& mat, std::vector<cv::Point2d>& v_point);
void Mat_to_vector_Point3i(cv::Mat& mat, std::vector<cv::Point3i>& v_point);
void Mat_to_vector_Point3f(cv::Mat& mat, std::vector<cv::Point3f>& v_point);
void Mat_to_vector_Point3d(cv::Mat& mat, std::vector<cv::Point3d>& v_point);
void vector_Point_to_Mat(std::vector<cv::Point>& v_point, cv::Mat& mat);
void vector_Point2f_to_Mat(std::vector<cv::Point2f>& v_point, cv::Mat& mat);
void vector_Point2d_to_Mat(std::vector<cv::Point2d>& v_point, cv::Mat& mat);
void vector_Point3i_to_Mat(std::vector<cv::Point3i>& v_point, cv::Mat& mat);
void vector_Point3f_to_Mat(std::vector<cv::Point3f>& v_point, cv::Mat& mat);
void vector_Point3d_to_Mat(std::vector<cv::Point3d>& v_point, cv::Mat& mat);
void vector_Vec4i_to_Mat(std::vector<cv::Vec4i>& v_vec, cv::Mat& mat);
void vector_Vec4f_to_Mat(std::vector<cv::Vec4f>& v_vec, cv::Mat& mat);
void vector_Vec6f_to_Mat(std::vector<cv::Vec6f>& v_vec, cv::Mat& mat);
void Mat_to_vector_Mat(cv::Mat& mat, std::vector<cv::Mat>& v_mat);
void vector_Mat_to_Mat(std::vector<cv::Mat>& v_mat, cv::Mat& mat);
void Mat_to_vector_vector_Mat(cv::Mat& mat, std::vector< std::vector< cv::Mat > >& vv_mat);
void vector_vector_Mat_to_Mat(std::vector< std::vector< cv::Mat > >& vv_mat, cv::Mat& mat);
void Mat_to_vector_vector_char(cv::Mat& mat, std::vector< std::vector< char > >& vv_ch);
void vector_vector_char_to_Mat(std::vector< std::vector< char > >& vv_ch, cv::Mat& mat);
void Mat_to_vector_vector_Point(cv::Mat& mat, std::vector< std::vector< cv::Point > >& vv_pt);
void vector_vector_Point_to_Mat(std::vector< std::vector< cv::Point > >& vv_pt, cv::Mat& mat);
void Mat_to_vector_vector_Point2f(cv::Mat& mat, std::vector< std::vector< cv::Point2f > >& vv_pt);
void vector_vector_Point2f_to_Mat(std::vector< std::vector< cv::Point2f > >& vv_pt, cv::Mat& mat);
void Mat_to_vector_vector_Point3f(cv::Mat& mat, std::vector< std::vector< cv::Point3f > >& vv_pt);
void vector_vector_Point3f_to_Mat(std::vector< std::vector< cv::Point3f > >& vv_pt, cv::Mat& mat);
@@ -0,0 +1,42 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "common.h"
#include "opencv2/opencv_modules.hpp"
#ifdef HAVE_OPENCV_FEATURES2D
# include "opencv2/features2d.hpp"
#endif
#ifdef HAVE_OPENCV_VIDEO
# include "opencv2/video.hpp"
#endif
#ifdef HAVE_OPENCV_CONTRIB
# include "opencv2/contrib.hpp"
#endif
extern "C" {
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM* vm, void* )
{
JNIEnv* env;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK)
return -1;
/* get class with (*env)->FindClass */
/* register methods with (*env)->RegisterNatives */
return JNI_VERSION_1_6;
}
JNIEXPORT void JNICALL
JNI_OnUnload(JavaVM*, void*)
{
//do nothing
}
} // extern "C"
@@ -0,0 +1,110 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
// Author: abratchik
#define LOG_TAG "org.opencv.utils.Converters"
#include "common.h"
jobject vector_String_to_List(JNIEnv* env, std::vector<cv::String>& vs) {
static jclass juArrayList = ARRAYLIST(env);
static jmethodID m_create = CONSTRUCTOR(env, juArrayList);
jmethodID m_add = LIST_ADD(env, juArrayList);
jobject result = env->NewObject(juArrayList, m_create, vs.size());
for (std::vector<cv::String>::iterator it = vs.begin(); it != vs.end(); ++it) {
jstring element = env->NewStringUTF((*it).c_str());
env->CallBooleanMethod(result, m_add, element);
env->DeleteLocalRef(element);
}
return result;
}
std::vector<cv::String> List_to_vector_String(JNIEnv* env, jobject list)
{
static jclass juArrayList = ARRAYLIST(env);
jmethodID m_size = LIST_SIZE(env,juArrayList);
jmethodID m_get = LIST_GET(env, juArrayList);
jint len = env->CallIntMethod(list, m_size);
std::vector<cv::String> result;
result.reserve(len);
for (jint i=0; i<len; i++)
{
jstring element = static_cast<jstring>(env->CallObjectMethod(list, m_get, i));
const char* pchars = env->GetStringUTFChars(element, NULL);
result.push_back(pchars);
env->ReleaseStringUTFChars(element, pchars);
env->DeleteLocalRef(element);
}
return result;
}
void Copy_vector_String_to_List(JNIEnv* env, std::vector<cv::String>& vs, jobject list)
{
static jclass juArrayList = ARRAYLIST(env);
jmethodID m_clear = LIST_CLEAR(env, juArrayList);
jmethodID m_add = LIST_ADD(env, juArrayList);
env->CallVoidMethod(list, m_clear);
for (std::vector<cv::String>::iterator it = vs.begin(); it != vs.end(); ++it)
{
jstring element = env->NewStringUTF((*it).c_str());
env->CallBooleanMethod(list, m_add, element);
env->DeleteLocalRef(element);
}
}
jobject vector_string_to_List(JNIEnv* env, std::vector<std::string>& vs) {
static jclass juArrayList = ARRAYLIST(env);
static jmethodID m_create = CONSTRUCTOR(env, juArrayList);
jmethodID m_add = LIST_ADD(env, juArrayList);
jobject result = env->NewObject(juArrayList, m_create, vs.size());
for (std::vector<std::string>::iterator it = vs.begin(); it != vs.end(); ++it) {
jstring element = env->NewStringUTF((*it).c_str());
env->CallBooleanMethod(result, m_add, element);
env->DeleteLocalRef(element);
}
return result;
}
std::vector<std::string> List_to_vector_string(JNIEnv* env, jobject list)
{
static jclass juArrayList = ARRAYLIST(env);
jmethodID m_size = LIST_SIZE(env,juArrayList);
jmethodID m_get = LIST_GET(env, juArrayList);
jint len = env->CallIntMethod(list, m_size);
std::vector<std::string> result;
result.reserve(len);
for (jint i=0; i<len; i++)
{
jstring element = static_cast<jstring>(env->CallObjectMethod(list, m_get, i));
const char* pchars = env->GetStringUTFChars(element, NULL);
result.push_back(pchars);
env->ReleaseStringUTFChars(element, pchars);
env->DeleteLocalRef(element);
}
return result;
}
void Copy_vector_string_to_List(JNIEnv* env, std::vector<std::string>& vs, jobject list)
{
static jclass juArrayList = ARRAYLIST(env);
jmethodID m_clear = LIST_CLEAR(env, juArrayList);
jmethodID m_add = LIST_ADD(env, juArrayList);
env->CallVoidMethod(list, m_clear);
for (std::vector<std::string>::iterator it = vs.begin(); it != vs.end(); ++it)
{
jstring element = env->NewStringUTF((*it).c_str());
env->CallBooleanMethod(list, m_add, element);
env->DeleteLocalRef(element);
}
}
@@ -0,0 +1,26 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
// Author: abratchik
#ifndef LISTCONVERTERS_HPP
#define LISTCONVERTERS_HPP
#include "opencv2/opencv_modules.hpp"
#include "opencv2/core.hpp"
jobject vector_String_to_List(JNIEnv* env, std::vector<cv::String>& vs);
std::vector<cv::String> List_to_vector_String(JNIEnv* env, jobject list);
void Copy_vector_String_to_List(JNIEnv* env, std::vector<cv::String>& vs, jobject list);
jobject vector_string_to_List(JNIEnv* env, std::vector<std::string>& vs);
std::vector<std::string> List_to_vector_string(JNIEnv* env, jobject list);
void Copy_vector_string_to_List(JNIEnv* env, std::vector<std::string>& vs, jobject list);
#endif /* LISTCONVERTERS_HPP */
@@ -0,0 +1,8 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "common.h"
// Include all generated JNI code
#include "opencv_jni.hpp"
@@ -0,0 +1,38 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
// Author: abratchik
#undef LOGE
#undef LOGD
#ifdef __ANDROID__
# include <android/log.h>
# define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
# ifdef DEBUG
# define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
# else
# define LOGD(...)
# endif
#else
# define LOGE(...)
# define LOGD(...)
#endif
#ifndef OPENCV_JAVA_HPP
#define OPENCV_JAVA_HPP
#define MATOFINT(ENV) static_cast<jclass>(ENV->NewGlobalRef(ENV->FindClass("org/opencv/core/MatOfInt")))
#define GETNATIVEOBJ(ENV, CLS, MAT) ENV->GetLongField(MAT, ENV->GetFieldID(CLS, "nativeObj", "J"))
#define CONSTRUCTOR(ENV, CLS) ENV->GetMethodID(CLS, "<init>", "(I)V")
#define ARRAYLIST(ENV) static_cast<jclass>(ENV->NewGlobalRef(ENV->FindClass("java/util/ArrayList")))
#define LIST_ADD(ENV, LIST) ENV->GetMethodID(LIST, "add", "(Ljava/lang/Object;)Z")
#define LIST_GET(ENV, LIST) ENV->GetMethodID(LIST, "get", "(I)Ljava/lang/Object;")
#define LIST_SIZE(ENV, LIST) ENV->GetMethodID(LIST, "size", "()I")
#define LIST_CLEAR(ENV, LIST) ENV->GetMethodID(LIST, "clear", "()V")
#define CHECK_MAT(cond) if(!(cond)){ LOGD("FAILED: " #cond); return; }
#endif // OPENCV_JAVA_HPP
+165
View File
@@ -0,0 +1,165 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#ifdef __ANDROID__
#include <android/bitmap.h>
#define LOG_TAG "org.opencv.android.Utils"
#include "common.h"
using namespace cv;
extern "C" {
/*
* Class: org_opencv_android_Utils
* Method: void nBitmapToMat2(Bitmap b, long m_addr, boolean unPremultiplyAlpha)
*/
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat2
(JNIEnv * env, jclass, jobject bitmap, jlong m_addr, jboolean needUnPremultiplyAlpha);
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat2
(JNIEnv * env, jclass, jobject bitmap, jlong m_addr, jboolean needUnPremultiplyAlpha)
{
AndroidBitmapInfo info;
void* pixels = 0;
Mat& dst = *((Mat*)m_addr);
try {
LOGD("nBitmapToMat");
CV_Assert( AndroidBitmap_getInfo(env, bitmap, &info) >= 0 );
CV_Assert( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
info.format == ANDROID_BITMAP_FORMAT_RGB_565 );
CV_Assert( AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0 );
CV_Assert( pixels );
dst.create(info.height, info.width, CV_8UC4);
if( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 )
{
LOGD("nBitmapToMat: RGBA_8888 -> CV_8UC4");
Mat tmp(info.height, info.width, CV_8UC4, pixels);
if(needUnPremultiplyAlpha) cvtColor(tmp, dst, COLOR_mRGBA2RGBA);
else tmp.copyTo(dst);
} else {
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
LOGD("nBitmapToMat: RGB_565 -> CV_8UC4");
Mat tmp(info.height, info.width, CV_8UC2, pixels);
cvtColor(tmp, dst, COLOR_BGR5652RGBA);
}
AndroidBitmap_unlockPixels(env, bitmap);
return;
} catch(const cv::Exception& e) {
AndroidBitmap_unlockPixels(env, bitmap);
LOGE("nBitmapToMat caught cv::Exception: %s", e.what());
jclass je = env->FindClass("org/opencv/core/CvException");
if(!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
return;
} catch (...) {
AndroidBitmap_unlockPixels(env, bitmap);
LOGE("nBitmapToMat caught unknown exception (...)");
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {nBitmapToMat}");
return;
}
}
// old signature is left for binary compatibility with 2.4.0 & 2.4.1, to removed in 2.5
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat
(JNIEnv * env, jclass, jobject bitmap, jlong m_addr);
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat
(JNIEnv * env, jclass, jobject bitmap, jlong m_addr)
{
Java_org_opencv_android_Utils_nBitmapToMat2(env, 0, bitmap, m_addr, false);
}
/*
* Class: org_opencv_android_Utils
* Method: void nMatToBitmap2(long m_addr, Bitmap b, boolean premultiplyAlpha)
*/
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap2
(JNIEnv * env, jclass, jlong m_addr, jobject bitmap, jboolean needPremultiplyAlpha);
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap2
(JNIEnv * env, jclass, jlong m_addr, jobject bitmap, jboolean needPremultiplyAlpha)
{
AndroidBitmapInfo info;
void* pixels = 0;
Mat& src = *((Mat*)m_addr);
try {
LOGD("nMatToBitmap");
CV_Assert( AndroidBitmap_getInfo(env, bitmap, &info) >= 0 );
CV_Assert( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
info.format == ANDROID_BITMAP_FORMAT_RGB_565 );
CV_Assert( src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols );
CV_Assert( src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4 );
CV_Assert( AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0 );
CV_Assert( pixels );
if( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 )
{
Mat tmp(info.height, info.width, CV_8UC4, pixels);
if(src.type() == CV_8UC1)
{
LOGD("nMatToBitmap: CV_8UC1 -> RGBA_8888");
cvtColor(src, tmp, COLOR_GRAY2RGBA);
} else if(src.type() == CV_8UC3){
LOGD("nMatToBitmap: CV_8UC3 -> RGBA_8888");
cvtColor(src, tmp, COLOR_RGB2RGBA);
} else if(src.type() == CV_8UC4){
LOGD("nMatToBitmap: CV_8UC4 -> RGBA_8888");
if(needPremultiplyAlpha) cvtColor(src, tmp, COLOR_RGBA2mRGBA);
else src.copyTo(tmp);
}
} else {
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
Mat tmp(info.height, info.width, CV_8UC2, pixels);
if(src.type() == CV_8UC1)
{
LOGD("nMatToBitmap: CV_8UC1 -> RGB_565");
cvtColor(src, tmp, COLOR_GRAY2BGR565);
} else if(src.type() == CV_8UC3){
LOGD("nMatToBitmap: CV_8UC3 -> RGB_565");
cvtColor(src, tmp, COLOR_RGB2BGR565);
} else if(src.type() == CV_8UC4){
LOGD("nMatToBitmap: CV_8UC4 -> RGB_565");
cvtColor(src, tmp, COLOR_RGBA2BGR565);
}
}
AndroidBitmap_unlockPixels(env, bitmap);
return;
} catch(const cv::Exception& e) {
AndroidBitmap_unlockPixels(env, bitmap);
LOGE("nMatToBitmap caught cv::Exception: %s", e.what());
jclass je = env->FindClass("org/opencv/core/CvException");
if(!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
return;
} catch (...) {
AndroidBitmap_unlockPixels(env, bitmap);
LOGE("nMatToBitmap caught unknown exception (...)");
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}");
return;
}
}
// old signature is left for binary compatibility with 2.4.0 & 2.4.1, to removed in 2.5
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap
(JNIEnv * env, jclass, jlong m_addr, jobject bitmap);
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap
(JNIEnv * env, jclass, jlong m_addr, jobject bitmap)
{
Java_org_opencv_android_Utils_nMatToBitmap2(env, 0, m_addr, bitmap, false);
}
} // extern "C"
#endif //__ANDROID__
@@ -0,0 +1,8 @@
package org.opencv.osgi;
/**
* Dummy interface to allow some integration testing within OSGi implementation.
*/
public interface OpenCVInterface
{
}
@@ -0,0 +1,18 @@
package org.opencv.osgi;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class is intended to provide a convenient way to load OpenCV's native
* library from the Java bundle. If Blueprint is enabled in the OSGi container
* this class will be instantiated automatically and the init() method called
* loading the native library.
*/
public class OpenCVNativeLoader implements OpenCVInterface {
public void init() {
System.loadLibrary("opencv_java@OPENCV_JAVA_LIB_NAME_SUFFIX@");
Logger.getLogger("org.opencv.osgi").log(Level.INFO, "Successfully loaded OpenCV native library.");
}
}
@@ -0,0 +1,913 @@
package org.opencv.utils;
import java.util.ArrayList;
import java.util.List;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfDMatch;
import org.opencv.core.MatOfInt;
import org.opencv.core.MatOfKeyPoint;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.MatOfPoint3f;
import org.opencv.core.Point;
import org.opencv.core.Point3;
import org.opencv.core.Size;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.Rect2d;
import org.opencv.core.DMatch;
import org.opencv.core.KeyPoint;
public class Converters {
public static Mat vector_Point_to_Mat(List<Point> pts) {
return vector_Point_to_Mat(pts, CvType.CV_32S);
}
public static Mat vector_Point2f_to_Mat(List<Point> pts) {
return vector_Point_to_Mat(pts, CvType.CV_32F);
}
public static Mat vector_Point2d_to_Mat(List<Point> pts) {
return vector_Point_to_Mat(pts, CvType.CV_64F);
}
public static Mat vector_Point_to_Mat(List<Point> pts, int typeDepth) {
Mat res;
int count = (pts != null) ? pts.size() : 0;
if (count > 0) {
switch (typeDepth) {
case CvType.CV_32S: {
res = new Mat(count, 1, CvType.CV_32SC2);
int[] buff = new int[count * 2];
for (int i = 0; i < count; i++) {
Point p = pts.get(i);
buff[i * 2] = (int) p.x;
buff[i * 2 + 1] = (int) p.y;
}
res.put(0, 0, buff);
}
break;
case CvType.CV_32F: {
res = new Mat(count, 1, CvType.CV_32FC2);
float[] buff = new float[count * 2];
for (int i = 0; i < count; i++) {
Point p = pts.get(i);
buff[i * 2] = (float) p.x;
buff[i * 2 + 1] = (float) p.y;
}
res.put(0, 0, buff);
}
break;
case CvType.CV_64F: {
res = new Mat(count, 1, CvType.CV_64FC2);
double[] buff = new double[count * 2];
for (int i = 0; i < count; i++) {
Point p = pts.get(i);
buff[i * 2] = p.x;
buff[i * 2 + 1] = p.y;
}
res.put(0, 0, buff);
}
break;
default:
throw new IllegalArgumentException("'typeDepth' can be CV_32S, CV_32F or CV_64F");
}
} else {
res = new Mat();
}
return res;
}
public static Mat vector_Point3i_to_Mat(List<Point3> pts) {
return vector_Point3_to_Mat(pts, CvType.CV_32S);
}
public static Mat vector_Point3f_to_Mat(List<Point3> pts) {
return vector_Point3_to_Mat(pts, CvType.CV_32F);
}
public static Mat vector_Point3d_to_Mat(List<Point3> pts) {
return vector_Point3_to_Mat(pts, CvType.CV_64F);
}
public static Mat vector_Point3_to_Mat(List<Point3> pts, int typeDepth) {
Mat res;
int count = (pts != null) ? pts.size() : 0;
if (count > 0) {
switch (typeDepth) {
case CvType.CV_32S: {
res = new Mat(count, 1, CvType.CV_32SC3);
int[] buff = new int[count * 3];
for (int i = 0; i < count; i++) {
Point3 p = pts.get(i);
buff[i * 3] = (int) p.x;
buff[i * 3 + 1] = (int) p.y;
buff[i * 3 + 2] = (int) p.z;
}
res.put(0, 0, buff);
}
break;
case CvType.CV_32F: {
res = new Mat(count, 1, CvType.CV_32FC3);
float[] buff = new float[count * 3];
for (int i = 0; i < count; i++) {
Point3 p = pts.get(i);
buff[i * 3] = (float) p.x;
buff[i * 3 + 1] = (float) p.y;
buff[i * 3 + 2] = (float) p.z;
}
res.put(0, 0, buff);
}
break;
case CvType.CV_64F: {
res = new Mat(count, 1, CvType.CV_64FC3);
double[] buff = new double[count * 3];
for (int i = 0; i < count; i++) {
Point3 p = pts.get(i);
buff[i * 3] = p.x;
buff[i * 3 + 1] = p.y;
buff[i * 3 + 2] = p.z;
}
res.put(0, 0, buff);
}
break;
default:
throw new IllegalArgumentException("'typeDepth' can be CV_32S, CV_32F or CV_64F");
}
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_Point2f(Mat m, List<Point> pts) {
Mat_to_vector_Point(m, pts);
}
public static void Mat_to_vector_Point2d(Mat m, List<Point> pts) {
Mat_to_vector_Point(m, pts);
}
public static void Mat_to_vector_Point(Mat m, List<Point> pts) {
if (pts == null)
throw new IllegalArgumentException("Output List can't be null");
int count = m.rows();
int type = m.type();
if (m.cols() != 1)
throw new IllegalArgumentException("Input Mat should have one column\n" + m);
pts.clear();
if (type == CvType.CV_32SC2) {
int[] buff = new int[2 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
pts.add(new Point(buff[i * 2], buff[i * 2 + 1]));
}
} else if (type == CvType.CV_32FC2) {
float[] buff = new float[2 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
pts.add(new Point(buff[i * 2], buff[i * 2 + 1]));
}
} else if (type == CvType.CV_64FC2) {
double[] buff = new double[2 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
pts.add(new Point(buff[i * 2], buff[i * 2 + 1]));
}
} else {
throw new IllegalArgumentException(
"Input Mat should be of CV_32SC2, CV_32FC2 or CV_64FC2 type\n" + m);
}
}
public static void Mat_to_vector_Point3i(Mat m, List<Point3> pts) {
Mat_to_vector_Point3(m, pts);
}
public static void Mat_to_vector_Point3f(Mat m, List<Point3> pts) {
Mat_to_vector_Point3(m, pts);
}
public static void Mat_to_vector_Point3d(Mat m, List<Point3> pts) {
Mat_to_vector_Point3(m, pts);
}
public static void Mat_to_vector_Point3(Mat m, List<Point3> pts) {
if (pts == null)
throw new IllegalArgumentException("Output List can't be null");
int count = m.rows();
int type = m.type();
if (m.cols() != 1)
throw new IllegalArgumentException("Input Mat should have one column\n" + m);
pts.clear();
if (type == CvType.CV_32SC3) {
int[] buff = new int[3 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
pts.add(new Point3(buff[i * 3], buff[i * 3 + 1], buff[i * 3 + 2]));
}
} else if (type == CvType.CV_32FC3) {
float[] buff = new float[3 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
pts.add(new Point3(buff[i * 3], buff[i * 3 + 1], buff[i * 3 + 2]));
}
} else if (type == CvType.CV_64FC3) {
double[] buff = new double[3 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
pts.add(new Point3(buff[i * 3], buff[i * 3 + 1], buff[i * 3 + 2]));
}
} else {
throw new IllegalArgumentException(
"Input Mat should be of CV_32SC3, CV_32FC3 or CV_64FC3 type\n" + m);
}
}
public static Mat vector_Mat_to_Mat(List<Mat> mats) {
Mat res;
int count = (mats != null) ? mats.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_32SC2);
int[] buff = new int[count * 2];
for (int i = 0; i < count; i++) {
long addr = mats.get(i).nativeObj;
buff[i * 2] = (int) (addr >> 32);
buff[i * 2 + 1] = (int) (addr & 0xffffffff);
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_Mat(Mat m, List<Mat> mats) {
if (mats == null)
throw new IllegalArgumentException("mats == null");
int count = m.rows();
if (CvType.CV_32SC2 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_32SC2 != m.type() || m.cols()!=1\n" + m);
mats.clear();
int[] buff = new int[count * 2];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
long addr = (((long) buff[i * 2]) << 32) | (((long) buff[i * 2 + 1]) & 0xffffffffL);
mats.add(new Mat(addr));
}
}
public static Mat vector_float_to_Mat(List<Float> fs) {
Mat res;
int count = (fs != null) ? fs.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_32FC1);
float[] buff = new float[count];
for (int i = 0; i < count; i++) {
float f = fs.get(i);
buff[i] = f;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_float(Mat m, List<Float> fs) {
if (fs == null)
throw new IllegalArgumentException("fs == null");
int count = m.rows();
if (CvType.CV_32FC1 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_32FC1 != m.type() || m.cols()!=1\n" + m);
fs.clear();
float[] buff = new float[count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
fs.add(buff[i]);
}
}
public static Mat vector_uchar_to_Mat(List<Byte> bs) {
Mat res;
int count = (bs != null) ? bs.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_8UC1);
byte[] buff = new byte[count];
for (int i = 0; i < count; i++) {
byte b = bs.get(i);
buff[i] = b;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_uchar(Mat m, List<Byte> us) {
if (us == null)
throw new IllegalArgumentException("Output List can't be null");
int count = m.rows();
if (CvType.CV_8UC1 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_8UC1 != m.type() || m.cols()!=1\n" + m);
us.clear();
byte[] buff = new byte[count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
us.add(buff[i]);
}
}
public static Mat vector_char_to_Mat(List<Byte> bs) {
Mat res;
int count = (bs != null) ? bs.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_8SC1);
byte[] buff = new byte[count];
for (int i = 0; i < count; i++) {
byte b = bs.get(i);
buff[i] = b;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static Mat vector_int_to_Mat(List<Integer> is) {
Mat res;
int count = (is != null) ? is.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_32SC1);
int[] buff = new int[count];
for (int i = 0; i < count; i++) {
int v = is.get(i);
buff[i] = v;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_int(Mat m, List<Integer> is) {
if (is == null)
throw new IllegalArgumentException("is == null");
int count = m.rows();
if (CvType.CV_32SC1 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_32SC1 != m.type() || m.cols()!=1\n" + m);
is.clear();
int[] buff = new int[count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
is.add(buff[i]);
}
}
public static void Mat_to_vector_char(Mat m, List<Byte> bs) {
if (bs == null)
throw new IllegalArgumentException("Output List can't be null");
int count = m.rows();
if (CvType.CV_8SC1 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_8SC1 != m.type() || m.cols()!=1\n" + m);
bs.clear();
byte[] buff = new byte[count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
bs.add(buff[i]);
}
}
public static Mat vector_Rect_to_Mat(List<Rect> rs) {
Mat res;
int count = (rs != null) ? rs.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_32SC4);
int[] buff = new int[4 * count];
for (int i = 0; i < count; i++) {
Rect r = rs.get(i);
buff[4 * i] = r.x;
buff[4 * i + 1] = r.y;
buff[4 * i + 2] = r.width;
buff[4 * i + 3] = r.height;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_Rect(Mat m, List<Rect> rs) {
if (rs == null)
throw new IllegalArgumentException("rs == null");
int count = m.rows();
if (CvType.CV_32SC4 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_32SC4 != m.type() || m.rows()!=1\n" + m);
rs.clear();
int[] buff = new int[4 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
rs.add(new Rect(buff[4 * i], buff[4 * i + 1], buff[4 * i + 2], buff[4 * i + 3]));
}
}
public static Mat vector_Rect2d_to_Mat(List<Rect2d> rs) {
Mat res;
int count = (rs != null) ? rs.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_64FC4);
double[] buff = new double[4 * count];
for (int i = 0; i < count; i++) {
Rect2d r = rs.get(i);
buff[4 * i] = r.x;
buff[4 * i + 1] = r.y;
buff[4 * i + 2] = r.width;
buff[4 * i + 3] = r.height;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_Rect2d(Mat m, List<Rect2d> rs) {
if (rs == null)
throw new IllegalArgumentException("rs == null");
int count = m.rows();
if (CvType.CV_64FC4 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_64FC4 != m.type() || m.rows()!=1\n" + m);
rs.clear();
double[] buff = new double[4 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
rs.add(new Rect2d(buff[4 * i], buff[4 * i + 1], buff[4 * i + 2], buff[4 * i + 3]));
}
}
public static Mat vector_KeyPoint_to_Mat(List<KeyPoint> kps) {
Mat res;
int count = (kps != null) ? kps.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_64FC(7));
double[] buff = new double[count * 7];
for (int i = 0; i < count; i++) {
KeyPoint kp = kps.get(i);
buff[7 * i] = kp.pt.x;
buff[7 * i + 1] = kp.pt.y;
buff[7 * i + 2] = kp.size;
buff[7 * i + 3] = kp.angle;
buff[7 * i + 4] = kp.response;
buff[7 * i + 5] = kp.octave;
buff[7 * i + 6] = kp.class_id;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_KeyPoint(Mat m, List<KeyPoint> kps) {
if (kps == null)
throw new IllegalArgumentException("Output List can't be null");
int count = m.rows();
if (CvType.CV_64FC(7) != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_64FC(7) != m.type() || m.cols()!=1\n" + m);
kps.clear();
double[] buff = new double[7 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
kps.add(new KeyPoint((float) buff[7 * i], (float) buff[7 * i + 1], (float) buff[7 * i + 2], (float) buff[7 * i + 3],
(float) buff[7 * i + 4], (int) buff[7 * i + 5], (int) buff[7 * i + 6]));
}
}
// vector_vector_Mat
public static Mat vector_vector_Mat_to_Mat(List<List<Mat>> vecMats, List<Mat> mats) {
Mat res;
int lCount = (vecMats != null) ? vecMats.size() : 0;
if (lCount > 0) {
for (List<Mat> matList : vecMats) {
Mat mat = vector_Mat_to_Mat(matList);
mats.add(mat);
}
res = vector_Mat_to_Mat(mats);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_vector_Mat(Mat m, List<List<Mat>> vecMats) {
if (vecMats == null)
throw new IllegalArgumentException("Output List can't be null");
if (m == null)
throw new IllegalArgumentException("Input Mat can't be null");
vecMats.clear();
List<Mat> mats = new ArrayList<Mat>(m.rows());
Mat_to_vector_Mat(m, mats);
for (Mat mi : mats) {
List<Mat> rowList = new ArrayList<Mat>(mi.rows());
Mat_to_vector_Mat(mi, rowList);
vecMats.add(rowList);
mi.release();
}
mats.clear();
}
// vector_vector_Point
public static Mat vector_vector_Point_to_Mat(List<MatOfPoint> pts, List<Mat> mats) {
Mat res;
int lCount = (pts != null) ? pts.size() : 0;
if (lCount > 0) {
mats.addAll(pts);
res = vector_Mat_to_Mat(mats);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_vector_Point(Mat m, List<MatOfPoint> pts) {
if (pts == null)
throw new IllegalArgumentException("Output List can't be null");
if (m == null)
throw new IllegalArgumentException("Input Mat can't be null");
List<Mat> mats = new ArrayList<Mat>(m.rows());
Mat_to_vector_Mat(m, mats);
for (Mat mi : mats) {
MatOfPoint pt = new MatOfPoint(mi);
pts.add(pt);
mi.release();
}
mats.clear();
}
// vector_vector_Point2f
public static void Mat_to_vector_vector_Point2f(Mat m, List<MatOfPoint2f> pts) {
if (pts == null)
throw new IllegalArgumentException("Output List can't be null");
if (m == null)
throw new IllegalArgumentException("Input Mat can't be null");
List<Mat> mats = new ArrayList<Mat>(m.rows());
Mat_to_vector_Mat(m, mats);
for (Mat mi : mats) {
MatOfPoint2f pt = new MatOfPoint2f(mi);
pts.add(pt);
mi.release();
}
mats.clear();
}
// vector_vector_Point2f
public static Mat vector_vector_Point2f_to_Mat(List<MatOfPoint2f> pts, List<Mat> mats) {
Mat res;
int lCount = (pts != null) ? pts.size() : 0;
if (lCount > 0) {
mats.addAll(pts);
res = vector_Mat_to_Mat(mats);
} else {
res = new Mat();
}
return res;
}
// vector_vector_Point3f
public static void Mat_to_vector_vector_Point3f(Mat m, List<MatOfPoint3f> pts) {
if (pts == null)
throw new IllegalArgumentException("Output List can't be null");
if (m == null)
throw new IllegalArgumentException("Input Mat can't be null");
List<Mat> mats = new ArrayList<Mat>(m.rows());
Mat_to_vector_Mat(m, mats);
for (Mat mi : mats) {
MatOfPoint3f pt = new MatOfPoint3f(mi);
pts.add(pt);
mi.release();
}
mats.clear();
}
// vector_vector_Point3f
public static Mat vector_vector_Point3f_to_Mat(List<MatOfPoint3f> pts, List<Mat> mats) {
Mat res;
int lCount = (pts != null) ? pts.size() : 0;
if (lCount > 0) {
mats.addAll(pts);
res = vector_Mat_to_Mat(mats);
} else {
res = new Mat();
}
return res;
}
// vector_vector_KeyPoint
public static Mat vector_vector_KeyPoint_to_Mat(List<MatOfKeyPoint> kps, List<Mat> mats) {
Mat res;
int lCount = (kps != null) ? kps.size() : 0;
if (lCount > 0) {
mats.addAll(kps);
res = vector_Mat_to_Mat(mats);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_vector_KeyPoint(Mat m, List<MatOfKeyPoint> kps) {
if (kps == null)
throw new IllegalArgumentException("Output List can't be null");
if (m == null)
throw new IllegalArgumentException("Input Mat can't be null");
List<Mat> mats = new ArrayList<Mat>(m.rows());
Mat_to_vector_Mat(m, mats);
for (Mat mi : mats) {
MatOfKeyPoint vkp = new MatOfKeyPoint(mi);
kps.add(vkp);
mi.release();
}
mats.clear();
}
public static Mat vector_double_to_Mat(List<Double> ds) {
Mat res;
int count = (ds != null) ? ds.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_64FC1);
double[] buff = new double[count];
for (int i = 0; i < count; i++) {
double v = ds.get(i);
buff[i] = v;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_double(Mat m, List<Double> ds) {
if (ds == null)
throw new IllegalArgumentException("ds == null");
int count = m.rows();
if (CvType.CV_64FC1 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_64FC1 != m.type() || m.cols()!=1\n" + m);
ds.clear();
double[] buff = new double[count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
ds.add(buff[i]);
}
}
public static Mat vector_DMatch_to_Mat(List<DMatch> matches) {
Mat res;
int count = (matches != null) ? matches.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_64FC4);
double[] buff = new double[count * 4];
for (int i = 0; i < count; i++) {
DMatch m = matches.get(i);
buff[4 * i] = m.queryIdx;
buff[4 * i + 1] = m.trainIdx;
buff[4 * i + 2] = m.imgIdx;
buff[4 * i + 3] = m.distance;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_DMatch(Mat m, List<DMatch> matches) {
if (matches == null)
throw new IllegalArgumentException("Output List can't be null");
int count = m.rows();
if (CvType.CV_64FC4 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_64FC4 != m.type() || m.cols()!=1\n" + m);
matches.clear();
double[] buff = new double[4 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
matches.add(new DMatch((int) buff[4 * i], (int) buff[4 * i + 1], (int) buff[4 * i + 2], (float) buff[4 * i + 3]));
}
}
// vector_vector_DMatch
public static Mat vector_vector_DMatch_to_Mat(List<MatOfDMatch> lvdm, List<Mat> mats) {
Mat res;
int lCount = (lvdm != null) ? lvdm.size() : 0;
if (lCount > 0) {
mats.addAll(lvdm);
res = vector_Mat_to_Mat(mats);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_vector_DMatch(Mat m, List<MatOfDMatch> lvdm) {
if (lvdm == null)
throw new IllegalArgumentException("Output List can't be null");
if (m == null)
throw new IllegalArgumentException("Input Mat can't be null");
List<Mat> mats = new ArrayList<Mat>(m.rows());
Mat_to_vector_Mat(m, mats);
lvdm.clear();
for (Mat mi : mats) {
MatOfDMatch vdm = new MatOfDMatch(mi);
lvdm.add(vdm);
mi.release();
}
mats.clear();
}
// vector_vector_char
public static Mat vector_vector_char_to_Mat(List<MatOfByte> lvb, List<Mat> mats) {
Mat res;
int lCount = (lvb != null) ? lvb.size() : 0;
if (lCount > 0) {
mats.addAll(lvb);
res = vector_Mat_to_Mat(mats);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_vector_char(Mat m, List<List<Byte>> llb) {
if (llb == null)
throw new IllegalArgumentException("Output List can't be null");
if (m == null)
throw new IllegalArgumentException("Input Mat can't be null");
List<Mat> mats = new ArrayList<Mat>(m.rows());
Mat_to_vector_Mat(m, mats);
for (Mat mi : mats) {
List<Byte> lb = new ArrayList<Byte>();
Mat_to_vector_char(mi, lb);
llb.add(lb);
mi.release();
}
mats.clear();
}
public static Mat vector_RotatedRect_to_Mat(List<RotatedRect> rs) {
Mat res;
int count = (rs != null) ? rs.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_32FC(5));
float[] buff = new float[5 * count];
for (int i = 0; i < count; i++) {
RotatedRect r = rs.get(i);
buff[5 * i] = (float)r.center.x;
buff[5 * i + 1] = (float)r.center.y;
buff[5 * i + 2] = (float)r.size.width;
buff[5 * i + 3] = (float)r.size.height;
buff[5 * i + 4] = (float)r.angle;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_RotatedRect(Mat m, List<RotatedRect> rs) {
if (rs == null)
throw new IllegalArgumentException("rs == null");
int count = m.rows();
if (CvType.CV_32FC(5) != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_32FC5 != m.type() || m.rows()!=1\n" + m);
rs.clear();
float[] buff = new float[5 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
rs.add(new RotatedRect(new Point(buff[5 * i], buff[5 * i + 1]), new Size(buff[5 * i + 2], buff[5 * i + 3]), buff[5 * i + 4]));
}
}
// vector_MatShape
public static Mat vector_MatShape_to_Mat(List<MatOfInt> matOfInts) {
Mat res;
int count = (matOfInts != null) ? matOfInts.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_32SC2);
int[] buff = new int[count * 2];
for (int i = 0; i < count; i++) {
long addr = matOfInts.get(i).nativeObj;
buff[i * 2] = (int) (addr >> 32);
buff[i * 2 + 1] = (int) (addr & 0xffffffff);
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_MatShape(Mat m, List<MatOfInt> matOfInts) {
if (matOfInts == null)
throw new IllegalArgumentException("matOfInts == null");
int count = m.rows();
if (CvType.CV_32SC2 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_32SC2 != m.type() || m.cols()!=1\n" + m);
matOfInts.clear();
int[] buff = new int[count * 2];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
long addr = (((long) buff[i * 2]) << 32) | (((long) buff[i * 2 + 1]) & 0xffffffffL);
matOfInts.add(MatOfInt.fromNativeAddr(addr));
}
}
// vector_vector_MatShape
public static Mat vector_vector_MatShape_to_Mat(List<List<MatOfInt>> vecMatOfInts, List<Mat> mats) {
Mat res;
int lCount = (vecMatOfInts != null) ? vecMatOfInts.size() : 0;
if (lCount > 0) {
for (List<MatOfInt> matList : vecMatOfInts) {
Mat mat = vector_MatShape_to_Mat(matList);
mats.add(mat);
}
res = vector_Mat_to_Mat(mats);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_vector_MatShape(Mat m, List<List<MatOfInt>> vecMatOfInts) {
if (vecMatOfInts == null)
throw new IllegalArgumentException("Output List can't be null");
if (m == null)
throw new IllegalArgumentException("Input Mat can't be null");
vecMatOfInts.clear();
List<Mat> mats = new ArrayList<Mat>(m.rows());
Mat_to_vector_Mat(m, mats);
for (Mat mi : mats) {
List<MatOfInt> rowList = new ArrayList<MatOfInt>(mi.rows());
Mat_to_vector_MatShape(mi, rowList);
vecMatOfInts.add(rowList);
mi.release();
}
mats.clear();
}
}
@@ -0,0 +1,23 @@
package org.opencv.core;
import java.lang.ref.Cleaner;
public abstract class CleanableMat {
// A native memory cleaner for the OpenCV library
public static Cleaner cleaner = Cleaner.create();
protected CleanableMat(long obj) {
if (obj == 0)
throw new UnsupportedOperationException("Native object address is NULL");
nativeObj = obj;
// The n_delete action must not refer to the object being registered. So, do not use nativeObj directly.
long nativeObjCopy = nativeObj;
cleaner.register(this, () -> n_delete(nativeObjCopy));
}
private static native void n_delete(long nativeObj);
public final long nativeObj;
}
@@ -0,0 +1,21 @@
package org.opencv.core;
public abstract class CleanableMat {
protected CleanableMat(long obj) {
if (obj == 0)
throw new UnsupportedOperationException("Native object address is NULL");
nativeObj = obj;
}
@Override
protected void finalize() throws Throwable {
n_delete(nativeObj);
super.finalize();
}
private static native void n_delete(long nativeObj);
public final long nativeObj;
}
@@ -0,0 +1,52 @@
//
// This file is auto-generated. Please don't modify it!
//
#undef LOG_TAG
#include "opencv2/opencv_modules.hpp"
#ifdef HAVE_OPENCV_$M
#include <string>
#include "opencv2/$m.hpp"
$includes
#define LOG_TAG "org.opencv.$m"
#include "common.h"
using namespace cv;
/// throw java exception
#undef throwJavaException
#define throwJavaException throwJavaException_$m
static void throwJavaException(JNIEnv *env, const std::exception *e, const char *method) {
std::string what = "unknown exception";
jclass je = 0;
if(e) {
std::string exception_type = "std::exception";
if(dynamic_cast<const cv::Exception*>(e)) {
exception_type = "cv::Exception";
je = env->FindClass("org/opencv/core/CvException");
}
what = exception_type + ": " + e->what();
}
if(!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, what.c_str());
LOGE("%s caught %s", method, what.c_str());
(void)method; // avoid "unused" warning
}
extern "C" {
$code
} // extern "C"
#endif // HAVE_OPENCV_$M
@@ -0,0 +1,20 @@
//
// This file is auto-generated. Please don't modify it!
//
package org.opencv.$module;
$imports
$docs$annotation
public class $jname {
protected final long nativeObj;
protected $jname(long addr) {
nativeObj = addr;
$jcleaner
}
public long getNativeObjAddr() { return nativeObj; }
// internal usage only
public static $jname __fromPtr__(long addr) { return new $jname(addr); }
@@ -0,0 +1,14 @@
//
// This file is auto-generated. Please don't modify it!
//
package org.opencv.$module;
$imports
$docs$annotation
public class $jname extends $base {
protected $jname(long addr) { super(addr); }
// internal usage only
public static $jname __fromPtr__(long addr) { return new $jname(addr); }
@@ -0,0 +1,9 @@
//
// This file is auto-generated. Please don't modify it!
//
package org.opencv.$module;
$imports
$docs$annotation
public class $jname {
+137
View File
@@ -0,0 +1,137 @@
project(${the_module}_jar)
set(OPENCV_JAVA_DIR "${CMAKE_CURRENT_BINARY_DIR}/opencv" CACHE INTERNAL "")
file(REMOVE_RECURSE "${OPENCV_JAVA_DIR}")
file(REMOVE "${OPENCV_DEPHELPER}/${the_module}_jar_source_copy")
set(java_src_dir "${OPENCV_JAVA_DIR}/java")
file(MAKE_DIRECTORY "${java_src_dir}")
set(JAR_NAME_WE opencv-${OPENCV_JAVA_LIB_NAME_SUFFIX})
set(JAR_NAME ${JAR_NAME_WE}.jar)
set(OPENCV_JAR_DIR "${OpenCV_BINARY_DIR}/bin/" CACHE INTERNAL "")
set(OPENCV_JAR_FILE "${OPENCV_JAR_DIR}${JAR_NAME}" CACHE INTERNAL "")
ocv_copyfiles_append_dir(JAVA_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/java" "${java_src_dir}")
set(depends gen_opencv_java_source "${OPENCV_DEPHELPER}/gen_opencv_java_source")
ocv_copyfiles_add_target(${the_module}_jar_source_copy JAVA_SRC_COPY "Copy Java(JAR) source files" ${depends})
set(depends ${the_module}_jar_source_copy "${OPENCV_DEPHELPER}/${the_module}_jar_source_copy")
if(OPENCV_JAVA_SOURCE_VERSION)
set(OPENCV_ANT_JAVAC_EXTRA_ATTRS "${OPENCV_ANT_JAVAC_EXTRA_ATTRS} source=\"${OPENCV_JAVA_SOURCE_VERSION}\"")
endif()
if(OPENCV_JAVA_TARGET_VERSION)
set(OPENCV_ANT_JAVAC_EXTRA_ATTRS "${OPENCV_ANT_JAVAC_EXTRA_ATTRS} target=\"${OPENCV_JAVA_TARGET_VERSION}\"")
endif()
set(OPENCV_JAVADOC_DESTINATION "${OpenCV_BINARY_DIR}/doc/doxygen/html/javadoc" CACHE STRING "")
# Old Javadoc URL looks like this: https://docs.oracle.com/javase/6/docs/api/
# New Javadoc URL looks like this: https://docs.oracle.com/en/java/javase/11/docs/api/
set(OPENCV_JAVADOC_LINK_URL "" CACHE STRING "See details in modules/java/jar/CMakeLists.txt")
if(OPENCV_JAVADOC_LINK_URL)
set(CMAKE_CONFIG_OPENCV_JAVADOC_LINK "link=\"${OPENCV_JAVADOC_LINK_URL}\"")
endif()
if(OPENCV_JAVA_SDK_BUILD_TYPE STREQUAL "ANT")
file(MAKE_DIRECTORY "${OPENCV_JAVA_DIR}/build/classes")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.xml.in" "${OPENCV_JAVA_DIR}/build.xml" @ONLY)
list(APPEND depends "${OPENCV_JAVA_DIR}/build.xml")
ocv_cmake_byproducts(__byproducts BYPRODUCTS "${OPENCV_JAR_FILE}")
add_custom_command(OUTPUT "${OPENCV_DEPHELPER}/${the_module}_jar"
${__byproducts} # required for add_custom_target() by ninja
COMMAND ${ANT_EXECUTABLE} -noinput -k jar
COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/${the_module}_jar"
WORKING_DIRECTORY "${OPENCV_JAVA_DIR}"
DEPENDS ${depends}
COMMENT "Generating ${JAR_NAME}"
)
add_custom_target(${the_module}_jar DEPENDS "${OPENCV_DEPHELPER}/${the_module}_jar")
elseif(OPENCV_JAVA_SDK_BUILD_TYPE STREQUAL "JAVA")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/MANIFEST.MF.in" "${OPENCV_JAVA_DIR}/MANIFEST.MF" @ONLY)
list(APPEND depends "${OPENCV_JAVA_DIR}/MANIFEST.MF")
ocv_cmake_byproducts(__byproducts BYPRODUCTS "${OPENCV_JAVA_DIR}/java_sources")
add_custom_command(OUTPUT "${OPENCV_DEPHELPER}/${the_module}_jar"
BYPRODUCTS ${__byproducts} # required for add_custom_target() by ninja
DEPENDS ${depends}
COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/${the_module}_jar"
COMMAND ${CMAKE_COMMAND}
-D OPENCV_JAVA_DIR="${OPENCV_JAVA_DIR}/java"
-D OUTPUT="${OPENCV_JAVA_DIR}/java_sources"
-P "${CMAKE_CURRENT_SOURCE_DIR}/list_java_sources.cmake"
)
add_custom_target(${the_module}_jar_sources
DEPENDS "${OPENCV_DEPHELPER}/${the_module}_jar"
)
list(APPEND CMAKE_JAVA_COMPILE_FLAGS -encoding utf-8 ${OPENCV_EXTRA_JAVA_COMPILE_FLAGS})
add_jar(${the_module}_jar
SOURCES "@${OPENCV_JAVA_DIR}/java_sources"
MANIFEST "${OPENCV_JAVA_DIR}/MANIFEST.MF"
OUTPUT_NAME "${JAR_NAME_WE}"
OUTPUT_DIR "${OPENCV_JAR_DIR}")
add_dependencies(${the_module}_jar ${the_module}_jar_sources)
else()
ocv_assert(0)
endif()
install(FILES ${OPENCV_JAR_FILE} OPTIONAL DESTINATION ${OPENCV_JAR_INSTALL_PATH} COMPONENT java)
add_dependencies(${the_module} ${the_module}_jar)
if(BUILD_DOCS)
if(OPENCV_JAVA_SDK_BUILD_TYPE STREQUAL "ANT")
add_custom_command(OUTPUT "${OPENCV_DEPHELPER}/${the_module}doc"
COMMAND ${ANT_EXECUTABLE} -noinput -k javadoc
COMMAND ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/${the_module}doc"
WORKING_DIRECTORY "${OPENCV_JAVA_DIR}"
DEPENDS ${depends}
COMMENT "Generating Javadoc"
)
add_custom_target(${the_module}doc DEPENDS "${OPENCV_DEPHELPER}/${the_module}doc")
install(DIRECTORY ${OpenCV_BINARY_DIR}/doc/doxygen/html/javadoc
DESTINATION "${OPENCV_DOC_INSTALL_PATH}/html"
COMPONENT "docs" OPTIONAL
${compatible_MESSAGE_NEVER}
)
elseif(OPENCV_JAVA_SDK_BUILD_TYPE STREQUAL "JAVA")
set(Java_JAVADOC_EXECUTABLE ${Java_JAVADOC_EXECUTABLE} -encoding utf-8)
# create_javadoc produces target ${_target}_javadoc
create_javadoc(${the_module}
FILES "@${OPENCV_JAVA_DIR}/java_sources"
SOURCEPATH "${OPENCV_JAVA_DIR}/java"
INSTALLPATH "${OPENCV_JAVADOC_DESTINATION}"
WINDOWTITLE "OpenCV ${OPENCV_VERSION_PLAIN} Java documentation"
DOCTITLE "OpenCV Java documentation (${OPENCV_VERSION})"
VERSION TRUE
)
add_dependencies(${the_module}_javadoc ${the_module}_jar_sources)
add_custom_target(${the_module}doc DEPENDS ${the_module}_javadoc)
install(DIRECTORY ${OpenCV_BINARY_DIR}/doc/doxygen/html/javadoc/${the_module}/
DESTINATION "${OPENCV_DOC_INSTALL_PATH}/html/javadoc"
COMPONENT "docs" OPTIONAL
${compatible_MESSAGE_NEVER}
)
else()
ocv_assert(0)
endif()
set(CMAKE_DOXYGEN_JAVADOC_NODE
"<tab type=\"user\" url=\"./javadoc/index.html\" title=\"Java documentation\"/>"
CACHE INTERNAL "Link to the Java documentation") # set to the cache to make it global
add_custom_target(doxygen_javadoc DEPENDS ${the_module}doc)
add_dependencies(opencv_docs ${the_module}doc)
else()
unset(CMAKE_DOXYGEN_JAVADOC_NODE CACHE)
endif()
+6
View File
@@ -0,0 +1,6 @@
Specification-Title: OpenCV
Specification-Version: @OPENCV_VERSION@
Implementation-Title: OpenCV
Implementation-Version: @OPENCV_VCSVERSION@
Implementation-Date: @OPENCV_TIMESTAMP@
Automatic-Module-Name: org.opencv
+69
View File
@@ -0,0 +1,69 @@
<!-- This is an Apache Ant build file. As part of the desktop java build -->
<!-- process, this config is used to package the autogenerated .java -->
<!-- interface files into OpenCV.jar -->
<project name="OpenCV">
<tstamp>
<format property="timestamp" pattern="EEE MMM d yyyy HH:mm:ss z"/>
</tstamp>
<target name="jar">
<!-- This is to make a jar with a source attachment, for e.g. easy -->
<!-- navigation in Eclipse. See this question: -->
<!-- http://stackoverflow.com/questions/3584968/ant-how-to-compile-jar-that-includes-source-attachment -->
<javac sourcepath="" srcdir="java" destdir="build/classes" debug="on" includeantruntime="false" @OPENCV_ANT_JAVAC_EXTRA_ATTRS@ >
<include name="**/*.java"/>
<compilerarg line="-encoding utf-8"/>
</javac>
<jar destfile="@OPENCV_JAR_FILE@">
<fileset dir="java"/>
<fileset dir="build/classes"/>
<manifest>
<attribute name="Specification-Title" value="OpenCV"/>
<attribute name="Specification-Version" value="@OPENCV_VERSION@"/>
<attribute name="Implementation-Title" value="OpenCV"/>
<attribute name="Implementation-Version" value="@OPENCV_VCSVERSION@"/>
<attribute name="Implementation-Date" value="${timestamp}"/>
<attribute name="Automatic-Module-Name" value="org.opencv"/>
</manifest>
</jar>
</target>
<target name="javadoc">
<copy file="@OpenCV_SOURCE_DIR@/doc/mymath.js"
todir="@OPENCV_JAVADOC_DESTINATION@" />
<!-- synchronize with platforms\android\build_sdk.py -->
<javadoc
packagenames="org.opencv.*"
sourcepath="java"
destdir="@OPENCV_JAVADOC_DESTINATION@"
Windowtitle="OpenCV @OPENCV_VERSION_PLAIN@ Java documentation"
Doctitle="OpenCV Java documentation (@OPENCV_VERSION@)"
bottom="Generated on ${timestamp} / OpenCV @OPENCV_VCSVERSION@"
failonerror="true"
encoding="UTF-8" charset="UTF-8" docencoding="UTF-8"
@CMAKE_CONFIG_OPENCV_JAVADOC_LINK@
additionalparam="--allow-script-in-comments"
>
<bottom>
<![CDATA[
<script>
var url = window.location.href;
var pos = url.lastIndexOf('/javadoc/');
url = pos >= 0 ? (url.substring(0, pos) + '/javadoc/mymath.js') : (window.location.origin + '/mymath.js');
var script = document.createElement('script');
script.setAttribute("src", url);
script.setAttribute("defer", "")
document.head.appendChild(script);
script = document.createElement('script');
script.setAttribute("src", '@OPENCV_MATHJAX_RELPATH@/es5/tex-chtml.js');
script.setAttribute("defer", "")
document.head.appendChild(script);
</script>
]]>
</bottom>
</javadoc>
</target>
</project>
+19
View File
@@ -0,0 +1,19 @@
file(GLOB_RECURSE java_sources "${OPENCV_JAVA_DIR}/*.java")
set(__sources "")
foreach(dst ${java_sources})
set(__sources "${__sources}${dst}\n")
endforeach()
function(ocv_update_file filepath content)
if(EXISTS "${filepath}")
file(READ "${filepath}" actual_content)
else()
set(actual_content "")
endif()
if(NOT ("${actual_content}" STREQUAL "${content}"))
file(WRITE "${filepath}" "${content}")
endif()
endfunction()
ocv_update_file("${OUTPUT}" "${__sources}")
+102
View File
@@ -0,0 +1,102 @@
project(${the_module})
glob_more_specific_sources(H "${CMAKE_CURRENT_SOURCE_DIR}/../generator/src" handwritten_h_sources)
glob_more_specific_sources(CPP "${CMAKE_CURRENT_SOURCE_DIR}/../generator/src" handwritten_cpp_sources)
# grab C++ files from misc/java
foreach(m ${OPENCV_MODULES_BUILD})
if (";${OPENCV_MODULE_${m}_WRAPPERS};" MATCHES ";java;" AND HAVE_${m})
set(module_java_dir "${OPENCV_MODULE_${m}_LOCATION}/misc/java")
include_directories("${module_java_dir}/src/cpp")
file(GLOB _result "${module_java_dir}/src/cpp/*.h" "${module_java_dir}/src/cpp/*.hpp" "${module_java_dir}/src/cpp/*.cpp")
list(APPEND handwritten_cpp_sources ${_result})
endif()
endforeach()
if(ANDROID)
ocv_update(JNI_OUTPUT_PATH "${OpenCV_BINARY_DIR}/jni/${ANDROID_NDK_ABI_NAME}")
else()
ocv_update(JNI_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH}")
endif()
set(__type MODULE)
if(BUILD_FAT_JAVA_LIB)
set(__type SHARED) # samples link to libopencv_java
elseif(APPLE)
set(CMAKE_SHARED_MODULE_SUFFIX ".dylib") # Java is not able to load .so files
endif()
ocv_add_library(${the_module} ${__type}
${handwritten_h_sources} ${handwritten_cpp_sources} ${generated_cpp_sources}
${copied_files}
)
add_dependencies(${the_module} gen_opencv_java_source)
ocv_target_include_directories(${the_module} "${CMAKE_CURRENT_SOURCE_DIR}/../generator/src/cpp")
ocv_target_include_directories(${the_module} "${OPENCV_JAVA_BINDINGS_DIR}/gen/cpp")
ocv_target_include_modules(${the_module} ${OPENCV_MODULE_${the_module}_DEPS})
if(NOT ANDROID)
ocv_target_include_directories(${the_module} SYSTEM ${JNI_INCLUDE_DIRS})
endif()
set(__deps ${OPENCV_MODULE_${the_module}_DEPS})
list(REMOVE_ITEM __deps opencv_java_bindings_generator) # don't add dummy module to target_link_libraries list
if(BUILD_FAT_JAVA_LIB)
ocv_list_unique(__deps)
set(__extradeps ${__deps})
ocv_list_filterout(__extradeps "^opencv_")
if(__extradeps)
list(REMOVE_ITEM __deps ${__extradeps})
endif()
if(APPLE)
foreach(_dep ${__deps})
ocv_target_link_libraries(${the_module} PRIVATE -Wl,-force_load "${_dep}")
endforeach()
elseif(((CV_GCC OR CV_CLANG OR UNIX) OR (OPENCV_FORCE_FAT_JAVA_LIB_LD_RULES)) AND (NOT OPENCV_SKIP_FAT_JAVA_LIB_LD_RULES))
ocv_target_link_libraries(${the_module} PRIVATE -Wl,-whole-archive ${__deps} -Wl,-no-whole-archive)
else()
ocv_target_link_libraries(${the_module} PRIVATE ${__deps})
endif()
ocv_target_link_libraries(${the_module} PRIVATE ${__extradeps} ${OPENCV_LINKER_LIBS})
else()
ocv_target_link_libraries(${the_module} PRIVATE ${__deps} ${OPENCV_LINKER_LIBS})
endif()
# Additional target properties
set_target_properties(${the_module} PROPERTIES
OUTPUT_NAME "${the_module}${OPENCV_JAVA_LIB_NAME_SUFFIX}"
ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
LIBRARY_OUTPUT_DIRECTORY ${JNI_OUTPUT_PATH}
RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
DEFINE_SYMBOL CVAPI_EXPORTS
)
if(ANDROID)
ocv_target_link_libraries(${the_module} PUBLIC jnigraphics # for Mat <=> Bitmap converters
INTERFACE jnigraphics
)
ocv_target_link_libraries(${the_module} PUBLIC log dl z
INTERFACE log dl z
)
# force strip library after the build command
# because samples and tests will make a copy of the library before install
if(NOT BUILD_WITH_DEBUG_INFO AND NOT CMAKE_BUILD_TYPE MATCHES "Debug")
add_custom_command(TARGET ${the_module} POST_BUILD COMMAND ${CMAKE_STRIP} --strip-unneeded "$<TARGET_FILE:${the_module}>")
endif()
endif()
if(ENABLE_SOLUTION_FOLDERS)
set_target_properties(${the_module} PROPERTIES FOLDER "bindings")
endif()
set(__install_export "")
if(BUILD_FAT_JAVA_LIB)
set(__install_export EXPORT OpenCVModules)
endif()
ocv_install_target(${the_module} OPTIONAL ${__install_export}
RUNTIME DESTINATION ${OPENCV_JNI_BIN_INSTALL_PATH} COMPONENT java
LIBRARY DESTINATION ${OPENCV_JNI_INSTALL_PATH} COMPONENT java
ARCHIVE DESTINATION ${OPENCV_JNI_INSTALL_PATH} COMPONENT java
)
@@ -0,0 +1,7 @@
bin/
gen/
build.xml
local.properties
proguard-project.txt
project.properties
default.properties
@@ -0,0 +1,25 @@
project(opencv_test_android)
set(OPENCV_ANDROID_TEST_DIR "${OpenCV_BINARY_DIR}/android_test" CACHE INTERNAL "")
file(REMOVE_RECURSE "${OPENCV_ANDROID_TEST_DIR}")
set(ANDROID_TESTS_SRC_DIRS
"'${CMAKE_CURRENT_SOURCE_DIR}/src', \
'${OpenCV_SOURCE_DIR}/modules/java/test/common_test/src', \
'${CMAKE_BINARY_DIR}/modules/java_bindings_generator/gen/test'" CACHE INTERNAL "")
set(ANDROID_TESTS_RES_DIR "'${OpenCV_SOURCE_DIR}/modules/java/test/common_test/res'" CACHE INTERNAL "")
list(APPEND TEST_PROJECT_FILES "CMakeLists.txt" "gradle.properties" "settings.gradle")
foreach(TEST_PROJECT_FILE ${TEST_PROJECT_FILES})
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/${TEST_PROJECT_FILE}" DESTINATION "${OPENCV_ANDROID_TEST_DIR}")
endforeach()
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests_module/AndroidManifest.xml" DESTINATION "${OPENCV_ANDROID_TEST_DIR}/tests_module")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tests_module/build.gradle.in" "${OPENCV_ANDROID_TEST_DIR}/tests_module/build.gradle" @ONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build.gradle.in" "${OPENCV_ANDROID_TEST_DIR}/build.gradle" @ONLY)
file(COPY "${OpenCV_SOURCE_DIR}/platforms/android/gradle-wrapper/gradlew" DESTINATION "${OPENCV_ANDROID_TEST_DIR}")
file(COPY "${OpenCV_SOURCE_DIR}/platforms/android/gradle-wrapper/gradlew.bat" DESTINATION "${OPENCV_ANDROID_TEST_DIR}")
file(COPY "${OpenCV_SOURCE_DIR}/platforms/android/gradle-wrapper/gradle/wrapper/gradle-wrapper.jar" DESTINATION "${OPENCV_ANDROID_TEST_DIR}/gradle/wrapper")
configure_file("${OpenCV_SOURCE_DIR}/platforms/android/gradle-wrapper/gradle/wrapper/gradle-wrapper.properties.in" "${OPENCV_ANDROID_TEST_DIR}/gradle/wrapper/gradle-wrapper.properties" @ONLY)
@@ -0,0 +1,27 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:@ANDROID_GRADLE_PLUGIN_VERSION@'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:@KOTLIN_PLUGIN_VERSION@'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
@@ -0,0 +1,18 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2g
android.useAndroidX=true
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
@@ -0,0 +1,6 @@
rootProject.name = 'android_test'
include ':opencv'
project(':opencv').projectDir = new File('../opencv_android/opencv')
include ':tests_module'
@@ -0,0 +1,636 @@
package org.opencv.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.List;
import junit.framework.TestCase;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Point3;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.core.DMatch;
import org.opencv.core.KeyPoint;
import org.opencv.imgcodecs.Imgcodecs;
import android.util.Log;
import java.lang.reflect.Method;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
public class OpenCVTestCase extends TestCase {
public static class TestSkipException extends RuntimeException {
public TestSkipException() {}
}
//change to 'true' to unblock fail on fail("Not yet implemented")
public static final boolean passNYI = true;
protected static boolean isTestCaseEnabled = true;
protected static final String XFEATURES2D = "org.opencv.xfeatures2d.";
protected static final String DEFAULT_FACTORY = "create";
protected static final int matSize = 10;
protected static final double EPS = 0.001;
protected static final double weakEPS = 0.5;
private static final String TAG = "OpenCVTestCase";
protected Mat dst;
protected Mat truth;
protected Scalar colorBlack;
protected Scalar colorWhite;
// Naming notation: <channels info>_[depth]_[dimensions]_value
// examples: gray0 - single channel 8U 2d Mat filled with 0
// grayRnd - single channel 8U 2d Mat filled with random numbers
// gray0_32f_1d
// TODO: OpenCVTestCase refactorings
// - rename matrices
// - create methods gray0() and create src1 explicitly
// - create some masks
// - use truth member everywhere - remove truth from base class - each test
// fixture should use own truth filed
protected Mat gray0;
protected Mat gray1;
protected Mat gray2;
protected Mat gray3;
protected Mat gray9;
protected Mat gray127;
protected Mat gray128;
protected Mat gray255;
protected Mat grayRnd;
protected Mat gray_16u_256;
protected Mat gray_16s_1024;
protected Mat gray0_32f;
protected Mat gray1_32f;
protected Mat gray3_32f;
protected Mat gray9_32f;
protected Mat gray255_32f;
protected Mat grayE_32f;
protected Mat grayRnd_32f;
protected Mat gray0_32f_1d;
protected Mat gray0_64f;
protected Mat gray0_64f_1d;
protected Mat rgba0;
protected Mat rgba128;
protected Mat rgbLena;
protected Mat grayChess;
protected Mat gray255_32f_3d;
protected Mat v1;
protected Mat v2;
@Override
protected void setUp() throws Exception {
super.setUp();
dst = new Mat();
assertTrue(dst.empty());
truth = null;
colorBlack = new Scalar(0);
colorWhite = new Scalar(255, 255, 255);
gray0 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(0));
gray1 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(1));
gray2 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(2));
gray3 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(3));
gray9 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(9));
gray127 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(127));
gray128 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(128));
gray255 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(255));
grayRnd = new Mat(matSize, matSize, CvType.CV_8U);
Core.randu(grayRnd, 0, 256);
gray_16u_256 = new Mat(matSize, matSize, CvType.CV_16U, new Scalar(256));
gray_16s_1024 = new Mat(matSize, matSize, CvType.CV_16S, new Scalar(1024));
gray0_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(0.0));
gray1_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(1.0));
gray3_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(3.0));
gray9_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(9.0));
gray255_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(255.0));
grayE_32f = new Mat(matSize, matSize, CvType.CV_32F);
grayE_32f = Mat.eye(matSize, matSize, CvType.CV_32FC1);
grayRnd_32f = new Mat(matSize, matSize, CvType.CV_32F);
Core.randu(grayRnd_32f, 0, 256);
gray0_64f = new Mat(matSize, matSize, CvType.CV_64F, new Scalar(0.0));
gray0_32f_1d = new Mat(1, matSize, CvType.CV_32F, new Scalar(0.0));
gray0_64f_1d = new Mat(1, matSize, CvType.CV_64F, new Scalar(0.0));
rgba0 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(0));
rgba128 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(128));
rgbLena = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH);
grayChess = Imgcodecs.imread(OpenCVTestRunner.CHESS_PATH, Imgcodecs.IMREAD_GRAYSCALE);
gray255_32f_3d = new Mat(new int[]{matSize, matSize, matSize}, CvType.CV_32F, new Scalar(255.0));
v1 = new Mat(1, 3, CvType.CV_32F);
v1.put(0, 0, 1.0, 3.0, 2.0);
v2 = new Mat(1, 3, CvType.CV_32F);
v2.put(0, 0, 2.0, 1.0, 3.0);
}
@Override
protected void tearDown() throws Exception {
gray0.release();
gray1.release();
gray2.release();
gray3.release();
gray9.release();
gray127.release();
gray128.release();
gray255.release();
gray_16u_256.release();
gray_16s_1024.release();
grayRnd.release();
gray0_32f.release();
gray1_32f.release();
gray3_32f.release();
gray9_32f.release();
gray255_32f.release();
grayE_32f.release();
grayE_32f.release();
grayRnd_32f.release();
gray0_32f_1d.release();
gray0_64f.release();
gray0_64f_1d.release();
rgba0.release();
rgba128.release();
rgbLena.release();
grayChess.release();
gray255_32f_3d.release();
v1.release();
v2.release();
super.tearDown();
}
@Override
protected void runTest() throws Throwable {
// Do nothing if the precondition does not hold.
if (isTestCaseEnabled) {
try {
super.runTest();
} catch (TestSkipException ex) {
Log.w(TAG, "Test case \"" + this.getClass().getName() + "\" skipped!");
assertTrue(true);
}
} else {
Log.e(TAG, "Test case \"" + this.getClass().getName() + "\" disabled!");
}
}
public void runBare() throws Throwable {
Throwable exception = null;
try {
setUp();
} catch (TestSkipException ex) {
Log.w(TAG, "Test case \"" + this.getClass().getName() + "\" skipped!");
assertTrue(true);
return;
}
try {
runTest();
} catch (Throwable running) {
exception = running;
} finally {
try {
tearDown();
} catch (Throwable tearingDown) {
if (exception == null) exception = tearingDown;
}
}
if (exception != null) throw exception;
}
protected Mat getMat(int type, double... vals)
{
return new Mat(matSize, matSize, type, new Scalar(vals));
}
protected Mat makeMask(Mat m, double... vals)
{
m.submat(0, m.rows(), 0, m.cols() / 2).setTo(new Scalar(vals));
return m;
}
public static void fail(String msg) {
if(msg == "Not yet implemented" && passNYI)
return;
TestCase.fail(msg);
}
public static void assertGE(double v1, double v2) {
assertTrue("Failed: " + v1 + " >= " + v2, v1 >= v2);
}
public static <E extends Number> void assertListEquals(List<E> list1, List<E> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
if (!list1.isEmpty())
{
if (list1.get(0) instanceof Float || list1.get(0) instanceof Double)
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertEquals(list1.get(i), list2.get(i));
}
public static <E extends Number> void assertListEquals(List<E> list1, List<E> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertTrue(Math.abs(list1.get(i).doubleValue() - list2.get(i).doubleValue()) <= epsilon);
}
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertArrayEquals(short[] ar1, short[] ar2) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i]);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertArrayEquals(byte[] ar1, byte[] ar2) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i]);
}
public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i], epsilon);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertListMatEquals(List<Mat> list1, List<Mat> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertMatEqual(list1.get(i), list2.get(i), epsilon);
}
public static void assertListPointEquals(List<Point> list1, List<Point> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertPointEquals(list1.get(i), list2.get(i), epsilon);
}
public static void assertArrayPointsEquals(Point[] vp1, Point[] vp2, double epsilon) {
if (vp1.length != vp2.length) {
fail("Arrays have different sizes.");
}
for (int i = 0; i < vp1.length; i++)
assertPointEquals(vp1[i], vp2[i], epsilon);
}
public static void assertListPoint3Equals(List<Point3> list1, List<Point3> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertPoint3Equals(list1.get(i), list2.get(i), epsilon);
}
public static void assertListRectEquals(List<Rect> list1, List<Rect> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertRectEquals(list1.get(i), list2.get(i));
}
public static void assertListRotatedRectEquals(List<RotatedRect> list1, List<RotatedRect> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertRotatedRectEquals(list1.get(i), list2.get(i));
}
public static void assertRectEquals(Rect expected, Rect actual) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x);
assertEquals(msg, expected.y, actual.y);
assertEquals(msg, expected.width, actual.width);
assertEquals(msg, expected.height, actual.height);
}
public static void assertRotatedRectEquals(RotatedRect expected, RotatedRect actual) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.center.x, actual.center.x);
assertEquals(msg, expected.center.y, actual.center.y);
assertEquals(msg, expected.size.width, actual.size.width);
assertEquals(msg, expected.size.height, actual.size.height);
assertEquals(msg, expected.angle, actual.angle);
}
public static void assertMatEqual(Mat m1, Mat m2) {
compareMats(m1, m2, true);
}
public static void assertMatNotEqual(Mat m1, Mat m2) {
compareMats(m1, m2, false);
}
public static void assertMatEqual(Mat expected, Mat actual, double eps) {
compareMats(expected, actual, eps, true);
}
public static void assertMatNotEqual(Mat expected, Mat actual, double eps) {
compareMats(expected, actual, eps, false);
}
public static void assertKeyPointEqual(KeyPoint expected, KeyPoint actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertTrue(msg, Math.hypot(expected.pt.x - actual.pt.x, expected.pt.y - actual.pt.y) < eps);
assertTrue(msg, Math.abs(expected.size - actual.size) < eps);
assertTrue(msg, Math.abs(expected.angle - actual.angle) < eps);
assertTrue(msg, Math.abs(expected.response - actual.response) < eps);
assertEquals(msg, expected.octave, actual.octave);
assertEquals(msg, expected.class_id, actual.class_id);
}
public static void assertListKeyPointEquals(List<KeyPoint> expected, List<KeyPoint> actual, double epsilon) {
assertEquals(expected.size(), actual.size());
for (int i = 0; i < expected.size(); i++)
assertKeyPointEqual(expected.get(i), actual.get(i), epsilon);
}
public static void assertDMatchEqual(DMatch expected, DMatch actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.queryIdx, actual.queryIdx);
assertEquals(msg, expected.trainIdx, actual.trainIdx);
assertEquals(msg, expected.imgIdx, actual.imgIdx);
assertTrue(msg, Math.abs(expected.distance - actual.distance) < eps);
}
public static void assertScalarEqual(Scalar expected, Scalar actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertTrue(msg, Math.abs(expected.val[0] - actual.val[0]) < eps);
assertTrue(msg, Math.abs(expected.val[1] - actual.val[1]) < eps);
assertTrue(msg, Math.abs(expected.val[2] - actual.val[2]) < eps);
assertTrue(msg, Math.abs(expected.val[3] - actual.val[3]) < eps);
}
public static void assertArrayDMatchEquals(DMatch[] expected, DMatch[] actual, double epsilon) {
assertEquals(expected.length, actual.length);
for (int i = 0; i < expected.length; i++)
assertDMatchEqual(expected[i], actual[i], epsilon);
}
public static void assertListDMatchEquals(List<DMatch> expected, List<DMatch> actual, double epsilon) {
DMatch expectedArray[] = expected.toArray(new DMatch[0]);
DMatch actualArray[] = actual.toArray(new DMatch[0]);
assertArrayDMatchEquals(expectedArray, actualArray, epsilon);
}
public static void assertPointEquals(Point expected, Point actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x, eps);
assertEquals(msg, expected.y, actual.y, eps);
}
public static void assertSizeEquals(Size expected, Size actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.width, actual.width, eps);
assertEquals(msg, expected.height, actual.height, eps);
}
public static void assertPoint3Equals(Point3 expected, Point3 actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x, eps);
assertEquals(msg, expected.y, actual.y, eps);
assertEquals(msg, expected.z, actual.z, eps);
}
static private boolean dimensionsEqual(Mat expected, Mat actual) {
if (expected.dims() != actual.dims()) {
return false;
}
if (expected.dims() > 2) {
for (int i = 0; i < expected.dims(); i++) {
if (expected.size(i) != actual.size(i)) {
return false;
}
}
return true;
} else {
return expected.cols() == actual.cols() && expected.rows() == actual.rows();
}
}
static private void compareMats(Mat expected, Mat actual, boolean isEqualityMeasured) {
if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
}
if (expected.depth() == CvType.CV_32F || expected.depth() == CvType.CV_64F) {
if (isEqualityMeasured)
throw new UnsupportedOperationException(
"Floating-point Mats must not be checked for exact match. Use assertMatEqual(Mat expected, Mat actual, double eps) instead.");
else
throw new UnsupportedOperationException(
"Floating-point Mats must not be checked for exact match. Use assertMatNotEqual(Mat expected, Mat actual, double eps) instead.");
}
Mat diff = new Mat();
Core.absdiff(expected, actual, diff);
Mat reshaped = diff.reshape(1);
int mistakes = Core.countNonZero(reshaped);
reshaped.release();
diff.release();
if (isEqualityMeasured)
assertTrue("Mats are different in " + mistakes + " points", 0 == mistakes);
else
assertFalse("Mats are equal", 0 == mistakes);
}
static private void compareMats(Mat expected, Mat actual, double eps, boolean isEqualityMeasured) {
if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
}
Mat diff = new Mat();
Core.absdiff(expected, actual, diff);
double maxDiff = Core.norm(diff, Core.NORM_INF);
if (isEqualityMeasured)
assertTrue("Max difference between expected and actual Mats is "+ maxDiff + ", that bigger than " + eps,
maxDiff <= eps);
else
assertFalse("Max difference between expected and actual Mats is "+ maxDiff + ", that less than " + eps,
maxDiff <= eps);
}
protected static String readFile(String path) {
try {
BufferedReader br = new BufferedReader(new FileReader(path));
String line;
StringBuffer result = new StringBuffer();
while ((line = br.readLine()) != null) {
result.append(line);
result.append("\n");
}
return result.toString();
} catch (IOException e) {
OpenCVTestRunner.Log("Failed to read file \"" + path
+ "\". Exception is thrown: " + e);
return null;
}
}
protected static void writeFile(String path, String content) {
FileOutputStream stream = null;
try {
stream = new FileOutputStream(new File(path));
FileChannel fc = stream.getChannel();
fc.write(Charset.defaultCharset().encode(content));
} catch (IOException e) {
OpenCVTestRunner.Log("Failed to write file \"" + path
+ "\". Exception is thrown: " + e);
} finally {
if (stream != null)
try {
stream.close();
} catch (IOException e) {
OpenCVTestRunner.Log("Exception is thrown: " + e);
}
}
}
protected <T> T createClassInstance(String cname, String factoryName, Class cParams[], Object oValues[]) {
T instance = null;
assertFalse("Class name should not be empty", "".equals(cname));
String message="";
try {
Class algClass = getClassForName(cname);
Method factory = null;
if(cParams!=null && cParams.length>0) {
if(!"".equals(factoryName)) {
factory = algClass.getDeclaredMethod(factoryName, cParams);
instance = (T) factory.invoke(null, oValues);
}
else {
instance = (T) algClass.getConstructor(cParams).newInstance(oValues);
}
}
else {
if(!"".equals(factoryName)) {
factory = algClass.getDeclaredMethod(factoryName);
instance = (T) factory.invoke(null);
}
else {
instance = (T) algClass.getConstructor().newInstance();
}
}
}
catch(Exception ex) {
if (cname.startsWith(XFEATURES2D))
{
throw new TestSkipException();
}
message = TAG + " :: " + "could not instantiate " + cname + "! Exception: " + ex.getMessage();
}
assertNotNull(message, instance);
return instance;
}
protected <T> void setProperty(T instance, String propertyName, String propertyType, Object propertyValue) {
String message = "";
try {
String smethod = "set" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
Method setter = instance.getClass().getMethod(smethod, getClassForName(propertyType));
setter.invoke(instance, propertyValue);
}
catch(Exception ex) {
message = "Error when setting property [" + propertyName + "]: " + ex.getMessage();
}
assertTrue(message, "".equals(message));
}
protected Class getClassForName(String sclass) throws ClassNotFoundException{
if("int".equals(sclass))
return Integer.TYPE;
else if("long".equals(sclass))
return Long.TYPE;
else if("double".equals(sclass))
return Double.TYPE;
else if("float".equals(sclass))
return Float.TYPE;
else if("boolean".equals(sclass))
return Boolean.TYPE;
else if("char".equals(sclass))
return Character.TYPE;
else if("byte".equals(sclass))
return Byte.TYPE;
else if("short".equals(sclass))
return Short.TYPE;
else
return Class.forName(sclass);
}
}
@@ -0,0 +1,78 @@
package org.opencv.test;
import java.io.File;
import java.io.IOException;
import junit.framework.Assert;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import android.content.Context;
import android.util.Log;
import androidx.test.runner.AndroidJUnitRunner;
/**
* This only class is Android specific.
*/
public class OpenCVTestRunner extends AndroidJUnitRunner {
private static final long MANAGER_TIMEOUT = 3000;
public static String LENA_PATH;
public static String CHESS_PATH;
public static String LBPCASCADE_FRONTALFACE_PATH;
public static Context context;
private static String TAG = "opencv_test_java";
public static String getTempFileName(String extension)
{
File cache = context.getCacheDir();
if (!extension.startsWith("."))
extension = "." + extension;
try {
File tmp = File.createTempFile("OpenCV", extension, cache);
String path = tmp.getAbsolutePath();
tmp.delete();
return path;
} catch (IOException e) {
Log("Failed to get temp file name. Exception is thrown: " + e);
}
return null;
}
static public void Log(String message) {
Log.e(TAG, message);
}
static public void Log(Mat m) {
Log.e(TAG, m + "\n " + m.dump());
}
@Override
public void onStart() {
Assert.assertTrue(OpenCVLoader.initLocal());
context = getTargetContext();
Assert.assertNotNull("Context can't be 'null'", context);
LENA_PATH = Utils.exportResource(context, context.getResources().getIdentifier("lena", "drawable", context.getPackageName()));
CHESS_PATH = Utils.exportResource(context, context.getResources().getIdentifier("chessboard", "drawable", context.getPackageName()));
//LBPCASCADE_FRONTALFACE_PATH = Utils.exportResource(context, R.raw.lbpcascade_frontalface);
/*
* The original idea about test order randomization is from
* marek.defecinski blog.
*/
//List<TestCase> testCases = androidTestRunner.getTestCases();
//Collections.shuffle(testCases); //shuffle the tests order
super.onStart();
}
public static String getOutputFileName(String name)
{
return context.getExternalFilesDir(null).getAbsolutePath() + File.separatorChar + name;
}
}
@@ -0,0 +1,25 @@
package org.opencv.test.android
import org.opencv.core.CvType
import org.opencv.core.Mat
import org.opencv.core.times
import org.opencv.test.OpenCVTestCase
import kotlin.math.abs
class KotlinTest : OpenCVTestCase() {
fun testMatrixMultiplication() {
val m1 = Mat.ones(2, 3, CvType.CV_32F)
val m2 = Mat.ones(3, 2, CvType.CV_32F)
val m3 = m1.matMul(m2)
val m4 = m1 * m2
val value1 = floatArrayOf(3f)
m3.get(0, 1, value1)
val value2 = floatArrayOf(5f)
m4[0, 1, value2]
assertGE(0.001, abs(value1[0] - value2[0]).toDouble())
}
}
@@ -0,0 +1,225 @@
package org.opencv.test.android;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.test.OpenCVTestCase;
import org.opencv.test.OpenCVTestRunner;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.util.Log;
public class UtilsTest extends OpenCVTestCase {
private int[] testImgWH = new int[]{64, 48};
private byte[] testImgBgColor = new byte[]{1, 2, 3};
private int[] testImgRect = new int[] {15, 17, 25, 37};
private byte[] testImgRectColor = new byte[]{45, 15, 67};
private Mat createTestBGRImg() {
Mat img = new Mat(testImgWH[1], testImgWH[0], CvType.CV_8UC3,
new Scalar(testImgBgColor[2], testImgBgColor[1], testImgBgColor[0]));
byte[] color = new byte[]{testImgRectColor[2], testImgRectColor[1], testImgRectColor[0]};
for (int i = testImgRect[1]; i < testImgRect[3]; i++) {
for (int j = testImgRect[0]; j < testImgRect[2]; j++) {
img.put(i, j, color);
}
}
return img;
}
private Bitmap createTestBitmap() {
Bitmap img = Bitmap.createBitmap(testImgWH[0], testImgWH[1], Bitmap.Config.ARGB_8888);
img.eraseColor(Color.argb(255, testImgBgColor[0], testImgBgColor[1] ,testImgBgColor[2]));
for (int i = testImgRect[1]; i < testImgRect[3]; i++) {
for (int j = testImgRect[0]; j < testImgRect[2]; j++) {
img.setPixel(j, i, Color.argb(
255, testImgRectColor[0], testImgRectColor[1], testImgRectColor[2]));
}
}
return img;
}
public void testMatBitmapConversion() {
Mat mat = new Mat();
Imgproc.cvtColor(createTestBGRImg(), mat, Imgproc.COLOR_BGR2RGBA);
Bitmap bmp = createTestBitmap();
Bitmap convertedBmp = Bitmap.createBitmap(
Bitmap.createBitmap(testImgWH[0], testImgWH[1], Bitmap.Config.ARGB_8888));
Utils.matToBitmap(mat, convertedBmp);
assertTrue(bmp.sameAs(convertedBmp));
Mat convertedMat = new Mat();
Utils.bitmapToMat(bmp, convertedMat);
Mat diff = new Mat();
Core.absdiff(mat, convertedMat, diff);
Scalar channelsDiff = Core.sumElems(diff);
assertEquals(0.0, channelsDiff.val[0]);
assertEquals(0.0, channelsDiff.val[1]);
assertEquals(0.0, channelsDiff.val[2]);
assertEquals(0.0, channelsDiff.val[3]);
}
public void testBitmapToMat() {
BitmapFactory.Options opt16 = new BitmapFactory.Options();
opt16.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bmp16 = BitmapFactory.decodeFile(OpenCVTestRunner.LENA_PATH, opt16);
Mat m16 = new Mat();
Utils.bitmapToMat(bmp16, m16);
assertTrue(m16.rows() == 512 && m16.cols() == 512 && m16.type() == CvType.CV_8UC4);
/*BitmapFactory.Options opt32 = new BitmapFactory.Options();
opt32.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bmp32 = BitmapFactory.decodeFile(OpenCVTestRunner.LENA_PATH, opt32);*/
Bitmap bmp32 = bmp16.copy(Bitmap.Config.ARGB_8888, false);
Mat m32 = new Mat();
Utils.bitmapToMat(bmp32, m32);
assertTrue(m16.rows() == m32.rows() && m16.cols() == m32.cols() && m16.type() == m32.type());
double maxDiff = Core.norm(m16, m32, Core.NORM_INF);
Log.d("Bmp->Mat", "bmp16->Mat vs bmp32->Mat diff = " + maxDiff);
assertTrue(maxDiff <= 8 /* 8 == 2^8 / 2^5 */);
}
public void testExportResourceContextInt() {
fail("Not yet implemented");
}
public void testExportResourceContextIntString() {
fail("Not yet implemented");
}
public void testLoadResourceContextInt() {
fail("Not yet implemented");
}
public void testLoadResourceContextIntInt() {
fail("Not yet implemented");
}
public void testMatToBitmap() {
Mat imgBGR = Imgcodecs.imread( OpenCVTestRunner.LENA_PATH );
assertTrue(imgBGR != null && !imgBGR.empty() && imgBGR.channels() == 3);
Mat m16 = new Mat(imgBGR.rows(), imgBGR.cols(), CvType.CV_8UC4);
Mat m32 = new Mat(imgBGR.rows(), imgBGR.cols(), CvType.CV_8UC4);
Bitmap bmp16 = Bitmap.createBitmap(imgBGR.cols(), imgBGR.rows(), Bitmap.Config.RGB_565);
Bitmap bmp32 = Bitmap.createBitmap(imgBGR.cols(), imgBGR.rows(), Bitmap.Config.ARGB_8888);
double maxDiff;
Scalar s0 = new Scalar(0);
Scalar s255 = Scalar.all(255);
// RGBA
Mat imgRGBA = new Mat();
Imgproc.cvtColor(imgBGR, imgRGBA, Imgproc.COLOR_BGR2RGBA);
assertFalse(imgRGBA.empty() && imgRGBA.channels() == 4);
bmp16.eraseColor(Color.BLACK); m16.setTo(s0);
Utils.matToBitmap(imgRGBA, bmp16); Utils.bitmapToMat(bmp16, m16);
maxDiff = Core.norm(imgRGBA, m16, Core.NORM_INF);
Log.d("RGBA->bmp16->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff <= 8 /* 8 == 2^8 / 2^5 */);
bmp32.eraseColor(Color.WHITE); m32.setTo(s255);
Utils.matToBitmap(imgRGBA, bmp32); Utils.bitmapToMat(bmp32, m32);
maxDiff = Core.norm(imgRGBA, m32, Core.NORM_INF);
Log.d("RGBA->bmp32->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff == 0);
// RGB
Mat imgRGB = new Mat();
Imgproc.cvtColor(imgBGR, imgRGB, Imgproc.COLOR_BGR2RGB);
assertFalse(imgRGB.empty() && imgRGB.channels() == 3);
bmp16.eraseColor(Color.BLACK); m16.setTo(s0);
Utils.matToBitmap(imgRGB, bmp16); Utils.bitmapToMat(bmp16, m16);
maxDiff = Core.norm(imgRGBA, m16, Core.NORM_INF);
Log.d("RGB->bmp16->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff <= 8 /* 8 == 2^8 / 2^5 */);
bmp32.eraseColor(Color.WHITE); m32.setTo(s255);
Utils.matToBitmap(imgRGB, bmp32); Utils.bitmapToMat(bmp32, m32);
maxDiff = Core.norm(imgRGBA, m32, Core.NORM_INF);
Log.d("RGB->bmp32->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff == 0);
// Gray
Mat imgGray = new Mat();
Imgproc.cvtColor(imgBGR, imgGray, Imgproc.COLOR_BGR2GRAY);
assertFalse(imgGray.empty() && imgGray.channels() == 1);
Mat tmp = new Mat();
bmp16.eraseColor(Color.BLACK); m16.setTo(s0);
Utils.matToBitmap(imgGray, bmp16); Utils.bitmapToMat(bmp16, m16);
Core.extractChannel(m16, tmp, 0);
maxDiff = Core.norm(imgGray, tmp, Core.NORM_INF);
Log.d("Gray->bmp16->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff <= 8 /* 8 == 2^8 / 2^5 */);
bmp32.eraseColor(Color.WHITE); m32.setTo(s255);
Utils.matToBitmap(imgGray, bmp32); Utils.bitmapToMat(bmp32, m32);
tmp.setTo(s0);
Core.extractChannel(m32, tmp, 0);
maxDiff = Core.norm(imgGray, tmp, Core.NORM_INF);
Log.d("Gray->bmp32->RGBA", "maxDiff = " + maxDiff);
assertTrue(maxDiff == 0);
}
public void testAlphaPremultiplication() {
final int size = 256;
Bitmap bmp = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Mat mOrig = new Mat(size, size, CvType.CV_8UC4);
Mat mUnPre = new Mat(size, size, CvType.CV_8UC4);
for(int y=0; y<size; y++) {
int a = y;
for(int x=0; x<size; x++) {
int color = Color.argb(a, 0, x, y);
bmp.setPixel(x, y, color);
mOrig.put(y, x, Color.red(color), Color.green(color), Color.blue(color), Color.alpha(color));
int colorUnPre = bmp.getPixel(x, y);
mUnPre.put(y, x, Color.red(colorUnPre), Color.green(colorUnPre), Color.blue(colorUnPre), Color.alpha(colorUnPre));
}
}
// Bitmap -> Mat
Mat m1 = new Mat();
Mat m2 = new Mat();
Utils.bitmapToMat(bmp, m1, false);
Imgproc.cvtColor(mOrig, m2, Imgproc.COLOR_RGBA2mRGBA);
assertMatEqual(m1, m2, 1.1);
Utils.bitmapToMat(bmp, m1, true);
assertMatEqual(m1, mUnPre, 1.1);
// Mat -> Bitmap
Bitmap bmp1 = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mOrig, bmp1, true);
Utils.bitmapToMat(bmp1, m1, true);
//assertMatEqual(m1, mUnPre, 1.1);
Mat diff = new Mat();
Core.absdiff(m1, mUnPre, diff);
int numDiff = Core.countNonZero(diff.reshape(1));
assertTrue(numDiff < size * 4);
}
}
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.opencv.samples.tutorial1"
>
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
</application>
</manifest>
@@ -0,0 +1,36 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
namespace 'org.opencv.tests'
compileSdkVersion @ANDROID_COMPILE_SDK_VERSION@
defaultConfig {
applicationId "org.opencv.tests"
minSdkVersion @ANDROID_MIN_SDK_VERSION@
targetSdkVersion @ANDROID_TARGET_SDK_VERSION@
versionCode 301
versionName "3.01"
testInstrumentationRunner "org.opencv.test.OpenCVTestRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
androidTest {
java.srcDirs = [@ANDROID_TESTS_SRC_DIRS@]
}
main {
manifest.srcFile 'AndroidManifest.xml'
res.srcDirs = [@ANDROID_TESTS_RES_DIR@]
}
}
}
dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation project(':opencv')
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
</LinearLayout>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World!</string>
<string name="app_name">OpenCV_JavaAPI_Tests</string>
</resources>
@@ -0,0 +1,529 @@
package org.opencv.test.utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Point3;
import org.opencv.core.Size;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.DMatch;
import org.opencv.core.KeyPoint;
import org.opencv.test.OpenCVTestCase;
import org.opencv.utils.Converters;
import java.util.ArrayList;
import java.util.List;
public class ConvertersTest extends OpenCVTestCase {
public void testMat_to_vector_char() {
Mat src = new Mat(3, 1, CvType.CV_8SC1);
src.put(0, 0, 2, 4, 3);
List<Byte> bs = new ArrayList<Byte>();
Converters.Mat_to_vector_char(src, bs);
List<Byte> truth = new ArrayList<Byte>();
byte value1 = 2;
byte value2 = 4;
byte value3 = 3;
truth.add(Byte.valueOf(value1));
truth.add(Byte.valueOf(value2));
truth.add(Byte.valueOf(value3));
assertEquals(truth, bs);
}
public void testMat_to_vector_DMatch() {
Mat src = new Mat(4, 1, CvType.CV_64FC4);
src.put(0, 0, 1, 4, 4, 10, 2, 3, 5, 6, 3, 1, 8, 12, 4, 9, 5, 15);
List<DMatch> matches = new ArrayList<DMatch>();
Converters.Mat_to_vector_DMatch(src, matches);
List<DMatch> truth = new ArrayList<DMatch>();
truth.add(new DMatch(1, 4, 4, 10));
truth.add(new DMatch(2, 3, 5, 6));
truth.add(new DMatch(3, 1, 8, 12));
truth.add(new DMatch(4, 9, 5, 15));
//assertListDMatchEquals(truth, matches, EPS);
fail("Not yet implemented");
}
public void testMat_to_vector_float() {
Mat src = new Mat(4, 1, CvType.CV_32FC1);
src.put(0, 0, 2, 4, 3, 9);
List<Float> fs = new ArrayList<Float>();
Converters.Mat_to_vector_float(src, fs);
List<Float> truth = new ArrayList<Float>();
truth.add(2.0f);
truth.add(4.0f);
truth.add(3.0f);
truth.add(9.0f);
assertListEquals(truth, fs, EPS);
}
public void testMat_to_vector_int() {
Mat src = new Mat(4, 1, CvType.CV_32SC1);
src.put(0, 0, 2, 4, 3, 9);
List<Integer> fs = new ArrayList<Integer>();
Converters.Mat_to_vector_int(src, fs);
List<Integer> truth = new ArrayList<Integer>();
truth.add(2);
truth.add(4);
truth.add(3);
truth.add(9);
assertListEquals(truth, fs);
}
public void testMat_to_vector_KeyPoint() {
Mat src = new Mat(1, 1, CvType.CV_64FC(7));
src.put(0, 0, 2, 4, 3, 9, 10, 12, 7);
List<KeyPoint> kps = new ArrayList<KeyPoint>();
Converters.Mat_to_vector_KeyPoint(src, kps);
List<KeyPoint> truth = new ArrayList<KeyPoint>();
truth.add(new KeyPoint(2, 4, 3, 9, 10, 12, 7));
assertListKeyPointEquals(truth, kps, EPS);
}
public void testMat_to_vector_Mat() {
// Mat src = new Mat(4, 1, CvType.CV_32SC2);
// src.put(0, 0, 2, 2, 3, 3, 4, 4, 5, 5);
//
// List<Mat> mats = new ArrayList<Mat>();
// Converters.Mat_to_vector_Mat(src, mats);
//
// List<Mat> truth = new ArrayList<Mat>();
// truth.add(new Mat(2, 1, CvType.CV_32SC1, Scalar.all(2.0)));
// truth.add(new Mat(2, 1, CvType.CV_32SC1, Scalar.all(3.0)));
// truth.add(new Mat(2, 1, CvType.CV_32SC1, Scalar.all(4.0)));
// truth.add(new Mat(2, 1, CvType.CV_32SC1, Scalar.all(5.0)));
// assertListEqualMat(truth, mats, EPS);
fail("Not yet implemented");
}
public void testMat_to_vector_Point() {
Mat src = new Mat(4, 1, CvType.CV_32SC2);
src.put(0, 0, 2, 4, 3, 9, 10, 4, 35, 54);
List<Point> points = new ArrayList<Point>();
Converters.Mat_to_vector_Point(src, points);
List<Point> truth = new ArrayList<Point>();
truth.add(new Point(2, 4));
truth.add(new Point(3, 9));
truth.add(new Point(10, 4));
truth.add(new Point(35, 54));
assertListPointEquals(truth, points, EPS);
}
public void testMat_to_vector_Point2d() {
Mat src = new Mat(4, 1, CvType.CV_64FC2);
src.put(0, 0, 12.0, 4.0, 3.0, 29.0, 10.0, 24.0, 35.0, 54.0);
List<Point> points = new ArrayList<Point>();
Converters.Mat_to_vector_Point2d(src, points);
List<Point> truth = new ArrayList<Point>();
truth.add(new Point(12.0, 4.0));
truth.add(new Point(3.0, 29.0));
truth.add(new Point(10.0, 24.0));
truth.add(new Point(35.0, 54.0));
assertListPointEquals(truth, points, EPS);
}
public void testMat_to_vector_Point2f() {
Mat src = new Mat(4, 1, CvType.CV_32FC2);
src.put(0, 0, 2, 14, 31, 19, 10, 44, 5, 41);
List<Point> points = new ArrayList<Point>();
Converters.Mat_to_vector_Point(src, points);
List<Point> truth = new ArrayList<Point>();
truth.add(new Point(2, 14));
truth.add(new Point(31, 19));
truth.add(new Point(10, 44));
truth.add(new Point(5, 41));
assertListPointEquals(truth, points, EPS);
}
public void testMat_to_vector_Point3() {
Mat src = new Mat(4, 1, CvType.CV_32SC3);
src.put(0, 0, 2, 14, 12, 31, 19, 22, 10, 44, 45, 5, 41, 31);
List<Point3> points = new ArrayList<Point3>();
Converters.Mat_to_vector_Point3(src, points);
List<Point3> truth = new ArrayList<Point3>();
truth.add(new Point3(2, 14, 12));
truth.add(new Point3(31, 19, 22));
truth.add(new Point3(10, 44, 45));
truth.add(new Point3(5, 41, 31));
assertListPoint3Equals(truth, points, EPS);
}
public void testMat_to_vector_Point3d() {
Mat src = new Mat(4, 1, CvType.CV_64FC3);
src.put(0, 0, 2.0, 4.0, 3.0, 5.0, 9.0, 12.0, 10.0, 14.0, 15.0, 5.0, 11.0, 31.0);
List<Point3> points = new ArrayList<Point3>();
Converters.Mat_to_vector_Point3(src, points);
List<Point3> truth = new ArrayList<Point3>();
truth.add(new Point3(2.0, 4.0, 3.0));
truth.add(new Point3(5.0, 9.0, 12.0));
truth.add(new Point3(10.0, 14.0, 15.0));
truth.add(new Point3(5.0, 11.0, 31.0));
assertListPoint3Equals(truth, points, EPS);
}
public void testMat_to_vector_Point3f() {
Mat src = new Mat(4, 1, CvType.CV_32FC3);
src.put(0, 0, 2.0, 4.0, 3.0, 5.0, 9.0, 12.0, 10.0, 14.0, 15.0, 5.0, 11.0, 31.0);
List<Point3> points = new ArrayList<Point3>();
Converters.Mat_to_vector_Point3(src, points);
List<Point3> truth = new ArrayList<Point3>();
truth.add(new Point3(2.0, 4.0, 3.0));
truth.add(new Point3(5.0, 9.0, 12.0));
truth.add(new Point3(10.0, 14.0, 15.0));
truth.add(new Point3(5.0, 11.0, 31.0));
assertListPoint3Equals(truth, points, EPS);
}
public void testMat_to_vector_Point3i() {
Mat src = new Mat(4, 1, CvType.CV_32SC3);
src.put(0, 0, 2, 14, 12, 31, 19, 22, 10, 44, 45, 5, 41, 31);
List<Point3> points = new ArrayList<Point3>();
Converters.Mat_to_vector_Point3(src, points);
List<Point3> truth = new ArrayList<Point3>();
truth.add(new Point3(2, 14, 12));
truth.add(new Point3(31, 19, 22));
truth.add(new Point3(10, 44, 45));
truth.add(new Point3(5, 41, 31));
assertListPoint3Equals(truth, points, EPS);
}
public void testMat_to_vector_Rect() {
Mat src = new Mat(2, 1, CvType.CV_32SC4);
src.put(0, 0, 2, 2, 5, 2, 0, 0, 6, 4);
List<Rect> rectangles = new ArrayList<Rect>();
Converters.Mat_to_vector_Rect(src, rectangles);
List<Rect> truth = new ArrayList<Rect>();
truth.add(new Rect(2, 2, 5, 2));
truth.add(new Rect(0, 0, 6, 4));
assertListRectEquals(truth, rectangles);
}
public void testMat_to_vector_RotatedRect() {
Mat src = new Mat(2, 1, CvType.CV_32FC(5));
src.put(0, 0, 2, 2, 5, 2, 7,
0, 6, 4, 1, 3);
List<RotatedRect> rectangles = new ArrayList<RotatedRect>();
Converters.Mat_to_vector_RotatedRect(src, rectangles);
List<RotatedRect> truth = new ArrayList<RotatedRect>();
truth.add(new RotatedRect(new Point(2, 2), new Size(5, 2), 7));
truth.add(new RotatedRect(new Point(0, 6), new Size(4, 1), 3));
assertListRotatedRectEquals(truth, rectangles);
}
public void testMat_to_vector_uchar() {
Mat src = new Mat(3, 1, CvType.CV_8UC1);
src.put(0, 0, 2, 4, 3);
List<Byte> bs = new ArrayList<Byte>();
Converters.Mat_to_vector_uchar(src, bs);
List<Byte> truth = new ArrayList<Byte>();
byte value1 = 2;
byte value2 = 4;
byte value3 = 3;
truth.add(Byte.valueOf(value1));
truth.add(Byte.valueOf(value2));
truth.add(Byte.valueOf(value3));
assertEquals(truth, bs);
}
public void testMat_to_vector_vector_char() {
fail("Not yet implemented");
}
public void testMat_to_vector_vector_DMatch() {
fail("Not yet implemented");
}
public void testMat_to_vector_vector_KeyPoint() {
fail("Not yet implemented");
}
public void testMat_to_vector_vector_Point2f() {
fail("Not yet implemented");
}
public void testVector_char_to_Mat() {
List<Byte> bytes = new ArrayList<Byte>();
byte value1 = 1;
byte value2 = 2;
byte value3 = 3;
byte value4 = 4;
bytes.add(Byte.valueOf(value1));
bytes.add(Byte.valueOf(value2));
bytes.add(Byte.valueOf(value3));
bytes.add(Byte.valueOf(value4));
dst = Converters.vector_char_to_Mat(bytes);
truth = new Mat(4, 1, CvType.CV_8SC1);
truth.put(0, 0, 1, 2, 3, 4);
assertMatEqual(truth, dst);
}
public void testVector_DMatch_to_Mat() {
List<DMatch> matches = new ArrayList<DMatch>();
matches.add(new DMatch(1, 4, 4, 10));
matches.add(new DMatch(2, 3, 5, 6));
matches.add(new DMatch(3, 1, 8, 12));
matches.add(new DMatch(4, 9, 5, 15));
dst = Converters.vector_DMatch_to_Mat(matches);
Mat truth = new Mat(4, 1, CvType.CV_64FC4);
truth.put(0, 0, 1, 4, 4, 10, 2, 3, 5, 6, 3, 1, 8, 12, 4, 9, 5, 15);
assertMatEqual(truth, dst, EPS);
}
public void testVector_double_to_Mat() {
List<Double> inputVector = new ArrayList<Double>();
inputVector.add(2.0);
inputVector.add(4.0);
inputVector.add(3.0);
inputVector.add(9.0);
dst = Converters.vector_double_to_Mat(inputVector);
truth = new Mat(4, 1, CvType.CV_64FC1);
truth.put(0, 0, 2, 4, 3, 9);
assertMatEqual(truth, dst, EPS);
}
public void testVector_float_to_Mat() {
List<Float> inputVector = new ArrayList<Float>();
inputVector.add(2.0f);
inputVector.add(4.0f);
inputVector.add(3.0f);
inputVector.add(9.0f);
dst = Converters.vector_float_to_Mat(inputVector);
truth = new Mat(4, 1, CvType.CV_32FC1);
truth.put(0, 0, 2, 4, 3, 9);
assertMatEqual(truth, dst, EPS);
}
public void testVector_int_to_Mat() {
List<Integer> inputVector = new ArrayList<Integer>();
inputVector.add(2);
inputVector.add(4);
inputVector.add(3);
inputVector.add(9);
dst = Converters.vector_int_to_Mat(inputVector);
truth = new Mat(4, 1, CvType.CV_32SC1);
truth.put(0, 0, 2, 4, 3, 9);
assertMatEqual(truth, dst);
}
public void testVector_KeyPoint_to_Mat() {
List<KeyPoint> kps = new ArrayList<KeyPoint>();
kps.add(new KeyPoint(2, 4, 3, 9, 10, 12, 7));
dst = Converters.vector_KeyPoint_to_Mat(kps);
Mat truth = new Mat(1, 1, CvType.CV_64FC(7));
truth.put(0, 0, 2, 4, 3, 9, 10, 12, 7);
assertMatEqual(truth, dst, EPS);
}
public void testVector_Mat_to_Mat() {
// List<Mat> mats = new ArrayList<Mat>();
// mats.add(new Mat(2, 1, CvType.CV_32SC1, Scalar.all(2.0)));
// mats.add(new Mat(2, 1, CvType.CV_32SC1, Scalar.all(2.0)));
// mats.add(new Mat(2, 1, CvType.CV_32SC1, Scalar.all(2.0)));
// mats.add(new Mat(2, 1, CvType.CV_32SC1, Scalar.all(2.0)));
// mats.add(gray0);
// mats.add(gray255);
//
// dst = Converters.vector_Mat_to_Mat(mats);
fail("Not yet implemented");
}
public void testVector_Point_to_Mat() {
List<Point> points = new ArrayList<Point>();
points.add(new Point(2, 4));
points.add(new Point(3, 9));
points.add(new Point(10, 4));
points.add(new Point(35, 54));
dst = Converters.vector_Point_to_Mat(points);
truth = new Mat(4, 1, CvType.CV_32SC2);
truth.put(0, 0, 2, 4, 3, 9, 10, 4, 35, 54);
assertMatEqual(truth, dst);
}
public void testVector_Point_to_MatListOfPoint() {
fail("Not yet implemented");
}
public void testVector_Point_to_MatListOfPointInt() {
fail("Not yet implemented");
}
public void testVector_Point2d_to_Mat() {
List<Point> points = new ArrayList<Point>();
points.add(new Point(12.0, 4.0));
points.add(new Point(3.0, 9.0));
points.add(new Point(1.0, 2.0));
dst = Converters.vector_Point2d_to_Mat(points);
truth = new Mat(3, 1, CvType.CV_64FC2);
truth.put(0, 0, 12.0, 4.0, 3.0, 9.0, 1.0, 2.0);
assertMatEqual(truth, dst, EPS);
}
public void testVector_Point2f_to_Mat() {
List<Point> points = new ArrayList<Point>();
points.add(new Point(2.0, 3.0));
points.add(new Point(1.0, 2.0));
points.add(new Point(1.0, 4.0));
dst = Converters.vector_Point2f_to_Mat(points);
truth = new Mat(3, 1, CvType.CV_32FC2);
truth.put(0, 0, 2.0, 3.0, 1.0, 2.0, 1.0, 4.0);
assertMatEqual(truth, dst, EPS);
}
public void testVector_Point3_to_Mat() {
List<Point3> points = new ArrayList<Point3>();
points.add(new Point3(2, 4, 3));
points.add(new Point3(5, 9, 12));
points.add(new Point3(10, 14, 15));
points.add(new Point3(5, 11, 31));
dst = Converters.vector_Point3_to_Mat(points, CvType.CV_32S);
truth = new Mat(4, 1, CvType.CV_32SC3);
truth.put(0, 0, 2.0, 4.0, 3.0, 5.0, 9.0, 12.0, 10.0, 14.0, 15.0, 5.0, 11.0, 31.0);
assertMatEqual(truth, dst);
}
public void testVector_Point3d_to_Mat() {
List<Point3> points = new ArrayList<Point3>();
points.add(new Point3(2.0, 4.0, 3.0));
points.add(new Point3(5.0, 9.0, 12.0));
points.add(new Point3(10.0, 14.0, 15.0));
points.add(new Point3(5.0, 11.0, 31.0));
dst = Converters.vector_Point3d_to_Mat(points);
truth = new Mat(4, 1, CvType.CV_64FC3);
truth.put(0, 0, 2.0, 4.0, 3.0, 5.0, 9.0, 12.0, 10.0, 14.0, 15.0, 5.0, 11.0, 31.0);
assertMatEqual(truth, dst, EPS);
}
public void testVector_Point3f_to_Mat() {
List<Point3> points = new ArrayList<Point3>();
points.add(new Point3(2.0, 4.0, 3.0));
points.add(new Point3(5.0, 9.0, 12.0));
points.add(new Point3(10.0, 14.0, 15.0));
points.add(new Point3(5.0, 11.0, 31.0));
dst = Converters.vector_Point3f_to_Mat(points);
truth = new Mat(4, 1, CvType.CV_32FC3);
truth.put(0, 0, 2.0, 4.0, 3.0, 5.0, 9.0, 12.0, 10.0, 14.0, 15.0, 5.0, 11.0, 31.0);
assertMatEqual(truth, dst, EPS);
}
public void testVector_Point3i_to_Mat() {
List<Point3> points = new ArrayList<Point3>();
points.add(new Point3(2, 4, 3));
points.add(new Point3(5, 6, 2));
points.add(new Point3(0, 4, 5));
points.add(new Point3(5, 1, 3));
dst = Converters.vector_Point3i_to_Mat(points);
truth = new Mat(4, 1, CvType.CV_32SC3);
truth.put(0, 0, 2, 4, 3, 5, 6, 2, 0, 4, 5, 5, 1, 3);
assertMatEqual(truth, dst);
}
public void testVector_Rect_to_Mat() {
List<Rect> rectangles = new ArrayList<Rect>();
rectangles.add(new Rect(2, 2, 5, 2));
rectangles.add(new Rect(0, 0, 6, 4));
dst = Converters.vector_Rect_to_Mat(rectangles);
truth = new Mat(2, 1, CvType.CV_32SC4);
truth.put(0, 0, 2, 2, 5, 2, 0, 0, 6, 4);
assertMatEqual(truth, dst);
}
public void testVector_RotatedRect_to_Mat() {
List<RotatedRect> rectangles = new ArrayList<RotatedRect>();
rectangles.add(new RotatedRect(new Point(2, 2), new Size(5, 2), 7));
rectangles.add(new RotatedRect(new Point(0, 0), new Size(6, 4), 3));
Mat dst = Converters.vector_RotatedRect_to_Mat(rectangles);
Mat truth = new Mat(2, 1, CvType.CV_32FC(5));
truth.put(0, 0, 2, 2, 5, 2, 7,
0, 0, 6, 4, 3);
assertMatEqual(truth, dst, EPS);
}
public void testVector_uchar_to_Mat() {
List<Byte> bytes = new ArrayList<Byte>();
byte value1 = 1;
byte value2 = 2;
byte value3 = 3;
byte value4 = 4;
bytes.add(Byte.valueOf(value1));
bytes.add(Byte.valueOf(value2));
bytes.add(Byte.valueOf(value3));
bytes.add(Byte.valueOf(value4));
dst = Converters.vector_uchar_to_Mat(bytes);
truth = new Mat(4, 1, CvType.CV_8UC1);
truth.put(0, 0, 1, 2, 3, 4);
assertMatEqual(truth, dst);
}
public void testVector_vector_char_to_Mat() {
fail("Not yet implemented");
}
public void testVector_vector_DMatch_to_Mat() {
fail("Not yet implemented");
}
public void testVector_vector_KeyPoint_to_Mat() {
fail("Not yet implemented");
}
public void testVector_vector_Point_to_Mat() {
fail("Not yet implemented");
}
}
@@ -0,0 +1,74 @@
if(NOT ANT_EXECUTABLE
OR NOT BUILD_opencv_imgcodecs
OR NOT BUILD_opencv_calib3d)
return()
endif()
project(opencv_test_java)
set(OPENCV_JAR_FILE "${OPENCV_JAR_FILE}")
get_filename_component(JAR_NAME "${OPENCV_JAR_FILE}" NAME)
set(OPENCV_JAVA_TEST_DIR "${OpenCV_BINARY_DIR}/java_test" CACHE INTERNAL "")
file(REMOVE_RECURSE "${OPENCV_JAVA_TEST_DIR}")
file(MAKE_DIRECTORY "${OPENCV_JAVA_TEST_DIR}")
file(REMOVE "${OPENCV_DEPHELPER}/${the_module}_test_source_copy")
set(test_dir ${CMAKE_CURRENT_SOURCE_DIR})
set(depends "")
# 1. gather and copy common test files (resources, utils, etc.)
copy_common_tests("${CMAKE_CURRENT_SOURCE_DIR}/../common_test" "${OPENCV_JAVA_TEST_DIR}" depends)
# 2. gather and copy tests from each module
ocv_copyfiles_append_dir(JAVA_TEST_SRC_COPY "${OPENCV_JAVA_BINDINGS_DIR}/gen/test" "${OPENCV_JAVA_TEST_DIR}/src")
list(APPEND depends gen_opencv_java_source "${OPENCV_DEPHELPER}/gen_opencv_java_source")
ocv_copyfiles_add_target(${the_module}_test_source_copy JAVA_TEST_SRC_COPY "Copy Java(Test) source files" ${depends})
set(depends ${the_module}_test_source_copy "${OPENCV_DEPHELPER}/${the_module}_test_source_copy")
# 3. gather and copy specific files for pure java
file(GLOB_RECURSE test_files RELATIVE "${test_dir}" "${test_dir}/src/*")
file(GLOB_RECURSE test_lib_files RELATIVE "${test_dir}" "${test_dir}/lib/*.jar")
foreach(f ${test_files} ${test_lib_files})
add_custom_command(OUTPUT "${OPENCV_JAVA_TEST_DIR}/${f}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${test_dir}/${f}" "${OPENCV_JAVA_TEST_DIR}/${f}"
DEPENDS "${test_dir}/${f}"
COMMENT "Copying ${f}"
)
list(APPEND depends "${test_dir}/${f}" "${OPENCV_JAVA_TEST_DIR}/${f}")
endforeach()
# Copy the OpenCV jar after it has been generated.
add_custom_command(OUTPUT "${OPENCV_JAVA_TEST_DIR}/bin/${JAR_NAME}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OPENCV_JAR_FILE}" "${OPENCV_JAVA_TEST_DIR}/bin/${JAR_NAME}"
DEPENDS "${OPENCV_JAR_FILE}" "${OPENCV_DEPHELPER}/${the_module}_jar"
COMMENT "Copying the OpenCV jar"
)
add_custom_command(OUTPUT "${OPENCV_JAVA_TEST_DIR}/build.xml"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/build.xml" "${OPENCV_JAVA_TEST_DIR}/build.xml"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/build.xml"
COMMENT "Copying build.xml"
)
add_custom_command(OUTPUT "${OPENCV_JAVA_TEST_DIR}/build/jar/opencv-test.jar"
COMMAND "${ANT_EXECUTABLE}" -noinput -k build
WORKING_DIRECTORY "${OPENCV_JAVA_TEST_DIR}"
DEPENDS ${depends} "${OPENCV_JAVA_TEST_DIR}/build.xml" "${CMAKE_CURRENT_SOURCE_DIR}/build.xml" "${OPENCV_JAR_FILE}" "${OPENCV_JAVA_TEST_DIR}/bin/${JAR_NAME}"
COMMENT "Build Java tests"
)
file(GENERATE OUTPUT "${OPENCV_JAVA_TEST_DIR}/ant-$<CONFIGURATION>.properties" CONTENT "opencv.lib.path=$<TARGET_FILE_DIR:${the_module}>")
add_custom_target(${PROJECT_NAME} ALL
DEPENDS ${the_module} "${OPENCV_JAVA_TEST_DIR}/build/jar/opencv-test.jar"
SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/build.xml"
)
if(ENABLE_SOLUTION_FOLDERS)
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER "tests accuracy")
endif()
add_dependencies(opencv_tests ${PROJECT_NAME})
+76
View File
@@ -0,0 +1,76 @@
<project name="OpenCV-Test">
<property environment="env"/>
<property file="ant-${opencv.build.type}.properties"/>
<property name="test.dir" value="testResults"/>
<property name="build.dir" value="build"/>
<property name="opencv.test.package" value="*"/>
<property name="opencv.test.class" value="*"/>
<property name="opencv.test.exclude" value=""/>
<path id="master-classpath">
<fileset dir="lib">
<include name="*.jar"/>
</fileset>
<fileset dir="bin">
<include name="*.jar"/>
</fileset>
</path>
<target name="clean">
<delete dir="build"/>
<delete dir="${test.dir}"/>
</target>
<target name="compile">
<mkdir dir="build/classes"/>
<javac sourcepath="" srcdir="src" destdir="build/classes" debug="on" includeantruntime="false" >
<include name="**/*.java"/>
<classpath refid="master-classpath"/>
</javac>
</target>
<target name="jar" depends="compile">
<mkdir dir="build/jar"/>
<jar destfile="build/jar/opencv-test.jar" basedir="build/classes">
<manifest>
<attribute name="Main-Class" value="org.opencv.test.OpenCVTestRunner"/>
</manifest>
</jar>
</target>
<target name="test" depends="jar">
<mkdir dir="${test.dir}"/>
<junit printsummary="withOutAndErr" failureproperty="junit_test.failed" haltonfailure="false" haltonerror="false" showoutput="true" logfailedtests="true" maxmemory="256m">
<sysproperty key="java.library.path" path="${opencv.lib.path}"/>
<env key="PATH" path="${opencv.lib.path}:${env.PATH}:${env.Path}"/>
<env key="DYLD_LIBRARY_PATH" path="${env.OPENCV_SAVED_DYLD_LIBRARY_PATH}"/> <!-- https://github.com/opencv/opencv/issues/14353 -->
<classpath refid="master-classpath"/>
<classpath>
<pathelement location="build/classes"/>
</classpath>
<formatter type="xml"/>
<batchtest fork="yes" todir="${test.dir}">
<zipfileset src="build/jar/opencv-test.jar" includes="**/${opencv.test.package}/${opencv.test.class}.class" excludes="**/OpenCVTest*, ${opencv.test.exclude}">
<exclude name="**/*$*.class"/>
</zipfileset>
</batchtest>
</junit>
<junitreport todir="${test.dir}">
<fileset dir="${test.dir}">
<include name="TEST-*.xml"/>
</fileset>
<report format="noframes" todir="${test.dir}"/>
</junitreport>
<fail message="JUnit test execution failed" if="junit_test.failed"/>
</target>
<target name="build" depends="jar">
</target>
<target name="buildAndTest" depends="test">
</target>
</project>
Binary file not shown.
@@ -0,0 +1,660 @@
// TODO: This file is largely a duplicate of the one in android_test.
package org.opencv.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.List;
import junit.framework.TestCase;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Point3;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.core.DMatch;
import org.opencv.core.KeyPoint;
import org.opencv.imgcodecs.Imgcodecs;
public class OpenCVTestCase extends TestCase {
public static class TestSkipException extends RuntimeException {
public TestSkipException() {}
}
//change to 'true' to unblock fail on fail("Not yet implemented")
public static final boolean passNYI = true;
protected static boolean isTestCaseEnabled = true;
protected static final String XFEATURES2D = "org.opencv.xfeatures2d.";
protected static final String DEFAULT_FACTORY = "create";
protected static final int matSize = 10;
protected static final double EPS = 0.001;
protected static final double weakEPS = 0.5;
private static final String TAG = "OpenCVTestCase";
protected Mat dst;
protected Mat truth;
protected Scalar colorBlack;
protected Scalar colorWhite;
// Naming notation: <channels info>_[depth]_[dimensions]_value
// examples: gray0 - single channel 8U 2d Mat filled with 0
// grayRnd - single channel 8U 2d Mat filled with random numbers
// gray0_32f_1d
// TODO: OpenCVTestCase refactorings
// - rename matrices
// - create methods gray0() and create src1 explicitly
// - create some masks
// - use truth member everywhere - remove truth from base class - each test
// fixture should use own truth filed
protected Mat gray0;
protected Mat gray1;
protected Mat gray2;
protected Mat gray3;
protected Mat gray9;
protected Mat gray127;
protected Mat gray128;
protected Mat gray255;
protected Mat grayRnd;
protected Mat gray_16u_256;
protected Mat gray_16s_1024;
protected Mat gray0_32f;
protected Mat gray1_32f;
protected Mat gray3_32f;
protected Mat gray9_32f;
protected Mat gray255_32f;
protected Mat grayE_32f;
protected Mat grayRnd_32f;
protected Mat gray0_32f_1d;
protected Mat gray0_64f;
protected Mat gray0_64f_1d;
protected Mat rgba0;
protected Mat rgba128;
protected Mat rgbLena;
protected Mat grayChess;
protected Mat gray255_32f_3d;
protected Mat v1;
protected Mat v2;
@Override
protected void setUp() throws Exception {
super.setUp();
try {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
} catch (SecurityException e) {
System.out.println(e.toString());
System.exit(-1);
} catch (UnsatisfiedLinkError e) {
System.out.println(e.toString());
System.exit(-1);
}
Core.setErrorVerbosity(false);
String pwd;
try {
pwd = new File(".").getCanonicalPath() + File.separator;
} catch (IOException e) {
System.out.println(e);
return;
}
OpenCVTestRunner.LENA_PATH = pwd + "res/drawable/lena.png";
OpenCVTestRunner.CHESS_PATH = pwd + "res/drawable/chessboard.jpg";
OpenCVTestRunner.LBPCASCADE_FRONTALFACE_PATH = pwd + "res/raw/lbpcascade_frontalface.xml";
assert(new File(OpenCVTestRunner.LENA_PATH).exists());
assert(new File(OpenCVTestRunner.CHESS_PATH).exists());
assert(new File(OpenCVTestRunner.LBPCASCADE_FRONTALFACE_PATH).exists());
dst = new Mat();
assertTrue(dst.empty());
truth = null;
colorBlack = new Scalar(0);
colorWhite = new Scalar(255, 255, 255);
gray0 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(0));
gray1 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(1));
gray2 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(2));
gray3 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(3));
gray9 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(9));
gray127 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(127));
gray128 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(128));
gray255 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(255));
grayRnd = new Mat(matSize, matSize, CvType.CV_8U);
Core.randu(grayRnd, 0, 256);
gray_16u_256 = new Mat(matSize, matSize, CvType.CV_16U, new Scalar(256));
gray_16s_1024 = new Mat(matSize, matSize, CvType.CV_16S, new Scalar(1024));
gray0_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(0.0));
gray1_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(1.0));
gray3_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(3.0));
gray9_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(9.0));
gray255_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(255.0));
grayE_32f = new Mat(matSize, matSize, CvType.CV_32F);
grayE_32f = Mat.eye(matSize, matSize, CvType.CV_32FC1);
grayRnd_32f = new Mat(matSize, matSize, CvType.CV_32F);
Core.randu(grayRnd_32f, 0, 256);
gray0_64f = new Mat(matSize, matSize, CvType.CV_64F, new Scalar(0.0));
gray0_32f_1d = new Mat(1, matSize, CvType.CV_32F, new Scalar(0.0));
gray0_64f_1d = new Mat(1, matSize, CvType.CV_64F, new Scalar(0.0));
rgba0 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(0));
rgba128 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(128));
rgbLena = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH);
grayChess = Imgcodecs.imread(OpenCVTestRunner.CHESS_PATH, Imgcodecs.IMREAD_GRAYSCALE);
gray255_32f_3d = new Mat(new int[]{matSize, matSize, matSize}, CvType.CV_32F, new Scalar(255.0));
v1 = new Mat(1, 3, CvType.CV_32F);
v1.put(0, 0, 1.0, 3.0, 2.0);
v2 = new Mat(1, 3, CvType.CV_32F);
v2.put(0, 0, 2.0, 1.0, 3.0);
}
@Override
protected void tearDown() throws Exception {
gray0.release();
gray1.release();
gray2.release();
gray3.release();
gray9.release();
gray127.release();
gray128.release();
gray255.release();
gray_16u_256.release();
gray_16s_1024.release();
grayRnd.release();
gray0_32f.release();
gray1_32f.release();
gray3_32f.release();
gray9_32f.release();
gray255_32f.release();
grayE_32f.release();
grayE_32f.release();
grayRnd_32f.release();
gray0_32f_1d.release();
gray0_64f.release();
gray0_64f_1d.release();
rgba0.release();
rgba128.release();
rgbLena.release();
grayChess.release();
gray255_32f_3d.release();
v1.release();
v2.release();
super.tearDown();
}
@Override
protected void runTest() throws Throwable {
// Do nothing if the precondition does not hold.
if (isTestCaseEnabled) {
try {
super.runTest();
} catch (TestSkipException ex) {
OpenCVTestRunner.Log(TAG + " :: " + "Test case \"" + this.getClass().getName() + "\" skipped!");
assertTrue(true);
}
} else {
OpenCVTestRunner.Log(TAG + " :: " + "Test case \"" + this.getClass().getName() + "\" disabled!");
}
}
public void runBare() throws Throwable {
Throwable exception = null;
try {
setUp();
} catch (TestSkipException ex) {
OpenCVTestRunner.Log(TAG + " :: " + "Test case \"" + this.getClass().getName() + "\" skipped!");
assertTrue(true);
return;
}
try {
runTest();
} catch (Throwable running) {
exception = running;
} finally {
try {
tearDown();
} catch (Throwable tearingDown) {
if (exception == null) exception = tearingDown;
}
}
if (exception != null) throw exception;
}
protected Mat getMat(int type, double... vals)
{
return new Mat(matSize, matSize, type, new Scalar(vals));
}
protected Mat makeMask(Mat m, double... vals)
{
m.submat(0, m.rows(), 0, m.cols() / 2).setTo(new Scalar(vals));
return m;
}
public static void fail(String msg) {
if(msg == "Not yet implemented" && passNYI)
return;
TestCase.fail(msg);
}
public static void assertGE(double v1, double v2) {
assertTrue("Failed: " + v1 + " >= " + v2, v1 >= v2);
}
public static <E extends Number> void assertListEquals(List<E> list1, List<E> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
if (!list1.isEmpty())
{
if (list1.get(0) instanceof Float || list1.get(0) instanceof Double)
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertEquals(list1.get(i), list2.get(i));
}
public static <E extends Number> void assertListEquals(List<E> list1, List<E> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertTrue(Math.abs(list1.get(i).doubleValue() - list2.get(i).doubleValue()) <= epsilon);
}
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertArrayEquals(byte[] ar1, byte[] ar2) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i]);
}
public static void assertArrayEquals(short[] ar1, short[] ar2) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i]);
}
public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i], epsilon);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertListMatEquals(List<Mat> list1, List<Mat> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertMatEqual(list1.get(i), list2.get(i), epsilon);
}
public static void assertListPointEquals(List<Point> list1, List<Point> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertPointEquals(list1.get(i), list2.get(i), epsilon);
}
public static void assertArrayPointsEquals(Point[] vp1, Point[] vp2, double epsilon) {
if (vp1.length != vp2.length) {
fail("Arrays have different sizes.");
}
for (int i = 0; i < vp1.length; i++)
assertPointEquals(vp1[i], vp2[i], epsilon);
}
public static void assertListPoint3Equals(List<Point3> list1, List<Point3> list2, double epsilon) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertPoint3Equals(list1.get(i), list2.get(i), epsilon);
}
public static void assertListRectEquals(List<Rect> list1, List<Rect> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertRectEquals(list1.get(i), list2.get(i));
}
public static void assertListRotatedRectEquals(List<RotatedRect> list1, List<RotatedRect> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertRotatedRectEquals(list1.get(i), list2.get(i));
}
public static void assertRectEquals(Rect expected, Rect actual) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x);
assertEquals(msg, expected.y, actual.y);
assertEquals(msg, expected.width, actual.width);
assertEquals(msg, expected.height, actual.height);
}
public static void assertRotatedRectEquals(RotatedRect expected, RotatedRect actual) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.center.x, actual.center.x);
assertEquals(msg, expected.center.y, actual.center.y);
assertEquals(msg, expected.size.width, actual.size.width);
assertEquals(msg, expected.size.height, actual.size.height);
assertEquals(msg, expected.angle, actual.angle);
}
public static void assertMatEqual(Mat m1, Mat m2) {
compareMats(m1, m2, true);
}
public static void assertMatNotEqual(Mat m1, Mat m2) {
compareMats(m1, m2, false);
}
public static void assertMatEqual(Mat expected, Mat actual, double eps) {
compareMats(expected, actual, eps, true);
}
public static void assertMatNotEqual(Mat expected, Mat actual, double eps) {
compareMats(expected, actual, eps, false);
}
public static void assertKeyPointEqual(KeyPoint expected, KeyPoint actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertTrue(msg, Math.hypot(expected.pt.x - actual.pt.x, expected.pt.y - actual.pt.y) < eps);
assertTrue(msg, Math.abs(expected.size - actual.size) < eps);
assertTrue(msg, Math.abs(expected.angle - actual.angle) < eps);
assertTrue(msg, Math.abs(expected.response - actual.response) < eps);
assertEquals(msg, expected.octave, actual.octave);
assertEquals(msg, expected.class_id, actual.class_id);
}
public static void assertListKeyPointEquals(List<KeyPoint> expected, List<KeyPoint> actual, double epsilon) {
assertEquals(expected.size(), actual.size());
for (int i = 0; i < expected.size(); i++)
assertKeyPointEqual(expected.get(i), actual.get(i), epsilon);
}
public static void assertDMatchEqual(DMatch expected, DMatch actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.queryIdx, actual.queryIdx);
assertEquals(msg, expected.trainIdx, actual.trainIdx);
assertEquals(msg, expected.imgIdx, actual.imgIdx);
assertTrue(msg, Math.abs(expected.distance - actual.distance) < eps);
}
public static void assertScalarEqual(Scalar expected, Scalar actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertTrue(msg, Math.abs(expected.val[0] - actual.val[0]) < eps);
assertTrue(msg, Math.abs(expected.val[1] - actual.val[1]) < eps);
assertTrue(msg, Math.abs(expected.val[2] - actual.val[2]) < eps);
assertTrue(msg, Math.abs(expected.val[3] - actual.val[3]) < eps);
}
public static void assertArrayDMatchEquals(DMatch[] expected, DMatch[] actual, double epsilon) {
assertEquals(expected.length, actual.length);
for (int i = 0; i < expected.length; i++)
assertDMatchEqual(expected[i], actual[i], epsilon);
}
public static void assertListDMatchEquals(List<DMatch> expected, List<DMatch> actual, double epsilon) {
DMatch expectedArray[] = expected.toArray(new DMatch[0]);
DMatch actualArray[] = actual.toArray(new DMatch[0]);
assertArrayDMatchEquals(expectedArray, actualArray, epsilon);
}
public static void assertPointEquals(Point expected, Point actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x, eps);
assertEquals(msg, expected.y, actual.y, eps);
}
public static void assertSizeEquals(Size expected, Size actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.width, actual.width, eps);
assertEquals(msg, expected.height, actual.height, eps);
}
public static void assertPoint3Equals(Point3 expected, Point3 actual, double eps) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x, eps);
assertEquals(msg, expected.y, actual.y, eps);
assertEquals(msg, expected.z, actual.z, eps);
}
static private boolean dimensionsEqual(Mat expected, Mat actual) {
if (expected.dims() != actual.dims()) {
return false;
}
if (expected.dims() > 2) {
for (int i = 0; i < expected.dims(); i++) {
if (expected.size(i) != actual.size(i)) {
return false;
}
}
return true;
} else {
return expected.cols() == actual.cols() && expected.rows() == actual.rows();
}
}
static private void compareMats(Mat expected, Mat actual, boolean isEqualityMeasured) {
if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
}
if (expected.depth() == CvType.CV_32F || expected.depth() == CvType.CV_64F) {
if (isEqualityMeasured)
throw new UnsupportedOperationException(
"Floating-point Mats must not be checked for exact match. Use assertMatEqual(Mat expected, Mat actual, double eps) instead.");
else
throw new UnsupportedOperationException(
"Floating-point Mats must not be checked for exact match. Use assertMatNotEqual(Mat expected, Mat actual, double eps) instead.");
}
Mat diff = new Mat();
Core.absdiff(expected, actual, diff);
Mat reshaped = diff.reshape(1);
int mistakes = Core.countNonZero(reshaped);
reshaped.release();
diff.release();
if (isEqualityMeasured)
assertTrue("Mats are different in " + mistakes + " points", 0 == mistakes);
else
assertFalse("Mats are equal", 0 == mistakes);
}
static private void compareMats(Mat expected, Mat actual, double eps, boolean isEqualityMeasured) {
if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
}
Mat diff = new Mat();
Core.absdiff(expected, actual, diff);
double maxDiff = Core.norm(diff, Core.NORM_INF);
if (isEqualityMeasured)
assertTrue("Max difference between expected and actual Mats is "+ maxDiff + ", that bigger than " + eps,
maxDiff <= eps);
else
assertFalse("Max difference between expected and actual Mats is "+ maxDiff + ", that less than " + eps,
maxDiff <= eps);
}
protected static String readFile(String path) {
try {
BufferedReader br = new BufferedReader(new FileReader(path));
String line;
StringBuffer result = new StringBuffer();
while ((line = br.readLine()) != null) {
result.append(line);
result.append("\n");
}
return result.toString();
} catch (IOException e) {
OpenCVTestRunner.Log("Failed to read file \"" + path
+ "\". Exception is thrown: " + e);
return null;
}
}
protected static void writeFile(String path, String content) {
FileOutputStream stream = null;
try {
stream = new FileOutputStream(new File(path));
FileChannel fc = stream.getChannel();
fc.write(Charset.defaultCharset().encode(content));
} catch (IOException e) {
OpenCVTestRunner.Log("Failed to write file \"" + path
+ "\". Exception is thrown: " + e);
} finally {
if (stream != null)
try {
stream.close();
} catch (IOException e) {
OpenCVTestRunner.Log("Exception is thrown: " + e);
}
}
}
protected <T> T createClassInstance(String cname, String factoryName, Class cParams[], Object oValues[]) {
T instance = null;
assertFalse("Class name should not be empty", "".equals(cname));
String message="";
try {
Class algClass = getClassForName(cname);
Method factory = null;
if(cParams!=null && cParams.length>0) {
if(!"".equals(factoryName)) {
factory = algClass.getDeclaredMethod(factoryName, cParams);
instance = (T) factory.invoke(null, oValues);
}
else {
instance = (T) algClass.getConstructor(cParams).newInstance(oValues);
}
}
else {
if(!"".equals(factoryName)) {
factory = algClass.getDeclaredMethod(factoryName);
instance = (T) factory.invoke(null);
}
else {
instance = (T) algClass.getConstructor().newInstance();
}
}
}
catch(Exception ex) {
if (cname.startsWith(XFEATURES2D))
{
throw new TestSkipException();
}
message = TAG + " :: " + "could not instantiate " + cname + "! Exception: " + ex.getMessage();
}
assertNotNull(message, instance);
return instance;
}
protected <T> void setProperty(T instance, String propertyName, String propertyType, Object propertyValue) {
String message = "";
try {
String smethod = "set" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
Method setter = instance.getClass().getMethod(smethod, getClassForName(propertyType));
setter.invoke(instance, propertyValue);
}
catch(Exception ex) {
message = "Error when setting property [" + propertyName + "]: " + ex.getMessage();
}
assertTrue(message, "".equals(message));
}
protected Class getClassForName(String sclass) throws ClassNotFoundException{
if("int".equals(sclass))
return Integer.TYPE;
else if("long".equals(sclass))
return Long.TYPE;
else if("double".equals(sclass))
return Double.TYPE;
else if("float".equals(sclass))
return Float.TYPE;
else if("boolean".equals(sclass))
return Boolean.TYPE;
else if("char".equals(sclass))
return Character.TYPE;
else if("byte".equals(sclass))
return Byte.TYPE;
else if("short".equals(sclass))
return Short.TYPE;
else
return Class.forName(sclass);
}
}
@@ -0,0 +1,43 @@
package org.opencv.test;
import java.io.File;
import java.io.IOException;
import org.opencv.core.Mat;
public class OpenCVTestRunner {
public static String LENA_PATH = "";
public static String CHESS_PATH = "";
public static String LBPCASCADE_FRONTALFACE_PATH = "";
private static String TAG = "opencv_test_java";
public static String getTempFileName(String extension)
{
if (!extension.startsWith("."))
extension = "." + extension;
try {
File tmp = File.createTempFile("OpenCV", extension);
String path = tmp.getAbsolutePath();
tmp.delete();
return path;
} catch (IOException e) {
Log("Failed to get temp file name. Exception is thrown: " + e);
}
return null;
}
static public void Log(String message) {
System.out.println(TAG + " :: " + message);
}
static public void Log(Mat m) {
System.out.println(TAG + " :: " + m + "\n " + m.dump());
}
public static String getOutputFileName(String name)
{
return getTempFileName(name);
}
}