vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
if(NOT HAVE_JULIA)
|
||||
message(STATUS "Julia not found. Not compiling Julia Bindings. ${HAVE_JULIA}")
|
||||
ocv_module_disable(julia)
|
||||
elseif(NOT PYTHON_DEFAULT_EXECUTABLE)
|
||||
message(WARNING "Python required for Julia bindings...disabling")
|
||||
ocv_module_disable(julia)
|
||||
endif()
|
||||
|
||||
# WARN_MIXED_PRECISION
|
||||
macro(WARN_MIXED_PRECISION COMPILER_BITNESS JULIA_BITNESS)
|
||||
set(MSG "Your compiler is ${COMPILER_BITNESS}-bit")
|
||||
set(MSG "${MSG} but your version of Julia is ${JULIA_BITNESS}-bit.")
|
||||
set(MSG "${MSG} To build Julia bindings, please switch to a ${JULIA_BITNESS}-bit compiler.")
|
||||
message(WARNING ${MSG})
|
||||
endmacro()
|
||||
|
||||
|
||||
math(EXPR ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
|
||||
if (${ARCH} EQUAL 32 AND ${Julia_WORD_SIZE} MATCHES "64")
|
||||
warn_mixed_precision("32" "64")
|
||||
ocv_module_disable(julia)
|
||||
return()
|
||||
elseif (${ARCH} EQUAL 64 AND NOT ${Julia_WORD_SIZE} MATCHES "64")
|
||||
warn_mixed_precision("64" "32")
|
||||
ocv_module_disable(julia)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT JlCxx_DIR)
|
||||
execute_process(
|
||||
COMMAND "${Julia_EXECUTABLE}" --startup-file=no -e "using CxxWrap; print(CxxWrap.CxxWrapCore.prefix_path())"
|
||||
OUTPUT_VARIABLE JlCxx_DIR
|
||||
)
|
||||
endif()
|
||||
|
||||
if(JlCxx_DIR)
|
||||
if(EXISTS ${JlCxx_DIR}/JlCxxConfig.cmake)
|
||||
else()
|
||||
message(STATUS "JlCxx found but not source build - disabling Julia module")
|
||||
ocv_module_disable(julia)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(JlCxx QUIET)
|
||||
|
||||
if(NOT JlCxx_FOUND)
|
||||
message(STATUS "JlCxx not found")
|
||||
ocv_module_disable(julia)
|
||||
return()
|
||||
else()
|
||||
message(STATUS "JlCxx_DIR: ${JlCxx_DIR}")
|
||||
endif()
|
||||
|
||||
set(JlCxx_DIR "${JlCxx_DIR}" CACHE STRING ADVANCED)
|
||||
set(HAVE_JULIA "YES" CACHE STRING ADVANCED)
|
||||
|
||||
|
||||
set(the_description "The Julia bindings")
|
||||
ocv_add_module(
|
||||
julia
|
||||
BINDINGS
|
||||
OPTIONAL
|
||||
opencv_core
|
||||
opencv_imgproc
|
||||
opencv_imgcodecs
|
||||
opencv_highgui
|
||||
opencv_videoio
|
||||
opencv_dnn
|
||||
opencv_features
|
||||
opencv_objdetect
|
||||
opencv_calib3d
|
||||
)
|
||||
|
||||
set(HDR_PARSER_PATH ${CMAKE_SOURCE_DIR}/modules/python/src2/hdr_parser.py)
|
||||
|
||||
set(opencv_hdrs "")
|
||||
foreach(m ${OPENCV_MODULES_BUILD})
|
||||
list(APPEND opencv_hdrs ${OPENCV_MODULE_${m}_HEADERS})
|
||||
endforeach(m)
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/gen/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/gen)
|
||||
file(COPY ${HDR_PARSER_PATH} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/gen)
|
||||
|
||||
message(STATUS "Generating Julia Binding Files")
|
||||
|
||||
execute_process(
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/gen"
|
||||
COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/gen/gen_all.py" ${CMAKE_SOURCE_DIR}/modules ${OPENCV_MODULES_BUILD}
|
||||
)
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_BINARY_DIR}/gen/cpp_files/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/gen/autogen_cpp)
|
||||
file(COPY ${CMAKE_CURRENT_BINARY_DIR}/gen/jl_cxx_files/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/gen/autogen_jl)
|
||||
|
||||
ocv_glob_module_sources()
|
||||
ocv_module_include_directories()
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-prototypes -Wmissing-declarations)
|
||||
|
||||
ocv_add_library(${the_module} SHARED ${OPENCV_MODULE_${the_module}_HEADERS}
|
||||
${OPENCV_MODULE_${the_module}_SOURCES}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/gen/autogen_cpp/cv_core.cpp")
|
||||
|
||||
if(NOT JULIA_PKG_INSTALL_PATH)
|
||||
set(JULIA_PKG_INSTALL_PATH ${CMAKE_BINARY_DIR})
|
||||
endif()
|
||||
set(JULIA_PKG_INSTALL_PATH_HOOK ${JULIA_PKG_INSTALL_PATH} CACHE STRING "" FORCE)
|
||||
mark_as_advanced(JULIA_PKG_INSTALL_PATH_HOOK)
|
||||
|
||||
|
||||
message(STATUS "Installing ${the_module} bindings at ${JULIA_PKG_INSTALL_PATH}")
|
||||
|
||||
|
||||
install(DIRECTORY package/ DESTINATION ${JULIA_PKG_INSTALL_PATH})
|
||||
install(TARGETS ${the_module} LIBRARY DESTINATION ${JULIA_PKG_INSTALL_PATH}/OpenCV/src/lib)
|
||||
|
||||
|
||||
if(JULIA_PKG_INSTALL_ENV)
|
||||
set(JULIA_PKG_EXECS "Pkg.activate(${JULIA_PKG_INSTALL_ENV});${JULIA_PKG_EXECS}")
|
||||
endif()
|
||||
|
||||
|
||||
set(JULIA_COMMAND "\"${Julia_EXECUTABLE}\" -e \"using Pkg; ${JULIA_PKG_EXECS}\"")
|
||||
# message(STATUS "Installing Julia bindings using ${JULIA_COMMAND}")
|
||||
|
||||
|
||||
if(NOT INSTALL_CREATE_DISTRIB)
|
||||
install(CODE "
|
||||
set(JULIA_PKG_PATH \"${JULIA_PKG_INSTALL_PATH}/OpenCV\")
|
||||
execute_process(COMMAND \"${Julia_EXECUTABLE}\" ${CMAKE_CURRENT_LIST_DIR}/package/install_package.jl \${JULIA_PKG_PATH} OUTPUT_VARIABLE JULIA_INSTALL_OUT)
|
||||
message(STATUS \"Install output: \${JULIA_INSTALL_OUT}\")
|
||||
")
|
||||
endif()
|
||||
|
||||
|
||||
# ocv_create_module()
|
||||
|
||||
# ocv_add_accuracy_tests()
|
||||
# ocv_add_perf_tests()
|
||||
ocv_add_samples()
|
||||
|
||||
message(STATUS ${OPENCV_MODULE_${the_module}_DEPS_TO_LINK})
|
||||
|
||||
ocv_target_link_libraries(${the_module} PUBLIC ${OPENCV_MODULE_${the_module}_DEPS_TO_LINK}
|
||||
INTERFACE ${OPENCV_MODULE_${the_module}_DEPS_TO_LINK}
|
||||
)
|
||||
ocv_target_link_libraries(${the_module} PUBLIC ${OPENCV_MODULE_${the_module}_DEPS_EXT}
|
||||
INTERFACE ${OPENCV_MODULE_${the_module}_DEPS_EXT}
|
||||
)
|
||||
ocv_target_link_libraries(${the_module} PRIVATE ${OPENCV_LINKER_LIBS} ${OPENCV_HAL_LINKER_LIBS} ${IPP_LIBS} ${ARGN})
|
||||
|
||||
ocv_target_link_libraries(${the_module} JlCxx::cxxwrap_julia)
|
||||
ocv_target_link_libraries(${the_module} JlCxx::cxxwrap_julia_stl)
|
||||
|
||||
# targets# opencv_julia_sources --> opencv_julia
|
||||
|
||||
|
||||
add_custom_command(TARGET ${the_module}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/package/OpenCV ${CMAKE_BINARY_DIR}/OpenCV
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/gen/autogen_jl/ ${CMAKE_BINARY_DIR}/OpenCV/src
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${the_module}> ${CMAKE_BINARY_DIR}/OpenCV/src/lib/libopencv_julia
|
||||
COMMENT "Copying over julia package"
|
||||
)
|
||||
|
||||
|
||||
|
||||
if (BUILD_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
@@ -0,0 +1,3 @@
|
||||
The code is a part of OpenCV and is distributed under Apache 2 license.
|
||||
See https://www.apache.org/licenses/LICENSE-2.0
|
||||
Copyright (C) 2020 by Archit Rungta.
|
||||
@@ -0,0 +1,107 @@
|
||||
OpenCV Julia Bindings
|
||||
============================
|
||||
This module contains some limited functionality that allows OpenCV functions be used from Julia. Upon installation the binding files are automatically registered with Julia's package manager like any normal package.
|
||||
|
||||
This module requires Julia 1.4 and the CxxWrap.jl 0.10 when built from source. To use the compiled binary distributions Julia 1.6 is recommended.
|
||||
|
||||
Using Prebuilt Binaries
|
||||
---
|
||||
The easiest way to use OpenCV from Julia bindings is to use the version registered with Julia's package manager. This is also the only tested way to use Julia bindings on Windows. To do that simply start the Julia REPL. Hit `]` and then type `add OpenCV`.
|
||||
|
||||
```bash
|
||||
$ julia
|
||||
...
|
||||
julia> ]
|
||||
pkg> add OpenCV
|
||||
```
|
||||
|
||||
---
|
||||
The following steps walk over a source build of the Julia bindings.
|
||||
|
||||
CxxWrap Installation
|
||||
----
|
||||
Installation of CxxWrap is like any other Julia Package. Just start the REPL. Hit `]` and then type `add CxxWrap`.
|
||||
|
||||
```
|
||||
$ julia
|
||||
...
|
||||
julia> ]
|
||||
pkg> add CxxWrap
|
||||
```
|
||||
|
||||
For now, Julia module is only compatible with Ubuntu and MacOS. Also, you must use a source build of [libcxxwrap-julia](https://github.com/JuliaInterop/libcxxwrap-julia). Follow the link for instructions on how to do that.
|
||||
|
||||
Build
|
||||
-----
|
||||
The Julia module is fully integrated into the OpenCV build system. While compiling add this to your command line `-DWITH_JULIA=ON`. If cmake finds a Julia executable available on the host system while configuring OpenCV, it will attempt to generate Julia wrappers for all OpenCV modules. If cmake is having trouble finding your Julia installation, you can explicitly point it to the Julia executable by defining the `Julia_EXECUTABLE` variable. For example:
|
||||
|
||||
cmake -DWITH_JULIA=ON -DJulia_EXECUTABLE=/home/user/julia-1.4.1/bin ..
|
||||
|
||||
If you prefer using the gui version of cmake (cmake-gui), you can use the *Add Entry* option in the GUI to manually add the *path* variable `Julia_EXECUTABLE`.
|
||||
|
||||
Note, you need a valid Python installation to build the Julia Bindings.
|
||||
|
||||
Install
|
||||
-------
|
||||
By default the Julia package is installed in `CMAKE_BINARY_DIR`, you can change this by setting the `JULIA_PKG_INSTALL_PATH` cmake variable. The package is automatically registered with the Julia package manager.
|
||||
|
||||
---
|
||||
|
||||
Run
|
||||
---
|
||||
|
||||
In order to use the bindings, simply type
|
||||
```bash
|
||||
$ julia
|
||||
...
|
||||
julia> using OpenCV
|
||||
```
|
||||
|
||||
Note that this works only if you called `make install`. To run the wrapper package without making the installation target you must first set the environment variable `JULIA_LOAD_PATH` to the directory containing the OpenCV package. For example if in the build directory
|
||||
```bash
|
||||
$ export JULIA_LOAD_PATH=$PWD/OpenCV
|
||||
$ julia
|
||||
...
|
||||
julia> using OpenCV
|
||||
```
|
||||
|
||||
The Julia package does not export any symbols so all functions/structs/constants must be prefixed with OpenCV
|
||||
```Julia
|
||||
using OpenCV
|
||||
const cv = OpenCV
|
||||
img = cv.imread('cameraman.tif');
|
||||
|
||||
cv.imshow("window name", img)
|
||||
|
||||
cv.waitKey(Int32(0))
|
||||
```
|
||||
|
||||
Finally, because Julia does not support OOP paradigm some changes had to be made. To access functions like `obj.function(ARGS)` you should instead use `function(obj, ARGS)`. The below example of reading frames from a VideoCapture should make it more clear.
|
||||
|
||||
```Julia
|
||||
cap = OpenCV.VideoCapture(Int32(0))
|
||||
ret, img = OpenCV.read(cap)
|
||||
```
|
||||
|
||||
Instead of calling `cap.read()`, we called `OpenCV.read(cap)`
|
||||
|
||||
Another change is that all integer and float constants might need to prefixed with appropriate type constructor. This is needed because OpenCV functions accept 32-bit integers/floats but integer and float constants in Julia are sized based on the whether Julia is running in 64bit or 32bit mode.
|
||||
|
||||
------------------------------------------------------------------
|
||||
|
||||
|
||||
Usage
|
||||
---
|
||||
This section has some more information about how to use the Julia bindings.
|
||||
|
||||
The function signatures are identical to Python bindings except the previously mentioned OOP exception. All functions that will accept a Mat/numpy array in C++/Python signatures will instead accept `OpenCV.InputArray` type in the Julia functions. `OpenCV.InputArray` is a union type between `CxxMat` and `AbstractArray{T, 3}`. As such, you can pass any arrays generated by any Julia function directly into OpenCV. If the AbstractArray is strided and has appropriate strides, the bindings will try to directly pass the memory region to OpenCV functions. However, if that's not possible then the array will first be copied to a `DenseArray` and then passed to OpenCV. The previously mentioned `CxxMat` is a black-box pointer type and should never be needed by users.
|
||||
|
||||
The output arrays of all OpenCV functions are of the type `OpenCV.Mat{T}`. Currently, all array input and output is restricted to 3D only (2D Mat and an additional dimension for color channels). The `OpenCV.Mat` type inherits from `AbstractArray{T, 3}` and can be directly passed to any Julia function that accepts AbstractArray types. It internally maintains a pointer to the original C++ `Mat` type to make sure that the memory is never deallocated. However, if you copy the `OpenCV.Mat` type object then the pointer is not copied and array moves to a Julia owned memory space.
|
||||
|
||||
All other types map directly to the corresponding types on C++. Unlike Python, `Point`, `Size`, `Rect` etc are represented not as tuples but as appropriate objects like `OpenCV.Point{Float32}` and so on. However, `Scalar` types are a tuple of numbers where the tuple has a size of 1-4.
|
||||
|
||||
|
||||
Current Functionality
|
||||
---
|
||||
|
||||
The bindings implement most of the functionality present in the core,imgproc,highgui,videoio,dnn,calib3d and imgcodecs. The samples also implement some additional manually wrapped functionality. The complete list of automatically wrapped functionality is [here](gen/funclist.csv).
|
||||
@@ -0,0 +1,169 @@
|
||||
|
||||
# Original FindJulia.cmake from https://github.com/QuantStack/xtensor-julia-cookiecutter/blob/master/%7B%7Bcookiecutter.github_project_name%7D%7D/cmake/FindJulia.cmake
|
||||
if(Julia_FOUND)
|
||||
return()
|
||||
endif()
|
||||
|
||||
####################
|
||||
# Julia Executable #
|
||||
####################
|
||||
|
||||
find_program(Julia_EXECUTABLE julia DOC "Julia executable")
|
||||
|
||||
#################
|
||||
# Julia Version #
|
||||
#################
|
||||
|
||||
if(Julia_EXECUTABLE)
|
||||
message(STATUS "Found Julia executable: " ${Julia_EXECUTABLE})
|
||||
|
||||
execute_process(
|
||||
COMMAND "${Julia_EXECUTABLE}" --startup-file=no --version
|
||||
OUTPUT_VARIABLE Julia_VERSION_STRING
|
||||
)
|
||||
else()
|
||||
return()
|
||||
endif()
|
||||
|
||||
string(
|
||||
REGEX REPLACE ".*([0-9]+\\.[0-9]+\\.[0-9]+).*" "\\1"
|
||||
Julia_VERSION_STRING "${Julia_VERSION_STRING}"
|
||||
)
|
||||
|
||||
MESSAGE(STATUS "Julia_VERSION_STRING: ${Julia_VERSION_STRING}")
|
||||
|
||||
##################
|
||||
# Julia Includes #
|
||||
##################
|
||||
|
||||
set(JULIA_HOME_NAME "Sys.BINDIR")
|
||||
if(${Julia_VERSION_STRING} VERSION_LESS "0.7.0")
|
||||
set(JULIA_HOME_NAME "JULIA_HOME")
|
||||
else()
|
||||
set(USING_LIBDL "using Libdl")
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{JULIA_INCLUDE_DIRS})
|
||||
set(Julia_INCLUDE_DIRS $ENV{JULIA_INCLUDE_DIRS}
|
||||
CACHE STRING "Location of Julia include files")
|
||||
elseif(Julia_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${Julia_EXECUTABLE} --startup-file=no -E "julia_include_dir = joinpath(match(r\"(.*)(bin)\",${JULIA_HOME_NAME}).captures[1],\"include\",\"julia\")\n
|
||||
if !isdir(julia_include_dir) # then we're running directly from build\n
|
||||
julia_base_dir_aux = splitdir(splitdir(${JULIA_HOME_NAME})[1])[1] # useful for running-from-build\n
|
||||
julia_include_dir = joinpath(julia_base_dir_aux, \"usr\", \"include\" )\n
|
||||
julia_include_dir *= \";\" * joinpath(julia_base_dir_aux, \"src\", \"support\" )\n
|
||||
julia_include_dir *= \";\" * joinpath(julia_base_dir_aux, \"src\" )\n
|
||||
end\n
|
||||
julia_include_dir"
|
||||
OUTPUT_VARIABLE Julia_INCLUDE_DIRS
|
||||
)
|
||||
|
||||
string(REGEX REPLACE "\"" "" Julia_INCLUDE_DIRS "${Julia_INCLUDE_DIRS}")
|
||||
string(REGEX REPLACE "\n" "" Julia_INCLUDE_DIRS "${Julia_INCLUDE_DIRS}")
|
||||
set(Julia_INCLUDE_DIRS ${Julia_INCLUDE_DIRS}
|
||||
CACHE PATH "Location of Julia include files")
|
||||
elseif(Julia_PREFIX)
|
||||
set(Julia_INCLUDE_DIRS ${Julia_PREFIX}/include/julia)
|
||||
endif()
|
||||
MESSAGE(STATUS "Julia_INCLUDE_DIRS: ${Julia_INCLUDE_DIRS}")
|
||||
|
||||
###################
|
||||
# Julia Libraries #
|
||||
###################
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .a)
|
||||
endif()
|
||||
|
||||
if(Julia_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${Julia_EXECUTABLE} --startup-file=no -E "${USING_LIBDL}\nabspath(Libdl.dlpath((ccall(:jl_is_debugbuild, Cint, ()) != 0) ? \"libjulia-debug\" : \"libjulia\"))"
|
||||
OUTPUT_VARIABLE Julia_LIBRARY
|
||||
)
|
||||
|
||||
string(REGEX REPLACE "\"" "" Julia_LIBRARY "${Julia_LIBRARY}")
|
||||
string(REGEX REPLACE "\n" "" Julia_LIBRARY "${Julia_LIBRARY}")
|
||||
string(STRIP "${Julia_LIBRARY}" Julia_LIBRARY)
|
||||
|
||||
if(WIN32)
|
||||
get_filename_component(Julia_LIBRARY_DIR ${Julia_LIBRARY} DIRECTORY)
|
||||
get_filename_component(Julia_LIBRARY_DIR ${Julia_LIBRARY_DIR} DIRECTORY)
|
||||
find_library(win_Julia_LIBRARY
|
||||
NAMES libjulia.dll.a
|
||||
PATHS "${Julia_LIBRARY_DIR}/lib"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
set(Julia_LIBRARY "${win_Julia_LIBRARY}")
|
||||
endif()
|
||||
|
||||
set(Julia_LIBRARY "${Julia_LIBRARY}"
|
||||
CACHE PATH "Julia library")
|
||||
else()
|
||||
find_library(Julia_LIBRARY NAMES libjulia.${Julia_VERSION_STRING}.dylib julia libjulia libjulia.dll.a CMAKE_FIND_ROOT_PATH_BOTH)
|
||||
endif()
|
||||
|
||||
get_filename_component(Julia_LIBRARY_DIR ${Julia_LIBRARY} DIRECTORY)
|
||||
|
||||
MESSAGE(STATUS "Julia_LIBRARY_DIR: ${Julia_LIBRARY_DIR}")
|
||||
MESSAGE(STATUS "Julia_LIBRARY: ${Julia_LIBRARY}")
|
||||
|
||||
##############
|
||||
# JULIA_HOME #
|
||||
##############
|
||||
|
||||
if(Julia_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${Julia_EXECUTABLE} --startup-file=no -E "${JULIA_HOME_NAME}"
|
||||
OUTPUT_VARIABLE JULIA_HOME
|
||||
)
|
||||
|
||||
string(REGEX REPLACE "\"" "" JULIA_HOME "${JULIA_HOME}")
|
||||
string(REGEX REPLACE "\n" "" JULIA_HOME "${JULIA_HOME}")
|
||||
|
||||
MESSAGE(STATUS "JULIA_HOME: ${JULIA_HOME}")
|
||||
|
||||
###################
|
||||
# libLLVM version #
|
||||
###################
|
||||
|
||||
execute_process(
|
||||
COMMAND ${Julia_EXECUTABLE} --startup-file=no -E "Base.libllvm_version"
|
||||
OUTPUT_VARIABLE Julia_LLVM_VERSION
|
||||
)
|
||||
|
||||
string(REGEX REPLACE "\"" "" Julia_LLVM_VERSION "${Julia_LLVM_VERSION}")
|
||||
string(REGEX REPLACE "\n" "" Julia_LLVM_VERSION "${Julia_LLVM_VERSION}")
|
||||
|
||||
MESSAGE(STATUS "Julia_LLVM_VERSION: ${Julia_LLVM_VERSION}")
|
||||
endif()
|
||||
|
||||
##################################
|
||||
# Check for Existence of Headers #
|
||||
##################################
|
||||
|
||||
find_path(Julia_MAIN_HEADER julia.h HINTS ${Julia_INCLUDE_DIRS})
|
||||
|
||||
#######################################
|
||||
# Determine if we are on 32 or 64 bit #
|
||||
#######################################
|
||||
|
||||
if(Julia_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${Julia_EXECUTABLE} --startup-file=no -E "Sys.WORD_SIZE"
|
||||
OUTPUT_VARIABLE Julia_WORD_SIZE
|
||||
)
|
||||
string(REGEX REPLACE "\n" "" Julia_WORD_SIZE "${Julia_WORD_SIZE}")
|
||||
MESSAGE(STATUS "Julia_WORD_SIZE: ${Julia_WORD_SIZE}")
|
||||
endif()
|
||||
|
||||
###########################
|
||||
# FindPackage Boilerplate #
|
||||
###########################
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Julia
|
||||
REQUIRED_VARS Julia_LIBRARY Julia_LIBRARY_DIR Julia_INCLUDE_DIRS Julia_MAIN_HEADER Julia_EXECUTABLE
|
||||
VERSION_VAR Julia_VERSION_STRING
|
||||
FAIL_MESSAGE "Julia not found"
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
# ========================= julia =========================
|
||||
if(WITH_JULIA OR HAVE_JULIA)
|
||||
status("")
|
||||
status(" JULIA:" HAVE_JULIA THEN "YES" ELSE "NO")
|
||||
if(HAVE_JULIA)
|
||||
status(" Julia_EXECUTABLE:" ${Julia_EXECUTABLE})
|
||||
status(" JlCxx_DIR:" ${JlCxx_DIR})
|
||||
if(HAVE_JULIA MATCHES "YES")
|
||||
status(" JULIA_PKG_INSTALL_PATH:" ${JULIA_PKG_INSTALL_PATH_HOOK})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,18 @@
|
||||
OCV_OPTION(WITH_JULIA "Include Julia support (opencv_contrib)" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT AND NOT WIN32))
|
||||
|
||||
ocv_assert(OPENCV_INITIAL_PASS)
|
||||
|
||||
if(WITH_JULIA OR DEFINED Julia_FOUND)
|
||||
ocv_cmake_hook_append(STATUS_DUMP_EXTRA "${CMAKE_CURRENT_LIST_DIR}/hooks/STATUS_DUMP_EXTRA.cmake")
|
||||
endif()
|
||||
|
||||
# --- Julia ---
|
||||
if(WITH_JULIA AND NOT DEFINED Julia_FOUND)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/FindJulia.cmake)
|
||||
if(NOT Julia_FOUND)
|
||||
message(WARNING "Julia was not found. Disabling Julia bindings...")
|
||||
ocv_module_disable(julia)
|
||||
endif()
|
||||
|
||||
set(HAVE_JULIA ON)
|
||||
endif()
|
||||
@@ -0,0 +1,148 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
// Copyright (C) 2020 by Archit Rungta
|
||||
|
||||
#include "jlcxx/array.hpp"
|
||||
#include "jlcxx/jlcxx.hpp"
|
||||
#include "jlcxx/functions.hpp"
|
||||
#include "jlcxx/stl.hpp"
|
||||
#include "jlcxx/tuple.hpp"
|
||||
|
||||
#include "jlcv.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
using namespace jlcxx;
|
||||
|
||||
|
||||
namespace jlcxx
|
||||
{
|
||||
template <typename T>
|
||||
struct IsSmartPointerType<cv::Ptr<T>> : std::true_type
|
||||
{
|
||||
};
|
||||
template <typename T>
|
||||
struct ConstructorPointerType<cv::Ptr<T>>
|
||||
{
|
||||
typedef T *type;
|
||||
};
|
||||
|
||||
template<typename T, int Val>
|
||||
struct BuildParameterList<cv::Vec<T, Val>>
|
||||
{
|
||||
typedef ParameterList<T, std::integral_constant<int, Val>> type;
|
||||
};
|
||||
${include_code}
|
||||
|
||||
|
||||
//
|
||||
// Manual Wrapping BEGIN
|
||||
//
|
||||
|
||||
#ifdef HAVE_OPENCV_FEATURES
|
||||
// template <>
|
||||
// struct SuperType<cv::Feature2D>
|
||||
// {
|
||||
// typedef cv::Algorithm type;
|
||||
// };
|
||||
// TODO: Needs to be fixed but doesn't matter for now
|
||||
template <>
|
||||
struct SuperType<cv::SimpleBlobDetector>
|
||||
{
|
||||
typedef cv::Feature2D type;
|
||||
};
|
||||
#endif
|
||||
|
||||
//
|
||||
// Manual Wrapping END
|
||||
//
|
||||
} // namespace jlcxx
|
||||
JLCXX_MODULE cv_wrap(jlcxx::Module &mod)
|
||||
{
|
||||
mod.map_type<RotatedRect>("RotatedRect");
|
||||
mod.map_type<TermCriteria>("TermCriteria");
|
||||
mod.map_type<Range>("Range");
|
||||
|
||||
mod.add_type<Parametric<TypeVar<1>, TypeVar<2>>>("CxxVec")
|
||||
.apply<Vec4f, Vec6f, Vec3d, Vec2d>([](auto wrapped){
|
||||
typedef typename decltype(wrapped)::type WrappedT;
|
||||
typedef typename get_template_type_vec<WrappedT>::type T;
|
||||
wrapped.template constructor<const T*>();
|
||||
});
|
||||
|
||||
mod.add_type<Mat>("CxxMat").constructor<int, const int *, int, void *, const size_t *>();
|
||||
|
||||
mod.method("jlopencv_core_get_sizet", [](){return sizeof(size_t);});
|
||||
jlcxx::add_smart_pointer<cv::Ptr>(mod, "cv_Ptr");
|
||||
mod.method("jlopencv_core_Mat_mutable_data", [](Mat m) {
|
||||
return make_tuple(m.data, m.type(), m.channels(), m.size[1], m.size[0], m.step[1], m.step[0]);
|
||||
});
|
||||
|
||||
|
||||
mod.add_type<Parametric<TypeVar<1>>>("CxxScalar")
|
||||
.apply<Scalar_<int>, Scalar_<float>, Scalar_<double>>([](auto wrapped) {
|
||||
typedef typename decltype(wrapped)::type WrappedT;
|
||||
typedef typename get_template_type<WrappedT>::type T;
|
||||
wrapped.template constructor<T, T, T, T>();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Manual Wrapping BEGIN
|
||||
//
|
||||
|
||||
#ifdef HAVE_OPENCV_HIGHGUI
|
||||
mod.method("createButton", [](const string & bar_name, jl_function_t* on_change, int type, bool initial_button_state) {createButton(bar_name, [](int s, void* c) {
|
||||
JuliaFunction f((jl_function_t*)c);
|
||||
f(forward<int>(s));
|
||||
}, (void*)on_change, type, initial_button_state);});
|
||||
|
||||
mod.method("setMouseCallback", [](const string & winname, jl_function_t* onMouse) {
|
||||
setMouseCallback(winname, [](int event, int x, int y, int flags, void* c) {
|
||||
JuliaFunction f((jl_function_t*)c);
|
||||
f(forward<int>(event), forward<int>(x), forward<int>(y), forward<int>(flags));
|
||||
}, (void*)onMouse);});
|
||||
|
||||
mod.method("createTrackbar", [](const String &trackbarname, const String &winname, int& value, int count, jl_function_t* onChange) {
|
||||
createTrackbar(trackbarname, winname, &value, count, [](int s, void* c) {
|
||||
JuliaFunction f((jl_function_t*)c);
|
||||
f(forward<int>(s));
|
||||
}, (void*)onChange);});
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_OBJDETECT
|
||||
mod.add_type<cv::CascadeClassifier>("CascadeClassifier");
|
||||
mod.method("jlopencv_cv_cv_CascadeClassifier_cv_CascadeClassifier_CascadeClassifier", [](string &filename) { return jlcxx::create<cv::CascadeClassifier>(filename); });
|
||||
mod.method("jlopencv_cv_cv_CascadeClassifier_cv_CascadeClassifier_detectMultiScale", [](cv::CascadeClassifier &cobj, Mat &image, double &scaleFactor, int &minNeighbors, int &flags, Size &minSize, Size &maxSize) {vector<Rect> objects; cobj.detectMultiScale(image, objects, scaleFactor, minNeighbors, flags, minSize, maxSize); return objects; });
|
||||
mod.method("jlopencv_cv_cv_CascadeClassifier_cv_CascadeClassifier_empty", [](cv::CascadeClassifier &cobj) { auto retval = cobj.empty(); return retval; });
|
||||
|
||||
mod.set_const("CASCADE_DO_CANNY_PRUNING", (int)cv::CASCADE_DO_CANNY_PRUNING);
|
||||
mod.set_const("CASCADE_DO_ROUGH_SEARCH", (int)cv::CASCADE_DO_ROUGH_SEARCH);
|
||||
mod.set_const("CASCADE_FIND_BIGGEST_OBJECT", (int)cv::CASCADE_FIND_BIGGEST_OBJECT);
|
||||
mod.set_const("CASCADE_SCALE_IMAGE", (int)cv::CASCADE_SCALE_IMAGE);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_FEATURES
|
||||
mod.add_type<cv::Feature2D>("Feature2D");
|
||||
mod.add_type<cv::SimpleBlobDetector>("SimpleBlobDetector", jlcxx::julia_base_type<cv::Feature2D>());
|
||||
mod.add_type<cv::SimpleBlobDetector::Params>("SimpleBlobDetector_Params");
|
||||
#endif
|
||||
|
||||
//
|
||||
// Manual Wrapping END
|
||||
//
|
||||
|
||||
${cpp_code}
|
||||
|
||||
#ifdef HAVE_OPENCV_FEATURES
|
||||
|
||||
mod.method("jlopencv_cv_cv_Feature2D_cv_Feature2D_detect", [](cv::Ptr<cv::Feature2D> &cobj, Mat &image, Mat &mask) {vector<KeyPoint> keypoints; cobj->detect(image, keypoints, mask); return keypoints; });
|
||||
mod.method("jlopencv_cv_cv_SimpleBlobDetector_create", [](SimpleBlobDetector_Params ¶meters) { auto retval = cv::SimpleBlobDetector::create(parameters); return retval; });
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
${code}
|
||||
|
||||
${submodule_imports}
|
||||
@@ -0,0 +1,7 @@
|
||||
module ${modname}
|
||||
import ..OpenCV
|
||||
|
||||
${code}
|
||||
|
||||
${submodule_imports}
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
${code}
|
||||
|
||||
${submodule_imports}
|
||||
@@ -0,0 +1,122 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
// Copyright (C) 2020 by Archit Rungta
|
||||
|
||||
// This header files hacks into the mapping code of CxxWrap to support automatic conversion between types from OpenCV and Julia
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "jlcxx/jlcxx.hpp"
|
||||
#include "jlcxx/functions.hpp"
|
||||
#include "jlcxx/stl.hpp"
|
||||
#include "jlcxx/array.hpp"
|
||||
#include "jlcxx/tuple.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include <opencv2/core/ocl.hpp>
|
||||
|
||||
#include <opencv2/core/bindings_utils.hpp>
|
||||
|
||||
|
||||
#include <opencv2/opencv_modules.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
using namespace jlcxx;
|
||||
|
||||
#ifdef HAVE_OPENCV_HIGHGUI
|
||||
#include <opencv2/highgui.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_IMGPROC
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_VIDEOIO
|
||||
#include <opencv2/videoio.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_FEATURES
|
||||
#include <opencv2/features.hpp>
|
||||
typedef SimpleBlobDetector::Params SimpleBlobDetector_Params;
|
||||
typedef AKAZE::DescriptorType AKAZE_DescriptorType;
|
||||
typedef AgastFeatureDetector::DetectorType AgastFeatureDetector_DetectorType;
|
||||
typedef FastFeatureDetector::DetectorType FastFeatureDetector_DetectorType;
|
||||
typedef DescriptorMatcher::MatcherType DescriptorMatcher_MatcherType;
|
||||
typedef KAZE::DiffusivityType KAZE_DiffusivityType;
|
||||
typedef ORB::ScoreType ORB_ScoreType;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_XOBJDETECT
|
||||
|
||||
#include <opencv2/xobjdetect.hpp>
|
||||
|
||||
typedef HOGDescriptor::HistogramNormType HOGDescriptor_HistogramNormType;
|
||||
typedef HOGDescriptor::DescriptorStorageFormat HOGDescriptor_DescriptorStorageFormat;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_FLANN
|
||||
typedef cvflann::flann_distance_t cvflann_flann_distance_t;
|
||||
typedef cvflann::flann_algorithm_t cvflann_flann_algorithm_t;
|
||||
|
||||
typedef flann::IndexParams flann_IndexParams;
|
||||
typedef flann::SearchParams flann_SearchParams;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
|
||||
#include <opencv2/dnn.hpp>
|
||||
typedef cv::dnn::DictValue LayerId;
|
||||
typedef cv::dnn::Backend dnn_Backend;
|
||||
typedef cv::dnn::Target dnn_Target;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_CALIB3D
|
||||
|
||||
#include <opencv2/calib3d.hpp>
|
||||
#endif
|
||||
|
||||
template <typename C>
|
||||
struct get_template_type;
|
||||
template <typename C>
|
||||
struct get_template_type_vec;
|
||||
|
||||
template <template <typename> class C, typename T>
|
||||
struct get_template_type<C<T>> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <template <typename, int> class C, typename T, int N>
|
||||
struct get_template_type_vec<C<T, N>> {
|
||||
using type = T;
|
||||
int dim = N;
|
||||
};
|
||||
|
||||
template<typename T, bool v>
|
||||
struct force_enum{};
|
||||
template<typename T>
|
||||
struct force_enum<T, false>{
|
||||
using Type = T;
|
||||
};
|
||||
template<typename T>
|
||||
struct force_enum<T, true>{
|
||||
using Type = int64_t;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct force_enum_int{
|
||||
using Type = typename force_enum<T, std::is_enum<T>::value>::Type;
|
||||
};
|
||||
|
||||
typedef vector<Mat> vector_Mat;
|
||||
typedef vector<UMat> vector_UMat;
|
||||
|
||||
typedef char* c_string;
|
||||
|
||||
|
||||
#include "jlcv_types.hpp"
|
||||
@@ -0,0 +1,283 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
// Copyright (C) 2020 by Archit Rungta
|
||||
|
||||
template<typename T>
|
||||
struct CxxPoint
|
||||
{
|
||||
T x;
|
||||
T y;
|
||||
};
|
||||
template<typename T>
|
||||
struct CxxPoint3
|
||||
{
|
||||
T x;
|
||||
T y;
|
||||
T z;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct CxxSize
|
||||
{
|
||||
T width;
|
||||
T height;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct CxxRect
|
||||
{
|
||||
T x;
|
||||
T y;
|
||||
T width;
|
||||
T height;
|
||||
};
|
||||
|
||||
struct CxxRotatedRect
|
||||
{
|
||||
Point2f center;
|
||||
Size2f size;
|
||||
float angle;
|
||||
};
|
||||
|
||||
struct CxxRange
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
};
|
||||
|
||||
struct CxxTermCriteria
|
||||
{
|
||||
int type;
|
||||
int maxCount;
|
||||
double epsilon;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct CxxComplex
|
||||
{
|
||||
T re;
|
||||
T im;
|
||||
};
|
||||
|
||||
|
||||
namespace jlcxx
|
||||
{
|
||||
template <> struct IsMirroredType<cv::Range> : std::true_type {};
|
||||
template <> struct IsMirroredType<cv::RotatedRect> : std::true_type {};
|
||||
template <> struct IsMirroredType<cv::TermCriteria> : std::true_type {};
|
||||
|
||||
template<typename T> struct IsMirroredType<cv::Point_<T>> : std::true_type {};
|
||||
|
||||
template<typename T> struct static_type_mapping<cv::Point_<T>> { using type = CxxPoint<T>; };
|
||||
|
||||
template<typename T>
|
||||
struct julia_type_factory<cv::Point_<T>>
|
||||
{
|
||||
static inline jl_datatype_t* julia_type()
|
||||
{
|
||||
return (jl_datatype_t*)apply_type((jl_value_t*)jlcxx::julia_type("Point"), jl_svec1(julia_base_type<T>()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConvertToJulia<cv::Point_<T>, NoMappingTrait>
|
||||
{
|
||||
CxxPoint<T> operator()(const cv::Point_<T>& cpp_val) const
|
||||
{
|
||||
return *reinterpret_cast<const CxxPoint<T>*>(&cpp_val);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct ConvertToCpp<cv::Point_<T>, NoMappingTrait>
|
||||
{
|
||||
inline cv::Point operator()(const CxxPoint<T>& julia_val) const
|
||||
{
|
||||
return *reinterpret_cast<const cv::Point_<T>*>(&julia_val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename T> struct IsMirroredType<cv::Size_<T>> : std::true_type {};
|
||||
|
||||
template<typename T> struct static_type_mapping<cv::Size_<T>> { using type = CxxSize<T>; };
|
||||
|
||||
template<typename T>
|
||||
struct julia_type_factory<cv::Size_<T>>
|
||||
{
|
||||
static inline jl_datatype_t* julia_type()
|
||||
{
|
||||
return (jl_datatype_t*)apply_type((jl_value_t*)jlcxx::julia_type("Size"), jl_svec1(julia_base_type<T>()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConvertToJulia<cv::Size_<T>, NoMappingTrait>
|
||||
{
|
||||
CxxSize<T> operator()(const cv::Size_<T>& cpp_val) const
|
||||
{
|
||||
return *reinterpret_cast<const CxxSize<T>*>(&cpp_val);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct ConvertToCpp<cv::Size_<T>, NoMappingTrait>
|
||||
{
|
||||
inline cv::Size operator()(const CxxSize<T>& julia_val) const
|
||||
{
|
||||
return *reinterpret_cast<const cv::Size_<T>*>(&julia_val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename T> struct IsMirroredType<cv::Point3_<T>> : std::true_type {};
|
||||
|
||||
template<typename T> struct static_type_mapping<cv::Point3_<T>> { using type = CxxPoint3<T>; };
|
||||
|
||||
template<typename T>
|
||||
struct julia_type_factory<cv::Point3_<T>>
|
||||
{
|
||||
static inline jl_datatype_t* julia_type()
|
||||
{
|
||||
return (jl_datatype_t*)apply_type((jl_value_t*)jlcxx::julia_type("Point3"), jl_svec1(julia_base_type<T>()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConvertToJulia<cv::Point3_<T>, NoMappingTrait>
|
||||
{
|
||||
CxxPoint3<T> operator()(const cv::Point3_<T>& cpp_val) const
|
||||
{
|
||||
return *reinterpret_cast<const CxxPoint3<T>*>(&cpp_val);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct ConvertToCpp<cv::Point3_<T>, NoMappingTrait>
|
||||
{
|
||||
inline cv::Point3_<T> operator()(const CxxPoint3<T>& julia_val) const
|
||||
{
|
||||
return *reinterpret_cast<const cv::Point3_<T>*>(&julia_val);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct IsMirroredType<cv::Rect_<T>> : std::true_type {};
|
||||
|
||||
template<typename T> struct static_type_mapping<cv::Rect_<T>> { using type = CxxRect<T>; };
|
||||
|
||||
template<typename T>
|
||||
struct julia_type_factory<cv::Rect_<T>>
|
||||
{
|
||||
static inline jl_datatype_t* julia_type()
|
||||
{
|
||||
return (jl_datatype_t*)apply_type((jl_value_t*)jlcxx::julia_type("Rect"), jl_svec1(julia_base_type<T>()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConvertToJulia<cv::Rect_<T>, NoMappingTrait>
|
||||
{
|
||||
CxxRect<T> operator()(const cv::Rect_<T>& cpp_val) const
|
||||
{
|
||||
return *reinterpret_cast<const CxxRect<T>*>(&cpp_val);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct ConvertToCpp<cv::Rect_<T>, NoMappingTrait>
|
||||
{
|
||||
inline cv::Rect operator()(const CxxRect<T>& julia_val) const
|
||||
{
|
||||
return *reinterpret_cast<const cv::Rect_<T>*>(&julia_val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T> struct IsMirroredType<cv::Complex<T>> : std::true_type {};
|
||||
|
||||
template<typename T> struct static_type_mapping<cv::Complex<T>> { using type = CxxComplex<T>; };
|
||||
|
||||
template<typename T>
|
||||
struct julia_type_factory<cv::Complex<T>>
|
||||
{
|
||||
static inline jl_datatype_t* julia_type()
|
||||
{
|
||||
return (jl_datatype_t*)apply_type((jl_value_t*)jlcxx::julia_type("cvComplex"), jl_svec1(julia_base_type<T>()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConvertToJulia<cv::Complex<T>, NoMappingTrait>
|
||||
{
|
||||
CxxComplex<T> operator()(const cv::Complex<T>& cpp_val) const
|
||||
{
|
||||
return *reinterpret_cast<const CxxComplex<T>*>(&cpp_val);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct ConvertToCpp<cv::Complex<T>, NoMappingTrait>
|
||||
{
|
||||
inline cv::Complex<T> operator()(const CxxComplex<T>& julia_val) const
|
||||
{
|
||||
return *reinterpret_cast<const cv::Complex<T>*>(&julia_val);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BoxValue<Size_<T>,CxxSize<T>>
|
||||
{
|
||||
inline jl_value_t* operator()(Size_<T> cppval)
|
||||
{
|
||||
return jl_new_bits((jl_value_t*)julia_type<Size_<T>>(), reinterpret_cast<CxxSize<T>*>(&cppval));
|
||||
}
|
||||
|
||||
inline jl_value_t* operator()(Size_<T> cppval, jl_value_t* dt)
|
||||
{
|
||||
return jl_new_bits(dt, reinterpret_cast<CxxSize<T>*>(&cppval));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BoxValue<Point_<T>,CxxPoint<T>>
|
||||
{
|
||||
inline jl_value_t* operator()(Point_<T> cppval)
|
||||
{
|
||||
return jl_new_bits((jl_value_t*)julia_type<Point_<T>>(), reinterpret_cast<CxxPoint<T>*>(&cppval));
|
||||
}
|
||||
|
||||
inline jl_value_t* operator()(Point_<T> cppval, jl_value_t* dt)
|
||||
{
|
||||
return jl_new_bits(dt, reinterpret_cast<CxxPoint<T>*>(&cppval));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BoxValue<Point3_<T>,CxxPoint3<T>>
|
||||
{
|
||||
inline jl_value_t* operator()(Point3_<T> cppval)
|
||||
{
|
||||
return jl_new_bits((jl_value_t*)julia_type<Point3_<T>>(), reinterpret_cast<CxxPoint3<T>*>(&cppval));
|
||||
}
|
||||
|
||||
inline jl_value_t* operator()(Point3_<T> cppval, jl_value_t* dt)
|
||||
{
|
||||
return jl_new_bits(dt, reinterpret_cast<CxxPoint3<T>*>(&cppval));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BoxValue<Rect_<T>,CxxRect<T>>
|
||||
{
|
||||
inline jl_value_t* operator()(Rect_<T> cppval)
|
||||
{
|
||||
return jl_new_bits((jl_value_t*)julia_type<Rect_<T>>(), reinterpret_cast<CxxRect<T>*>(&cppval));
|
||||
}
|
||||
|
||||
inline jl_value_t* operator()(Rect_<T> cppval, jl_value_t* dt)
|
||||
{
|
||||
return jl_new_bits(dt, reinterpret_cast<CxxRect<T>*>(&cppval));
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,459 @@
|
||||
// This file is a modified array.hpp from https://github.com/JuliaInterop/libcxxwrap-julia
|
||||
// required for the hack that allows automated conversion of OpenCV types.
|
||||
// Shouldn't be needed once CxxWrap gets inbuilt support
|
||||
// Here is the original copyright and the license:
|
||||
/*
|
||||
==
|
||||
|
||||
Copyright (c) 2015: Bart Janssens.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
==
|
||||
*/
|
||||
|
||||
|
||||
#ifndef JLCXX_ARRAY_HPP
|
||||
#define JLCXX_ARRAY_HPP
|
||||
|
||||
#include "jlcxx/type_conversion.hpp"
|
||||
#include "jlcxx/tuple.hpp"
|
||||
|
||||
namespace jlcxx
|
||||
{
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
struct ValueExtractor
|
||||
{
|
||||
inline CppT operator()(PointedT* p)
|
||||
{
|
||||
return convert_to_cpp<CppT>(*p);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename PointedT>
|
||||
struct ValueExtractor<PointedT, PointedT>
|
||||
{
|
||||
inline PointedT& operator()(PointedT* p)
|
||||
{
|
||||
return *p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
class array_iterator_base : public std::iterator<std::random_access_iterator_tag, CppT>
|
||||
{
|
||||
private:
|
||||
PointedT* m_ptr;
|
||||
public:
|
||||
array_iterator_base() : m_ptr(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
explicit array_iterator_base(PointedT* p) : m_ptr(p)
|
||||
{
|
||||
}
|
||||
|
||||
template <class OtherPointedT, class OtherCppT>
|
||||
array_iterator_base(array_iterator_base<OtherPointedT, OtherCppT> const& other) : m_ptr(other.m_ptr) {}
|
||||
|
||||
auto operator*() -> decltype(ValueExtractor<PointedT,CppT>()(m_ptr))
|
||||
{
|
||||
return ValueExtractor<PointedT,CppT>()(m_ptr);
|
||||
}
|
||||
|
||||
array_iterator_base<PointedT, CppT>& operator++()
|
||||
{
|
||||
++m_ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
array_iterator_base<PointedT, CppT>& operator--()
|
||||
{
|
||||
--m_ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
array_iterator_base<PointedT, CppT>& operator+=(std::ptrdiff_t n)
|
||||
{
|
||||
m_ptr += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
array_iterator_base<PointedT, CppT>& operator-=(std::ptrdiff_t n)
|
||||
{
|
||||
m_ptr -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PointedT* ptr() const
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
};
|
||||
|
||||
/// Wrap a Julia 1D array in a C++ class. Array is allocated on the C++ side
|
||||
template<typename ValueT>
|
||||
class Array
|
||||
{
|
||||
public:
|
||||
Array(const size_t n = 0)
|
||||
{
|
||||
jl_value_t* array_type = apply_array_type(julia_type<ValueT>(), 1);
|
||||
m_array = jl_alloc_array_1d(array_type, n);
|
||||
}
|
||||
|
||||
Array(jl_datatype_t* applied_type, const size_t n = 0)
|
||||
{
|
||||
jl_value_t* array_type = apply_array_type(applied_type, 1);
|
||||
m_array = jl_alloc_array_1d(array_type, n);
|
||||
}
|
||||
|
||||
/// Append an element to the end of the list
|
||||
template<typename VT>
|
||||
void push_back(VT&& val)
|
||||
{
|
||||
JL_GC_PUSH1(&m_array);
|
||||
const size_t pos = jl_array_len(m_array);
|
||||
jl_array_grow_end(m_array, 1);
|
||||
jl_arrayset(m_array, box<ValueT>(val), pos);
|
||||
JL_GC_POP();
|
||||
}
|
||||
|
||||
/// Access to the wrapped array
|
||||
jl_array_t* wrapped()
|
||||
{
|
||||
return m_array;
|
||||
}
|
||||
|
||||
// access to the pointer for GC macros
|
||||
jl_array_t** gc_pointer()
|
||||
{
|
||||
return &m_array;
|
||||
}
|
||||
|
||||
private:
|
||||
jl_array_t* m_array;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename T, typename TraitT=mapping_trait<T>>
|
||||
struct ArrayElementType
|
||||
{
|
||||
using type = static_julia_type<T>;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ArrayElementType<T,WrappedPtrTrait>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// Reference a Julia array in an STL-compatible wrapper
|
||||
template<typename ValueT, int Dim = 1>
|
||||
class ArrayRef
|
||||
{
|
||||
public:
|
||||
|
||||
using julia_t = typename detail::ArrayElementType<ValueT>::type;
|
||||
|
||||
ArrayRef(jl_array_t* arr) : m_array(arr)
|
||||
{
|
||||
assert(wrapped() != nullptr);
|
||||
}
|
||||
|
||||
/// Convert from existing C-array (memory owned by C++)
|
||||
template<typename... SizesT>
|
||||
ArrayRef(julia_t* ptr, const SizesT... sizes);
|
||||
|
||||
/// Convert from existing C-array, explicitly setting Julia ownership
|
||||
template<typename... SizesT>
|
||||
ArrayRef(const bool julia_owned, julia_t* ptr, const SizesT... sizes);
|
||||
|
||||
typedef array_iterator_base<julia_t, ValueT> iterator;
|
||||
typedef array_iterator_base<julia_t const, ValueT const> const_iterator;
|
||||
|
||||
inline jl_array_t* wrapped() const
|
||||
{
|
||||
return m_array;
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(static_cast<julia_t*>(jl_array_data(wrapped())));
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(static_cast<julia_t*>(jl_array_data(wrapped())));
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(static_cast<julia_t*>(jl_array_data(wrapped())) + jl_array_len(wrapped()));
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(static_cast<julia_t*>(jl_array_data(wrapped())) + jl_array_len(wrapped()));
|
||||
}
|
||||
|
||||
void push_back(const ValueT& val)
|
||||
{
|
||||
static_assert(Dim == 1, "ArrayRef::push_back is only for 1D ArrayRef");
|
||||
static_assert(std::is_same<julia_t,ValueT>::value, "ArrayRef::push_back is only for arrays of fundamental types");
|
||||
jl_array_t* arr_ptr = wrapped();
|
||||
JL_GC_PUSH1(&arr_ptr);
|
||||
const size_t pos = size();
|
||||
jl_array_grow_end(arr_ptr, 1);
|
||||
jl_arrayset(arr_ptr, box<ValueT>(val), pos);
|
||||
JL_GC_POP();
|
||||
}
|
||||
|
||||
const julia_t* data() const
|
||||
{
|
||||
return (julia_t*)jl_array_data(wrapped());
|
||||
}
|
||||
|
||||
julia_t* data()
|
||||
{
|
||||
return (julia_t*)jl_array_data(wrapped());
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return jl_array_len(wrapped());
|
||||
}
|
||||
|
||||
ValueT& operator[](const std::size_t i)
|
||||
{
|
||||
if constexpr(std::is_same<julia_t, ValueT>::value)
|
||||
{
|
||||
return data()[i];
|
||||
}
|
||||
else if constexpr(std::is_same<julia_t, static_julia_type<ValueT>>::value && !std::is_same<julia_t, WrappedCppPtr>::value)
|
||||
{
|
||||
return *reinterpret_cast<ValueT*>(&data()[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *extract_pointer_nonull<ValueT>(data()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const ValueT& operator[](const std::size_t i) const
|
||||
{
|
||||
if constexpr(std::is_same<julia_t, ValueT>::value)
|
||||
{
|
||||
return data()[i];
|
||||
}
|
||||
else if constexpr(std::is_same<julia_t, static_julia_type<ValueT>>::value && !std::is_same<julia_t, WrappedCppPtr>::value)
|
||||
{
|
||||
return *reinterpret_cast<ValueT*>(&data()[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *extract_pointer_nonull<ValueT>(data()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
jl_array_t* m_array;
|
||||
};
|
||||
|
||||
// Conversions
|
||||
template<typename T, int Dim, typename SubTraitT>
|
||||
struct static_type_mapping<ArrayRef<T, Dim>, CxxWrappedTrait<SubTraitT>>
|
||||
{
|
||||
typedef jl_array_t* type;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename T, typename TraitT=mapping_trait<T>>
|
||||
struct PackedArrayType
|
||||
{
|
||||
static jl_datatype_t* type()
|
||||
{
|
||||
return julia_type<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct PackedArrayType<T*, WrappedPtrTrait>
|
||||
{
|
||||
static jl_datatype_t* type()
|
||||
{
|
||||
return (jl_datatype_t*)apply_type((jl_value_t*)jlcxx::julia_type("Ptr"), jl_svec1(julia_base_type<T>()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename SubTraitT>
|
||||
struct PackedArrayType<T,CxxWrappedTrait<SubTraitT>>
|
||||
{
|
||||
static jl_datatype_t* type()
|
||||
{
|
||||
create_if_not_exists<T&>();
|
||||
return julia_type<T&>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T, int Dim>
|
||||
struct julia_type_factory<ArrayRef<T, Dim>>
|
||||
{
|
||||
static inline jl_datatype_t* julia_type()
|
||||
{
|
||||
create_if_not_exists<T>();
|
||||
return (jl_datatype_t*)apply_array_type(detail::PackedArrayType<T>::type(), Dim);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ValueT, typename... SizesT>
|
||||
jl_array_t* wrap_array(const bool julia_owned, ValueT* c_ptr, const SizesT... sizes)
|
||||
{
|
||||
jl_datatype_t* dt = julia_type<ArrayRef<ValueT, sizeof...(SizesT)>>();
|
||||
jl_value_t *dims = nullptr;
|
||||
JL_GC_PUSH1(&dims);
|
||||
dims = convert_to_julia(std::make_tuple(static_cast<cxxint_t>(sizes)...));
|
||||
jl_array_t* result = jl_ptr_to_array((jl_value_t*)dt, c_ptr, dims, julia_owned);
|
||||
JL_GC_POP();
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename ValueT, int Dim>
|
||||
template<typename... SizesT>
|
||||
ArrayRef<ValueT, Dim>::ArrayRef(julia_t* c_ptr, const SizesT... sizes) : m_array(wrap_array(false, c_ptr, sizes...))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ValueT, int Dim>
|
||||
template<typename... SizesT>
|
||||
ArrayRef<ValueT, Dim>::ArrayRef(const bool julia_owned, julia_t* c_ptr, const SizesT... sizes) : m_array(wrap_array(julia_owned, c_ptr, sizes...))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ValueT, typename... SizesT>
|
||||
auto make_julia_array(ValueT* c_ptr, const SizesT... sizes) -> ArrayRef<ValueT, sizeof...(SizesT)>
|
||||
{
|
||||
return ArrayRef<ValueT, sizeof...(SizesT)>(false, c_ptr, sizes...);
|
||||
}
|
||||
|
||||
template<typename T, typename SubTraitT>
|
||||
struct static_type_mapping<Array<T>, CxxWrappedTrait<SubTraitT>>
|
||||
{
|
||||
typedef jl_array_t* type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct julia_type_factory<Array<T>>
|
||||
{
|
||||
static inline jl_datatype_t* julia_type()
|
||||
{
|
||||
create_if_not_exists<T>();
|
||||
return (jl_datatype_t*)apply_array_type(jlcxx::julia_type<T>(), 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int Dim>
|
||||
struct ConvertToJulia<ArrayRef<T,Dim>>
|
||||
{
|
||||
template<typename ArrayRefT>
|
||||
jl_array_t* operator()(ArrayRefT&& arr) const
|
||||
{
|
||||
return arr.wrapped();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConvertToJulia<Array<T>>
|
||||
{
|
||||
jl_value_t* operator()(Array<T>&& arr) const
|
||||
{
|
||||
return (jl_value_t*)arr.wrapped();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int Dim, typename SubTraitT>
|
||||
struct ConvertToCpp<ArrayRef<T,Dim>, CxxWrappedTrait<SubTraitT>>
|
||||
{
|
||||
ArrayRef<T,Dim> operator()(jl_array_t* arr) const
|
||||
{
|
||||
return ArrayRef<T,Dim>(arr);
|
||||
}
|
||||
};
|
||||
|
||||
// Iterator operator implementation
|
||||
template<typename PointedT, typename CppT>
|
||||
bool operator!=(const array_iterator_base<PointedT, CppT>& l, const array_iterator_base<PointedT, CppT>& r)
|
||||
{
|
||||
return r.ptr() != l.ptr();
|
||||
}
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
bool operator==(const array_iterator_base<PointedT, CppT>& l, const array_iterator_base<PointedT, CppT>& r)
|
||||
{
|
||||
return r.ptr() == l.ptr();
|
||||
}
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
bool operator<=(const array_iterator_base<PointedT, CppT>& l, const array_iterator_base<PointedT, CppT>& r)
|
||||
{
|
||||
return l.ptr() <= r.ptr();
|
||||
}
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
bool operator>=(const array_iterator_base<PointedT, CppT>& l, const array_iterator_base<PointedT, CppT>& r)
|
||||
{
|
||||
return l.ptr() >= r.ptr();
|
||||
}
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
bool operator>(const array_iterator_base<PointedT, CppT>& l, const array_iterator_base<PointedT, CppT>& r)
|
||||
{
|
||||
return l.ptr() > r.ptr();
|
||||
}
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
bool operator<(const array_iterator_base<PointedT, CppT>& l, const array_iterator_base<PointedT, CppT>& r)
|
||||
{
|
||||
return l.ptr() < r.ptr();
|
||||
}
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
array_iterator_base<PointedT, CppT> operator+(const array_iterator_base<PointedT, CppT>& l, const std::ptrdiff_t n)
|
||||
{
|
||||
return array_iterator_base<PointedT, CppT>(l.ptr() + n);
|
||||
}
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
array_iterator_base<PointedT, CppT> operator+(const std::ptrdiff_t n, const array_iterator_base<PointedT, CppT>& r)
|
||||
{
|
||||
return array_iterator_base<PointedT, CppT>(r.ptr() + n);
|
||||
}
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
array_iterator_base<PointedT, CppT> operator-(const array_iterator_base<PointedT, CppT>& l, const std::ptrdiff_t n)
|
||||
{
|
||||
return array_iterator_base<PointedT, CppT>(l.ptr() - n);
|
||||
}
|
||||
|
||||
template<typename PointedT, typename CppT>
|
||||
std::ptrdiff_t operator-(const array_iterator_base<PointedT, CppT>& l, const array_iterator_base<PointedT, CppT>& r)
|
||||
{
|
||||
return l.ptr() - r.ptr();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
Float64|0.1|0.1
|
||||
Float64|1.0|1.0
|
||||
Float64|0|0
|
||||
Int64|NORM_L2|cv_NORM_L2
|
||||
Float64|0.04|0.04
|
||||
Bool|true|true
|
||||
Float64|0.0f|0
|
||||
Float64|DBL_MAX|typemax(Float64)
|
||||
Ptr{Float32}|Ptr<float>()|cpp_to_julia(PtrifloatkOP())
|
||||
Int64|CV_32F|CV_32F
|
||||
Int64|20|20
|
||||
Array{String, 1}|std::vector<String>()|cpp_to_julia(stdggvectoriStringkOP())
|
||||
Float64|1|1
|
||||
TermCriteria|TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5,1)|cpp_to_julia(TermCriteriaOTermCriteriaggMAXRITERRTermCriteriaggEPSSbSXP())
|
||||
Int64|4|4
|
||||
Int64|LINE_8|cv_LINE_8
|
||||
Float64|0.5|0.5
|
||||
Float64|0.5f|0.5
|
||||
Int64|MARKER_CROSS|cv_MARKER_CROSS
|
||||
Float64|1|1
|
||||
Point{Int32}|Point(-1,-1)|cpp_to_julia(PointOTXSTXP())
|
||||
Float64|CV_PI*0.5|pi*0.5
|
||||
Int64|QT_FONT_NORMAL|cv_QT_FONT_NORMAL
|
||||
Point{Int32}|Point()|cpp_to_julia(PointOP())
|
||||
Float64|CV_PI|pi
|
||||
Float64|-1|-1
|
||||
Int64|300|300
|
||||
Int64|3|3
|
||||
String|""|""
|
||||
Scalar|Scalar()|cpp_to_julia(ScalarOP())
|
||||
Float64|1.f|1
|
||||
Array{Int32, 1}|std::vector<int>()|cpp_to_julia(stdggvectoriintkOP())
|
||||
InputArray|Mat()|CxxMat()
|
||||
Int64|BORDER_DEFAULT|cv_BORDER_DEFAULT
|
||||
Int64|CV_32S|CV_32S
|
||||
Int64|IMREAD_COLOR|cv_IMREAD_COLOR
|
||||
Float64|100|100
|
||||
Size{Int32}|Size(8, 8)|cpp_to_julia(SizeOeSGeP())
|
||||
Array{InputArray, 1}||Array{InputArray, 1}()
|
||||
Int64|GC_EVAL|cv_GC_EVAL
|
||||
Int64|8|8
|
||||
Int64|DIST_LABEL_CCOMP|cv_DIST_LABEL_CCOMP
|
||||
Int64|CAP_ANY|cv_CAP_ANY
|
||||
Float64|0|0
|
||||
Int64|-1|-1
|
||||
Float64|-DBL_MAX|-typemax(Float64)
|
||||
Scalar|Scalar::all(0)|cpp_to_julia(ScalarggallOWP())
|
||||
InputArray||CxxMat()
|
||||
Int64|QT_STYLE_NORMAL|cv_QT_STYLE_NORMAL
|
||||
Int64|INTER_LINEAR|cv_INTER_LINEAR
|
||||
Bool|false|false
|
||||
Int64|CV_64F|CV_64F
|
||||
Point{Int32}|Point(-1, -1)|cpp_to_julia(PointOTXSGTXP())
|
||||
Scalar|morphologyDefaultBorderValue()|cpp_to_julia(morphologyDefaultBorderValueOP())
|
||||
Int64|IMREAD_ANYCOLOR|cv_IMREAD_ANYCOLOR
|
||||
Int64|INT_MAX|typemax(Int32)
|
||||
String|String()|""
|
||||
Float64|1.|1
|
||||
Int64|WINDOW_AUTOSIZE|cv_WINDOW_AUTOSIZE
|
||||
Int64|DECOMP_LU|cv_DECOMP_LU
|
||||
Float64|40.0|40.0
|
||||
Int64|BORDER_CONSTANT|cv_BORDER_CONSTANT
|
||||
Array{UInt8, 1}|std::vector<uchar>()|cpp_to_julia(stdggvectoriucharkOP())
|
||||
Int64|0|0
|
||||
Float64|255.|255
|
||||
Scalar|Scalar(1)|cpp_to_julia(ScalarOXP())
|
||||
Int64|1|1
|
||||
Size{Int32}|Size()|cpp_to_julia(SizeOP())
|
||||
TermCriteria|TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 20, FLT_EPSILON)|cpp_to_julia(TermCriteriaOTermCriteriaggEPSGRGTermCriteriaggCOUNTSGYWSGFLTREPSILONP())
|
||||
Int64|RANSAC|cv_RANSAC
|
||||
Float64|8.0|8.0
|
||||
Float64|-1|-1
|
||||
Int64|21|21
|
||||
TermCriteria|TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)|TermCriteriaOGTermCriteriaggCOUNTGRGTermCriteriaggEPSSGZWSGDBLREPSILONP
|
||||
TermCriteria|TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6)|TermCriteriaOTermCriteriaggCOUNTRTermCriteriaggEPSSGZWSGXeTcP
|
||||
Int64|CALIB_CB_SYMMETRIC_GRID|cv_CALIB_CB_SYMMETRIC_GRID
|
||||
InputArray|cv::Mat()|CxxMat()
|
||||
Int64|SOLVEPNP_ITERATIVE|cv_SOLVEPNP_ITERATIVE
|
||||
Float64|3|3
|
||||
Int64|CALIB_FIX_INTRINSIC|cv_CALIB_FIX_INTRINSIC
|
||||
Float64|5|5
|
||||
Float64|0.99|0.99
|
||||
Int64|CALIB_ZERO_DISPARITY|cv_CALIB_ZERO_DISPARITY
|
||||
size_t|2000|2000
|
||||
SolvePnPMethod|SOLVEPNP_ITERATIVE|cv_SOLVEPNP_ITERATIVE
|
||||
Float64|0.0|0.0
|
||||
Ptr{Feature2D}|SimpleBlobDetector::create()|SimpleBlobDetectorggcreateOP
|
||||
Int64|StereoSGBM::MODE_SGBM|StereoSGBMggMODERSGBM
|
||||
Int64|CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE|cv_CALIB_CB_ADAPTIVE_THRESH + cv_CALIB_CB_NORMALIZE_IMAGE
|
||||
Float64|3.|3
|
||||
size_t|10|10
|
||||
Int64|16|16
|
||||
Point{Float64}|Point2d(0, 0)|PointYdOWSGWP
|
||||
Int64|2000|2000
|
||||
Int64|FM_RANSAC|cv_FM_RANSAC
|
||||
Int64|100|100
|
||||
TermCriteria|TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)|TermCriteriaOTermCriteriaggCOUNTGRGTermCriteriaggEPSSGXWWSGDBLREPSILONP
|
||||
HandEyeCalibrationMethod|CALIB_HAND_EYE_TSAI|cv_CALIB_HAND_EYE_TSAI
|
||||
Float64|0.8F|0.8
|
||||
Int64|fisheye::CALIB_FIX_INTRINSIC|cv_fisheye_CALIB_FIX_INTRINSIC
|
||||
Float64|0.999|0.999
|
||||
Float64|0.995|0.995
|
||||
Int64|1000|1000
|
||||
@@ -0,0 +1,490 @@
|
||||
cv.borderInterpolate
|
||||
cv.copyMakeBorder
|
||||
cv.add
|
||||
cv.subtract
|
||||
cv.multiply
|
||||
cv.divide
|
||||
cv.scaleAdd
|
||||
cv.addWeighted
|
||||
cv.convertScaleAbs
|
||||
cv.LUT
|
||||
cv.sum
|
||||
cv.countNonZero
|
||||
cv.findNonZero
|
||||
cv.mean
|
||||
cv.meanStdDev
|
||||
cv.norm
|
||||
cv.PSNR
|
||||
cv.batchDistance
|
||||
cv.normalize
|
||||
cv.minMaxLoc
|
||||
cv.reduce
|
||||
cv.merge
|
||||
cv.split
|
||||
cv.mixChannels
|
||||
cv.extractChannel
|
||||
cv.insertChannel
|
||||
cv.flip
|
||||
cv.rotate
|
||||
cv.repeat
|
||||
cv.hconcat
|
||||
cv.vconcat
|
||||
cv.bitwise_and
|
||||
cv.bitwise_or
|
||||
cv.bitwise_xor
|
||||
cv.bitwise_not
|
||||
cv.absdiff
|
||||
cv.copyTo
|
||||
cv.inRange
|
||||
cv.compare
|
||||
cv.min
|
||||
cv.max
|
||||
cv.sqrt
|
||||
cv.pow
|
||||
cv.exp
|
||||
cv.log
|
||||
cv.polarToCart
|
||||
cv.cartToPolar
|
||||
cv.phase
|
||||
cv.magnitude
|
||||
cv.checkRange
|
||||
cv.patchNaNs
|
||||
cv.gemm
|
||||
cv.mulTransposed
|
||||
cv.transpose
|
||||
cv.transform
|
||||
cv.perspectiveTransform
|
||||
cv.completeSymm
|
||||
cv.setIdentity
|
||||
cv.determinant
|
||||
cv.trace
|
||||
cv.invert
|
||||
cv.solve
|
||||
cv.sort
|
||||
cv.sortIdx
|
||||
cv.solveCubic
|
||||
cv.solvePoly
|
||||
cv.eigen
|
||||
cv.eigenNonSymmetric
|
||||
cv.calcCovarMatrix
|
||||
cv.PCACompute
|
||||
cv.PCAProject
|
||||
cv.PCABackProject
|
||||
cv.SVDecomp
|
||||
cv.SVBackSubst
|
||||
cv.Mahalanobis
|
||||
cv.dft
|
||||
cv.idft
|
||||
cv.dct
|
||||
cv.idct
|
||||
cv.mulSpectrums
|
||||
cv.getOptimalDFTSize
|
||||
cv.setRNGSeed
|
||||
cv.randu
|
||||
cv.randn
|
||||
cv.randShuffle
|
||||
cv.kmeans
|
||||
cv.cubeRoot
|
||||
cv.fastAtan2
|
||||
cv.ipp.useIPP
|
||||
cv.ipp.setUseIPP
|
||||
cv.ipp.getIppVersion
|
||||
cv.ipp.useIPP_NotExact
|
||||
cv.ipp.setUseIPP_NotExact
|
||||
cv.utils.dumpInputArray
|
||||
cv.utils.dumpInputArrayOfArrays
|
||||
cv.utils.dumpInputOutputArray
|
||||
cv.utils.dumpInputOutputArrayOfArrays
|
||||
cv.utils.dumpBool
|
||||
cv.utils.dumpInt
|
||||
cv.utils.dumpSizeT
|
||||
cv.utils.dumpFloat
|
||||
cv.utils.dumpDouble
|
||||
cv.utils.dumpCString
|
||||
cv.utils.testAsyncArray
|
||||
cv.utils.testAsyncException
|
||||
cv.solveLP
|
||||
cv.FileStorage.FileStorage
|
||||
cv.FileStorage.open
|
||||
cv.FileStorage.isOpened
|
||||
cv.FileStorage.release
|
||||
cv.FileStorage.releaseAndGetString
|
||||
cv.FileStorage.getFirstTopLevelNode
|
||||
cv.FileStorage.root
|
||||
#cv.FileStorage.operator[]
|
||||
cv.FileStorage.write
|
||||
cv.FileStorage.writeComment
|
||||
cv.FileStorage.startWriteStruct
|
||||
cv.FileStorage.endWriteStruct
|
||||
cv.FileStorage.getFormat
|
||||
cv.FileNode.FileNode
|
||||
cv.FileNode.keys
|
||||
cv.FileNode.type
|
||||
cv.FileNode.empty
|
||||
cv.FileNode.isNone
|
||||
cv.FileNode.isSeq
|
||||
cv.FileNode.isMap
|
||||
cv.FileNode.isInt
|
||||
cv.FileNode.isReal
|
||||
cv.FileNode.isString
|
||||
cv.FileNode.isNamed
|
||||
cv.FileNode.name
|
||||
cv.FileNode.size
|
||||
cv.FileNode.rawSize
|
||||
cv.FileNode.real
|
||||
cv.FileNode.string
|
||||
cv.FileNode.mat
|
||||
cv.KeyPoint.KeyPoint
|
||||
cv.KeyPoint.convert
|
||||
cv.KeyPoint.overlap
|
||||
cv.DMatch.DMatch
|
||||
cv.setNumThreads
|
||||
cv.getNumThreads
|
||||
cv.getThreadNum
|
||||
cv.getBuildInformation
|
||||
cv.getVersionString
|
||||
cv.getVersionMajor
|
||||
cv.getVersionMinor
|
||||
cv.getVersionRevision
|
||||
cv.getTickCount
|
||||
cv.getTickFrequency
|
||||
cv.Subdiv2D.Subdiv2D
|
||||
cv.Subdiv2D.initDelaunay
|
||||
cv.Subdiv2D.insert
|
||||
cv.Subdiv2D.locate
|
||||
cv.Subdiv2D.findNearest
|
||||
cv.Subdiv2D.getEdgeList
|
||||
cv.Subdiv2D.getLeadingEdgeList
|
||||
cv.Subdiv2D.getTriangleList
|
||||
cv.Subdiv2D.getVoronoiFacetList
|
||||
cv.Subdiv2D.getVertex
|
||||
cv.Subdiv2D.getEdge
|
||||
cv.Subdiv2D.nextEdge
|
||||
cv.Subdiv2D.rotateEdge
|
||||
cv.Subdiv2D.symEdge
|
||||
cv.Subdiv2D.edgeOrg
|
||||
cv.Subdiv2D.edgeDst
|
||||
cv.getGaussianKernel
|
||||
cv.getDerivKernels
|
||||
cv.getGaborKernel
|
||||
cv.getStructuringElement
|
||||
cv.medianBlur
|
||||
cv.GaussianBlur
|
||||
cv.bilateralFilter
|
||||
cv.boxFilter
|
||||
cv.sqrBoxFilter
|
||||
cv.blur
|
||||
cv.filter2D
|
||||
cv.sepFilter2D
|
||||
cv.Sobel
|
||||
cv.spatialGradient
|
||||
cv.Scharr
|
||||
cv.Laplacian
|
||||
cv.Canny
|
||||
cv.cornerMinEigenVal
|
||||
cv.cornerHarris
|
||||
cv.cornerEigenValsAndVecs
|
||||
cv.preCornerDetect
|
||||
cv.cornerSubPix
|
||||
cv.goodFeaturesToTrack
|
||||
cv.HoughLines
|
||||
cv.HoughLinesP
|
||||
cv.HoughLinesPointSet
|
||||
cv.HoughCircles
|
||||
cv.erode
|
||||
cv.dilate
|
||||
cv.morphologyEx
|
||||
cv.resize
|
||||
cv.warpAffine
|
||||
cv.warpPerspective
|
||||
cv.remap
|
||||
cv.convertMaps
|
||||
cv.getRotationMatrix2D
|
||||
cv.invertAffineTransform
|
||||
cv.getPerspectiveTransform
|
||||
cv.getAffineTransform
|
||||
cv.getRectSubPix
|
||||
cv.logPolar
|
||||
cv.linearPolar
|
||||
cv.warpPolar
|
||||
cv.integral
|
||||
cv.accumulate
|
||||
cv.accumulateSquare
|
||||
cv.accumulateProduct
|
||||
cv.accumulateWeighted
|
||||
cv.phaseCorrelate
|
||||
cv.createHanningWindow
|
||||
cv.threshold
|
||||
cv.adaptiveThreshold
|
||||
cv.pyrDown
|
||||
cv.pyrUp
|
||||
cv.calcHist
|
||||
cv.calcBackProject
|
||||
cv.compareHist
|
||||
cv.equalizeHist
|
||||
cv.createCLAHE
|
||||
cv.wrapperEMD
|
||||
cv.watershed
|
||||
cv.pyrMeanShiftFiltering
|
||||
cv.grabCut
|
||||
cv.distanceTransform
|
||||
cv.floodFill
|
||||
cv.cvtColor
|
||||
cv.cvtColorTwoPlane
|
||||
cv.demosaicing
|
||||
cv.moments
|
||||
cv.HuMoments
|
||||
cv.matchTemplate
|
||||
cv.connectedComponents
|
||||
cv.connectedComponentsWithStats
|
||||
cv.findContours
|
||||
cv.approxPolyDP
|
||||
cv.arcLength
|
||||
cv.boundingRect
|
||||
cv.contourArea
|
||||
cv.minAreaRect
|
||||
cv.boxPoints
|
||||
cv.minEnclosingCircle
|
||||
cv.minEnclosingTriangle
|
||||
cv.matchShapes
|
||||
cv.convexHull
|
||||
cv.convexityDefects
|
||||
cv.isContourConvex
|
||||
cv.intersectConvexConvex
|
||||
cv.fitEllipse
|
||||
cv.fitEllipseAMS
|
||||
cv.fitEllipseDirect
|
||||
cv.fitLine
|
||||
cv.pointPolygonTest
|
||||
cv.rotatedRectangleIntersection
|
||||
cv.createGeneralizedHoughBallard
|
||||
cv.createGeneralizedHoughGuil
|
||||
cv.applyColorMap
|
||||
cv.line
|
||||
cv.arrowedLine
|
||||
cv.rectangle
|
||||
cv.circle
|
||||
cv.ellipse
|
||||
cv.drawMarker
|
||||
cv.fillConvexPoly
|
||||
cv.fillPoly
|
||||
cv.polylines
|
||||
cv.drawContours
|
||||
cv.clipLine
|
||||
cv.ellipse2Poly
|
||||
cv.putText
|
||||
cv.getTextSize
|
||||
cv.getFontScaleFromHeight
|
||||
cv.dnn.Net.Net
|
||||
cv.dnn.Net.readFromModelOptimizer
|
||||
cv.dnn.Net.empty
|
||||
cv.dnn.Net.dump
|
||||
cv.dnn.Net.dumpToFile
|
||||
cv.dnn.Net.setInputShape
|
||||
cv.dnn.Net.forwardAsync
|
||||
cv.dnn.Net.forward
|
||||
cv.dnn.Net.setPreferableBackend
|
||||
cv.dnn.Net.setPreferableTarget
|
||||
cv.dnn.Net.setInput
|
||||
cv.dnn.Net.setParam
|
||||
cv.dnn.Net.getParam
|
||||
cv.dnn.Net.getFLOPS
|
||||
cv.dnn.Net.getMemoryConsumption
|
||||
cv.dnn.Net.enableFusion
|
||||
cv.dnn.Net.getPerfProfile
|
||||
cv.dnn.readNetFromTensorflow
|
||||
cv.dnn.readNetFromTorch
|
||||
cv.dnn.readNet
|
||||
cv.dnn.readTorchBlob
|
||||
cv.dnn.readNetFromModelOptimizer
|
||||
cv.dnn.readNetFromONNX
|
||||
cv.dnn.readTensorFromONNX
|
||||
cv.dnn.blobFromImage
|
||||
cv.dnn.blobFromImages
|
||||
cv.dnn.imagesFromBlob
|
||||
cv.dnn.shrinkCaffeModel
|
||||
cv.dnn.writeTextGraph
|
||||
cv.dnn.NMSBoxes
|
||||
cv.dnn.Model.Model
|
||||
cv.dnn.Model.setInputSize
|
||||
cv.dnn.Model.setInputMean
|
||||
cv.dnn.Model.setInputScale
|
||||
cv.dnn.Model.setInputCrop
|
||||
cv.dnn.Model.setInputSwapRB
|
||||
cv.dnn.Model.setInputParams
|
||||
cv.dnn.Model.setPreferableTarget
|
||||
cv.dnn.Model.predict
|
||||
cv.dnn.ClassificationModel.ClassificationModel
|
||||
cv.dnn.ClassificationModel.classify
|
||||
cv.dnn.KeypointsModel.KeypointsModel
|
||||
cv.dnn.KeypointsModel.estimate
|
||||
cv.dnn.SegmentationModel.SegmentationModel
|
||||
cv.dnn.SegmentationModel.segment
|
||||
cv.dnn.DetectionModel.DetectionModel
|
||||
cv.dnn.DetectionModel.detect
|
||||
cv.imread
|
||||
cv.imreadmulti
|
||||
cv.imwrite
|
||||
cv.imdecode
|
||||
cv.imencode
|
||||
cv.haveImageReader
|
||||
cv.haveImageWriter
|
||||
cv.VideoCapture.VideoCapture
|
||||
cv.VideoCapture.open
|
||||
cv.VideoCapture.isOpened
|
||||
cv.VideoCapture.release
|
||||
cv.VideoCapture.grab
|
||||
cv.VideoCapture.retrieve
|
||||
cv.VideoCapture.read
|
||||
cv.VideoCapture.set
|
||||
cv.VideoCapture.get
|
||||
cv.VideoCapture.getBackendName
|
||||
cv.VideoCapture.setExceptionMode
|
||||
cv.VideoCapture.getExceptionMode
|
||||
cv.VideoWriter.VideoWriter
|
||||
cv.VideoWriter.open
|
||||
cv.VideoWriter.isOpened
|
||||
cv.VideoWriter.release
|
||||
cv.VideoWriter.write
|
||||
cv.VideoWriter.set
|
||||
cv.VideoWriter.get
|
||||
cv.VideoWriter.fourcc
|
||||
cv.VideoWriter.getBackendName
|
||||
cv.namedWindow
|
||||
cv.destroyWindow
|
||||
cv.destroyAllWindows
|
||||
cv.startWindowThread
|
||||
cv.waitKeyEx
|
||||
cv.waitKey
|
||||
cv.imshow
|
||||
cv.resizeWindow
|
||||
cv.moveWindow
|
||||
cv.setWindowProperty
|
||||
cv.setWindowTitle
|
||||
cv.getWindowProperty
|
||||
cv.getWindowImageRect
|
||||
cv.selectROI
|
||||
cv.selectROIs
|
||||
cv.getTrackbarPos
|
||||
cv.setTrackbarPos
|
||||
cv.setTrackbarMax
|
||||
cv.setTrackbarMin
|
||||
cv.addText
|
||||
cv.displayOverlay
|
||||
cv.displayStatusBar
|
||||
cv.Rodrigues
|
||||
cv.findHomography
|
||||
cv.RQDecomp3x3
|
||||
cv.decomposeProjectionMatrix
|
||||
cv.matMulDeriv
|
||||
cv.composeRT
|
||||
cv.projectPoints
|
||||
cv.solvePnP
|
||||
cv.solvePnPRansac
|
||||
cv.solveP3P
|
||||
cv.solvePnPRefineLM
|
||||
cv.solvePnPRefineVVS
|
||||
cv.solvePnPGeneric
|
||||
cv.initCameraMatrix2D
|
||||
cv.findChessboardCorners
|
||||
cv.checkChessboard
|
||||
cv.findChessboardCornersSB
|
||||
cv.findChessboardCornersSB
|
||||
cv.estimateChessboardSharpness
|
||||
cv.find4QuadCornerSubpix
|
||||
cv.drawChessboardCorners
|
||||
cv.drawFrameAxes
|
||||
cv.CirclesGridFinderParameters.CirclesGridFinderParameters
|
||||
cv.findCirclesGrid
|
||||
cv.findCirclesGrid
|
||||
cv.calibrateCamera
|
||||
cv.calibrateCamera
|
||||
cv.calibrateCameraRO
|
||||
cv.calibrateCameraRO
|
||||
cv.calibrationMatrixValues
|
||||
cv.stereoCalibrate
|
||||
cv.stereoCalibrate
|
||||
cv.stereoRectify
|
||||
cv.stereoRectifyUncalibrated
|
||||
cv.rectify3Collinear
|
||||
cv.getOptimalNewCameraMatrix
|
||||
cv.calibrateHandEye
|
||||
cv.convertPointsToHomogeneous
|
||||
cv.convertPointsFromHomogeneous
|
||||
cv.findFundamentalMat
|
||||
cv.findFundamentalMat
|
||||
cv.findEssentialMat
|
||||
cv.findEssentialMat
|
||||
cv.decomposeEssentialMat
|
||||
cv.recoverPose
|
||||
cv.recoverPose
|
||||
cv.recoverPose
|
||||
cv.computeCorrespondEpilines
|
||||
cv.triangulatePoints
|
||||
cv.correctMatches
|
||||
cv.filterSpeckles
|
||||
cv.getValidDisparityROI
|
||||
cv.validateDisparity
|
||||
cv.reprojectImageTo3D
|
||||
cv.sampsonDistance
|
||||
cv.estimateAffine3D
|
||||
cv.estimateTranslation3D
|
||||
cv.estimateAffine2D
|
||||
cv.estimateAffinePartial2D
|
||||
cv.decomposeHomographyMat
|
||||
cv.filterHomographyDecompByVisibleRefpoints
|
||||
cv.StereoMatcher.compute
|
||||
cv.StereoMatcher.getMinDisparity
|
||||
cv.StereoMatcher.setMinDisparity
|
||||
cv.StereoMatcher.getNumDisparities
|
||||
cv.StereoMatcher.setNumDisparities
|
||||
cv.StereoMatcher.getBlockSize
|
||||
cv.StereoMatcher.setBlockSize
|
||||
cv.StereoMatcher.getSpeckleWindowSize
|
||||
cv.StereoMatcher.setSpeckleWindowSize
|
||||
cv.StereoMatcher.getSpeckleRange
|
||||
cv.StereoMatcher.setSpeckleRange
|
||||
cv.StereoMatcher.getDisp12MaxDiff
|
||||
cv.StereoMatcher.setDisp12MaxDiff
|
||||
cv.StereoBM.getPreFilterType
|
||||
cv.StereoBM.setPreFilterType
|
||||
cv.StereoBM.getPreFilterSize
|
||||
cv.StereoBM.setPreFilterSize
|
||||
cv.StereoBM.getPreFilterCap
|
||||
cv.StereoBM.setPreFilterCap
|
||||
cv.StereoBM.getTextureThreshold
|
||||
cv.StereoBM.setTextureThreshold
|
||||
cv.StereoBM.getUniquenessRatio
|
||||
cv.StereoBM.setUniquenessRatio
|
||||
cv.StereoBM.getSmallerBlockSize
|
||||
cv.StereoBM.setSmallerBlockSize
|
||||
cv.StereoBM.getROI1
|
||||
cv.StereoBM.setROI1
|
||||
cv.StereoBM.getROI2
|
||||
cv.StereoBM.setROI2
|
||||
cv.StereoBM.create
|
||||
cv.StereoSGBM.getPreFilterCap
|
||||
cv.StereoSGBM.setPreFilterCap
|
||||
cv.StereoSGBM.getUniquenessRatio
|
||||
cv.StereoSGBM.setUniquenessRatio
|
||||
cv.StereoSGBM.getP1
|
||||
cv.StereoSGBM.setP1
|
||||
cv.StereoSGBM.getP2
|
||||
cv.StereoSGBM.setP2
|
||||
cv.StereoSGBM.getMode
|
||||
cv.StereoSGBM.setMode
|
||||
cv.StereoSGBM.create
|
||||
cv.undistort
|
||||
cv.initUndistortRectifyMap
|
||||
cv.getDefaultNewCameraMatrix
|
||||
cv.undistortPoints
|
||||
cv.undistortPoints
|
||||
cv.fisheye.projectPoints
|
||||
cv.fisheye.distortPoints
|
||||
cv.fisheye.undistortPoints
|
||||
cv.fisheye.initUndistortRectifyMap
|
||||
cv.fisheye.undistortImage
|
||||
cv.fisheye.estimateNewCameraMatrixForUndistortRectify
|
||||
cv.fisheye.calibrate
|
||||
cv.fisheye.stereoRectify
|
||||
cv.fisheye.stereoCalibrate
|
||||
|
@@ -0,0 +1,332 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of OpenCV project.
|
||||
# It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
# of this distribution and at http://opencv.org/license.html
|
||||
# Copyright (C) 2020 by Archit Rungta
|
||||
|
||||
from __future__ import unicode_literals # Needed for python2
|
||||
|
||||
import hdr_parser, sys, re, os
|
||||
from string import Template
|
||||
from pprint import pprint
|
||||
from collections import namedtuple
|
||||
|
||||
import os, shutil
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
from io import StringIO
|
||||
else:
|
||||
from cStringIO import StringIO
|
||||
|
||||
|
||||
from parse_tree import *
|
||||
|
||||
mod_template = ""
|
||||
with open("binding_templates_cpp/cv_core.cpp", "r") as f:
|
||||
mod_template = Template(f.read())
|
||||
|
||||
|
||||
def normalize_name(name):
|
||||
return name.replace('.', '::')
|
||||
|
||||
def normalize_class_name(name):
|
||||
_, classes, name = split_decl_name(normalize_name(name))
|
||||
return "_".join(classes+[name])
|
||||
|
||||
def normalize_full_name(name):
|
||||
ns, classes, name = split_decl_name(normalize_name(name))
|
||||
return "::".join(ns)+'::'+'_'.join(classes+[name])
|
||||
|
||||
|
||||
|
||||
def split_decl_name(name):
|
||||
chunks = name.split('::')
|
||||
namespace = chunks[:-1]
|
||||
classes = []
|
||||
while namespace and '::'.join(namespace) not in namespaces:
|
||||
classes.insert(0, namespace.pop())
|
||||
|
||||
ns = '::'.join(namespace)
|
||||
if ns not in namespaces and ns:
|
||||
assert(0)
|
||||
|
||||
return namespace, classes, chunks[-1]
|
||||
|
||||
def registered_tp_search(tp):
|
||||
found = False
|
||||
if not tp:
|
||||
return True
|
||||
for tpx in registered_types:
|
||||
if re.findall(tpx, tp):
|
||||
found = True
|
||||
break
|
||||
return found
|
||||
|
||||
namespaces = {}
|
||||
enums = []
|
||||
classes = {}
|
||||
functions = {}
|
||||
registered_types = ["int", "Size.*", "Rect.*", "Scalar", "RotatedRect", "Point.*", "explicit", "string", "bool", "uchar",
|
||||
"Vec.*", "float", "double", "char", "Mat", "size_t", "RNG", "TermCriteria"]
|
||||
|
||||
class ClassInfo(ClassInfo):
|
||||
def get_cpp_code_header(self):
|
||||
if self.ismap:
|
||||
return 'mod.map_type<%s>("%s");\n'%(self.name, self.mapped_name)
|
||||
if not self.base:
|
||||
return 'mod.add_type<%s>("%s");\n' % (self.name, self.mapped_name)
|
||||
else:
|
||||
return 'mod.add_type<%s>("%s", jlcxx::julia_base_type<%s>());\n' % (self.name, self.mapped_name, self.base)
|
||||
|
||||
def get_cpp_code_body(self):
|
||||
if self.ismap:
|
||||
return ''
|
||||
cpp_code = StringIO()
|
||||
for cons in self.constructors:
|
||||
cons.__class__ = FuncVariant
|
||||
cpp_code.write(cons.get_cons_code(self.name, self.mapped_name))
|
||||
#add get/set
|
||||
cpp_code.write('\n')
|
||||
cpp_code.write(self.get_setters())
|
||||
cpp_code.write('\n')
|
||||
cpp_code.write(self.get_getters())
|
||||
cpp_code.write(';')
|
||||
return cpp_code.getvalue()
|
||||
|
||||
# return code for functions and setters and getters if simple class or functions and map type
|
||||
|
||||
def get_prop_func_cpp(self, mode, propname):
|
||||
return "jlopencv_" + self.mapped_name + "_"+mode+"_"+propname
|
||||
|
||||
def get_getters(self):
|
||||
stra = ""
|
||||
for prop in self.props:
|
||||
if not self.isalgorithm:
|
||||
stra = stra + '\nmod.method("%s", [](const %s &cobj) {return %scobj.%s;});' % (self.get_prop_func_cpp("get", prop.name), self.name, '(int)' if prop.tp in enums else '', prop.name)
|
||||
else:
|
||||
stra = stra + '\nmod.method("%s", [](const cv::Ptr<%s> &cobj) {return %scobj->%s;});' % (self.get_prop_func_cpp("get", prop.name), self.name,'(int)' if prop.tp in enums else '', prop.name)
|
||||
return stra
|
||||
|
||||
def get_setters(self):
|
||||
stra = ""
|
||||
for prop in self.props:
|
||||
if prop.readonly:
|
||||
continue
|
||||
if not self.isalgorithm:
|
||||
stra = stra + '\nmod.method("%s", [](%s &cobj,const force_enum_int<%s>::Type &v) {cobj.%s=(%s)v;});' % (self.get_prop_func_cpp("set", prop.name), self.name, prop.tp, prop.name, prop.tp)
|
||||
else:
|
||||
stra = stra + '\nmod.method("%s", [](cv::Ptr<%s> cobj, const force_enum_int<%s>::Type &v) {cobj->%s=(%s)v;});' % (self.get_prop_func_cpp("set", prop.name), self.name, prop.tp, prop.name, prop.tp)
|
||||
return stra
|
||||
|
||||
class FuncVariant(FuncVariant):
|
||||
|
||||
def get_return(self):
|
||||
outstr = ""
|
||||
for arg in self.inlist+self.optlist:
|
||||
if arg.tp not in pass_by_val_types and arg.tp not in enums and self.promote_type(arg.tp)!=arg.tp:
|
||||
outstr = outstr + "%s=%s_down;\n"%(arg.name, arg.name)
|
||||
|
||||
if len(self.outlist)==0:
|
||||
return outstr+";"
|
||||
elif len(self.outlist)==1:
|
||||
return outstr+"return %s;" % ( ('(int64_t)' if self.outlist[0].tp in enums else ('' if self.promote_type(self.outlist[0].tp)==self.outlist[0].tp else '(%s)'%self.promote_type(self.outlist[0].tp))) + self.outlist[0].name)
|
||||
return outstr+"return make_tuple(%s);" % ",".join(["move(%s)" % (('(int64_t)' if x.tp in enums else ('' if self.promote_type(x.tp)==x.tp else '(%s)'%self.promote_type(x.tp))) +x.name) for x in self.outlist])
|
||||
|
||||
def promote_type(self, tp):
|
||||
if tp=='int':
|
||||
return 'long long'
|
||||
elif tp =='float':
|
||||
return 'double'
|
||||
return tp
|
||||
|
||||
def get_argument(self, isalgo):
|
||||
args = self.inlist + self.optlist
|
||||
if self.classname!="" and not self.isconstructor and not self.isstatic:
|
||||
if isalgo:
|
||||
args = [ArgInfo("cobj", ("cv::Ptr<%s>" % self.classname))] + args
|
||||
else:
|
||||
args = [ArgInfo("cobj", self.classname)] + args
|
||||
|
||||
argnamelist = []
|
||||
for arg in args:
|
||||
if arg.tp in pass_by_val_types:
|
||||
print("PATHWAY NOT TESTED")
|
||||
argnamelist.append(arg.tp[:-1] +"& "+arg.name)
|
||||
elif arg.tp in enums:
|
||||
argnamelist.append("int64_t& " + arg.name)
|
||||
else:
|
||||
if arg.tp=='bool':
|
||||
# Bool pass-by-reference is broken
|
||||
argnamelist.append(arg.tp+" " +arg.name)
|
||||
else:
|
||||
argnamelist.append(self.promote_type(arg.tp) + "& "+arg.name)
|
||||
# argnamelist = [(arg.tp if arg.tp not in pass_by_val_types else arg.tp[:-1]) +"& "+arg.name for arg in args]
|
||||
argstr = ", ".join(argnamelist)
|
||||
return argstr
|
||||
|
||||
def get_def_outtypes(self):
|
||||
outstr = ""
|
||||
for arg in self.deflist:
|
||||
outstr = outstr + "%s %s;"%(arg.tp if arg.tp not in pass_by_val_types else arg.tp[:-1], arg.name)
|
||||
for arg in self.inlist+self.optlist:
|
||||
if arg.tp not in pass_by_val_types and arg.tp not in enums and self.promote_type(arg.tp)!=arg.tp:
|
||||
outstr = outstr + "%s %s_down=(%s)%s;"%(arg.tp if arg.tp not in pass_by_val_types else arg.tp[:-1], arg.name, arg.tp, arg.name)
|
||||
|
||||
return outstr
|
||||
|
||||
def get_retval(self, isalgo):
|
||||
if self.rettype:
|
||||
stra = "auto retval = "
|
||||
else:
|
||||
stra = ""
|
||||
arlist = []
|
||||
for x in self.args:
|
||||
if x.tp in pass_by_val_types:
|
||||
arlist.append("&"+x.name)
|
||||
elif x.tp in enums:
|
||||
arlist.append("(%s)%s" %(x.tp, x.name))
|
||||
else:
|
||||
if self.promote_type(x.tp) == x.tp:
|
||||
arlist.append(x.name)
|
||||
else:
|
||||
if len([y for y in self.inlist+self.optlist if y.name==x.name])>0:
|
||||
# print("ss")
|
||||
arlist.append("%s_down" %(x.name))
|
||||
else:
|
||||
arlist.append(x.name)
|
||||
|
||||
argstr = ", ".join(arlist)
|
||||
if self.classname and not self.isstatic:
|
||||
stra = stra + "cobj%s%s(%s); " %("->" if isalgo else ".",self.name.split('::')[-1], argstr)
|
||||
else:
|
||||
stra = stra + "%s(%s);" % (self.name, argstr)
|
||||
return stra
|
||||
|
||||
def get_cons_code(self, name, mapped_name):
|
||||
# if self.get_argument(False) == '':
|
||||
# return ''
|
||||
arglist = []
|
||||
for x in self.args:
|
||||
if x.tp in pass_by_val_types:
|
||||
arglist.append("&"+x.name)
|
||||
elif x.tp in enums:
|
||||
arglist.append("(%s)%s" %(x.tp, x.name))
|
||||
else:
|
||||
if self.promote_type(x.tp) == x.tp:
|
||||
arglist.append(x.name)
|
||||
else:
|
||||
# print("ss")
|
||||
arglist.append("%s_down" %(x.name))
|
||||
return 'mod.method("%s", [](%s) { %s return jlcxx::create<%s>(%s);});' % (self.get_wrapper_name(), self.get_argument(False), self.get_def_outtypes(), name, " ,".join(arglist))
|
||||
|
||||
def get_complete_code(self, classname, isalgo=False):
|
||||
outstr = '.method("%s", [](%s) {%s %s %s})' % (self.get_wrapper_name(), self.get_argument(isalgo),self.get_def_outtypes(), self.get_retval(isalgo), self.get_return())
|
||||
return outstr
|
||||
|
||||
|
||||
|
||||
def gen(srcfiles):
|
||||
namespaces, default_values = gen_tree(srcfiles)
|
||||
cpp_code = StringIO()
|
||||
include_code = StringIO()
|
||||
nsi = sorted(namespaces.items(), key =lambda x: x[0])
|
||||
|
||||
for name, ns in nsi:
|
||||
cpp_code.write("using namespace %s;\n" % name.replace(".", "::"))
|
||||
|
||||
if name.split('.')[-1] == '':
|
||||
continue
|
||||
nsname = name
|
||||
nsprefix = '_'.join(nsname.split('::')[1:])
|
||||
|
||||
def sort_classes(classes):
|
||||
class_inherits = []
|
||||
class_inherits_names = set()
|
||||
class_noinherits = []
|
||||
parent = {}
|
||||
for name, cl in classes:
|
||||
if cl.base:
|
||||
class_inherits.append((name, cl))
|
||||
parent[name] = cl.base
|
||||
class_inherits_names.add(name)
|
||||
else:
|
||||
class_noinherits.append((name,cl))
|
||||
|
||||
final_order = class_noinherits
|
||||
|
||||
while len(class_inherits)>0:
|
||||
for cli in class_inherits:
|
||||
if parent[cli[0]] not in class_inherits_names:
|
||||
final_order.append(cli)
|
||||
class_inherits.remove(cli)
|
||||
class_inherits_names.remove(cli[0])
|
||||
|
||||
|
||||
return final_order
|
||||
|
||||
sorted_cls = sort_classes(ns.classes.items())
|
||||
for name, cl in sorted_cls:
|
||||
cl.__class__ = ClassInfo
|
||||
cpp_code.write(cl.get_cpp_code_header())
|
||||
if cl.base:
|
||||
include_code.write("""
|
||||
template <>
|
||||
struct SuperType<%s>
|
||||
{
|
||||
typedef %s type;
|
||||
};
|
||||
""" % (cl.name.replace('.', '::'), cl.base.replace('.', '::')))
|
||||
|
||||
for e1,e2 in ns.enums.items():
|
||||
# cpp_code.write('\n mod.add_bits<{0}>("{1}", jlcxx::julia_type("CppEnum"));'.format(e2[0], e2[1]))
|
||||
enums.append(e2[0])
|
||||
enums.append(e2[1])
|
||||
enums.append(e2[0].replace("cv::", "").replace("::", '_'))
|
||||
|
||||
|
||||
for tp in ns.register_types:
|
||||
cpp_code.write(' mod.add_type<%s>("%s");\n' %(tp, normalize_class_name(tp)))
|
||||
|
||||
# print(enums)
|
||||
for name, ns in namespaces.items():
|
||||
|
||||
nsname = name.replace("::", "_")
|
||||
for name, cl in ns.classes.items():
|
||||
cl.__class__ = ClassInfo
|
||||
cpp_code.write(cl.get_cpp_code_body())
|
||||
for mname, fs in cl.methods.items():
|
||||
for f in fs:
|
||||
f.__class__ = FuncVariant
|
||||
cpp_code.write('\n mod%s;' % f.get_complete_code(cl.name, cl.isalgorithm))
|
||||
# for f in cl.constructors:
|
||||
# cpp_code.write('\n %s; \n' % f.get_cons_code(cl.name, cl.mapped_name))
|
||||
|
||||
|
||||
for mname, fs in ns.funcs.items():
|
||||
for f in fs:
|
||||
f.__class__ = FuncVariant
|
||||
cpp_code.write('\n mod%s;' % f.get_complete_code("", False))
|
||||
|
||||
for mapname, name in sorted(ns.consts.items()):
|
||||
cpp_code.write(' mod.set_const("%s_%s", (force_enum_int<decltype(%s)>::Type)%s);\n'%(nsname, name, mapname, mapname))
|
||||
compat_name = re.sub(r"([a-z])([A-Z])", r"\1_\2", name).upper()
|
||||
if name != compat_name:
|
||||
cpp_code.write(' mod.set_const("%s_%s", (force_enum_int<decltype(%s)>::Type)%s);\n'%(nsname, compat_name, mapname, mapname))
|
||||
default_values = list(set(default_values))
|
||||
for val in default_values:
|
||||
# val = handle_cpp_arg(val)
|
||||
|
||||
cpp_code.write(' mod.method("%s", [](){return (force_enum_int<decltype(%s)>::Type)%s;});\n'%(get_var(val), val, val))
|
||||
|
||||
with open ('autogen_cpp/cv_core.cpp', 'w') as fd:
|
||||
fd.write(mod_template.substitute(include_code = include_code.getvalue(), cpp_code=cpp_code.getvalue()))
|
||||
|
||||
|
||||
|
||||
srcfiles = hdr_parser.opencv_hdr_list
|
||||
if len(sys.argv) > 1:
|
||||
srcfiles = [l.strip() for l in sys.argv[1].split(';')]
|
||||
|
||||
|
||||
gen(srcfiles)
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of OpenCV project.
|
||||
# It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
# of this distribution and at http://opencv.org/license.html
|
||||
# Copyright (C) 2020 by Archit Rungta
|
||||
|
||||
|
||||
from __future__ import unicode_literals # Needed for python2
|
||||
|
||||
import hdr_parser, sys, re, os
|
||||
from string import Template
|
||||
from pprint import pprint
|
||||
from collections import namedtuple
|
||||
if sys.version_info[0] >= 3:
|
||||
from io import StringIO
|
||||
else:
|
||||
from cStringIO import StringIO
|
||||
import os, shutil
|
||||
|
||||
from parse_tree import *
|
||||
|
||||
|
||||
|
||||
submodule_template = Template('')
|
||||
root_template = Template('')
|
||||
with open("binding_templates_jl/template_cv2_submodule.jl", "r") as f:
|
||||
submodule_template = Template(f.read())
|
||||
with open("binding_templates_jl/template_cv2_root.jl", "r") as f:
|
||||
root_template = Template(f.read())
|
||||
|
||||
|
||||
class FuncVariant(FuncVariant):
|
||||
|
||||
def get_complete_code(self, classname='', isalgo = False, iscons = False, gen_default = True, ns = ''):
|
||||
return 'const %s = OpenCV.%s_%s' %(self.mapped_name, ns, self.mapped_name)
|
||||
|
||||
|
||||
def gen(srcfiles):
|
||||
namespaces, _ = gen_tree(srcfiles)
|
||||
|
||||
jl_code = StringIO()
|
||||
for name, ns in namespaces.items():
|
||||
# cv_types.extend(ns.registered)
|
||||
jl_code = StringIO()
|
||||
nsname = '_'.join(name.split('::')[1:])
|
||||
|
||||
# Do not duplicate functions. This should prevent overwriting of Mat function by UMat functions
|
||||
function_signatures = []
|
||||
if name != 'cv':
|
||||
for cname, cl in ns.classes.items():
|
||||
cl.__class__ = ClassInfo
|
||||
for mname, fs in cl.methods.items():
|
||||
for f in fs:
|
||||
f.__class__ = FuncVariant
|
||||
if f.mapped_name in function_signatures:
|
||||
print("Skipping entirely: ", f.name)
|
||||
continue
|
||||
jl_code.write('\n%s' % f.get_complete_code(isalgo = cl.isalgorithm, ns=nsname))
|
||||
function_signatures.append(f.mapped_name)
|
||||
for f in cl.constructors:
|
||||
f.__class__ = FuncVariant
|
||||
jl_code.write('\n%s' % f.get_complete_code(classname = cl.mapped_name, isalgo = cl.isalgorithm, iscons = True, ns=nsname))
|
||||
break
|
||||
for mname, fs in ns.funcs.items():
|
||||
for f in fs:
|
||||
f.__class__ = FuncVariant
|
||||
if f.mapped_name in function_signatures:
|
||||
continue
|
||||
jl_code.write('\n%s' % f.get_complete_code(ns=nsname))
|
||||
function_signatures.append(f.mapped_name)
|
||||
jl_code.write('\n')
|
||||
for mapname, cname in sorted(ns.consts.items()):
|
||||
jl_code.write(' const %s = OpenCV.%s_%s\n'%(cname, name.replace('::', '_'), cname))
|
||||
compat_name = re.sub(r"([a-z])([A-Z])", r"\1_\2", cname).upper()
|
||||
if cname != compat_name:
|
||||
jl_code.write(' const %s = OpenCV.%s_%s;\n'%(compat_name, name.replace('::', '_'), compat_name))
|
||||
|
||||
imports = ''
|
||||
for namex in namespaces:
|
||||
if namex.startswith(name) and len(namex.split('::')) == 1 + len(name.split('::')):
|
||||
imports = imports + '\ninclude("%s_wrap.jl")'%namex.replace('::', '_')
|
||||
code = ''
|
||||
if name == 'cv':
|
||||
code = root_template.substitute(modname = name, code = jl_code.getvalue(), submodule_imports = imports)
|
||||
else:
|
||||
code = submodule_template.substitute(modname = name.split('::')[-1], code = jl_code.getvalue(), submodule_imports = imports)
|
||||
|
||||
with open ('autogen_jl/%s_wrap.jl' % ns.name.replace('::', '_'), 'w') as fd:
|
||||
fd.write(code)
|
||||
|
||||
|
||||
|
||||
srcfiles = hdr_parser.opencv_hdr_list
|
||||
if len(sys.argv) > 1:
|
||||
srcfiles = [l.strip() for l in sys.argv[1].split(';')]
|
||||
|
||||
|
||||
gen(srcfiles)
|
||||
Executable
+244
@@ -0,0 +1,244 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of OpenCV project.
|
||||
# It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
# of this distribution and at http://opencv.org/license.html
|
||||
# Copyright (C) 2020 by Archit Rungta
|
||||
|
||||
from __future__ import unicode_literals # Needed for python2
|
||||
|
||||
import hdr_parser, sys, re, os
|
||||
from string import Template
|
||||
from pprint import pprint
|
||||
from collections import namedtuple
|
||||
if sys.version_info[0] >= 3:
|
||||
from io import StringIO
|
||||
else:
|
||||
from cStringIO import StringIO
|
||||
import os, shutil
|
||||
|
||||
from parse_tree import *
|
||||
|
||||
|
||||
jl_cpp_argmap = {}
|
||||
jl_cpp_defmap = {}
|
||||
julia_types = ["Int32", "Float32", "Float64", "Bool", "String", "Array", "Any"]
|
||||
cv_types = ["UMat","Size" ]
|
||||
|
||||
submodule_template = Template('')
|
||||
root_template = Template('')
|
||||
with open("binding_templates_jl/template_cv2_submodule_cxx.jl", "r") as f:
|
||||
submodule_template = Template(f.read())
|
||||
with open("binding_templates_jl/template_cv2_root.jl", "r") as f:
|
||||
root_template = Template(f.read())
|
||||
with open("typemap.txt", 'r') as f:
|
||||
tmp = f.readlines()
|
||||
for ln in tmp:
|
||||
ln = ln.strip('\n').split(':')
|
||||
jl_cpp_argmap[ln[0]] = ln[1]
|
||||
with open("defval.txt", 'r') as f:
|
||||
tmp = f.readlines()
|
||||
for ln in tmp:
|
||||
ln = ln.strip('\n').split('|')
|
||||
if ln[0] not in jl_cpp_defmap:
|
||||
jl_cpp_defmap[ln[0]] = {}
|
||||
jl_cpp_defmap[ln[0]][ln[1]] = ln[2]
|
||||
|
||||
|
||||
def handle_def_arg(inp, tp = '', ns=''):
|
||||
tp = tp.strip()
|
||||
inp = inp.strip()
|
||||
|
||||
out = ''
|
||||
|
||||
if inp in jl_cpp_defmap[tp]:
|
||||
out = jl_cpp_defmap[tp][inp]
|
||||
elif inp != '':
|
||||
print(inp+" not found")
|
||||
# print(inp, tp, out)
|
||||
return out
|
||||
|
||||
def handle_jl_arg(inp):
|
||||
if not inp:
|
||||
return ''
|
||||
inp = inp.replace('std::', '')
|
||||
if inp in jl_cpp_argmap:
|
||||
return jl_cpp_argmap[inp]
|
||||
inp = inp.replace('cv::', '')
|
||||
return inp
|
||||
# return outs
|
||||
|
||||
class ClassInfo(ClassInfo):
|
||||
|
||||
def get_jl_code(self):
|
||||
|
||||
if self.ismap:
|
||||
return ''
|
||||
return self.overload_get()+self.overload_set()
|
||||
|
||||
def overload_get(self):
|
||||
stra = "function Base.getproperty(m::%s, s::Symbol)\n" %(self.mapped_name)
|
||||
if self.isalgorithm:
|
||||
stra = "function Base.getproperty(m::cv_Ptr{%s}, s::Symbol)\n" %(self.mapped_name)
|
||||
for prop in self.props:
|
||||
stra = stra + " if s==:" + prop.name+"\n"
|
||||
stra = stra + " return cpp_to_julia(%s(m))\n"%self.get_prop_func_cpp("get", prop.name)
|
||||
stra = stra + " end\n"
|
||||
stra = stra + " return Base.getfield(m, s)\nend\n"
|
||||
return stra
|
||||
|
||||
def overload_set(self):
|
||||
|
||||
stra = "function Base.setproperty!(m::%s, s::Symbol, v)\n" %(self.mapped_name)
|
||||
if self.isalgorithm:
|
||||
stra = "function Base.setproperty!(m::cv_Ptr{%s}, s::Symbol, v)\n" %(self.mapped_name)
|
||||
|
||||
for prop in self.props:
|
||||
if not prop.readonly:
|
||||
continue
|
||||
stra = stra + " if s==:" + prop.name+"\n"
|
||||
stra = stra + " %s(m, julia_to_cpp(v))\n"%(self.get_prop_func_cpp("set", prop.name))
|
||||
stra = stra + " end\n"
|
||||
stra = stra + " return Base.setfield!(m, s, v)\nend\n"
|
||||
return stra
|
||||
|
||||
class FuncVariant(FuncVariant):
|
||||
|
||||
def promote_type(self, tp):
|
||||
if tp=='int':
|
||||
return 'long long'
|
||||
elif tp =='float':
|
||||
return 'double'
|
||||
return tp
|
||||
|
||||
|
||||
def get_argument_full(self, classname='', isalgo = False):
|
||||
arglist = self.inlist + self.optlist
|
||||
|
||||
argnamelist = [arg.name+"::"+(handle_jl_arg(self.promote_type(arg.tp)) if handle_jl_arg(arg.tp) not in pass_by_val_types else handle_jl_arg(self.promote_type(arg.tp[:-1]))) for arg in arglist]
|
||||
argstr = ", ".join(argnamelist)
|
||||
return argstr
|
||||
|
||||
def get_argument_opt(self, ns=''):
|
||||
# [print(arg.default_value,":",handle_def_arg(arg.default_value, handle_jl_arg(arg.tp))) for arg in self.optlist]
|
||||
try:
|
||||
str2 = ", ".join(["%s::%s = %s(%s)" % (arg.name, handle_jl_arg(self.promote_type(arg.tp)), handle_jl_arg(self.promote_type(arg.tp)) if (arg.tp == 'int' or arg.tp=='float' or arg.tp=='double') else '', handle_def_arg(arg.default_value, handle_jl_arg(self.promote_type(arg.tp)), ns)) for arg in self.optlist])
|
||||
return str2
|
||||
except KeyError:
|
||||
return ''
|
||||
|
||||
def get_argument_def(self, classname, isalgo):
|
||||
arglist = self.inlist
|
||||
argnamelist = [arg.name+"::"+(handle_jl_arg(self.promote_type(arg.tp)) if handle_jl_arg(self.promote_type(arg.tp)) not in pass_by_val_types else handle_jl_arg(self.promote_type(arg.tp[:-1]))) for arg in arglist]
|
||||
argstr = ", ".join(argnamelist)
|
||||
return argstr
|
||||
|
||||
def get_return(self, classname=''):
|
||||
argstr = ''
|
||||
arglist = self.inlist + self.optlist
|
||||
return "return cpp_to_julia(%s(%s))" %(self.get_wrapper_name(), ",".join(["julia_to_cpp(%s)" % (x.name) for x in arglist]))
|
||||
|
||||
def get_algo_tp(self, classname, isalgo):
|
||||
if not isalgo or not classname:
|
||||
return ''
|
||||
return ' where {T <: %s}' % classname
|
||||
|
||||
def get_complete_code(self, classname='', isalgo = False, iscons = False, gen_default = True, ns = ''):
|
||||
if classname and not iscons:
|
||||
if isalgo:
|
||||
self.inlist = [ArgInfo("cobj", "cv_Ptr{T}")] + self.inlist
|
||||
else:
|
||||
self.inlist = [ArgInfo("cobj", classname)] + self.inlist
|
||||
map_name = self.mapped_name
|
||||
if ns!='cv':
|
||||
map_name = '%s_%s' %(ns.split('::')[-1], map_name)
|
||||
outstr = 'function %s(%s)%s\n\t%s\nend\n' % (map_name, self.get_argument_full(classname, isalgo), self.get_algo_tp(classname, isalgo),self.get_return())
|
||||
|
||||
|
||||
str2 = ", ".join([x.name for x in self.inlist + self.optlist])
|
||||
# outstr = outstr +
|
||||
if self.get_argument_opt() != '' and gen_default:
|
||||
outstr = outstr + ('%s(%s; %s)%s = %s(%s)\n' % (map_name, self.get_argument_def(classname, isalgo), self.get_argument_opt(ns), self.get_algo_tp(classname, isalgo), map_name, str2))
|
||||
|
||||
if iscons and len(self.inlist+self.optlist)==0 and ns=='cv':
|
||||
return ''
|
||||
|
||||
return outstr
|
||||
|
||||
|
||||
|
||||
def gen(srcfiles):
|
||||
namespaces, _ = gen_tree(srcfiles)
|
||||
|
||||
jl_code = StringIO()
|
||||
for name, ns in namespaces.items():
|
||||
cv_types.extend(ns.registered)
|
||||
jl_code = StringIO()
|
||||
nsname = name
|
||||
for e1,e2 in ns.enums.items():
|
||||
# jl_code.write('\n const {0} = Int32'.format(e2[0]))
|
||||
jl_code.write('\n const {0} = Int64 \n'.format(e2[0].replace("cv::", "").replace("::", "_")))
|
||||
|
||||
# Do not duplicate functions. This should prevent overwriting of Mat function by UMat functions
|
||||
function_signatures = []
|
||||
for cname, cl in ns.classes.items():
|
||||
cl.__class__ = ClassInfo
|
||||
jl_code.write(cl.get_jl_code())
|
||||
for mname, fs in cl.methods.items():
|
||||
for f in fs:
|
||||
f.__class__ = FuncVariant
|
||||
sign = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist+f.optlist])
|
||||
if sign in function_signatures:
|
||||
print("Skipping entirely: ", f.name)
|
||||
continue
|
||||
sign2 = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist])
|
||||
gend = True
|
||||
if sign2 in function_signatures:
|
||||
print("Skipping default declaration: ", f.name)
|
||||
gend = False
|
||||
jl_code.write('\n%s' % f.get_complete_code(classname = cl.mapped_name, isalgo = cl.isalgorithm, gen_default = gend, ns=nsname))
|
||||
function_signatures.append(sign)
|
||||
function_signatures.append(sign2)
|
||||
for f in cl.constructors:
|
||||
f.__class__ = FuncVariant
|
||||
jl_code.write('\n%s' % f.get_complete_code(classname = cl.mapped_name, isalgo = cl.isalgorithm, iscons = True, ns=nsname))
|
||||
for mname, fs in ns.funcs.items():
|
||||
for f in fs:
|
||||
f.__class__ = FuncVariant
|
||||
sign = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist+f.optlist])
|
||||
if sign in function_signatures:
|
||||
print("Skipping entirely: ", f.name)
|
||||
continue
|
||||
gend = True
|
||||
sign2 = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist])
|
||||
if sign2 in function_signatures:
|
||||
print("Skipping default declaration: ", f.name)
|
||||
gend = False
|
||||
|
||||
jl_code.write('\n%s' % f.get_complete_code(gen_default = gend, ns=nsname))
|
||||
function_signatures.append(sign)
|
||||
function_signatures.append(sign2)
|
||||
|
||||
|
||||
imports = ''
|
||||
for namex in namespaces:
|
||||
if namex.startswith(name) and len(namex.split('::')) == 1 + len(name.split('::')):
|
||||
imports = imports + '\ninclude("%s_cxx_wrap.jl")'%namex.replace('::', '_')
|
||||
code = ''
|
||||
if name == 'cv':
|
||||
code = root_template.substitute(modname = name, code = jl_code.getvalue(), submodule_imports = imports)
|
||||
else:
|
||||
code = submodule_template.substitute(code = jl_code.getvalue(), submodule_imports = imports)
|
||||
|
||||
with open ('autogen_jl/%s_cxx_wrap.jl' % ns.name.replace('::', '_'), 'w') as fd:
|
||||
fd.write(code)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
srcfiles = hdr_parser.opencv_hdr_list
|
||||
if len(sys.argv) > 1:
|
||||
srcfiles = [l.strip() for l in sys.argv[1].split(';')]
|
||||
|
||||
gen(srcfiles)
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# This file is part of OpenCV project.
|
||||
# It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
# of this distribution and at http://opencv.org/license.html
|
||||
# Copyright (C) 2020 by Archit Rungta
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
mod_path = sys.argv[1]
|
||||
|
||||
|
||||
hdr_list = [
|
||||
mod_path+"/core/include/opencv2/core.hpp",
|
||||
mod_path+"/core/include/opencv2/core/base.hpp",
|
||||
mod_path+"/core/include/opencv2/core/bindings_utils.hpp",
|
||||
mod_path+"/core/include/opencv2/core/optim.hpp",
|
||||
mod_path+"/core/include/opencv2/core/persistence.hpp",
|
||||
mod_path+"/core/include/opencv2/core/types.hpp",
|
||||
mod_path+"/core/include/opencv2/core/utility.hpp"]
|
||||
|
||||
for module in sys.argv[2:]:
|
||||
if module=='opencv_imgproc':
|
||||
hdr_list.append(mod_path+"/imgproc/include/opencv2/imgproc.hpp")
|
||||
elif module =='opencv_dnn':
|
||||
hdr_list.append(mod_path+"/dnn/include/opencv2/dnn/dnn.hpp")
|
||||
elif module == 'opencv_imgcodecs':
|
||||
hdr_list.append(mod_path+"/imgcodecs/include/opencv2/imgcodecs.hpp")
|
||||
elif module =='opencv_videoio':
|
||||
hdr_list.append(mod_path+"/videoio/include/opencv2/videoio.hpp")
|
||||
elif module =='opencv_highgui':
|
||||
hdr_list.append(mod_path+"/highgui/include/opencv2/highgui.hpp")
|
||||
elif module =='opencv_calib3d':
|
||||
hdr_list.append(mod_path+"/calib3d/include/opencv2/calib3d.hpp")
|
||||
|
||||
if not os.path.exists('autogen_cpp'):
|
||||
os.makedirs('autogen_cpp')
|
||||
os.makedirs('autogen_jl')
|
||||
|
||||
subprocess.call([sys.executable, 'gen3_cpp.py', str(';'.join(hdr_list))])
|
||||
subprocess.call([sys.executable, 'gen3_julia_cxx.py', str(';'.join(hdr_list))])
|
||||
subprocess.call([sys.executable, 'gen3_julia.py', str(';'.join(hdr_list))])
|
||||
@@ -0,0 +1,49 @@
|
||||
#Adapted from IndirectArray
|
||||
|
||||
struct Mat{T <: dtypes} <: AbstractArray{T,3}
|
||||
mat
|
||||
data_raw
|
||||
data
|
||||
|
||||
@inline function Mat{T}(mat, data_raw::AbstractArray{T,3}) where {T <: dtypes}
|
||||
data = reinterpret(T, data_raw)
|
||||
new{T}(mat, data_raw, data)
|
||||
end
|
||||
|
||||
@inline function Mat(data_raw::AbstractArray{T, 3}) where {T <: dtypes}
|
||||
data = reinterpret(T, data_raw)
|
||||
mat = nothing
|
||||
new{T}(mat, data_raw, data)
|
||||
end
|
||||
end
|
||||
|
||||
function Base.deepcopy_internal(x::Mat{T}, y::IdDict) where {T}
|
||||
if haskey(y, x)
|
||||
return y[x]
|
||||
end
|
||||
ret = Base.copy(x)
|
||||
y[x] = ret
|
||||
return ret
|
||||
end
|
||||
|
||||
Base.size(A::Mat) = size(A.data)
|
||||
Base.axes(A::Mat) = axes(A.data)
|
||||
Base.IndexStyle(::Type{Mat{T}}) where {T} = IndexCartesian()
|
||||
|
||||
Base.strides(A::Mat{T}) where {T} = strides(A.data)
|
||||
Base.copy(A::Mat{T}) where {T} = Mat(copy(A.data_raw))
|
||||
Base.pointer(A::Mat) = Base.pointer(A.data)
|
||||
|
||||
Base.unsafe_convert(::Type{Ptr{T}}, A::Mat{S}) where {T, S} = Base.unsafe_convert(Ptr{T}, A.data)
|
||||
|
||||
@inline function Base.getindex(A::Mat{T}, I::Vararg{Int,3}) where {T}
|
||||
@boundscheck checkbounds(A.data, I...)
|
||||
@inbounds ret = A.data[I...]
|
||||
ret
|
||||
end
|
||||
|
||||
@inline function Base.setindex!(A::Mat, x, I::Vararg{Int,3})
|
||||
@boundscheck checkbounds(A.data, I...)
|
||||
A.data[I...] = x
|
||||
return A
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
module OpenCV
|
||||
|
||||
import Base.size
|
||||
|
||||
include("cv_cxx.jl")
|
||||
|
||||
|
||||
include("cv_wrap.jl")
|
||||
|
||||
end
|
||||
@@ -0,0 +1,50 @@
|
||||
#Adapted from IndirectArray
|
||||
|
||||
struct Vec{T, N} <: AbstractArray{T,1}
|
||||
cpp_object
|
||||
data::AbstractArray{T, 1}
|
||||
cpp_allocated::Bool
|
||||
@inline function Vec{T, N}(obj) where {T, N}
|
||||
|
||||
new{T, N}(obj, Base.unsafe_wrap(Array{T, 1}, Ptr{T}(obj.cpp_object), N), true)
|
||||
end
|
||||
|
||||
@inline function Vec{T, N}(data_raw::AbstractArray{T, 1}) where {T, N}
|
||||
if size(data_raw, 1) != N
|
||||
throw("Array is improper Size for Vec declared")
|
||||
end
|
||||
new{T, N}(nothing, data_raw, false)
|
||||
end
|
||||
end
|
||||
|
||||
function Base.deepcopy_internal(x::Vec{T,N}, y::IdDict) where {T, N}
|
||||
if haskey(y, x)
|
||||
return y[x]
|
||||
end
|
||||
ret = Base.copy(x)
|
||||
y[x] = ret
|
||||
return ret
|
||||
end
|
||||
|
||||
Base.size(A::Vec) = Base.size(A.data)
|
||||
Base.axes(A::Vec) = Base.axes(A.data)
|
||||
Base.IndexStyle(::Type{Vec{T,N}}) where {T, N} = IndexLinear()
|
||||
|
||||
Base.strides(A::Vec{T,N}) where {T, N} = (1)
|
||||
function Base.copy(A::Vec{T,N}) where {T, N}
|
||||
return Vec{T, N}(copy(A.data))
|
||||
end
|
||||
Base.pointer(A::Vec) = Base.pointer(A.data)
|
||||
|
||||
Base.unsafe_convert(::Type{Ptr{T}}, A::Vec{S, N}) where {T, S, N} = Base.unsafe_convert(Ptr{T}, A.data)
|
||||
|
||||
@inline function Base.getindex(A::Vec{T,N}, I::Int) where {T, N}
|
||||
@boundscheck checkbounds(A.data, I)
|
||||
return A.data[I]
|
||||
end
|
||||
|
||||
@inline function Base.setindex!(A::Vec, x, I::Int)
|
||||
@boundscheck checkbounds(A.data, I)
|
||||
A.data[I] = x
|
||||
return A
|
||||
end
|
||||
@@ -0,0 +1,52 @@
|
||||
# using StaticArrays
|
||||
|
||||
include("typestructs.jl")
|
||||
include("Vec.jl")
|
||||
const dtypes = Union{UInt8, Int8, UInt16, Int16, Int32, Float32, Float64}
|
||||
size_t = UInt64
|
||||
|
||||
using CxxWrap
|
||||
@wrapmodule(joinpath(@__DIR__,"lib","libopencv_julia"), :cv_wrap)
|
||||
function __init__()
|
||||
@initcxx
|
||||
|
||||
if jlopencv_core_get_sizet()==4
|
||||
size_t = UInt32
|
||||
end
|
||||
end
|
||||
const Scalar = Union{Tuple{}, Tuple{Number}, Tuple{Number, Number}, Tuple{Number, Number, Number}, NTuple{4, Number}}
|
||||
|
||||
include("Mat.jl")
|
||||
|
||||
const InputArray = Union{AbstractArray{T, 3} where {T <: dtypes}, CxxMat}
|
||||
|
||||
include("mat_conversion.jl")
|
||||
include("types_conversion.jl")
|
||||
|
||||
function cpp_to_julia(var)
|
||||
return var
|
||||
end
|
||||
function julia_to_cpp(var)
|
||||
return var
|
||||
end
|
||||
|
||||
function cpp_to_julia(var::Tuple)
|
||||
ret_arr = Array{Any, 1}()
|
||||
for it in var
|
||||
push!(ret_arr, cpp_to_julia(it))
|
||||
end
|
||||
return tuple(ret_arr...)
|
||||
end
|
||||
|
||||
function cpp_to_julia(var::CxxBool)
|
||||
return Bool(var)
|
||||
end
|
||||
|
||||
function julia_to_cpp(var::Bool)
|
||||
return CxxBool(var)
|
||||
end
|
||||
|
||||
|
||||
include("cv_cxx_wrap.jl")
|
||||
|
||||
include("cv_manual_wrap.jl")
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
function createButton(bar_name::String, on_change, userdata, type::Int32 = 0, initial_button_state::Bool = false)
|
||||
func = (x)->on_change(x, userdata)
|
||||
CxxWrap.gcprotect(userdata)
|
||||
CxxWrap.gcprotect(func)
|
||||
CxxWrap.gcprotect(on_change)
|
||||
return jl_cpp_cv2.createButton(bar_name,func, type, initial_button_state)
|
||||
end
|
||||
|
||||
function setMouseCallback(winname::String, onMouse, userdata)
|
||||
func = (event, x, y, flags)->onMouse(event, x, y, flags, userdata)
|
||||
CxxWrap.gcprotect(userdata)
|
||||
CxxWrap.gcprotect(func)
|
||||
CxxWrap.gcprotect(onMouse)
|
||||
return jl_cpp_cv2.setMouseCallback(winname,func)
|
||||
end
|
||||
|
||||
function createTrackbar(trackbarname::String, winname::String, value::Ref{Int32}, count::Int32, onChange, userdata)
|
||||
func = (x)->onChange(x, userdata)
|
||||
CxxWrap.gcprotect(userdata)
|
||||
CxxWrap.gcprotect(func)
|
||||
CxxWrap.gcprotect(onChange)
|
||||
return jl_cpp_cv2.createTrackbar(trackbarname, winname, value, count, func)
|
||||
end
|
||||
|
||||
function CascadeClassifier(filename::String)
|
||||
return cpp_to_julia(jlopencv_cv_cv_CascadeClassifier_cv_CascadeClassifier_CascadeClassifier(julia_to_cpp(filename)))
|
||||
end
|
||||
|
||||
|
||||
function detect(cobj::cv_Ptr{T}, image::InputArray, mask::InputArray) where {T <: Feature2D}
|
||||
return cpp_to_julia(jlopencv_cv_cv_Feature2D_cv_Feature2D_detect(julia_to_cpp(cobj),julia_to_cpp(image),julia_to_cpp(mask)))
|
||||
end
|
||||
detect(cobj::cv_Ptr{T}, image::InputArray; mask::InputArray = (CxxMat())) where {T <: Feature2D} = detect(cobj, image, mask)
|
||||
|
||||
|
||||
function detectMultiScale(cobj::CascadeClassifier, image::InputArray, scaleFactor::Float64, minNeighbors::Int32, flags::Int32, minSize::Size{Int32}, maxSize::Size{Int32})
|
||||
return cpp_to_julia(jlopencv_cv_cv_CascadeClassifier_cv_CascadeClassifier_detectMultiScale(julia_to_cpp(cobj),julia_to_cpp(image),julia_to_cpp(scaleFactor),julia_to_cpp(minNeighbors),julia_to_cpp(flags),julia_to_cpp(minSize),julia_to_cpp(maxSize)))
|
||||
end
|
||||
detectMultiScale(cobj::CascadeClassifier, image::InputArray; scaleFactor::Float64 = Float64(1.1), minNeighbors::Int32 = Int32(3), flags::Int32 = Int32(0), minSize::Size{Int32} = (Size{Int32}(0,0)), maxSize::Size{Int32} = (Size{Int32}(0,0))) = detectMultiScale(cobj, image, scaleFactor, minNeighbors, flags, minSize, maxSize)
|
||||
|
||||
function empty(cobj::CascadeClassifier)
|
||||
return cpp_to_julia(jlopencv_cv_cv_CascadeClassifier_cv_CascadeClassifier_empty(julia_to_cpp(cobj)))
|
||||
end
|
||||
|
||||
function SimpleBlobDetector_create(parameters::SimpleBlobDetector_Params)
|
||||
return cpp_to_julia(jlopencv_cv_cv_SimpleBlobDetector_create(julia_to_cpp(parameters)))
|
||||
end
|
||||
SimpleBlobDetector_create(; parameters::SimpleBlobDetector_Params = (SimpleBlobDetector_Params())) = SimpleBlobDetector_create(parameters)
|
||||
@@ -0,0 +1,106 @@
|
||||
const CV_CN_MAX = 512
|
||||
const CV_CN_SHIFT = 3
|
||||
const CV_DEPTH_MAX = (1 << CV_CN_SHIFT)
|
||||
|
||||
const CV_8U = 0
|
||||
const CV_8S = 1
|
||||
const CV_16U = 2
|
||||
const CV_16S = 3
|
||||
const CV_32S = 4
|
||||
const CV_32F = 5
|
||||
const CV_64F = 6
|
||||
|
||||
const CV_MAT_DEPTH_MASK = (CV_DEPTH_MAX - 1)
|
||||
CV_MAT_DEPTH(flags) = ((flags) & CV_MAT_DEPTH_MASK)
|
||||
|
||||
CV_MAKETYPE(depth,cn) = (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
|
||||
CV_MAKE_TYPE = CV_MAKETYPE
|
||||
|
||||
function cpp_to_julia(mat::CxxMat)
|
||||
rets = jlopencv_core_Mat_mutable_data(mat)
|
||||
if rets[2] == CV_MAKE_TYPE(CV_8U, rets[3])
|
||||
dtype = UInt8
|
||||
elseif rets[2]==CV_MAKE_TYPE(CV_8S, rets[3])
|
||||
dtype = Int8
|
||||
elseif rets[2]==CV_MAKE_TYPE(CV_16U, rets[3])
|
||||
dtype = UInt16
|
||||
elseif rets[2]==CV_MAKE_TYPE(CV_16S, rets[3])
|
||||
dtype = Int16
|
||||
elseif rets[2]==CV_MAKE_TYPE(CV_32S, rets[3])
|
||||
dtype = Int32
|
||||
elseif rets[2]==CV_MAKE_TYPE(CV_32F, rets[3])
|
||||
dtype = Float32
|
||||
elseif rets[2]==CV_MAKE_TYPE(CV_64F, rets[3])
|
||||
dtype = Float64
|
||||
else
|
||||
error("Bad type returned from OpenCV")
|
||||
end
|
||||
steps = [rets[6]/sizeof(dtype), rets[7]/sizeof(dtype)]
|
||||
# println(steps[1]/rets[3], steps[2]/rets[3]/rets[4])
|
||||
#TODO: Implement views when steps do not result in continous memory
|
||||
arr = Base.unsafe_wrap(Array{dtype, 3}, Ptr{dtype}(rets[1].cpp_object), (rets[3], rets[4], rets[5]))
|
||||
|
||||
#Preserve Mat so that array allocated by C++ isn't deallocated
|
||||
return Mat{dtype}(mat, arr)
|
||||
end
|
||||
|
||||
function julia_to_cpp(img::InputArray)
|
||||
if typeof(img) <: CxxMat
|
||||
return img
|
||||
end
|
||||
steps = 0
|
||||
try
|
||||
steps = strides(img)
|
||||
catch
|
||||
# Copy array since array is not strided
|
||||
img = img[:, :, :]
|
||||
steps = strides(img)
|
||||
end
|
||||
|
||||
if steps[1] <= steps[2] <= steps[3] && steps[1]==1
|
||||
steps_a = Array{size_t, 1}()
|
||||
ndims_a = Array{Int32, 1}()
|
||||
sz = sizeof(eltype(img))
|
||||
push!(steps_a, UInt64(steps[3]*sz))
|
||||
push!(steps_a, UInt64(steps[2]*sz))
|
||||
push!(steps_a, UInt64(steps[1]*sz))
|
||||
|
||||
push!(ndims_a, Int32(size(img)[3]))
|
||||
push!(ndims_a, Int32(size(img)[2]))
|
||||
if eltype(img) == UInt8
|
||||
return CxxMat(2, pointer(ndims_a), CV_MAKE_TYPE(CV_8U, size(img)[1]), Ptr{Nothing}(pointer(img)), pointer(steps_a))
|
||||
elseif eltype(img) == UInt16
|
||||
return CxxMat(2, pointer(ndims_a), CV_MAKE_TYPE(CV_16U, size(img)[1]), Ptr{Nothing}(pointer(img)), pointer(steps_a))
|
||||
elseif eltype(img) == Int8
|
||||
return CxxMat(2, pointer(ndims_a), CV_MAKE_TYPE(CV_8S, size(img)[1]), Ptr{Nothing}(pointer(img)), pointer(steps_a))
|
||||
elseif eltype(img) == Int16
|
||||
return CxxMat(2, pointer(ndims_a), CV_MAKE_TYPE(CV_16S, size(img)[1]), Ptr{Nothing}(pointer(img)), pointer(steps_a))
|
||||
elseif eltype(img) == Int32
|
||||
return CxxMat(2, pointer(ndims_a), CV_MAKE_TYPE(CV_32S, size(img)[1]), Ptr{Nothing}(pointer(img)), pointer(steps_a))
|
||||
elseif eltype(img) == Float32
|
||||
return CxxMat(2, pointer(ndims_a), CV_MAKE_TYPE(CV_32F, size(img)[1]), Ptr{Nothing}(pointer(img)), pointer(steps_a))
|
||||
elseif eltype(img) == Float64
|
||||
return CxxMat(2, pointer(ndims_a), CV_MAKE_TYPE(CV_64F, size(img)[1]), Ptr{Nothing}(pointer(img)), pointer(steps_a))
|
||||
end
|
||||
else
|
||||
# Copy array, invalid config
|
||||
return julia_to_cpp(img[:, :, :])
|
||||
end
|
||||
end
|
||||
|
||||
function julia_to_cpp(var::Array{T, 1}) where {T <: InputArray}
|
||||
ret = CxxWrap.StdVector{CxxMat}()
|
||||
for x in var
|
||||
push!(ret, julia_to_cpp(x))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function cpp_to_julia(var::CxxWrap.StdVector{T}) where {T <: CxxMat}
|
||||
ret = Array{Mat, 1}()
|
||||
for x in var
|
||||
push!(ret, cpp_to_julia(x))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
function cpp_to_julia(var::CxxScalar{T}) where {T}
|
||||
var = Vec{T, 4}(var)
|
||||
return (var[1], var[2], var[3], var[4])
|
||||
end
|
||||
|
||||
function cpp_to_julia(var::CxxVec{T, N}) where {T, N}
|
||||
return Vec{T, N}(var)
|
||||
end
|
||||
|
||||
function julia_to_cpp(sc::Scalar)
|
||||
if size(sc,1)==0
|
||||
return CxxScalar{Float64}(0,0,0,0)
|
||||
elseif size(sc, 1) == 1
|
||||
return CxxScalar{Float64}(Float64(sc[1]), 0, 0, 0)
|
||||
elseif size(sc,1) == 2
|
||||
return CxxScalar{Float64}(Float64(sc[1]), Float64(sc[2]), 0, 0)
|
||||
elseif size(sc,1) == 3
|
||||
return CxxScalar{Float64}(Float64(sc[1]), Float64(sc[2]), Float64(sc[3]), 0)
|
||||
end
|
||||
return CxxScalar{Float64}(Float64(sc[1]), Float64(sc[2]), Float64(sc[3]), Float64(sc[4]))
|
||||
end
|
||||
|
||||
function julia_to_cpp(vec::Vec{T, N}) where {T, N}
|
||||
return CxxVec{T, N}(Base.pointer(vec))
|
||||
end
|
||||
|
||||
function julia_to_cpp(var::Array{T, 1}) where {T <: Scalar}
|
||||
ret = CxxWrap.StdVector{CxxScalar}()
|
||||
for x in var
|
||||
push!(ret, julia_to_cpp(x))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function julia_to_cpp(var::Array{Vec{T, N}, 1}) where {T, N}
|
||||
ret = CxxWrap.StdVector{CxxVec{T, N}}()
|
||||
for x in var
|
||||
push!(ret, julia_to_cpp(x))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function julia_to_cpp(var::Array{T, 1}) where {T}
|
||||
if size(var, 1) == 0
|
||||
return CxxWrap.StdVector{T}()
|
||||
end
|
||||
ret = CxxWrap.StdVector{typeof(julia_to_cpp(var[1]))}()
|
||||
for x in var
|
||||
push!(ret, julia_to_cpp(x))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function cpp_to_julia(var::CxxWrap.StdVector{T}) where {T <: CxxScalar}
|
||||
ret = Array{Scalar, 1}()
|
||||
for x in var
|
||||
push!(ret, cpp_to_julia(x))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function cpp_to_julia(var::CxxWrap.StdVector{CxxVec{T, N}}) where {T, N}
|
||||
ret = Array{Vec{T, N}, 1}()
|
||||
for x in var
|
||||
push!(ret, cpp_to_julia(x))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function cpp_to_julia(var::CxxWrap.StdVector{T}) where {T}
|
||||
if size(var, 1) == 0
|
||||
return Array{T, 1}()
|
||||
end
|
||||
ret = Array{typeof(cpp_to_julia(var[1])), 1}()
|
||||
for x in var
|
||||
push!(ret, cpp_to_julia(x))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
struct Point{T}
|
||||
x::T
|
||||
y::T
|
||||
end
|
||||
|
||||
struct Point3{T}
|
||||
x::T
|
||||
y::T
|
||||
z::T
|
||||
end
|
||||
|
||||
|
||||
struct Size{T}
|
||||
width::T
|
||||
height::T
|
||||
end
|
||||
|
||||
|
||||
struct Rect{T}
|
||||
x::T
|
||||
y::T
|
||||
width::T
|
||||
height::T
|
||||
end
|
||||
|
||||
struct RotatedRect
|
||||
center::Point{Float32}
|
||||
size::Size{Float32}
|
||||
angle::Float32
|
||||
end
|
||||
|
||||
struct Range
|
||||
start::Int32
|
||||
end_::Int32
|
||||
end
|
||||
|
||||
struct TermCriteria
|
||||
type::Int32
|
||||
maxCount::Int32
|
||||
epsilon::Float64
|
||||
end
|
||||
|
||||
struct cvComplex{T}
|
||||
re::T
|
||||
im::T
|
||||
end
|
||||
@@ -0,0 +1,531 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of OpenCV project.
|
||||
# It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
# of this distribution and at http://opencv.org/license.html
|
||||
# Copyright (C) 2020 by Archit Rungta
|
||||
|
||||
|
||||
import hdr_parser, sys, re, os
|
||||
from string import Template
|
||||
from pprint import pprint
|
||||
from collections import namedtuple
|
||||
import json
|
||||
import os, shutil
|
||||
from io import StringIO
|
||||
|
||||
|
||||
forbidden_arg_types = ["void*"]
|
||||
|
||||
ignored_arg_types = ["RNG*"]
|
||||
|
||||
pass_by_val_types = ["Point*", "Point2f*", "Rect*", "String*", "double*", "float*", "int*"]
|
||||
|
||||
|
||||
def get_char(c):
|
||||
if c.isalpha():
|
||||
return c
|
||||
if ord(c)%52 < 26:
|
||||
return chr(ord('a')+ord(c)%26)
|
||||
return chr(ord('A')+ord(c)%26)
|
||||
|
||||
|
||||
def get_var(inp):
|
||||
out = ''
|
||||
for c in inp:
|
||||
out = out+get_char(c)
|
||||
return out
|
||||
|
||||
def normalize_name(name):
|
||||
return name.replace('.', '::')
|
||||
|
||||
def normalize_class_name(name):
|
||||
_, classes, name = split_decl_name(normalize_name(name))
|
||||
return "_".join(classes+[name])
|
||||
|
||||
def normalize_full_name(name):
|
||||
ns, classes, name = split_decl_name(normalize_name(name))
|
||||
return "::".join(ns)+'::'+'_'.join(classes+[name])
|
||||
|
||||
|
||||
|
||||
def split_decl_name(name):
|
||||
chunks = name.split('::')
|
||||
namespace = chunks[:-1]
|
||||
classes = []
|
||||
while namespace and '::'.join(namespace) not in namespaces:
|
||||
classes.insert(0, namespace.pop())
|
||||
|
||||
ns = '::'.join(namespace)
|
||||
if ns not in namespaces and ns:
|
||||
assert(0)
|
||||
|
||||
return namespace, classes, chunks[-1]
|
||||
|
||||
|
||||
def handle_cpp_arg(inp):
|
||||
def handle_vector(match):
|
||||
return handle_cpp_arg("%svector<%s>" % (match.group(1), match.group(2)))
|
||||
def handle_ptr(match):
|
||||
return handle_cpp_arg("%sPtr<%s>" % (match.group(1), match.group(2)))
|
||||
inp = re.sub("(.*)vector_(.*)", handle_vector, inp)
|
||||
inp = re.sub("(.*)Ptr_(.*)", handle_ptr, inp)
|
||||
|
||||
|
||||
return inp.replace("String", "string")
|
||||
|
||||
def get_template_arg(inp):
|
||||
inp = inp.replace(' ','').replace('*', '').replace('cv::', '').replace('std::', '')
|
||||
def handle_vector(match):
|
||||
return get_template_arg("%s" % (match.group(1)))
|
||||
def handle_ptr(match):
|
||||
return get_template_arg("%s" % (match.group(1)))
|
||||
inp = re.sub("vector<(.*)>", handle_vector, inp)
|
||||
inp = re.sub("Ptr<(.*)>", handle_ptr, inp)
|
||||
ns, cl, n = split_decl_name(inp)
|
||||
inp = "::".join(cl+[n])
|
||||
# print(inp)
|
||||
return inp.replace("String", "string")
|
||||
|
||||
def registered_tp_search(tp):
|
||||
found = False
|
||||
if not tp:
|
||||
return True
|
||||
for tpx in registered_types:
|
||||
if re.findall(tpx, tp):
|
||||
found = True
|
||||
break
|
||||
return found
|
||||
|
||||
namespaces = {}
|
||||
type_paths = {}
|
||||
enums = {}
|
||||
classes = {}
|
||||
functions = {}
|
||||
registered_types = ["int", "Size.*", "Rect.*", "Scalar", "RotatedRect", "Point.*", "explicit", "string", "bool", "uchar",
|
||||
"Vec.*", "float", "double", "char", "Mat", "size_t", "RNG", "DescriptorExtractor", "FeatureDetector", "TermCriteria"]
|
||||
|
||||
class ClassProp(object):
|
||||
"""
|
||||
Helper class to store field information(type, name and flags) of classes and structs
|
||||
"""
|
||||
def __init__(self, decl):
|
||||
self.tp = decl[0]
|
||||
self.name = decl[1]
|
||||
self.readonly = True
|
||||
if "/RW" in decl[3]:
|
||||
self.readonly = False
|
||||
|
||||
class ClassInfo(object):
|
||||
def __init__(self, name, decl=None):
|
||||
self.name = name
|
||||
self.mapped_name = normalize_class_name(name)
|
||||
self.ismap = False #CV_EXPORTS_W_MAP
|
||||
self.isalgorithm = False #if class inherits from cv::Algorithm
|
||||
self.methods = {} #Dictionary of methods
|
||||
self.props = [] #Collection of ClassProp associated with this class
|
||||
self.base = None #name of base class if current class inherits another class
|
||||
self.constructors = [] #Array of constructors for this class
|
||||
self.add_decl(decl)
|
||||
classes[name] = self
|
||||
|
||||
def add_decl(self, decl):
|
||||
if decl:
|
||||
# print(decl)
|
||||
bases = decl[1].split(',')
|
||||
if len(bases[0].split()) > 1:
|
||||
bases[0] = bases[0].split()[1]
|
||||
|
||||
bases = [x.replace(' ','') for x in bases]
|
||||
# print(bases)
|
||||
if len(bases) > 1:
|
||||
# Clear the set a bit
|
||||
bases = list(set(bases))
|
||||
bases.remove('cv::class')
|
||||
bases_clear = []
|
||||
for bb in bases:
|
||||
if self.name not in bb:
|
||||
bases_clear.append(bb)
|
||||
bases = bases_clear
|
||||
if len(bases) > 1:
|
||||
print("Note: Class %s has more than 1 base class (not supported by CxxWrap)" % (self.name,))
|
||||
print(" Bases: ", " ".join(bases))
|
||||
print(" Only the first base class will be used")
|
||||
if len(bases) >= 1:
|
||||
self.base = bases[0].replace('.', '::')
|
||||
if "cv::Algorithm" in bases:
|
||||
self.isalgorithm = True
|
||||
|
||||
for m in decl[2]:
|
||||
if m.startswith("="):
|
||||
self.mapped_name = m[1:]
|
||||
# if m == "/Map":
|
||||
# self.ismap = True
|
||||
self.props = [ClassProp(p) for p in decl[3]]
|
||||
# return code for functions and setters and getters if simple class or functions and map type
|
||||
|
||||
def get_prop_func_cpp(self, mode, propname):
|
||||
return "jlopencv_" + self.mapped_name + "_"+mode+"_"+propname
|
||||
|
||||
argumentst = []
|
||||
default_values = []
|
||||
class ArgInfo(object):
|
||||
"""
|
||||
Helper class to parse and contain information about function arguments
|
||||
"""
|
||||
|
||||
def sec(self, arg_tuple):
|
||||
self.isbig = arg_tuple[0] in ["Mat", "vector_Mat", "cuda::GpuMat", "GpuMat", "vector_GpuMat", "UMat", "vector_UMat"] # or self.tp.startswith("vector")
|
||||
|
||||
self.tp = handle_cpp_arg(arg_tuple[0]) #C++ Type of argument
|
||||
argumentst.append(self.tp)
|
||||
self.name = arg_tuple[1] #Name of argument
|
||||
# TODO: Handle default values nicely
|
||||
self.default_value = arg_tuple[2] #Default value
|
||||
self.inputarg = True #Input argument
|
||||
self.outputarg = False #output argument
|
||||
self.ref = False
|
||||
|
||||
for m in arg_tuple[3]:
|
||||
if m == "/O":
|
||||
self.inputarg = False
|
||||
self.outputarg = True
|
||||
elif m == "/IO":
|
||||
self.inputarg = True
|
||||
self.outputarg = True
|
||||
elif m == '/Ref':
|
||||
self.ref = True
|
||||
|
||||
if self.tp in pass_by_val_types:
|
||||
self.outputarg = True
|
||||
|
||||
|
||||
|
||||
def __init__(self, name, tp = None):
|
||||
if not tp:
|
||||
self.sec(name)
|
||||
else:
|
||||
self.name = name
|
||||
self.tp = tp
|
||||
|
||||
|
||||
class FuncVariant(object):
|
||||
"""
|
||||
Helper class to parse and contain information about different overloaded versions of same function
|
||||
"""
|
||||
def __init__(self, classname, name, mapped_name, decl, namespace, istatic=False):
|
||||
self.classname = classname
|
||||
self.name = name
|
||||
self.mapped_name = mapped_name
|
||||
|
||||
self.isconstructor = name.split('::')[-1]==classname.split('::')[-1]
|
||||
self.isstatic = istatic
|
||||
self.namespace = namespace
|
||||
|
||||
self.rettype = decl[4]
|
||||
if self.rettype == "void" or not self.rettype:
|
||||
self.rettype = ""
|
||||
else:
|
||||
self.rettype = handle_cpp_arg(self.rettype)
|
||||
|
||||
self.args = []
|
||||
|
||||
for ainfo in decl[3]:
|
||||
a = ArgInfo(ainfo)
|
||||
if a.default_value and ('(' in a.default_value or ':' in a.default_value):
|
||||
default_values.append(a.default_value)
|
||||
assert not a.tp in forbidden_arg_types, 'Forbidden type "{}" for argument "{}" in "{}" ("{}")'.format(a.tp, a.name, self.name, self.classname)
|
||||
if a.tp in ignored_arg_types:
|
||||
continue
|
||||
|
||||
self.args.append(a)
|
||||
self.init_proto()
|
||||
|
||||
if name not in functions:
|
||||
functions[name]= []
|
||||
functions[name].append(self)
|
||||
|
||||
if not registered_tp_search(get_template_arg(self.rettype)):
|
||||
namespaces[namespace].register_types.append(get_template_arg(self.rettype))
|
||||
for arg in self.args:
|
||||
if not registered_tp_search(get_template_arg(arg.tp)):
|
||||
namespaces[namespace].register_types.append(get_template_arg(arg.tp))
|
||||
|
||||
|
||||
def get_wrapper_name(self):
|
||||
"""
|
||||
Return wrapping function name
|
||||
"""
|
||||
name = self.name.replace('::', '_')
|
||||
if self.classname:
|
||||
classname = self.classname.replace('::', '_') + "_"
|
||||
else:
|
||||
classname = ""
|
||||
return "jlopencv_" + self.namespace.replace('::','_') + '_' + classname + name
|
||||
|
||||
|
||||
def init_proto(self):
|
||||
# string representation of argument list, with '[', ']' symbols denoting optional arguments, e.g.
|
||||
# "src1, src2[, dst[, mask]]" for cv.add
|
||||
prototype = ""
|
||||
|
||||
inlist = []
|
||||
optlist = []
|
||||
outlist = []
|
||||
deflist = []
|
||||
biglist = []
|
||||
|
||||
# This logic can almost definitely be simplified
|
||||
|
||||
for a in self.args:
|
||||
if a.isbig and not (a.inputarg and not a.default_value):
|
||||
optlist.append(a)
|
||||
if a.outputarg:
|
||||
outlist.append(a)
|
||||
if a.inputarg and not a.default_value:
|
||||
inlist.append(a)
|
||||
elif a.inputarg and a.default_value and not a.isbig:
|
||||
optlist.append(a)
|
||||
elif not (a.isbig and not (a.inputarg and not a.default_value)):
|
||||
deflist.append(a)
|
||||
|
||||
if self.rettype:
|
||||
outlist = [ArgInfo("retval", self.rettype)] + outlist
|
||||
|
||||
if self.isconstructor:
|
||||
assert outlist == [] or outlist[0].tp == "explicit"
|
||||
outlist = [ArgInfo("retval", self.classname)]
|
||||
|
||||
|
||||
self.outlist = outlist
|
||||
self.optlist = optlist
|
||||
self.deflist = deflist
|
||||
|
||||
self.inlist = inlist
|
||||
|
||||
self.prototype = prototype
|
||||
|
||||
class NameSpaceInfo(object):
|
||||
def __init__(self, name):
|
||||
self.funcs = {}
|
||||
self.classes = {} #Dictionary of classname : ClassInfo objects
|
||||
self.enums = {}
|
||||
self.consts = {}
|
||||
self.register_types = []
|
||||
self.name = name
|
||||
|
||||
def add_func(decl):
|
||||
"""
|
||||
Creates functions based on declaration and add to appropriate classes and/or namespaces
|
||||
"""
|
||||
decl[0] = decl[0].replace('.', '::')
|
||||
namespace, classes, barename = split_decl_name(decl[0])
|
||||
name = "::".join(namespace+classes+[barename])
|
||||
full_classname = "::".join(namespace + classes)
|
||||
classname = "::".join(classes)
|
||||
namespace = '::'.join(namespace)
|
||||
is_static = False
|
||||
isphantom = False
|
||||
mapped_name = ''
|
||||
|
||||
for m in decl[2]:
|
||||
if m == "/S":
|
||||
is_static = True
|
||||
elif m == "/phantom":
|
||||
print("phantom not supported yet ")
|
||||
return
|
||||
elif m.startswith("="):
|
||||
mapped_name = m[1:]
|
||||
elif m.startswith("/mappable="):
|
||||
print("Mappable not supported yet")
|
||||
return
|
||||
# if m == "/V":
|
||||
# print("skipping ", name)
|
||||
# return
|
||||
|
||||
if classname and full_classname not in namespaces[namespace].classes:
|
||||
# print("HH1")
|
||||
# print(namespace, classname)
|
||||
namespaces[namespace].classes[full_classname] = ClassInfo(full_classname)
|
||||
assert(0)
|
||||
|
||||
|
||||
if is_static:
|
||||
# Add it as global function
|
||||
func_map = namespaces[namespace].funcs
|
||||
if name not in func_map:
|
||||
func_map[name] = []
|
||||
if not mapped_name:
|
||||
mapped_name = "_".join(classes + [barename])
|
||||
func_map[name].append(FuncVariant("", name, mapped_name, decl, namespace, True))
|
||||
else:
|
||||
if classname:
|
||||
func = FuncVariant(full_classname, name, barename, decl, namespace, False)
|
||||
if func.isconstructor:
|
||||
namespaces[namespace].classes[full_classname].constructors.append(func)
|
||||
else:
|
||||
func_map = namespaces[namespace].classes[full_classname].methods
|
||||
if name not in func_map:
|
||||
func_map[name] = []
|
||||
func_map[name].append(func)
|
||||
else:
|
||||
func_map = namespaces[namespace].funcs
|
||||
if name not in func_map:
|
||||
func_map[name] = []
|
||||
if not mapped_name:
|
||||
mapped_name = barename
|
||||
func_map[name].append(FuncVariant("", name, mapped_name, decl, namespace, False))
|
||||
|
||||
|
||||
def add_class(stype, name, decl):
|
||||
"""
|
||||
Creates class based on name and declaration. Add it to list of classes and to JSON file
|
||||
"""
|
||||
# print("n", name)
|
||||
name = name.replace('.', '::')
|
||||
classinfo = ClassInfo(name, decl)
|
||||
namespace, classes, barename = split_decl_name(name)
|
||||
namespace = '::'.join(namespace)
|
||||
|
||||
if classinfo.name in classes:
|
||||
namespaces[namespace].classes[name].add_decl(decl)
|
||||
else:
|
||||
namespaces[namespace].classes[name] = classinfo
|
||||
|
||||
|
||||
|
||||
def add_const(name, decl, tp = ''):
|
||||
name = name.replace('.','::')
|
||||
namespace, classes, barename = split_decl_name(name)
|
||||
namespace = '::'.join(namespace)
|
||||
mapped_name = '_'.join(classes+[barename])
|
||||
ns = namespaces[namespace]
|
||||
if mapped_name in ns.consts:
|
||||
print("Generator error: constant %s (name=%s) already exists" \
|
||||
% (name, name))
|
||||
sys.exit(-1)
|
||||
ns.consts[name] = mapped_name
|
||||
|
||||
def add_enum(name, decl):
|
||||
name = name.replace('.', '::')
|
||||
mapped_name = normalize_class_name(name)
|
||||
# print(name)
|
||||
if mapped_name.endswith("<unnamed>"):
|
||||
mapped_name = None
|
||||
else:
|
||||
enums[name.replace(".", "::")] = mapped_name
|
||||
const_decls = decl[3]
|
||||
|
||||
if mapped_name:
|
||||
namespace, classes, name2 = split_decl_name(name)
|
||||
namespace = '::'.join(namespace)
|
||||
mapped_name = '_'.join(classes+[name2])
|
||||
# print(mapped_name)
|
||||
namespaces[namespace].enums[name] = (name.replace(".", "::"),mapped_name)
|
||||
|
||||
for decl in const_decls:
|
||||
name = decl[0]
|
||||
add_const(name.replace("const ", "", ).strip(), decl, "int")
|
||||
|
||||
|
||||
|
||||
def gen_tree(srcfiles):
|
||||
parser = hdr_parser.CppHeaderParser(generate_umat_decls=False, generate_gpumat_decls=False)
|
||||
|
||||
allowed_func_list = []
|
||||
|
||||
with open("funclist.csv", "r") as f:
|
||||
allowed_func_list = f.readlines()
|
||||
allowed_func_list = [x[:-1] for x in allowed_func_list]
|
||||
|
||||
|
||||
count = 0
|
||||
# step 1: scan the headers and build more descriptive maps of classes, consts, functions
|
||||
for hdr in srcfiles:
|
||||
decls = parser.parse(hdr)
|
||||
for ns in parser.namespaces:
|
||||
ns = ns.replace('.', '::')
|
||||
if ns not in namespaces:
|
||||
namespaces[ns] = NameSpaceInfo(ns)
|
||||
count += len(decls)
|
||||
if len(decls) == 0:
|
||||
continue
|
||||
if hdr.find('opencv2/') >= 0: #Avoid including the shadow files
|
||||
# code_include.write( '#include "{0}"\n'.format(hdr[hdr.rindex('opencv2/'):]) )
|
||||
pass
|
||||
for decl in decls:
|
||||
name = decl[0]
|
||||
if name.startswith("struct") or name.startswith("class"):
|
||||
# class/struct
|
||||
p = name.find(" ")
|
||||
stype = name[:p]
|
||||
name = name[p+1:].strip()
|
||||
add_class(stype, name, decl)
|
||||
elif name.startswith("const"):
|
||||
# constant
|
||||
assert(0)
|
||||
add_const(name.replace("const ", "").strip(), decl)
|
||||
elif name.startswith("enum"):
|
||||
# enum
|
||||
add_enum(name.rsplit(" ", 1)[1], decl)
|
||||
else:
|
||||
# function
|
||||
if decl[0] in allowed_func_list:
|
||||
add_func(decl)
|
||||
# step 1.5 check if all base classes exist
|
||||
# print(classes)
|
||||
for name, classinfo in classes.items():
|
||||
if classinfo.base:
|
||||
base = classinfo.base
|
||||
# print(base)
|
||||
if base not in classes:
|
||||
print("Generator error: unable to resolve base %s for %s"
|
||||
% (classinfo.base, classinfo.name))
|
||||
sys.exit(-1)
|
||||
base_instance = classes[base]
|
||||
classinfo.base = base
|
||||
classinfo.isalgorithm |= base_instance.isalgorithm # wrong processing of 'isalgorithm' flag:
|
||||
# doesn't work for trees(graphs) with depth > 2
|
||||
classes[name] = classinfo
|
||||
|
||||
# tree-based propagation of 'isalgorithm'
|
||||
processed = dict()
|
||||
def process_isalgorithm(classinfo):
|
||||
if classinfo.isalgorithm or classinfo in processed:
|
||||
return classinfo.isalgorithm
|
||||
res = False
|
||||
if classinfo.base:
|
||||
res = process_isalgorithm(classes[classinfo.base])
|
||||
#assert not (res == True or classinfo.isalgorithm is False), "Internal error: " + classinfo.name + " => " + classinfo.base
|
||||
classinfo.isalgorithm |= res
|
||||
res = classinfo.isalgorithm
|
||||
processed[classinfo] = True
|
||||
return res
|
||||
for name, classinfo in classes.items():
|
||||
process_isalgorithm(classinfo)
|
||||
|
||||
for name, ns in namespaces.items():
|
||||
if name.split('.')[-1] == '':
|
||||
continue
|
||||
ns.registered = []
|
||||
for name, cl in ns.classes.items():
|
||||
registered_types.append(get_template_arg(name))
|
||||
ns.registered.append(cl.mapped_name)
|
||||
nss, clss, bs = split_decl_name(name)
|
||||
type_paths[bs] = [name.replace("::", ".")]
|
||||
type_paths["::".join(clss+[bs])] = [name.replace("::", ".")]
|
||||
|
||||
|
||||
for e1,e2 in ns.enums.items():
|
||||
registered_types.append(get_template_arg(e2[0]))
|
||||
registered_types.append(get_template_arg(e2[0]).replace('::', '_')) #whyyy typedef
|
||||
ns.registered.append(e2[1])
|
||||
|
||||
ns.register_types = list(set(ns.register_types))
|
||||
ns.register_types = [tp for tp in ns.register_types if not registered_tp_search(tp) and not tp in ns.registered]
|
||||
for tp in ns.register_types:
|
||||
registered_types.append(get_template_arg(tp))
|
||||
ns.registered.append(get_template_arg(tp))
|
||||
default_valuesr = list(set(default_values))
|
||||
# registered_types = registered_types + ns.register_types
|
||||
return namespaces, default_valuesr
|
||||
@@ -0,0 +1,53 @@
|
||||
double*:NONCONVERT1
|
||||
vector<vector<Point2f>>:Array{Array{Point{Float32}, 1}, 1}
|
||||
TermCriteria:TermCriteria
|
||||
char:Char
|
||||
RotatedRect:RotatedRect
|
||||
Point2f:Point{Float32}
|
||||
Rect:Rect{Int32}
|
||||
vector<KeyPoint>:Array{KeyPoint, 1}
|
||||
double:Float64
|
||||
Point*:NONCONVERT2
|
||||
vector<Point>:Array{Point{Int32}, 1}
|
||||
vector<uchar>:Array{UInt8, 1}
|
||||
String:String
|
||||
string:String
|
||||
vector<Vec4f>:Array{Vec{Float32, 4}, 1}
|
||||
bool:Bool
|
||||
vector<Rect2d>:Array{Rect{Float64}, 1}
|
||||
LayerId:LayerId
|
||||
vector<int>:Array{Int32, 1}
|
||||
Rect*:NONCONVERT3
|
||||
MatShape:Array{Int32, 1}
|
||||
c_string:Cstring
|
||||
vector<RotatedRect>:Array{RotatedRect, 1}
|
||||
Net:Net
|
||||
size_t:size_t
|
||||
vector<double>:Array{Float64, 1}
|
||||
Point:Point{Int32}
|
||||
Mat:InputArray
|
||||
KeyPoint:KeyPoint
|
||||
Moments:Moments
|
||||
RNG*:NONCONVERT4
|
||||
int:Int64
|
||||
vector<float>:Array{Float32, 1}
|
||||
vector<Rect>:Array{Rect{Int32}, 1}
|
||||
Scalar:Scalar
|
||||
Point2f*:NONCONVERT5
|
||||
int*:NONCONVERT6
|
||||
vector<vector<Mat>>:Array{Array{InputArray, 1}, 1}
|
||||
vector<Mat>:Array{InputArray, 1}
|
||||
vector<String>:Array{String, 1}
|
||||
vector<string>:Array{String, 1}
|
||||
vector<Point2f>:Array{Point{Float32}, 1}
|
||||
Size:Size{Int32}
|
||||
vector<MatShape>:Array{Array{Int32, 1}, 1}
|
||||
float:Float64
|
||||
Ptr<float>:Ptr{Float32}
|
||||
vector<Vec6f>:Array{Vec{Float32, 6}, 1}
|
||||
Ptr<FeatureDetector>:Ptr{Feature2D}
|
||||
Point2d:Point{Float64}
|
||||
SolvePnPMethod:SolvePnPMethod
|
||||
CirclesGridFinderParameters:CirclesGridFinderParameters
|
||||
HandEyeCalibrationMethod:HandEyeCalibrationMethod
|
||||
long long:Int64
|
||||
@@ -0,0 +1,36 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
// Copyright (C) 2020 by Archit Rungta
|
||||
|
||||
#ifndef OPENCV_JULIA_HPP
|
||||
#define OPENCV_JULIA_HPP
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
|
||||
/**
|
||||
@defgroup julia Julia bindings for OpenCV
|
||||
|
||||
Julia (https://julialang.org) is a programming language for scientific community with growing popularity.
|
||||
These are bindings for a subset of OpenCV functionality, based on libcxxwrap-julia and CxxWrap packages.
|
||||
|
||||
For installation instructions, see README.md in this module or OpenCV wiki (https://github.com/opencv/opencv/wiki)
|
||||
*/
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace julia
|
||||
{
|
||||
|
||||
//! @addtogroup julia
|
||||
//! @{
|
||||
|
||||
// initializes Julia bindings module
|
||||
CV_WRAP void initJulia(int argc, char **argv);
|
||||
|
||||
//! @} julia
|
||||
|
||||
} // namespace julia
|
||||
} // namespace cv
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
# This file is machine-generated - editing it directly is not advised
|
||||
|
||||
[[Base64]]
|
||||
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
|
||||
[[CxxWrap]]
|
||||
deps = ["Libdl", "MacroTools", "libcxxwrap_julia_jll"]
|
||||
git-tree-sha1 = "762359626941f45b21238eb373a0bcedf6b61dd7"
|
||||
uuid = "1f15a43c-97ca-5a2a-ae31-89f07a497df4"
|
||||
version = "0.11.0"
|
||||
|
||||
[[Dates]]
|
||||
deps = ["Printf"]
|
||||
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
|
||||
[[Distributed]]
|
||||
deps = ["Random", "Serialization", "Sockets"]
|
||||
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
|
||||
|
||||
[[InteractiveUtils]]
|
||||
deps = ["Markdown"]
|
||||
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
|
||||
|
||||
[[LibGit2]]
|
||||
deps = ["Printf"]
|
||||
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
|
||||
|
||||
[[Libdl]]
|
||||
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
|
||||
|
||||
[[Logging]]
|
||||
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
||||
|
||||
[[MacroTools]]
|
||||
deps = ["Markdown", "Random"]
|
||||
git-tree-sha1 = "f7d2e3f654af75f01ec49be82c231c382214223a"
|
||||
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
|
||||
version = "0.5.5"
|
||||
|
||||
[[Markdown]]
|
||||
deps = ["Base64"]
|
||||
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
|
||||
|
||||
[[Pkg]]
|
||||
deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
|
||||
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
||||
|
||||
[[Printf]]
|
||||
deps = ["Unicode"]
|
||||
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
|
||||
|
||||
[[REPL]]
|
||||
deps = ["InteractiveUtils", "Markdown", "Sockets"]
|
||||
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
|
||||
|
||||
[[Random]]
|
||||
deps = ["Serialization"]
|
||||
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||
|
||||
[[SHA]]
|
||||
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
|
||||
|
||||
[[Serialization]]
|
||||
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
|
||||
|
||||
[[Sockets]]
|
||||
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
|
||||
|
||||
[[Test]]
|
||||
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
|
||||
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
||||
[[UUIDs]]
|
||||
deps = ["Random", "SHA"]
|
||||
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||
|
||||
[[Unicode]]
|
||||
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
|
||||
|
||||
[[libcxxwrap_julia_jll]]
|
||||
deps = ["Libdl", "Pkg"]
|
||||
git-tree-sha1 = "1b2520ea0c1d5cbc12e8a97c15427133d726f743"
|
||||
uuid = "3eaa8342-bff7-56a5-9981-c04077f7cee7"
|
||||
version = "0.8.0+0"
|
||||
@@ -0,0 +1,8 @@
|
||||
name = "OpenCV"
|
||||
uuid = "c5c8e1f8-82bd-4b4b-a82d-991e5c6b68de"
|
||||
authors = ["Archit Rungta <architrungta120@gmail.com>"]
|
||||
version = "0.1.0"
|
||||
|
||||
[deps]
|
||||
CxxWrap = "1f15a43c-97ca-5a2a-ae31-89f07a497df4"
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
@@ -0,0 +1,12 @@
|
||||
# Not using Artifacts for now
|
||||
# This is a simple script to finally register the OpenCV package
|
||||
# with the local package manager.
|
||||
|
||||
using Pkg
|
||||
|
||||
print(ARGS)
|
||||
if size(ARGS) == 2
|
||||
Pkg.activate(ARGS[2])
|
||||
end
|
||||
|
||||
Pkg.develop(PackageSpec(path=ARGS[1]))
|
||||
@@ -0,0 +1,20 @@
|
||||
using OpenCV
|
||||
|
||||
const cv = OpenCV
|
||||
|
||||
|
||||
# chess1.png is at https://raw.githubusercontent.com/opencv/opencv_extra/master/testdata/cv/cameracalibration/chess1.png
|
||||
img = cv.imread("chess1.png",cv.IMREAD_GRAYSCALE)
|
||||
climg = cv.cvtColor(img, cv.COLOR_GRAY2BGR)
|
||||
|
||||
# Find the chess board corners
|
||||
ret, corners = cv.findChessboardCorners(img, cv.Size{Int32}(7,5))
|
||||
|
||||
# If found, add object points, image points (after refining them)
|
||||
if ret
|
||||
climg = cv.drawChessboardCorners(climg, cv.Size{Int32}(7,5), corners,ret)
|
||||
cv.imshow("img",climg)
|
||||
cv.waitKey(Int32(0))
|
||||
|
||||
cv.destroyAllWindows()
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
using OpenCV
|
||||
|
||||
function detect(img::OpenCV.InputArray, cascade)
|
||||
rects = OpenCV.detectMultiScale(cascade, img, scaleFactor=1.3, minNeighbors=Int32(4), minSize=OpenCV.Size{Int32}(30, 30), flags=OpenCV.CASCADE_SCALE_IMAGE)
|
||||
processed_rects = []
|
||||
for rect in rects
|
||||
push!(processed_rects, (rect.x, rect.y, rect.width+rect.x, rect.height+rect.y))
|
||||
end
|
||||
return processed_rects
|
||||
end
|
||||
|
||||
function draw_rects(img, rects, color)
|
||||
for x in rects
|
||||
OpenCV.rectangle(img, OpenCV.Point{Int32}(x[1], x[2]), OpenCV.Point{Int32}(x[3], x[4]), color, thickness = Int32(2))
|
||||
end
|
||||
end
|
||||
|
||||
cap = OpenCV.VideoCapture(Int32(0))
|
||||
|
||||
# Replace the paths for the classifiers before running
|
||||
|
||||
cascade = OpenCV.CascadeClassifier("haarcascade_frontalface_alt.xml")
|
||||
nested = OpenCV.CascadeClassifier("haarcascade_eye.xml")
|
||||
|
||||
OpenCV.namedWindow("facedetect")
|
||||
|
||||
while true
|
||||
ret, img = OpenCV.read(cap)
|
||||
if ret==false
|
||||
print("Webcam stopped")
|
||||
break
|
||||
end
|
||||
gray = OpenCV.cvtColor(img, OpenCV.COLOR_BGR2GRAY)
|
||||
gray = OpenCV.equalizeHist(gray)
|
||||
|
||||
rects = detect(gray, cascade)
|
||||
vis = copy(img)
|
||||
draw_rects(vis, rects, (0.0, 255.0, 0.0))
|
||||
|
||||
if ~OpenCV.empty(nested)
|
||||
for x in rects
|
||||
roi = view(gray, :, Int(x[1]):Int(x[3]), Int(x[2]):Int(x[4]))
|
||||
subrects = detect(roi, nested)
|
||||
draw_view = view(vis, :, Int(x[1]):Int(x[3]), Int(x[2]):Int(x[4]))
|
||||
draw_rects(draw_view, subrects, (255.0, 0.0, 0.0))
|
||||
end
|
||||
end
|
||||
|
||||
OpenCV.imshow("facedetect", vis)
|
||||
if OpenCV.waitKey(Int32(5))==27
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
OpenCV.release(cap)
|
||||
|
||||
OpenCV.destroyAllWindows()
|
||||
|
||||
print("Stopped")
|
||||
@@ -0,0 +1,39 @@
|
||||
using OpenCV
|
||||
const cv = OpenCV
|
||||
size0 = Int32(300)
|
||||
# take the model from https://github.com/opencv/opencv_extra/tree/master/testdata/dnn
|
||||
net = cv.dnn_DetectionModel("opencv_face_detector.pbtxt", "opencv_face_detector_uint8.pb")
|
||||
|
||||
cv.dnn.setPreferableTarget(net, cv.dnn.DNN_TARGET_CPU)
|
||||
cv.dnn.setInputMean(net, (104, 177, 123))
|
||||
cv.dnn.setInputScale(net, 1.)
|
||||
cv.dnn.setInputSize(net, size0, size0)
|
||||
|
||||
cap = cv.VideoCapture(Int32(0))
|
||||
while true
|
||||
ok, frame = cv.read(cap)
|
||||
if ok == false
|
||||
break
|
||||
end
|
||||
classIds, confidences, boxes = cv.dnn.detect(net, frame, confThreshold=Float32(0.5))
|
||||
|
||||
for i in 1:size(boxes,1)
|
||||
confidence = confidences[i]
|
||||
x0 = Int32(boxes[i].x)
|
||||
y0 = Int32(boxes[i].y)
|
||||
x1 = Int32(boxes[i].x+boxes[i].width)
|
||||
y1 = Int32(boxes[i].y+boxes[i].height)
|
||||
cv.rectangle(frame, cv.Point{Int32}(x0, y0), cv.Point{Int32}(x1, y1), (100, 255, 100); thickness = Int32(5))
|
||||
label = "face: " * string(confidence)
|
||||
lsize, bl = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, Int32(1))
|
||||
cv.rectangle(frame, cv.Point{Int32}(x0,y0), cv.Point{Int32}(x0+lsize.width, y0+lsize.height+bl), (100,255,100); thickness = Int32(-1))
|
||||
cv.putText(frame, label, cv.Point{Int32}(x0, y0 + lsize.height),
|
||||
cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0); thickness = Int32(1), lineType = cv.LINE_AA)
|
||||
end
|
||||
|
||||
|
||||
cv.imshow("detections", frame)
|
||||
if cv.waitKey(Int32(30)) >= 0
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
using OpenCV
|
||||
const cv = OpenCV
|
||||
|
||||
img = rand(UInt8, 3, 500, 500)
|
||||
filter = rand(Float32, 1, 5, 5)/25
|
||||
|
||||
out = OpenCV.filter2D(img, Int32(-1), filter)
|
||||
|
||||
cv.namedWindow("orig")
|
||||
cv.namedWindow("out")
|
||||
|
||||
cv.imshow("orig", img)
|
||||
cv.imshow("out", out)
|
||||
|
||||
cv.waitKey(Int32(0))
|
||||
@@ -0,0 +1,29 @@
|
||||
using OpenCV
|
||||
|
||||
println("")
|
||||
println("This is a simple exmample demonstrating the use of SimpleBlobDetector")
|
||||
println("")
|
||||
print("Path to image: ")
|
||||
img_dir = readline()
|
||||
|
||||
img = OpenCV.imread(img_dir)
|
||||
img_gray = OpenCV.cvtColor(img, OpenCV.COLOR_BGR2GRAY)
|
||||
|
||||
OpenCV.namedWindow("Img - Color")
|
||||
OpenCV.namedWindow("Img - Gray")
|
||||
|
||||
|
||||
OpenCV.imshow("Img - Color", img)
|
||||
OpenCV.imshow("Img - Gray", img_gray)
|
||||
|
||||
OpenCV.waitKey(Int32(0))
|
||||
|
||||
OpenCV.destroyAllWindows()
|
||||
|
||||
detector = OpenCV.SimpleBlobDetector_create()
|
||||
kps = OpenCV.detect(detector, img_gray)
|
||||
|
||||
println("Number of keypoints: ", size(kps))
|
||||
for kp in kps
|
||||
println(kp.pt, "\t", kp.size)
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
// Copyright (C) 2020 by Archit Rungta
|
||||
|
||||
// Needed to prevent documentation warning
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace julia
|
||||
{
|
||||
void initJulia(int, char **) {}
|
||||
} // namespace julia
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,28 @@
|
||||
set(JULIA_TEST_PROXY ${CMAKE_CURRENT_BINARY_DIR}/test.proxy)
|
||||
file(REMOVE ${JULIA_TEST_PROXY})
|
||||
|
||||
# generate
|
||||
# call the python executable to generate the julia gateways
|
||||
add_custom_command(
|
||||
OUTPUT ${JULIA_TEST_PROXY}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/testsuite.jl ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/test_feature2d.jl ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/test_objdetect.jl ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/test_imgproc.jl ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/test_mat.jl ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/test_dnn.jl ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${JULIA_TEST_PROXY}
|
||||
COMMENT "Building Julia tests"
|
||||
)
|
||||
|
||||
# targets# opencv_julia_sources --> opencv_julia
|
||||
|
||||
add_custom_target(opencv_test_julia ALL DEPENDS ${JULIA_TEST_PROXY})
|
||||
add_dependencies(opencv_test_julia ${the_module})
|
||||
|
||||
message(STATUS "Placing Julia tests in ${CMAKE_CURRENT_BINARY_DIR}")
|
||||
# run the julia test suite
|
||||
add_test(NAME opencv_test_julia
|
||||
COMMAND ${Julia_EXECUTABLE} "testsuite.jl"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
function IOU(boxA, boxB)
|
||||
xA = max(boxA[1], boxB[1])
|
||||
yA = max(boxA[2], boxB[2])
|
||||
xB = min(boxA[3], boxB[3])
|
||||
yB = min(boxA[4], boxB[4])
|
||||
interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)
|
||||
boxAArea = (boxA[3] - boxA[1] + 1) * (boxA[4] - boxA[2] + 1)
|
||||
boxBArea = (boxB[3] - boxB[1] + 1) * (boxB[4] - boxB[2] + 1)
|
||||
iou = interArea / float(boxAArea + boxBArea - interArea)
|
||||
return iou
|
||||
end
|
||||
|
||||
const cv = OpenCV
|
||||
net = cv.dnn.DetectionModel(joinpath(ENV["OPENCV_TEST_DATA_PATH"], "dnn", "opencv_face_detector.pbtxt"),joinpath(ENV["OPENCV_TEST_DATA_PATH"], "dnn", "opencv_face_detector_uint8.pb"))
|
||||
size0 = 300
|
||||
|
||||
cv.dnn.setPreferableTarget(net, cv.dnn.DNN_TARGET_CPU)
|
||||
cv.dnn.setInputMean(net, (104, 177, 123))
|
||||
cv.dnn.setInputScale(net, 1.)
|
||||
cv.dnn.setInputSize(net, size0, size0)
|
||||
|
||||
|
||||
img = OpenCV.imread(joinpath(test_dir, "cascadeandhog", "images", "mona-lisa.png"))
|
||||
|
||||
classIds, confidences, boxes = cv.dnn.detect(net, img, confThreshold=0.5)
|
||||
|
||||
box = (boxes[1].x, boxes[1].y, boxes[1].x+boxes[1].width, boxes[1].y+boxes[1].height)
|
||||
expected_rect = (185,101,129+185,169+101)
|
||||
|
||||
@test IOU(box, expected_rect) > 0.8
|
||||
|
||||
print("dnn test passed\n")
|
||||
@@ -0,0 +1,23 @@
|
||||
# test simple blob detector
|
||||
img_gray = OpenCV.imread(joinpath(test_dir, "shared", "pic1.png"), OpenCV.IMREAD_GRAYSCALE)
|
||||
|
||||
detector = OpenCV.SimpleBlobDetector_create()
|
||||
|
||||
# Compare centers of keypoints and se how many of them match,
|
||||
kps = OpenCV.detect(detector, img_gray)
|
||||
|
||||
kps_expect = [OpenCV.Point{Float32}(174.9114f0, 227.75146f0),OpenCV.Point{Float32}(106.925545f0, 179.5765f0)]
|
||||
for kp in kps
|
||||
closest_match = 100000
|
||||
for kpe in kps_expect
|
||||
dx = kpe.x - kp.pt.x
|
||||
dy = kpe.y - kp.pt.y
|
||||
if sqrt(dx*dx+dy*dy) < closest_match
|
||||
closest_match = sqrt(dx*dx+dy*dy)
|
||||
end
|
||||
end
|
||||
|
||||
@test closest_match < 10
|
||||
end
|
||||
|
||||
println("feature2d test passed")
|
||||
@@ -0,0 +1,28 @@
|
||||
# Create a random image
|
||||
img = rand(UInt8 , 3, 500, 500)
|
||||
|
||||
# Test input as AbstractArray and cvtColor
|
||||
img_gray = OpenCV.cvtColor(img, OpenCV.COLOR_RGB2GRAY)
|
||||
|
||||
@test size(img_gray, 1) == 1 && size(img_gray, 2) == size(img, 2) && size(img_gray, 3) == size(img, 3)
|
||||
|
||||
# Exception test
|
||||
try
|
||||
# This should throw an error
|
||||
OpenCV.cvtColor(img_gray, OpenCV.COLOR_RGB2GRAY)
|
||||
exit(1)
|
||||
catch
|
||||
# Error caught so we can continue
|
||||
end
|
||||
|
||||
ve = view(img, :,200:300, 200:300)
|
||||
|
||||
# Auto-conversion from-to OpenCV types
|
||||
ve_gray = OpenCV.cvtColor(ve, OpenCV.COLOR_RGB2GRAY)
|
||||
|
||||
# Shape check
|
||||
@test size(ve_gray)[1] == 1 && size(img_gray)[1] == 1
|
||||
|
||||
|
||||
|
||||
print("imgproc test passed\n")
|
||||
@@ -0,0 +1,118 @@
|
||||
# This file is adapted from test/abstractarray.jl from Julia.
|
||||
|
||||
# This file is a part of Julia. License is MIT: https://julialang.org/license
|
||||
|
||||
A_abs = rand(5,4,3)
|
||||
A = OpenCV.Mat(A_abs)
|
||||
@testset "Bounds checking" begin
|
||||
@test checkbounds(Bool, A, 1, 1, 1) == true
|
||||
@test checkbounds(Bool, A, 5, 4, 3) == true
|
||||
@test checkbounds(Bool, A, 0, 1, 1) == false
|
||||
@test checkbounds(Bool, A, 1, 0, 1) == false
|
||||
@test checkbounds(Bool, A, 1, 1, 0) == false
|
||||
@test checkbounds(Bool, A, 6, 4, 3) == false
|
||||
@test checkbounds(Bool, A, 5, 5, 3) == false
|
||||
@test checkbounds(Bool, A, 5, 4, 4) == false
|
||||
@test checkbounds(Bool, A, 1) == true # linear indexing
|
||||
@test checkbounds(Bool, A, 60) == true
|
||||
@test checkbounds(Bool, A, 61) == false
|
||||
@test checkbounds(Bool, A, 2, 2, 2, 1) == true # extra indices
|
||||
@test checkbounds(Bool, A, 2, 2, 2, 2) == false
|
||||
@test checkbounds(Bool, A, 1, 1) == false
|
||||
@test checkbounds(Bool, A, 1, 12) == false
|
||||
@test checkbounds(Bool, A, 5, 12) == false
|
||||
@test checkbounds(Bool, A, 1, 13) == false
|
||||
@test checkbounds(Bool, A, 6, 12) == false
|
||||
end
|
||||
|
||||
@testset "single CartesianIndex" begin
|
||||
@test checkbounds(Bool, A, CartesianIndex((1, 1, 1))) == true
|
||||
@test checkbounds(Bool, A, CartesianIndex((5, 4, 3))) == true
|
||||
@test checkbounds(Bool, A, CartesianIndex((0, 1, 1))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((1, 0, 1))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((1, 1, 0))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((6, 4, 3))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((5, 5, 3))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((5, 4, 4))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((1,))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((60,))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((61,))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((2, 2, 2, 1,))) == true
|
||||
@test checkbounds(Bool, A, CartesianIndex((2, 2, 2, 2,))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((1, 1,))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((1, 12,))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((5, 12,))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((1, 13,))) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((6, 12,))) == false
|
||||
end
|
||||
|
||||
@testset "mix of CartesianIndex and Int" begin
|
||||
@test checkbounds(Bool, A, CartesianIndex((1,)), 1, CartesianIndex((1,))) == true
|
||||
@test checkbounds(Bool, A, CartesianIndex((5, 4)), 3) == true
|
||||
@test checkbounds(Bool, A, CartesianIndex((0, 1)), 1) == false
|
||||
@test checkbounds(Bool, A, 1, CartesianIndex((0, 1))) == false
|
||||
@test checkbounds(Bool, A, 1, 1, CartesianIndex((0,))) == false
|
||||
@test checkbounds(Bool, A, 6, CartesianIndex((4, 3))) == false
|
||||
@test checkbounds(Bool, A, 5, CartesianIndex((5,)), 3) == false
|
||||
@test checkbounds(Bool, A, CartesianIndex((5,)), CartesianIndex((4,)), CartesianIndex((4,))) == false
|
||||
end
|
||||
|
||||
@testset "vector indices" begin
|
||||
@test checkbounds(Bool, A, 1:5, 1:4, 1:3) == true
|
||||
@test checkbounds(Bool, A, 0:5, 1:4, 1:3) == false
|
||||
@test checkbounds(Bool, A, 1:5, 0:4, 1:3) == false
|
||||
@test checkbounds(Bool, A, 1:5, 1:4, 0:3) == false
|
||||
@test checkbounds(Bool, A, 1:6, 1:4, 1:3) == false
|
||||
@test checkbounds(Bool, A, 1:5, 1:5, 1:3) == false
|
||||
@test checkbounds(Bool, A, 1:5, 1:4, 1:4) == false
|
||||
@test checkbounds(Bool, A, 1:60) == true
|
||||
@test checkbounds(Bool, A, 1:61) == false
|
||||
@test checkbounds(Bool, A, 2, 2, 2, 1:1) == true # extra indices
|
||||
@test checkbounds(Bool, A, 2, 2, 2, 1:2) == false
|
||||
@test checkbounds(Bool, A, 1:5, 1:4) == false
|
||||
@test checkbounds(Bool, A, 1:5, 1:12) == false
|
||||
@test checkbounds(Bool, A, 1:5, 1:13) == false
|
||||
@test checkbounds(Bool, A, 1:6, 1:12) == false
|
||||
end
|
||||
|
||||
@testset "logical" begin
|
||||
@test checkbounds(Bool, A, trues(5), trues(4), trues(3)) == true
|
||||
@test checkbounds(Bool, A, trues(6), trues(4), trues(3)) == false
|
||||
@test checkbounds(Bool, A, trues(5), trues(5), trues(3)) == false
|
||||
@test checkbounds(Bool, A, trues(5), trues(4), trues(4)) == false
|
||||
@test checkbounds(Bool, A, trues(60)) == true
|
||||
@test checkbounds(Bool, A, trues(61)) == false
|
||||
@test checkbounds(Bool, A, 2, 2, 2, trues(1)) == true # extra indices
|
||||
@test checkbounds(Bool, A, 2, 2, 2, trues(2)) == false
|
||||
@test checkbounds(Bool, A, trues(5), trues(12)) == false
|
||||
@test checkbounds(Bool, A, trues(5), trues(13)) == false
|
||||
@test checkbounds(Bool, A, trues(6), trues(12)) == false
|
||||
@test checkbounds(Bool, A, trues(5, 4, 3)) == true
|
||||
@test checkbounds(Bool, A, trues(5, 4, 2)) == false
|
||||
@test checkbounds(Bool, A, trues(5, 12)) == false
|
||||
@test checkbounds(Bool, A, trues(1, 5), trues(1, 4, 1), trues(1, 1, 3)) == false
|
||||
@test checkbounds(Bool, A, trues(1, 5), trues(1, 4, 1), trues(1, 1, 2)) == false
|
||||
@test checkbounds(Bool, A, trues(1, 5), trues(1, 5, 1), trues(1, 1, 3)) == false
|
||||
@test checkbounds(Bool, A, trues(1, 5), :, 2) == false
|
||||
end
|
||||
|
||||
@testset "array of CartesianIndex" begin
|
||||
@test checkbounds(Bool, A, [CartesianIndex((1, 1, 1))]) == true
|
||||
@test checkbounds(Bool, A, [CartesianIndex((5, 4, 3))]) == true
|
||||
@test checkbounds(Bool, A, [CartesianIndex((0, 1, 1))]) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((1, 0, 1))]) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((1, 1, 0))]) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((6, 4, 3))]) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((5, 5, 3))]) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((5, 4, 4))]) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((1, 1))], 1) == true
|
||||
@test checkbounds(Bool, A, [CartesianIndex((5, 4))], 3) == true
|
||||
@test checkbounds(Bool, A, [CartesianIndex((0, 1))], 1) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((1, 0))], 1) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((1, 1))], 0) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((6, 4))], 3) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((5, 5))], 3) == false
|
||||
@test checkbounds(Bool, A, [CartesianIndex((5, 4))], 4) == false
|
||||
end
|
||||
|
||||
println("OpenCV.Mat tests passed")
|
||||
@@ -0,0 +1,29 @@
|
||||
function detect(img::OpenCV.InputArray, cascade)
|
||||
rects = OpenCV.detectMultiScale(cascade, img)
|
||||
return (rects[1].x, rects[1].y, rects[1].width+rects[1].x, rects[1].height+rects[1].y)
|
||||
end
|
||||
|
||||
|
||||
function IOU(boxA, boxB)
|
||||
xA = max(boxA[1], boxB[1])
|
||||
yA = max(boxA[2], boxB[2])
|
||||
xB = min(boxA[3], boxB[3])
|
||||
yB = min(boxA[4], boxB[4])
|
||||
interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)
|
||||
boxAArea = (boxA[3] - boxA[1] + 1) * (boxA[4] - boxA[2] + 1)
|
||||
boxBArea = (boxB[3] - boxB[1] + 1) * (boxB[4] - boxB[2] + 1)
|
||||
iou = interArea / float(boxAArea + boxBArea - interArea)
|
||||
return iou
|
||||
end
|
||||
|
||||
cascade = OpenCV.CascadeClassifier(joinpath(test_dir, "cascadeandhog", "cascades", "haarcascade_frontalface_alt.xml"))
|
||||
|
||||
img = OpenCV.imread(joinpath(test_dir, "cascadeandhog", "images", "mona-lisa.png"), OpenCV.IMREAD_GRAYSCALE)
|
||||
|
||||
rect = detect(img, cascade)
|
||||
|
||||
expected_rect = (164,119,306,261)
|
||||
|
||||
@test IOU(rect, expected_rect) > 0.95
|
||||
|
||||
print("objdetect test passed\n")
|
||||
@@ -0,0 +1,15 @@
|
||||
print("Loading module\n")
|
||||
|
||||
using OpenCV
|
||||
using Test
|
||||
|
||||
|
||||
test_dir = joinpath(ENV["OPENCV_TEST_DATA_PATH"], "cv")
|
||||
|
||||
include("test_mat.jl")
|
||||
include("test_feature2d.jl")
|
||||
include("test_imgproc.jl")
|
||||
include("test_objdetect.jl")
|
||||
include("test_dnn.jl")
|
||||
|
||||
exit(0)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
@@ -0,0 +1,150 @@
|
||||
Introduction to Julia OpenCV Binding {#tutorial_julia}
|
||||
=======================================
|
||||
|
||||
OpenCV
|
||||
------
|
||||
|
||||
OpenCV (Open Source Computer Vision Library) is an open source computer vision and machine learning software library. OpenCV was built to provide a common infrastructure for computer vision applications and to accelerate the use of machine perception in the commercial products. Distributed under permissive license, OpenCV makes it easy for businesses to utilize and modify the code.
|
||||
|
||||
The library has more than 2500 optimized algorithms, which includes a comprehensive set of both classic and state-of-the-art computer vision and machine learning algorithms. These algorithms can be used to detect and recognize faces, identify objects, classify human actions in videos, track camera movements, track moving objects, extract 3D models of objects, produce 3D point clouds from stereo cameras, stitch images together to produce a high resolution image of an entire scene, find similar images from an image database, remove red eyes from images taken using flash, follow eye movements, recognize scenery and establish markers to overlay it with augmented reality, etc. OpenCV has more than 47 thousand people of user community and estimated number of downloads exceeding 18 million. The library is used extensively in companies, research groups and by governmental bodies.
|
||||
|
||||
Julia
|
||||
-------------
|
||||
Julia is a high-performance, high-level, and dynamic programming language that specializes in tasks relateted numerical, and scientefic computing. However, It can also be used for general programming with GUI and web programming. Julia can be considered as a combination of rapid interpreter style prototyping capability of Python with the raw speed of C because of its special "just-ahead-of-time" compilation.
|
||||
|
||||
Inspite of all this, Julia severely lacks in a lot of traditional computer vision and image processing algorithms. This also hampers the usage of Julia in any pipeline that requires computer vision. The OpenCV bindings for Julia aims to solve this problem.
|
||||
|
||||
The Bindings
|
||||
-----------------------
|
||||
The OpenCV bindings for Julia are created automatically using Python scripts at configure time and then installed with the Julia package manager on the system. These bindings cover most of the important functionality present in the core, imgproc, imgcodecs, highgui, videio, calib3d, and dnn modules. These bindings depend on CxxWrap.jl and the process for usage and compilation is explained in detail below. The Bindings have been tested on Ubuntu and Mac. Windows might work but is not officially tested and supported right now.
|
||||
|
||||
The generation process and the method by which the binding works are similar to the Python bindings. The only major difference is that CxxWrap.jl does not support optional arguments. As a consequence, it's necessary to define the optional arguments in Julia code which adds a lot of additional complexity.
|
||||
|
||||
How To Install The Bindings
|
||||
-----------------------
|
||||
The easiest and recommended way to install the bindings is using Julia's inbuilt package manager. OpenCV is available as a registered package for Julia and is supported on all major platforms and architectures. The following steps checked for correctness on Julia v1.6.1
|
||||
|
||||
TO install start the Julia REPL. Hit `]` and then type `add OpenCV`.
|
||||
|
||||
```bash
|
||||
$ julia
|
||||
...
|
||||
julia> ]
|
||||
pkg> add OpenCV
|
||||
```
|
||||
|
||||
How To Build The Bindings
|
||||
-----------------------
|
||||
Before you can build the bindings, make sure that you know how to build OpenCV with all the functionality you require and the contrib modules except the Julia Bindings. As mentioned before, the Julia bindings are not officially supported on Windows right now and a better alternative would be to try it with WSL/WSL2.
|
||||
|
||||
The pre-requisites for the Julia Bindings are:
|
||||
- [CxxWrap.jl](https://github.com/JuliaInterop/CxxWrap.jl)
|
||||
- [libcxxwrap-julia](https://github.com/JuliaInterop/libcxxwrap-julia)
|
||||
- Python
|
||||
- Julia
|
||||
|
||||
It is recommended to use Julia 1.4+ and the latest versions of CxxWrap.jl and libcxxwrap-julia.
|
||||
|
||||
The first step is to build [libcxxwrap-julia](https://github.com/JuliaInterop/libcxxwrap-julia) from source. The link explains how to do that. You must also setup the override in `/.julia/artifacts/Overrides.toml` as explained at the link.
|
||||
|
||||
Once that's done you start a Julia terminal and Just start the REPL. Hit `]` and then type `add CxxWrap`.
|
||||
|
||||
```bash
|
||||
$ julia
|
||||
...
|
||||
julia> ]
|
||||
pkg> add CxxWrap
|
||||
```
|
||||
|
||||
This should install CxxWrap. At this step you should also check whether your libcxxwrap-julia override was set correctly or not. You can do this by checking the value of `CxxWrap.CxxWrapCore.prefix_path()` The output should show the build directory of libcxxwrap-julia
|
||||
|
||||
```bash
|
||||
julia> using CxxWrap
|
||||
|
||||
julia> CxxWrap.CxxWrapCore.prefix_path()
|
||||
"$HOME/src/libcxxwrap-julia-build"
|
||||
```
|
||||
|
||||
|
||||
|
||||
You're now ready to build the Julia bindings. Just add the `-DWITH_JULIA=ON` to your cmake configure command and Julia bindings will be built. For example:
|
||||
|
||||
`cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules -DWITH_JULIA=ON ../opencv`
|
||||
|
||||
This command assumes that the parent directory has `opencv` and `opencv_contrib` folders containing the repositories. If cmake complains about being unable to find the Julia executable add `Julia_EXECUTABLE` variable like:
|
||||
|
||||
`cmake -DWITH_JULIA=ON -DJulia_EXECUTABLE=$HOME/julia-1.4.1/bin/julia ...`
|
||||
|
||||
By default, the installed package will stay in the same directory as your build directory. You can change this using the cmake variable `JULIA_PKG_INSTALL_PATH`
|
||||
|
||||
Finally, type `sudo make install` to have the binding registered with the Julia package manager.
|
||||
|
||||
Sample Usage
|
||||
-----------------------
|
||||
|
||||
In order to use the bindings, simply type
|
||||
|
||||
```
|
||||
$ julia
|
||||
...
|
||||
julia> using OpenCV
|
||||
```
|
||||
|
||||
Note that this works only if you called `make install`. To run the wrapper package without making the installation target you must first set the environment variable `JULIA_LOAD_PATH` to the directory containing the OpenCV package. For example if in the build directory
|
||||
|
||||
```
|
||||
$ export JULIA_LOAD_PATH=$PWD/OpenCV
|
||||
$ julia
|
||||
...
|
||||
julia> using OpenCV
|
||||
```
|
||||
|
||||
The Julia package does not export any symbols so all functions/structs/constants must be prefixed with OpenCV
|
||||
|
||||
```
|
||||
using OpenCV
|
||||
const cv = OpenCV
|
||||
img = cv.imread('cameraman.tif');
|
||||
|
||||
cv.imshow("window name", img)
|
||||
|
||||
cv.waitKey(Int32(0))
|
||||
```
|
||||
|
||||
Finally, because Julia does not support OOP paradigm some changes had to be made. To access functions like `obj.function(ARGS)` you should instead use `function(obj, ARGS)`. The below example of reading frames from a VideoCapture should make it more clear.
|
||||
|
||||
```
|
||||
cap = OpenCV.VideoCapture(Int32(0))
|
||||
ret, img = OpenCV.read(cap)
|
||||
```
|
||||
|
||||
Instead of calling `cap.read()`, we called `OpenCV.read(cap)`
|
||||
|
||||
Another change is that all integer and float constants might need to prefixed with appropriate type constructor. This is needed because OpenCV functions accept 32-bit integers/floats but integer and float constants in Julia are sized based on the whether Julia is running in 64bit or 32bit mode.
|
||||
|
||||
Running The Included Sample
|
||||
-----------------------
|
||||
|
||||
|
||||
Let's try running one of the included samples now. In this tutorial we will see how to run the `face_detect_dnn.jl` sample. This samples uses a deep neural network to detect faces in the video stream by webcam. The screenshot is from a slightly edited version that reads an image instead. First navigate to `opencv_contrib/modules/julia/samples/`. Next, you need two files "opencv_face_detector.pbtxt" and "opencv_face_detector_uint8.pb" from [link](https://github.com/opencv/opencv_extra/tree/master/testdata/dnn);simply download and place them in the same directory as `face_detect_dnn.jl`. Now you're ready to run. Start a terminal and simply type:
|
||||
|
||||
```
|
||||
> julia face_detect_dnn.jl
|
||||
```
|
||||
|
||||

|
||||
|
||||
You should now see a working example of face detection using deep neural networks.
|
||||
|
||||
Note: The sample might take some time to load.
|
||||
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
Below is the list of contributors of OpenCV.jl bindings and tutorials.
|
||||
|
||||
- Archit Rungta (Author of the initial version and GSoC student, Indian Institute of Technology, Kharagpur)
|
||||
- Sayan Sinha (GSoC mentor, Indian Institute of Technology, Kharagpur)
|
||||
- Mosè Giordano (GSoC Phase 2 mentor)
|
||||
- Vadim Pisarevsky (GSoC mentor)
|
||||
Reference in New Issue
Block a user