add part of opencv

This commit is contained in:
Tang1705
2020-01-27 20:20:56 +08:00
parent 0c4ac1d8bb
commit a71fa47620
6518 changed files with 3122580 additions and 0 deletions

View File

@@ -0,0 +1,182 @@
# ----------------------------------------------------------------------------
# CMake file for js support
# ----------------------------------------------------------------------------
set(the_description "The js bindings")
if(NOT BUILD_opencv_js) # should be enabled explicitly (by build_js.py script)
ocv_module_disable(js)
endif()
set(OPENCV_JS "opencv.js")
find_path(EMSCRIPTEN_INCLUDE_DIR
emscripten/bind.h
PATHS
ENV EMSCRIPTEN_ROOT
PATH_SUFFIXES system/include include
DOC "Location of Emscripten SDK")
if(NOT EMSCRIPTEN_INCLUDE_DIR OR NOT PYTHON_DEFAULT_AVAILABLE)
set(DISABLE_MSG "Module 'js' disabled because the following dependencies are not found:")
if(NOT EMSCRIPTEN_INCLUDE_DIR)
set(DISABLE_MSG "${DISABLE_MSG} Emscripten")
endif()
if(NOT PYTHON_DEFAULT_AVAILABLE)
set(DISABLE_MSG "${DISABLE_MSG} Python")
endif()
message(STATUS ${DISABLE_MSG})
ocv_module_disable(js)
endif()
ocv_add_module(js BINDINGS)
ocv_module_include_directories(${EMSCRIPTEN_INCLUDE_DIR})
# get list of modules to wrap
# message(STATUS "Wrapped in js:")
set(OPENCV_JS_MODULES)
foreach(m ${OPENCV_MODULES_BUILD})
if(";${OPENCV_MODULE_${m}_WRAPPERS};" MATCHES ";js;" AND HAVE_${m})
list(APPEND OPENCV_JS_MODULES ${m})
# message(STATUS "\t${m}")
endif()
endforeach()
set(opencv_hdrs "")
foreach(m ${OPENCV_JS_MODULES})
list(APPEND opencv_hdrs ${OPENCV_MODULE_${m}_HEADERS})
endforeach(m)
# header blacklist
ocv_list_filterout(opencv_hdrs "modules/.*.h$")
ocv_list_filterout(opencv_hdrs "modules/core/.*/cuda")
ocv_list_filterout(opencv_hdrs "modules/core/.*/opencl")
ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/opengl.hpp")
ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/ocl.hpp")
ocv_list_filterout(opencv_hdrs "modules/cuda.*")
ocv_list_filterout(opencv_hdrs "modules/cudev")
ocv_list_filterout(opencv_hdrs "modules/core/.*/hal/")
ocv_list_filterout(opencv_hdrs "modules/.*/detection_based_tracker.hpp") # Conditional compilation
ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/utils/.*")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}")
set(bindings_cpp "${CMAKE_CURRENT_BINARY_DIR}/bindings.cpp")
set(scripts_hdr_parser "${CMAKE_CURRENT_SOURCE_DIR}/../python/src2/hdr_parser.py")
set(JS_HELPER "${CMAKE_CURRENT_SOURCE_DIR}/src/helpers.js")
add_custom_command(
OUTPUT ${bindings_cpp}
COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/src/embindgen.py" ${scripts_hdr_parser} ${bindings_cpp} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${CMAKE_CURRENT_SOURCE_DIR}/src/core_bindings.cpp"
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/core_bindings.cpp
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/embindgen.py
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/templates.py
DEPENDS ${scripts_hdr_parser}
#(not needed - generated by CMake) DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/headers.txt
DEPENDS ${opencv_hdrs}
DEPENDS ${JS_HELPER})
add_definitions("-std=c++11")
link_libraries(${OPENCV_MODULE_${the_module}_DEPS})
OCV_OPTION(BUILD_WASM_INTRIN_TESTS "Build WASM intrin tests" OFF )
if(BUILD_WASM_INTRIN_TESTS)
add_definitions(-DTEST_WASM_INTRIN)
ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../ts/include")
ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../imgcodecs/include")
ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../videoio/include")
ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../highgui/include")
ocv_add_executable(${the_module} ${bindings_cpp} "${CMAKE_CURRENT_SOURCE_DIR}/../ts/src/ts_gtest.cpp")
else()
ocv_add_executable(${the_module} ${bindings_cpp})
endif()
set(COMPILE_FLAGS "")
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-missing-prototypes")
endif()
if(COMPILE_FLAGS)
set_target_properties(${the_module} PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS})
endif()
set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} --memory-init-file 0 -s TOTAL_MEMORY=128MB -s WASM_MEM_MAX=1GB -s ALLOW_MEMORY_GROWTH=1")
set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s MODULARIZE=1 -s SINGLE_FILE=1")
set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s EXPORT_NAME=\"'cv'\" -s DEMANGLE_SUPPORT=1")
set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s FORCE_FILESYSTEM=1 --use-preload-plugins --bind --post-js ${JS_HELPER} ${COMPILE_FLAGS}")
set_target_properties(${the_module} PROPERTIES LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS}")
# add UMD wrapper
set(MODULE_JS_PATH "${OpenCV_BINARY_DIR}/bin/${the_module}.js")
set(OCV_JS_PATH "${OpenCV_BINARY_DIR}/bin/${OPENCV_JS}")
add_custom_command(
OUTPUT ${OCV_JS_PATH}
COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/src/make_umd.py" ${MODULE_JS_PATH} "${OCV_JS_PATH}"
DEPENDS ${the_module}
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/make_umd.py")
add_custom_target(${OPENCV_JS} ALL
DEPENDS ${OCV_JS_PATH}
DEPENDS ${the_module})
# test
set(opencv_test_js_bin_dir "${EXECUTABLE_OUTPUT_PATH}")
set(test_dir ${CMAKE_CURRENT_SOURCE_DIR}/test)
set(opencv_test_js_file_deps "")
# message(STATUS "${opencv_test_js_bin_dir}")
# make sure the build directory exists
file(MAKE_DIRECTORY "${opencv_test_js_bin_dir}")
# gather and copy specific files for js test
file(GLOB_RECURSE test_files RELATIVE "${test_dir}" "${test_dir}/*")
foreach(f ${test_files})
# message(STATUS "copy ${test_dir}/${f} ${opencv_test_js_bin_dir}/${f}")
add_custom_command(OUTPUT "${opencv_test_js_bin_dir}/${f}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${test_dir}/${f}" "${opencv_test_js_bin_dir}/${f}"
DEPENDS "${test_dir}/${f}"
COMMENT "Copying ${f}"
)
list(APPEND opencv_test_js_file_deps "${test_dir}/${f}" "${opencv_test_js_bin_dir}/${f}")
endforeach()
# copy test data
set(test_data "haarcascade_frontalface_default.xml")
set(test_data_path "${PROJECT_SOURCE_DIR}/../../data/haarcascades/${test_data}")
add_custom_command(OUTPUT "${opencv_test_js_bin_dir}/${test_data}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${test_data_path}" "${opencv_test_js_bin_dir}/${test_data}"
DEPENDS "${test_data_path}"
COMMENT "Copying ${test_data}"
)
list(APPEND opencv_test_js_file_deps "${test_data_path}" "${opencv_test_js_bin_dir}/${test_data}")
add_custom_target(${PROJECT_NAME}_test ALL
DEPENDS ${OCV_JS_PATH} ${opencv_test_js_file_deps})
# perf
set(opencv_perf_js_bin_dir "${EXECUTABLE_OUTPUT_PATH}/perf")
set(perf_dir ${CMAKE_CURRENT_SOURCE_DIR}/perf)
set(opencv_perf_js_file_deps "")
# make sure the build directory exists
file(MAKE_DIRECTORY "${opencv_perf_js_bin_dir}")
# gather and copy specific files for js perf
file(GLOB_RECURSE perf_files RELATIVE "${perf_dir}" "${perf_dir}/*")
foreach(f ${perf_files})
add_custom_command(OUTPUT "${opencv_perf_js_bin_dir}/${f}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${perf_dir}/${f}" "${opencv_perf_js_bin_dir}/${f}"
DEPENDS "${perf_dir}/${f}"
COMMENT "Copying ${f}"
)
list(APPEND opencv_perf_js_file_deps "${perf_dir}/${f}" "${opencv_perf_js_bin_dir}/${f}")
endforeach()
add_custom_target(${PROJECT_NAME}_perf ALL
DEPENDS ${OCV_JS_PATH} ${opencv_perf_js_file_deps})

View File

@@ -0,0 +1,35 @@
# OpenCV.js Performance Test
## Node.js Version
### Prerequisites
1. node.js, npm: Make sure you have installed these beforehand with the system package manager.
2. Benchmark.js: Make sure you have installed Benchmark.js by npm before use. Please run `npm install` in the directory `<build_dir>/bin/perf`.
### How to Use
For example, if you want to test the performance of cvtColor, please run `perf_cvtcolor.js` by node in terminal:
```sh
node perf_cvtcolor.js
```
All tests of cvtColor will be run by above command.
If you just want to run one specific case, please use `--test_param_filter="()"` flag, like:
```sh
node perf_cvtcolor.js --test_param_filter="(1920x1080, COLOR_BGR2GRAY)"
```
## Browser Version
### How to Use
To run performance tests, please launch a local web server in <build_dir>/bin folder. For example, node http-server which serves on localhost:8080.
Navigate the web browser to the kernel page you want to test, like http://localhost:8080/perf/imgproc/cvtcolor.html.
You can input the paramater, and then click the `Run` button to run the specific case, or it will run all the cases.

View File

@@ -0,0 +1,18 @@
if (typeof window === 'undefined') {
var cv = require("../opencv");
}
const cvSize = {
szODD: new cv.Size(127, 61),
szQVGA: new cv.Size(320, 240),
szVGA: new cv.Size(640, 480),
szqHD: new cv.Size(960, 540),
sz720p: new cv.Size(1280, 720),
sz1080p: new cv.Size(1920, 1080),
sz130x60: new cv.Size(130, 60),
sz213x120: new cv.Size(120 * 1280 / 720, 120),
}
if (typeof window === 'undefined') {
exports.cvSize = cvSize;
}

View File

@@ -0,0 +1,19 @@
{
"name": "opencv_js_perf",
"description": "Perfermance tests for opencv js bindings",
"version": "1.0.0",
"dependencies" : {
"benchmark" : "latest"
},
"repository": {
"type": "git",
"url": "https://github.com/opencv/opencv.git"
},
"keywords": [],
"author": "",
"license": "BSD-3-Clause",
"bugs": {
"url": "https://github.com/opencv/opencv/issues"
},
"homepage": "https://github.com/opencv/opencv"
}

View File

@@ -0,0 +1,59 @@
var fillGradient = function(cv, img, delta=5) {
let ch = img.channels();
console.assert(!img.empty() && img.depth() == cv.CV_8U && ch <= 4);
let n = 255 / delta;
for(let r = 0; r < img.rows; ++r) {
let kR = r % (2*n);
let valR = (kR<=n) ? delta*kR : delta*(2*n-kR);
for(let c = 0; c < img.cols; ++c) {
let kC = c % (2*n);
let valC = (kC<=n) ? delta*kC : delta*(2*n-kC);
let vals = [valR, valC, 200*r/img.rows, 255];
let p = img.ptr(r, c);
for(let i = 0; i < ch; ++i) p[i] = vals[i];
}
}
}
var cvtStr2cvSize = function(strSize) {
let size;
switch(strSize) {
case "127,61": size = cvSize.szODD;break;
case '320,240': size = cvSize.szQVGA;break;
case '640,480': size = cvSize.szVGA;break;
case '960,540': size = cvSize.szqHD;break;
case '1280,720': size = cvSize.sz720p;break;
case '1920,1080': size = cvSize.sz1080p;break;
case "130,60": size = cvSize.sz130x60;break;
case '213,120': size = cvSize.sz213x120;break;
default: console.error("unsupported size for this case");
}
return size;
}
var combine = function() {
let result = [[]];
for (let i = 0; i < arguments.length; ++i) {
result = permute(result, arguments[i]);
}
return result;
}
function permute (source, target) {
let result = [];
for (let i = 0; i < source.length; ++i) {
for (let j = 0; j < target.length; ++j) {
let tmp = source[i].slice();
tmp.push(target[j]);
result.push(tmp);
}
}
return result;
}
if (typeof window === 'undefined') {
exports.fillGradient = fillGradient;
exports.cvtStr2cvSize = cvtStr2cvSize;
exports.combine = combine;
}

View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OpenCV.js Performance Test</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
body {
font-size: 13px;
}
.top-margin {
margin-top:10px;
}
h1, h4 {
margin: 24px 0 0;
}
h1 {
font-size: 2.0em;
}
h4 {
font-size: 1.2em;
}
pre {
font-family: 'Consolas', 'Monaco', monospace, serif;
font-size: 12px;
tab-size: 2;
}
input[type=checkbox] {
vertical-align: middle;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="row">
<div class="col-12">
<h1>OpenCV.js Performance Test</h1>
<div>
<h4>Modules</h4>
<h7>Image Processing</h7>
</div>
<div>
<h4>Kernels</h4>
<h7>CvtColor</h7>
</div>
<div>
<h4>Parameters Filter</h4>
<input type="text" id="params" min="1" size="40" placeholder="default: run all the case"/> for example: (640x480,COLOR_RGBA2GRAY)
</div>
<div class='row labels-wrapper' id='labelitem'></div>
<div class="row top-margin">
</div>
<div>
<button type="button" id="runButton" class="btn btn-primary disabled" disabled="disabled">Loading</button>
(It will take several minutes)</div>
<div class="row top-margin">
</div>
<div>
<pre id="log"></pre>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/platform/1.3.5/platform.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.4/benchmark.js"></script>
<script src="../../opencv.js" type="text/javascript"></script>
<script src="../base.js"></script>
<script src="../perf_helpfunc.js"></script>
<script src="./perf_cvtcolor.js"></script>
</body>
</html>

View File

@@ -0,0 +1,572 @@
const isNodeJs = (typeof window) === 'undefined'? true : false;
if (isNodeJs) {
var Benchmark = require('benchmark');
var cv = require('../../opencv');
var HelpFunc = require('../perf_helpfunc');
var Base = require('../base');
} else {
var paramsElement = document.getElementById('params');
var runButton = document.getElementById('runButton');
var logElement = document.getElementById('log');
}
cv.onRuntimeInitialized = () => {
console.log('opencv.js loaded');
if (isNodeJs) {
global.cv = cv;
global.combine = HelpFunc.combine;
global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize;
global.cvSize = Base.cvSize;
} else {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
let totalCaseNum, currentCaseId;
//extra color conversions supported implicitly
{
cv.CX_BGRA2HLS = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2HLS,
cv.CX_BGRA2HLS_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2HLS_FULL,
cv.CX_BGRA2HSV = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2HSV,
cv.CX_BGRA2HSV_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2HSV_FULL,
cv.CX_BGRA2Lab = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2Lab,
cv.CX_BGRA2Luv = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2Luv,
cv.CX_BGRA2XYZ = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2XYZ,
cv.CX_BGRA2YCrCb = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2YCrCb,
cv.CX_BGRA2YUV = cv.COLOR_COLORCVT_MAX + cv.COLOR_BGR2YUV,
cv.CX_HLS2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_HLS2BGR,
cv.CX_HLS2BGRA_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_HLS2BGR_FULL,
cv.CX_HLS2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_HLS2RGB,
cv.CX_HLS2RGBA_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_HLS2RGB_FULL,
cv.CX_HSV2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_HSV2BGR,
cv.CX_HSV2BGRA_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_HSV2BGR_FULL,
cv.CX_HSV2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_HSV2RGB,
cv.CX_HSV2RGBA_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_HSV2RGB_FULL,
cv.CX_Lab2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Lab2BGR,
cv.CX_Lab2LBGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Lab2LBGR,
cv.CX_Lab2LRGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Lab2LRGB,
cv.CX_Lab2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Lab2RGB,
cv.CX_LBGRA2Lab = cv.COLOR_COLORCVT_MAX + cv.COLOR_LBGR2Lab,
cv.CX_LBGRA2Luv = cv.COLOR_COLORCVT_MAX + cv.COLOR_LBGR2Luv,
cv.CX_LRGBA2Lab = cv.COLOR_COLORCVT_MAX + cv.COLOR_LRGB2Lab,
cv.CX_LRGBA2Luv = cv.COLOR_COLORCVT_MAX + cv.COLOR_LRGB2Luv,
cv.CX_Luv2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Luv2BGR,
cv.CX_Luv2LBGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Luv2LBGR,
cv.CX_Luv2LRGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Luv2LRGB,
cv.CX_Luv2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_Luv2RGB,
cv.CX_RGBA2HLS = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2HLS,
cv.CX_RGBA2HLS_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2HLS_FULL,
cv.CX_RGBA2HSV = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2HSV,
cv.CX_RGBA2HSV_FULL = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2HSV_FULL,
cv.CX_RGBA2Lab = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2Lab,
cv.CX_RGBA2Luv = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2Luv,
cv.CX_RGBA2XYZ = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2XYZ,
cv.CX_RGBA2YCrCb = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2YCrCb,
cv.CX_RGBA2YUV = cv.COLOR_COLORCVT_MAX + cv.COLOR_RGB2YUV,
cv.CX_XYZ2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_XYZ2BGR,
cv.CX_XYZ2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_XYZ2RGB,
cv.CX_YCrCb2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_YCrCb2BGR,
cv.CX_YCrCb2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_YCrCb2RGB,
cv.CX_YUV2BGRA = cv.COLOR_COLORCVT_MAX + cv.COLOR_YUV2BGR,
cv.CX_YUV2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_YUV2RGB
};
const CvtMode = [
"COLOR_BGR2BGR555", "COLOR_BGR2BGR565", "COLOR_BGR2BGRA", "COLOR_BGR2GRAY",
"COLOR_BGR2HLS", "COLOR_BGR2HLS_FULL", "COLOR_BGR2HSV", "COLOR_BGR2HSV_FULL",
"COLOR_BGR2Lab", "COLOR_BGR2Luv", "COLOR_BGR2RGB", "COLOR_BGR2RGBA", "COLOR_BGR2XYZ",
"COLOR_BGR2YCrCb", "COLOR_BGR2YUV", "COLOR_BGR5552BGR", "COLOR_BGR5552BGRA",
"COLOR_BGR5552GRAY", "COLOR_BGR5552RGB", "COLOR_BGR5552RGBA", "COLOR_BGR5652BGR",
"COLOR_BGR5652BGRA", "COLOR_BGR5652GRAY", "COLOR_BGR5652RGB", "COLOR_BGR5652RGBA",
"COLOR_BGRA2BGR", "COLOR_BGRA2BGR555", "COLOR_BGRA2BGR565", "COLOR_BGRA2GRAY", "COLOR_BGRA2RGBA",
"CX_BGRA2HLS", "CX_BGRA2HLS_FULL", "CX_BGRA2HSV", "CX_BGRA2HSV_FULL",
"CX_BGRA2Lab", "CX_BGRA2Luv", "CX_BGRA2XYZ",
"CX_BGRA2YCrCb", "CX_BGRA2YUV",
"COLOR_GRAY2BGR", "COLOR_GRAY2BGR555", "COLOR_GRAY2BGR565", "COLOR_GRAY2BGRA",
"COLOR_HLS2BGR", "COLOR_HLS2BGR_FULL", "COLOR_HLS2RGB", "COLOR_HLS2RGB_FULL",
"CX_HLS2BGRA", "CX_HLS2BGRA_FULL", "CX_HLS2RGBA", "CX_HLS2RGBA_FULL",
"COLOR_HSV2BGR", "COLOR_HSV2BGR_FULL", "COLOR_HSV2RGB", "COLOR_HSV2RGB_FULL",
"CX_HSV2BGRA", "CX_HSV2BGRA_FULL", "CX_HSV2RGBA", "CX_HSV2RGBA_FULL",
"COLOR_Lab2BGR", "COLOR_Lab2LBGR", "COLOR_Lab2LRGB", "COLOR_Lab2RGB",
"CX_Lab2BGRA", "CX_Lab2LBGRA", "CX_Lab2LRGBA", "CX_Lab2RGBA",
"COLOR_LBGR2Lab", "COLOR_LBGR2Luv", "COLOR_LRGB2Lab", "COLOR_LRGB2Luv",
"CX_LBGRA2Lab", "CX_LBGRA2Luv", "CX_LRGBA2Lab", "CX_LRGBA2Luv",
"COLOR_Luv2BGR", "COLOR_Luv2LBGR", "COLOR_Luv2LRGB", "COLOR_Luv2RGB",
"CX_Luv2BGRA", "CX_Luv2LBGRA", "CX_Luv2LRGBA", "CX_Luv2RGBA",
"COLOR_RGB2BGR555", "COLOR_RGB2BGR565", "COLOR_RGB2GRAY",
"COLOR_RGB2HLS", "COLOR_RGB2HLS_FULL", "COLOR_RGB2HSV", "COLOR_RGB2HSV_FULL",
"COLOR_RGB2Lab", "COLOR_RGB2Luv", "COLOR_RGB2XYZ", "COLOR_RGB2YCrCb", "COLOR_RGB2YUV",
"COLOR_RGBA2BGR", "COLOR_RGBA2BGR555", "COLOR_RGBA2BGR565", "COLOR_RGBA2GRAY",
"CX_RGBA2HLS", "CX_RGBA2HLS_FULL", "CX_RGBA2HSV", "CX_RGBA2HSV_FULL",
"CX_RGBA2Lab", "CX_RGBA2Luv", "CX_RGBA2XYZ",
"CX_RGBA2YCrCb", "CX_RGBA2YUV",
"COLOR_XYZ2BGR", "COLOR_XYZ2RGB", "CX_XYZ2BGRA", "CX_XYZ2RGBA",
"COLOR_YCrCb2BGR", "COLOR_YCrCb2RGB", "CX_YCrCb2BGRA", "CX_YCrCb2RGBA",
"COLOR_YUV2BGR", "COLOR_YUV2RGB", "CX_YUV2BGRA", "CX_YUV2RGBA"
];
const CvtModeSize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p];
const combiCvtMode = combine(CvtModeSize, CvtMode);
// didn't support 16u and 32f perf tests according to
// https://github.com/opencv/opencv/commit/4e679e1cc5b075ec006b29a58b4fe117523fba1d
const CvtMode16U = [
"COLOR_BGR2BGRA", "COLOR_BGR2GRAY",
"COLOR_BGR2RGB", "COLOR_BGR2RGBA", "COLOR_BGR2XYZ",
"COLOR_BGR2YCrCb", "COLOR_BGR2YUV",
"COLOR_BGRA2BGR", "COLOR_BGRA2GRAY", "COLOR_BGRA2RGBA",
"CX_BGRA2XYZ",
"CX_BGRA2YCrCb", "CX_BGRA2YUV",
"COLOR_GRAY2BGR", "COLOR_GRAY2BGRA",
"COLOR_RGB2GRAY",
"COLOR_RGB2XYZ", "COLOR_RGB2YCrCb", "COLOR_RGB2YUV",
"COLOR_RGBA2BGR", "COLOR_RGBA2GRAY",
"CX_RGBA2XYZ",
"CX_RGBA2YCrCb", "CX_RGBA2YUV",
"COLOR_XYZ2BGR", "COLOR_XYZ2RGB", "CX_XYZ2BGRA", "CX_XYZ2RGBA",
"COLOR_YCrCb2BGR", "COLOR_YCrCb2RGB", "CX_YCrCb2BGRA", "CX_YCrCb2RGBA",
"COLOR_YUV2BGR", "COLOR_YUV2RGB", "CX_YUV2BGRA", "CX_YUV2RGBA"
];
const CvtMode16USize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p];
const combiCvtMode16U = combine(CvtMode16USize, CvtMode16U);
const CvtMode32F = [
"COLOR_BGR2BGRA", "COLOR_BGR2GRAY",
"COLOR_BGR2HLS", "COLOR_BGR2HLS_FULL", "COLOR_BGR2HSV", "COLOR_BGR2HSV_FULL",
"COLOR_BGR2Lab", "COLOR_BGR2Luv", "COLOR_BGR2RGB", "COLOR_BGR2RGBA", "COLOR_BGR2XYZ",
"COLOR_BGR2YCrCb", "COLOR_BGR2YUV",
"COLOR_BGRA2BGR", "COLOR_BGRA2GRAY", "COLOR_BGRA2RGBA",
"CX_BGRA2HLS", "CX_BGRA2HLS_FULL", "CX_BGRA2HSV", "CX_BGRA2HSV_FULL",
"CX_BGRA2Lab", "CX_BGRA2Luv", "CX_BGRA2XYZ",
"CX_BGRA2YCrCb", "CX_BGRA2YUV",
"COLOR_GRAY2BGR", "COLOR_GRAY2BGRA",
"COLOR_HLS2BGR", "COLOR_HLS2BGR_FULL", "COLOR_HLS2RGB", "COLOR_HLS2RGB_FULL",
"CX_HLS2BGRA", "CX_HLS2BGRA_FULL", "CX_HLS2RGBA", "CX_HLS2RGBA_FULL",
"COLOR_HSV2BGR", "COLOR_HSV2BGR_FULL", "COLOR_HSV2RGB", "COLOR_HSV2RGB_FULL",
"CX_HSV2BGRA", "CX_HSV2BGRA_FULL", "CX_HSV2RGBA", "CX_HSV2RGBA_FULL",
"COLOR_Lab2BGR", "COLOR_Lab2LBGR", "COLOR_Lab2LRGB", "COLOR_Lab2RGB",
"CX_Lab2BGRA", "CX_Lab2LBGRA", "CX_Lab2LRGBA", "CX_Lab2RGBA",
"COLOR_LBGR2Lab", "COLOR_LBGR2Luv", "COLOR_LRGB2Lab", "COLOR_LRGB2Luv",
"CX_LBGRA2Lab", "CX_LBGRA2Luv", "CX_LRGBA2Lab", "CX_LRGBA2Luv",
"COLOR_Luv2BGR", "COLOR_Luv2LBGR", "COLOR_Luv2LRGB", "COLOR_Luv2RGB",
"CX_Luv2BGRA", "CX_Luv2LBGRA", "CX_Luv2LRGBA", "CX_Luv2RGBA",
"COLOR_RGB2GRAY",
"COLOR_RGB2HLS", "COLOR_RGB2HLS_FULL", "COLOR_RGB2HSV", "COLOR_RGB2HSV_FULL",
"COLOR_RGB2Lab", "COLOR_RGB2Luv", "COLOR_RGB2XYZ", "COLOR_RGB2YCrCb", "COLOR_RGB2YUV",
"COLOR_RGBA2BGR", "COLOR_RGBA2GRAY",
"CX_RGBA2HLS", "CX_RGBA2HLS_FULL", "CX_RGBA2HSV", "CX_RGBA2HSV_FULL",
"CX_RGBA2Lab", "CX_RGBA2Luv", "CX_RGBA2XYZ",
"CX_RGBA2YCrCb", "CX_RGBA2YUV",
"COLOR_XYZ2BGR", "COLOR_XYZ2RGB", "CX_XYZ2BGRA", "CX_XYZ2RGBA",
"COLOR_YCrCb2BGR", "COLOR_YCrCb2RGB", "CX_YCrCb2BGRA", "CX_YCrCb2RGBA",
"COLOR_YUV2BGR", "COLOR_YUV2RGB", "CX_YUV2BGRA", "CX_YUV2RGBA"
];
const CvtMode32FSize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p];
const combiCvtMode32F = combine(CvtMode32FSize, CvtMode32F);
const CvtModeBayer = [
"COLOR_BayerBG2BGR", "COLOR_BayerBG2BGRA", "COLOR_BayerBG2BGR_VNG", "COLOR_BayerBG2GRAY",
"COLOR_BayerGB2BGR", "COLOR_BayerGB2BGRA", "COLOR_BayerGB2BGR_VNG", "COLOR_BayerGB2GRAY",
"COLOR_BayerGR2BGR", "COLOR_BayerGR2BGRA", "COLOR_BayerGR2BGR_VNG", "COLOR_BayerGR2GRAY",
"COLOR_BayerRG2BGR", "COLOR_BayerRG2BGRA", "COLOR_BayerRG2BGR_VNG", "COLOR_BayerRG2GRAY"
];
const CvtModeBayerSize = [cvSize.szODD, cvSize.szVGA];
const combiCvtModeBayer = combine(CvtModeBayerSize, CvtModeBayer);
const CvtMode2 = [
"COLOR_YUV2BGR_NV12", "COLOR_YUV2BGRA_NV12", "COLOR_YUV2RGB_NV12", "COLOR_YUV2RGBA_NV12", "COLOR_YUV2BGR_NV21", "COLOR_YUV2BGRA_NV21", "COLOR_YUV2RGB_NV21", "COLOR_YUV2RGBA_NV21",
"COLOR_YUV2BGR_YV12", "COLOR_YUV2BGRA_YV12", "COLOR_YUV2RGB_YV12", "COLOR_YUV2RGBA_YV12", "COLOR_YUV2BGR_IYUV", "COLOR_YUV2BGRA_IYUV", "COLOR_YUV2RGB_IYUV", "COLOR_YUV2RGBA_IYUV",
"COLOR_YUV2GRAY_420", "COLOR_YUV2RGB_UYVY", "COLOR_YUV2BGR_UYVY", "COLOR_YUV2RGBA_UYVY", "COLOR_YUV2BGRA_UYVY", "COLOR_YUV2RGB_YUY2", "COLOR_YUV2BGR_YUY2", "COLOR_YUV2RGB_YVYU",
"COLOR_YUV2BGR_YVYU", "COLOR_YUV2RGBA_YUY2", "COLOR_YUV2BGRA_YUY2", "COLOR_YUV2RGBA_YVYU", "COLOR_YUV2BGRA_YVYU"
];
const CvtMode2Size = [cvSize.szVGA, cvSize.sz1080p, cvSize.sz130x60];
const combiCvtMode2 = combine(CvtMode2Size, CvtMode2);
const CvtMode3 = [
"COLOR_RGB2YUV_IYUV", "COLOR_BGR2YUV_IYUV", "COLOR_RGBA2YUV_IYUV", "COLOR_BGRA2YUV_IYUV",
"COLOR_RGB2YUV_YV12", "COLOR_BGR2YUV_YV12", "COLOR_RGBA2YUV_YV12", "COLOR_BGRA2YUV_YV12"
];
const CvtMode3Size = [cvSize.szVGA, cvSize.sz720p, cvSize.sz1080p, cvSize.sz130x60];
const combiCvtMode3 = combine(CvtMode3Size, CvtMode3);
const EdgeAwareBayerMode = [
"COLOR_BayerBG2BGR_EA", "COLOR_BayerGB2BGR_EA", "COLOR_BayerRG2BGR_EA", "COLOR_BayerGR2BGR_EA"
];
const EdgeAwareBayerModeSize = [cvSize.szVGA, cvSize.sz720p, cvSize.sz1080p, cvSize.sz130x60];
const combiEdgeAwareBayer = combine(EdgeAwareBayerModeSize, EdgeAwareBayerMode);
// This function returns an array. The 1st element is the channel number of
// source mat and 2nd element is the channel number of destination mat.
function getConversionInfo(cvtMode) {
switch(cvtMode) {
case "COLOR_BayerBG2GRAY": case "COLOR_BayerGB2GRAY":
case "COLOR_BayerGR2GRAY": case "COLOR_BayerRG2GRAY":
case "COLOR_YUV2GRAY_420":
return [1, 1];
case "COLOR_GRAY2BGR555": case "COLOR_GRAY2BGR565":
return [1, 2];
case "COLOR_BayerBG2BGR": case "COLOR_BayerBG2BGR_VNG":
case "COLOR_BayerGB2BGR": case "COLOR_BayerGB2BGR_VNG":
case "COLOR_BayerGR2BGR": case "COLOR_BayerGR2BGR_VNG":
case "COLOR_BayerRG2BGR": case "COLOR_BayerRG2BGR_VNG":
case "COLOR_GRAY2BGR":
case "COLOR_YUV2BGR_NV12": case "COLOR_YUV2RGB_NV12":
case "COLOR_YUV2BGR_NV21": case "COLOR_YUV2RGB_NV21":
case "COLOR_YUV2BGR_YV12": case "COLOR_YUV2RGB_YV12":
case "COLOR_YUV2BGR_IYUV": case "COLOR_YUV2RGB_IYUV":
return [1, 3];
case "COLOR_GRAY2BGRA":
case "COLOR_YUV2BGRA_NV12": case "COLOR_YUV2RGBA_NV12":
case "COLOR_YUV2BGRA_NV21": case "COLOR_YUV2RGBA_NV21":
case "COLOR_YUV2BGRA_YV12": case "COLOR_YUV2RGBA_YV12":
case "COLOR_YUV2BGRA_IYUV": case "COLOR_YUV2RGBA_IYUV":
case "COLOR_BayerBG2BGRA": case "COLOR_BayerGB2BGRA":
case "COLOR_BayerGR2BGRA": case "COLOR_BayerRG2BGRA":
return [1, 4];
case "COLOR_BGR5552GRAY": case "COLOR_BGR5652GRAY":
return [2, 1];
case "COLOR_BGR5552BGR": case "COLOR_BGR5552RGB":
case "COLOR_BGR5652BGR": case "COLOR_BGR5652RGB":
case "COLOR_YUV2RGB_UYVY": case "COLOR_YUV2BGR_UYVY":
case "COLOR_YUV2RGB_YUY2": case "COLOR_YUV2BGR_YUY2":
case "COLOR_YUV2RGB_YVYU": case "COLOR_YUV2BGR_YVYU":
return [2, 3];
case "COLOR_BGR5552BGRA": case "COLOR_BGR5552RGBA":
case "COLOR_BGR5652BGRA": case "COLOR_BGR5652RGBA":
case "COLOR_YUV2RGBA_UYVY": case "COLOR_YUV2BGRA_UYVY":
case "COLOR_YUV2RGBA_YUY2": case "COLOR_YUV2BGRA_YUY2":
case "COLOR_YUV2RGBA_YVYU": case "COLOR_YUV2BGRA_YVYU":
return [2, 4];
case "COLOR_BGR2GRAY": case "COLOR_RGB2GRAY":
case "COLOR_RGB2YUV_IYUV": case "COLOR_RGB2YUV_YV12":
case "COLOR_BGR2YUV_IYUV": case "COLOR_BGR2YUV_YV12":
return [3, 1];
case "COLOR_BGR2BGR555": case "COLOR_BGR2BGR565":
case "COLOR_RGB2BGR555": case "COLOR_RGB2BGR565":
return [3, 2];
case "COLOR_BGR2HLS": case "COLOR_BGR2HLS_FULL":
case "COLOR_BGR2HSV": case "COLOR_BGR2HSV_FULL":
case "COLOR_BGR2Lab": case "COLOR_BGR2Luv":
case "COLOR_BGR2RGB": case "COLOR_BGR2XYZ":
case "COLOR_BGR2YCrCb": case "COLOR_BGR2YUV":
case "COLOR_HLS2BGR": case "COLOR_HLS2BGR_FULL":
case "COLOR_HLS2RGB": case "COLOR_HLS2RGB_FULL":
case "COLOR_HSV2BGR": case "COLOR_HSV2BGR_FULL":
case "COLOR_HSV2RGB": case "COLOR_HSV2RGB_FULL":
case "COLOR_Lab2BGR": case "COLOR_Lab2LBGR":
case "COLOR_Lab2LRGB": case "COLOR_Lab2RGB":
case "COLOR_LBGR2Lab": case "COLOR_LBGR2Luv":
case "COLOR_LRGB2Lab": case "COLOR_LRGB2Luv":
case "COLOR_Luv2BGR": case "COLOR_Luv2LBGR":
case "COLOR_Luv2LRGB": case "COLOR_Luv2RGB":
case "COLOR_RGB2HLS": case "COLOR_RGB2HLS_FULL":
case "COLOR_RGB2HSV": case "COLOR_RGB2HSV_FULL":
case "COLOR_RGB2Lab": case "COLOR_RGB2Luv":
case "COLOR_RGB2XYZ": case "COLOR_RGB2YCrCb":
case "COLOR_RGB2YUV": case "COLOR_XYZ2BGR":
case "COLOR_XYZ2RGB": case "COLOR_YCrCb2BGR":
case "COLOR_YCrCb2RGB": case "COLOR_YUV2BGR":
case "COLOR_YUV2RGB":
return [3, 3];
case "COLOR_BGR2BGRA": case "COLOR_BGR2RGBA":
case "CX_HLS2BGRA": case "CX_HLS2BGRA_FULL":
case "CX_HLS2RGBA": case "CX_HLS2RGBA_FULL":
case "CX_HSV2BGRA": case "CX_HSV2BGRA_FULL":
case "CX_HSV2RGBA": case "CX_HSV2RGBA_FULL":
case "CX_Lab2BGRA": case "CX_Lab2LBGRA":
case "CX_Lab2LRGBA": case "CX_Lab2RGBA":
case "CX_Luv2BGRA": case "CX_Luv2LBGRA":
case "CX_Luv2LRGBA": case "CX_Luv2RGBA":
case "CX_XYZ2BGRA": case "CX_XYZ2RGBA":
case "CX_YCrCb2BGRA": case "CX_YCrCb2RGBA":
case "CX_YUV2BGRA": case "CX_YUV2RGBA":
return [3, 4];
case "COLOR_BGRA2GRAY": case "COLOR_RGBA2GRAY":
case "COLOR_RGBA2YUV_IYUV": case "COLOR_RGBA2YUV_YV12":
case "COLOR_BGRA2YUV_IYUV": case "COLOR_BGRA2YUV_YV12":
return [4, 1];
case "COLOR_BGRA2BGR555": case "COLOR_BGRA2BGR565":
case "COLOR_RGBA2BGR555": case "COLOR_RGBA2BGR565":
return [4, 2];
case "COLOR_BGRA2BGR": case "CX_BGRA2HLS":
case "CX_BGRA2HLS_FULL": case "CX_BGRA2HSV":
case "CX_BGRA2HSV_FULL": case "CX_BGRA2Lab":
case "CX_BGRA2Luv": case "CX_BGRA2XYZ":
case "CX_BGRA2YCrCb": case "CX_BGRA2YUV":
case "CX_LBGRA2Lab": case "CX_LBGRA2Luv":
case "CX_LRGBA2Lab": case "CX_LRGBA2Luv":
case "COLOR_RGBA2BGR": case "CX_RGBA2HLS":
case "CX_RGBA2HLS_FULL": case "CX_RGBA2HSV":
case "CX_RGBA2HSV_FULL": case "CX_RGBA2Lab":
case "CX_RGBA2Luv": case "CX_RGBA2XYZ":
case "CX_RGBA2YCrCb": case "CX_RGBA2YUV":
return [4, 3];
case "COLOR_BGRA2RGBA":
return [4, 4];
default:
console.error("Unknown conversion type");
break;
};
return [0, 0];
}
function getMatType(chPair) {
let dataType = "8U"; // now just support "8U" data type, we can set it as a param to extend the data type later.
let mat1Type, mat2Type;
if (chPair[0] === 0) {
mat1Type = `CV_${dataType}C`;
} else {
mat1Type = `CV_${dataType}C${chPair[0].toString()}`;
}
if (chPair[1] === 0) {
mat2Type = `CV_${dataType}C`;
} else {
mat2Type = `CV_${dataType}C${chPair[1].toString()}`;
}
return [mat1Type, mat2Type];
}
function addCvtColorCase(suite) {
suite.add('cvtColor', function() {
cv.cvtColor(mat1, mat2, mode, 0);
}, {
'setup': function() {
let size = this.params.size;
let matType = this.params.matType;
let mode = cv[this.params.mode]%cv.COLOR_COLORCVT_MAX;
let mat1 = new cv.Mat(size[1], size[0], cv[matType[0]]);
let mat2 = new cv.Mat(size[1], size[0], cv[matType[1]]);
},
'teardown': function() {
mat1.delete();
mat2.delete();
}
});
}
function addCvtModeCase(suite, combination) {
totalCaseNum += combination.length;
for(let i = 0; i < combination.length; ++i) {
let size = combination[i][0];
let mode = combination[i][1];
let chPair = getConversionInfo(mode);
let matType = getMatType(chPair);
let sizeArray = [size.width, size.height];
addCvtColorCase(suite);
// set init params
let index = suite.length - 1;
suite[index].params = {
size: sizeArray,
matType: matType,
mode: mode
};
};
}
function addCvtModeBayerCase(suite, combination) {
totalCaseNum += combination.length;
for(let i = 0; i < combination.length; ++i) {
let size = combination[i][0];
let mode = combination[i][1];
let chPair = getConversionInfo(mode);
let matType = getMatType(chPair);
let sizeArray = [size.width, size.height];
addCvtColorCase(suite);
// set init params
let index = suite.length - 1;
suite[index].params = {
size: sizeArray,
matType: matType,
mode: mode
};
};
}
function addCvtMode2Case(suite, combination) {
totalCaseNum += combination.length;
for(let i = 0; i < combination.length; ++i) {
let size = combination[i][0];
let mode = combination[i][1];
let chPair = getConversionInfo(mode);
let matType = getMatType(chPair);
let sizeArray = [size.width, size.height+size.height/2];
addCvtColorCase(suite);
// set init params
let index = suite.length - 1;
suite[index].params = {
size: sizeArray,
matType: matType,
mode: mode
};
};
}
function addCvtMode3Case(suite, combination) {
totalCaseNum += combination.length;
for(let i = 0; i < combination.length; ++i) {
let size = combination[i][0];
let mode = combination[i][1];
let chPair = getConversionInfo(mode);
let matType = getMatType(chPair);
let sizeArray = [size.width, size.height+size.height/2];
addCvtColorCase(suite);
// set init params
let index = suite.length - 1;
suite[index].params = {
size: sizeArray,
matType: matType,
mode: mode
};
};
}
function addEdgeAwareBayerModeCase(suite, combination) {
totalCaseNum += combination.length;
for(let i = 0; i < combination.length; ++i) {
let size = combination[i][0];
let mode = combination[i][1];
let chPair = getConversionInfo(mode);
let matType = getMatType(chPair);
let sizeArray = [size.width, size.height];
addCvtColorCase(suite);
// set init params
let index = suite.length - 1;
suite[index].params = {
size: sizeArray,
matType: matType,
mode: mode
};
};
}
function decodeParams2Case(suite, params) {
let sizeStr = (params.match(/[0-9]+/g) || []).slice(0, 2).toString();
let mode = (params.match(/CX\_[A-z]+2[A-z]+/) || params.match(/COLOR\_[A-z]+2[A-z]+/) || []).toString();
let size = cvtStr2cvSize(sizeStr);
// check if the params match and add case
for (let i = 0; i < combinations.length; ++i) {
let combination = combinations[i];
for (let j = 0; j < combination.length; ++j) {
if (size === combination[j][0] && mode === combination[j][1]) {
cvtFunc[i](suite, [combination[j]]);
}
}
}
}
function log(message) {
console.log(message);
if (!isNodeJs) {
logElement.innerHTML += `\n${'\t' + message}`;
}
}
function setBenchmarkSuite(suite) {
suite
// add listeners
.on('cycle', function(event) {
++currentCaseId;
let params = event.target.params;
let mode = params.mode;
let size = params.size;
log(`=== ${event.target.name} ${currentCaseId} ===`);
log(`params: (${parseInt(size[0])}x${parseInt(size[1])}, ${mode})`);
log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms');
log('mean time:' +String(event.target.stats.mean*1000)+' ms');
log('stddev time:' +String(event.target.stats.deviation*1000)+' ms');
log(String(event.target));
})
.on('error', function(event) { log(`test case ${event.target.name} failed`); })
.on('complete', function(event) {
log(`\n ###################################`)
log(`Finished testing ${event.currentTarget.length} cases \n`);
if (!isNodeJs) {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
});
}
function genBenchmarkCase(paramsContent) {
let suite = new Benchmark.Suite;
totalCaseNum = 0;
currentCaseId = 0;
if (/\([0-9]+x[0-9]+,[\ ]*\w+\)/g.test(paramsContent.toString())) {
let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+\)/g)[0];
decodeParams2Case(suite, params);
} else {
log("no filter or getting invalid params, run all the cases");
addCvtModeCase(suite, combiCvtMode);
addCvtModeBayerCase(suite, combiCvtModeBayer);
addCvtMode2Case(suite, combiCvtMode2);
addCvtMode3Case(suite, combiCvtMode3);
}
setBenchmarkSuite(suite);
log(`Running ${totalCaseNum} tests from CvtColor`);
suite.run({ 'async': true }); // run the benchmark
}
// init
let cvtFunc = [addCvtModeCase, addCvtModeBayerCase, addCvtMode2Case, addCvtMode3Case];//, addEdgeAwareBayerModeCase];
let combinations = [combiCvtMode, combiCvtModeBayer, combiCvtMode2, combiCvtMode3];//, combiEdgeAwareBayer];
// set test filter params
if (isNodeJs) {
const args = process.argv.slice(2);
let paramsContent = '';
if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*\w+\)/g.test(args.toString())) {
paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+\)/g)[0];
}
genBenchmarkCase(paramsContent);
} else {
runButton.onclick = function() {
let paramsContent = paramsElement.value;
genBenchmarkCase(paramsContent);
if (totalCaseNum !== 0) {
runButton.setAttribute("disabled", "disabled");
runButton.setAttribute('class', 'btn btn-primary disabled');
runButton.innerHTML = "Running";
}
}
}
};

