Merge pull request #25986 from asmorkalov:as/js_for_contrib

Split Javascript white-list to support contrib modules #25986

Single whitelist converted to several per-module json files. They are concatenated automatically and can be overriden by user config.

Related to https://github.com/opencv/opencv/pull/25656

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
pull/10318/merge
Alexander Smorkalov 3 months ago committed by GitHub
parent 697512bb9f
commit 6c6d5cd7b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 21
      modules/calib3d/misc/js/gen_dict.json
  2. 15
      modules/core/misc/js/gen_dict.json
  3. 12
      modules/dnn/misc/js/gen_dict.json
  4. 19
      modules/features2d/misc/js/gen_dict.json
  5. 95
      modules/imgproc/misc/js/gen_dict.json
  6. 15
      modules/js/generator/CMakeLists.txt
  7. 50
      modules/js/generator/embindgen.py
  8. 28
      modules/objdetect/misc/js/gen_dict.json
  9. 25
      modules/photo/misc/js/gen_dict.json
  10. 17
      modules/video/misc/js/gen_dict.json
  11. 4
      platforms/js/build_js.py

@ -0,0 +1,21 @@
{
"whitelist":
{
"": [
"findHomography",
"calibrateCameraExtended",
"drawFrameAxes",
"estimateAffine2D",
"getDefaultNewCameraMatrix",
"initUndistortRectifyMap",
"Rodrigues",
"solvePnP",
"solvePnPRansac",
"solvePnPRefineLM",
"projectPoints",
"undistort",
"fisheye_initUndistortRectifyMap",
"fisheye_projectPoints"
]
}
}

@ -0,0 +1,15 @@
{
"whitelist":
{
"": [
"absdiff", "add", "addWeighted", "bitwise_and", "bitwise_not", "bitwise_or", "bitwise_xor", "cartToPolar",
"compare", "convertScaleAbs", "copyMakeBorder", "countNonZero", "determinant", "dft", "divide", "eigen",
"exp", "flip", "getOptimalDFTSize","gemm", "hconcat", "inRange", "invert", "kmeans", "log", "magnitude",
"max", "mean", "meanStdDev", "merge", "min", "minMaxLoc", "mixChannels", "multiply", "norm", "normalize",
"perspectiveTransform", "polarToCart", "pow", "randn", "randu", "reduce", "repeat", "rotate", "setIdentity", "setRNGSeed",
"solve", "solvePoly", "split", "sqrt", "subtract", "trace", "transform", "transpose", "vconcat",
"setLogLevel", "getLogLevel", "LUT"
],
"Algorithm": []
}
}

@ -0,0 +1,12 @@
{
"whitelist":
{
"dnn_Net": ["setInput", "forward", "setPreferableBackend","getUnconnectedOutLayersNames"],
"": ["readNetFromCaffe", "readNetFromTensorflow", "readNetFromTorch", "readNetFromDarknet",
"readNetFromONNX", "readNetFromTFLite", "readNet", "blobFromImage"]
},
"namespace_prefix_override":
{
"dnn": ""
}
}

@ -0,0 +1,19 @@
{
"whitelist":
{
"Feature2D": ["detect", "compute", "detectAndCompute", "descriptorSize", "descriptorType", "defaultNorm", "empty", "getDefaultName"],
"BRISK": ["create", "getDefaultName"],
"ORB": ["create", "setMaxFeatures", "setScaleFactor", "setNLevels", "setEdgeThreshold", "setFastThreshold", "setFirstLevel", "setWTA_K", "setScoreType", "setPatchSize", "getFastThreshold", "getDefaultName"],
"MSER": ["create", "detectRegions", "setDelta", "getDelta", "setMinArea", "getMinArea", "setMaxArea", "getMaxArea", "setPass2Only", "getPass2Only", "getDefaultName"],
"FastFeatureDetector": ["create", "setThreshold", "getThreshold", "setNonmaxSuppression", "getNonmaxSuppression", "setType", "getType", "getDefaultName"],
"AgastFeatureDetector": ["create", "setThreshold", "getThreshold", "setNonmaxSuppression", "getNonmaxSuppression", "setType", "getType", "getDefaultName"],
"GFTTDetector": ["create", "setMaxFeatures", "getMaxFeatures", "setQualityLevel", "getQualityLevel", "setMinDistance", "getMinDistance", "setBlockSize", "getBlockSize", "setHarrisDetector", "getHarrisDetector", "setK", "getK", "getDefaultName"],
"SimpleBlobDetector": ["create", "setParams", "getParams", "getDefaultName"],
"SimpleBlobDetector_Params": [],
"KAZE": ["create", "setExtended", "getExtended", "setUpright", "getUpright", "setThreshold", "getThreshold", "setNOctaves", "getNOctaves", "setNOctaveLayers", "getNOctaveLayers", "setDiffusivity", "getDiffusivity", "getDefaultName"],
"AKAZE": ["create", "setDescriptorType", "getDescriptorType", "setDescriptorSize", "getDescriptorSize", "setDescriptorChannels", "getDescriptorChannels", "setThreshold", "getThreshold", "setNOctaves", "getNOctaves", "setNOctaveLayers", "getNOctaveLayers", "setDiffusivity", "getDiffusivity", "getDefaultName"],
"DescriptorMatcher": ["add", "clear", "empty", "isMaskSupported", "train", "match", "knnMatch", "radiusMatch", "clone", "create"],
"BFMatcher": ["isMaskSupported", "create"],
"": ["drawKeypoints", "drawMatches", "drawMatchesKnn"]
}
}

