Skip to content
This repository was archived by the owner on Oct 18, 2023. It is now read-only.

Commit ae1faee

Browse files
Merge pull request justadudewhohacks#474 from piercus/master
Add mat.eigen(), mat.solve(mat2) and mat.matMul(mat2)
2 parents 1df4974 + 4bebf5b commit ae1faee

File tree

8 files changed

+187
-1
lines changed

8 files changed

+187
-1
lines changed

cc/core/Mat.cc

+38
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,19 @@ NAN_MODULE_INIT(Mat::Init) {
9595
Nan::SetPrototypeMethod(ctor, "copyMakeBorderAsync", CopyMakeBorderAsync);
9696
Nan::SetPrototypeMethod(ctor, "reduce", Reduce);
9797
Nan::SetPrototypeMethod(ctor, "reduceAsync", ReduceAsync);
98+
Nan::SetPrototypeMethod(ctor, "eigen", Eigen);
99+
Nan::SetPrototypeMethod(ctor, "eigenAsync", EigenAsync);
100+
Nan::SetPrototypeMethod(ctor, "solve", Solve);
101+
Nan::SetPrototypeMethod(ctor, "solveAsync", SolveAsync);
102+
98103
#if CV_VERSION_MINOR > 1
99104
Nan::SetPrototypeMethod(ctor, "rotate", Rotate);
100105
Nan::SetPrototypeMethod(ctor, "rotateAsync", RotateAsync);
101106
#endif
102107

103108
Nan::SetPrototypeMethod(ctor, "release", Release);
104109

110+
105111
FF_PROTO_SET_MAT_OPERATIONS(ctor);
106112

107113
MatImgproc::Init(ctor);
@@ -870,6 +876,38 @@ NAN_METHOD(Mat::ReduceAsync) {
870876
);
871877
}
872878

