I cloned the OpenCV Git repository: git clone https://github.com/opencv/opencv.git
and did not change anything.
Then I followed the build opencv.js documentation on OpenCV step by step
https://docs.opencv.org/4.5.2/d4/da1/tutorial_js_setup.html
and successfully built the opencv.js and tests with the command
python ./platforms/js/build_js.py build_js --build_test
Then I opened with a live server the created test.html and saw that all tests were successful: "581 assertions of 581 passed, 0 failed."
But when I insert the built opencv.js between the <script> </script> tags and use it, it still works except for cv.imread(). I get the error message: `
"Uncaught TypeError: cv.imread is not a function".`
Here is the code block:
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let matrix = cv.imread("canvas");
Then I used the official opencv.js and imread() worked. The problem is, however, that opencv.js is 7.7 mb in size, because it includes most of OpenCV's capabilities and I only need some core and image processing functions.
How can imread() be included in the build? I could not find a solution so far. I only found the build Whitelist: it is in the OpenCV repository and has the name opencv_js.config.py and includes the following. Any idea how imread() can be included in the build? Because the OpenCV JavaScript documentation uses imread() in pretty much every example, there should be an easy way to include it.
# Classes and methods whitelist
core = {
'': [
'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',
],
'Algorithm': [],
}
imgproc = {'': ['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','initUndistortRectifyMap', 'integral','integral2', 'isContourConvex', 'line', \
'matchShapes', 'matchTemplate','medianBlur', 'minAreaRect', 'minEnclosingCircle', 'moments', 'morphologyEx', \
'pointPolygonTest', 'putText','pyrDown','pyrUp','rectangle','remap', 'resize','sepFilter2D','threshold', \
'undistort','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'
],
}
objdetect = {'': ['groupRectangles'],
'HOGDescriptor': ['load', 'HOGDescriptor', 'getDefaultPeopleDetector', 'getDaimlerPeopleDetector', 'setSVMDetector', 'detectMultiScale'],
'CascadeClassifier': ['load', 'detectMultiScale2', 'CascadeClassifier', 'detectMultiScale3', 'empty', 'detectMultiScale'],
'QRCodeDetector': ['QRCodeDetector', 'decode', 'decodeCurved', 'detect', 'detectAndDecode', 'detectMulti', 'setEpsX', 'setEpsY']}
video = {'': ['CamShift', 'calcOpticalFlowFarneback', 'calcOpticalFlowPyrLK', 'createBackgroundSubtractorMOG2', \
'findTransformECC', 'meanShift'],
'BackgroundSubtractorMOG2': ['BackgroundSubtractorMOG2', 'apply'],
'BackgroundSubtractor': ['apply', 'getBackgroundImage']}
dnn = {'dnn_Net': ['setInput', 'forward'],
'': ['readNetFromCaffe', 'readNetFromTensorflow', 'readNetFromTorch', 'readNetFromDarknet',
'readNetFromONNX', 'readNet', 'blobFromImage']}
features2d = {'Feature2D': ['detect', 'compute', 'detectAndCompute', 'descriptorSize', 'descriptorType', 'defaultNorm', 'empty', 'getDefaultName'],
'BRISK': ['create', 'getDefaultName'],
'ORB': ['create', 'setMaxFeatures', 'setScaleFactor', 'setNLevels', 'setEdgeThreshold', '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'],
'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']}
photo = {'': ['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']
}
aruco = {'': ['detectMarkers', 'drawDetectedMarkers', 'drawAxis', 'estimatePoseSingleMarkers', 'estimatePoseBoard', 'estimatePoseCharucoBoard', 'interpolateCornersCharuco', 'drawDetectedCornersCharuco'],
'aruco_Dictionary': ['get', 'drawMarker'],
'aruco_Board': ['create'],
'aruco_GridBoard': ['create', 'draw'],
'aruco_CharucoBoard': ['create', 'draw'],
'aruco_DetectorParameters': ['create']
}
calib3d = {'': ['findHomography', 'calibrateCameraExtended', 'drawFrameAxes', 'estimateAffine2D', \
'getDefaultNewCameraMatrix', 'initUndistortRectifyMap', 'Rodrigues', \
'solvePnP', 'solvePnPRansac', 'solvePnPRefineLM']}
white_list = makeWhiteList([core, imgproc, objdetect, video, dnn, features2d, photo, aruco, calib3d])