View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OpenCV.js Performance Test</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
body {
font-size: 13px;
}
.top-margin {
margin-top:10px;
}
h1, h4 {
margin: 24px 0 0;
}
h1 {
font-size: 2.0em;
}
h4 {
font-size: 1.2em;
}
pre {
font-family: 'Consolas', 'Monaco', monospace, serif;
font-size: 12px;
tab-size: 2;
}
input[type=checkbox] {
vertical-align: middle;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="row">
<div class="col-12">
<h1>OpenCV.js Performance Test</h1>
<div>
<h4>Modules</h4>
<h7>Image Processing</h7>
</div>
<div>
<h4>Kernels</h4>
<h7>Resize</h7>
</div>
<div>
<h4>Parameters Filter</h4>
<input type="text" id="params" min="1" size="40" placeholder="default: run all the case"/> for example: (CV_8UC1,640x480,960x540)
</div>
<div class='row labels-wrapper' id='labelitem'></div>
<div class="row top-margin">
</div>
<div>
<button type="button" id="runButton" class="btn btn-primary disabled" disabled="disabled">Loading</button>
(It will take several minutes)</div>
<div class="row top-margin">
</div>
<div>
<pre id="log"></pre>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/platform/1.3.5/platform.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.4/benchmark.js"></script>
<script src="../../opencv.js" type="text/javascript"></script>
<script src="../base.js"></script>
<script src="../perf_helpfunc.js"></script>
<script src="./perf_resize.js"></script>
</body>
</html>

View File

@@ -0,0 +1,262 @@
const isNodeJs = (typeof window) === 'undefined'? true : false;
if (isNodeJs) {
var Benchmark = require('benchmark');
var cv = require('../../opencv');
var HelpFunc = require('../perf_helpfunc');
var Base = require('../base');
} else {
var paramsElement = document.getElementById('params');
var runButton = document.getElementById('runButton');
var logElement = document.getElementById('log');
}
cv.onRuntimeInitialized = () => {
console.log('opencv.js loaded');
if (isNodeJs) {
global.cv = cv;
global.combine = HelpFunc.combine;
global.fillGradient = HelpFunc.fillGradient;
global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize;
global.cvSize = Base.cvSize;
} else {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
let totalCaseNum, currentCaseId;
const matTypesUpLinear = ['CV_8UC1', 'CV_8UC2', 'CV_8UC3', 'CV_8UC4'];
const size1UpLinear = [cvSize.szVGA];
const size2UpLinear = [cvSize.szqHD, cvSize.sz720p];
const combiUpLinear = combine(matTypesUpLinear, size1UpLinear, size2UpLinear);
const combiDownLinear = [
['CV_8UC1', cvSize.szVGA, cvSize.szQVGA],
['CV_8UC2', cvSize.szVGA, cvSize.szQVGA],
['CV_8UC3', cvSize.szVGA, cvSize.szQVGA],
['CV_8UC4', cvSize.szVGA, cvSize.szQVGA],
['CV_8UC1', cvSize.szqHD, cvSize.szVGA],
['CV_8UC2', cvSize.szqHD, cvSize.szVGA],
['CV_8UC3', cvSize.szqHD, cvSize.szVGA],
['CV_8UC4', cvSize.szqHD, cvSize.szVGA],
['CV_8UC1', cvSize.sz720p, cvSize.sz213x120],// face detection min_face_size = 20%
['CV_8UC2', cvSize.sz720p, cvSize.sz213x120],// face detection min_face_size = 20%
['CV_8UC3', cvSize.sz720p, cvSize.sz213x120],// face detection min_face_size = 20%
['CV_8UC4', cvSize.sz720p, cvSize.sz213x120],// face detection min_face_size = 20%
['CV_8UC1', cvSize.sz720p, cvSize.szVGA],
['CV_8UC2', cvSize.sz720p, cvSize.szVGA],
['CV_8UC3', cvSize.sz720p, cvSize.szVGA],
['CV_8UC4', cvSize.sz720p, cvSize.szVGA],
['CV_8UC1', cvSize.sz720p, cvSize.szQVGA],
['CV_8UC2', cvSize.sz720p, cvSize.szQVGA],
['CV_8UC3', cvSize.sz720p, cvSize.szQVGA],
['CV_8UC4', cvSize.sz720p, cvSize.szQVGA]
];
const matTypesAreaFast = ['CV_8UC1', 'CV_8UC3', 'CV_8UC4', 'CV_16UC1', 'CV_16UC3', 'CV_16UC4'];
const sizesAreaFast = [cvSize.szVGA, cvSize.szqHD, cvSize.sz720p, cvSize.sz1080p];
const scalesAreaFast = [2];
const combiAreaFast = combine(matTypesAreaFast, sizesAreaFast, scalesAreaFast);
function addResizeUpLinearCase(suite, combination) {
totalCaseNum += combination.length;
for (let i = 0; i < combination.length; ++i) {
let matType = combination[i][0];
let from = combination[i][1];
let to = combination[i][2];
suite.add('resize', function() {
cv.resize(src, dst, to, 0, 0, cv.INTER_LINEAR_EXACT);
}, {
'setup': function() {
let from = this.params.from;
let to = this.params.to;
let matType = cv[this.params.matType];
let src = new cv.Mat(from, matType);
let dst = new cv.Mat(to, matType);
fillGradient(cv, src);
},
'teardown': function() {
src.delete();
dst.delete();
}
});
// set init params
let index = suite.length - 1;
suite[index].params = {
from: from,
to: to,
matType: matType
};
}
}
function addResizeDownLinearCase(suite, combination) {
totalCaseNum += combination.length;
for (let i = 0; i < combination.length; ++i) {
let matType = combination[i][0];
let from = combination[i][1];
let to = combination[i][2];
suite.add('resize', function() {
cv.resize(src, dst, to, 0, 0, cv.INTER_LINEAR_EXACT);
}, {
'setup': function() {
let from = this.params.from;
let to = this.params.to;
let matType = cv[this.params.matType];
let src = new cv.Mat(from, matType);
let dst = new cv.Mat(to, matType);
fillGradient(cv, src);
},
'teardown': function() {
src.delete();
dst.delete();
}
});
// set init params
let index = suite.length - 1;
suite[index].params = {
from: from,
to: to,
matType: matType
};
}
}
function addResizeAreaFastCase(suite, combination) {
totalCaseNum += combination.length;
for (let i = 0; i < combination.length; ++i) {
let matType = combination[i][0];
let from = combination[i][1];
let scale = combination[i][2];
from.width = (Math.floor(from.width/scale))*scale;
from.height = (Math.floor(from.height/scale))*scale;
let to = {
width: from.width/scale,
height: from.height/scale}; // for params print
suite.add('resize', function() {
cv.resize(src, dst, dst.size(), 0, 0, cv.INTER_AREA);
}, {
'setup': function() {
let from = this.params.from;
let scale = this.params.scale;
let matType = cv[this.params.matType];
let src = new cv.Mat(from, matType);
let dst = new cv.Mat(from.height/scale, from.width/scale, matType);
},
'teardown': function() {
src.delete();
dst.delete();
}
});
// set init params
let index = suite.length - 1;
suite[index].params = {
from: from,
scale: scale,
matType: matType
};
}
}
function decodeParams2Case(suite, params) {
let sizeString = (params.match(/[0-9]+x[0-9]+/g) || []).slice(0, 2).toString();
let sizes = (sizeString.match(/[0-9]+/g) || []);
let size1Str = sizes.slice(0, 2).toString();
let size2Str = sizes.slice(2, 5).toString();
let matType = (params.match(/CV\_[0-9]+[A-z][A-z][0-9]/) || []).toString();
let size1 = cvtStr2cvSize(size1Str);
let size2 = cvtStr2cvSize(size2Str);
// check if the params match and add case
for (let i = 0; i < combinations.length; ++i) {
let combination = combinations[i];
for (let j = 0; j < combination.length; ++j) {
if (matType === combination[j][0] && size1 === combination[j][1] && size2 === combination[j][2]) {
resizeFunc[i](suite, [combination[j]]);
}
}
}
}
function log(message) {
console.log(message);
if (!isNodeJs) {
logElement.innerHTML += `\n${'\t'.repeat(1) + message}`;
}
}
function setBenchmarkSuite(suite) {
suite
// add listeners
.on('cycle', function(event) {
++currentCaseId;
let params = event.target.params;
let matType = params.matType;
let size1 = params.from;
let size2 = params.to;
log(`=== ${event.target.name} ${currentCaseId} ===`);
log(`params: (${matType},${parseInt(size1.width)}x${parseInt(size1.height)},`+
`${parseInt(size2.width)}x${parseInt(size2.height)})`);
log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms');
log('mean time:' +String(event.target.stats.mean*1000)+' ms');
log('stddev time:' +String(event.target.stats.deviation*1000)+' ms');
log(String(event.target));
})
.on('error', function(event) { log(`test case ${event.target.name} failed`); })
.on('complete', function(event) {
log(`\n ###################################`)
log(`Finished testing ${event.currentTarget.length} cases \n`);
if (!isNodeJs) {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
});
}
function genBenchmarkCase(paramsContent) {
let suite = new Benchmark.Suite;
totalCaseNum = 0;
currentCaseId = 0;
if (/\(\w+,[\ ]*[0-9]+x[0-9]+,[\ ]*[0-9]+x[0-9]+\)/g.test(paramsContent.toString())) {
let params = paramsContent.toString().match(/\(\w+,[\ ]*[0-9]+x[0-9]+,[\ ]*[0-9]+x[0-9]+\)/g)[0];
decodeParams2Case(suite, params);
} else {
log("no filter or getting invalid params, run all the cases");
addResizeUpLinearCase(suite, combiUpLinear);
addResizeDownLinearCase(suite, combiDownLinear);
}
setBenchmarkSuite(suite);
log(`Running ${totalCaseNum} tests from Resize`);
suite.run({ 'async': true }); // run the benchmark
}
// init
let resizeFunc = [addResizeUpLinearCase, addResizeDownLinearCase];//, addResizeAreaFastCase];
let combinations = [combiUpLinear, combiDownLinear];//, combiAreaFast];
// set test filter params
if (isNodeJs) {
const args = process.argv.slice(2);
let paramsContent = '';
if (/--test_param_filter=\(\w+,[\ ]*[0-9]+x[0-9]+,[\ ]*[0-9]+x[0-9]+\)/g.test(args.toString())) {
paramsContent = args.toString().match(/\(\w+,[\ ]*[0-9]+x[0-9]+,[\ ]*[0-9]+x[0-9]+\)/g)[0];
}
genBenchmarkCase(paramsContent);
} else {
runButton.onclick = function() {
let paramsContent = paramsElement.value;
genBenchmarkCase(paramsContent);
if (totalCaseNum !== 0) {
runButton.setAttribute("disabled", "disabled");
runButton.setAttribute('class', 'btn btn-primary disabled');
runButton.innerHTML = "Running";
}
}
}
};

View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OpenCV.js Performance Test</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
body {
font-size: 13px;
}
.top-margin {
margin-top:10px;
}
h1, h4 {
margin: 24px 0 0;
}
h1 {
font-size: 2.0em;
}
h4 {
font-size: 1.2em;
}
pre {
font-family: 'Consolas', 'Monaco', monospace, serif;
font-size: 12px;
tab-size: 2;
}
input[type=checkbox] {
vertical-align: middle;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="row">
<div class="col-12">
<h1>OpenCV.js Performance Test</h1>
<div>
<h4>Modules</h4>
<h7>Image Processing</h7>
</div>
<div>
<h4>Kernels</h4>
<h7>Threshold</h7>
</div>
<div>
<h4>Parameters Filter</h4>
<input type="text" id="params" min="1" size="40" placeholder="default: run all the case"/> for example: (1920x1080, CV_8UC1, THRESH_BINARY)
</div>
<div class='row labels-wrapper' id='labelitem'></div>
<div class="row top-margin">
</div>
<div>
<button type="button" id="runButton" class="btn btn-primary disabled" disabled="disabled">Loading</button>
(It will take several minutes)</div>
<div class="row top-margin">
</div>
<div>
<pre id="log"></pre>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/platform/1.3.5/platform.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.4/benchmark.js"></script>
<script src="../../opencv.js" type="text/javascript"></script>
<script src="../base.js"></script>
<script src="../perf_helpfunc.js"></script>
<script src="./perf_threshold.js"></script>
</body>
</html>

View File

@@ -0,0 +1,217 @@
const isNodeJs = (typeof window) === 'undefined'? true : false;
if (isNodeJs) {
var Benchmark = require('benchmark');
var cv = require('../../opencv');
var HelpFunc = require('../perf_helpfunc');
var Base = require('../base');
} else {
var paramsElement = document.getElementById('params');
var runButton = document.getElementById('runButton');
var logElement = document.getElementById('log');
}
cv.onRuntimeInitialized = () => {
console.log('opencv.js loaded');
if (isNodeJs) {
global.cv = cv;
global.combine = HelpFunc.combine;
global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize;
global.cvSize = Base.cvSize;
} else {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
let totalCaseNum, currentCaseId;
const typicalMatSizes = [cvSize.szVGA, cvSize.sz720p, cvSize.sz1080p, cvSize.szODD];
const matTypes = ['CV_8UC1', 'CV_16SC1', 'CV_32FC1', 'CV_64FC1'];
const threshTypes = ['THRESH_BINARY', 'THRESH_BINARY_INV', 'THRESH_TRUNC', 'THRESH_TOZERO', 'THRESH_TOZERO_INV'];
const combiSizeMatTypeThreshType = combine(typicalMatSizes, matTypes, threshTypes);
const combiSizeOnly = combine(typicalMatSizes, ['CV_8UC1'], ['THRESH_BINARY|THRESH_OTSU']);
function addSizeMatTypeThreshTypeCase(suite, combination) {
totalCaseNum += combination.length;
for (let i = 0; i < combination.length; ++i) {
let matSize = combination[i][0];
let matType = combination[i][1];
let threshType = combination[i][2];
suite.add('threshold', function() {
cv.threshold(src, dst, threshold, thresholdMax, threshType);
}, {
'setup': function() {
let matSize = this.params.matSize;
let matType = cv[this.params.matType];
let threshType = cv[this.params.threshType];
let threshold = 127.0;
let thresholdMax = 210.0;
let src = new cv.Mat(matSize, matType);
let dst = new cv.Mat(matSize, matType);
let srcView = src.data;
srcView[0] = 0;
srcView[1] = 100;
srcView[2] = 200;
},
'teardown': function() {
src.delete();
dst.delete();
}
});
// set init params
let index = suite.length - 1;
suite[index].params = {
matSize: matSize,
matType: matType,
threshType: threshType
};
}
}
function addSizeOnlyCase(suite, combination) {
totalCaseNum += combination.length;
for (let i = 0; i < combination.length; ++i) {
let matSize = combination[i][0];
suite.add('threshold', function() {
cv.threshold(src, dst, threshold, thresholdMax, cv.THRESH_BINARY|cv.THRESH_OTSU);
}, {
'setup': function() {
let matSize = this.params.matSize;
let threshold = 127.0;
let thresholdMax = 210.0;
let src = new cv.Mat(matSize, cv.CV_8UC1);
let dst = new cv.Mat(matSize, cv.CV_8UC1);
let srcView = src.data;
srcView[0] = 0;
srcView[1] = 100;
srcView[2] = 200;
},
'teardown': function() {
src.delete();
dst.delete();
}
});
// set init params
let index = suite.length - 1;
suite[index].params = {
matSize: matSize,
matType: 'CV_8UC1',
threshType: 'THRESH_BINARY|THRESH_OTSU'
};
}
}
function decodeParams2Case(suite, params, isSizeOnly) {
let sizeString = params.match(/[0-9]+x[0-9]+/g).toString();
let sizes = sizeString.match(/[0-9]+/g);
let size1Str = sizes.slice(0, 2).toString();
let matSize = cvtStr2cvSize(size1Str);
let matType, threshType;
if (isSizeOnly) {
matType = 'CV_8UC1';
threshType = 'THRESH_BINARY|THRESH_OTSU';
} else {
matType = (params.match(/CV\_[0-9]+[A-z][A-z][0-9]/) || []).toString();
threshType = (params.match(/THRESH\_[A-z]+\_?[A-z]*/) || []).toString();
}
// check if the params match and add case
for (let i = 0; i < combinations.length; ++i) {
let combination = combinations[i];
for (let j = 0; j < combination.length; ++j) {
if (matSize === combination[j][0] && matType === combination[j][1] && threshType === combination[j][2]) {
thresholdFunc[i](suite, [combination[j]]);
}
}
}
}
function log(message) {
console.log(message);1
if (!isNodeJs) {
logElement.innerHTML += `\n${'\t'.repeat(1) + message}`;
}
}
function setBenchmarkSuite(suite) {
suite
// add listeners
.on('cycle', function(event) {
++currentCaseId;
let params = event.target.params;
let matSize = params.matSize;
let matType = params.matType;
let threshType = params.threshType;
log(`=== ${event.target.name} ${currentCaseId} ===`);
log(`params: (${parseInt(matSize.width)}x${parseInt(matSize.height)},`+
`${matType},${threshType})`);
log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms');
log('mean time:' +String(event.target.stats.mean*1000)+' ms');
log('stddev time:' +String(event.target.stats.deviation*1000)+' ms');
log(String(event.target));
})
.on('error', function(event) { log(`test case ${event.target.name} failed`); })
.on('complete', function(event) {
log(`\n ###################################`)
log(`Finished testing ${event.currentTarget.length} cases \n`);
if (!isNodeJs) {
runButton.removeAttribute('disabled');
runButton.setAttribute('class', 'btn btn-primary');
runButton.innerHTML = 'Run';
}
});
}
function genBenchmarkCase(paramsContent) {
let suite = new Benchmark.Suite;
totalCaseNum = 0;
currentCaseId = 0;
if (/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g.test(paramsContent.toString())) {
let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g)[0];
let isSizeOnly = 0;
decodeParams2Case(suite, params, isSizeOnly);
} else if (/[\ ]*[0-9]+x[0-9]+[\ ]*/g.test(paramsContent.toString())) {
let params = paramsContent.toString().match(/[\ ]*[0-9]+x[0-9]+[\ ]*/g)[0];
let isSizeOnly = 1;
decodeParams2Case(suite, params, isSizeOnly);
}
else {
log("no filter or getting invalid params, run all the cases");
addSizeMatTypeThreshTypeCase(suite, combiSizeMatTypeThreshType);
addSizeOnlyCase(suite, combiSizeOnly);
}
setBenchmarkSuite(suite);
log(`Running ${totalCaseNum} tests from Threshold`);
suite.run({ 'async': true }); // run the benchmark
}
// init
let thresholdFunc = [addSizeMatTypeThreshTypeCase, addSizeOnlyCase];
let combinations = [combiSizeMatTypeThreshType, combiSizeOnly];
// set test filter params
if (isNodeJs) {
const args = process.argv.slice(2);
let paramsContent = '';
if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g.test(args.toString())) {
paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g)[0];
} else if (/--test_param_filter=[\ ]*[0-9]+x[0-9]+[\ ]*/g.test(args.toString())) {
paramsContent = args.toString().match(/[\ ]*[0-9]+x[0-9]+[\ ]*/g)[0];
}
genBenchmarkCase(paramsContent);
} else {
runButton.onclick = function() {
let paramsContent = paramsElement.value;
genBenchmarkCase(paramsContent);
if (totalCaseNum !== 0) {
runButton.setAttribute("disabled", "disabled");
runButton.setAttribute('class', 'btn btn-primary disabled');
runButton.innerHTML = "Running";
}
}
}
};

View File

@@ -0,0 +1,16 @@
{
"extends": "google",
"parserOptions": {
"ecmaVersion": 6
},
"rules": {
"max-len": ["error", 100, {"ignoreUrls": true}],
"quotes": ["error", "single"],
"indent": ["error", 4, {"ArrayExpression": "first",
"CallExpression": {"arguments": "first"},
"SwitchCase": 1}],
"no-var": "off",
"prefer-rest-params": "off",
"require-jsdoc": "off"
}
}

View File

@@ -0,0 +1,745 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
/*M///////////////////////////////////////////////////////////////////////////////////////
// Author: Sajjad Taheri, University of California, Irvine. sajjadt[at]uci[dot]edu
//
// LICENSE AGREEMENT
// Copyright (c) 2015 The Regents of the University of California (Regents)
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the University nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//M*/
#include <emscripten/bind.h>
@INCLUDES@
#include "../../../modules/core/src/parallel_impl.hpp"
#ifdef TEST_WASM_INTRIN
#include "../../../modules/core/include/opencv2/core/hal/intrin.hpp"
#include "../../../modules/core/include/opencv2/core/utils/trace.hpp"
#include "../../../modules/ts/include/opencv2/ts/ts_gtest.h"
namespace cv {
namespace hal {
#include "../../../modules/core/test/test_intrin_utils.hpp"
}
}
#endif
using namespace emscripten;
using namespace cv;
#ifdef HAVE_OPENCV_DNN
using namespace dnn;
#endif
#ifdef HAVE_OPENCV_ARUCO
using namespace aruco;
#endif
namespace binding_utils
{
template<typename classT, typename enumT>
static inline typename std::underlying_type<enumT>::type classT::* underlying_ptr(enumT classT::* enum_ptr)
{
return reinterpret_cast<typename std::underlying_type<enumT>::type classT::*>(enum_ptr);
}
template<typename T>
emscripten::val matData(const cv::Mat& mat)
{
return emscripten::val(emscripten::memory_view<T>((mat.total()*mat.elemSize())/sizeof(T),
(T*)mat.data));
}
template<typename T>
emscripten::val matPtr(const cv::Mat& mat, int i)
{
return emscripten::val(emscripten::memory_view<T>(mat.step1(0), mat.ptr<T>(i)));
}
template<typename T>
emscripten::val matPtr(const cv::Mat& mat, int i, int j)
{
return emscripten::val(emscripten::memory_view<T>(mat.step1(1), mat.ptr<T>(i,j)));
}
cv::Mat* createMat(int rows, int cols, int type, intptr_t data, size_t step)
{
return new cv::Mat(rows, cols, type, reinterpret_cast<void*>(data), step);
}
static emscripten::val getMatSize(const cv::Mat& mat)
{
emscripten::val size = emscripten::val::array();
for (int i = 0; i < mat.dims; i++) {
size.call<void>("push", mat.size[i]);
}
return size;
}
static emscripten::val getMatStep(const cv::Mat& mat)
{
emscripten::val step = emscripten::val::array();
for (int i = 0; i < mat.dims; i++) {
step.call<void>("push", mat.step[i]);
}
return step;
}
static Mat matEye(int rows, int cols, int type)
{
return Mat(cv::Mat::eye(rows, cols, type));
}
static Mat matEye(Size size, int type)
{
return Mat(cv::Mat::eye(size, type));
}
void convertTo(const Mat& obj, Mat& m, int rtype, double alpha, double beta)
{
obj.convertTo(m, rtype, alpha, beta);
}
void convertTo(const Mat& obj, Mat& m, int rtype)
{
obj.convertTo(m, rtype);
}
void convertTo(const Mat& obj, Mat& m, int rtype, double alpha)
{
obj.convertTo(m, rtype, alpha);
}
Size matSize(const cv::Mat& mat)
{
return mat.size();
}
cv::Mat matZeros(int arg0, int arg1, int arg2)
{
return cv::Mat::zeros(arg0, arg1, arg2);
}
cv::Mat matZeros(cv::Size arg0, int arg1)
{
return cv::Mat::zeros(arg0,arg1);
}
cv::Mat matOnes(int arg0, int arg1, int arg2)
{
return cv::Mat::ones(arg0, arg1, arg2);
}
cv::Mat matOnes(cv::Size arg0, int arg1)
{
return cv::Mat::ones(arg0, arg1);
}
double matDot(const cv::Mat& obj, const Mat& mat)
{
return obj.dot(mat);
}
Mat matMul(const cv::Mat& obj, const Mat& mat, double scale)
{
return Mat(obj.mul(mat, scale));
}
Mat matT(const cv::Mat& obj)
{
return Mat(obj.t());
}
Mat matInv(const cv::Mat& obj, int type)
{
return Mat(obj.inv(type));
}
void matCopyTo(const cv::Mat& obj, cv::Mat& mat)
{
return obj.copyTo(mat);
}
void matCopyTo(const cv::Mat& obj, cv::Mat& mat, const cv::Mat& mask)
{
return obj.copyTo(mat, mask);
}
Mat matDiag(const cv::Mat& obj, int d)
{
return obj.diag(d);
}
Mat matDiag(const cv::Mat& obj)
{
return obj.diag();
}
void matSetTo(cv::Mat& obj, const cv::Scalar& s)
{
obj.setTo(s);
}
void matSetTo(cv::Mat& obj, const cv::Scalar& s, const cv::Mat& mask)
{
obj.setTo(s, mask);
}
emscripten::val rotatedRectPoints(const cv::RotatedRect& obj)
{
cv::Point2f points[4];
obj.points(points);
emscripten::val pointsArray = emscripten::val::array();
for (int i = 0; i < 4; i++) {
pointsArray.call<void>("push", points[i]);
}
return pointsArray;
}
Rect rotatedRectBoundingRect(const cv::RotatedRect& obj)
{
return obj.boundingRect();
}
Rect2f rotatedRectBoundingRect2f(const cv::RotatedRect& obj)
{
return obj.boundingRect2f();
}
int cvMatDepth(int flags)
{
return CV_MAT_DEPTH(flags);
}
class MinMaxLoc
{
public:
double minVal;
double maxVal;
Point minLoc;
Point maxLoc;
};
MinMaxLoc minMaxLoc(const cv::Mat& src, const cv::Mat& mask)
{
MinMaxLoc result;
cv::minMaxLoc(src, &result.minVal, &result.maxVal, &result.minLoc, &result.maxLoc, mask);
return result;
}
MinMaxLoc minMaxLoc_1(const cv::Mat& src)
{
MinMaxLoc result;
cv::minMaxLoc(src, &result.minVal, &result.maxVal, &result.minLoc, &result.maxLoc);
return result;
}
class Circle
{
public:
Point2f center;
float radius;
};
#ifdef HAVE_OPENCV_IMGPROC
Circle minEnclosingCircle(const cv::Mat& points)
{
Circle circle;
cv::minEnclosingCircle(points, circle.center, circle.radius);
return circle;
}
int floodFill_withRect_helper(cv::Mat& arg1, cv::Mat& arg2, Point arg3, Scalar arg4, emscripten::val arg5, Scalar arg6 = Scalar(), Scalar arg7 = Scalar(), int arg8 = 4)
{
cv::Rect rect;
int rc = cv::floodFill(arg1, arg2, arg3, arg4, &rect, arg6, arg7, arg8);
arg5.set("x", emscripten::val(rect.x));
arg5.set("y", emscripten::val(rect.y));
arg5.set("width", emscripten::val(rect.width));
arg5.set("height", emscripten::val(rect.height));
return rc;
}
int floodFill_wrapper(cv::Mat& arg1, cv::Mat& arg2, Point arg3, Scalar arg4, emscripten::val arg5, Scalar arg6, Scalar arg7, int arg8) {
return floodFill_withRect_helper(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
int floodFill_wrapper_1(cv::Mat& arg1, cv::Mat& arg2, Point arg3, Scalar arg4, emscripten::val arg5, Scalar arg6, Scalar arg7) {
return floodFill_withRect_helper(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
int floodFill_wrapper_2(cv::Mat& arg1, cv::Mat& arg2, Point arg3, Scalar arg4, emscripten::val arg5, Scalar arg6) {
return floodFill_withRect_helper(arg1, arg2, arg3, arg4, arg5, arg6);
}
int floodFill_wrapper_3(cv::Mat& arg1, cv::Mat& arg2, Point arg3, Scalar arg4, emscripten::val arg5) {
return floodFill_withRect_helper(arg1, arg2, arg3, arg4, arg5);
}
int floodFill_wrapper_4(cv::Mat& arg1, cv::Mat& arg2, Point arg3, Scalar arg4) {
return cv::floodFill(arg1, arg2, arg3, arg4);
}
#endif
#ifdef HAVE_OPENCV_VIDEO
emscripten::val CamShiftWrapper(const cv::Mat& arg1, Rect& arg2, TermCriteria arg3)
{
RotatedRect rotatedRect = cv::CamShift(arg1, arg2, arg3);
emscripten::val result = emscripten::val::array();
result.call<void>("push", rotatedRect);
result.call<void>("push", arg2);
return result;
}
emscripten::val meanShiftWrapper(const cv::Mat& arg1, Rect& arg2, TermCriteria arg3)
{
int n = cv::meanShift(arg1, arg2, arg3);
emscripten::val result = emscripten::val::array();
result.call<void>("push", n);
result.call<void>("push", arg2);
return result;
}
#endif // HAVE_OPENCV_VIDEO
std::string getExceptionMsg(const cv::Exception& e) {
return e.msg;
}
void setExceptionMsg(cv::Exception& e, std::string msg) {
e.msg = msg;
return;
}
cv::Exception exceptionFromPtr(intptr_t ptr) {
return *reinterpret_cast<cv::Exception*>(ptr);
}
std::string getBuildInformation() {
return cv::getBuildInformation();
}
#ifdef TEST_WASM_INTRIN
void test_hal_intrin_uint8() {
cv::hal::test_hal_intrin_uint8();
}
void test_hal_intrin_int8() {
cv::hal::test_hal_intrin_int8();
}
void test_hal_intrin_uint16() {
cv::hal::test_hal_intrin_uint16();
}
void test_hal_intrin_int16() {
cv::hal::test_hal_intrin_int16();
}
void test_hal_intrin_uint32() {
cv::hal::test_hal_intrin_uint32();
}
void test_hal_intrin_int32() {
cv::hal::test_hal_intrin_int32();
}
void test_hal_intrin_uint64() {
cv::hal::test_hal_intrin_uint64();
}
void test_hal_intrin_int64() {
cv::hal::test_hal_intrin_int64();
}
void test_hal_intrin_float32() {
cv::hal::test_hal_intrin_float32();
}
void test_hal_intrin_float64() {
cv::hal::test_hal_intrin_float64();
}
void test_hal_intrin_all() {
cv::hal::test_hal_intrin_uint8();
cv::hal::test_hal_intrin_int8();
cv::hal::test_hal_intrin_uint16();
cv::hal::test_hal_intrin_int16();
cv::hal::test_hal_intrin_uint32();
cv::hal::test_hal_intrin_int32();
cv::hal::test_hal_intrin_uint64();
cv::hal::test_hal_intrin_int64();
cv::hal::test_hal_intrin_float32();
cv::hal::test_hal_intrin_float64();
}
#endif
}
EMSCRIPTEN_BINDINGS(binding_utils)
{
register_vector<int>("IntVector");
register_vector<float>("FloatVector");
register_vector<double>("DoubleVector");
register_vector<cv::Point>("PointVector");
register_vector<cv::Mat>("MatVector");
register_vector<cv::Rect>("RectVector");
register_vector<cv::KeyPoint>("KeyPointVector");
register_vector<cv::DMatch>("DMatchVector");
register_vector<std::vector<cv::DMatch>>("DMatchVectorVector");
emscripten::class_<cv::Mat>("Mat")
.constructor<>()
.constructor<const Mat&>()
.constructor<Size, int>()
.constructor<int, int, int>()
.constructor<int, int, int, const Scalar&>()
.constructor(&binding_utils::createMat, allow_raw_pointers())
.class_function("eye", select_overload<Mat(Size, int)>(&binding_utils::matEye))
.class_function("eye", select_overload<Mat(int, int, int)>(&binding_utils::matEye))
.class_function("ones", select_overload<Mat(Size, int)>(&binding_utils::matOnes))
.class_function("ones", select_overload<Mat(int, int, int)>(&binding_utils::matOnes))
.class_function("zeros", select_overload<Mat(Size, int)>(&binding_utils::matZeros))
.class_function("zeros", select_overload<Mat(int, int, int)>(&binding_utils::matZeros))
.property("rows", &cv::Mat::rows)
.property("cols", &cv::Mat::cols)
.property("matSize", &binding_utils::getMatSize)
.property("step", &binding_utils::getMatStep)
.property("data", &binding_utils::matData<unsigned char>)
.property("data8S", &binding_utils::matData<char>)
.property("data16U", &binding_utils::matData<unsigned short>)
.property("data16S", &binding_utils::matData<short>)
.property("data32S", &binding_utils::matData<int>)
.property("data32F", &binding_utils::matData<float>)
.property("data64F", &binding_utils::matData<double>)
.function("elemSize", select_overload<size_t()const>(&cv::Mat::elemSize))
.function("elemSize1", select_overload<size_t()const>(&cv::Mat::elemSize1))
.function("channels", select_overload<int()const>(&cv::Mat::channels))
.function("convertTo", select_overload<void(const Mat&, Mat&, int, double, double)>(&binding_utils::convertTo))
.function("convertTo", select_overload<void(const Mat&, Mat&, int)>(&binding_utils::convertTo))
.function("convertTo", select_overload<void(const Mat&, Mat&, int, double)>(&binding_utils::convertTo))
.function("total", select_overload<size_t()const>(&cv::Mat::total))
.function("row", select_overload<Mat(int)const>(&cv::Mat::row))
.function("create", select_overload<void(int, int, int)>(&cv::Mat::create))
.function("create", select_overload<void(Size, int)>(&cv::Mat::create))
.function("rowRange", select_overload<Mat(int, int)const>(&cv::Mat::rowRange))
.function("rowRange", select_overload<Mat(const Range&)const>(&cv::Mat::rowRange))
.function("copyTo", select_overload<void(const Mat&, Mat&)>(&binding_utils::matCopyTo))
.function("copyTo", select_overload<void(const Mat&, Mat&, const Mat&)>(&binding_utils::matCopyTo))
.function("type", select_overload<int()const>(&cv::Mat::type))
.function("empty", select_overload<bool()const>(&cv::Mat::empty))
.function("colRange", select_overload<Mat(int, int)const>(&cv::Mat::colRange))
.function("colRange", select_overload<Mat(const Range&)const>(&cv::Mat::colRange))
.function("step1", select_overload<size_t(int)const>(&cv::Mat::step1))
.function("clone", select_overload<Mat()const>(&cv::Mat::clone))
.function("depth", select_overload<int()const>(&cv::Mat::depth))
.function("col", select_overload<Mat(int)const>(&cv::Mat::col))
.function("dot", select_overload<double(const Mat&, const Mat&)>(&binding_utils::matDot))
.function("mul", select_overload<Mat(const Mat&, const Mat&, double)>(&binding_utils::matMul))
.function("inv", select_overload<Mat(const Mat&, int)>(&binding_utils::matInv))
.function("t", select_overload<Mat(const Mat&)>(&binding_utils::matT))
.function("roi", select_overload<Mat(const Rect&)const>(&cv::Mat::operator()))
.function("diag", select_overload<Mat(const Mat&, int)>(&binding_utils::matDiag))
.function("diag", select_overload<Mat(const Mat&)>(&binding_utils::matDiag))
.function("isContinuous", select_overload<bool()const>(&cv::Mat::isContinuous))
.function("setTo", select_overload<void(Mat&, const Scalar&)>(&binding_utils::matSetTo))
.function("setTo", select_overload<void(Mat&, const Scalar&, const Mat&)>(&binding_utils::matSetTo))
.function("size", select_overload<Size(const Mat&)>(&binding_utils::matSize))
.function("ptr", select_overload<val(const Mat&, int)>(&binding_utils::matPtr<unsigned char>))
.function("ptr", select_overload<val(const Mat&, int, int)>(&binding_utils::matPtr<unsigned char>))
.function("ucharPtr", select_overload<val(const Mat&, int)>(&binding_utils::matPtr<unsigned char>))
.function("ucharPtr", select_overload<val(const Mat&, int, int)>(&binding_utils::matPtr<unsigned char>))
.function("charPtr", select_overload<val(const Mat&, int)>(&binding_utils::matPtr<char>))
.function("charPtr", select_overload<val(const Mat&, int, int)>(&binding_utils::matPtr<char>))
.function("shortPtr", select_overload<val(const Mat&, int)>(&binding_utils::matPtr<short>))
.function("shortPtr", select_overload<val(const Mat&, int, int)>(&binding_utils::matPtr<short>))
.function("ushortPtr", select_overload<val(const Mat&, int)>(&binding_utils::matPtr<unsigned short>))
.function("ushortPtr", select_overload<val(const Mat&, int, int)>(&binding_utils::matPtr<unsigned short>))
.function("intPtr", select_overload<val(const Mat&, int)>(&binding_utils::matPtr<int>))
.function("intPtr", select_overload<val(const Mat&, int, int)>(&binding_utils::matPtr<int>))
.function("floatPtr", select_overload<val(const Mat&, int)>(&binding_utils::matPtr<float>))
.function("floatPtr", select_overload<val(const Mat&, int, int)>(&binding_utils::matPtr<float>))
.function("doublePtr", select_overload<val(const Mat&, int)>(&binding_utils::matPtr<double>))
.function("doublePtr", select_overload<val(const Mat&, int, int)>(&binding_utils::matPtr<double>))
.function("charAt", select_overload<char&(int)>(&cv::Mat::at<char>))
.function("charAt", select_overload<char&(int, int)>(&cv::Mat::at<char>))
.function("charAt", select_overload<char&(int, int, int)>(&cv::Mat::at<char>))
.function("ucharAt", select_overload<unsigned char&(int)>(&cv::Mat::at<unsigned char>))
.function("ucharAt", select_overload<unsigned char&(int, int)>(&cv::Mat::at<unsigned char>))
.function("ucharAt", select_overload<unsigned char&(int, int, int)>(&cv::Mat::at<unsigned char>))
.function("shortAt", select_overload<short&(int)>(&cv::Mat::at<short>))
.function("shortAt", select_overload<short&(int, int)>(&cv::Mat::at<short>))
.function("shortAt", select_overload<short&(int, int, int)>(&cv::Mat::at<short>))
.function("ushortAt", select_overload<unsigned short&(int)>(&cv::Mat::at<unsigned short>))
.function("ushortAt", select_overload<unsigned short&(int, int)>(&cv::Mat::at<unsigned short>))
.function("ushortAt", select_overload<unsigned short&(int, int, int)>(&cv::Mat::at<unsigned short>))
.function("intAt", select_overload<int&(int)>(&cv::Mat::at<int>) )
.function("intAt", select_overload<int&(int, int)>(&cv::Mat::at<int>) )
.function("intAt", select_overload<int&(int, int, int)>(&cv::Mat::at<int>) )
.function("floatAt", select_overload<float&(int)>(&cv::Mat::at<float>))
.function("floatAt", select_overload<float&(int, int)>(&cv::Mat::at<float>))
.function("floatAt", select_overload<float&(int, int, int)>(&cv::Mat::at<float>))
.function("doubleAt", select_overload<double&(int, int, int)>(&cv::Mat::at<double>))
.function("doubleAt", select_overload<double&(int)>(&cv::Mat::at<double>))
.function("doubleAt", select_overload<double&(int, int)>(&cv::Mat::at<double>));
emscripten::value_object<cv::Range>("Range")
.field("start", &cv::Range::start)
.field("end", &cv::Range::end);
emscripten::value_object<cv::TermCriteria>("TermCriteria")
.field("type", &cv::TermCriteria::type)
.field("maxCount", &cv::TermCriteria::maxCount)
.field("epsilon", &cv::TermCriteria::epsilon);
#define EMSCRIPTEN_CV_SIZE(type) \
emscripten::value_object<type>("#type") \
.field("width", &type::width) \
.field("height", &type::height);
EMSCRIPTEN_CV_SIZE(Size)
EMSCRIPTEN_CV_SIZE(Size2f)
#define EMSCRIPTEN_CV_POINT(type) \
emscripten::value_object<type>("#type") \
.field("x", &type::x) \
.field("y", &type::y); \
EMSCRIPTEN_CV_POINT(Point)
EMSCRIPTEN_CV_POINT(Point2f)
#define EMSCRIPTEN_CV_RECT(type, name) \
emscripten::value_object<cv::Rect_<type>> (name) \
.field("x", &cv::Rect_<type>::x) \
.field("y", &cv::Rect_<type>::y) \
.field("width", &cv::Rect_<type>::width) \
.field("height", &cv::Rect_<type>::height);
EMSCRIPTEN_CV_RECT(int, "Rect")
EMSCRIPTEN_CV_RECT(float, "Rect2f")
emscripten::value_object<cv::RotatedRect>("RotatedRect")
.field("center", &cv::RotatedRect::center)
.field("size", &cv::RotatedRect::size)
.field("angle", &cv::RotatedRect::angle);
function("rotatedRectPoints", select_overload<emscripten::val(const cv::RotatedRect&)>(&binding_utils::rotatedRectPoints));
function("rotatedRectBoundingRect", select_overload<Rect(const cv::RotatedRect&)>(&binding_utils::rotatedRectBoundingRect));
function("rotatedRectBoundingRect2f", select_overload<Rect2f(const cv::RotatedRect&)>(&binding_utils::rotatedRectBoundingRect2f));
emscripten::value_object<cv::KeyPoint>("KeyPoint")
.field("angle", &cv::KeyPoint::angle)
.field("class_id", &cv::KeyPoint::class_id)
.field("octave", &cv::KeyPoint::octave)
.field("pt", &cv::KeyPoint::pt)
.field("response", &cv::KeyPoint::response)
.field("size", &cv::KeyPoint::size);
emscripten::value_object<cv::DMatch>("DMatch")
.field("queryIdx", &cv::DMatch::queryIdx)
.field("trainIdx", &cv::DMatch::trainIdx)
.field("imgIdx", &cv::DMatch::imgIdx)
.field("distance", &cv::DMatch::distance);
emscripten::value_array<cv::Scalar_<double>> ("Scalar")
.element(emscripten::index<0>())
.element(emscripten::index<1>())
.element(emscripten::index<2>())
.element(emscripten::index<3>());
emscripten::value_object<binding_utils::MinMaxLoc>("MinMaxLoc")
.field("minVal", &binding_utils::MinMaxLoc::minVal)
.field("maxVal", &binding_utils::MinMaxLoc::maxVal)
.field("minLoc", &binding_utils::MinMaxLoc::minLoc)
.field("maxLoc", &binding_utils::MinMaxLoc::maxLoc);
emscripten::value_object<binding_utils::Circle>("Circle")
.field("center", &binding_utils::Circle::center)
.field("radius", &binding_utils::Circle::radius);
emscripten::value_object<cv::Moments >("Moments")
.field("m00", &cv::Moments::m00)
.field("m10", &cv::Moments::m10)
.field("m01", &cv::Moments::m01)
.field("m20", &cv::Moments::m20)
.field("m11", &cv::Moments::m11)
.field("m02", &cv::Moments::m02)
.field("m30", &cv::Moments::m30)
.field("m21", &cv::Moments::m21)
.field("m12", &cv::Moments::m12)
.field("m03", &cv::Moments::m03)
.field("mu20", &cv::Moments::mu20)
.field("mu11", &cv::Moments::mu11)
.field("mu02", &cv::Moments::mu02)
.field("mu30", &cv::Moments::mu30)
.field("mu21", &cv::Moments::mu21)
.field("mu12", &cv::Moments::mu12)
.field("mu03", &cv::Moments::mu03)
.field("nu20", &cv::Moments::nu20)
.field("nu11", &cv::Moments::nu11)
.field("nu02", &cv::Moments::nu02)
.field("nu30", &cv::Moments::nu30)
.field("nu21", &cv::Moments::nu21)
.field("nu12", &cv::Moments::nu12)
.field("nu03", &cv::Moments::nu03);
emscripten::value_object<cv::Exception>("Exception")
.field("code", &cv::Exception::code)
.field("msg", &binding_utils::getExceptionMsg, &binding_utils::setExceptionMsg);
function("exceptionFromPtr", &binding_utils::exceptionFromPtr, allow_raw_pointers());
#ifdef HAVE_OPENCV_IMGPROC
function("minEnclosingCircle", select_overload<binding_utils::Circle(const cv::Mat&)>(&binding_utils::minEnclosingCircle));
function("floodFill", select_overload<int(cv::Mat&, cv::Mat&, Point, Scalar, emscripten::val, Scalar, Scalar, int)>(&binding_utils::floodFill_wrapper));
function("floodFill", select_overload<int(cv::Mat&, cv::Mat&, Point, Scalar, emscripten::val, Scalar, Scalar)>(&binding_utils::floodFill_wrapper_1));
function("floodFill", select_overload<int(cv::Mat&, cv::Mat&, Point, Scalar, emscripten::val, Scalar)>(&binding_utils::floodFill_wrapper_2));
function("floodFill", select_overload<int(cv::Mat&, cv::Mat&, Point, Scalar, emscripten::val)>(&binding_utils::floodFill_wrapper_3));
function("floodFill", select_overload<int(cv::Mat&, cv::Mat&, Point, Scalar)>(&binding_utils::floodFill_wrapper_4));
#endif
function("minMaxLoc", select_overload<binding_utils::MinMaxLoc(const cv::Mat&, const cv::Mat&)>(&binding_utils::minMaxLoc));
function("minMaxLoc", select_overload<binding_utils::MinMaxLoc(const cv::Mat&)>(&binding_utils::minMaxLoc_1));
#ifdef HAVE_OPENCV_IMGPROC
function("morphologyDefaultBorderValue", &cv::morphologyDefaultBorderValue);
#endif
function("CV_MAT_DEPTH", &binding_utils::cvMatDepth);
#ifdef HAVE_OPENCV_VIDEO
function("CamShift", select_overload<emscripten::val(const cv::Mat&, Rect&, TermCriteria)>(&binding_utils::CamShiftWrapper));
function("meanShift", select_overload<emscripten::val(const cv::Mat&, Rect&, TermCriteria)>(&binding_utils::meanShiftWrapper));
#endif
function("getBuildInformation", &binding_utils::getBuildInformation);
#ifdef HAVE_PTHREADS_PF
function("parallel_pthreads_set_threads_num", &cv::parallel_pthreads_set_threads_num);
function("parallel_pthreads_get_threads_num", &cv::parallel_pthreads_get_threads_num);
#endif
#ifdef TEST_WASM_INTRIN
function("test_hal_intrin_uint8", &binding_utils::test_hal_intrin_uint8);
function("test_hal_intrin_int8", &binding_utils::test_hal_intrin_int8);
function("test_hal_intrin_uint16", &binding_utils::test_hal_intrin_uint16);
function("test_hal_intrin_int16", &binding_utils::test_hal_intrin_int16);
function("test_hal_intrin_uint32", &binding_utils::test_hal_intrin_uint32);
function("test_hal_intrin_int32", &binding_utils::test_hal_intrin_int32);
function("test_hal_intrin_uint64", &binding_utils::test_hal_intrin_uint64);
function("test_hal_intrin_int64", &binding_utils::test_hal_intrin_int64);
function("test_hal_intrin_float32", &binding_utils::test_hal_intrin_float32);
function("test_hal_intrin_float64", &binding_utils::test_hal_intrin_float64);
function("test_hal_intrin_all", &binding_utils::test_hal_intrin_all);
#endif
constant("CV_8UC1", CV_8UC1);
constant("CV_8UC2", CV_8UC2);
constant("CV_8UC3", CV_8UC3);
constant("CV_8UC4", CV_8UC4);
constant("CV_8SC1", CV_8SC1);
constant("CV_8SC2", CV_8SC2);
constant("CV_8SC3", CV_8SC3);
constant("CV_8SC4", CV_8SC4);
constant("CV_16UC1", CV_16UC1);
constant("CV_16UC2", CV_16UC2);
constant("CV_16UC3", CV_16UC3);
constant("CV_16UC4", CV_16UC4);
constant("CV_16SC1", CV_16SC1);
constant("CV_16SC2", CV_16SC2);
constant("CV_16SC3", CV_16SC3);
constant("CV_16SC4", CV_16SC4);
constant("CV_32SC1", CV_32SC1);
constant("CV_32SC2", CV_32SC2);
constant("CV_32SC3", CV_32SC3);
constant("CV_32SC4", CV_32SC4);
constant("CV_32FC1", CV_32FC1);
constant("CV_32FC2", CV_32FC2);
constant("CV_32FC3", CV_32FC3);
constant("CV_32FC4", CV_32FC4);
constant("CV_64FC1", CV_64FC1);
constant("CV_64FC2", CV_64FC2);
constant("CV_64FC3", CV_64FC3);
constant("CV_64FC4", CV_64FC4);
constant("CV_8U", CV_8U);
constant("CV_8S", CV_8S);
constant("CV_16U", CV_16U);
constant("CV_16S", CV_16S);
constant("CV_32S", CV_32S);
constant("CV_32F", CV_32F);
constant("CV_64F", CV_64F);
constant("INT_MIN", INT_MIN);
constant("INT_MAX", INT_MAX);
}

View File

@@ -0,0 +1,912 @@
###############################################################################
#
# IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
#
# By downloading, copying, installing or using the software you agree to this license.
# If you do not agree to this license, do not download, install,
# copy or use the software.
#
#
# License Agreement
# For Open Source Computer Vision Library
#
# Copyright (C) 2013, OpenCV Foundation, all rights reserved.
# Third party copyrights are property of their respective owners.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistribution's of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistribution's in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * The name of the copyright holders may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# This software is provided by the copyright holders and contributors "as is" and
# any express or implied warranties, including, but not limited to, the implied
# warranties of merchantability and fitness for a particular purpose are disclaimed.
# In no event shall the Intel Corporation or contributors be liable for any direct,
# indirect, incidental, special, exemplary, or consequential damages
# (including, but not limited to, procurement of substitute goods or services;
# loss of use, data, or profits; or business interruption) however caused
# and on any theory of liability, whether in contract, strict liability,
# or tort (including negligence or otherwise) arising in any way out of
# the use of this software, even if advised of the possibility of such damage.
#
###############################################################################
# AUTHOR: Sajjad Taheri, University of California, Irvine. sajjadt[at]uci[dot]edu
#
# LICENSE AGREEMENT
# Copyright (c) 2015, 2015 The Regents of the University of California (Regents)
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the University nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
###############################################################################
from __future__ import print_function
import sys, re, os
from templates import *
if sys.version_info[0] >= 3:
from io import StringIO
else:
from cStringIO import StringIO
func_table = {}
# Ignore these functions due to Embind limitations for now
ignore_list = ['locate', #int&
'minEnclosingCircle', #float&
'checkRange',
'minMaxLoc', #double*
'floodFill', # special case, implemented in core_bindings.cpp
'phaseCorrelate',
'randShuffle',
'calibrationMatrixValues', #double&
'undistortPoints', # global redefinition
'CamShift', #Rect&
'meanShift' #Rect&
]
def makeWhiteList(module_list):
wl = {}
for m in module_list:
for k in m.keys():
if k in wl:
wl[k] += m[k]
else:
wl[k] = m[k]
return wl
white_list = None
exec(open(os.environ["OPENCV_JS_WHITELIST"]).read())
assert(white_list)
# Features to be exported
export_enums = False
export_consts = True
with_wrapped_functions = True
with_default_params = True
with_vec_from_js_array = True
wrapper_namespace = "Wrappers"
type_dict = {
'InputArray': 'const cv::Mat&',
'OutputArray': 'cv::Mat&',
'InputOutputArray': 'cv::Mat&',
'InputArrayOfArrays': 'const std::vector<cv::Mat>&',
'OutputArrayOfArrays': 'std::vector<cv::Mat>&',
'String': 'std::string',
'const String&':'const std::string&'
}
def normalize_class_name(name):
return re.sub(r"^cv\.", "", name).replace(".", "_")
class ClassProp(object):
def __init__(self, decl):
self.tp = decl[0].replace("*", "_ptr").strip()
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.cname = name.replace(".", "::")
self.name = self.wname = normalize_class_name(name)
self.ismap = False
self.issimple = False
self.isalgorithm = False
self.methods = {}
self.ext_constructors = {}
self.props = []
self.consts = {}
customname = False
self.jsfuncs = {}
self.constructor_arg_num = set()
self.has_smart_ptr = False
if decl:
self.bases = decl[1].split()[1:]
if len(self.bases) > 1:
self.bases = [self.bases[0].strip(",")]
# return sys.exit(-1)
if self.bases and self.bases[0].startswith("cv::"):
self.bases[0] = self.bases[0][4:]
if self.bases and self.bases[0] == "Algorithm":
self.isalgorithm = True
for m in decl[2]:
if m.startswith("="):
self.wname = m[1:]
customname = True
elif m == "/Map":
self.ismap = True
elif m == "/Simple":
self.issimple = True
self.props = [ClassProp(p) for p in decl[3]]
if not customname and self.wname.startswith("Cv"):
self.wname = self.wname[2:]
def handle_ptr(tp):
if tp.startswith('Ptr_'):
tp = 'Ptr<' + "::".join(tp.split('_')[1:]) + '>'
return tp
def handle_vector(tp):
if tp.startswith('vector_'):
tp = handle_vector(tp[tp.find('_') + 1:])
tp = 'std::vector<' + "::".join(tp.split('_')) + '>'
return tp
class ArgInfo(object):
def __init__(self, arg_tuple):
self.tp = handle_ptr(arg_tuple[0]).strip()
self.name = arg_tuple[1]
self.defval = arg_tuple[2]
self.isarray = False
self.arraylen = 0
self.arraycvt = None
self.inputarg = True
self.outputarg = False
self.returnarg = False
self.const = False
self.reference = False
for m in arg_tuple[3]:
if m == "/O":
self.inputarg = False
self.outputarg = True
self.returnarg = True
elif m == "/IO":
self.inputarg = True
self.outputarg = True
self.returnarg = True
elif m.startswith("/A"):
self.isarray = True
self.arraylen = m[2:].strip()
elif m.startswith("/CA"):
self.isarray = True
self.arraycvt = m[2:].strip()
elif m == "/C":
self.const = True
elif m == "/Ref":
self.reference = True
if self.tp == "Mat":
if self.outputarg:
self.tp = "cv::Mat&"
elif self.inputarg:
self.tp = "const cv::Mat&"
if self.tp == "vector_Mat":
if self.outputarg:
self.tp = "std::vector<cv::Mat>&"
elif self.inputarg:
self.tp = "const std::vector<cv::Mat>&"
self.tp = handle_vector(self.tp).strip()
if self.const:
self.tp = "const " + self.tp
if self.reference:
self.tp = self.tp + "&"
self.py_inputarg = False
self.py_outputarg = False
class FuncVariant(object):
def __init__(self, class_name, name, decl, is_constructor, is_class_method, is_const, is_virtual, is_pure_virtual, ref_return, const_return):
self.class_name = class_name
self.name = self.wname = name
self.is_constructor = is_constructor
self.is_class_method = is_class_method
self.is_const = is_const
self.is_virtual = is_virtual
self.is_pure_virtual = is_pure_virtual
self.refret = ref_return
self.constret = const_return
self.rettype = handle_vector(handle_ptr(decl[1]).strip()).strip()
if self.rettype == "void":
self.rettype = ""
self.args = []
self.array_counters = {}
for a in decl[3]:
ainfo = ArgInfo(a)
if ainfo.isarray and not ainfo.arraycvt:
c = ainfo.arraylen
c_arrlist = self.array_counters.get(c, [])
if c_arrlist:
c_arrlist.append(ainfo.name)
else:
self.array_counters[c] = [ainfo.name]
self.args.append(ainfo)
class FuncInfo(object):
def __init__(self, class_name, name, cname, namespace, isconstructor):
self.class_name = class_name
self.name = name
self.cname = cname
self.namespace = namespace
self.variants = []
self.is_constructor = isconstructor
def add_variant(self, variant):
self.variants.append(variant)
class Namespace(object):
def __init__(self):
self.funcs = {}
self.enums = {}
self.consts = {}
class JSWrapperGenerator(object):
def __init__(self):
self.bindings = []
self.wrapper_funcs = []
self.classes = {}
self.namespaces = {}
self.enums = {}
self.parser = hdr_parser.CppHeaderParser()
self.class_idx = 0
def add_class(self, stype, name, decl):
class_info = ClassInfo(name, decl)
class_info.decl_idx = self.class_idx
self.class_idx += 1
if class_info.name in self.classes:
print("Generator error: class %s (cpp_name=%s) already exists" \
% (class_info.name, class_info.cname))
sys.exit(-1)
self.classes[class_info.name] = class_info
if class_info.bases:
chunks = class_info.bases[0].split('::')
base = '_'.join(chunks)
while base not in self.classes and len(chunks) > 1:
del chunks[-2]
base = '_'.join(chunks)
if base not in self.classes:
print("Generator error: unable to resolve base %s for %s"
% (class_info.bases[0], class_info.name))
sys.exit(-1)
else:
class_info.bases[0] = "::".join(chunks)
class_info.isalgorithm |= self.classes[base].isalgorithm
def split_decl_name(self, name):
chunks = name.split('.')
namespace = chunks[:-1]
classes = []
while namespace and '.'.join(namespace) not in self.parser.namespaces:
classes.insert(0, namespace.pop())
return namespace, classes, chunks[-1]
def add_enum(self, decl):
name = decl[0].rsplit(" ", 1)[1]
namespace, classes, val = self.split_decl_name(name)
namespace = '.'.join(namespace)
ns = self.namespaces.setdefault(namespace, Namespace())
if len(name) == 0: name = "<unnamed>"
if name.endswith("<unnamed>"):
i = 0
while True:
i += 1
candidate_name = name.replace("<unnamed>", "unnamed_%u" % i)
if candidate_name not in ns.enums:
name = candidate_name
break;
cname = name.replace('.', '::')
type_dict[normalize_class_name(name)] = cname
if name in ns.enums:
print("Generator warning: enum %s (cname=%s) already exists" \
% (name, cname))
# sys.exit(-1)
else:
ns.enums[name] = []
for item in decl[3]:
ns.enums[name].append(item)
const_decls = decl[3]
for decl in const_decls:
name = decl[0]
self.add_const(name.replace("const ", "").strip(), decl)
def add_const(self, name, decl):
cname = name.replace('.','::')
namespace, classes, name = self.split_decl_name(name)
namespace = '.'.join(namespace)
name = '_'.join(classes+[name])
ns = self.namespaces.setdefault(namespace, Namespace())
if name in ns.consts:
print("Generator error: constant %s (cname=%s) already exists" \
% (name, cname))
sys.exit(-1)
ns.consts[name] = cname
def add_func(self, decl):
namespace, classes, barename = self.split_decl_name(decl[0])
cpp_name = "::".join(namespace + classes + [barename])
name = barename
class_name = ''
bare_class_name = ''
if classes:
class_name = normalize_class_name('.'.join(namespace + classes))
bare_class_name = classes[-1]
namespace = '.'.join(namespace)
is_constructor = name == bare_class_name
is_class_method = False
is_const_method = False
is_virtual_method = False
is_pure_virtual_method = False
const_return = False
ref_return = False
for m in decl[2]:
if m == "/S":
is_class_method = True
elif m == "/C":
is_const_method = True
elif m == "/V":
is_virtual_method = True
elif m == "/PV":
is_pure_virtual_method = True
elif m == "/Ref":
ref_return = True
elif m == "/CRet":
const_return = True
elif m.startswith("="):
name = m[1:]
if class_name:
cpp_name = barename
func_map = self.classes[class_name].methods
else:
func_map = self.namespaces.setdefault(namespace, Namespace()).funcs
func = func_map.setdefault(name, FuncInfo(class_name, name, cpp_name, namespace, is_constructor))
variant = FuncVariant(class_name, name, decl, is_constructor, is_class_method, is_const_method,
is_virtual_method, is_pure_virtual_method, ref_return, const_return)
func.add_variant(variant)
def save(self, path, name, buf):
f = open(path + "/" + name, "wt")
f.write(buf.getvalue())
f.close()
def gen_function_binding_with_wrapper(self, func, class_info):
binding_text = None
wrapper_func_text = None
bindings = []
wrappers = []
for index, variant in enumerate(func.variants):
factory = False
if class_info and 'Ptr<' in variant.rettype:
factory = True
base_class_name = variant.rettype
base_class_name = base_class_name.replace("Ptr<","").replace(">","").strip()
if base_class_name in self.classes:
self.classes[base_class_name].has_smart_ptr = True
else:
print(base_class_name, ' not found in classes for registering smart pointer using ', class_info.name, 'instead')
self.classes[class_info.name].has_smart_ptr = True
def_args = []
has_def_param = False
# Return type
ret_type = 'void' if variant.rettype.strip() == '' else variant.rettype
if ret_type.startswith('Ptr'): #smart pointer
ptr_type = ret_type.replace('Ptr<', '').replace('>', '')
if ptr_type in type_dict:
ret_type = type_dict[ptr_type]
for key in type_dict:
if key in ret_type:
ret_type = ret_type.replace(key, type_dict[key])
arg_types = []
unwrapped_arg_types = []
for arg in variant.args:
arg_type = None
if arg.tp in type_dict:
arg_type = type_dict[arg.tp]
else:
arg_type = arg.tp
# Add default value
if with_default_params and arg.defval != '':
def_args.append(arg.defval);
arg_types.append(arg_type)
unwrapped_arg_types.append(arg_type)
# Function attribure
func_attribs = ''
if '*' in ''.join(arg_types):
func_attribs += ', allow_raw_pointers()'
if variant.is_pure_virtual:
func_attribs += ', pure_virtual()'
# Wrapper function
wrap_func_name = (func.class_name+"_" if class_info != None else "") + func.name.split("::")[-1] + "_wrapper"
js_func_name = func.name
# TODO: Name functions based wrap directives or based on arguments list
if index > 0:
wrap_func_name += str(index)
js_func_name += str(index)
c_func_name = 'Wrappers::' + wrap_func_name
# Binding template-
raw_arg_names = ['arg' + str(i + 1) for i in range(0, len(variant.args))]
arg_names = []
w_signature = []
casted_arg_types = []
for arg_type, arg_name in zip(arg_types, raw_arg_names):
casted_arg_name = arg_name
if with_vec_from_js_array:
# Only support const vector reference as input parameter
match = re.search(r'const std::vector<(.*)>&', arg_type)
if match:
type_in_vect = match.group(1)
if type_in_vect in ['int', 'float', 'double', 'char', 'uchar', 'String', 'std::string']:
casted_arg_name = 'emscripten::vecFromJSArray<' + type_in_vect + '>(' + arg_name + ')'
arg_type = re.sub(r'std::vector<(.*)>', 'emscripten::val', arg_type)
w_signature.append(arg_type + ' ' + arg_name)
arg_names.append(casted_arg_name)
casted_arg_types.append(arg_type)
arg_types = casted_arg_types
# Argument list, signature
arg_names_casted = [c if a == b else c + '.as<' + a + '>()' for a, b, c in
zip(unwrapped_arg_types, arg_types, arg_names)]
# Add self object to the parameters
if class_info and not factory:
arg_types = [class_info.cname + '&'] + arg_types
w_signature = [class_info.cname + '& arg0 '] + w_signature
for j in range(0, len(def_args) + 1):
postfix = ''
if j > 0:
postfix = '_' + str(j);
###################################
# Wrapper
if factory: # TODO or static
name = class_info.cname+'::' if variant.class_name else ""
cpp_call_text = static_class_call_template.substitute(scope=name,
func=func.cname,
args=', '.join(arg_names[:len(arg_names)-j]))
elif class_info:
cpp_call_text = class_call_template.substitute(obj='arg0',
func=func.cname,
args=', '.join(arg_names[:len(arg_names)-j]))
else:
cpp_call_text = call_template.substitute(func=func.cname,
args=', '.join(arg_names[:len(arg_names)-j]))
wrapper_func_text = wrapper_function_template.substitute(ret_val=ret_type,
func=wrap_func_name+postfix,
signature=', '.join(w_signature[:len(w_signature)-j]),
cpp_call=cpp_call_text,
const='' if variant.is_const else '')
###################################
# Binding
if class_info:
if factory:
# print("Factory Function: ", c_func_name, len(variant.args) - j, class_info.name)
if variant.is_pure_virtual:
# FIXME: workaround for pure virtual in constructor
# e.g. DescriptorMatcher_clone_wrapper
continue
# consider the default parameter variants
args_num = len(variant.args) - j
if args_num in class_info.constructor_arg_num:
# FIXME: workaournd for constructor overload with same args number
# e.g. DescriptorMatcher
continue
class_info.constructor_arg_num.add(args_num)
binding_text = ctr_template.substitute(const='const' if variant.is_const else '',
cpp_name=c_func_name+postfix,
ret=ret_type,
args=','.join(arg_types[:len(arg_types)-j]),
optional=func_attribs)
else:
binding_template = overload_class_static_function_template if variant.is_class_method else \
overload_class_function_template
binding_text = binding_template.substitute(js_name=js_func_name,
const='' if variant.is_const else '',
cpp_name=c_func_name+postfix,
ret=ret_type,
args=','.join(arg_types[:len(arg_types)-j]),
optional=func_attribs)
else:
binding_text = overload_function_template.substitute(js_name=js_func_name,
cpp_name=c_func_name+postfix,
const='const' if variant.is_const else '',
ret=ret_type,
args=', '.join(arg_types[:len(arg_types)-j]),
optional=func_attribs)
bindings.append(binding_text)
wrappers.append(wrapper_func_text)
return [bindings, wrappers]
def gen_function_binding(self, func, class_info):
if not class_info == None :
func_name = class_info.cname+'::'+func.cname
else :
func_name = func.cname
binding_text = None
binding_text_list = []
for index, variant in enumerate(func.variants):
factory = False
#TODO if variant.is_class_method and variant.rettype == ('Ptr<' + class_info.name + '>'):
if (not class_info == None) and variant.rettype == ('Ptr<' + class_info.name + '>') or (func.name.startswith("create") and variant.rettype):
factory = True
base_class_name = variant.rettype
base_class_name = base_class_name.replace("Ptr<","").replace(">","").strip()
if base_class_name in self.classes:
self.classes[base_class_name].has_smart_ptr = True
else:
print(base_class_name, ' not found in classes for registering smart pointer using ', class_info.name, 'instead')
self.classes[class_info.name].has_smart_ptr = True
# Return type
ret_type = 'void' if variant.rettype.strip() == '' else variant.rettype
ret_type = ret_type.strip()
if ret_type.startswith('Ptr'): #smart pointer
ptr_type = ret_type.replace('Ptr<', '').replace('>', '')
if ptr_type in type_dict:
ret_type = type_dict[ptr_type]
for key in type_dict:
if key in ret_type:
ret_type = ret_type.replace(key, type_dict[key])
if variant.constret and ret_type.startswith('const') == False:
ret_type = 'const ' + ret_type
if variant.refret and ret_type.endswith('&') == False:
ret_type += '&'
arg_types = []
orig_arg_types = []
def_args = []
for arg in variant.args:
if arg.tp in type_dict:
arg_type = type_dict[arg.tp]
else:
arg_type = arg.tp
#if arg.outputarg:
# arg_type += '&'
orig_arg_types.append(arg_type)
if with_default_params and arg.defval != '':
def_args.append(arg.defval)
arg_types.append(orig_arg_types[-1])
# Function attribure
func_attribs = ''
if '*' in ''.join(orig_arg_types):
func_attribs += ', allow_raw_pointers()'
if variant.is_pure_virtual:
func_attribs += ', pure_virtual()'
#TODO better naming
#if variant.name in self.jsfunctions:
#else
js_func_name = variant.name
c_func_name = func.cname if (factory and variant.is_class_method == False) else func_name
################################### Binding
for j in range(0, len(def_args) + 1):
postfix = ''
if j > 0:
postfix = '_' + str(j);
if factory:
binding_text = ctr_template.substitute(const='const' if variant.is_const else '',
cpp_name=c_func_name+postfix,
ret=ret_type,
args=','.join(arg_types[:len(arg_types)-j]),
optional=func_attribs)
else:
binding_template = overload_class_static_function_template if variant.is_class_method else \
overload_function_template if class_info == None else overload_class_function_template
binding_text = binding_template.substitute(js_name=js_func_name,
const='const' if variant.is_const else '',
cpp_name=c_func_name+postfix,
ret=ret_type,
args=','.join(arg_types[:len(arg_types)-1]),
optional=func_attribs)
binding_text_list.append(binding_text)
return binding_text_list
def print_decls(self, decls):
"""
Prints the list of declarations, retrieived by the parse() method
"""
for d in decls:
print(d[0], d[1], ";".join(d[2]))
for a in d[3]:
print(" ", a[0], a[1], a[2], end="")
if a[3]:
print("; ".join(a[3]))
else:
print()
def gen(self, dst_file, src_files, core_bindings):
# step 1: scan the headers and extract classes, enums and functions
headers = []
for hdr in src_files:
decls = self.parser.parse(hdr)
# print(hdr);
# self.print_decls(decls);
if len(decls) == 0:
continue
headers.append(hdr[hdr.rindex('opencv2/'):])
for decl in decls:
name = decl[0]
type = name[:name.find(" ")]
if type == "struct" or type == "class": # class/structure case
name = name[name.find(" ") + 1:].strip()
self.add_class(type, name, decl)
elif name.startswith("enum"): # enumerations
self.add_enum(decl)
elif name.startswith("const"):
# constant
self.add_const(name.replace("const ", "").strip(), decl)
else: # class/global function
self.add_func(decl)
# step 2: generate bindings
# Global functions
for ns_name, ns in sorted(self.namespaces.items()):
if ns_name.split('.')[0] != 'cv':
continue
for name, func in sorted(ns.funcs.items()):
if name in ignore_list:
continue
if not name in white_list['']:
continue
ext_cnst = False
# Check if the method is an external constructor
for variant in func.variants:
if "Ptr<" in variant.rettype:
# Register the smart pointer
base_class_name = variant.rettype
base_class_name = base_class_name.replace("Ptr<","").replace(">","").strip()
self.classes[base_class_name].has_smart_ptr = True
# Adds the external constructor
class_name = func.name.replace("create", "")
if not class_name in self.classes:
self.classes[base_class_name].methods[func.cname] = func
else:
self.classes[class_name].methods[func.cname] = func
ext_cnst = True
if ext_cnst:
continue
if with_wrapped_functions:
binding, wrapper = self.gen_function_binding_with_wrapper(func, class_info=None)
self.bindings += binding
self.wrapper_funcs += wrapper
else:
binding = self.gen_function_binding(func, class_info=None)
self.bindings+=binding
# generate code for the classes and their methods
class_list = list(self.classes.items())
for name, class_info in class_list:
class_bindings = []
if not name in white_list:
continue
# Generate bindings for methods
for method_name, method in class_info.methods.items():
if method.cname in ignore_list:
continue
if not method.name in white_list[method.class_name]:
continue
if method.is_constructor:
for variant in method.variants:
args = []
for arg in variant.args:
arg_type = type_dict[arg.tp] if arg.tp in type_dict else arg.tp
args.append(arg_type)
# print('Constructor: ', class_info.name, len(variant.args))
args_num = len(variant.args)
if args_num in class_info.constructor_arg_num:
continue
class_info.constructor_arg_num.add(args_num)
class_bindings.append(constructor_template.substitute(signature=', '.join(args)))
else:
if with_wrapped_functions and (len(method.variants) > 1 or len(method.variants[0].args)>0 or "String" in method.variants[0].rettype):
binding, wrapper = self.gen_function_binding_with_wrapper(method, class_info=class_info)
self.wrapper_funcs = self.wrapper_funcs + wrapper
class_bindings = class_bindings + binding
else:
binding = self.gen_function_binding(method, class_info=class_info)
class_bindings = class_bindings + binding
# Regiseter Smart pointer
if class_info.has_smart_ptr:
class_bindings.append(smart_ptr_reg_template.substitute(cname=class_info.cname, name=class_info.name))
# Attach external constructors
# for method_name, method in class_info.ext_constructors.items():
# print("ext constructor", method_name)
#if class_info.ext_constructors:
# Generate bindings for properties
for property in class_info.props:
_class_property = class_property_enum_template if property.tp in type_dict else class_property_template
class_bindings.append(_class_property.substitute(js_name=property.name, cpp_name='::'.join(
[class_info.cname, property.name])))
dv = ''
base = Template("""base<$base>""")
assert len(class_info.bases) <= 1 , "multiple inheritance not supported"
if len(class_info.bases) == 1:
dv = "," + base.substitute(base=', '.join(class_info.bases))
self.bindings.append(class_template.substitute(cpp_name=class_info.cname,
js_name=name,
class_templates=''.join(class_bindings),
derivation=dv))
if export_enums:
# step 4: generate bindings for enums
# TODO anonymous enums are ignored for now.
for ns_name, ns in sorted(self.namespaces.items()):
if ns_name.split('.')[0] != 'cv':
continue
for name, enum in sorted(ns.enums.items()):
if not name.endswith('.anonymous'):
name = name.replace("cv.", "")
enum_values = []
for enum_val in enum:
value = enum_val[0][enum_val[0].rfind(".")+1:]
enum_values.append(enum_item_template.substitute(val=value,
cpp_val=name.replace('.', '::')+'::'+value))
self.bindings.append(enum_template.substitute(cpp_name=name.replace(".", "::"),
js_name=name.replace(".", "_"),
enum_items=''.join(enum_values)))
else:
print(name)
#TODO: represent anonymous enums with constants
if export_consts:
# step 5: generate bindings for consts
for ns_name, ns in sorted(self.namespaces.items()):
if ns_name.split('.')[0] != 'cv':
continue
for name, const in sorted(ns.consts.items()):
# print("Gen consts: ", name, const)
self.bindings.append(const_template.substitute(js_name=name, value=const))
with open(core_bindings) as f:
ret = f.read()
header_includes = '\n'.join(['#include "{}"'.format(hdr) for hdr in headers])
ret = ret.replace('@INCLUDES@', header_includes)
defis = '\n'.join(self.wrapper_funcs)
ret += wrapper_codes_template.substitute(ns=wrapper_namespace, defs=defis)
ret += emscripten_binding_template.substitute(binding_name='testBinding', bindings=''.join(self.bindings))
# print(ret)
text_file = open(dst_file, "w")
text_file.write(ret)
text_file.close()
if __name__ == "__main__":
if len(sys.argv) < 4:
print("Usage:\n", \
os.path.basename(sys.argv[0]), \
"<full path to hdr_parser.py> <bindings.cpp> <headers.txt> <core_bindings.cpp>")
print("Current args are: ", ", ".join(["'"+a+"'" for a in sys.argv]))
exit(0)
dstdir = "."
hdr_parser_path = os.path.abspath(sys.argv[1])
if hdr_parser_path.endswith(".py"):
hdr_parser_path = os.path.dirname(hdr_parser_path)
sys.path.append(hdr_parser_path)
import hdr_parser
bindingsCpp = sys.argv[2]
headers = open(sys.argv[3], 'r').read().split(';')
coreBindings = sys.argv[4]
generator = JSWrapperGenerator()
generator.gen(bindingsCpp, headers, coreBindings)

View File

@@ -0,0 +1,403 @@
// //////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
if (typeof Module.FS === 'undefined' && typeof FS !== 'undefined') {
Module.FS = FS;
}
Module['imread'] = function(imageSource) {
var img = null;
if (typeof imageSource === 'string') {
img = document.getElementById(imageSource);
} else {
img = imageSource;
}
var canvas = null;
var ctx = null;
if (img instanceof HTMLImageElement) {
canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, img.width, img.height);
} else if (img instanceof HTMLCanvasElement) {
canvas = img;
ctx = canvas.getContext('2d');
} else {
throw new Error('Please input the valid canvas or img id.');
return;
}
var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
return cv.matFromImageData(imgData);
};
Module['imshow'] = function(canvasSource, mat) {
var canvas = null;
if (typeof canvasSource === 'string') {
canvas = document.getElementById(canvasSource);
} else {
canvas = canvasSource;
}
if (!(canvas instanceof HTMLCanvasElement)) {
throw new Error('Please input the valid canvas element or id.');
return;
}
if (!(mat instanceof cv.Mat)) {
throw new Error('Please input the valid cv.Mat instance.');
return;
}
// convert the mat type to cv.CV_8U
var img = new cv.Mat();
var depth = mat.type()%8;
var scale = depth <= cv.CV_8S? 1.0 : (depth <= cv.CV_32S? 1.0/256.0 : 255.0);
var shift = (depth === cv.CV_8S || depth === cv.CV_16S)? 128.0 : 0.0;
mat.convertTo(img, cv.CV_8U, scale, shift);
// convert the img type to cv.CV_8UC4
switch (img.type()) {
case cv.CV_8UC1:
cv.cvtColor(img, img, cv.COLOR_GRAY2RGBA);
break;
case cv.CV_8UC3:
cv.cvtColor(img, img, cv.COLOR_RGB2RGBA);
break;
case cv.CV_8UC4:
break;
default:
throw new Error('Bad number of channels (Source image must have 1, 3 or 4 channels)');
return;
}
var imgData = new ImageData(new Uint8ClampedArray(img.data), img.cols, img.rows);
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
canvas.width = imgData.width;
canvas.height = imgData.height;
ctx.putImageData(imgData, 0, 0);
img.delete();
};
Module['VideoCapture'] = function(videoSource) {
var video = null;
if (typeof videoSource === 'string') {
video = document.getElementById(videoSource);
} else {
video = videoSource;
}
if (!(video instanceof HTMLVideoElement)) {
throw new Error('Please input the valid video element or id.');
return;
}
var canvas = document.createElement('canvas');
canvas.width = video.width;
canvas.height = video.height;
var ctx = canvas.getContext('2d');
this.video = video;
this.read = function(frame) {
if (!(frame instanceof cv.Mat)) {
throw new Error('Please input the valid cv.Mat instance.');
return;
}
if (frame.type() !== cv.CV_8UC4) {
throw new Error('Bad type of input mat: the type should be cv.CV_8UC4.');
return;
}
if (frame.cols !== video.width || frame.rows !== video.height) {
throw new Error('Bad size of input mat: the size should be same as the video.');
return;
}
ctx.drawImage(video, 0, 0, video.width, video.height);
frame.data.set(ctx.getImageData(0, 0, video.width, video.height).data);
};
};
function Range(start, end) {
this.start = typeof(start) === 'undefined' ? 0 : start;
this.end = typeof(end) === 'undefined' ? 0 : end;
}
Module['Range'] = Range;
function Point(x, y) {
this.x = typeof(x) === 'undefined' ? 0 : x;
this.y = typeof(y) === 'undefined' ? 0 : y;
}
Module['Point'] = Point;
function Size(width, height) {
this.width = typeof(width) === 'undefined' ? 0 : width;
this.height = typeof(height) === 'undefined' ? 0 : height;
}
Module['Size'] = Size;
function Rect() {
switch (arguments.length) {
case 0: {
// new cv.Rect()
this.x = 0;
this.y = 0;
this.width = 0;
this.height = 0;
break;
}
case 1: {
// new cv.Rect(rect)
var rect = arguments[0];
this.x = rect.x;
this.y = rect.y;
this.width = rect.width;
this.height = rect.height;
break;
}
case 2: {
// new cv.Rect(point, size)
var point = arguments[0];
var size = arguments[1];
this.x = point.x;
this.y = point.y;
this.width = size.width;
this.height = size.height;
break;
}
case 4: {
// new cv.Rect(x, y, width, height)
this.x = arguments[0];
this.y = arguments[1];
this.width = arguments[2];
this.height = arguments[3];
break;
}
default: {
throw new Error('Invalid arguments');
}
}
}
Module['Rect'] = Rect;
function RotatedRect() {
switch (arguments.length) {
case 0: {
this.center = {x: 0, y: 0};
this.size = {width: 0, height: 0};
this.angle = 0;
break;
}
case 3: {
this.center = arguments[0];
this.size = arguments[1];
this.angle = arguments[2];
break;
}
default: {
throw new Error('Invalid arguments');
}
}
}
RotatedRect.points = function(obj) {
return Module.rotatedRectPoints(obj);
};
RotatedRect.boundingRect = function(obj) {
return Module.rotatedRectBoundingRect(obj);
};
RotatedRect.boundingRect2f = function(obj) {
return Module.rotatedRectBoundingRect2f(obj);
};
Module['RotatedRect'] = RotatedRect;
function Scalar(v0, v1, v2, v3) {
this.push(typeof(v0) === 'undefined' ? 0 : v0);
this.push(typeof(v1) === 'undefined' ? 0 : v1);
this.push(typeof(v2) === 'undefined' ? 0 : v2);
this.push(typeof(v3) === 'undefined' ? 0 : v3);
}
Scalar.prototype = new Array; // eslint-disable-line no-array-constructor
Scalar.all = function(v) {
return new Scalar(v, v, v, v);
};
Module['Scalar'] = Scalar;
function MinMaxLoc() {
switch (arguments.length) {
case 0: {
this.minVal = 0;
this.maxVal = 0;
this.minLoc = new Point();
this.maxLoc = new Point();
break;
}
case 4: {
this.minVal = arguments[0];
this.maxVal = arguments[1];
this.minLoc = arguments[2];
this.maxLoc = arguments[3];
break;
}
default: {
throw new Error('Invalid arguments');
}
}
}
Module['MinMaxLoc'] = MinMaxLoc;
function Circle() {
switch (arguments.length) {
case 0: {
this.center = new Point();
this.radius = 0;
break;
}
case 2: {
this.center = arguments[0];
this.radius = arguments[1];
break;
}
default: {
throw new Error('Invalid arguments');
}
}
}
Module['Circle'] = Circle;
function TermCriteria() {
switch (arguments.length) {
case 0: {
this.type = 0;
this.maxCount = 0;
this.epsilon = 0;
break;
}
case 3: {
this.type = arguments[0];
this.maxCount = arguments[1];
this.epsilon = arguments[2];
break;
}
default: {
throw new Error('Invalid arguments');
}
}
}
Module['TermCriteria'] = TermCriteria;
Module['matFromArray'] = function(rows, cols, type, array) {
var mat = new cv.Mat(rows, cols, type);
switch (type) {
case cv.CV_8U:
case cv.CV_8UC1:
case cv.CV_8UC2:
case cv.CV_8UC3:
case cv.CV_8UC4: {
mat.data.set(array);
break;
}
case cv.CV_8S:
case cv.CV_8SC1:
case cv.CV_8SC2:
case cv.CV_8SC3:
case cv.CV_8SC4: {
mat.data8S.set(array);
break;
}
case cv.CV_16U:
case cv.CV_16UC1:
case cv.CV_16UC2:
case cv.CV_16UC3:
case cv.CV_16UC4: {
mat.data16U.set(array);
break;
}
case cv.CV_16S:
case cv.CV_16SC1:
case cv.CV_16SC2:
case cv.CV_16SC3:
case cv.CV_16SC4: {
mat.data16S.set(array);
break;
}
case cv.CV_32S:
case cv.CV_32SC1:
case cv.CV_32SC2:
case cv.CV_32SC3:
case cv.CV_32SC4: {
mat.data32S.set(array);
break;
}
case cv.CV_32F:
case cv.CV_32FC1:
case cv.CV_32FC2:
case cv.CV_32FC3:
case cv.CV_32FC4: {
mat.data32F.set(array);
break;
}
case cv.CV_64F:
case cv.CV_64FC1:
case cv.CV_64FC2:
case cv.CV_64FC3:
case cv.CV_64FC4: {
mat.data64F.set(array);
break;
}
default: {
throw new Error('Type is unsupported');
}
}
return mat;
};
Module['matFromImageData'] = function(imageData) {
var mat = new cv.Mat(imageData.height, imageData.width, cv.CV_8UC4);
mat.data.set(imageData.data);
return mat;
};

View File

@@ -0,0 +1,115 @@
###############################################################################
#
# IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
#
# By downloading, copying, installing or using the software you agree to this license.
# If you do not agree to this license, do not download, install,
# copy or use the software.
#
#
# License Agreement
# For Open Source Computer Vision Library
#
# Copyright (C) 2013, OpenCV Foundation, all rights reserved.
# Third party copyrights are property of their respective owners.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistribution's of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistribution's in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * The name of the copyright holders may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# This software is provided by the copyright holders and contributors "as is" and
# any express or implied warranties, including, but not limited to, the implied
# warranties of merchantability and fitness for a particular purpose are disclaimed.
# In no event shall the Intel Corporation or contributors be liable for any direct,
# indirect, incidental, special, exemplary, or consequential damages
# (including, but not limited to, procurement of substitute goods or services;
# loss of use, data, or profits; or business interruption) however caused
# and on any theory of liability, whether in contract, strict liability,
# or tort (including negligence or otherwise) arising in any way out of
# the use of this software, even if advised of the possibility of such damage.
#
###############################################################################
# AUTHOR: Sajjad Taheri, University of California, Irvine. sajjadt[at]uci[dot]edu
#
# LICENSE AGREEMENT
# Copyright (c) 2015, 2015 The Regents of the University of California (Regents)
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the University nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
###############################################################################
import os, sys, re, json, shutil
from subprocess import Popen, PIPE, STDOUT
def make_umd(opencvjs, cvjs):
src = open(opencvjs, 'r+b')
dst = open(cvjs, 'w+b')
content = src.read()
dst.seek(0)
# inspired by https://github.com/umdjs/umd/blob/95563fd6b46f06bda0af143ff67292e7f6ede6b7/templates/returnExportsGlobal.js
dst.write(("""
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(function () {
return (root.cv = factory());
});
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else if (typeof window === 'object') {
// Browser globals
root.cv = factory();
} else if (typeof importScripts === 'function') {
// Web worker
root.cv = factory;
} else {
// Other shells, e.g. d8
root.cv = factory();
}
}(this, function () {
%s
if (typeof Module === 'undefined')
Module = {};
return cv(Module);
}));
""" % (content)).lstrip())
if __name__ == "__main__":
if len(sys.argv) > 2:
opencvjs = sys.argv[1]
cvjs = sys.argv[2]
if not os.path.isfile(opencvjs):
print('opencv.js file not found! Have you compiled the opencv_js module?')
exit()
make_umd(opencvjs, cvjs);

View File

@@ -0,0 +1,195 @@
###############################################################################
#
# IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
#
# By downloading, copying, installing or using the software you agree to this license.
# If you do not agree to this license, do not download, install,
# copy or use the software.
#
#
# License Agreement
# For Open Source Computer Vision Library
#
# Copyright (C) 2013, OpenCV Foundation, all rights reserved.
# Third party copyrights are property of their respective owners.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistribution's of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistribution's in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * The name of the copyright holders may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# This software is provided by the copyright holders and contributors "as is" and
# any express or implied warranties, including, but not limited to, the implied
# warranties of merchantability and fitness for a particular purpose are disclaimed.
# In no event shall the Intel Corporation or contributors be liable for any direct,
# indirect, incidental, special, exemplary, or consequential damages
# (including, but not limited to, procurement of substitute goods or services;
# loss of use, data, or profits; or business interruption) however caused
# and on any theory of liability, whether in contract, strict liability,
# or tort (including negligence or otherwise) arising in any way out of
# the use of this software, even if advised of the possibility of such damage.
#
###############################################################################
# AUTHOR: Sajjad Taheri, University of California, Irvine. sajjadt[at]uci[dot]edu
#
# LICENSE AGREEMENT
# Copyright (c) 2015, 2015 The Regents of the University of California (Regents)
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the University nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##############################################################################
from string import Template
wrapper_codes_template = Template("namespace $ns {\n$defs\n}")
call_template = Template("""$func($args)""")
class_call_template = Template("""$obj.$func($args)""")
static_class_call_template = Template("""$scope$func($args)""")
wrapper_function_template = Template(""" $ret_val $func($signature)$const {
return $cpp_call;
}
""")
wrapper_function_with_def_args_template = Template(""" $ret_val $func($signature)$const {
$check_args
}
""")
wrapper_overload_def_values = [
Template("""return $cpp_call;"""), Template("""if ($arg0.isUndefined())
return $cpp_call;
else
$next"""),
Template("""if ($arg0.isUndefined() && $arg1.isUndefined())
return $cpp_call;
else $next"""),
Template("""if ($arg0.isUndefined() && $arg1.isUndefined() && $arg2.isUndefined())
return $cpp_call;
else $next"""),
Template("""if ($arg0.isUndefined() && $arg1.isUndefined() && $arg2.isUndefined() && $arg3.isUndefined())
return $cpp_call;
else $next"""),
Template("""if ($arg0.isUndefined() && $arg1.isUndefined() && $arg2.isUndefined() && $arg3.isUndefined() &&
$arg4.isUndefined())
return $cpp_call;
else $next"""),
Template("""if ($arg0.isUndefined() && $arg1.isUndefined() && $arg2.isUndefined() && $arg3.isUndefined() &&
$arg4.isUndefined() && $arg5.isUndefined() )
return $cpp_call;
else $next"""),
Template("""if ($arg0.isUndefined() && $arg1.isUndefined() && $arg2.isUndefined() && $arg3.isUndefined() &&
$arg4.isUndefined() && $arg5.isUndefined() && $arg6.isUndefined() )
return $cpp_call;
else $next"""),
Template("""if ($arg0.isUndefined() && $arg1.isUndefined() && $arg2.isUndefined() && $arg3.isUndefined() &&
$arg4.isUndefined() && $arg5.isUndefined()&& $arg6.isUndefined() && $arg7.isUndefined())
return $cpp_call;
else $next"""),
Template("""if ($arg0.isUndefined() && $arg1.isUndefined() && $arg2.isUndefined() && $arg3.isUndefined() &&
$arg4.isUndefined() && $arg5.isUndefined()&& $arg6.isUndefined() && $arg7.isUndefined() &&
$arg8.isUndefined())
return $cpp_call;
else $next"""),
Template("""if ($arg0.isUndefined() && $arg1.isUndefined() && $arg2.isUndefined() && $arg3.isUndefined() &&
$arg4.isUndefined() && $arg5.isUndefined()&& $arg6.isUndefined() && $arg7.isUndefined()&&
$arg8.isUndefined() && $arg9.isUndefined())
return $cpp_call;
else $next""")]
emscripten_binding_template = Template("""
EMSCRIPTEN_BINDINGS($binding_name) {$bindings
}
""")
simple_function_template = Template("""
emscripten::function("$js_name", &$cpp_name);
""")
smart_ptr_reg_template = Template("""
.smart_ptr<Ptr<$cname>>("Ptr<$name>")
""")
overload_function_template = Template("""
function("$js_name", select_overload<$ret($args)$const>(&$cpp_name)$optional);
""")
overload_class_function_template = Template("""
.function("$js_name", select_overload<$ret($args)$const>(&$cpp_name)$optional)""")
overload_class_static_function_template = Template("""
.class_function("$js_name", select_overload<$ret($args)$const>(&$cpp_name)$optional)""")
class_property_template = Template("""
.property("$js_name", &$cpp_name)""")
class_property_enum_template = Template("""
.property("$js_name", binding_utils::underlying_ptr(&$cpp_name))""")
ctr_template = Template("""
.constructor(select_overload<$ret($args)$const>(&$cpp_name)$optional)""")
smart_ptr_ctr_overload_template = Template("""
.smart_ptr_constructor("$ptr_type", select_overload<$ret($args)$const>(&$cpp_name)$optional)""")
function_template = Template("""
.function("$js_name", &$cpp_name)""")
static_function_template = Template("""
.class_function("$js_name", &$cpp_name)""")
constructor_template = Template("""
.constructor<$signature>()""")
enum_item_template = Template("""
.value("$val", $cpp_val)""")
enum_template = Template("""
emscripten::enum_<$cpp_name>("$js_name")$enum_items;
""")
const_template = Template("""
constant("$js_name", static_cast<long>($value));
""")
vector_template = Template("""
emscripten::register_vector<$cType>("$js_name");
""")
map_template = Template("""
emscripten::register_map<cpp_type_key,$cpp_type_val>("$js_name");
""")
class_template = Template("""
emscripten::class_<$cpp_name $derivation>("$js_name")$class_templates;
""")

View File

@@ -0,0 +1,12 @@
{
"extends": "google",
"parserOptions": {
"ecmaVersion": 6
},
"rules": {
"max-len": ["error", 100, {"ignoreUrls": true}],
"quotes": ["error", "single"],
"indent": ["error", 4, {"ArrayExpression": "first",
"CallExpression": {"arguments": "first"}}]
}
}

View File

@@ -0,0 +1,28 @@
{
"name": "opencv_js_tests",
"description": "Tests for opencv js bindings",
"version": "1.0.1",
"dependencies": {
"ansi-colors": "^4.1.1",
"minimist": "^1.2.0",
"node-qunit": "latest"
},
"devDependencies": {
"eslint": "latest",
"eslint-config-google": "latest"
},
"scripts": {
"test": "node tests.js"
},
"repository": {
"type": "git",
"url": "https://github.com/opencv/opencv.git"
},
"keywords": [],
"author": "",
"license": "BSD-3-Clause",
"bugs": {
"url": "https://github.com/opencv/opencv/issues"
},
"homepage": "https://github.com/opencv/opencv"
}

View File

@@ -0,0 +1,214 @@
try {
require('puppeteer')
} catch (e) {
console.error(
"\nFATAL ERROR:" +
"\n Package 'puppeteer' is not available." +
"\n Run 'npm install --no-save puppeteer' before running this script" +
"\n * You may use PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 environment variable to avoid automatic Chromium downloading" +
"\n (specify own Chromium/Chrome version through PUPPETEER_EXECUTABLE_PATH=`which google-chrome` environment variable)" +
"\n");
process.exit(1);
}
const puppeteer = require('puppeteer')
const colors = require("ansi-colors")
const path = require("path");
const fs = require("fs");
const http = require("http");
run_main(require('minimist')(process.argv.slice(2)));
async function run_main(o = {}) {
try {
await main(o);
console.magenta("FATAL: Unexpected exit!");
process.exit(1);
} catch (e) {
console.error(colors.magenta("FATAL: Unexpected exception!"));
console.error(e);
process.exit(1);
}
}
async function main(o = {}) {
o = Object.assign({}, {
buildFolder: __dirname,
port: 8080,
debug: false,
noHeadless: false,
serverPrefix: `http://localhost`,
noExit: false,
screenshot: undefined,
help: false,
noTryCatch: false,
maxBlockDuration: 30000
}, o)
if (typeof o.screenshot == 'string' && o.screenshot == 'false') {
console.log(colors.red('ERROR: misused screenshot option, use --no-screenshot instead'));
}
if (o.noExit) {
o.maxBlockDuration = 999999999
}
o.debug && console.log('Current Options', o);
if (o.help) {
printHelpAndExit();
}
const serverAddress = `${o.serverPrefix}:${o.port}`
const url = `${serverAddress}/tests.html${o.noTryCatch ? '?notrycatch=1' : ''}`;
if (!fs.existsSync(o.buildFolder)) {
console.error(`Expected folder "${o.buildFolder}" to exists. Aborting`);
}
o.debug && debug('Server Listening at ' + url);
const server = await staticServer(o.buildFolder, o.port, m => debug, m => error);
o.debug && debug(`Browser launching ${!o.noHeadless ? 'headless' : 'not headless'}`);
const browser = await puppeteer.launch({ headless: !o.noHeadless });
const page = await browser.newPage();
page.on('console', e => {
locationMsg = formatMessage(`${e.location().url}:${e.location().lineNumber}:${e.location().columnNumber}`);
if (e.type() === 'error') {
console.log(colors.red(formatMessage('' + e.text(), `-- ERROR:${locationMsg}: `, )));
}
else if (o.debug) {
o.debug && console.log(colors.grey(formatMessage('' + e.text(), `-- ${locationMsg}: `)));
}
});
o.debug && debug(`Opening page address ${url}`);
await page.goto(url);
await page.waitForFunction(() => (document.querySelector(`#qunit-testresult`) && document.querySelector(`#qunit-testresult`).textContent || '').trim().toLowerCase().startsWith('tests completed'));
const text = await getText(`#qunit-testresult`);
if (!text) {
return await fail(`An error occurred extracting test results. Check the build folder ${o.buildFolder} is correct and has build with tests enabled.`);
}
o.debug && debug(colors.blackBright("* UserAgent: " + await getText('#qunit-userAgent')));
const testFailed = !text.includes(' 0 failed');
if (testFailed && !o.debug) {
process.stdout.write(colors.grey("* Use '--debug' parameter to see details of failed tests.\n"));
}
if (o.screenshot || (o.screenshot === undefined && testFailed)) {
await page.screenshot({ path: 'screenshot.png', fullPage: 'true' });
process.stdout.write(colors.grey(`* Screenshot taken: ${o.buildFolder}/screenshot.png\n`));
}
if (testFailed) {
const report = await failReport();
process.stdout.write(`
${colors.red.bold.underline('Failed tests ! :(')}
${colors.redBright(colors.symbols.cross + ' ' + report.join(`\n${colors.symbols.cross} `))}
${colors.redBright(`=== Summary ===\n${text}`)}
`);
}
else {
process.stdout.write(colors.green(`
${colors.symbols.check} No Errors :)
=== Summary ===\n${text}
`));
}
if (o.noExit) {
while (true) {
await new Promise(r => setTimeout(r, 5000));
}
}
await server && server.close();
await browser.close();
process.exit(testFailed ? 1 : 0);
async function getText(s) {
return await page.evaluate((s) => (document.querySelector(s) && document.querySelector(s).innerText) || ''.trim(), s);
}
async function failReport() {
const failures = await page.evaluate(() => Array.from(document.querySelectorAll('#qunit-tests .fail')).filter(e => e.querySelector('.module-name')).map(e => ({
moduleName: e.querySelector('.module-name') && e.querySelector('.module-name').textContent,
testName: e.querySelector('.test-name') && e.querySelector('.test-name').textContent,
expected: e.querySelector('.test-expected pre') && e.querySelector('.test-expected pre').textContent,
actual: e.querySelector('.test-actual pre') && e.querySelector('.test-actual pre').textContent,
code: e.querySelector('.test-source') && e.querySelector('.test-source').textContent.replace("Source: at ", ""),
})));
return failures.map(f => `${f.moduleName}: ${f.testName} (${formatMessage(f.code)})`);
}
async function fail(s) {
await failReport();
process.stdout.write(colors.red(s) + '\n');
if (o.screenshot || o.screenshot === undefined) {
await page.screenshot({ path: 'screenshot.png', fullPage: 'true' });
process.stdout.write(colors.grey(`* Screenshot taken: ${o.buildFolder}/screenshot.png\n`));
}
process.exit(1);
}
async function debug(s) {
process.stdout.write(s + '\n');
}
async function error(s) {
process.stdout.write(s + '\n');
}
function formatMessage(message, prefix) {
prefix = prefix || '';
return prefix + ('' + message).split('\n').map(l => l.replace(serverAddress, o.buildFolder)).join('\n' + prefix);
}
}
function printHelpAndExit() {
console.log(`
Usage:
# First, remember to build opencv.js with tests enabled:
${colors.blueBright(`python ./platforms/js/build_js.py build_js --build_test`)}
# Install the tool locally (needed only once) and run it
${colors.blueBright(`cd build_js/bin`)}
${colors.blueBright(`npm install`)}
${colors.blueBright(`node run_puppeteer`)}
By default will run a headless browser silently printing a small report in the terminal.
But it could used to debug the tests in the browser, take screenshots, global tool or
targeting external servers exposing the tests.
TIP: you could install the tool globally (npm install --global build_js/bin) to execute it from any local folder.
# Options
* port?: number. Default 8080
* buildFolder?: string. Default __dirname (this folder)
* debug?: boolean. Default false
* noHeadless?: boolean. Default false
* serverPrefix?: string . Default http://localhost
* help?: boolean
* screenshot?: boolean . Make screenshot on failure by default. Use --no-screenshot to disable screenshots completely.
* noExit?: boolean default false. If true it will keep running the server - together with noHeadless you can debug in the browser.
* noTryCatch?: boolean will disable Qunit tryCatch - so exceptions are dump to stdout rather than in the browser.
* maxBlockDuration: QUnit timeout. If noExit is given then is infinity.
`);
process.exit(0);
}
async function staticServer(basePath, port, onFound, onNotFound) {
return new Promise(async (resolve) => {
const server = http.createServer((req, res) => {
var url = resolveUrl(req.url);
onFound && onFound(url);
var stream = fs.createReadStream(path.join(basePath, url || ''));
stream.on('error', function () {
onNotFound && onNotFound(url);
res.writeHead(404);
res.end();
});
stream.pipe(res);
}).listen(port);
server.on('listening', () => {
resolve(server);
});
});
function resolveUrl(url = '') {
var i = url.indexOf('?');
if (i != -1) {
url = url.substr(0, i);
}
i = url.indexOf('#');
if (i != -1) {
url = url.substr(0, i);
}
return url;
}
}

View File

@@ -0,0 +1,91 @@
// 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.
if (typeof module !== 'undefined' && module.exports) {
// The environment is Node.js
var cv = require('./opencv.js'); // eslint-disable-line no-var
}
QUnit.module('Camera Calibration and 3D Reconstruction', {});
QUnit.test('constants', function(assert) {
assert.strictEqual(typeof cv.LMEDS, 'number');
assert.strictEqual(typeof cv.RANSAC, 'number');
assert.strictEqual(typeof cv.RHO, 'number');
});
QUnit.test('findHomography', function(assert) {
let srcPoints = cv.matFromArray(4, 1, cv.CV_32FC2, [
56,
65,
368,
52,
28,
387,
389,
390,
]);
let dstPoints = cv.matFromArray(4, 1, cv.CV_32FC2, [
0,
0,
300,
0,
0,
300,
300,
300,
]);
const mat = cv.findHomography(srcPoints, dstPoints);
assert.ok(mat instanceof cv.Mat);
});
QUnit.test('Rodrigues', function(assert) {
// Converts a rotation matrix to a rotation vector and vice versa
// data64F is the output array
const rvec0 = cv.matFromArray(1, 3, cv.CV_64F, [1,1,1]);
let rMat0 = new cv.Mat();
let rvec1 = new cv.Mat();
// Args: input Mat, output Mat. The function mutates the output Mat, so the function does not return anything.
// cv.Rodrigues (InputArray=src, OutputArray=dst, jacobian=0)
// https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#void%20Rodrigues(InputArray%20src,%20OutputArray%20dst,%20OutputArray%20jacobian)
// vec to Mat, starting number is 3 long and each element is 1.
cv.Rodrigues(rvec0, rMat0);
assert.ok(rMat0.data64F.length == 9);
assert.ok(0.23 > rMat0.data64F[0] > 0.22);
// convert Mat to Vec, should be same as what we started with, 3 long and each item should be a 1.
cv.Rodrigues(rMat0, rvec1);
assert.ok(rvec1.data64F.length == 3);
assert.ok(1.01 > rvec1.data64F[0] > 0.9);
// Answer should be around 1: 0.9999999999999999
});
QUnit.test('estimateAffine2D', function(assert) {
const inputs = cv.matFromArray(4, 1, cv.CV_32FC2, [
1, 1,
80, 0,
0, 80,
80, 80
]);
const outputs = cv.matFromArray(4, 1, cv.CV_32FC2, [
21, 51,
70, 77,
40, 40,
10, 70
]);
const M = cv.estimateAffine2D(inputs, outputs);
assert.ok(M instanceof cv.Mat);
assert.deepEqual(Array.from(M.data), [
23, 55, 97, 126, 87, 139, 227, 63, 0, 0,
0, 0, 0, 0, 232, 191, 71, 246, 12, 68,
165, 35, 53, 64, 99, 56, 27, 66, 14, 254,
212, 63, 103, 102, 102, 102, 102, 102, 182, 191,
195, 252, 174, 22, 55, 97, 73, 64
]);
});

View File

@@ -0,0 +1,115 @@
// 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.
if (typeof module !== 'undefined' && module.exports) {
// The environment is Node.js
var cv = require('./opencv.js'); // eslint-disable-line no-var
}
function generateTestFrame(width, height) {
let w = width || 200;
let h = height || 200;
let img = new cv.Mat(h, w, cv.CV_8UC1, new cv.Scalar(0, 0, 0, 0));
let s = new cv.Scalar(255, 255, 255, 255);
let s128 = new cv.Scalar(128, 128, 128, 128);
let rect = new cv.Rect(w / 4, h / 4, w / 2, h / 2);
img.roi(rect).setTo(s);
img.roi(new cv.Rect(w / 2 - w / 8, h / 2 - h / 8, w / 4, h / 4)).setTo(s128);
cv.rectangle(img, new cv.Point(w / 8, h / 8), new cv.Point(w - w / 8, h - h / 8), s, 5);
cv.rectangle(img, new cv.Point(w / 5, h / 5), new cv.Point(w - w / 5, h - h / 5), s128, 3);
cv.line(img, new cv.Point(-w, 0), new cv.Point(w / 2, h / 2), s128, 5);
cv.line(img, new cv.Point(2*w, 0), new cv.Point(w / 2, h / 2), s, 5);
return img;
}
QUnit.module('Features2D', {});
QUnit.test('Detectors', function(assert) {
let image = generateTestFrame();
let kp = new cv.KeyPointVector();
let orb = new cv.ORB();
orb.detect(image, kp);
assert.equal(kp.size(), 67, 'ORB');
let mser = new cv.MSER();
mser.detect(image, kp);
assert.equal(kp.size(), 7, 'MSER');
let brisk = new cv.BRISK();
brisk.detect(image, kp);
assert.equal(kp.size(), 191, 'BRISK');
let ffd = new cv.FastFeatureDetector();
ffd.detect(image, kp);
assert.equal(kp.size(), 12, 'FastFeatureDetector');
let afd = new cv.AgastFeatureDetector();
afd.detect(image, kp);
assert.equal(kp.size(), 67, 'AgastFeatureDetector');
let gftt = new cv.GFTTDetector();
gftt.detect(image, kp);
assert.equal(kp.size(), 168, 'GFTTDetector');
let kaze = new cv.KAZE();
kaze.detect(image, kp);
assert.equal(kp.size(), 159, 'KAZE');
let akaze = new cv.AKAZE();
akaze.detect(image, kp);
assert.equal(kp.size(), 53, 'AKAZE');
});
QUnit.test('BFMatcher', function(assert) {
// Generate key points.
let image = generateTestFrame();
let kp = new cv.KeyPointVector();
let descriptors = new cv.Mat();
let orb = new cv.ORB();
orb.detectAndCompute(image, new cv.Mat(), kp, descriptors);
assert.equal(kp.size(), 67);
// Run a matcher.
let dm = new cv.DMatchVector();
let matcher = new cv.BFMatcher();
matcher.match(descriptors, descriptors, dm);
assert.equal(dm.size(), 67);
});
QUnit.test('Drawing', function(assert) {
// Generate key points.
let image = generateTestFrame();
let kp = new cv.KeyPointVector();
let descriptors = new cv.Mat();
let orb = new cv.ORB();
orb.detectAndCompute(image, new cv.Mat(), kp, descriptors);
assert.equal(kp.size(), 67);
let dst = new cv.Mat();
cv.drawKeypoints(image, kp, dst);
assert.equal(dst.rows, image.rows);
assert.equal(dst.cols, image.cols);
// Run a matcher.
let dm = new cv.DMatchVector();
let matcher = new cv.BFMatcher();
matcher.match(descriptors, descriptors, dm);
assert.equal(dm.size(), 67);
cv.drawMatches(image, kp, image, kp, dm, dst);
assert.equal(dst.rows, image.rows);
assert.equal(dst.cols, 2 * image.cols);
dm = new cv.DMatchVectorVector();
matcher.knnMatch(descriptors, descriptors, dm, 2);
assert.equal(dm.size(), 67);
cv.drawMatchesKnn(image, kp, image, kp, dm, dst);
assert.equal(dst.rows, image.rows);
assert.equal(dst.cols, 2 * image.cols);
});

View File

@@ -0,0 +1,979 @@
// //////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//
// //////////////////////////////////////////////////////////////////////////////////////
// Author: Sajjad Taheri, University of California, Irvine. sajjadt[at]uci[dot]edu
//
// LICENSE AGREEMENT
// Copyright (c) 2015 The Regents of the University of California (Regents)
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the University nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
if (typeof module !== 'undefined' && module.exports) {
// The environment is Node.js
var cv = require('./opencv.js'); // eslint-disable-line no-var
}
QUnit.module('Image Processing', {});
QUnit.test('test_imgProc', function(assert) {
// calcHist
{
let vec1 = new cv.Mat.ones(new cv.Size(20, 20), cv.CV_8UC1); // eslint-disable-line new-cap
let source = new cv.MatVector();
source.push_back(vec1);
let channels = [0];
let histSize = [256];
let ranges =[0, 256];
let hist = new cv.Mat();
let mask = new cv.Mat();
let binSize = cv._malloc(4);
let binView = new Int32Array(cv.HEAP8.buffer, binSize);
binView[0] = 10;
cv.calcHist(source, channels, mask, hist, histSize, ranges, false);
// hist should contains a N X 1 array.
let size = hist.size();
assert.equal(size.height, 256);
assert.equal(size.width, 1);
// default parameters
cv.calcHist(source, channels, mask, hist, histSize, ranges);
size = hist.size();
assert.equal(size.height, 256);
assert.equal(size.width, 1);
// Do we need to verify data in histogram?
// let dataView = hist.data;
// Free resource
cv._free(binSize);
mask.delete();
hist.delete();
}
// cvtColor
{
let source = new cv.Mat(10, 10, cv.CV_8UC3);
let dest = new cv.Mat();
cv.cvtColor(source, dest, cv.COLOR_BGR2GRAY, 0);
assert.equal(dest.channels(), 1);
cv.cvtColor(source, dest, cv.COLOR_BGR2GRAY);
assert.equal(dest.channels(), 1);
cv.cvtColor(source, dest, cv.COLOR_BGR2BGRA, 0);
assert.equal(dest.channels(), 4);
cv.cvtColor(source, dest, cv.COLOR_BGR2BGRA);
assert.equal(dest.channels(), 4);
dest.delete();
source.delete();
}
// equalizeHist
{
let source = new cv.Mat(10, 10, cv.CV_8UC1);
let dest = new cv.Mat();
cv.equalizeHist(source, dest);
// eualizeHist changes the content of a image, but does not alter meta data
// of it.
assert.equal(source.channels(), dest.channels());
assert.equal(source.type(), dest.type());
dest.delete();
source.delete();
}
// floodFill
{
let center = new cv.Point(5, 5);
let rect = new cv.Rect(0, 0, 0, 0);
let img = new cv.Mat.zeros(10, 10, cv.CV_8UC1);
let color = new cv.Scalar (255);
cv.circle(img, center, 3, color, 1);
let edge = new cv.Mat();
cv.Canny(img, edge, 100, 255);
cv.copyMakeBorder(edge, edge, 1, 1, 1, 1, cv.BORDER_REPLICATE);
let expected_img_data = new Uint8Array([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 255, 0, 0, 0, 0,
0, 0, 0, 255, 255, 255, 255, 255, 0, 0,
0, 0, 0, 255, 0, 255, 0, 255, 0, 0,
0, 0, 255, 255, 255, 255, 0, 0, 255, 0,
0, 0, 0, 255, 0, 0, 0, 255, 0, 0,
0, 0, 0, 255, 255, 0, 255, 255, 0, 0,
0, 0, 0, 0, 0, 255, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
let img_elem = 10*10*1;
let expected_img_data_ptr = cv._malloc(img_elem);
let expected_img_data_heap = new Uint8Array(cv.HEAPU8.buffer,
expected_img_data_ptr,
img_elem);
expected_img_data_heap.set(new Uint8Array(expected_img_data.buffer));
let expected_img = new cv.Mat( 10, 10, cv.CV_8UC1, expected_img_data_ptr, 0);
let expected_rect = new cv.Rect(3,3,3,3);
let compare_result = new cv.Mat(10, 10, cv.CV_8UC1);
cv.floodFill(img, edge, center, color, rect);
cv.compare (img, expected_img, compare_result, cv.CMP_EQ);
// expect every pixels are the same.
assert.equal (cv.countNonZero(compare_result), img.total());
assert.equal (rect.x, expected_rect.x);
assert.equal (rect.y, expected_rect.y);
assert.equal (rect.width, expected_rect.width);
assert.equal (rect.height, expected_rect.height);
img.delete();
edge.delete();
expected_img.delete();
compare_result.delete();
}
// fillPoly
{
let img_width = 6;
let img_height = 6;
let img = new cv.Mat.zeros(img_height, img_width, cv.CV_8UC1);
let npts = 4;
let square_point_data = new Uint8Array([
1, 1,
4, 1,
4, 4,
1, 4]);
let square_points = cv.matFromArray(npts, 1, cv.CV_32SC2, square_point_data);
let pts = new cv.MatVector();
pts.push_back (square_points);
let color = new cv.Scalar (255);
let expected_img_data = new Uint8Array([
0, 0, 0, 0, 0, 0,
0, 255, 255, 255, 255, 0,
0, 255, 255, 255, 255, 0,
0, 255, 255, 255, 255, 0,
0, 255, 255, 255, 255, 0,
0, 0, 0, 0, 0, 0]);
let expected_img = cv.matFromArray(img_height, img_width, cv.CV_8UC1, expected_img_data);
cv.fillPoly(img, pts, color);
let compare_result = new cv.Mat(img_height, img_width, cv.CV_8UC1);
cv.compare (img, expected_img, compare_result, cv.CMP_EQ);
// expect every pixels are the same.
assert.equal (cv.countNonZero(compare_result), img.total());
img.delete();
square_points.delete();
pts.delete();
expected_img.delete();
compare_result.delete();
}
// fillConvexPoly
{
let img_width = 6;
let img_height = 6;
let img = new cv.Mat.zeros(img_height, img_width, cv.CV_8UC1);
let npts = 4;
let square_point_data = new Uint8Array([
1, 1,
4, 1,
4, 4,
1, 4]);
let square_points = cv.matFromArray(npts, 1, cv.CV_32SC2, square_point_data);
let color = new cv.Scalar (255);
let expected_img_data = new Uint8Array([
0, 0, 0, 0, 0, 0,
0, 255, 255, 255, 255, 0,
0, 255, 255, 255, 255, 0,
0, 255, 255, 255, 255, 0,
0, 255, 255, 255, 255, 0,
0, 0, 0, 0, 0, 0]);
let expected_img = cv.matFromArray(img_height, img_width, cv.CV_8UC1, expected_img_data);
cv.fillConvexPoly(img, square_points, color);
let compare_result = new cv.Mat(img_height, img_width, cv.CV_8UC1);
cv.compare (img, expected_img, compare_result, cv.CMP_EQ);
// expect every pixels are the same.
assert.equal (cv.countNonZero(compare_result), img.total());
img.delete();
square_points.delete();
expected_img.delete();
compare_result.delete();
}
});
QUnit.test('test_segmentation', function(assert) {
const THRESHOLD = 127.0;
const THRESHOLD_MAX = 210.0;
// threshold
{
let source = new cv.Mat(1, 5, cv.CV_8UC1);
let sourceView = source.data;
sourceView[0] = 0; // < threshold
sourceView[1] = 100; // < threshold
sourceView[2] = 200; // > threshold
let dest = new cv.Mat();
cv.threshold(source, dest, THRESHOLD, THRESHOLD_MAX, cv.THRESH_BINARY);
let destView = dest.data;
assert.equal(destView[0], 0);
assert.equal(destView[1], 0);
assert.equal(destView[2], THRESHOLD_MAX);
}
// adaptiveThreshold
{
let source = cv.Mat.zeros(1, 5, cv.CV_8UC1);
let sourceView = source.data;
sourceView[0] = 50;
sourceView[1] = 150;
sourceView[2] = 200;
let dest = new cv.Mat();
const C = 0;
const blockSize = 3;
cv.adaptiveThreshold(source, dest, THRESHOLD_MAX,
cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, blockSize, C);
let destView = dest.data;
assert.equal(destView[0], 0);
assert.equal(destView[1], THRESHOLD_MAX);
assert.equal(destView[2], THRESHOLD_MAX);
}
});
QUnit.test('test_shape', function(assert) {
// moments
{
let points = new cv.Mat(1, 4, cv.CV_32SC2);
let data32S = points.data32S;
data32S[0]=50;
data32S[1]=56;
data32S[2]=53;
data32S[3]=53;
data32S[4]=46;
data32S[5]=54;
data32S[6]=49;
data32S[7]=51;
let m = cv.moments(points, false);
let area = cv.contourArea(points, false);
assert.equal(m.m00, 0);
assert.equal(m.m01, 0);
assert.equal(m.m10, 0);
assert.equal(area, 0);
// default parameters
m = cv.moments(points);
area = cv.contourArea(points);
assert.equal(m.m00, 0);
assert.equal(m.m01, 0);
assert.equal(m.m10, 0);
assert.equal(area, 0);
points.delete();
}
});
QUnit.test('test_min_enclosing', function(assert) {
{
let points = new cv.Mat(4, 1, cv.CV_32FC2);
points.data32F[0] = 0;
points.data32F[1] = 0;
points.data32F[2] = 1;
points.data32F[3] = 0;
points.data32F[4] = 1;
points.data32F[5] = 1;
points.data32F[6] = 0;
points.data32F[7] = 1;
let circle = cv.minEnclosingCircle(points);
assert.deepEqual(circle.center, {x: 0.5, y: 0.5});
assert.ok(Math.abs(circle.radius - Math.sqrt(2) / 2) < 0.001);
points.delete();
}
});
QUnit.test('test_filter', function(assert) {
// blur
{
let mat1 = cv.Mat.ones(5, 5, cv.CV_8UC3);
let mat2 = new cv.Mat();
cv.blur(mat1, mat2, {height: 3, width: 3}, {x: -1, y: -1}, cv.BORDER_DEFAULT);
// Verify result.
let size = mat2.size();
assert.equal(mat2.channels(), 3);
assert.equal(size.height, 5);
assert.equal(size.width, 5);
cv.blur(mat1, mat2, {height: 3, width: 3}, {x: -1, y: -1});
// Verify result.
size = mat2.size();
assert.equal(mat2.channels(), 3);
assert.equal(size.height, 5);
assert.equal(size.width, 5);
cv.blur(mat1, mat2, {height: 3, width: 3});
// Verify result.
size = mat2.size();
assert.equal(mat2.channels(), 3);
assert.equal(size.height, 5);
assert.equal(size.width, 5);
mat1.delete();
mat2.delete();
}
// GaussianBlur
{
let mat1 = cv.Mat.ones(7, 7, cv.CV_8UC1);
let mat2 = new cv.Mat();
cv.GaussianBlur(mat1, mat2, new cv.Size(3, 3), 0, 0, // eslint-disable-line new-cap
cv.BORDER_DEFAULT);
// Verify result.
let size = mat2.size();
assert.equal(mat2.channels(), 1);
assert.equal(size.height, 7);
assert.equal(size.width, 7);
}
// medianBlur
{
let mat1 = cv.Mat.ones(9, 9, cv.CV_8UC3);
let mat2 = new cv.Mat();
cv.medianBlur(mat1, mat2, 3);
// Verify result.
let size = mat2.size();
assert.equal(mat2.channels(), 3);
assert.equal(size.height, 9);
assert.equal(size.width, 9);
}
// Transpose
{
let mat1 = cv.Mat.eye(9, 9, cv.CV_8UC3);
let mat2 = new cv.Mat();
cv.transpose(mat1, mat2);
// Verify result.
let size = mat2.size();
assert.equal(mat2.channels(), 3);
assert.equal(size.height, 9);
assert.equal(size.width, 9);
}
// bilateralFilter
{
let mat1 = cv.Mat.ones(11, 11, cv.CV_8UC3);
let mat2 = new cv.Mat();
cv.bilateralFilter(mat1, mat2, 3, 6, 1.5, cv.BORDER_DEFAULT);
// Verify result.
let size = mat2.size();
assert.equal(mat2.channels(), 3);
assert.equal(size.height, 11);
assert.equal(size.width, 11);
// default parameters
cv.bilateralFilter(mat1, mat2, 3, 6, 1.5);
// Verify result.
size = mat2.size();
assert.equal(mat2.channels(), 3);
assert.equal(size.height, 11);
assert.equal(size.width, 11);
mat1.delete();
mat2.delete();
}
// Watershed
{
let mat = cv.Mat.ones(11, 11, cv.CV_8UC3);
let out = new cv.Mat(11, 11, cv.CV_32SC1);
cv.watershed(mat, out);
// Verify result.
let size = out.size();
assert.equal(out.channels(), 1);
assert.equal(size.height, 11);
assert.equal(size.width, 11);
assert.equal(out.elemSize1(), 4);
mat.delete();
out.delete();
}
// Concat
{
let mat = cv.Mat.ones({height: 10, width: 5}, cv.CV_8UC3);
let mat2 = cv.Mat.eye({height: 10, width: 5}, cv.CV_8UC3);
let mat3 = cv.Mat.eye({height: 10, width: 5}, cv.CV_8UC3);
let out = new cv.Mat();
let input = new cv.MatVector();
input.push_back(mat);
input.push_back(mat2);
input.push_back(mat3);
cv.vconcat(input, out);
// Verify result.
let size = out.size();
assert.equal(out.channels(), 3);
assert.equal(size.height, 30);
assert.equal(size.width, 5);
assert.equal(out.elemSize1(), 1);
cv.hconcat(input, out);
// Verify result.
size = out.size();
assert.equal(out.channels(), 3);
assert.equal(size.height, 10);
assert.equal(size.width, 15);
assert.equal(out.elemSize1(), 1);
input.delete();
out.delete();
}
// distanceTransform letiants
{
let mat = cv.Mat.ones(11, 11, cv.CV_8UC1);
let out = new cv.Mat(11, 11, cv.CV_32FC1);
let labels = new cv.Mat(11, 11, cv.CV_32FC1);
const maskSize = 3;
cv.distanceTransform(mat, out, cv.DIST_L2, maskSize, cv.CV_32F);
// Verify result.
let size = out.size();
assert.equal(out.channels(), 1);
assert.equal(size.height, 11);
assert.equal(size.width, 11);
assert.equal(out.elemSize1(), 4);
cv.distanceTransformWithLabels(mat, out, labels, cv.DIST_L2, maskSize,
cv.DIST_LABEL_CCOMP);
// Verify result.
size = out.size();
assert.equal(out.channels(), 1);
assert.equal(size.height, 11);
assert.equal(size.width, 11);
assert.equal(out.elemSize1(), 4);
size = labels.size();
assert.equal(labels.channels(), 1);
assert.equal(size.height, 11);
assert.equal(size.width, 11);
assert.equal(labels.elemSize1(), 4);
mat.delete();
out.delete();
labels.delete();
}
// Min, Max
{
let data1 = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9]);
let data2 = new Uint8Array([0, 4, 0, 8, 0, 12, 0, 16, 0]);
let expectedMin = new Uint8Array([0, 2, 0, 4, 0, 6, 0, 8, 0]);
let expectedMax = new Uint8Array([1, 4, 3, 8, 5, 12, 7, 16, 9]);
let dataPtr = cv._malloc(3*3*1);
let dataPtr2 = cv._malloc(3*3*1);
let dataHeap = new Uint8Array(cv.HEAPU8.buffer, dataPtr, 3*3*1);
dataHeap.set(new Uint8Array(data1.buffer));
let dataHeap2 = new Uint8Array(cv.HEAPU8.buffer, dataPtr2, 3*3*1);
dataHeap2.set(new Uint8Array(data2.buffer));
let mat1 = new cv.Mat(3, 3, cv.CV_8UC1, dataPtr, 0);
let mat2 = new cv.Mat(3, 3, cv.CV_8UC1, dataPtr2, 0);
let mat3 = new cv.Mat();
cv.min(mat1, mat2, mat3);
// Verify result.
let size = mat2.size();
assert.equal(mat2.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqual(mat3.data, expectedMin);
cv.max(mat1, mat2, mat3);
// Verify result.
size = mat2.size();
assert.equal(mat2.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqual(mat3.data, expectedMax);
cv._free(dataPtr);
cv._free(dataPtr2);
}
// Bitwise operations
{
let data1 = new Uint8Array([0, 1, 2, 4, 8, 16, 32, 64, 128]);
let data2 = new Uint8Array([255, 255, 255, 255, 255, 255, 255, 255, 255]);
let expectedAnd = new Uint8Array([0, 1, 2, 4, 8, 16, 32, 64, 128]);
let expectedOr = new Uint8Array([255, 255, 255, 255, 255, 255, 255, 255, 255]);
let expectedXor = new Uint8Array([255, 254, 253, 251, 247, 239, 223, 191, 127]);
let expectedNot = new Uint8Array([255, 254, 253, 251, 247, 239, 223, 191, 127]);
let dataPtr = cv._malloc(3*3*1);
let dataPtr2 = cv._malloc(3*3*1);
let dataHeap = new Uint8Array(cv.HEAPU8.buffer, dataPtr, 3*3*1);
dataHeap.set(new Uint8Array(data1.buffer));
let dataHeap2 = new Uint8Array(cv.HEAPU8.buffer, dataPtr2, 3*3*1);
dataHeap2.set(new Uint8Array(data2.buffer));
let mat1 = new cv.Mat(3, 3, cv.CV_8UC1, dataPtr, 0);
let mat2 = new cv.Mat(3, 3, cv.CV_8UC1, dataPtr2, 0);
let mat3 = new cv.Mat();
let none = new cv.Mat();
cv.bitwise_not(mat1, mat3, none);
// Verify result.
let size = mat3.size();
assert.equal(mat3.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqual(mat3.data, expectedNot);
cv.bitwise_and(mat1, mat2, mat3, none);
// Verify result.
size = mat3.size();
assert.equal(mat3.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqual(mat3.data, expectedAnd);
cv.bitwise_or(mat1, mat2, mat3, none);
// Verify result.
size = mat3.size();
assert.equal(mat3.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqual(mat3.data, expectedOr);
cv.bitwise_xor(mat1, mat2, mat3, none);
// Verify result.
size = mat3.size();
assert.equal(mat3.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqual(mat3.data, expectedXor);
cv._free(dataPtr);
cv._free(dataPtr2);
}
// Arithmetic operations
{
let data1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8]);
let data2 = new Uint8Array([0, 2, 4, 6, 8, 10, 12, 14, 16]);
let data3 = new Uint8Array([0, 1, 0, 1, 0, 1, 0, 1, 0]);
// |data1 - data2|
let expectedAbsDiff = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8]);
let expectedAdd = new Uint8Array([0, 3, 6, 9, 12, 15, 18, 21, 24]);
const alpha = 4;
const beta = -1;
const gamma = 3;
// 4*data1 - data2 + 3
let expectedWeightedAdd = new Uint8Array([3, 5, 7, 9, 11, 13, 15, 17, 19]);
let dataPtr = cv._malloc(3*3*1);
let dataPtr2 = cv._malloc(3*3*1);
let dataPtr3 = cv._malloc(3*3*1);
let dataHeap = new Uint8Array(cv.HEAPU8.buffer, dataPtr, 3*3*1);
dataHeap.set(new Uint8Array(data1.buffer));
let dataHeap2 = new Uint8Array(cv.HEAPU8.buffer, dataPtr2, 3*3*1);
dataHeap2.set(new Uint8Array(data2.buffer));
let dataHeap3 = new Uint8Array(cv.HEAPU8.buffer, dataPtr3, 3*3*1);
dataHeap3.set(new Uint8Array(data3.buffer));
let mat1 = new cv.Mat(3, 3, cv.CV_8UC1, dataPtr, 0);
let mat2 = new cv.Mat(3, 3, cv.CV_8UC1, dataPtr2, 0);
let mat3 = new cv.Mat(3, 3, cv.CV_8UC1, dataPtr3, 0);
let dst = new cv.Mat();
let none = new cv.Mat();
cv.absdiff(mat1, mat2, dst);
// Verify result.
let size = dst.size();
assert.equal(dst.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqual(dst.data, expectedAbsDiff);
cv.add(mat1, mat2, dst, none, -1);
// Verify result.
size = dst.size();
assert.equal(dst.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqual(dst.data, expectedAdd);
cv.addWeighted(mat1, alpha, mat2, beta, gamma, dst, -1);
// Verify result.
size = dst.size();
assert.equal(dst.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqual(dst.data, expectedWeightedAdd);
// default parameter
cv.addWeighted(mat1, alpha, mat2, beta, gamma, dst);
// Verify result.
size = dst.size();
assert.equal(dst.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqual(dst.data, expectedWeightedAdd);
mat1.delete();
mat2.delete();
mat3.delete();
dst.delete();
none.delete();
}
// Integral letiants
{
let mat = cv.Mat.eye({height: 100, width: 100}, cv.CV_8UC3);
let sum = new cv.Mat();
let sqSum = new cv.Mat();
let title = new cv.Mat();
cv.integral(mat, sum, -1);
// Verify result.
let size = sum.size();
assert.equal(sum.channels(), 3);
assert.equal(size.height, 100+1);
assert.equal(size.width, 100+1);
cv.integral2(mat, sum, sqSum, -1, -1);
// Verify result.
size = sum.size();
assert.equal(sum.channels(), 3);
assert.equal(size.height, 100+1);
assert.equal(size.width, 100+1);
size = sqSum.size();
assert.equal(sqSum.channels(), 3);
assert.equal(size.height, 100+1);
assert.equal(size.width, 100+1);
mat.delete();
sum.delete();
sqSum.delete();
title.delete();
}
// Mean, meanSTDev
{
let mat = cv.Mat.eye({height: 100, width: 100}, cv.CV_8UC3);
let sum = new cv.Mat();
let sqSum = new cv.Mat();
let title = new cv.Mat();
cv.integral(mat, sum, -1);
// Verify result.
let size = sum.size();
assert.equal(sum.channels(), 3);
assert.equal(size.height, 100+1);
assert.equal(size.width, 100+1);
cv.integral2(mat, sum, sqSum, -1, -1);
// Verify result.
size = sum.size();
assert.equal(sum.channels(), 3);
assert.equal(size.height, 100+1);
assert.equal(size.width, 100+1);
size = sqSum.size();
assert.equal(sqSum.channels(), 3);
assert.equal(size.height, 100+1);
assert.equal(size.width, 100+1);
mat.delete();
sum.delete();
sqSum.delete();
title.delete();
}
// Invert
{
let inv1 = new cv.Mat();
let inv2 = new cv.Mat();
let inv3 = new cv.Mat();
let inv4 = new cv.Mat();
let data1 = new Float32Array([1, 0, 0,
0, 1, 0,
0, 0, 1]);
let data2 = new Float32Array([0, 0, 0,
0, 5, 0,
0, 0, 0]);
let data3 = new Float32Array([1, 1, 1, 0,
0, 3, 1, 2,
2, 3, 1, 0,
1, 0, 2, 1]);
let data4 = new Float32Array([1, 4, 5,
4, 2, 2,
5, 2, 2]);
let expected1 = new Float32Array([1, 0, 0,
0, 1, 0,
0, 0, 1]);
// Inverse does not exist!
let expected3 = new Float32Array([-3, -1/2, 3/2, 1,
1, 1/4, -1/4, -1/2,
3, 1/4, -5/4, -1/2,
-3, 0, 1, 1]);
let expected4 = new Float32Array([0, -1, 1,
-1, 23/2, -9,
1, -9, 7]);
let dataPtr1 = cv._malloc(3*3*4);
let dataPtr2 = cv._malloc(3*3*4);
let dataPtr3 = cv._malloc(4*4*4);
let dataPtr4 = cv._malloc(3*3*4);
let dataHeap = new Float32Array(cv.HEAP32.buffer, dataPtr1, 3*3);
dataHeap.set(new Float32Array(data1.buffer));
let dataHeap2 = new Float32Array(cv.HEAP32.buffer, dataPtr2, 3*3);
dataHeap2.set(new Float32Array(data2.buffer));
let dataHeap3 = new Float32Array(cv.HEAP32.buffer, dataPtr3, 4*4);
dataHeap3.set(new Float32Array(data3.buffer));
let dataHeap4 = new Float32Array(cv.HEAP32.buffer, dataPtr4, 3*3);
dataHeap4.set(new Float32Array(data4.buffer));
let mat1 = new cv.Mat(3, 3, cv.CV_32FC1, dataPtr1, 0);
let mat2 = new cv.Mat(3, 3, cv.CV_32FC1, dataPtr2, 0);
let mat3 = new cv.Mat(4, 4, cv.CV_32FC1, dataPtr3, 0);
let mat4 = new cv.Mat(3, 3, cv.CV_32FC1, dataPtr4, 0);
QUnit.assert.deepEqualWithTolerance = function( value, expected, tolerance ) {
for (let i = 0; i < value.length; i= i+1) {
this.pushResult( {
result: Math.abs(value[i]-expected[i]) < tolerance,
actual: value[i],
expected: expected[i],
} );
}
};
cv.invert(mat1, inv1, 0);
// Verify result.
let size = inv1.size();
assert.equal(inv1.channels(), 1);
assert.equal(size.height, 3);
assert.equal(size.width, 3);
assert.deepEqualWithTolerance(inv1.data32F, expected1, 0.0001);
cv.invert(mat2, inv2, 0);
// Verify result.
assert.deepEqualWithTolerance(inv3.data32F, expected3, 0.0001);
cv.invert(mat3, inv3, 0);
// Verify result.
size = inv3.size();
assert.equal(inv3.channels(), 1);
assert.equal(size.height, 4);
assert.equal(size.width, 4);
assert.deepEqualWithTolerance(inv3.data32F, expected3, 0.0001);
cv.invert(mat3, inv3, 1);
// Verify result.
assert.deepEqualWithTolerance(inv3.data32F, expected3, 0.0001);
cv.invert(mat4, inv4, 2);
// Verify result.
assert.deepEqualWithTolerance(inv4.data32F, expected4, 0.0001);
cv.invert(mat4, inv4, 3);
// Verify result.
assert.deepEqualWithTolerance(inv4.data32F, expected4, 0.0001);
mat1.delete();
mat2.delete();
mat3.delete();
mat4.delete();
inv1.delete();
inv2.delete();
inv3.delete();
inv4.delete();
}
//Rotate
{
let dst = new cv.Mat();
let src = cv.matFromArray(3, 2, cv.CV_8U, [1,2,3,4,5,6]);
cv.rotate(src, dst, cv.ROTATE_90_CLOCKWISE);
size = dst.size();
assert.equal(size.height, 2, "ROTATE_HEIGHT");
assert.equal(size.width, 3, "ROTATE_WIGTH");
let expected = new Uint8Array([5,3,1,6,4,2]);
assert.deepEqual(dst.data, expected);
dst.delete();
src.delete();
}
});
QUnit.test('warpPolar', function(assert) {
const lines = new cv.Mat(255, 255, cv.CV_8U, new cv.Scalar(0));
for (let r = 0; r < lines.rows; r++) {
lines.row(r).setTo(new cv.Scalar(r));
}
cv.warpPolar(lines, lines, { width: 5, height: 5 }, new cv.Point(2, 2), 3,
cv.INTER_CUBIC | cv.WARP_FILL_OUTLIERS | cv.WARP_INVERSE_MAP);
assert.ok(lines instanceof cv.Mat);
assert.deepEqual(Array.from(lines.data), [
159, 172, 191, 210, 223,
146, 159, 191, 223, 236,
128, 128, 0, 0, 0,
109, 96, 64, 32, 19,
96, 83, 64, 45, 32
]);
});

View File

@@ -0,0 +1,987 @@
// //////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//
// //////////////////////////////////////////////////////////////////////////////////////
// Author: Sajjad Taheri, University of California, Irvine. sajjadt[at]uci[dot]edu
//
// LICENSE AGREEMENT
// Copyright (c) 2015 The Regents of the University of California (Regents)
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the University nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
if (typeof module !== 'undefined' && module.exports) {
// The environment is Node.js
var cv = require('./opencv.js'); // eslint-disable-line no-var
}
QUnit.module('Core', {});
QUnit.test('test_mat_creation', function(assert) {
// Mat constructors.
// Mat::Mat(int rows, int cols, int type)
{
let mat = new cv.Mat(10, 20, cv.CV_8UC3);
assert.equal(mat.type(), cv.CV_8UC3);
assert.equal(mat.depth(), cv.CV_8U);
assert.equal(mat.channels(), 3);
assert.ok(mat.empty() === false);
let size = mat.size();
assert.equal(size.height, 10);
assert.equal(size.width, 20);
mat.delete();
}
// Mat::Mat(const Mat &)
{
// Copy from another Mat
let mat1 = new cv.Mat(10, 20, cv.CV_8UC3);
let mat2 = new cv.Mat(mat1);
assert.equal(mat2.type(), mat1.type());
assert.equal(mat2.depth(), mat1.depth());
assert.equal(mat2.channels(), mat1.channels());
assert.equal(mat2.empty(), mat1.empty());
let size1 = mat1.size;
let size2 = mat2.size();
assert.ok(size1[0] === size2[0]);
assert.ok(size1[1] === size2[1]);
mat1.delete();
mat2.delete();
}
// Mat::Mat(int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
{
// 10 * 10 and one channel
let data = cv._malloc(10 * 10 * 1);
let mat = new cv.Mat(10, 10, cv.CV_8UC1, data, 0);
assert.equal(mat.type(), cv.CV_8UC1);
assert.equal(mat.depth(), cv.CV_8U);
assert.equal(mat.channels(), 1);
assert.ok(mat.empty() === false);
let size = mat.size();
assert.ok(size.height === 10);
assert.ok(size.width === 10);
mat.delete();
}
// Mat::Mat(int rows, int cols, int type, const Scalar& scalar)
{
// 2 * 2 8UC4 mat
let mat = new cv.Mat(2, 2, cv.CV_8UC4, [0, 1, 2, 3]);
for (let r = 0; r < mat.rows; r++) {
for (let c = 0; c < mat.cols; c++) {
let element = mat.ptr(r, c);
assert.equal(element[0], 0);
assert.equal(element[1], 1);
assert.equal(element[2], 2);
assert.equal(element[3], 3);
}
}
mat.delete();
}
// Mat::create(int, int, int)
{
let mat = new cv.Mat();
mat.create(10, 5, cv.CV_8UC3);
let size = mat.size();
assert.ok(mat.type() === cv.CV_8UC3);
assert.ok(size.height === 10);
assert.ok(size.width === 5);
assert.ok(mat.channels() === 3);
mat.delete();
}
// Mat::create(Size, int)
{
let mat = new cv.Mat();
mat.create({height: 10, width: 5}, cv.CV_8UC4);
let size = mat.size();
assert.ok(mat.type() === cv.CV_8UC4);
assert.ok(size.height === 10);
assert.ok(size.width === 5);
assert.ok(mat.channels() === 4);
mat.delete();
}
// clone
{
let mat = cv.Mat.ones(5, 5, cv.CV_8UC1);
let mat2 = mat.clone();
assert.equal(mat.channels, mat2.channels);
assert.equal(mat.size().height, mat2.size().height);
assert.equal(mat.size().width, mat2.size().width);
assert.deepEqual(mat.data, mat2.data);
mat.delete();
mat2.delete();
}
// copyTo
{
let mat = cv.Mat.ones(5, 5, cv.CV_8UC1);
let mat2 = new cv.Mat();
mat.copyTo(mat2);
assert.equal(mat.channels, mat2.channels);
assert.equal(mat.size().height, mat2.size().height);
assert.equal(mat.size().width, mat2.size().width);
assert.deepEqual(mat.data, mat2.data);
mat.delete();
mat2.delete();
}
// copyTo1
{
let mat = cv.Mat.ones(5, 5, cv.CV_8UC1);
let mat2 = new cv.Mat();
let mask = new cv.Mat(5, 5, cv.CV_8UC1, new cv.Scalar(1));
mat.copyTo(mat2, mask);
assert.equal(mat.channels, mat2.channels);
assert.equal(mat.size().height, mat2.size().height);
assert.equal(mat.size().width, mat2.size().width);
assert.deepEqual(mat.data, mat2.data);
mat.delete();
mat2.delete();
mask.delete();
}
// matFromArray
{
let arrayC1 = [0, -1, 2, -3];
let arrayC2 = [0, -1, 2, -3, 4, -5, 6, -7];
let arrayC3 = [0, -1, 2, -3, 4, -5, 6, -7, 9, -9, 10, -11];
let arrayC4 = [0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, 13, 14, 15];
let mat8UC1 = cv.matFromArray(2, 2, cv.CV_8UC1, arrayC1);
let mat8UC2 = cv.matFromArray(2, 2, cv.CV_8UC2, arrayC2);
let mat8UC3 = cv.matFromArray(2, 2, cv.CV_8UC3, arrayC3);
let mat8UC4 = cv.matFromArray(2, 2, cv.CV_8UC4, arrayC4);
let mat8SC1 = cv.matFromArray(2, 2, cv.CV_8SC1, arrayC1);
let mat8SC2 = cv.matFromArray(2, 2, cv.CV_8SC2, arrayC2);
let mat8SC3 = cv.matFromArray(2, 2, cv.CV_8SC3, arrayC3);
let mat8SC4 = cv.matFromArray(2, 2, cv.CV_8SC4, arrayC4);
let mat16UC1 = cv.matFromArray(2, 2, cv.CV_16UC1, arrayC1);
let mat16UC2 = cv.matFromArray(2, 2, cv.CV_16UC2, arrayC2);
let mat16UC3 = cv.matFromArray(2, 2, cv.CV_16UC3, arrayC3);
let mat16UC4 = cv.matFromArray(2, 2, cv.CV_16UC4, arrayC4);
let mat16SC1 = cv.matFromArray(2, 2, cv.CV_16SC1, arrayC1);
let mat16SC2 = cv.matFromArray(2, 2, cv.CV_16SC2, arrayC2);
let mat16SC3 = cv.matFromArray(2, 2, cv.CV_16SC3, arrayC3);
let mat16SC4 = cv.matFromArray(2, 2, cv.CV_16SC4, arrayC4);
let mat32SC1 = cv.matFromArray(2, 2, cv.CV_32SC1, arrayC1);
let mat32SC2 = cv.matFromArray(2, 2, cv.CV_32SC2, arrayC2);
let mat32SC3 = cv.matFromArray(2, 2, cv.CV_32SC3, arrayC3);
let mat32SC4 = cv.matFromArray(2, 2, cv.CV_32SC4, arrayC4);
let mat32FC1 = cv.matFromArray(2, 2, cv.CV_32FC1, arrayC1);
let mat32FC2 = cv.matFromArray(2, 2, cv.CV_32FC2, arrayC2);
let mat32FC3 = cv.matFromArray(2, 2, cv.CV_32FC3, arrayC3);
let mat32FC4 = cv.matFromArray(2, 2, cv.CV_32FC4, arrayC4);
let mat64FC1 = cv.matFromArray(2, 2, cv.CV_64FC1, arrayC1);
let mat64FC2 = cv.matFromArray(2, 2, cv.CV_64FC2, arrayC2);
let mat64FC3 = cv.matFromArray(2, 2, cv.CV_64FC3, arrayC3);
let mat64FC4 = cv.matFromArray(2, 2, cv.CV_64FC4, arrayC4);
assert.deepEqual(mat8UC1.data, new Uint8Array(arrayC1));
assert.deepEqual(mat8UC2.data, new Uint8Array(arrayC2));
assert.deepEqual(mat8UC3.data, new Uint8Array(arrayC3));
assert.deepEqual(mat8UC4.data, new Uint8Array(arrayC4));
assert.deepEqual(mat8SC1.data8S, new Int8Array(arrayC1));
assert.deepEqual(mat8SC2.data8S, new Int8Array(arrayC2));
assert.deepEqual(mat8SC3.data8S, new Int8Array(arrayC3));
assert.deepEqual(mat8SC4.data8S, new Int8Array(arrayC4));
assert.deepEqual(mat16UC1.data16U, new Uint16Array(arrayC1));
assert.deepEqual(mat16UC2.data16U, new Uint16Array(arrayC2));
assert.deepEqual(mat16UC3.data16U, new Uint16Array(arrayC3));
assert.deepEqual(mat16UC4.data16U, new Uint16Array(arrayC4));
assert.deepEqual(mat16SC1.data16S, new Int16Array(arrayC1));
assert.deepEqual(mat16SC2.data16S, new Int16Array(arrayC2));
assert.deepEqual(mat16SC3.data16S, new Int16Array(arrayC3));
assert.deepEqual(mat16SC4.data16S, new Int16Array(arrayC4));
assert.deepEqual(mat32SC1.data32S, new Int32Array(arrayC1));
assert.deepEqual(mat32SC2.data32S, new Int32Array(arrayC2));
assert.deepEqual(mat32SC3.data32S, new Int32Array(arrayC3));
assert.deepEqual(mat32SC4.data32S, new Int32Array(arrayC4));
assert.deepEqual(mat32FC1.data32F, new Float32Array(arrayC1));
assert.deepEqual(mat32FC2.data32F, new Float32Array(arrayC2));
assert.deepEqual(mat32FC3.data32F, new Float32Array(arrayC3));
assert.deepEqual(mat32FC4.data32F, new Float32Array(arrayC4));
assert.deepEqual(mat64FC1.data64F, new Float64Array(arrayC1));
assert.deepEqual(mat64FC2.data64F, new Float64Array(arrayC2));
assert.deepEqual(mat64FC3.data64F, new Float64Array(arrayC3));
assert.deepEqual(mat64FC4.data64F, new Float64Array(arrayC4));
mat8UC1.delete();
mat8UC2.delete();
mat8UC3.delete();
mat8UC4.delete();
mat8SC1.delete();
mat8SC2.delete();
mat8SC3.delete();
mat8SC4.delete();
mat16UC1.delete();
mat16UC2.delete();
mat16UC3.delete();
mat16UC4.delete();
mat16SC1.delete();
mat16SC2.delete();
mat16SC3.delete();
mat16SC4.delete();
mat32SC1.delete();
mat32SC2.delete();
mat32SC3.delete();
mat32SC4.delete();
mat32FC1.delete();
mat32FC2.delete();
mat32FC3.delete();
mat32FC4.delete();
mat64FC1.delete();
mat64FC2.delete();
mat64FC3.delete();
mat64FC4.delete();
}
// matFromImageData
{
// Only test in browser
if (typeof window === 'undefined') {
return;
}
let canvas = window.document.createElement('canvas');
canvas.width = 2;
canvas.height = 2;
let ctx = canvas.getContext('2d');
ctx.fillStyle='#FF0000';
ctx.fillRect(0, 0, 1, 1);
ctx.fillRect(1, 1, 1, 1);
let imageData = ctx.getImageData(0, 0, 2, 2);
let mat = cv.matFromImageData(imageData);
assert.deepEqual(mat.data, new Uint8Array(imageData.data));
mat.delete();
}
// Mat(mat)
{
let mat = new cv.Mat(2, 2, cv.CV_8UC4, new cv.Scalar(1, 0, 1, 0));
let mat1 = new cv.Mat(mat);
let mat2 = mat;
assert.equal(mat.rows, mat1.rows);
assert.equal(mat.cols, mat1.cols);
assert.equal(mat.type(), mat1.type());
assert.deepEqual(mat.data, mat1.data);
mat.delete();
assert.equal(mat1.isDeleted(), false);
assert.equal(mat2.isDeleted(), true);
mat1.delete();
}
// mat.setTo
{
let mat = new cv.Mat(2, 2, cv.CV_8UC4);
let s = [0, 1, 2, 3];
mat.setTo(s);
assert.deepEqual(mat.ptr(0, 0), new Uint8Array(s));
assert.deepEqual(mat.ptr(0, 1), new Uint8Array(s));
assert.deepEqual(mat.ptr(1, 0), new Uint8Array(s));
assert.deepEqual(mat.ptr(1, 1), new Uint8Array(s));
let s1 = [0, 0, 0, 0];
mat.setTo(s1);
let mask = cv.matFromArray(2, 2, cv.CV_8UC1, [0, 1, 0, 1]);
mat.setTo(s, mask);
assert.deepEqual(mat.ptr(0, 0), new Uint8Array(s1));
assert.deepEqual(mat.ptr(0, 1), new Uint8Array(s));
assert.deepEqual(mat.ptr(1, 0), new Uint8Array(s1));
assert.deepEqual(mat.ptr(1, 1), new Uint8Array(s));
mat.delete();
mask.delete();
}
});
QUnit.test('test_mat_ptr', function(assert) {
const RValue = 3;
const GValue = 7;
const BValue = 197;
// cv.CV_8UC1 + Mat::ptr(int).
{
let mat = new cv.Mat(10, 10, cv.CV_8UC1);
let view = mat.data;
// Alter matrix[2, 1].
let step = 10;
view[2 * step + 1] = RValue;
// Access matrix[2, 1].
view = mat.ptr(2);
assert.equal(view[1], RValue);
mat.delete();
}
// cv.CV_8UC3 + Mat::ptr(int).
{
let mat = new cv.Mat(10, 10, cv.CV_8UC3);
let view = mat.data;
// Alter matrix[2, 1].
let step = 3 * 10;
view[2 * step + 3] = RValue;
view[2 * step + 3 + 1] = GValue;
view[2 * step + 3 + 2] = BValue;
// Access matrix[2, 1].
view = mat.ptr(2);
assert.equal(view[3], RValue);
assert.equal(view[3 + 1], GValue);
assert.equal(view[3 + 2], BValue);
mat.delete();
}
// cv.CV_8UC3 + Mat::ptr(int, int).
{
let mat = new cv.Mat(10, 10, cv.CV_8UC3);
let view = mat.data;
// Alter matrix[2, 1].
let step = 3 * 10;
view[2 * step + 3] = RValue;
view[2 * step + 3 + 1] = GValue;
view[2 * step + 3 + 2] = BValue;
// Access matrix[2, 1].
view = mat.ptr(2, 1);
assert.equal(view[0], RValue);
assert.equal(view[1], GValue);
assert.equal(view[2], BValue);
mat.delete();
}
const RValueF32 = 3.3;
const GValueF32 = 7.3;
const BValueF32 = 197.3;
const EPSILON = 0.001;
// cv.CV_32FC1 + Mat::ptr(int).
{
let mat = new cv.Mat(10, 10, cv.CV_32FC1);
let view = mat.data32F;
// Alter matrix[2, 1].
let step = 10;
view[2 * step + 1] = RValueF32;
// Access matrix[2, 1].
view = mat.floatPtr(2);
assert.ok(Math.abs(view[1] - RValueF32) < EPSILON);
mat.delete();
}
// cv.CV_32FC3 + Mat::ptr(int).
{
let mat = new cv.Mat(10, 10, cv.CV_32FC3);
let view = mat.data32F;
// Alter matrix[2, 1].
let step = mat.step1(0);
view[2 * step + 3] = RValueF32;
view[2 * step + 3 + 1] = GValueF32;
view[2 * step + 3 + 2] = BValueF32;
// Access matrix[2, 1].
view = mat.floatPtr(2);
assert.ok(Math.abs(view[3] - RValueF32) < EPSILON);
assert.ok(Math.abs(view[3 + 1] - GValueF32) < EPSILON);
assert.ok(Math.abs(view[3 + 2] - BValueF32) < EPSILON);
mat.delete();
}
// cv.CV_32FC3 + Mat::ptr(int, int).
{
let mat = new cv.Mat(10, 10, cv.CV_32FC3);
let view = mat.data32F;
// Alter matrix[2, 1].
let step = mat.step1(0);
view[2 * step + 3] = RValueF32;
view[2 * step + 3 + 1] = GValueF32;
view[2 * step + 3 + 2] = BValueF32;
// Access matrix[2, 1].
view = mat.floatPtr(2, 1);
assert.ok(Math.abs(view[0] - RValueF32) < EPSILON);
assert.ok(Math.abs(view[1] - GValueF32) < EPSILON);
assert.ok(Math.abs(view[2] - BValueF32) < EPSILON);
mat.delete();
}
});
QUnit.test('test_mat_zeros', function(assert) {
let zeros = new Uint8Array(10*10).fill(0);
// Mat::zeros(int, int, int)
{
let mat = cv.Mat.zeros(10, 10, cv.CV_8UC1);
let view = mat.data;
assert.deepEqual(view, zeros);
mat.delete();
}
// Mat::zeros(Size, int)
{
let mat = cv.Mat.zeros({height: 10, width: 10}, cv.CV_8UC1);
let view = mat.data;
assert.deepEqual(view, zeros);
mat.delete();
}
});
QUnit.test('test_mat_ones', function(assert) {
let ones = new Uint8Array(10*10).fill(1);
// Mat::ones(int, int, int)
{
let mat = cv.Mat.ones(10, 10, cv.CV_8UC1);
let view = mat.data;
assert.deepEqual(view, ones);
}
// Mat::ones(Size, int)
{
let mat = cv.Mat.ones({height: 10, width: 10}, cv.CV_8UC1);
let view = mat.data;
assert.deepEqual(view, ones);
}
});
QUnit.test('test_mat_eye', function(assert) {
let eye4by4 = new Uint8Array([1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1]);
// Mat::eye(int, int, int)
{
let mat = cv.Mat.eye(4, 4, cv.CV_8UC1);
let view = mat.data;
assert.deepEqual(view, eye4by4);
}
// Mat::eye(Size, int)
{
let mat = cv.Mat.eye({height: 4, width: 4}, cv.CV_8UC1);
let view = mat.data;
assert.deepEqual(view, eye4by4);
}
});
QUnit.test('test_mat_miscs', function(assert) {
// Mat::col(int)
{
let mat = cv.matFromArray(2, 2, cv.CV_8UC2, [1, 2, 3, 4, 5, 6, 7, 8]);
let col = mat.col(1);
assert.equal(col.isContinuous(), false);
assert.equal(col.ptr(0, 0)[0], 3);
assert.equal(col.ptr(0, 0)[1], 4);
assert.equal(col.ptr(1, 0)[0], 7);
assert.equal(col.ptr(1, 0)[1], 8);
col.delete();
mat.delete();
}
// Mat::row(int)
{
let mat = cv.Mat.zeros(5, 5, cv.CV_8UC2);
let row = mat.row(1);
let view = row.data;
assert.equal(view[0], 0);
assert.equal(view[4], 0);
row.delete();
mat.delete();
}
// Mat::convertTo(Mat, int, double, double)
{
let mat = cv.Mat.ones(5, 5, cv.CV_8UC3);
let grayMat = cv.Mat.zeros(5, 5, cv.CV_8UC1);
mat.convertTo(grayMat, cv.CV_8U, 2, 1);
// dest = 2 * source(x, y) + 1.
let view = grayMat.data;
assert.equal(view[0], (1 * 2) + 1);
mat.convertTo(grayMat, cv.CV_8U);
// dest = 1 * source(x, y) + 0.
assert.equal(view[0], 1);
mat.convertTo(grayMat, cv.CV_8U, 2);
// dest = 2 * source(x, y) + 0.
assert.equal(view[0], 2);
grayMat.delete();
mat.delete();
}
// split
{
const R =7;
const G =13;
const B =29;
let mat = cv.Mat.ones(5, 5, cv.CV_8UC3);
let view = mat.data;
view[0] = R;
view[1] = G;
view[2] = B;
let bgrPlanes = new cv.MatVector();
cv.split(mat, bgrPlanes);
assert.equal(bgrPlanes.size(), 3);
let rMat = bgrPlanes.get(0);
view = rMat.data;
assert.equal(view[0], R);
let gMat = bgrPlanes.get(1);
view = gMat.data;
assert.equal(view[0], G);
let bMat = bgrPlanes.get(2);
view = bMat.data;
assert.equal(view[0], B);
mat.delete();
rMat.delete();
gMat.delete();
bgrPlanes.delete();
bMat.delete();
}
// elemSize
{
let mat = cv.Mat.ones(5, 5, cv.CV_8UC3);
assert.equal(mat.elemSize(), 3);
assert.equal(mat.elemSize1(), 1);
let mat2 = cv.Mat.zeros(5, 5, cv.CV_8UC1);
assert.equal(mat2.elemSize(), 1);
assert.equal(mat2.elemSize1(), 1);
let mat3 = cv.Mat.eye(5, 5, cv.CV_16UC3);
assert.equal(mat3.elemSize(), 2 * 3);
assert.equal(mat3.elemSize1(), 2);
mat.delete();
mat2.delete();
mat3.delete();
}
// step
{
let mat = cv.Mat.ones(5, 5, cv.CV_8UC3);
assert.equal(mat.step[0], 15);
assert.equal(mat.step[1], 3);
let mat2 = cv.Mat.zeros(5, 5, cv.CV_8UC1);
assert.equal(mat2.step[0], 5);
assert.equal(mat2.step[1], 1);
let mat3 = cv.Mat.eye(5, 5, cv.CV_16UC3);
assert.equal(mat3.step[0], 30);
assert.equal(mat3.step[1], 6);
mat.delete();
mat2.delete();
mat3.delete();
}
// dot
{
let mat = cv.Mat.ones(5, 5, cv.CV_8UC1);
let mat2 = cv.Mat.eye(5, 5, cv.CV_8UC1);
assert.equal(mat.dot(mat), 25);
assert.equal(mat.dot(mat2), 5);
assert.equal(mat2.dot(mat2), 5);
mat.delete();
mat2.delete();
}
// mul
{
const FACTOR = 5;
let mat = cv.Mat.ones(4, 4, cv.CV_8UC1);
let mat2 = cv.Mat.eye(4, 4, cv.CV_8UC1);
let expected = new Uint8Array([FACTOR, 0, 0, 0,
0, FACTOR, 0, 0,
0, 0, FACTOR, 0,
0, 0, 0, FACTOR]);
let mat3 = mat.mul(mat2, FACTOR);
assert.deepEqual(mat3.data, expected);
mat.delete();
mat2.delete();
mat3.delete();
}
});
QUnit.test('test mat access', function(assert) {
// test memory view
{
let data = new Uint8Array([0, 0, 0, 255, 0, 1, 2, 3]);
let dataPtr = cv._malloc(8);
let dataHeap = new Uint8Array(cv.HEAPU8.buffer, dataPtr, 8);
dataHeap.set(new Uint8Array(data.buffer));
let mat = new cv.Mat(8, 1, cv.CV_8UC1, dataPtr, 0);
let unsignedCharView = new Uint8Array(data.buffer);
let charView = new Int8Array(data.buffer);
let shortView = new Int16Array(data.buffer);
let unsignedShortView = new Uint16Array(data.buffer);
let intView = new Int32Array(data.buffer);
let float32View = new Float32Array(data.buffer);
let float64View = new Float64Array(data.buffer);
assert.deepEqual(unsignedCharView, mat.data);
assert.deepEqual(charView, mat.data8S);
assert.deepEqual(shortView, mat.data16S);
assert.deepEqual(unsignedShortView, mat.data16U);
assert.deepEqual(intView, mat.data32S);
assert.deepEqual(float32View, mat.data32F);
assert.deepEqual(float64View, mat.data64F);
}
// test ucharAt(i)
{
let data = new Uint8Array([0, 0, 0, 255, 0, 1, 2, 3]);
let dataPtr = cv._malloc(8);
let dataHeap = new Uint8Array(cv.HEAPU8.buffer, dataPtr, 8);
dataHeap.set(new Uint8Array(data.buffer));
let mat = new cv.Mat(8, 1, cv.CV_8UC1, dataPtr, 0);
assert.equal(mat.ucharAt(0), 0);
assert.equal(mat.ucharAt(1), 0);
assert.equal(mat.ucharAt(2), 0);
assert.equal(mat.ucharAt(3), 255);
assert.equal(mat.ucharAt(4), 0);
assert.equal(mat.ucharAt(5), 1);
assert.equal(mat.ucharAt(6), 2);
assert.equal(mat.ucharAt(7), 3);
}
// test ushortAt(i)
{
let data = new Uint16Array([0, 1000, 65000, 255, 0, 1, 2, 3]);
let dataPtr = cv._malloc(16);
let dataHeap = new Uint16Array(cv.HEAPU8.buffer, dataPtr, 8);
dataHeap.set(new Uint16Array(data.buffer));
let mat = new cv.Mat(8, 1, cv.CV_16SC1, dataPtr, 0);
assert.equal(mat.ushortAt(0), 0);
assert.equal(mat.ushortAt(1), 1000);
assert.equal(mat.ushortAt(2), 65000);
assert.equal(mat.ushortAt(3), 255);
assert.equal(mat.ushortAt(4), 0);
assert.equal(mat.ushortAt(5), 1);
assert.equal(mat.ushortAt(6), 2);
assert.equal(mat.ushortAt(7), 3);
}
// test intAt(i)
{
let data = new Int32Array([0, -1000, 65000, 255, -2000000, -1, 2, 3]);
let dataPtr = cv._malloc(32);
let dataHeap = new Int32Array(cv.HEAPU32.buffer, dataPtr, 8);
dataHeap.set(new Int32Array(data.buffer));
let mat = new cv.Mat(8, 1, cv.CV_32SC1, dataPtr, 0);
assert.equal(mat.intAt(0), 0);
assert.equal(mat.intAt(1), -1000);
assert.equal(mat.intAt(2), 65000);
assert.equal(mat.intAt(3), 255);
assert.equal(mat.intAt(4), -2000000);
assert.equal(mat.intAt(5), -1);
assert.equal(mat.intAt(6), 2);
assert.equal(mat.intAt(7), 3);
}
// test floatAt(i)
{
const EPSILON = 0.001;
let data = new Float32Array([0, -10.5, 650.001, 255, -20.1, -1.2, 2, 3.5]);
let dataPtr = cv._malloc(32);
let dataHeap = new Float32Array(cv.HEAPU32.buffer, dataPtr, 8);
dataHeap.set(new Float32Array(data.buffer));
let mat = new cv.Mat(8, 1, cv.CV_32FC1, dataPtr, 0);
assert.equal(Math.abs(mat.floatAt(0)-0) < EPSILON, true);
assert.equal(Math.abs(mat.floatAt(1)+10.5) < EPSILON, true);
assert.equal(Math.abs(mat.floatAt(2)-650.001) < EPSILON, true);
assert.equal(Math.abs(mat.floatAt(3)-255) < EPSILON, true);
assert.equal(Math.abs(mat.floatAt(4)+20.1) < EPSILON, true);
assert.equal(Math.abs(mat.floatAt(5)+1.2) < EPSILON, true);
assert.equal(Math.abs(mat.floatAt(6)-2) < EPSILON, true);
assert.equal(Math.abs(mat.floatAt(7)-3.5) < EPSILON, true);
}
// test intAt(i,j)
{
let mat = cv.Mat.eye({height: 3, width: 3}, cv.CV_32SC1);
assert.equal(mat.intAt(0, 0), 1);
assert.equal(mat.intAt(0, 1), 0);
assert.equal(mat.intAt(0, 2), 0);
assert.equal(mat.intAt(1, 0), 0);
assert.equal(mat.intAt(1, 1), 1);
assert.equal(mat.intAt(1, 2), 0);
assert.equal(mat.intAt(2, 0), 0);
assert.equal(mat.intAt(2, 1), 0);
assert.equal(mat.intAt(2, 2), 1);
mat.delete();
}
});
QUnit.test('test_mat_operations', function(assert) {
// test minMaxLoc
{
let src = cv.Mat.ones(4, 4, cv.CV_8UC1);
src.data[2] = 0;
src.data[5] = 2;
let result = cv.minMaxLoc(src);
assert.equal(result.minVal, 0);
assert.equal(result.maxVal, 2);
assert.deepEqual(result.minLoc, {x: 2, y: 0});
assert.deepEqual(result.maxLoc, {x: 1, y: 1});
src.delete();
}
});
QUnit.test('test_mat_roi', function(assert) {
// test minMaxLoc
{
let mat = cv.matFromArray(2, 2, cv.CV_8UC1, [0, 1, 2, 3]);
let roi = mat.roi(new cv.Rect(1, 1, 1, 1));
assert.equal(roi.rows, 1);
assert.equal(roi.cols, 1);
assert.deepEqual(roi.data, new Uint8Array([mat.ucharAt(1, 1)]));
mat.delete();
roi.delete();
}
});
QUnit.test('test_mat_range', function(assert) {
{
let src = cv.matFromArray(2, 2, cv.CV_8UC1, [0, 1, 2, 3]);
let mat = src.colRange(0, 1);
assert.equal(mat.isContinuous(), false);
assert.equal(mat.rows, 2);
assert.equal(mat.cols, 1);
assert.equal(mat.ucharAt(0), 0);
assert.equal(mat.ucharAt(1), 2);
mat.delete();
mat = src.colRange({start: 0, end: 1});
assert.equal(mat.isContinuous(), false);
assert.equal(mat.rows, 2);
assert.equal(mat.cols, 1);
assert.equal(mat.ucharAt(0), 0);
assert.equal(mat.ucharAt(1), 2);
mat.delete();
mat = src.rowRange(1, 2);
assert.equal(mat.rows, 1);
assert.equal(mat.cols, 2);
assert.deepEqual(mat.data, new Uint8Array([2, 3]));
mat.delete();
mat = src.rowRange({start: 1, end: 2});
assert.equal(mat.rows, 1);
assert.equal(mat.cols, 2);
assert.deepEqual(mat.data, new Uint8Array([2, 3]));
mat.delete();
src.delete();
}
});
QUnit.test('test_mat_diag', function(assert) {
// test diag
{
let mat = cv.matFromArray(3, 3, cv.CV_8UC1, [0, 1, 2, 3, 4, 5, 6, 7, 8]);
let d = mat.diag();
let d1 = mat.diag(1);
let d2 = mat.diag(-1);
assert.equal(mat.isContinuous(), true);
assert.equal(d.isContinuous(), false);
assert.equal(d1.isContinuous(), false);
assert.equal(d2.isContinuous(), false);
assert.equal(d.ucharAt(0), 0);
assert.equal(d.ucharAt(1), 4);
assert.equal(d.ucharAt(2), 8);
assert.equal(d1.ucharAt(0), 1);
assert.equal(d1.ucharAt(1), 5);
assert.equal(d2.ucharAt(0), 3);
assert.equal(d2.ucharAt(1), 7);
mat.delete();
d.delete();
d1.delete();
d2.delete();
}
});

View File

@@ -0,0 +1,161 @@
// //////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//
// //////////////////////////////////////////////////////////////////////////////////////
// Author: Sajjad Taheri, University of California, Irvine. sajjadt[at]uci[dot]edu
//
// LICENSE AGREEMENT
// Copyright (c) 2015 The Regents of the University of California (Regents)
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the University nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
if (typeof module !== 'undefined' && module.exports) {
// The environment is Node.js
var cv = require('./opencv.js'); // eslint-disable-line no-var
cv.FS_createLazyFile('/', 'haarcascade_frontalface_default.xml', // eslint-disable-line new-cap
'haarcascade_frontalface_default.xml', true, false);
}
QUnit.module('Object Detection', {});
QUnit.test('Cascade classification', function(assert) {
// Group rectangle
{
let rectList = new cv.RectVector();
let weights = new cv.IntVector();
let groupThreshold = 1;
const eps = 0.2;
let rect1 = new cv.Rect(1, 2, 3, 4);
let rect2 = new cv.Rect(1, 4, 2, 3);
rectList.push_back(rect1);
rectList.push_back(rect2);
cv.groupRectangles(rectList, weights, groupThreshold, eps);
rectList.delete();
weights.delete();
}
// CascadeClassifier
{
let classifier = new cv.CascadeClassifier();
const modelPath = '/haarcascade_frontalface_default.xml';
assert.equal(classifier.empty(), true);
classifier.load(modelPath);
assert.equal(classifier.empty(), false);
let image = cv.Mat.eye({height: 10, width: 10}, cv.CV_8UC3);
let objects = new cv.RectVector();
let numDetections = new cv.IntVector();
const scaleFactor = 1.1;
const minNeighbors = 3;
const flags = 0;
const minSize = {height: 0, width: 0};
const maxSize = {height: 10, width: 10};
classifier.detectMultiScale2(image, objects, numDetections, scaleFactor,
minNeighbors, flags, minSize, maxSize);
// test default parameters
classifier.detectMultiScale2(image, objects, numDetections, scaleFactor,
minNeighbors, flags, minSize);
classifier.detectMultiScale2(image, objects, numDetections, scaleFactor,
minNeighbors, flags);
classifier.detectMultiScale2(image, objects, numDetections, scaleFactor,
minNeighbors);
classifier.detectMultiScale2(image, objects, numDetections, scaleFactor);
classifier.delete();
objects.delete();
numDetections.delete();
}
// HOGDescriptor
{
let hog = new cv.HOGDescriptor();
let mat = new cv.Mat({height: 10, width: 10}, cv.CV_8UC1);
let descriptors = new cv.FloatVector();
let locations = new cv.PointVector();
assert.equal(hog.winSize.height, 128);
assert.equal(hog.winSize.width, 64);
assert.equal(hog.nbins, 9);
assert.equal(hog.derivAperture, 1);
assert.equal(hog.winSigma, -1);
assert.equal(hog.histogramNormType, 0);
assert.equal(hog.nlevels, 64);
hog.nlevels = 32;
assert.equal(hog.nlevels, 32);
hog.delete();
mat.delete();
descriptors.delete();
locations.delete();
}
});

View File

@@ -0,0 +1,116 @@
// //////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
// Author : Rijubrata Bhaumik, Intel Corporation. rijubrata.bhaumik[at]intel[dot]com
if (typeof module !== 'undefined' && module.exports) {
// The environment is Node.js
var cv = require('./opencv.js'); // eslint-disable-line no-var
}
QUnit.module('Photo', {});
QUnit.test('test_photo', function(assert) {
// CalibrateDebevec
{
let calibration = new cv.CalibrateDebevec();
assert.ok(true, calibration);
//let response = calibration.process(images, exposures);
}
// CalibrateRobertson
{
let calibration = new cv.CalibrateRobertson();
assert.ok(true, calibration);
//let response = calibration.process(images, exposures);
}
// MergeDebevec
{
let merge = new cv.MergeDebevec();
assert.ok(true, merge);
//let hdr = merge.process(images, exposures, response);
}
// MergeMertens
{
let merge = new cv.MergeMertens();
assert.ok(true, merge);
//let hdr = merge.process(images, exposures, response);
}
// MergeRobertson
{
let merge = new cv.MergeRobertson();
assert.ok(true, merge);
//let hdr = merge.process(images, exposures, response);
}
// TonemapDrago
{
let tonemap = new cv.TonemapDrago();
assert.ok(true, tonemap);
// let ldr = new cv.Mat();
// let retval = tonemap.process(hdr, ldr);
}
// TonemapMantiuk
{
let tonemap = new cv.TonemapMantiuk();
assert.ok(true, tonemap);
// let ldr = new cv.Mat();
// let retval = tonemap.process(hdr, ldr);
}
// TonemapReinhard
{
let tonemap = new cv.TonemapReinhard();
assert.ok(true, tonemap);
// let ldr = new cv.Mat();
// let retval = tonemap.process(hdr, ldr);
}
// Inpaint
{
let src = new cv.Mat(100, 100, cv.CV_8UC3, new cv.Scalar(127, 127, 127, 255));
let mask = new cv.Mat(100, 100, cv.CV_8UC1, new cv.Scalar(0, 0, 0, 0));
let dst = new cv.Mat();
cv.line(mask, new cv.Point(10, 50), new cv.Point(90, 50), new cv.Scalar(255, 255, 255, 255),5);
cv.inpaint(src, mask, dst, 3, cv.INPAINT_TELEA);
assert.equal(dst.rows, 100);
assert.equal(dst.cols, 100);
assert.equal(dst.channels(), 3);
}
});

View File

@@ -0,0 +1,253 @@
// //////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
// //////////////////////////////////////////////////////////////////////////////////////
// Author: Sajjad Taheri, University of California, Irvine. sajjadt[at]uci[dot]edu
//
// LICENSE AGREEMENT
// Copyright (c) 2015 The Regents of the University of California (Regents)
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the University nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
if (typeof module !== 'undefined' && module.exports) {
// The environment is Node.js
var cv = require('./opencv.js'); // eslint-disable-line no-var
}
QUnit.module('Utils', {});
QUnit.test('Test vectors', function(assert) {
{
let pointVector = new cv.PointVector();
for (let i=0; i<100; ++i) {
pointVector.push_back({x: i, y: 2*i});
}
assert.equal(pointVector.size(), 100);
let index = 10;
let item = pointVector.get(index);
assert.equal(item.x, index);
assert.equal(item.y, 2*index);
index = 0;
item = pointVector.get(index);
assert.equal(item.x, index);
assert.equal(item.y, 2*index);
index = 99;
item = pointVector.get(index);
assert.equal(item.x, index);
assert.equal(item.y, 2*index);
pointVector.delete();
}
{
let pointVector = new cv.PointVector();
for (let i=0; i<100; ++i) {
pointVector.push_back(new cv.Point(i, 2*i));
}
pointVector.push_back(new cv.Point());
assert.equal(pointVector.size(), 101);
let index = 10;
let item = pointVector.get(index);
assert.equal(item.x, index);
assert.equal(item.y, 2*index);
index = 0;
item = pointVector.get(index);
assert.equal(item.x, index);
assert.equal(item.y, 2*index);
index = 99;
item = pointVector.get(index);
assert.equal(item.x, index);
assert.equal(item.y, 2*index);
index = 100;
item = pointVector.get(index);
assert.equal(item.x, 0);
assert.equal(item.y, 0);
pointVector.delete();
}
});
QUnit.test('Test Rect', function(assert) {
let rectVector = new cv.RectVector();
let rect = {x: 1, y: 2, width: 3, height: 4};
rectVector.push_back(rect);
rectVector.push_back(new cv.Rect());
rectVector.push_back(new cv.Rect(rect));
rectVector.push_back(new cv.Rect({x: 5, y: 6}, {width: 7, height: 8}));
rectVector.push_back(new cv.Rect(9, 10, 11, 12));
assert.equal(rectVector.size(), 5);
let item = rectVector.get(0);
assert.equal(item.x, 1);
assert.equal(item.y, 2);
assert.equal(item.width, 3);
assert.equal(item.height, 4);
item = rectVector.get(1);
assert.equal(item.x, 0);
assert.equal(item.y, 0);
assert.equal(item.width, 0);
assert.equal(item.height, 0);
item = rectVector.get(2);
assert.equal(item.x, 1);
assert.equal(item.y, 2);
assert.equal(item.width, 3);
assert.equal(item.height, 4);
item = rectVector.get(3);
assert.equal(item.x, 5);
assert.equal(item.y, 6);
assert.equal(item.width, 7);
assert.equal(item.height, 8);
item = rectVector.get(4);
assert.equal(item.x, 9);
assert.equal(item.y, 10);
assert.equal(item.width, 11);
assert.equal(item.height, 12);
rectVector.delete();
});
QUnit.test('Test Size', function(assert) {
{
let mat = new cv.Mat();
mat.create({width: 5, height: 10}, cv.CV_8UC4);
let size = mat.size();
assert.ok(mat.type() === cv.CV_8UC4);
assert.ok(size.height === 10);
assert.ok(size.width === 5);
assert.ok(mat.channels() === 4);
mat.delete();
}
{
let mat = new cv.Mat();
mat.create(new cv.Size(5, 10), cv.CV_8UC4);
let size = mat.size();
assert.ok(mat.type() === cv.CV_8UC4);
assert.ok(size.height === 10);
assert.ok(size.width === 5);
assert.ok(mat.channels() === 4);
mat.delete();
}
});
QUnit.test('test_rotated_rect', function(assert) {
{
let rect = {center: {x: 100, y: 100}, size: {height: 100, width: 50}, angle: 30};
assert.equal(rect.center.x, 100);
assert.equal(rect.center.y, 100);
assert.equal(rect.angle, 30);
assert.equal(rect.size.height, 100);
assert.equal(rect.size.width, 50);
}
{
let rect = new cv.RotatedRect();
assert.equal(rect.center.x, 0);
assert.equal(rect.center.y, 0);
assert.equal(rect.angle, 0);
assert.equal(rect.size.height, 0);
assert.equal(rect.size.width, 0);
let points = cv.RotatedRect.points(rect);
assert.equal(points[0].x, 0);
assert.equal(points[0].y, 0);
assert.equal(points[1].x, 0);
assert.equal(points[1].y, 0);
assert.equal(points[2].x, 0);
assert.equal(points[2].y, 0);
assert.equal(points[3].x, 0);
assert.equal(points[3].y, 0);
}
{
let rect = new cv.RotatedRect({x: 100, y: 100}, {height: 100, width: 50}, 30);
assert.equal(rect.center.x, 100);
assert.equal(rect.center.y, 100);
assert.equal(rect.angle, 30);
assert.equal(rect.size.height, 100);
assert.equal(rect.size.width, 50);
let points = cv.RotatedRect.points(rect);
assert.equal(points[0].x, cv.RotatedRect.boundingRect2f(rect).x);
assert.equal(points[1].y, cv.RotatedRect.boundingRect2f(rect).y);
}
});

View File

@@ -0,0 +1,107 @@
// //////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
// //////////////////////////////////////////////////////////////////////////////////////
// Author: Sajjad Taheri, University of California, Irvine. sajjadt[at]uci[dot]edu
//
// LICENSE AGREEMENT
// Copyright (c) 2015 The Regents of the University of California (Regents)
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the University nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
if (typeof module !== 'undefined' && module.exports) {
// The environment is Node.js
var cv = require('./opencv.js'); // eslint-disable-line no-var
}
QUnit.module('Video', {});
QUnit.test('Background Segmentation', function(assert) {
// BackgroundSubtractorMOG2
{
const history = 600;
const varThreshold = 15;
const detectShadows = true;
let mog2 = new cv.BackgroundSubtractorMOG2(history, varThreshold, detectShadows);
assert.equal(mog2 instanceof cv.BackgroundSubtractorMOG2, true);
mog2.delete();
mog2 = new cv.BackgroundSubtractorMOG2();
assert.equal(mog2 instanceof cv.BackgroundSubtractorMOG2, true);
mog2.delete();
mog2 = new cv.BackgroundSubtractorMOG2(history);
assert.equal(mog2 instanceof cv.BackgroundSubtractorMOG2, true);
mog2.delete();
mog2 = new cv.BackgroundSubtractorMOG2(history, varThreshold);
assert.equal(mog2 instanceof cv.BackgroundSubtractorMOG2, true);
mog2.delete();
}
});

View File

@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>OpenCV JS Tests</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.20.0.css" type="text/css" media="screen">
<style>
body {
font-family: Monospace;
background-color: #ffffff;
margin: 0px;
}
a {
color: #0040ff;
}
</style>
<script src="http://code.jquery.com/qunit/qunit-2.0.1.js"></script>
<script type="text/javascript">
QUnit.config.autostart = false;
QUnit.log(function(details) {
if (details.result) {
return;
}
var loc = details.module + ": " + details.name + ": ",
output = "FAILED: " + loc + ( details.message ? details.message : "" )
prefix = details.message ? ", " : "";
if (details.actual) {
output += prefix + "expected: " + details.expected + ", actual: " + details.actual;
prefix = ', ';
}
if (details.source) {
output += prefix + details.source;
}
console.warn(output);
});
QUnit.done(function(details) {
console.log("Total: " + details.total + " Failed: " + details.failed + " Passed: " + details.passed);
console.log("Time(ms): " + details.runtime);
});
// Helper for opencv.js (see below)
var Module = {
preRun: [function() {
Module.FS_createPreloadedFile('/', 'haarcascade_frontalface_default.xml', 'haarcascade_frontalface_default.xml', true, false);
}],
postRun: [] ,
onRuntimeInitialized: function() {
console.log("Emscripten runtime is ready, launching QUnit tests...");
//console.log(cv.getBuildInformation());
QUnit.start();
},
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
return function(text) {
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
printErr: function(text) {
console.error(text);
},
setStatus: function(text) {
console.log(text);
},
totalDependencies: 0
};
Module.setStatus('Downloading...');
window.onerror = function(event) {
Module.setStatus('Exception thrown, see JavaScript console');
Module.setStatus = function(text) {
if (text) Module.printErr('[post-exception status] ' + text);
};
};
function opencvjs_LoadError() {
Module.printErr('Failed to load/initialize opencv.js');
QUnit.module('LoaderFatalError', {});
QUnit.config.module = 'LoaderFatalError';
QUnit.only("Failed to load OpenCV.js", function(assert) {
assert.ok(false, "Can't load/initialize opencv.js");
});
QUnit.start();
}
</script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script type="application/javascript" async src="opencv.js" onerror="opencvjs_LoadError()"></script>
<script type="application/javascript" src="test_mat.js"></script>
<script type="application/javascript" src="test_utils.js"></script>
<script type="application/javascript" src="test_imgproc.js"></script>
<script type="application/javascript" src="test_objdetect.js"></script>
<script type="application/javascript" src="test_video.js"></script>
<script type="application/javascript" src="test_photo.js"></script>
<script type="application/javascript" src="test_features2d.js"></script>
<script type="application/javascript" src="test_calib3d.js"></script>
</body>
</html>

View File

@@ -0,0 +1,61 @@
// //////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
let testrunner = require('node-qunit');
testrunner.options.maxBlockDuration = 20000; // cause opencv_js.js need time to load
testrunner.run(
{
code: 'opencv.js',
tests: ['test_mat.js', 'test_utils.js', 'test_imgproc.js',
'test_objdetect.js', 'test_video.js', 'test_features2d.js',
'test_photo.js',
'test_calib3d.js'
],
},
function(err, report) {
console.log(report.failed + ' failed, ' + report.passed + ' passed');
if (report.failed) {
process.on('exit', function() {
process.exit(1);
});
}
}
);