#include "Contours.h" #include "OpenCV.h" #include v8::Persistent Contour::constructor; void Contour::Init(Handle target) { HandleScope scope; //Class v8::Local m = v8::FunctionTemplate::New(New); m->SetClassName(v8::String::NewSymbol("Contours")); // Constructor constructor = Persistent::New(m); constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->SetClassName(String::NewSymbol("Contours")); // Prototype //Local proto = constructor->PrototypeTemplate(); NODE_SET_PROTOTYPE_METHOD(constructor, "point", Point); NODE_SET_PROTOTYPE_METHOD(constructor, "points", Points); NODE_SET_PROTOTYPE_METHOD(constructor, "size", Size); NODE_SET_PROTOTYPE_METHOD(constructor, "cornerCount", CornerCount); NODE_SET_PROTOTYPE_METHOD(constructor, "area", Area); NODE_SET_PROTOTYPE_METHOD(constructor, "arcLength", ArcLength); NODE_SET_PROTOTYPE_METHOD(constructor, "approxPolyDP", ApproxPolyDP); NODE_SET_PROTOTYPE_METHOD(constructor, "convexHull", ConvexHull); NODE_SET_PROTOTYPE_METHOD(constructor, "boundingRect", BoundingRect); NODE_SET_PROTOTYPE_METHOD(constructor, "minAreaRect", MinAreaRect); NODE_SET_PROTOTYPE_METHOD(constructor, "isConvex", IsConvex); NODE_SET_PROTOTYPE_METHOD(constructor, "moments", Moments); NODE_SET_PROTOTYPE_METHOD(constructor, "hierarchy", Hierarchy); NODE_SET_PROTOTYPE_METHOD(constructor, "serialize", Serialize); NODE_SET_PROTOTYPE_METHOD(constructor, "deserialize", Deserialize); target->Set(String::NewSymbol("Contours"), m->GetFunction()); }; Handle Contour::New(const Arguments &args) { HandleScope scope; if (args.This()->InternalFieldCount() == 0) return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Cannot instantiate without new"))); Contour *contours; contours = new Contour; contours->Wrap(args.Holder()); return scope.Close(args.Holder()); } Contour::Contour(): ObjectWrap() { } Handle Contour::Point(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); int index = args[1]->NumberValue(); cv::Point point = self->contours[pos][index]; Local data = Object::New(); data->Set(String::NewSymbol("x"), Number::New(point.x)); data->Set(String::NewSymbol("y"), Number::New(point.y)); return scope.Close(data); } Handle Contour::Points(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); vector points = self->contours[pos]; Local data = Array::New(points.size()); for (std::vector::size_type i = 0; i != points.size(); i++) { Local point_data = Object::New(); point_data->Set(String::NewSymbol("x"), Number::New(points[i].x)); point_data->Set(String::NewSymbol("y"), Number::New(points[i].y)); data->Set(i, point_data); } return scope.Close(data); } // FIXME: this sould better be called "Length" as ``Contours`` is an Array like structure // also, this would allow to use ``Size`` for the function returning the number of corners // in the contour for better consistency with OpenCV. Handle Contour::Size(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); return scope.Close(Number::New(self->contours.size())); } Handle Contour::CornerCount(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); return scope.Close(Number::New(self->contours[pos].size())); } Handle Contour::Area(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); //return scope.Close(Number::New(contourArea(self->contours))); return scope.Close(Number::New(contourArea(cv::Mat(self->contours[pos])))); } Handle Contour::ArcLength(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); bool isClosed = args[1]->BooleanValue(); return scope.Close(Number::New(arcLength(cv::Mat(self->contours[pos]), isClosed))); } Handle Contour::ApproxPolyDP(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); double epsilon = args[1]->NumberValue(); bool isClosed = args[2]->BooleanValue(); cv::Mat approxed; approxPolyDP(cv::Mat(self->contours[pos]), approxed, epsilon, isClosed); approxed.copyTo(self->contours[pos]); return scope.Close(v8::Null()); } Handle Contour::ConvexHull(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); bool clockwise = args[1]->BooleanValue(); cv::Mat hull; cv::convexHull(cv::Mat(self->contours[pos]), hull, clockwise); hull.copyTo(self->contours[pos]); return scope.Close(v8::Null()); } Handle Contour::BoundingRect(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); cv::Rect bounding = cv::boundingRect(cv::Mat(self->contours[pos])); Local rect = Object::New(); rect->Set(String::NewSymbol("x"), Number::New(bounding.x)); rect->Set(String::NewSymbol("y"), Number::New(bounding.y)); rect->Set(String::NewSymbol("width"), Number::New(bounding.width)); rect->Set(String::NewSymbol("height"), Number::New(bounding.height)); return scope.Close(rect); } Handle Contour::MinAreaRect(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); cv::RotatedRect minimum = cv::minAreaRect(cv::Mat(self->contours[pos])); Local rect = Object::New(); rect->Set(String::NewSymbol("angle"), Number::New(minimum.angle)); Local size = Object::New(); size->Set(String::NewSymbol("height"), Number::New(minimum.size.height)); size->Set(String::NewSymbol("width"), Number::New(minimum.size.width)); rect->Set(String::NewSymbol("size"), size); Local center = Object::New(); center->Set(String::NewSymbol("x"), Number::New(minimum.center.x)); center->Set(String::NewSymbol("y"), Number::New(minimum.center.y)); v8::Local points = v8::Array::New(4); cv::Point2f rect_points[4]; minimum.points(rect_points); for (unsigned int i=0; i<4; i++){ Local point = Object::New(); point->Set(String::NewSymbol("x"), Number::New(rect_points[i].x)); point->Set(String::NewSymbol("y"), Number::New(rect_points[i].y)); points->Set(i, point); } rect->Set(String::NewSymbol("points"), points); return scope.Close(rect); } Handle Contour::IsConvex(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); return scope.Close(Boolean::New(isContourConvex(cv::Mat(self->contours[pos])))); } Handle Contour::Moments(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->NumberValue(); /// Get the moments cv::Moments mu = moments( self->contours[pos], false ); Local res = Object::New(); res->Set(String::NewSymbol("m00"), Number::New(mu.m00)); res->Set(String::NewSymbol("m10"), Number::New(mu.m10)); res->Set(String::NewSymbol("m01"), Number::New(mu.m01)); res->Set(String::NewSymbol("m11"), Number::New(mu.m11)); return scope.Close(res); } Handle Contour::Hierarchy(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); int pos = args[0]->IntegerValue(); cv::Vec4i hierarchy = self->hierarchy[pos]; Local res = Array::New(4); res->Set(0, Number::New(hierarchy[0])); res->Set(1, Number::New(hierarchy[1])); res->Set(2, Number::New(hierarchy[2])); res->Set(3, Number::New(hierarchy[3])); return scope.Close(res); } Handle Contour::Serialize(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); Local contours_data = Array::New(self->contours.size()); for (std::vector::size_type i = 0; i != self->contours.size(); i++) { vector points = self->contours[i]; Local contour_data = Array::New(points.size()); for (std::vector::size_type j = 0; j != points.size(); j++) { Local point_data = Array::New(2); point_data->Set(0, Number::New(points[j].x)); point_data->Set(1, Number::New(points[j].y)); contour_data->Set(j, point_data); } contours_data->Set(i, contour_data); } Local hierarchy_data = Array::New(self->hierarchy.size()); for (std::vector::size_type i = 0; i != self->hierarchy.size(); i++) { Local contour_data = Array::New(4); contour_data->Set(0, Number::New(self->hierarchy[i][0])); contour_data->Set(1, Number::New(self->hierarchy[i][1])); contour_data->Set(2, Number::New(self->hierarchy[i][2])); contour_data->Set(3, Number::New(self->hierarchy[i][3])); hierarchy_data->Set(i, contour_data); } Local data = Object::New(); data->Set(String::NewSymbol("contours"), contours_data); data->Set(String::NewSymbol("hierarchy"), hierarchy_data); return scope.Close(data); } Handle Contour::Deserialize(const Arguments &args) { HandleScope scope; Contour *self = ObjectWrap::Unwrap(args.This()); Handle data = Handle::Cast(args[0]); Handle contours_data = Handle::Cast(data->Get(v8::String::NewSymbol("contours"))); Handle hierarchy_data = Handle::Cast(data->Get(v8::String::NewSymbol("hierarchy"))); vector > contours_res; int contours_length = contours_data->Length(); for (int i = 0; i < contours_length; i++) { Handle contour_data = Handle::Cast(contours_data->Get(i)); vector points; int contour_length = contour_data->Length(); for (int j = 0; j < contour_length; j++) { Handle point_data = Handle::Cast(contour_data->Get(j)); int x = point_data->Get(0)->IntegerValue(); int y = point_data->Get(1)->IntegerValue(); points.push_back(cv::Point(x, y)); } contours_res.push_back(points); } vector hierarchy_res; int hierarchy_length = hierarchy_data->Length(); for (int i = 0; i < hierarchy_length; i++) { Handle contour_data = Handle::Cast(hierarchy_data->Get(i)); int a = contour_data->Get(0)->IntegerValue(); int b = contour_data->Get(1)->IntegerValue(); int c = contour_data->Get(2)->IntegerValue(); int d = contour_data->Get(3)->IntegerValue(); hierarchy_res.push_back(cv::Vec4i(a, b, c, d)); } self->contours = contours_res; self->hierarchy = hierarchy_res; return scope.Close(v8::Null()); }