@ -0,0 +1,95 @@
{
"whitelist":
{
"": [
"Canny",
"GaussianBlur",
"Laplacian",
"HoughLines",
"HoughLinesP",
"HoughCircles",
"Scharr",
"Sobel",
"adaptiveThreshold",
"approxPolyDP",
"arcLength",
"bilateralFilter",
"blur",
"boundingRect",
"boxFilter",
"calcBackProject",
"calcHist",
"circle",
"compareHist",
"connectedComponents",
"connectedComponentsWithStats",
"contourArea",
"convexHull",
"convexityDefects",
"cornerHarris",
"cornerMinEigenVal",
"createCLAHE",
"createLineSegmentDetector",
"cvtColor",
"demosaicing",
"dilate",
"distanceTransform",
"distanceTransformWithLabels",
"drawContours",
"ellipse",
"ellipse2Poly",
"equalizeHist",
"erode",
"filter2D",
"findContours",
"fitEllipse",
"fitLine",
"floodFill",
"getAffineTransform",
"getPerspectiveTransform",
"getRotationMatrix2D",
"getStructuringElement",
"goodFeaturesToTrack",
"grabCut",
"integral",
"integral2",
"isContourConvex",
"line",
"matchShapes",
"matchTemplate",
"medianBlur",
"minAreaRect",
"minEnclosingCircle",
"moments",
"morphologyEx",
"pointPolygonTest",
"putText",
"pyrDown",
"pyrUp",
"rectangle",
"remap",
"resize",
"sepFilter2D",
"threshold",
"warpAffine",
"warpPerspective",
"warpPolar",
"watershed",
"fillPoly",
"fillConvexPoly",
"polylines"
],
"CLAHE": ["apply", "collectGarbage", "getClipLimit", "getTilesGridSize", "setClipLimit", "setTilesGridSize"],
"segmentation_IntelligentScissorsMB": [
"IntelligentScissorsMB",
"setWeights",
"setGradientMagnitudeMaxLimit",
"setEdgeFeatureZeroCrossingParameters",
"setEdgeFeatureCannyParameters",
"applyImage",
"applyImageFeatures",
"buildMap",
"getContour"
]
}
}

