OpenCV.js
JavaScript Bindings for OpenCV
Sajjad Taheri
Donald Bren School of Computer Science, UCIrvine
OpenCV
- An Open Source Library for computer vision
- Image processing
- video processing
- machine learning
- object detection
- IO
- image coding
- GPU and SIMD acceleration
- Bindings for other languages:
- Python, Java
ASM.JS
"Mangled names"
Embind
Bind C++ functions and classes to JavaScript
C/C++ Program
LLVM Bytecode
Emscripten: From C++ to JavaScript
MSER: Sample class from OpenCV
class CV_EXPORTS_W MSER : public Feature2D
{
public:
//! the full constructor
CV_WRAP static Ptr<MSER> create( int _delta=5, int _min_area=60, int _max_area=14400,
double _max_variation=0.25, double _min_diversity=.2,
int _max_evolution=200, double _area_threshold=1.01,
double _min_margin=0.003, int _edge_blur_size=5 );
CV_WRAP virtual void detectRegions( InputArray image,
CV_OUT std::vector<std::vector<Point> >& msers,
std::vector<Rect>& bboxes ) = 0;
CV_WRAP virtual void setDelta(int delta) = 0;
CV_WRAP virtual int getDelta() const = 0;
CV_WRAP virtual void setMinArea(int minArea) = 0;
CV_WRAP virtual int getMinArea() const = 0;
CV_WRAP virtual void setMaxArea(int maxArea) = 0;
CV_WRAP virtual int getMaxArea() const = 0;
CV_WRAP virtual void setPass2Only(bool f) = 0;
CV_WRAP virtual bool getPass2Only() const = 0;
};
- OpenCV uses Macros to identify symbols to binding generators
Binding code for MSER Class
emscripten::class_<cv::MSER ,base<Feature2D>>("MSER")
.function("getPass2Only", select_overload<bool(cv::MSER&)>(&Wrappers::MSER_getPass2Only_wrap),pure_virtual() )
.function("setMinArea", select_overload<void(cv::MSER&,int)>(&Wrappers::MSER_setMinArea_wrap),pure_virtual() )
.function("getDelta", select_overload<int(cv::MSER&)>(&Wrappers::MSER_getDelta_wrap),pure_virtual() )
.class_function("create",select_overload<Ptr<MSER>(int,int,int,double,double,int,double,double,int)>(&Wrappers::create_MSER_wrapper))
.function("getMaxArea", select_overload<int(cv::MSER&)>(&Wrappers::MSER_getMaxArea_wrap),pure_virtual() )
.function("setMaxArea", select_overload<void(cv::MSER&,int)>(&Wrappers::MSER_setMaxArea_wrap),pure_virtual() )
.function("setPass2Only", select_overload<void(cv::MSER&,bool)>(&Wrappers::MSER_setPass2Only_wrap),pure_virtual() )
.function("getMinArea", select_overload<int(cv::MSER&)>(&Wrappers::MSER_getMinArea_wrap),pure_virtual() )
.function("detectRegions", select_overload<void(cv::MSER&,const cv::Mat&, std::vector<std::vector<Point> >&,std::vector<Rect>&)>(&Wrappers::MSER_detectRegions_wrap),pure_virtual() )
.function("setDelta", select_overload<void(cv::MSER&,int)>(&Wrappers::MSER_setDelta_wrap),pure_virtual() )
;
Binding Generator Script
- parses all OpenCV headers
- extracts all the symbols with OpenCV Wrap macros
- classes
- functions
- class functions
- properties
- enumerations and constants
- generates appropriate binding for each type
- extracts all the symbols with OpenCV Wrap macros
Results
-
We have covered six modules so far
- core
- image processing
- object detection
- features_2d
- image codecs
- machine learning
60 classes
800 functions(including class methods)
80 Enums
- Function overloading
- Default parameters
C++ code
JS code
void erode(){
Mat image,dst;
image = imread("image.jpg", CV_LOAD_IMAGE_COLOR);
// Create a structuring element
int erosion_size = 6;
Mat element = getStructuringElement(cv::MORPH_RECT,
cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1),
cv::Point(erosion_size, erosion_size) );
// Apply erosion or dilation on the image
erode(image,dst,element);
namedWindow( "Display window", CV_WINDOW_AUTOSIZE );
imshow( "Display window", image );
namedWindow( "Result window", CV_WINDOW_AUTOSIZE );
imshow( "Result window", dst );
}
function erode(){
var src = cv.matFromArray( getInput() , cv.CV_8UC4 );
var dst = new cv.Mat();
cv.cvtColor(src, src ,
cv.cv_ColorConversionCodes.COLOR_RGBA2RGB.value,0);
// Create a structuring element
var erosion_type = cv.cv_MorphShapes.MORPH_RECT.value;
var erosion_size=new cv.Size(2*Control.erosion_size+1,
2*Control.erosion_size+1 );
var element = cv.getStructuringElement( erosion_type
,erosion_size ) ;
// Apply erosion or dilation on the image
cv.erode(src, dst, element) ;
show_image( dst , "canvas2");
// Clean up
src.delete();
dst.delete();
erosion_size.delete();
}
Erode Function
Core and image processing modules
Feature Extraction module
HAAR object detection - Working with HTML5 video element
-
Image/Video are coming from HTML Canvas
- interface to grab/show image from HTML canvas
-
Canvas API gets images in RGBA format
-
OpenCV likes RGB better
-
-
Canvas only supports data with 8 bits per pixels
-
depth data are represented with 16 bits per pixels
-
work in progress to fix this
-
Input/Output Interface
Challenges
-
Generated JS files are big
-
10MB for library itself
-
2 MB for haar cascade face and eye models
-
-
Downloading and Parsing will be time consuming
-
JS library and files are gzipped
-
will be extracted after Emscripten system initialization
-
Web Assembly
-
-
OpenCV is not fully covered
-
Anonymous Enums are not supported by Embind
-
-
Some issues with SSE2
Performance
-
Sources of penalty
-
how well browsers supports asm.js
-
Data should be copied into/from ASM.js heap
-
before computation
-
after computation
-
saved on this by returning a pointer to the heap
-
-
-
Wrapper functions overhead
-
Image format conversion
-
RGBA -> RGB and vice versa
-
-
Text
Thanks!
OpenCV.js
By Sajjad Taheri
OpenCV.js
- 613