diff --git a/android/build.gradle b/android/build.gradle index 84971aa..f8f47f3 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -10,7 +10,7 @@ buildscript { } dependencies { - classpath "com.android.tools.build:gradle:7.2.1" + classpath "com.android.tools.build:gradle:8.6.0" // noinspection DifferentKotlinGradleVersion classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } @@ -61,7 +61,7 @@ static def findNodeModules(baseDir) { } basePath = basePath.getParent() } - throw new GradleException("react-native-fast-tflite: Failed to find node_modules/ path!") + throw new GradleException("react-native-fast-opencv: Failed to find node_modules/ path!") } def nodeModules = findNodeModules(projectDir) @@ -86,7 +86,7 @@ android { buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() buildFeatures { - prefab=true + prefab = true } externalNativeBuild { @@ -94,7 +94,7 @@ android { arguments "-DANDROID_STL=c++_shared", "-DNODE_MODULES_DIR=${nodeModules}" cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all" - abiFilters (*reactNativeArchitectures()) + abiFilters(*reactNativeArchitectures()) } } } @@ -165,7 +165,7 @@ dependencies { // For < 0.71, this will be from the local maven repo // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin //noinspection GradleDynamicVersion - implementation "com.facebook.react:react-native:+" + implementation "com.facebook.react:react-android:0.74.4" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'org.opencv:opencv:4.9.0' } diff --git a/android/gradle.properties b/android/gradle.properties index aa4ed09..a14917d 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,6 @@ -FastOpencv_kotlinVersion=1.7.0 -FastOpencv_minSdkVersion=21 -FastOpencv_targetSdkVersion=31 -FastOpencv_compileSdkVersion=31 -FastOpencv_ndkversion=21.4.7075529 +FastOpencv_kotlinVersion=1.9.0 +FastOpencv_minSdkVersion=24 +FastOpencv_targetSdkVersion=34 +FastOpencv_compileSdkVersion=34 +FastOpencv_ndkVersion=21.4.7075529 +android.useAndroidX=true diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..2c35211 Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..09523c0 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 0000000..f5feea6 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 0000000..9d21a21 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/cpp/ConvertImage.cpp b/cpp/ConvertImage.cpp index efe3e19..ea50bc0 100644 --- a/cpp/ConvertImage.cpp +++ b/cpp/ConvertImage.cpp @@ -155,7 +155,7 @@ Mat ImageConverter::str2mat(const string& s) string decoded_string = base64_decode(s); vector data(decoded_string.begin(), decoded_string.end()); - cv::Mat img = imdecode(data, IMREAD_UNCHANGED); + cv::Mat img = cv::imdecode(data, IMREAD_UNCHANGED); return img; } diff --git a/cpp/FOCV_Function.cpp b/cpp/FOCV_Function.cpp index 04c26cc..befb05d 100644 --- a/cpp/FOCV_Function.cpp +++ b/cpp/FOCV_Function.cpp @@ -28,12 +28,12 @@ constexpr uint64_t hashString(const char* str, size_t length) { // General idea of invocation switch is from react-native-opencv3 library, // but it was adapted and optimized. -jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* arguments) { +jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count) { jsi::Object value(runtime); - FOCV_FunctionArguments args(runtime, arguments); + FOCV_FunctionArguments args(runtime, arguments, count); - std::string functionName = args.asString(0); + auto functionName = args.asString(0); try { switch (hashString(functionName.c_str(), functionName.size())) { @@ -49,18 +49,18 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto src2 = args.asMatPtr(2); auto dst = args.asMatPtr(3); - if(args.isNumber(5)) { + if (count > 4) { auto mask = args.asMatPtr(4); - auto dtype = args.asNumber(5); - - cv::add(*src1, *src2, *dst, *mask, dtype); - } else if(args.isObject(4)) { - auto mask = args.asMatPtr(4); - + if (count > 5) { + auto dtype = args.asNumber(5); + + cv::add(*src1, *src2, *dst, *mask, dtype); + break; + } cv::add(*src1, *src2, *dst, *mask); - } else { - cv::add(*src1, *src2, *dst); + break; } + cv::add(*src1, *src2, *dst); } break; case hashString("addWeighted", 11): { auto src1 = args.asMatPtr(1); @@ -70,13 +70,13 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto gamma = args.asNumber(5); auto dst = args.asMatPtr(6); - if(args.isNumber(7)) { + if (count > 7) { auto dtype = args.asNumber(7); cv::addWeighted(*src1, alpha, *src2, beta, gamma, *dst, dtype); - } else { - cv::addWeighted(*src1, alpha, *src2, beta, gamma, *dst); + break; } + cv::addWeighted(*src1, alpha, *src2, beta, gamma, *dst); } break; case hashString("batchDistance", 13): { auto src1 = args.asMatPtr(1); @@ -97,51 +97,51 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto src2 = args.asMatPtr(2); auto dst = args.asMatPtr(3); - if(args.isObject(4)) { + if (count > 4) { auto mask = args.asMatPtr(4); cv::bitwise_and(*src1, *src2, *dst, *mask); - } else { - cv::bitwise_and(*src1, *src2, *dst); + break; } + cv::bitwise_and(*src1, *src2, *dst); } break; case hashString("bitwise_not", 11): { - auto src1 = args.asMatPtr(1); + auto src = args.asMatPtr(1); auto dst = args.asMatPtr(2); - if(args.isObject(3)) { + if (count > 3) { auto mask = args.asMatPtr(3); - cv::bitwise_not(*src1, *dst, *mask); - } else { - cv::bitwise_not(*src1, *dst); + cv::bitwise_not(*src, *dst, *mask); + break; } + cv::bitwise_not(*src, *dst); } break; case hashString("bitwise_or", 10): { auto src1 = args.asMatPtr(1); auto src2 = args.asMatPtr(2); auto dst = args.asMatPtr(3); - if(args.isObject(4)) { + if (count > 4) { auto mask = args.asMatPtr(4); cv::bitwise_or(*src1, *src2, *dst, *mask); - } else { - cv::bitwise_or(*src1, *src2, *dst); + break; } + cv::bitwise_or(*src1, *src2, *dst); } break; case hashString("bitwise_xor", 11): { auto src1 = args.asMatPtr(1); auto src2 = args.asMatPtr(2); auto dst = args.asMatPtr(3); - if(args.isObject(4)) { + if (count > 4) { auto mask = args.asMatPtr(4); cv::bitwise_xor(*src1, *src2, *dst, *mask); - } else { - cv::bitwise_xor(*src1, *src2, *dst); + break; } + cv::bitwise_xor(*src1, *src2, *dst); } break; case hashString("borderInterpolate", 17): { auto p = args.asNumber(1); @@ -162,41 +162,30 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum cv::calcCovarMatrix((*samples).data(), nsamples, *covar, *mean, flags, dtype); } break; case hashString("cartToPolar", 11): { - if(args.isMat(1)) { + auto angleInDegrees = (count > 5) ? args.asBool(5) : false; + if (args.isMat(1)) { auto x = args.asMatPtr(1); auto y = args.asMatPtr(2); auto magnitude = args.asMatPtr(3); auto angle = args.asMatPtr(4); - if(args.isBool(5)) { - auto angleInDegrees = args.asBool(5); - - cv::cartToPolar(*x, *y, *magnitude, *angle, angleInDegrees); - } else { - cv::cartToPolar(*x, *y, *magnitude, *angle); - } + cv::cartToPolar(*x, *y, *magnitude, *angle, angleInDegrees); } else { auto x = args.asMatVectorPtr(1); auto y = args.asMatVectorPtr(2); auto magnitude = args.asMatVectorPtr(3); auto angle = args.asMatVectorPtr(4); - if(args.isBool(5)) { - auto angleInDegrees = args.asBool(5); - - cv::cartToPolar(*x, *y, *magnitude, *angle, angleInDegrees); - } else { - cv::cartToPolar(*x, *y, *magnitude, *angle); - } + cv::cartToPolar(*x, *y, *magnitude, *angle, angleInDegrees); } } break; case hashString("checkRange", 10): { auto quiet = args.asBool(2); auto pos = args.asPointPtr(3); - auto minVal = args.asNumber(2); - auto maxVal = args.asNumber(2); + auto minVal = args.asNumber(4); + auto maxVal = args.asNumber(5); - if(args.isMat(1)) { + if (args.isMat(1)) { auto a = args.asMatPtr(1); cv::checkRange(*a, quiet, &(*pos), minVal, maxVal); } else { @@ -215,7 +204,7 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum case hashString("completeSymm", 12): { auto lowerToUpper = args.asBool(2); - if(args.isMat(1)) { + if (args.isMat(1)) { auto m = args.asMatPtr(1); cv::completeSymm(*m, lowerToUpper); } else { @@ -233,18 +222,18 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto src = args.asMatPtr(1); auto dst = args.asMatPtr(2); - if(args.isNumber(4)) { - auto alpha = args.asNumber(3); - auto beta = args.asNumber(4); - - cv::convertScaleAbs(*src, *dst, alpha, beta); - } else if(args.isNumber(3)) { + if (count > 3) { auto alpha = args.asNumber(3); - + if (count > 4) { + auto beta = args.asNumber(4); + + cv::convertScaleAbs(*src, *dst, alpha, beta); + break; + } cv::convertScaleAbs(*src, *dst, alpha); - } else { - cv::convertScaleAbs(*src, *dst); + break; } + cv::convertScaleAbs(*src, *dst); } break; case hashString("copyMakeBorder", 14): { auto src = args.asMatPtr(1); @@ -266,7 +255,7 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum cv::copyTo(*src, *dst, *mask); } break; case hashString("countNonZero", 12): { - if(args.isMat(1)) { + if (args.isMat(1)) { auto src = args.asMatPtr(1); auto result = cv::countNonZero(*src); value.setProperty(runtime, "value", result); @@ -310,13 +299,13 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto dst = args.asMatPtr(3); auto scale = args.asNumber(4); - if(args.isNumber(5)) { + if (count > 5) { auto dtype = args.asNumber(5); cv::divide(*src1, *src2, *dst, scale, dtype); - } else { - cv::divide(*src1, *src2, *dst, scale); + break; } + cv::divide(*src1, *src2, *dst, scale); } break; case hashString("eigen", 5): { auto src = args.asMatPtr(1); @@ -348,7 +337,7 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum case hashString("findNonZero", 11): { auto src = args.asMatPtr(1); - if(args.isMat(2)) { + if (args.isMat(2)) { auto idx = args.asMatPtr(2); cv::findNonZero(*src, *idx); } else { @@ -445,7 +434,7 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum case hashString("magnitude", 9): { auto magnitude = args.asMatPtr(3); - if(args.isMat(1)) { + if (args.isMat(1)) { auto x = args.asMatPtr(1); auto y = args.asMatPtr(2); cv::magnitude(*x, *y, *magnitude); @@ -458,7 +447,7 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum case hashString("Mahalanobis", 11): { auto icovar = args.asMatPtr(3); - if(args.isMat(1)) { + if (args.isMat(1)) { auto x = args.asMatPtr(1); auto y = args.asMatPtr(2); cv::Mahalanobis(*x, *y, *icovar); @@ -476,17 +465,17 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum cv::max(*src1, *src2, *dst); } break; case hashString("mean", 4): { + std::string id; auto src = args.asMatPtr(1); - std::string id = ""; - if(args.isObject(2)) { + if (count > 2) { auto mask = args.asMatPtr(2); auto scalar = cv::mean(*src, *mask); - std::string id = FOCV_Storage::save(scalar); + id = FOCV_Storage::save(scalar); } else { auto scalar = cv::mean(*src); - std::string id = FOCV_Storage::save(scalar); + id = FOCV_Storage::save(scalar); } return FOCV_JsiObject::wrap(runtime, "scalar", id); @@ -496,13 +485,13 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto mean = args.asMatPtr(2); auto stddev = args.asMatPtr(3); - if(args.isObject(4)) { + if (count > 4) { auto mask = args.asMatPtr(4); cv::meanStdDev(*src, *mean, *stddev, *mask); - } else { - cv::meanStdDev(*src, *mean, *stddev); + break; } + cv::meanStdDev(*src, *mean, *stddev); } break; case hashString("min", 3): { auto src1 = args.asMatPtr(1); @@ -516,11 +505,10 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum double min = 0; double max = 0; - if(args.isObject(2)) { + if (count > 2) { auto mask = args.asMatPtr(2); cv::minMaxIdx(*src, &min, &max, NULL, NULL, *mask); - } else { cv::minMaxIdx(*src, &min, &max); } @@ -534,13 +522,13 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto c = args.asMatPtr(3); auto flags = args.asNumber(4); - if(args.isBool(5)) { + if (count > 5) { auto conjB = args.asBool(5); cv::mulSpectrums(*a, *b, *c, flags, conjB); - } else { - cv::mulSpectrums(*a, *b, *c, flags); + break; } + cv::mulSpectrums(*a, *b, *c, flags); } break; case hashString("multiply", 8): { auto src1 = args.asMatPtr(1); @@ -548,13 +536,13 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto dst = args.asMatPtr(3); auto scale = args.asNumber(4); - if(args.isNumber(5)) { + if (count > 5) { auto dtype = args.asNumber(5); cv::multiply(*src1, *src2, *dst, scale, dtype); - } else { - cv::multiply(*src1, *src2, *dst, scale); + break; } + cv::multiply(*src1, *src2, *dst, scale); } break; case hashString("mulTransposed", 13): { auto src = args.asMatPtr(1); @@ -563,21 +551,22 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto delta = args.asMatPtr(4); auto scale = args.asNumber(5); - if(args.isNumber(6)) { + if (count > 6) { auto dtype = args.asNumber(6); cv::mulTransposed(*src, *dst, aTa, *delta, scale, dtype); - } else { - cv::mulTransposed(*src, *dst, aTa, *delta, scale); + break; } + cv::mulTransposed(*src, *dst, aTa, *delta, scale); } break; case hashString("norm", 4): { auto src = args.asMatPtr(1); auto normType = args.asNumber(2); double norm = 0; - if(args.isObject(3)) { + if (count > 3) { auto mask = args.asMatPtr(3); + norm = cv::norm(*src, normType, *mask); } else { norm = cv::norm(*src, normType); @@ -596,7 +585,7 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum case hashString("patchNaNs", 9): { auto alpha = args.asNumber(2); - if(args.isMat(1)) { + if (args.isMat(1)) { auto a = args.asMatPtr(1); cv::patchNaNs(*a, alpha); } else { @@ -615,7 +604,7 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto angle = args.asMatPtr(3); auto angleInDegrees = args.asBool(4); - if(args.isMat(1)) { + if (args.isMat(1)) { auto x = args.asMatPtr(1); auto y = args.asMatPtr(2); cv::phase(*x, *y, *angle, angleInDegrees); @@ -727,23 +716,23 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto src2 = args.asMatPtr(2); auto dst = args.asMatPtr(3); - if(args.isNumber(5)) { + if (count > 4) { auto mask = args.asMatPtr(4); - auto dtype = args.asNumber(5); - - cv::subtract(*src1, *src2, *dst, *mask, dtype); - } else if(args.isObject(4)) { - auto mask = args.asMatPtr(4); - + if (count > 5) { + auto dtype = args.asNumber(5); + + cv::subtract(*src1, *src2, *dst, *mask, dtype); + break; + } cv::subtract(*src1, *src2, *dst, *mask); - } else { - cv::subtract(*src1, *src2, *dst); + break; } + cv::subtract(*src1, *src2, *dst); } break; case hashString("sum", 3): { - std::string id = ""; + std::string id; - if(args.isMat(1)) { + if (args.isMat(1)) { auto src = args.asMatPtr(1); auto scalar = cv::sum(*src); id = FOCV_Storage::save(scalar); @@ -787,13 +776,13 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto dst = args.asMatPtr(2); auto code = args.asNumber(3); - if(args.isNumber(4)) { + if (count > 4) { auto dsnCn = args.asNumber(4); cv::cvtColor(*src, *dst, code, dsnCn); - } else { - cv::cvtColor(*src, *dst, code); + break; } + cv::cvtColor(*src, *dst, code); } break; case hashString("cvtColorTwoPlane", 16): { auto src1 = args.asMatPtr(1); @@ -808,13 +797,13 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto dst = args.asMatPtr(2); auto code = args.asNumber(3); - if(args.isNumber(4)) { + if (count > 4) { auto dsnCn = args.asNumber(4); cv::demosaicing(*src, *dst, code, dsnCn); - } else { - cv::demosaicing(*src, *dst, code); + break; } + cv::demosaicing(*src, *dst, code); } break; case hashString("applyColorMap", 13): { auto src = args.asMatPtr(1); @@ -971,18 +960,18 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto dp = args.asNumber(4); auto minDist = args.asNumber(5); - if(args.isNumber(7)) { - auto param1 = args.asNumber(6); - auto param2 = args.asNumber(7); - - cv::HoughCircles(*image, *circles, method, dp, minDist, param1, param2); - } else if(args.isNumber(6)) { + if (count > 6) { auto param1 = args.asNumber(6); - + if (count > 7) { + auto param2 = args.asNumber(7); + + cv::HoughCircles(*image, *circles, method, dp, minDist, param1, param2); + break; + } cv::HoughCircles(*image, *circles, method, dp, minDist, param1); - } else { - cv::HoughCircles(*image, *circles, method, dp, minDist); + break; } + cv::HoughCircles(*image, *circles, method, dp, minDist); } break; case hashString("HoughLines", 10): { auto image = args.asMatPtr(1); @@ -1079,19 +1068,17 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto ksize = args.asSizePtr(3); auto sigmaX = args.asNumber(4); - if(args.isNumber(5)) { + if (count > 5) { auto sigmaY = args.asNumber(5); - - if(args.isNumber(6)) { + if (count > 6) { auto borderType = args.asNumber(6); + cv::GaussianBlur(*src, *dst, *ksize, sigmaX, sigmaY, borderType); break; } - cv::GaussianBlur(*src, *dst, *ksize, sigmaX, sigmaY); break; } - cv::GaussianBlur(*src, *dst, *ksize, sigmaX); } break; case hashString("getGaborKernel", 14): { @@ -1130,17 +1117,17 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum } break; case hashString("getStructuringElement", 21): { std::string id; - auto shape = args.asNumber(1); auto ksize = args.asSizePtr(2); - if (args.isObject(3) && args.isPoint(3)) { + if (count > 3) { auto anchor = args.asPointPtr(3); - cv::Mat result = cv::getStructuringElement(shape, *ksize, *anchor); - id = FOCV_Storage::save(result); + + cv::Mat result = cv::getStructuringElement(shape, *ksize, *anchor); + id = FOCV_Storage::save(result); } else { - cv::Mat result = cv::getStructuringElement(shape, *ksize); - id = FOCV_Storage::save(result); + cv::Mat result = cv::getStructuringElement(shape, *ksize); + id = FOCV_Storage::save(result); } return FOCV_JsiObject::wrap(runtime, "mat", id); @@ -1175,33 +1162,27 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto op = args.asNumber(3); auto kernel = args.asMatPtr(4); - if(args.isObject(5) && args.isPoint(5)) { + if (count > 5) { auto anchor = args.asPointPtr(5); - - if(args.isNumber(6)) { + if (count > 6) { auto iterations = args.asNumber(6); - - if(args.isNumber(7)) { + if (count > 7) { auto borderType = args.asNumber(7); - - if(args.isObject(8) && args.isScalar(8)) { + if (count > 8) { auto borderValue = args.asScalarPtr(8); + cv::morphologyEx(*src, *dst, op, *kernel, *anchor, iterations, borderType, *borderValue); break; } - cv::morphologyEx(*src, *dst, op, *kernel, *anchor, iterations, borderType); break; } - cv::morphologyEx(*src, *dst, op, *kernel, *anchor, iterations); break; } - cv::morphologyEx(*src, *dst, op, *kernel, *anchor); break; } - cv::morphologyEx(*src, *dst, op, *kernel); } break; case hashString("adaptiveThreshold", 17): { @@ -1251,6 +1232,42 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum cv::threshold(*src, *dst, thresh, maxval, type); } break; + case hashString("calcOpticalFlowPyrLK", 20): { + auto prevImg = args.asMatPtr(1); + auto nextImg = args.asMatPtr(2); + auto prevPts = args.asMatPtr(3); + auto nextPts = args.asMatPtr(4); + auto status = args.asMatPtr(5); + auto err = args.asMatPtr(6); + + if (count > 7) { + auto winSize = args.asSizePtr(7); + if (count > 8) { + auto maxLevel = args.asNumber(8); + if (count > 9) { + auto termCriteria = args.asTermCriteriaPtr(9); + if (count > 10) { + auto flags = args.asNumber(10); + if (count > 11) { + auto minEigThreshold = args.asNumber(11); + + cv::calcOpticalFlowPyrLK(*prevImg, *nextImg, *prevPts, *nextPts, *status, *err, *winSize, maxLevel, *termCriteria, flags, minEigThreshold); + break; + } + cv::calcOpticalFlowPyrLK(*prevImg, *nextImg, *prevPts, *nextPts, *status, *err, *winSize, maxLevel, *termCriteria, flags); + break; + } + cv::calcOpticalFlowPyrLK(*prevImg, *nextImg, *prevPts, *nextPts, *status, *err, *winSize, maxLevel, *termCriteria); + break; + } + cv::calcOpticalFlowPyrLK(*prevImg, *nextImg, *prevPts, *nextPts, *status, *err, *winSize, maxLevel); + break; + } + cv::calcOpticalFlowPyrLK(*prevImg, *nextImg, *prevPts, *nextPts, *status, *err, *winSize); + break; + } + cv::calcOpticalFlowPyrLK(*prevImg, *nextImg, *prevPts, *nextPts, *status, *err); + } break; case hashString("matchTemplate", 13): { auto image = args.asMatPtr(1); auto templ = args.asMatPtr(2); @@ -1260,11 +1277,30 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum cv::matchTemplate(*image, *templ, *result, method, *mask); } break; + case hashString("phaseCorrelate", 14): { + std::string id; + auto src1 = args.asMatPtr(1); + auto src2 = args.asMatPtr(2); + double response = 0; + + if (count > 3) { + auto window = args.asMatPtr(3); + + cv::Point2f result = cv::phaseCorrelate(*src1, *src2, *window, &response); + id = FOCV_Storage::save(result); + } else { + cv::Point2f result = cv::phaseCorrelate(*src1, *src2, cv::noArray(), &response); + id = FOCV_Storage::save(result); + } + + value.setProperty(runtime, "phaseShift", FOCV_JsiObject::wrap(runtime, "point2f", id)); + value.setProperty(runtime, "response", jsi::Value(response)); + } break; case hashString("approxPolyDP", 12): { auto epsilon = args.asNumber(3); auto closed = args.asBool(4); - if(args.isMat(1)) { + if (args.isMat(1)) { auto curve = args.asMatPtr(1); if (args.isMat(2)) { auto approxCurve = args.asMatPtr(2); @@ -1296,26 +1332,26 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum case hashString("arcLength", 9): { auto closed = args.asBool(2); - if(args.isMat(1)) { + if (args.isMat(1)) { auto curve = args.asMatPtr(1); auto result = cv::arcLength(*curve, closed); value.setProperty(runtime, "value", jsi::Value(result)); - } else if(args.isMatVector(1)) { - auto curve = args.asMatVectorPtr(1); - auto result = cv::arcLength(*curve, closed); - value.setProperty(runtime, "value", jsi::Value(result)); + } else if (args.isMatVector(1)) { + auto curve = args.asMatVectorPtr(1); + auto result = cv::arcLength(*curve, closed); + value.setProperty(runtime, "value", jsi::Value(result)); } else { - auto curve = args.asPointVectorPtr(1); - auto result = cv::arcLength(*curve, closed); - value.setProperty(runtime, "value", jsi::Value(result)); + auto curve = args.asPointVectorPtr(1); + auto result = cv::arcLength(*curve, closed); + value.setProperty(runtime, "value", jsi::Value(result)); } } break; case hashString("boundingRect", 12): { cv::Rect rect; - if(args.isMat(1)) { + if (args.isMat(1)) { rect = cv::boundingRect(*args.asMatPtr(1)); - } else if(args.isMatVector(1)) { + } else if (args.isMatVector(1)) { rect = cv::boundingRect(*args.asMatVectorPtr(1)); } else { rect = cv::boundingRect(*args.asPointVectorPtr(1)); @@ -1342,9 +1378,9 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum value.setProperty(runtime, "value", jsi::Value(result)); } break; case hashString("contourArea", 11): { - auto oriented = args.asBool(2); + auto oriented = (count > 2) ? args.asBool(2) : false; - if(args.isMat(1)) { + if (args.isMat(1)) { auto src = args.asMatPtr(1); value.setProperty(runtime, "value", contourArea(*src, oriented)); } else { @@ -1370,7 +1406,7 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto mode = args.asNumber(3); auto method = args.asNumber(4); - if(args.isMatVector(2)) { + if (args.isMatVector(2)) { auto dst = args.asMatVectorPtr(2); cv::findContours(*src, *dst, mode, method); } else { @@ -1414,7 +1450,18 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum auto src = args.asMatPtr(1); auto dst = args.asMatPtr(2); auto rtype = args.asNumber(3); - + + if (count > 4) { + auto alpha = args.asNumber(4); + if (count > 5) { + auto beta = args.asNumber(5); + + (*src).convertTo(*dst, rtype, alpha, beta); + break; + } + (*src).convertTo(*dst, rtype, alpha); + break; + } (*src).convertTo(*dst, rtype); } break; case hashString("warpPerspective", 15): { @@ -1430,7 +1477,9 @@ jsi::Object FOCV_Function::invoke(jsi::Runtime& runtime, const jsi::Value* argum } break; } } catch (cv::Exception& e) { - std::cout << "Fast OpenCV Invoke Error: " << e.what() << "\n"; + std::string message(e.what()); + std::cout << "Fast OpenCV Invoke Error: " << message << "\n"; + throw std::runtime_error("Fast OpenCV Error: " + message); } return value; diff --git a/cpp/FOCV_Function.hpp b/cpp/FOCV_Function.hpp index a6838fe..6b7e45e 100644 --- a/cpp/FOCV_Function.hpp +++ b/cpp/FOCV_Function.hpp @@ -30,7 +30,7 @@ using namespace facebook; class FOCV_Function { public: - static jsi::Object invoke(jsi::Runtime& runtime, const jsi::Value* arguments); + static jsi::Object invoke(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count); }; diff --git a/cpp/FOCV_FunctionArguments.cpp b/cpp/FOCV_FunctionArguments.cpp index 29ce990..90044ea 100644 --- a/cpp/FOCV_FunctionArguments.cpp +++ b/cpp/FOCV_FunctionArguments.cpp @@ -10,97 +10,183 @@ #include "FOCV_Storage.hpp" #include "FOCV_JsiObject.hpp" -FOCV_FunctionArguments::FOCV_FunctionArguments(jsi::Runtime& runtime, const jsi::Value* arguments) { +FOCV_FunctionArguments::FOCV_FunctionArguments(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count) { this->arguments = arguments; this->runtime = &runtime; + this->count = count; } double FOCV_FunctionArguments::asNumber(int index) { + if (!this->isNumber(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a number!"); + } return this->arguments[index].asNumber(); } bool FOCV_FunctionArguments::asBool(int index) { + if (!this->isBool(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a boolean!"); + } return this->arguments[index].asBool(); } std::string FOCV_FunctionArguments::asString(int index) { + if (!this->isString(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a string!"); + } return this->arguments[index].asString(*this->runtime).utf8(*this->runtime); } std::shared_ptr FOCV_FunctionArguments::asMatPtr(int index) { + if (!this->isMat(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a Mat!"); + } return FOCV_Storage::get(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } std::shared_ptr> FOCV_FunctionArguments::asMatVectorPtr(int index) { + if (!this->isMatVector(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a MatVector!"); + } return FOCV_Storage::get>(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } std::shared_ptr FOCV_FunctionArguments::asPointPtr(int index) { + if (!this->isPoint(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a Point!"); + } return FOCV_Storage::get(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } std::shared_ptr> FOCV_FunctionArguments::asPointVectorPtr(int index) { + if (!this->isPointVector(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a PointVector!"); + } return FOCV_Storage::get>(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } std::shared_ptr> FOCV_FunctionArguments::asPoint2fVectorPtr(int index) { + if (!this->isPoint2fVector(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a Point2fVector!"); + } return FOCV_Storage::get>(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } std::shared_ptr>> FOCV_FunctionArguments::asPointVectorOfVectorsPtr(int index) { + if (!this->isPointVectorOfVectors(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a PointVectorOfVectors!"); + } return FOCV_Storage::get>>(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } std::shared_ptr FOCV_FunctionArguments::asRectPtr(int index) { + if (!this->isRect(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a Rect!"); + } return FOCV_Storage::get(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } std::shared_ptr> FOCV_FunctionArguments::asRectVectorPtr(int index) { + if (!this->isRectVector(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a RectVector!"); + } return FOCV_Storage::get>(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } std::shared_ptr FOCV_FunctionArguments::asSizePtr(int index) { + if (!this->isSize(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a Size!"); + } return FOCV_Storage::get(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } std::shared_ptr FOCV_FunctionArguments::asScalarPtr(int index) { + if (!this->isScalar(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a Scalar!"); + } return FOCV_Storage::get(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } std::shared_ptr FOCV_FunctionArguments::asRotatedRectPtr(int index) { + if (!this->isRotatedRect(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a RotatedRect!"); + } return FOCV_Storage::get(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); } +std::shared_ptr FOCV_FunctionArguments::asTermCriteriaPtr(int index) { + if (!this->isTermCriteria(index)) { + throw std::runtime_error("Fast OpenCV Error: Argument (" + std::to_string(index) + ") is not a TermCriteria!"); + } + return FOCV_Storage::get(FOCV_JsiObject::id_from_wrap(*this->runtime, arguments[index])); +} + bool FOCV_FunctionArguments::isNumber(int index) { + this->assertIndex(index); return this->arguments[index].isNumber(); } bool FOCV_FunctionArguments::isBool(int index) { + this->assertIndex(index); return this->arguments[index].isBool(); } bool FOCV_FunctionArguments::isString(int index) { + this->assertIndex(index); return this->arguments[index].isString(); } bool FOCV_FunctionArguments::isObject(int index) { + this->assertIndex(index); return this->arguments[index].isObject(); } bool FOCV_FunctionArguments::isMat(int index) { - return FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "mat"; + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "mat"; } bool FOCV_FunctionArguments::isMatVector(int index) { - return FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "mat_vector"; + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "mat_vector"; } bool FOCV_FunctionArguments::isPoint(int index) { - return FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "point"; + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "point"; +} + +bool FOCV_FunctionArguments::isPointVector(int index) { + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "point_vector"; +} + +bool FOCV_FunctionArguments::isPoint2fVector(int index) { + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "point2f_vector"; +} + +bool FOCV_FunctionArguments::isPointVectorOfVectors(int index) { + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "point_vector_vector"; +} + +bool FOCV_FunctionArguments::isRect(int index) { + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "rect"; +} + +bool FOCV_FunctionArguments::isRectVector(int index) { + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "rect_vector"; +} + +bool FOCV_FunctionArguments::isSize(int index) { + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "size"; } bool FOCV_FunctionArguments::isScalar(int index) { - return FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "scalar"; + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "scalar"; +} + +bool FOCV_FunctionArguments::isRotatedRect(int index) { + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "rotated_rect"; +} + +bool FOCV_FunctionArguments::isTermCriteria(int index) { + return this->isObject(index) && FOCV_JsiObject::type_from_wrap(*this->runtime, arguments[index]) == "term_criteria"; } diff --git a/cpp/FOCV_FunctionArguments.hpp b/cpp/FOCV_FunctionArguments.hpp index 038d019..545a5d3 100644 --- a/cpp/FOCV_FunctionArguments.hpp +++ b/cpp/FOCV_FunctionArguments.hpp @@ -32,13 +32,20 @@ class FOCV_FunctionArguments { private: const jsi::Value* arguments; jsi::Runtime* runtime; + size_t count; + + inline void assertIndex(int index) { + if (index < 0 || index >= count) { + throw std::runtime_error("Fast OpenCV Error: Argument index (" + std::to_string(index) + ") is out of bounds!"); + } + } public: - FOCV_FunctionArguments(jsi::Runtime& runtime, const jsi::Value* arguments); + FOCV_FunctionArguments(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count); + double asNumber(int index); bool asBool(int index); std::string asString(int index); - std::shared_ptr asMatPtr(int index); std::shared_ptr> asMatVectorPtr(int index); std::shared_ptr asPointPtr(int index); @@ -50,6 +57,7 @@ class FOCV_FunctionArguments { std::shared_ptr asSizePtr(int index); std::shared_ptr asScalarPtr(int index); std::shared_ptr asRotatedRectPtr(int index); + std::shared_ptr asTermCriteriaPtr(int index); bool isNumber(int index); bool isBool(int index); @@ -58,7 +66,15 @@ class FOCV_FunctionArguments { bool isMat(int index); bool isMatVector(int index); bool isPoint(int index); + bool isPointVector(int index); + bool isPoint2fVector(int index); + bool isPointVectorOfVectors(int index); + bool isRect(int index); + bool isRectVector(int index); + bool isSize(int index); bool isScalar(int index); + bool isRotatedRect(int index); + bool isTermCriteria(int index); }; #endif /* FOCV_FunctionArguments_hpp */ diff --git a/cpp/FOCV_Object.cpp b/cpp/FOCV_Object.cpp index 3a249c9..82dde62 100644 --- a/cpp/FOCV_Object.cpp +++ b/cpp/FOCV_Object.cpp @@ -29,84 +29,80 @@ constexpr uint64_t hashString(const char* str, size_t length) { return hash; } -jsi::Object FOCV_Object::create(jsi::Runtime& runtime, const jsi::Value* arguments) { - std::string id = ""; +jsi::Object FOCV_Object::create(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count) { + std::string id; std::string objectType = arguments[0].asString(runtime).utf8(runtime); switch(hashString(objectType.c_str(), objectType.size())) { case hashString("mat", 3): { - int rows = arguments[1].asNumber(); - int cols = arguments[2].asNumber(); - int type = arguments[3].asNumber(); + auto rows = static_cast(arguments[1].asNumber()); + auto cols = static_cast(arguments[2].asNumber()); + auto type = static_cast(arguments[3].asNumber()); + auto channels = CV_MAT_CN(type); + auto depth = CV_MAT_DEPTH(type); + std::vector size {rows, cols}; - if(arguments[4].isObject()) { - auto rawArray = arguments[4].asObject(runtime); - auto array = rawArray.asArray(runtime); + if (count > 4 && arguments[4].isObject()) { + auto array = arguments[4].asObject(runtime).asArray(runtime); + auto length = array.length(runtime); - auto rawLength = rawArray.getProperty(runtime, "length"); - auto length = rawLength.asNumber(); - - std::vector vec; - - for(auto i = 0; i < length; i++) { + std::vector vec; + vec.reserve(length); + for(size_t i = 0; i < length; i++) { vec.push_back(array.getValueAtIndex(runtime, i).asNumber()); } - cv::Mat mat{vec, true}; - mat = mat.reshape(1, rows); - mat.convertTo(mat, type); - - id = FOCV_Storage::save(mat); + cv::Mat object(vec, true); + object = object.reshape(channels, size); + object.convertTo(object, depth); + id = FOCV_Storage::save(object); } else { - cv::Mat object(rows, cols, type); + cv::Mat object(size, type); id = FOCV_Storage::save(object); } } break; case hashString("mat_vector", 10): { - std::vector object; - id = FOCV_Storage::save(object); + std::vector vec; + id = FOCV_Storage::save(vec); } break; case hashString("rect", 4): { - int x = arguments[1].asNumber(); - int y = arguments[2].asNumber(); - int width = arguments[3].asNumber(); - int height = arguments[4].asNumber(); + auto x = static_cast(arguments[1].asNumber()); + auto y = static_cast(arguments[2].asNumber()); + auto width = static_cast(arguments[3].asNumber()); + auto height = static_cast(arguments[4].asNumber()); cv::Rect object(x, y, width, height); id = FOCV_Storage::save(object); } break; case hashString("rect_vector", 11): { - std::vector object; - id = FOCV_Storage::save(object); + std::vector vec; + id = FOCV_Storage::save(vec); } break; case hashString("point", 5): { - int x = arguments[1].asNumber(); - int y = arguments[2].asNumber(); + auto x = static_cast(arguments[1].asNumber()); + auto y = static_cast(arguments[2].asNumber()); cv::Point object(x, y); id = FOCV_Storage::save(object); } break; case hashString("point_vector", 12): { - std::vector object; - id = FOCV_Storage::save(object); + std::vector vec; + id = FOCV_Storage::save(vec); } break; case hashString("point2f", 7): { - int x = arguments[1].asNumber(); - int y = arguments[2].asNumber(); + auto x = static_cast(arguments[1].asNumber()); + auto y = static_cast(arguments[2].asNumber()); cv::Point2f object(x, y); id = FOCV_Storage::save(object); } break; case hashString("point2f_vector", 14): { std::vector vec; - if (arguments[1].isObject()) { - auto rawArray = arguments[1].asObject(runtime); - auto array = rawArray.asArray(runtime); + if (count > 1 && arguments[1].isObject()) { + auto array = arguments[1].asObject(runtime).asArray(runtime); + auto length = array.length(runtime); - auto rawLength = rawArray.getProperty(runtime, "length"); - auto length = rawLength.asNumber(); - - for(auto i = 0; i < length; i++) { - jsi::Value value = array.getValueAtIndex(runtime, i); - std::string id = FOCV_JsiObject::id_from_wrap(runtime, value); - auto point2fPtr = FOCV_Storage::get(id); + for(size_t i = 0; i < length; i++) { + auto value = array.getValueAtIndex(runtime, i); + auto value_id = FOCV_JsiObject::id_from_wrap(runtime, value); + auto point2fPtr = FOCV_Storage::get(value_id); vec.push_back(*point2fPtr); } @@ -114,61 +110,73 @@ jsi::Object FOCV_Object::create(jsi::Runtime& runtime, const jsi::Value* argumen id = FOCV_Storage::save(vec); } break; case hashString("point_vector_vector", 19): { - std::vector> object; - id = FOCV_Storage::save(object); + std::vector> vec; + id = FOCV_Storage::save(vec); } break; case hashString("size", 4): { - int width = arguments[1].asNumber(); - int height = arguments[2].asNumber(); + auto width = static_cast(arguments[1].asNumber()); + auto height = static_cast(arguments[2].asNumber()); cv::Size object(width, height); id = FOCV_Storage::save(object); } break; case hashString("vec3b", 5): { - int a = arguments[1].asNumber(); - int b = arguments[2].asNumber(); - int c = arguments[3].asNumber(); + auto a = static_cast(arguments[1].asNumber()); + auto b = static_cast(arguments[2].asNumber()); + auto c = static_cast(arguments[3].asNumber()); cv::Vec3b object(a, b, c); id = FOCV_Storage::save(object); } break; case hashString("scalar", 6): { - if(arguments[4].isNumber()) { - int a = arguments[1].asNumber(); - int b = arguments[2].asNumber(); - int c = arguments[3].asNumber(); - int d = arguments[3].asNumber(); + if (count > 4 && arguments[4].isNumber()) { + auto a = arguments[1].asNumber(); + auto b = arguments[2].asNumber(); + auto c = arguments[3].asNumber(); + auto d = arguments[4].asNumber(); cv::Scalar object(a, b, c, d); id = FOCV_Storage::save(object); - } else if(arguments[3].isNumber()) { - int a = arguments[1].asNumber(); - int b = arguments[2].asNumber(); - int c = arguments[3].asNumber(); + } else if(count > 3 && arguments[3].isNumber()) { + auto a = arguments[1].asNumber(); + auto b = arguments[2].asNumber(); + auto c = arguments[3].asNumber(); cv::Scalar object(a, b, c); id = FOCV_Storage::save(object); } else { - int a = arguments[1].asNumber(); + auto a = arguments[1].asNumber(); cv::Scalar object(a); id = FOCV_Storage::save(object); } } break; case hashString("rotated_rect", 12): { - int x = arguments[1].asNumber(); - int y = arguments[2].asNumber(); - int width = arguments[3].asNumber(); - int height = arguments[4].asNumber(); - int angle = arguments[5].asNumber(); + auto x = static_cast(arguments[1].asNumber()); + auto y = static_cast(arguments[2].asNumber()); + auto width = static_cast(arguments[3].asNumber()); + auto height = static_cast(arguments[4].asNumber()); + auto angle = static_cast(arguments[5].asNumber()); cv::RotatedRect object(cv::Point(x,y), cv::Size(width, height), angle); id = FOCV_Storage::save(object); } break; + case hashString("term_criteria", 13): { + auto termCriteriaType = static_cast(arguments[1].asNumber()); + auto maxCount = static_cast(arguments[2].asNumber()); + auto epsilon = arguments[3].asNumber(); + + cv::TermCriteria object(termCriteriaType, maxCount, epsilon); + if (!object.isValid()) { + throw std::runtime_error("Fast OpenCV Error: Invalid TermCriteria object parameters!"); + } + + id = FOCV_Storage::save(object); + } break; } return FOCV_JsiObject::wrap(runtime, objectType, id); } -jsi::Object FOCV_Object::convertToJSI(jsi::Runtime& runtime, const jsi::Value* arguments) { +jsi::Object FOCV_Object::convertToJSI(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count) { jsi::Object value(runtime); std::string objectType = FOCV_JsiObject::type_from_wrap(runtime, arguments[0]); std::string id = FOCV_JsiObject::id_from_wrap(runtime, arguments[0]); @@ -194,7 +202,7 @@ jsi::Object FOCV_Object::convertToJSI(jsi::Runtime& runtime, const jsi::Value* a auto array = jsi::Array(runtime, mats.size()); - for (int i = 0; i < mats.size(); i++) { + for (size_t i = 0; i < mats.size(); i++) { jsi::Object item(runtime); item.setProperty(runtime, "size", jsi::Value(mats.at(i).size)); @@ -218,7 +226,7 @@ jsi::Object FOCV_Object::convertToJSI(jsi::Runtime& runtime, const jsi::Value* a auto array = jsi::Array(runtime, rects.size()); - for (int i = 0; i < rects.size(); i++) { + for (size_t i = 0; i < rects.size(); i++) { jsi::Object item(runtime); item.setProperty(runtime, "x", jsi::Value(rects.at(i).x)); @@ -236,12 +244,18 @@ jsi::Object FOCV_Object::convertToJSI(jsi::Runtime& runtime, const jsi::Value* a value.setProperty(runtime, "x", jsi::Value(point.x)); value.setProperty(runtime, "y", jsi::Value(point.y)); } break; + case hashString("point2f", 7): { + auto point = *FOCV_Storage::get(id); + + value.setProperty(runtime, "x", jsi::Value(point.x)); + value.setProperty(runtime, "y", jsi::Value(point.y)); + } break; case hashString("point_vector", 12): { auto points = *FOCV_Storage::get>(id); auto array = jsi::Array(runtime, points.size()); - for (int i = 0; i < points.size(); i++) { + for (size_t i = 0; i < points.size(); i++) { jsi::Object item(runtime); item.setProperty(runtime, "x", jsi::Value(points.at(i).x)); @@ -256,11 +270,11 @@ jsi::Object FOCV_Object::convertToJSI(jsi::Runtime& runtime, const jsi::Value* a auto vectors_array = jsi::Array(runtime, points_vector.size()); - for (int i = 0; i < points_vector.size(); i++) { - auto points = points_vector.at(i); + for (size_t i = 0; i < points_vector.size(); i++) { + const auto& points = points_vector.at(i); auto array = jsi::Array(runtime, points.size()); - for (int j = 0; j < points.size(); j++) { + for (size_t j = 0; j < points.size(); j++) { jsi::Object item(runtime); item.setProperty(runtime, "x", jsi::Value(points.at(j).x)); @@ -303,41 +317,48 @@ jsi::Object FOCV_Object::convertToJSI(jsi::Runtime& runtime, const jsi::Value* a value.setProperty(runtime, "height", jsi::Value(rect.size.height)); value.setProperty(runtime, "angle", jsi::Value(rect.angle)); } break; + case hashString("term_criteria", 13): { + auto termCriteria = *FOCV_Storage::get(id); + + value.setProperty(runtime, "type", jsi::Value(termCriteria.type)); + value.setProperty(runtime, "maxCount", jsi::Value(termCriteria.maxCount)); + value.setProperty(runtime, "epsilon", jsi::Value(termCriteria.epsilon)); + } break; } return value; } -jsi::Object FOCV_Object::copyObjectFromVector(jsi::Runtime& runtime, const jsi::Value* arguments) { +jsi::Object FOCV_Object::copyObjectFromVector(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count) { std::string createdId; jsi::Object value(runtime); std::string objectType = FOCV_JsiObject::type_from_wrap(runtime, arguments[0]); std::string vectorId = FOCV_JsiObject::id_from_wrap(runtime, arguments[0]); - int index = arguments[1].asNumber(); + auto index = static_cast(arguments[1].asNumber()); switch(hashString(objectType.c_str(), objectType.size())) { case hashString("mat_vector", 10): { auto array = *FOCV_Storage::get>(vectorId); - cv::Mat mat = array.at(index); + auto mat = array.at(index); createdId = FOCV_Storage::save(mat); return FOCV_JsiObject::wrap(runtime, "mat", createdId); } break; case hashString("rect_vector", 11): { auto array = *FOCV_Storage::get>(vectorId); - cv::Rect rect = array.at(index); + auto rect = array.at(index); createdId = FOCV_Storage::save(rect); return FOCV_JsiObject::wrap(runtime, "rect", createdId); } break; case hashString("point_vector", 12): { auto array = *FOCV_Storage::get>(vectorId); - cv::Point point = array.at(index); + auto point = array.at(index); createdId = FOCV_Storage::save(point); return FOCV_JsiObject::wrap(runtime, "point", createdId); } break; case hashString("point_vector_vector", 19): { auto array = *FOCV_Storage::get>>(vectorId); - std::vector point = array.at(index); + auto point = array.at(index); createdId = FOCV_Storage::save(point); return FOCV_JsiObject::wrap(runtime, "point_vector", createdId); } break; diff --git a/cpp/FOCV_Object.hpp b/cpp/FOCV_Object.hpp index 2e136ba..b256a62 100644 --- a/cpp/FOCV_Object.hpp +++ b/cpp/FOCV_Object.hpp @@ -30,9 +30,9 @@ using namespace facebook; class FOCV_Object { public: - static jsi::Object create(jsi::Runtime& runtime, const jsi::Value* arguments); - static jsi::Object convertToJSI(jsi::Runtime& runtime, const jsi::Value* arguments); - static jsi::Object copyObjectFromVector(jsi::Runtime& runtime, const jsi::Value* arguments); + static jsi::Object create(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count); + static jsi::Object convertToJSI(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count); + static jsi::Object copyObjectFromVector(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count); }; #endif /* FOCV_Object_hpp */ diff --git a/cpp/FOCV_Storage.cpp b/cpp/FOCV_Storage.cpp index d7ce421..af10b46 100644 --- a/cpp/FOCV_Storage.cpp +++ b/cpp/FOCV_Storage.cpp @@ -9,6 +9,13 @@ std::unordered_map FOCV_Storage::items = std::unordered_map(); -void FOCV_Storage::clear() { - items.clear(); +void FOCV_Storage::clear(const std::set &ids_to_keep) { + for (auto it = items.begin(); it != items.end();) { + auto id = it->first; + if (ids_to_keep.find(id) != ids_to_keep.end()) { + it++; + } else { + it = items.erase(it); + } + } } \ No newline at end of file diff --git a/cpp/FOCV_Storage.hpp b/cpp/FOCV_Storage.hpp index fbf1351..8f6972e 100644 --- a/cpp/FOCV_Storage.hpp +++ b/cpp/FOCV_Storage.hpp @@ -31,7 +31,7 @@ class FOCV_Storage { template static std::string save(std::string key, T &item); - static void clear(); + static void clear(const std::set &ids_to_keep); }; template @@ -52,8 +52,8 @@ std::string FOCV_Storage::save(std::string key, T &item) { template std::shared_ptr FOCV_Storage::get(std::string key) { - if(!items.contains(key)) { - // TODO: Error here! + if (!items.contains(key)) { + throw std::runtime_error("Fast OpenCV Error: Object with id '" + key + "' not found in storage!"); } return std::any_cast>(items.at(key)); diff --git a/cpp/react-native-fast-opencv.cpp b/cpp/react-native-fast-opencv.cpp index 7be7618..9b1bbd4 100644 --- a/cpp/react-native-fast-opencv.cpp +++ b/cpp/react-native-fast-opencv.cpp @@ -44,12 +44,12 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN runtime, jsi::PropNameID::forAscii(runtime, "frameBufferToMat"), 4, [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Object { - double rows = arguments[0].asNumber(); - double cols = arguments[1].asNumber(); - int channels = arguments[2].asNumber(); - jsi::Object input = arguments[3].asObject(runtime); + auto rows = arguments[0].asNumber(); + auto cols = arguments[1].asNumber(); + auto channels = arguments[2].asNumber(); + auto input = arguments[3].asObject(runtime); - int type = -1; + auto type = -1; if (channels == 1) { type = CV_8U; } @@ -64,11 +64,11 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN throw std::runtime_error("Fast OpenCV Error: Invalid channel count passed to frameBufferToMat!"); } - TypedArrayBase inputBuffer = getTypedArray(runtime, std::move(input)); + auto inputBuffer = getTypedArray(runtime, std::move(input)); auto vec = inputBuffer.toVector(runtime); cv::Mat mat(rows, cols, type); - memcpy(mat.data, vec.data(), (int)rows * (int)cols * channels); + memcpy(mat.data, vec.data(), (int)rows * (int)cols * (int)channels); auto id = FOCV_Storage::save(mat); return FOCV_JsiObject::wrap(runtime, "mat", id); @@ -76,11 +76,11 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN } else if (propName == "base64ToMat") { return jsi::Function::createFromHostFunction( - runtime, jsi::PropNameID::forAscii(runtime, "frameBufferToMat"), 1, + runtime, jsi::PropNameID::forAscii(runtime, "base64ToMat"), 1, [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Object { - std::string base64 = arguments[0].asString(runtime).utf8(runtime); + auto base64 = arguments[0].asString(runtime).utf8(runtime); auto mat = ImageConverter::str2mat(base64); auto id = FOCV_Storage::save(mat); @@ -94,7 +94,7 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Object { - std::string id = FOCV_JsiObject::id_from_wrap(runtime, arguments[0]); + auto id = FOCV_JsiObject::id_from_wrap(runtime, arguments[0]); auto mat = *FOCV_Storage::get(id); jsi::Object value(runtime); @@ -104,7 +104,7 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN value.setProperty(runtime, "channels", jsi::Value(mat.channels())); auto type = arguments[1].asString(runtime).utf8(runtime); - int size = mat.cols * mat.rows * mat.channels(); + auto size = mat.cols * mat.rows * mat.channels(); if(type == "uint8") { auto arr = TypedArray(runtime, size); @@ -148,7 +148,7 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Object { - return FOCV_Object::create(runtime, arguments); + return FOCV_Object::create(runtime, arguments, count); }); } else if (propName == "toJSValue") { @@ -157,7 +157,7 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Object { - return FOCV_Object::convertToJSI(runtime, arguments); + return FOCV_Object::convertToJSI(runtime, arguments, count); }); } else if (propName == "copyObjectFromVector") { @@ -166,7 +166,7 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Object { - return FOCV_Object::copyObjectFromVector(runtime, arguments); + return FOCV_Object::copyObjectFromVector(runtime, arguments, count); }); } else if (propName == "invoke") { @@ -175,15 +175,25 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Object { - return FOCV_Function::invoke(runtime, arguments); + return FOCV_Function::invoke(runtime, arguments, count); }); } else if (propName == "clearBuffers") { return jsi::Function::createFromHostFunction( runtime, jsi::PropNameID::forAscii(runtime, "clearBuffers"), 1, [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value { - - FOCV_Storage::clear(); + std::set ids_to_keep; + + if (count > 0) { + auto array = arguments[0].asObject(runtime).asArray(runtime); + auto length = array.length(runtime); + for (size_t i = 0; i < length; i++) { + auto id = array.getValueAtIndex(runtime, i).asString(runtime).utf8(runtime); + ids_to_keep.insert(id); + } + } + + FOCV_Storage::clear(ids_to_keep); return true; }); } diff --git a/docs/pages/apidetails.md b/docs/pages/apidetails.md index 0b1ba25..4e51d9a 100644 --- a/docs/pages/apidetails.md +++ b/docs/pages/apidetails.md @@ -3,6 +3,7 @@ ## Objects ### Create Object + The function creates a new object of the selected type and stores it in memory. The returned object contains the object identifier and type. ```js @@ -45,6 +46,7 @@ createObject( --- ### Copy Object from Vector + Copies an object from a vector to a separate object. ```js @@ -60,6 +62,7 @@ copyObjectFromVector(vector: RectVector, itemIndex: number): Rect; --- ### To JS Value + Converts an object to a JS-readable object. ```js @@ -120,13 +123,15 @@ toJSValue(scalar: Scalar): { ## Utils ### Clear Buffers + Clears stored objects from memory. ```js -clearBuffers(): void; +clearBuffers(idsToKeep?: string[]): void; ``` ### Frame Buffer to Mat + Creates an object of type Mat based on an array of Uint8Array. ```js @@ -134,6 +139,7 @@ frameBufferToMat(rows: number, cols: number, channels: number, input: Uint8Array ``` ### Base64 to Mat + Creates an object of type Mat based on image in Base64. ```js @@ -141,6 +147,7 @@ base64ToMat(data: string): Mat; ``` ### Mat to Buffer + Convert Mat object to Uint8Array or Float32Array based on value of parameter and returns with number of cols, rows and channels. ```ts @@ -175,4 +182,4 @@ Performs a function with specified parameters. A full list of functions with par ```js invoke(name: 'absdiff', src1: Mat, src2: Mat, dst: Mat): void; -``` \ No newline at end of file +``` diff --git a/docs/pages/availablefunctions.md b/docs/pages/availablefunctions.md index caf69c5..733419d 100644 --- a/docs/pages/availablefunctions.md +++ b/docs/pages/availablefunctions.md @@ -3,7 +3,9 @@ ## Core ### absdiff + Calculates the per-element absolute difference between two arrays or between an array and a scalar. + - src1 first input array. - src2 second input array. - dst output array that has the same size and type as input arrays. @@ -33,8 +35,6 @@ invoke( ): void; ``` - - ### addWeighted - src1 first input array. @@ -132,6 +132,7 @@ invoke(name: 'bitwise_xor', src1: Mat, src2: Mat, dst: Mat, mask?: Mat): void; ### borderInterpolate Computes the source location of an extrapolated pixel. + - p 0-based coordinate of the extrapolated pixel along one of the axes, likely <0 or >= len - len Length of the array along the corresponding axis. - borderType Border type, one of the BorderTypes, except for BORDER_TRANSPARENT and BORDER_ISOLATED . When borderType==BORDER_CONSTANT , the function always returns -1, regardless of p and len @@ -240,6 +241,7 @@ invoke( ### completeSymm Copies the lower or the upper half of a square matrix to its another half. + - m input-output floating-point square matrix - lowerToUpper operation flag; if true, the lower half is copied to the upper half. Otherwise, the upper half is copied to the lower half. @@ -289,12 +291,14 @@ invoke( Converts an array to another data type with optional scaling. -- src input array -- dst output array of the same type as src -- rtype desired output matrix type or, rather, the depth since the number of channels are the same as the input has; if rtype is negative, the output matrix will have the same type as the input. +- src input matrix. +- dst output matrix; if it does not have a proper size or type before the operation, it is reallocated. +- rtype desired output matrix type or, rather, the depth since the number of channels are the same as the input has; if rtype is negative, the output matrix will have the same type as the input. +- alpha optional scale factor. +- beta optional delta added to the scaled values. ```js -invoke(name: 'convertTo', src: Mat, dst: Mat, rtype: DataTypes): void; +invoke(name: 'convertTo', src: Mat, dst: Mat, rtype: DataTypes, alpha?: number, beta?: number): void; ``` ### copyMakeBorder @@ -764,7 +768,6 @@ invoke( ): { minVal: number; maxVal: number }; ``` - ### mulSpectrums Performs the per-element multiplication of two Fourier spectrums @@ -938,7 +941,7 @@ Computes the Peak Signal-to-Noise Ratio (PSNR) image quality metric @returns the Peak Signal-to-Noise Ratio (PSNR) image quality metric in decibels (dB) ```js -invoke(name: 'PSNR', src1: Mat, src2: Mat, R: number): number; +invoke(name: 'PSNR', src1: Mat, src2: Mat, R: number): { psnr: number }; ``` ### reduce @@ -983,7 +986,6 @@ Rotates matrix. - dst output array of the same type as src. - code rotate flag - ```js invoke(name: 'repeat', src: Mat, dst: Mat, code: RotateFlags): void; ``` @@ -1040,7 +1042,7 @@ Finds the real or complex roots of a polynomial equation - maxIters maximum number of iterations the algorithm does ```js -invoke(name: 'solvePoly', src: Mat, dst: Mat, maxIters: number): number; +invoke(name: 'solvePoly', src: Mat, dst: Mat, maxIters: number): { value: number }; ``` ### sort @@ -1164,11 +1166,10 @@ Applies vertical concatenation to given matrices invoke(name: 'vconcat', src: MatVector, dst: Mat): void; ``` - - ## ColorConversion ### cvtColor + Converts an image from one color space to another. - src input image: 8-bit unsigned, 16-bit unsigned ( CV_16UC... ), or single-precision floating-point. @@ -1267,9 +1268,10 @@ invoke( ## Imgproc – Drawing - ### arrowedLine + Draws a arrow segment pointing from the first point to the second one. + - img Image - pt1 The point the arrow starts from. - pt2 The point the arrow points to. @@ -1290,7 +1292,9 @@ invoke( ``` ### circle + Draws a circle. + - img Image where the circle is drawn. - center Center of the circle. - radius Radius of the circle. @@ -1310,7 +1314,9 @@ invoke( ``` ### clipLine + Clips the line against the image rectangle. The function cv::clipLine calculates a part of the line segment that is entirely within the specified rectangle. it returns false if the line segment is completely outside the rectangle. Otherwise, it returns true . + - imgSize Image size - pt1 First line point. - pt2 Second line point. @@ -1325,7 +1331,9 @@ invoke( ``` ### drawContours + Draws contours outlines or filled contours. The function draws contour outlines in the image if 𝚝𝚑𝚒𝚌𝚔𝚗𝚎𝚜𝚜≥0 or fills the area bounded by the contours if 𝚝𝚑𝚒𝚌𝚔𝚗𝚎𝚜𝚜<0. + - image Destination image. - contours All the input contours. Each contour is stored as a point vector - contourIdx Parameter indicating a contour to draw. If it is negative, all the contours are drawn. @@ -1346,7 +1354,9 @@ invoke( ``` ### drawMarker + Draws a marker on a predefined position in an image. + - img Image - position The point where the crosshair is positioned - color Line color @@ -1369,7 +1379,9 @@ invoke( ``` ### ellipse + Draws a simple or thick elliptic arc or fills an ellipse sector. + - img Image - center Center of the ellipse - axes Half of the size of the ellipse main axes @@ -1396,7 +1408,9 @@ invoke( ``` ### fillConvexPoly + Fills a convex polygon. + - img Image - pts Polygon vertices. - color Polygon color @@ -1413,7 +1427,9 @@ invoke( ``` ### fillPoly + Fills the area bounded by one or more polygons + - img Image - pts Array of polygons where each polygon is represented as an array of points - color Polygon colo @@ -1430,7 +1446,9 @@ invoke( ``` ### line + Draws a line segment connecting two points. + - img Image - pt1 First point of the line segment - pt2 Second point of the line segment @@ -1451,7 +1469,9 @@ invoke( ``` ### polylines + Draws several polygonal curves + - img Image - pts Array of polygonal curves. - isClosed Flag indicating whether the drawn polylines are closed or not. If they are closed, the function draws a line from the last vertex of each curve to its first vertex @@ -1472,7 +1492,9 @@ invoke( ``` ### rectangle + Draws a simple, thick, or filled up-right rectangle. + - img Image - pt1 Vertex of the rectangle - pt2 Vertex of the rectangle opposite to pt1 @@ -1494,9 +1516,10 @@ invoke( ## Imgproc – Feature - ### Canny + Finds edges in an image using the Canny algorithm + - name Function name. - image 8-bit input image. - edges output edge map; single channels 8-bit image, which has the same size as image @@ -1515,7 +1538,9 @@ invoke( ``` ### cornerHarris + Harris corner detector + - name Function name. - src Input single-channel 8-bit or floating-point image. - dst Image to store the Harris detector responses. It has the type CV_32FC1 and the same size as src @@ -1535,7 +1560,9 @@ invoke( ``` ### cornerMinEigenVal + Calculates the minimal eigenvalue of gradient matrices for corner detection + - name Function name. - src Input single-channel 8-bit or floating-point image - dst Image to store the minimal eigenvalues. It has the type CV_32FC1 and the same size as src @@ -1551,7 +1578,9 @@ invoke( ``` ### goodFeaturesToTrack + Determines strong corners on an image + - name Function name. - image Input 8-bit or floating-point 32-bit, single-channel image - corners Output vector of detected corners @@ -1571,7 +1600,9 @@ invoke( ``` ### HoughCircles + Finds circles in a grayscale image using the Hough transform + - name Function name. - image 8-bit, single-channel, grayscale input image. - circles Output vector of found circles. Each vector is encoded as 3 or 4 element floating-point vector (x,y,radius) or (x,y,radius,votes) @@ -1595,7 +1626,9 @@ invoke( ``` ### HoughLines + Finds lines in a binary image using the standard Hough transform + - name Function name. - image 8-bit, single-channel binary source image. The image may be modified by the function. - lines Output vector of lines. Each line is represented by a 2 or 3 element vector (ρ,θ) or (ρ,θ,votes) . ρ is the distance from the coordinate origin (0,0) (top-left corner of the image). θ is the line rotation angle in radians ( 0∼vertical line,π/2∼horizontal line ). votes is the value of accumulator @@ -1615,7 +1648,9 @@ invoke( ``` ### HoughLinesP + Finds line segments in a binary image using the probabilistic Hough transform + - name Function name. - image 8-bit, single-channel binary source image. The image may be modified by the function. - lines Output vector of lines. Each line is represented by a 2 or 3 element vector (ρ,θ) or (ρ,θ,votes) . ρ is the distance from the coordinate origin (0,0) (top-left corner of the image). θ is the line rotation angle in radians ( 0∼vertical line,π/2∼horizontal line ). votes is the value of accumulator @@ -1634,12 +1669,12 @@ invoke( ): void; ``` - ## Imgproc – Image Filtering - ### bilateralFilter + Applies the bilateral filter to an image. + - src Source 8-bit or floating-point, 1-channel or 3-channel image. - dst Destination image of the same size and type as src . - d Diameter of each pixel neighborhood that is used during filtering. If it is non-positive, it is computed from sigmaSpace. @@ -1660,6 +1695,7 @@ invoke( ``` ### blur + - src input image; it can have any number of channels, which are processed independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. - dst output image of the same size and type as src. - ksize blurring kernel size. @@ -1678,7 +1714,9 @@ invoke( ``` ### boxFilter + Blurs an image using the box filter. + - src input image. - dst output image of the same size and type as src. - ddepth the output image depth (-1 to use src.depth()). @@ -1701,7 +1739,9 @@ invoke( ``` ### buildPyramid + Constructs the Gaussian pyramid for an image. + - src Source image. Check pyrDown for the list of supported types. - dst Destination vector of maxlevel+1 images of the same type as src. dst[0] will be the same as src. dst[1] is the next pyramid layer, a smoothed and down-sized src, and so on. - maxlevel 0-based index of the last (the smallest) pyramid layer. It must be non-negative. @@ -1718,7 +1758,9 @@ invoke( ``` ### dilate + Dilates an image by using a specific structuring element. + - src input image; the number of channels can be arbitrary, but the depth should be one of CV_8U, CV_16U, CV_16S, CV_32F or CV_64F - dst output image of the same size and type as src. - kernel structuring element used for dilation; if elemenat=Mat(), a 3 x 3 rectangular structuring element is used. Kernel can be created using getStructuringElement @@ -1741,7 +1783,9 @@ invoke( ``` ### erode + Erodes an image by using a specific structuring element. + - src input image; the number of channels can be arbitrary, but the depth should be one of CV_8U, CV_16U, CV_16S, CV_32F or CV_64F - dst output image of the same size and type as src. - kernel structuring element used for dilation; if elemenat=Mat(), a 3 x 3 rectangular structuring element is used. Kernel can be created using getStructuringElement @@ -1764,7 +1808,9 @@ invoke( ``` ### filter2D + Convolves an image with the kernel. + - src input image. - dst output image of the same size and the same number of channels as src. - ddepth desired depth of the destination image @@ -1787,7 +1833,9 @@ invoke( ``` ### GaussianBlur + Blurs an image using a Gaussian filter. + - src input image; the image can have any number of channels, which are processed independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. - dst output image of the same size and type as src. - ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be positive and odd. Or, they can be zero's and then they are computed from sigma. @@ -1845,7 +1893,9 @@ invoke( ``` ### getGaussianKernel + Returns Gaussian filter coefficients. + - ksize Aperture size. It should be odd ( 𝚔𝚜𝚒𝚣𝚎mod2=1 ) and positive. - sigma Gaussian standard deviation. If it is non-positive, it is computed from ksize as sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8. - ktype Type of filter coefficients. It can be CV_32F or CV_64F . @@ -1860,7 +1910,9 @@ invoke( ``` ### getPerspectiveTransform + Calculates a perspective transform from four pairs of the corresponding points. + - name Function name. - src Coordinates of quadrangle vertices in the source image. - dst Coordinates of the corresponding quadrangle vertices in the destination image. @@ -1894,7 +1946,9 @@ invoke( ``` ### Laplacian + Calculates the Laplacian of an image. + - name Function name. - src Source image. - dst Destination image of the same size and the same number of channels as src . @@ -1918,8 +1972,10 @@ invoke( ``` ### medianBlur + Blurs an image using the median filter. The function smoothes an image using the median filter with the 𝚔𝚜𝚒𝚣𝚎×𝚔𝚜𝚒𝚣𝚎 aperture. Each channel of a multi-channel image is processed independently. In-place operation is supported. + - name Function name. - src input 1-, 3-, or 4-channel image; when ksize is 3 or 5, the image depth should be CV_8U, CV_16U, or CV_32F, for larger aperture sizes, it can only be CV_8U. - dst destination array of the same size and type as src. @@ -1938,9 +1994,11 @@ invoke(name: 'morphologyDefaultBorderValue'): Scalar; ``` ### morphologyEx + Performs advanced morphological transformations. The function cv::morphologyEx can perform advanced morphological transformations using an erosion and dilation as basic operations. Any of the operations can be done in-place. In case of multi-channel images, each channel is processed independently. + - name Function name. - src Source image. The number of channels can be arbitrary. The depth should be one of CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. - dst Destination image of the same size and type as source image. @@ -1986,12 +2044,12 @@ invoke( ): void; ``` - ## Imgproc – Misc - ### adaptiveThreshold + Applies an adaptive threshold to an array + - name Function name. - src Source 8-bit single-channel image. - dst Destination image of the same size and the same type as src @@ -2017,14 +2075,16 @@ invoke( ``` ### distanceTransform + Calculates the distance to the closest zero pixel for each pixel of the source image + - name Function name. -- src 8-bit, single-channel (binary) source image +- src 8-bit, single-channel (binary) source image - dst Output image with calculated distances. It is a 8-bit or 32-bit floating-point, single-channel image of the same size as src - distanceType Type of distance, @see DistanceTypes - maskSize Size of the distance transform mask, @see DistanceTransformMasks. In case of the DIST_L1 or DIST_C distance type, the parameter is forced to 3 because a 3×3 mask gives the same result as 5×5 or any larger aperture. -```js +```js invoke( name: 'distanceTransform', src: Mat, @@ -2035,7 +2095,9 @@ invoke( ``` ### integral + Calculates the integral of an image + - name Function name. - src input image as W×H, 8-bit or floating-point (32f or 64f). - sum integral image as (W+1)×(H+1) , 32-bit integer or floating-point (32f or 64f). @@ -2075,7 +2137,9 @@ invoke( ``` ### threshold + Applies a fixed-level threshold to each array element + - name Function name. - src input array (multiple-channel, 8-bit or 32-bit floating point). - dst output array of the same size and type and the same number of channels as src. @@ -2094,12 +2158,12 @@ invoke( ): void; ``` - ## Imgproc – Object Detection - ### matchTemplate + Compares a template against overlapped image regions + - image Image where the search is running. It must be 8-bit or 32-bit floating-point - templ Searched template. It must be not greater than the source image and have the same data type. - result Map of comparison results. It must be single-channel 32-bit floating-point. If image is W×H and templ is w×h , then result is (W−w+1)×(H−h+1) . @@ -2119,9 +2183,10 @@ invoke( ## Imgproc – Shape - ### approxPolyDP + Approximates a polygonal curve(s) with the specified precision + - curve Input vector of a 2D point stored in std::vector or Mat - approxCurve Result of the approximation. The type should match the type of the input curve - epsilonParameter specifying the approximation accuracy. This is the maximum distance between the original curve and its approximation @@ -2131,14 +2196,16 @@ Approximates a polygonal curve(s) with the specified precision invoke( name: 'approxPolyDP', curve: Mat | MatVector | PointVector, - approxCurve: Mat, + approxCurve: Mat | PointVector, epsilon: number, closed: boolean ): void; ``` ### arcLength + Calculates a contour perimeter or a curve length. + - curve Input vector of 2D points, stored in std::vector or Mat. - closed Flag indicating whether the curve is closed or not. @returns a curve length or a closed contour perimeter. @@ -2152,7 +2219,9 @@ invoke( ``` ### boundingRect + Calculates the up-right bounding rectangle of a point set or non-zero pixels of gray-scale image. + - array Input gray-scale image or 2D point set, stored in std::vector or Mat. @returns the minimal up-right bounding rectangle for the specified point set or non-zero pixels of gray-scale image @@ -2161,7 +2230,9 @@ invoke(name: 'boundingRect', array: Mat | MatVector | PointVector): Rect; ``` ### connectedComponents + computes the connected components labeled image of boolean image + - image the 8-bit single-channel image to be labeled - labels destination labeled image @returns N, the total number of labels [0, N-1] where 0 represents the background label @@ -2175,7 +2246,9 @@ invoke( ``` ### connectedComponentsWithStats + computes the connected components labeled image of boolean image and also produces a statistics output for each label + - image the 8-bit single-channel image to be labeled - labels destination labeled image - stats statistics output for each label, including the background label. Statistics are accessed via stats(label, COLUMN) where COLUMN is one of ConnectedComponentsTypes, selecting the statistic. The data type is CV_32S. @@ -2193,7 +2266,9 @@ invoke( ``` ### contourArea + Calculates a contour area + - contour Input vector of 2D points (contour vertices), stored in std::vector or Mat. - oriented Oriented area flag. If it is true, the function returns a signed area value, depending on the contour orientation (clockwise or counter-clockwise). Using this feature you can determine orientation of a contour by taking the sign of an area. By default, the parameter is false, which means that the absolute value is returned @returns area and the number of non-zero pixels, @@ -2207,7 +2282,9 @@ invoke( ``` ### convexHull + Finds the convex hull of a point set. + - points Input 2D point set, stored in std::vector or Mat. - hull Output convex hull. It is either an integer vector of indices or vector of points. In the first case, the hull elements are 0-based indices of the convex hull points in the original array (since the set of convex hull points is a subset of the original point set). In the second case, hull elements are the convex hull points themselves @@ -2216,7 +2293,9 @@ invoke(name: 'convexHull', points: Mat, hull: Mat): void; ``` ### convexityDefects + Finds the convexity defects of a contour. + - contour Input contour - convexHull Convex hull obtained using convexHull that should contain indices of the contour points that make the hull - convexityDefects output vector of convexity defects. In C++ and the new Python/Java interface each convexity defect is represented as 4-element integer vector (a.k.a. Vec4i): (start_index, end_index, farthest_pt_index, fixpt_depth), where indices are 0-based indices in the original contour of the convexity defect beginning, end and the farthest point, and fixpt_depth is fixed-point approximation (with 8 fractional bits) of the distance between the farthest contour point and the hull. That is, to get the floating-point value of the depth will be fixpt_depth/256.0. @@ -2231,7 +2310,9 @@ invoke( ``` ### findContours + Finds contours in a binary image + - image Source, an 8-bit single-channel image. Non-zero pixels are treated as 1s. Zero pixels remain 0s, so the image is treated as binary . You can use compare, inRange, threshold , adaptiveThreshold, Canny, and others to create a binary image out of a grayscale or color one. If mode equals to RETR_CCOMP or RETR_FLOODFILL, the input can also be a 32-bit integer image of labels (CV_32SC1). - contours Detected contours. Each contour is stored as a vector of points - mode Contour retrieval mode, @see RetrievalModes @@ -2248,7 +2329,9 @@ invoke( ``` ### fitLine + Fits a line to a 2D or 3D point set. + - points Input vector of 2D or 3D points, stored in a Mat. - line Output line parameters. In case of 2D fitting, it should be a vector of 4 elements (like Vec4f) - (vx, vy, x0, y0), where (vx, vy) is a normalized vector collinear to the line and (x0, y0) is a point on the line. In case of 3D fitting, it should be a vector of 6 elements (like Vec6f) - (vx, vy, vz, x0, y0, z0), where (vx, vy, vz) is a normalized vector collinear to the line and (x0, y0, z0) is a point on the line - disType Distance used by the M-estimator, @see DistanceTypes @@ -2269,16 +2352,20 @@ invoke( ``` ### isContourConvex + Tests a contour convexity. + - contour @returns whether the input contour is convex or not ```js -invoke(name: 'isContourConvex', contour: Mat): boolean; +invoke(name: 'isContourConvex', contour: Mat): { value: boolean }; ``` ### matchShapes + Compares two shapes + - contour1 First contour or grayscale image - contour2 Second contour or grayscale image - method Comparison method, @see ShapeMatchModes @@ -2292,11 +2379,13 @@ invoke( contour2: Mat, method: ShapeMatchModes, parameter: number -): number; +): { value: number }; ``` ### minAreaRect + Finds a rotated rectangle of the minimum area enclosing the input 2D point set. + - points Input vector of 2D points, stored in a Mat @returns the minimum-area bounding rectangle (possibly rotated) for a specified point set @@ -2304,9 +2393,10 @@ Finds a rotated rectangle of the minimum area enclosing the input 2D point set. invoke(name: 'minAreaRect', points: Mat): RotatedRect; ``` - ### warpPerspective + Applies a perspective transformation to an image. + - name Function name. - src input image. - dst output image that has the size dsize and the same type as src . @@ -2327,4 +2417,4 @@ invoke( borderMode: BorderTypes.BORDER_CONSTANT | BorderTypes.BORDER_REPLICATE, borderValue: Scalar ): void; -``` \ No newline at end of file +``` diff --git a/package.json b/package.json index f247444..09ea48a 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,6 @@ "react": "18.2.0", "react-native": "0.74.4", "react-native-builder-bob": "^0.29.0", - "react-native-fs": "2.20.0", "release-it": "17.6.0", "turbo": "^1.10.7", "typedoc": "^0.26.6", diff --git a/src/constants/Core.ts b/src/constants/Core.ts index 0c5a567..4201d14 100644 --- a/src/constants/Core.ts +++ b/src/constants/Core.ts @@ -90,3 +90,9 @@ export enum SortFlags { SORT_ASCENDING = 0, SORT_DESCENDING = 16, } + +export enum TermCriteriaType { + COUNT = 1, + MAX_ITER = COUNT, + EPS = 2, +} diff --git a/src/constants/ImageProcessing.ts b/src/constants/ImageProcessing.ts index 29efa44..c20c752 100644 --- a/src/constants/ImageProcessing.ts +++ b/src/constants/ImageProcessing.ts @@ -197,3 +197,9 @@ export enum ShapeMatchModes { CONTOURS_MATCH_I2 = 2, CONTOURS_MATCH_I3 = 3, } + +export enum OpticalFlowFlags { + OPTFLOW_USE_INITIAL_FLOW = 4, + OPTFLOW_LK_GET_MIN_EIGENVALS = 8, + OPTFLOW_FARNEBACK_GAUSSIAN = 256, +} diff --git a/src/functions/Core.ts b/src/functions/Core.ts index 9b8870d..8a07baf 100644 --- a/src/functions/Core.ts +++ b/src/functions/Core.ts @@ -750,7 +750,7 @@ export type Core = { * @param R the maximum pixel value (255 by default) * @returns the Peak Signal-to-Noise Ratio (PSNR) image quality metric in decibels (dB) */ - invoke(name: 'PSNR', src1: Mat, src2: Mat, R: number): number; + invoke(name: 'PSNR', src1: Mat, src2: Mat, R: number): { psnr: number }; /** * Reduces a matrix to a vector. @@ -830,7 +830,12 @@ export type Core = { * @param dst output (complex) array of roots * @param maxIters maximum number of iterations the algorithm does */ - invoke(name: 'solvePoly', src: Mat, dst: Mat, maxIters: number): number; + invoke( + name: 'solvePoly', + src: Mat, + dst: Mat, + maxIters: number + ): { value: number }; /** * Sorts each row or each column of a matrix. @@ -927,9 +932,18 @@ export type Core = { /** * Converts an array to another data type with optional scaling. * @param name Function name. - * @param src input array. - * @param dst output array of the same type as src - * @param rtype desired output matrix type or, rather, the depth since the number of channels are the same as the input has; if rtype is negative, the output matrix will have the same type as the input. + * @param src input matrix. + * @param dst output matrix; if it does not have a proper size or type before the operation, it is reallocated. + * @param rtype desired output matrix type or, rather, the depth since the number of channels are the same as the input has; if rtype is negative, the output matrix will have the same type as the input. + * @param alpha optional scale factor. + * @param beta optional delta added to the scaled values. */ - invoke(name: 'convertTo', src: Mat, dst: Mat, rtype: DataTypes): void; + invoke( + name: 'convertTo', + src: Mat, + dst: Mat, + rtype: DataTypes, + alpha?: number, + beta?: number + ): void; }; diff --git a/src/functions/ImageProcessing/ObjectDetection.ts b/src/functions/ImageProcessing/ObjectDetection.ts index ed58e55..5467d7b 100644 --- a/src/functions/ImageProcessing/ObjectDetection.ts +++ b/src/functions/ImageProcessing/ObjectDetection.ts @@ -1,7 +1,42 @@ -import type { TemplateMatchModes } from '../../constants/ImageProcessing'; -import type { Mat } from '../../objects/Objects'; +import type { + OpticalFlowFlags, + TemplateMatchModes, +} from '../../constants/ImageProcessing'; +import type { Mat, Point2f, Size, TermCriteria } from '../../objects/Objects'; export type ObjectDetection = { + /** + * Calculates an optical flow for a sparse feature set using the iterative Lucas-Kanade method with pyramids. + * @param name Function name + * @param prevImg First 8-bit input image or pyramid constructed by buildOpticalFlowPyramid. + * @param nextImg Second input image or pyramid of the same size and the same type as prevImg. + * @param prevPts Vector of 2D points for which the flow needs to be found; point coordinates must be single-precision floating-point numbers. + * @param nextPts Output vector of 2D points (with single-precision floating-point coordinates) containing the calculated new positions of input features in the second image; when OPTFLOW_USE_INITIAL_FLOW flag is passed, the vector must have the same size as in the input. + * @param status Output status vector (of unsigned chars); each element of the vector is set to 1 if the flow for the corresponding features has been found, otherwise, it is set to 0. + * @param err Output vector of errors; each element of the vector is set to an error for the corresponding feature, type of the error measure can be set in flags parameter; if the flow wasn't found then the error is not defined (use the status parameter to find such cases). + * @param winSize Size of the search window at each pyramid level. + * @param maxLevel 0-based maximal pyramid level number; if set to 0, pyramids are not used (single level), if set to 1, two levels are used, and so on; if pyramids are passed to input then algorithm will use as many levels as pyramids have but no more than maxLevel. + * @param criteria Parameter, specifying the termination criteria of the iterative search algorithm (after the specified maximum number of iterations criteria.maxCount or when the search window moves by less than criteria.epsilon). + * @param flags Operation flags: + * * OPTFLOW_USE_INITIAL_FLOW uses initial estimations, stored in nextPts; if the flag is not set, then prevPts is copied to nextPts and is considered the initial estimate. + * * OPTFLOW_LK_GET_MIN_EIGENVALS use minimum eigen values as an error measure (see minEigThreshold description); if the flag is not set, then L1 distance between patches around the original and a moved point, divided by number of pixels in a window, is used as a error measure. + * @param minEigThreshold The algorithm calculates the minimum eigen value of a 2x2 normal matrix of optical flow equations (this matrix is called a spatial gradient matrix in [36]), divided by number of pixels in a window; if this value is less than minEigThreshold, then a corresponding feature is filtered out and its flow is not processed, so it allows to remove bad points and get a performance boost. + */ + invoke( + name: 'calcOpticalFlowPyrLK', + prevImg: Mat, + nextImg: Mat, + prevPts: Mat, + nextPts: Mat, + status: Mat, + err: Mat, + winSize?: Size, + maxLevel?: number, + criteria?: TermCriteria, + flags?: OpticalFlowFlags, + minEigThreshold?: number + ): void; + /** * Compares a template against overlapped image regions * @param name Function name @@ -19,4 +54,23 @@ export type ObjectDetection = { method: TemplateMatchModes, mask: Mat ): void; + + /** + * The function is used to detect translational shifts that occur between two images. + * The operation takes advantage of the Fourier shift theorem for detecting the translational shift + * in the frequency domain. It can be used for fast image registration as well as motion estimation. + * + * For more information please see http://en.wikipedia.org/wiki/Phase_correlation + * + * @param name Function name + * @param src1 Source floating point array (CV_32FC1 or CV_64FC1) + * @param src2 Source floating point array (CV_32FC1 or CV_64FC1) + * @param window Floating point array with windowing coefficients to reduce edge effects (optional). + */ + invoke( + name: 'phaseCorrelate', + src1: Mat, + src2: Mat, + window?: Mat + ): { phaseShift: Point2f; response: number }; }; diff --git a/src/functions/ImageProcessing/Shape.ts b/src/functions/ImageProcessing/Shape.ts index 71931f8..94528a0 100644 --- a/src/functions/ImageProcessing/Shape.ts +++ b/src/functions/ImageProcessing/Shape.ts @@ -147,7 +147,7 @@ export type Shape = { * @param contour * @returns whether the input contour is convex or not */ - invoke(name: 'isContourConvex', contour: Mat): boolean; + invoke(name: 'isContourConvex', contour: Mat): { value: boolean }; /** * Compares two shapes @@ -163,7 +163,7 @@ export type Shape = { contour2: Mat, method: ShapeMatchModes, parameter: number - ): number; + ): { value: number }; /** * Finds a rotated rectangle of the minimum area enclosing the input 2D point set. diff --git a/src/objects/ObjectType.ts b/src/objects/ObjectType.ts index 57dfebd..0caa31c 100644 --- a/src/objects/ObjectType.ts +++ b/src/objects/ObjectType.ts @@ -12,4 +12,5 @@ export enum ObjectType { Vec3b = 'vec3b', Scalar = 'scalar', RotatedRect = 'rotated_rect', + TermCriteria = 'term_criteria', } diff --git a/src/objects/Objects.ts b/src/objects/Objects.ts index d475994..647448e 100644 --- a/src/objects/Objects.ts +++ b/src/objects/Objects.ts @@ -1,3 +1,4 @@ +import type { TermCriteriaType } from '../constants/Core'; import type { DataTypes } from '../constants/DataTypes'; import type { ObjectType } from './ObjectType'; @@ -17,6 +18,7 @@ export type Size = { id: string; type: ObjectType.Size }; export type Vec3b = { id: string; type: ObjectType.Vec3b }; export type Scalar = { id: string; type: ObjectType.Scalar }; export type RotatedRect = { id: string; type: ObjectType.RotatedRect }; +export type TermCriteria = { id: string; type: ObjectType.TermCriteria }; export type Vector = MatVector | PointVector | RectVector; export type Array = Mat | Vec3b; @@ -59,6 +61,12 @@ export type Objects = { c: number, d: number ): Scalar; + createObject( + type: ObjectType.TermCriteria, + termCriteriaType: TermCriteriaType, + maxCount: number, + epsilon: number + ): TermCriteria; toJSValue( mat: Mat, @@ -76,6 +84,10 @@ export type Objects = { x: number; y: number; }; + toJSValue(point2f: Point2f): { + x: number; + y: number; + }; toJSValue(pointVector: PointVector): { array: { x: number; @@ -112,13 +124,18 @@ export type Objects = { c?: number; d?: number; }; - toJSValue(scalar: RotatedRect): { + toJSValue(rotatedRect: RotatedRect): { centerX: number; centerY: number; width: number; height: number; angle: number; }; + toJSValue(termCriteria: TermCriteria): { + type: TermCriteriaType; + maxCount: number; + epsilon: number; + }; copyObjectFromVector(vector: MatVector, itemIndex: number): Mat; copyObjectFromVector(vector: PointVector, itemIndex: number): Point; diff --git a/src/utils/UtilsFunctions.ts b/src/utils/UtilsFunctions.ts index cec044d..2b92227 100644 --- a/src/utils/UtilsFunctions.ts +++ b/src/utils/UtilsFunctions.ts @@ -15,7 +15,7 @@ export type UtilsFunctions = { /** * Clears any buffers that were allocate to back Mats on the native side. */ - clearBuffers(): void; + clearBuffers(idsToKeep?: string[]): void; /** * Converts a byte array to a Mat. * @param rows - the number of rows in the Mat diff --git a/yarn.lock b/yarn.lock index e3e9fdb..316218f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4188,13 +4188,6 @@ __metadata: languageName: node linkType: hard -"base-64@npm:^0.1.0": - version: 0.1.0 - resolution: "base-64@npm:0.1.0" - checksum: 10/5a42938f82372ab5392cbacc85a5a78115cbbd9dbef9f7540fa47d78763a3a8bd7d598475f0d92341f66285afd377509851a9bb5c67bbecb89686e9255d5b3eb - languageName: node - linkType: hard - "base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -11150,7 +11143,6 @@ __metadata: react: "npm:18.2.0" react-native: "npm:0.74.4" react-native-builder-bob: "npm:^0.29.0" - react-native-fs: "npm:2.20.0" release-it: "npm:17.6.0" turbo: "npm:^1.10.7" typedoc: "npm:^0.26.6" @@ -11162,22 +11154,6 @@ __metadata: languageName: unknown linkType: soft -"react-native-fs@npm:2.20.0": - version: 2.20.0 - resolution: "react-native-fs@npm:2.20.0" - dependencies: - base-64: "npm:^0.1.0" - utf8: "npm:^3.0.0" - peerDependencies: - react-native: "*" - react-native-windows: "*" - peerDependenciesMeta: - react-native-windows: - optional: true - checksum: 10/372e59f55d5e544e87093d832896fa3d56ba9802ca140c17b4b8903afe047714e022d3b1a2ddf18d744cb7f4f973593c8083641db9ae0768688b1390078d67a2 - languageName: node - linkType: hard - "react-native-image-picker@npm:^7.1.2": version: 7.1.2 resolution: "react-native-image-picker@npm:7.1.2" @@ -13484,13 +13460,6 @@ __metadata: languageName: node linkType: hard -"utf8@npm:^3.0.0": - version: 3.0.0 - resolution: "utf8@npm:3.0.0" - checksum: 10/31d19c4faacbb65b09ebc1c21c32b20bdb0919c6f6773cee5001b99bb83f8e503e7233c08fc71ebb34f7cfebd95cec3243b81d90176097aa2f286cccb4ce866e - languageName: node - linkType: hard - "util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2"