879+
NAN_METHOD(Mat::Eigen) {
880+
FF::SyncBinding(
881+
std::make_shared<MatBindings::EigenWorker>(Mat::Converter::unwrap(info.This())),
882+
"Mat::Eigen",
883+
info
884+
);
885+
}
886+
887+
NAN_METHOD(Mat::EigenAsync) {
888+
FF::AsyncBinding(
889+
std::make_shared<MatBindings::EigenWorker>(Mat::Converter::unwrap(info.This())),
890+
"Mat::EigenAsync",
891+
info
892+
);
893+
}
894+
895+
NAN_METHOD(Mat::Solve) {
896+
FF::SyncBinding(
897+
std::make_shared<MatBindings::SolveWorker>(Mat::Converter::unwrap(info.This())),
898+
"Mat::Solve",
899+
info
900+
);
901+
}
902+
903+
NAN_METHOD(Mat::SolveAsync) {
904+
FF::AsyncBinding(
905+
std::make_shared<MatBindings::SolveWorker>(Mat::Converter::unwrap(info.This())),
906+
"Mat::SolveAsync",
907+
info
908+
);
909+
}
910+
873911
#if CV_VERSION_MINOR > 1
874912
NAN_METHOD(Mat::Rotate) {
875913
FF::SyncBinding(

cc/core/Mat.h

+5
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ class Mat : public Nan::ObjectWrap {
126126
static NAN_METHOD(CopyMakeBorderAsync);
127127
static NAN_METHOD(Reduce);
128128
static NAN_METHOD(ReduceAsync);
129+
static NAN_METHOD(Eigen);
130+
static NAN_METHOD(EigenAsync);
131+
static NAN_METHOD(Solve);
132+
static NAN_METHOD(SolveAsync);
133+
129134
#if CV_VERSION_MINOR > 1
130135
static NAN_METHOD(Rotate);
131136
static NAN_METHOD(RotateAsync);

cc/core/MatBindings.h

+52
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,59 @@ namespace MatBindings {
926926
);
927927
}
928928
};
929+
930+
struct EigenWorker : public CatchCvExceptionWorker {
931+
public:
932+
cv::Mat self;
933+
EigenWorker(cv::Mat self) {
934+
this->self = self;
935+
}
936+
937+
cv::Mat eigenvalues;
938+
939+
std::string executeCatchCvExceptionWorker() {
940+
cv::eigen(self, eigenvalues);
941+
return "";
942+
}
943+
944+
v8::Local<v8::Value> getReturnValue() {
945+
return Mat::Converter::wrap(eigenvalues);
946+
}
947+
};
948+
949+
struct SolveWorker : public CatchCvExceptionWorker {
950+
public:
951+
cv::Mat self;
952+
SolveWorker(cv::Mat self) {
953+
this->self = self;
954+
}
955+
956+
cv::Mat mat2;
957+
cv::Mat dst;
958+
int flags = 0; // cv.DECOMP_LU
959+
960+
std::string executeCatchCvExceptionWorker() {
961+
cv::solve(self, mat2, dst, flags);
962+
return "";
963+
}
929964

965+
v8::Local<v8::Value> getReturnValue() {
966+
return Mat::Converter::wrap(dst);
967+
}
968+
969+
bool unwrapRequiredArgs(Nan::NAN_METHOD_ARGS_TYPE info) {
970+
return (
971+
Mat::Converter::arg(0, &mat2, info)
972+
);
973+
}
974+
975+
bool unwrapOptionalArgs(Nan::NAN_METHOD_ARGS_TYPE info) {
976+
return (
977+
IntConverter::optArg(1, &flags, info)
978+
);
979+
}
980+
};
981+
930982
#if CV_VERSION_MINOR > 1
931983
struct RotateWorker : public OpWithCodeWorker {
932984
public:

cc/core/coreUtils.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@
9292
Nan::SetPrototypeMethod(ctor, "bitwiseXor", BitwiseXor); \
9393
Nan::SetPrototypeMethod(ctor, "abs", Abs); \
9494
Nan::SetPrototypeMethod(ctor, "transpose", Transpose); \
95-
Nan::SetPrototypeMethod(ctor, "determinant", Determinant);
95+
Nan::SetPrototypeMethod(ctor, "determinant", Determinant);\
96+
Nan::SetPrototypeMethod(ctor, "matMul", MatMul);
9697

9798
#define FF_INIT_ARITHMETIC_OPERATIONS(clazz, unwrapper) \
9899
static NAN_METHOD(Add) { \
@@ -158,6 +159,9 @@
158159
} \
159160
static NAN_METHOD(Transpose) { \
160161
FF_SELF_OPERATOR(cv::transpose, FF_UNWRAP_MAT_AND_GET); \
162+
} \
163+
static NAN_METHOD(MatMul) { \
164+
FF_OPERATOR(*, FF_APPLY_OPERATOR, FF_UNWRAP_MAT_AND_GET, Mat); \
161165
}
162166

163167
#define FF_INIT_VEC2_OPERATIONS() FF_INIT_MATRIX_OPERATIONS(Vec2, FF_UNWRAP_VEC2_AND_GET);

cc/cvTypes/cvTypes.cc

+7
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,11 @@ void CvTypes::Init(v8::Local<v8::Object> target) {
223223
FF_SET_CV_CONSTANT(target, COLORMAP_PINK);
224224
FF_SET_CV_CONSTANT(target, COLORMAP_HOT);
225225
FF_SET_CV_CONSTANT(target, COLORMAP_PARULA);
226+
227+
FF_SET_CV_CONSTANT(target, DECOMP_LU);
228+
FF_SET_CV_CONSTANT(target, DECOMP_CHOLESKY);
229+
FF_SET_CV_CONSTANT(target, DECOMP_EIG);
230+
FF_SET_CV_CONSTANT(target, DECOMP_SVD);
231+
FF_SET_CV_CONSTANT(target, DECOMP_QR);
232+
FF_SET_CV_CONSTANT(target, DECOMP_NORMAL);
226233
}

lib/typings/Mat.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ export class Mat {
133133
drawPolylines(pts: Point2[][], isClosed: boolean, color?: Vec3, thickness?: number, lineType?: number, shift?: number): void;
134134
drawRectangle(pt0: Point2, pt1: Point2, color?: Vec3, thickness?: number, lineType?: number, shift?: number): void;
135135
drawRectangle(rect: Rect, color?: Vec3, thickness?: number, lineType?: number, shift?: number): void;
136+
eigen(): Mat;
137+
eigenAsync(): Promise<Mat>;
136138
equalizeHist(): Mat;
137139
equalizeHistAsync(): Promise<Mat>;
138140
erode(kernel: Mat, anchor?: Point2, iterations?: number, borderType?: number): Mat;
@@ -197,6 +199,7 @@ export class Mat {
197199
integralAsync(sdepth?: number, sqdepth?: number): Promise<{ sum: Mat, sqsum: Mat, tilted: Mat }>;
198200
laplacian(ddepth: number, ksize?: number, scale?: number, delta?: number, borderType?: number): Mat;
199201
laplacianAsync(ddepth: number, ksize?: number, scale?: number, delta?: number, borderType?: number): Promise<Mat>;
202+
matMul(B: Mat): Mat;
200203
matMulDeriv(B: Mat): { dABdA: Mat, dABdB: Mat };
201204
matMulDerivAsync(B: Mat): Promise<{ dABdA: Mat, dABdB: Mat }>;
202205
matchTemplate(template: Mat, method: number, mask?: Mat): Mat;
@@ -278,6 +281,8 @@ export class Mat {
278281
setToAsync(value: Vec4, mask?: Mat): Promise<Mat>;
279282
sobel(ddepth: number, dx: number, dy: number, ksize?: number, scale?: number, delta?: number, borderType?: number): Mat;
280283
sobelAsync(ddepth: number, dx: number, dy: number, ksize?: number, scale?: number, delta?: number, borderType?: number): Promise<Mat>;
284+
solve(mat2: Mat, flags?: number): Mat;
285+
solveAsync(mat2: Mat, flags?: number): Promise<Mat>;
281286
split(): Mat[];
282287
splitAsync(): Promise<Mat[]>;
283288
splitChannels(): Mat[];

test/tests/core/Mat/Mat.test.js

+53
Original file line numberDiff line numberDiff line change
@@ -993,4 +993,57 @@ describe('Mat', () => {
993993
);
994994
});
995995
});
996+
997+
describe('eigen', () => {
998+
const makeTest = (values, expectedResults) => () => {
999+
generateAPITests({
1000+
getDut: () => new cv.Mat(values, cv.CV_32F),
1001+
methodName: 'eigen',
1002+
methodNameSpace: 'Mat',
1003+
expectOutput: (res, _, args) => {
1004+
expect(res).to.be.instanceOf(cv.Mat);
1005+
const arrayRes = res.getDataAsArray();
1006+
const tolerance = 1e-6;
1007+
arrayRes.forEach((r,i1) => {
1008+
r.forEach((n,i2) => {
1009+
expect(n).to.be.at.least(expectedResults[i1][i2]-tolerance);
1010+
expect(n).to.be.at.most(expectedResults[i1][i2]+tolerance)
1011+
})
1012+
})
1013+
}
1014+
});
1015+
};
1016+
1017+
describe('eigen', makeTest([[2,1],[1,2]], [[3], [1]]))
1018+
});
1019+
describe('solve', () => {
1020+
const makeTest = (values1, values2, flags, expectedResults) => () => {
1021+
const m2 = new cv.Mat(values2, cv.CV_32F);
1022+
1023+
generateAPITests({
1024+
getDut: () => new cv.Mat(values1, cv.CV_32F),
1025+
methodName: 'solve',
1026+
methodNameSpace: 'Mat',
1027+
getOptionalArgsMap: () => ([
1028+
['flags', flags]
1029+
]),
1030+
getRequiredArgs: () => ([m2]),
1031+
expectOutput: (res, _, args) => {
1032+
expect(res).to.be.instanceOf(cv.Mat);
1033+
const arrayRes = res.getDataAsArray();
1034+
const tolerance = 1e-6;
1035+
arrayRes.forEach((r,i1) => {
1036+
r.forEach((n,i2) => {
1037+
expect(n).to.be.at.least(expectedResults[i1][i2]-tolerance);
1038+
expect(n).to.be.at.most(expectedResults[i1][i2]+tolerance)
1039+
})
1040+
})
1041+
}
1042+
});
1043+
};
1044+
1045+
describe('Solve y = x equation on Id = X Id', makeTest([[1, 0, 0],[0, 1, 0],[0, 0, 1]], [[1, 0, 0],[0, 1, 0],[0, 0, 1]], cv.DECOMP_LU, [[1, 0, 0],[0, 1, 0],[0, 0, 1]]));
1046+
describe('Solve y = x equation on Id = X Id', makeTest([[1, 2],[3, 4]], [[5, 6],[7, 8]], cv.DECOMP_LU, [[-3, -4],[4, 5]]));
1047+
});
1048+
9961049
});

test/tests/core/Mat/operatorTests.js

+22
Original file line numberDiff line numberDiff line change
@@ -352,4 +352,26 @@ module.exports = () => {
352352
assertDataDeepEquals(res.getDataAsArray(), expectedResult);
353353
});
354354
});
355+
356+
describe('matMul', () => {
357+
operatorRequiresArg('matMul');
358+
359+
it('apply matMul to matrices', () => {
360+
const mat0 = new cv.Mat([
361+
[20, 40],
362+
[60, 80]
363+
], cv.CV_32F);
364+
const mat1 = new cv.Mat([
365+
[5, 4],
366+
[2, 1]
367+
], cv.CV_32F);
368+
const expectedResult = [
369+
[180, 120],
370+
[460, 320]
371+
];
372+
const res = mat0.matMul(mat1);
373+
assertMetaData(res)(2, 2, cv.CV_32F);
374+
assertDataDeepEquals(res.getDataAsArray(), expectedResult);
375+
});
376+
});
355377
};

0 commit comments

Comments
 (0)