#include "Contours.h" #include "OpenCV.h" #include #include Nan::Persistent Contour::constructor; void Contour::Init(Local target) { Nan::HandleScope scope; // Class/contructor Local ctor = Nan::New(Contour::New); constructor.Reset(ctor); ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->SetClassName(Nan::New("Contours").ToLocalChecked()); // Prototype // Local proto = constructor->PrototypeTemplate(); Nan::SetPrototypeMethod(ctor, "point", Point); Nan::SetPrototypeMethod(ctor, "size", Size); Nan::SetPrototypeMethod(ctor, "cornerCount", CornerCount); Nan::SetPrototypeMethod(ctor, "area", Area); Nan::SetPrototypeMethod(ctor, "arcLength", ArcLength); Nan::SetPrototypeMethod(ctor, "approxPolyDP", ApproxPolyDP); Nan::SetPrototypeMethod(ctor, "convexHull", ConvexHull); Nan::SetPrototypeMethod(ctor, "boundingRect", BoundingRect); Nan::SetPrototypeMethod(ctor, "minAreaRect", MinAreaRect); Nan::SetPrototypeMethod(ctor, "fitEllipse", FitEllipse); Nan::SetPrototypeMethod(ctor, "isConvex", IsConvex); Nan::SetPrototypeMethod(ctor, "moments", Moments); Nan::SetPrototypeMethod(ctor, "hierarchy", Hierarchy); Nan::SetPrototypeMethod(ctor, "serialize", Serialize); Nan::SetPrototypeMethod(ctor, "deserialize", Deserialize); target->Set(Nan::New("Contours").ToLocalChecked(), ctor->GetFunction()); }; NAN_METHOD(Contour::New) { Nan::HandleScope scope; if (info.This()->InternalFieldCount() == 0) { Nan::ThrowTypeError("Cannot instantiate without new"); } Contour *contours; contours = new Contour; contours->Wrap(info.Holder()); info.GetReturnValue().Set(info.Holder()); } Contour::Contour() : Nan::ObjectWrap() { } NAN_METHOD(Contour::Point) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); int index = info[1]->NumberValue(); cv::Point point = self->contours[pos][index]; Local data = Nan::New(); data->Set(Nan::New("x").ToLocalChecked(), Nan::New(point.x)); data->Set(Nan::New("y").ToLocalChecked(), Nan::New(point.y)); info.GetReturnValue().Set(data); } NAN_METHOD(Contour::Points) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); vector points = self->contours[pos]; Local data = Nan::New(points.size()); for (std::vector::size_type i = 0; i != points.size(); i++) { Local point_data = Nan::New(); point_data->Set(Nan::New("x").ToLocalChecked(), Nan::New(points[i].x)); point_data->Set(Nan::New("y").ToLocalChecked(), Nan::New(points[i].y)); data->Set(i, point_data); } info.GetReturnValue().Set(data); } // FIXME: this should 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. NAN_METHOD(Contour::Size) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(self->contours.size())); } NAN_METHOD(Contour::CornerCount) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); info.GetReturnValue().Set(Nan::New(self->contours[pos].size())); } NAN_METHOD(Contour::Area) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); // info.GetReturnValue().Set(Nan::New(contourArea(self->contours))); info.GetReturnValue().Set(Nan::New(contourArea(cv::Mat(self->contours[pos])))); } NAN_METHOD(Contour::ArcLength) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); bool isClosed = info[1]->BooleanValue(); info.GetReturnValue().Set(Nan::New(arcLength(cv::Mat(self->contours[pos]), isClosed))); } NAN_METHOD(Contour::ApproxPolyDP) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); double epsilon = info[1]->NumberValue(); bool isClosed = info[2]->BooleanValue(); cv::Mat approxed; approxPolyDP(cv::Mat(self->contours[pos]), approxed, epsilon, isClosed); approxed.copyTo(self->contours[pos]); info.GetReturnValue().Set(Nan::Null()); } NAN_METHOD(Contour::ConvexHull) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); bool clockwise = info[1]->BooleanValue(); cv::Mat hull; cv::convexHull(cv::Mat(self->contours[pos]), hull, clockwise); hull.copyTo(self->contours[pos]); info.GetReturnValue().Set(Nan::Null()); } NAN_METHOD(Contour::BoundingRect) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); cv::Rect bounding = cv::boundingRect(cv::Mat(self->contours[pos])); Local rect = Nan::New(); rect->Set(Nan::New("x").ToLocalChecked(), Nan::New(bounding.x)); rect->Set(Nan::New("y").ToLocalChecked(), Nan::New(bounding.y)); rect->Set(Nan::New("width").ToLocalChecked(), Nan::New(bounding.width)); rect->Set(Nan::New("height").ToLocalChecked(), Nan::New(bounding.height)); info.GetReturnValue().Set(rect); } NAN_METHOD(Contour::MinAreaRect) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); cv::RotatedRect minimum = cv::minAreaRect(cv::Mat(self->contours[pos])); Local rect = Nan::New(); rect->Set(Nan::New("angle").ToLocalChecked(), Nan::New(minimum.angle)); Local size = Nan::New(); size->Set(Nan::New("height").ToLocalChecked(), Nan::New(minimum.size.height)); size->Set(Nan::New("width").ToLocalChecked(), Nan::New(minimum.size.width)); rect->Set(Nan::New("size").ToLocalChecked(), size); Local center = Nan::New(); center->Set(Nan::New("x").ToLocalChecked(), Nan::New(minimum.center.x)); center->Set(Nan::New("y").ToLocalChecked(), Nan::New(minimum.center.y)); v8::Local points = Nan::New(4); cv::Point2f rect_points[4]; minimum.points(rect_points); for (unsigned int i=0; i<4; i++) { Local point = Nan::New(); point->Set(Nan::New("x").ToLocalChecked(), Nan::New(rect_points[i].x)); point->Set(Nan::New("y").ToLocalChecked(), Nan::New(rect_points[i].y)); points->Set(i, point); } rect->Set(Nan::New("points").ToLocalChecked(), points); info.GetReturnValue().Set(rect); } NAN_METHOD(Contour::FitEllipse) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); if (self->contours[pos].size() >= 5) { // Minimum number for an ellipse cv::RotatedRect ellipse = cv::fitEllipse(cv::Mat(self->contours[pos])); Local jsEllipse = Nan::New(); jsEllipse->Set(Nan::New("angle").ToLocalChecked(), Nan::New(ellipse.angle)); Local size = Nan::New(); size->Set(Nan::New("height").ToLocalChecked(), Nan::New(ellipse.size.height)); size->Set(Nan::New("width").ToLocalChecked(), Nan::New(ellipse.size.width)); jsEllipse->Set(Nan::New("size").ToLocalChecked(), size); Local center = Nan::New(); center->Set(Nan::New("x").ToLocalChecked(), Nan::New(ellipse.center.x)); center->Set(Nan::New("y").ToLocalChecked(), Nan::New(ellipse.center.y)); jsEllipse->Set(Nan::New("center").ToLocalChecked(), center); info.GetReturnValue().Set(jsEllipse); } info.GetReturnValue().Set(Nan::Null()); } NAN_METHOD(Contour::IsConvex) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); info.GetReturnValue().Set(Nan::New(isContourConvex(cv::Mat(self->contours[pos])))); } NAN_METHOD(Contour::Moments) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->NumberValue(); // Get the moments cv::Moments mu = moments( self->contours[pos], false ); Local res = Nan::New(); res->Set(Nan::New("m00").ToLocalChecked(), Nan::New(mu.m00)); res->Set(Nan::New("m10").ToLocalChecked(), Nan::New(mu.m10)); res->Set(Nan::New("m01").ToLocalChecked(), Nan::New(mu.m01)); res->Set(Nan::New("m11").ToLocalChecked(), Nan::New(mu.m11)); info.GetReturnValue().Set(res); } NAN_METHOD(Contour::Hierarchy) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); int pos = info[0]->IntegerValue(); cv::Vec4i hierarchy = self->hierarchy[pos]; Local res = Nan::New(4); res->Set(0, Nan::New(hierarchy[0])); res->Set(1, Nan::New(hierarchy[1])); res->Set(2, Nan::New(hierarchy[2])); res->Set(3, Nan::New(hierarchy[3])); info.GetReturnValue().Set(res); } NAN_METHOD(Contour::Serialize) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); Local contours_data = Nan::New(self->contours.size()); for (std::vector::size_type i = 0; i != self->contours.size(); i++) { vector points = self->contours[i]; Local contour_data = Nan::New(points.size()); for (std::vector::size_type j = 0; j != points.size(); j++) { Local point_data = Nan::New(2); point_data->Set(0, Nan::New(points[j].x)); point_data->Set(1, Nan::New(points[j].y)); contour_data->Set(j, point_data); } contours_data->Set(i, contour_data); } Local hierarchy_data = Nan::New(self->hierarchy.size()); for (std::vector::size_type i = 0; i != self->hierarchy.size(); i++) { Local contour_data = Nan::New(4); contour_data->Set(0, Nan::New(self->hierarchy[i][0])); contour_data->Set(1, Nan::New(self->hierarchy[i][1])); contour_data->Set(2, Nan::New(self->hierarchy[i][2])); contour_data->Set(3, Nan::New(self->hierarchy[i][3])); hierarchy_data->Set(i, contour_data); } Local data = Nan::New(); data->Set(Nan::New("contours").ToLocalChecked(), contours_data); data->Set(Nan::New("hierarchy").ToLocalChecked(), hierarchy_data); info.GetReturnValue().Set(data); } NAN_METHOD(Contour::Deserialize) { Nan::HandleScope scope; Contour *self = Nan::ObjectWrap::Unwrap(info.This()); Local data = Local::Cast(info[0]); Local contours_data = Local::Cast(data->Get(Nan::New("contours").ToLocalChecked())); Local hierarchy_data = Local::Cast(data->Get(Nan::New("hierarchy").ToLocalChecked())); vector > contours_res; int contours_length = contours_data->Length(); for (int i = 0; i < contours_length; i++) { Local contour_data = Local::Cast(contours_data->Get(i)); vector points; int contour_length = contour_data->Length(); for (int j = 0; j < contour_length; j++) { Local point_data = Local::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++) { Local contour_data = Local::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; info.GetReturnValue().Set(Nan::Null()); }