@ -38,8 +38,21 @@ set(scripts_hdr_parser "${JS_SOURCE_DIR}/../python/src2/hdr_parser.py")
if(DEFINED ENV{OPENCV_JS_WHITELIST})
set(OPENCV_JS_WHITELIST_FILE "$ENV{OPENCV_JS_WHITELIST}")
message(STATUS "Use white list from environment ${OPENCV_JS_WHITELIST_FILE}")
else()
set(OPENCV_JS_WHITELIST_FILE "${OpenCV_SOURCE_DIR}/platforms/js/opencv_js.config.py")
#generate white list from modules/<module_name>/misc/js/whitelist.json
set(OPENCV_JS_WHITELIST_FILE "${CMAKE_CURRENT_BINARY_DIR}/whitelist.json")
foreach(m in ${OPENCV_JS_MODULES})
set(js_whitelist "${OPENCV_MODULE_${m}_LOCATION}/misc/js/gen_dict.json")
if (EXISTS "${js_whitelist}")
file(READ "${js_whitelist}" whitelist_content)
list(APPEND OPENCV_JS_WHITELIST_CONTENT "\"${m}\": ${whitelist_content}")
endif()
endforeach(m)
string(REPLACE ";" ", \n" OPENCV_JS_WHITELIST_CONTENT_STRING "${OPENCV_JS_WHITELIST_CONTENT}")
set(OPENCV_JS_WHITELIST_CONTENT_STRING "{\n${OPENCV_JS_WHITELIST_CONTENT_STRING}}\n")
ocv_update_file("${OPENCV_JS_WHITELIST_FILE}" "${OPENCV_JS_WHITELIST_CONTENT_STRING}")
message(STATUS "Use autogenerated whitelist ${OPENCV_JS_WHITELIST_FILE}")
endif()
add_custom_command(

@ -76,6 +76,7 @@ if sys.version_info[0] >= 3:
else:
from cStringIO import StringIO
import json
func_table = {}
@ -103,11 +104,32 @@ def makeWhiteList(module_list):
wl[k] = m[k]
return wl
def makeWhiteListJson(module_list):
wl = {}
for n, gen_dict in module_list.items():
m = gen_dict["whitelist"]
for k in m.keys():
if k in wl:
wl[k] += m[k]
else:
wl[k] = m[k]
return wl
def makeNamespacePrefixOverride(module_list):
wl = {}
for n, gen_dict in module_list.items():
if "namespace_prefix_override" in gen_dict:
m = gen_dict["namespace_prefix_override"]
for k in m.keys():
if k in wl:
wl[k] += m[k]
else:
wl[k] = m[k]
return wl
white_list = None
namespace_prefix_override = {
'dnn' : '',
'aruco' : '',
}
namespace_prefix_override = None
# Features to be exported
export_enums = False
@ -834,6 +856,7 @@ class JSWrapperGenerator(object):
if method.cname in ignore_list:
continue
if not method.name in white_list[method.class_name]:
#print('Not in whitelist: "{}"'.format(method.name))
continue
if method.is_constructor:
for variant in method.variants:
@ -938,9 +961,9 @@ if __name__ == "__main__":
if len(sys.argv) < 5:
print("Usage:\n", \
os.path.basename(sys.argv[0]), \
"<full path to hdr_parser.py> <bindings.cpp> <headers.txt> <core_bindings.cpp> <opencv_js.config.py>")
"<full path to hdr_parser.py> <bindings.cpp> <headers.txt> <core_bindings.cpp> <whitelist.json or opencv_js.config.py>")
print("Current args are: ", ", ".join(["'"+a+"'" for a in sys.argv]))
exit(0)
exit(1)
dstdir = "."
hdr_parser_path = os.path.abspath(sys.argv[1])
@ -953,8 +976,23 @@ if __name__ == "__main__":
headers = open(sys.argv[3], 'r').read().split(';')
coreBindings = sys.argv[4]
whiteListFile = sys.argv[5]
if whiteListFile.endswith(".json") or whiteListFile.endswith(".JSON"):
with open(whiteListFile) as f:
gen_dict = json.load(f)
f.close()
white_list = makeWhiteListJson(gen_dict)
namespace_prefix_override = makeNamespacePrefixOverride(gen_dict)
elif whiteListFile.endswith(".py") or whiteListFile.endswith(".PY"):
exec(open(whiteListFile).read())
assert(white_list)
namespace_prefix_override = {
'dnn' : '',
'aruco' : '',
}
else:
print("Unexpected format of OpenCV config file", whiteListFile)
exit(1)
generator = JSWrapperGenerator()
generator.gen(bindingsCpp, headers, coreBindings)

@ -0,0 +1,28 @@
{
"whitelist":
{
"": ["groupRectangles", "getPredefinedDictionary", "extendDictionary", "drawDetectedMarkers", "generateImageMarker", "drawDetectedCornersCharuco", "drawDetectedDiamonds"],
"HOGDescriptor": ["load", "HOGDescriptor", "getDefaultPeopleDetector", "getDaimlerPeopleDetector", "setSVMDetector", "detectMultiScale"],
"CascadeClassifier": ["load", "detectMultiScale2", "CascadeClassifier", "detectMultiScale3", "empty", "detectMultiScale"],
"GraphicalCodeDetector": ["decode", "detect", "detectAndDecode", "detectMulti", "decodeMulti", "detectAndDecodeMulti"],
"QRCodeDetector": ["QRCodeDetector", "decode", "detect", "detectAndDecode", "detectMulti", "decodeMulti", "detectAndDecodeMulti", "decodeCurved", "detectAndDecodeCurved", "setEpsX", "setEpsY"],
"aruco_PredefinedDictionaryType": [],
"aruco_Dictionary": ["Dictionary", "getDistanceToId", "generateImageMarker", "getByteListFromBits", "getBitsFromByteList"],
"aruco_Board": ["Board", "matchImagePoints", "generateImage"],
"aruco_GridBoard": ["GridBoard", "generateImage", "getGridSize", "getMarkerLength", "getMarkerSeparation", "matchImagePoints"],
"aruco_CharucoParameters": ["CharucoParameters"],
"aruco_CharucoBoard": ["CharucoBoard", "generateImage", "getChessboardCorners", "getNearestMarkerCorners", "checkCharucoCornersCollinear", "matchImagePoints", "getLegacyPattern", "setLegacyPattern"],
"aruco_DetectorParameters": ["DetectorParameters"],
"aruco_RefineParameters": ["RefineParameters"],
"aruco_ArucoDetector": ["ArucoDetector", "detectMarkers", "refineDetectedMarkers", "setDictionary", "setDetectorParameters", "setRefineParameters"],
"aruco_CharucoDetector": ["CharucoDetector", "setBoard", "setCharucoParameters", "setDetectorParameters", "setRefineParameters", "detectBoard", "detectDiamonds"],
"QRCodeDetectorAruco_Params": ["Params"],
"QRCodeDetectorAruco": ["QRCodeDetectorAruco", "decode", "detect", "detectAndDecode", "detectMulti", "decodeMulti", "detectAndDecodeMulti", "setDetectorParameters", "setArucoParameters"],
"barcode_BarcodeDetector": ["BarcodeDetector", "decode", "detect", "detectAndDecode", "detectMulti", "decodeMulti", "detectAndDecodeMulti", "decodeWithType", "detectAndDecodeWithType"],
"FaceDetectorYN": ["setInputSize", "getInputSize", "setScoreThreshold", "getScoreThreshold", "setNMSThreshold", "getNMSThreshold", "setTopK", "getTopK", "detect", "create"]
},
"namespace_prefix_override":
{
"aruco": ""
}
}

