Skip to content

Commit

Permalink
Merge pull request #150 from tothadi/feat/row-rowrange-col-colrange
Browse files Browse the repository at this point in the history
Add bindings for row, rowRange, col, colRange
  • Loading branch information
UrielCh authored Jul 10, 2024
2 parents 8dbcf7a + bc087f0 commit 2494f4e
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 73 deletions.
92 changes: 52 additions & 40 deletions cc/core/Mat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ NAN_MODULE_INIT(Mat::Init) {
Nan::SetPrototypeMethod(ctor, "setData", SetData);
Nan::SetPrototypeMethod(ctor, "getRegion", GetRegion);
Nan::SetPrototypeMethod(ctor, "row", Row);
Nan::SetPrototypeMethod(ctor, "rowRange", RowRange);
Nan::SetPrototypeMethod(ctor, "col", Col);
Nan::SetPrototypeMethod(ctor, "colRange", ColRange);
Nan::SetPrototypeMethod(ctor, "copy", Copy);
Nan::SetPrototypeMethod(ctor, "copyAsync", CopyAsync);
Nan::SetPrototypeMethod(ctor, "copyTo", CopyTo);
Expand Down Expand Up @@ -327,7 +330,7 @@ NAN_MODULE_INIT(Mat::Init) {
}

// std::cout << "loop line " << cur[0] << "/" << sizes[1] << std::endl;
// std::cout << "loop cell " << cur[0] << "/" << sizes[0] << ", " << cur[1] << "/" << sizes[1] << std::endl;
// std::cout << "loop cell " << cur[0] << "/" << sizes[0] << ", " << cur[1] << "/" << sizes[1] << std::endl;
// std::cout << "loop cell " << cur[0] << "/" << sizes[0] << ", " << cur[1] << "/" << sizes[1] << ", " << cur[2] << "/" << sizes[2]<< std::endl;
// std::cout << "loop pos " << cur[0] << ", " << cur[1] << ", " << cur[2] << ", " << cur[3] << std::endl;

Expand Down Expand Up @@ -502,9 +505,9 @@ NAN_METHOD(Mat::New) {
else if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsInt32()) {
int type = info[2]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value();
if (info.Length() == 3 || info[3]->IsArray() || info[3]->IsNumber()) {

cv::Mat mat(info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(), info[1]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(), type);

/* fill vector */
// TODO by Vec
if (info[3]->IsArray()) {
Expand All @@ -527,17 +530,17 @@ NAN_METHOD(Mat::New) {
if(info[4]->IsNumber()){
int step = info[4]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value();
cv::Mat mat(
info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[1]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[1]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
type,
data,
step
);
self->setNativeObject(mat);
} else {
cv::Mat mat(
info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[1]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[1]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
type,
data
);
Expand Down Expand Up @@ -814,7 +817,7 @@ NAN_METHOD(Mat::GetDataAsArray) {
FF::TryCatch tryCatch("Mat::GetDataAsArray");
cv::Mat mat = Mat::unwrapSelf(info);
v8::Local<v8::Array> rowArray = Nan::New<v8::Array>(mat.size[0]);

switch (mat.dims) {
case 2: FF_MAT_APPLY_TYPED_OPERATOR(mat, rowArray, mat.type(), FF_JS_ARRAY_FROM_MAT_2D, FF::matGet); break;
case 3: FF_MAT_APPLY_TYPED_OPERATOR(mat, rowArray, mat.type(), FF_JS_ARRAY_FROM_MAT_3D, FF::matGet); break;
Expand Down Expand Up @@ -886,41 +889,50 @@ NAN_METHOD(Mat::Norm) {
info.GetReturnValue().Set(norm);
}

// The method makes a new header for the specified matrix row and returns it. This is an O(1)
// operation, regardless of the matrix size. The underlying data of the new matrix is shared with the
// original matrix.
NAN_METHOD(Mat::Row) {
FF::TryCatch tryCatch("Mat::Row");
if (!info[0]->IsNumber()) {
return tryCatch.throwError("usage: row(int r)");
FF::TryCatch tryCatch("Mat::Row");
int row;
if (FF::IntConverter::arg(0, &row, info)) {
return tryCatch.reThrow();
}
int r = (int)info[0]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value();
cv::Mat mat = Mat::unwrapSelf(info);
v8::Local<v8::Array> row = Nan::New<v8::Array>(mat.cols);
try {
if (mat.type() == CV_32FC1) {
for (int c = 0; c < mat.cols; c++) {
Nan::Set(row, c, Nan::New(mat.at<float>(r, c)));
}
} else if (mat.type() == CV_8UC1) {
for (int c = 0; c < mat.cols; c++) {
Nan::Set(row, c, Nan::New((uint)mat.at<uchar>(r, c)));
}
} else if (mat.type() == CV_8UC3) {
for (int c = 0; c < mat.cols; c++) {
cv::Vec3b vec = mat.at<cv::Vec3b>(r, c);
v8::Local<v8::Array> jsVec = Nan::New<v8::Array>(3);
for (int i = 0; i < 3; i++) {
Nan::Set(jsVec, i, Nan::New(vec[i]));
}
Nan::Set(row, c, jsVec);
}
} else {
return tryCatch.throwError("not implemented yet - mat type:" + std::to_string(mat.type()));
}
} catch(std::exception &e) {
return tryCatch.throwError(e.what());
} catch(...) {
return tryCatch.throwError("... Exception");
info.GetReturnValue().Set(Mat::Converter::wrap(Mat::unwrapSelf(info).row(row)));
}

// The method makes a new header for the specified matrix column and returns it. This is an O(1)
// operation, regardless of the matrix size. The underlying data of the new matrix is shared with the
// original matrix. See also the Mat::row description.
NAN_METHOD(Mat::Col) {
FF::TryCatch tryCatch("Mat::Col");
int col;
if (FF::IntConverter::arg(0, &col, info)) {
return tryCatch.reThrow();
}
info.GetReturnValue().Set(Mat::Converter::wrap(Mat::unwrapSelf(info).col(col)));
}

// The method makes a new header for the specified row span of the matrix. Similarly to Mat::row and
// Mat::col , this is an O(1) operation.
NAN_METHOD(Mat::RowRange) {
FF::TryCatch tryCatch("Mat::RowRange");
int start, end;
if (FF::IntConverter::arg(0, &start, info) || FF::IntConverter::arg(1, &end, info)) {
return tryCatch.reThrow();
}
info.GetReturnValue().Set(Mat::Converter::wrap(Mat::unwrapSelf(info).rowRange(start, end)));
}

// The method makes a new header for the specified column span of the matrix. Similarly to Mat::row and
// Mat::col , this is an O(1) operation.
NAN_METHOD(Mat::ColRange) {
FF::TryCatch tryCatch("Mat::ColRange");
int start, end;
if (FF::IntConverter::arg(0, &start, info) || FF::IntConverter::arg(1, &end, info)) {
return tryCatch.reThrow();
}
info.GetReturnValue().Set(row);
info.GetReturnValue().Set(Mat::Converter::wrap(Mat::unwrapSelf(info).colRange(start, end)));
}

NAN_METHOD(Mat::Release) {
Expand Down
3 changes: 3 additions & 0 deletions cc/core/Mat.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class Mat : public FF::ObjectWrap<Mat, cv::Mat> {
static NAN_METHOD(GetRegion);
static NAN_METHOD(Norm);
static NAN_METHOD(Row);
static NAN_METHOD(RowRange);
static NAN_METHOD(Col);
static NAN_METHOD(ColRange);
static NAN_METHOD(Release);
static NAN_METHOD(PushBack);
static NAN_METHOD(PushBackAsync);
Expand Down
65 changes: 65 additions & 0 deletions test/tests/core/Mat/accessor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,71 @@ if (toTest.core) {
generateIts('should return correct values at each pixel position', createAndAssertAtReturnsCorrectValues);
});

describe("row", () => {
it("should return a new Mat with the correct row", () => {
const type = cv.CV_8U;
const mat = new cv.Mat(
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
],
type
);
const row = mat.row(1);
assertDataDeepEquals([[4, 5, 6]], row.getDataAsArray());
});
});

describe("col", () => {
it("should return a new Mat with the correct col", () => {
const type = cv.CV_8U;
const mat = new cv.Mat(
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
],
type
);
const col = mat.col(1);
assertDataDeepEquals([[2], [5], [8]], col.getDataAsArray());
});
});

describe("rowRange", () => {
it("should return a new Mat with the correct row range", () => {
const type = cv.CV_8U;
const mat = new cv.Mat(
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12],
],
type
);
const rowRange = mat.rowRange(1, 3);
assertDataDeepEquals([[4, 5, 6], [7, 8, 9]], rowRange.getDataAsArray());
});
});

describe("colRange", () => {
it("should return a new Mat with the correct col range", () => {
const type = cv.CV_8U;
const mat = new cv.Mat(
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
],
type
);
const colRange = mat.colRange(1, 3);
assertDataDeepEquals([[2, 3], [6, 7], [10, 11]], colRange.getDataAsArray());
});
});

describe.skip('atRaw', () => {
it('atRaw', () => {
expect(true).to.be.false;
Expand Down
Loading

0 comments on commit 2494f4e

Please sign in to comment.