@ -0,0 +1,25 @@
{
"whitelist":
{
"": [
"createAlignMTB", "createCalibrateDebevec", "createCalibrateRobertson",
"createMergeDebevec", "createMergeMertens", "createMergeRobertson",
"createTonemapDrago", "createTonemapMantiuk", "createTonemapReinhard", "inpaint"],
"CalibrateCRF": ["process"],
"AlignMTB" : ["calculateShift", "shiftMat", "computeBitmaps", "getMaxBits", "setMaxBits",
"getExcludeRange", "setExcludeRange", "getCut", "setCut"],
"CalibrateDebevec" : ["getLambda", "setLambda", "getSamples", "setSamples", "getRandom", "setRandom"],
"CalibrateRobertson" : ["getMaxIter", "setMaxIter", "getThreshold", "setThreshold", "getRadiance"],
"MergeExposures" : ["process"],
"MergeDebevec" : ["process"],
"MergeMertens" : ["process", "getContrastWeight", "setContrastWeight", "getSaturationWeight",
"setSaturationWeight", "getExposureWeight", "setExposureWeight"],
"MergeRobertson" : ["process"],
"Tonemap" : ["process" , "getGamma", "setGamma"],
"TonemapDrago" : ["getSaturation", "setSaturation", "getBias", "setBias",
"getSigmaColor", "setSigmaColor", "getSigmaSpace","setSigmaSpace"],
"TonemapMantiuk" : ["getScale", "setScale", "getSaturation", "setSaturation"],
"TonemapReinhard" : ["getIntensity", "setIntensity", "getLightAdaptation", "setLightAdaptation",
"getColorAdaptation", "setColorAdaptation"]
}
}

@ -0,0 +1,17 @@
{
"whitelist":
{
"": [
"CamShift",
"calcOpticalFlowFarneback",
"calcOpticalFlowPyrLK",
"createBackgroundSubtractorMOG2",
"findTransformECC",
"meanShift"
],
"BackgroundSubtractorMOG2": ["BackgroundSubtractorMOG2", "apply"],
"BackgroundSubtractor": ["apply", "getBackgroundImage"],
"TrackerMIL": ["create"],
"TrackerMIL_Params": []
}
}

@ -256,8 +256,7 @@ if __name__ == "__main__":
parser.add_argument('--build_flags', help="Append Emscripten build options")
parser.add_argument('--build_wasm_intrin_test', default=False, action="store_true", help="Build WASM intrin tests")
# Write a path to modify file like argument of this flag
parser.add_argument('--config', default=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'opencv_js.config.py'),
help="Specify configuration file with own list of exported into JS functions")
parser.add_argument('--config', help="Specify configuration file with own list of exported into JS functions")
parser.add_argument('--webnn', action="store_true", help="Enable WebNN Backend")
transformed_args = ["--cmake_option=%s".format(arg) if arg[:2] == "-D" else arg for arg in sys.argv[1:]]
@ -265,6 +264,7 @@ if __name__ == "__main__":
log.debug("Args: %s", args)
if args.config is not None:
os.environ["OPENCV_JS_WHITELIST"] = os.path.abspath(args.config)
if 'EMMAKEN_JUST_CONFIGURE' in os.environ:

Loading…
Cancel
Save