From f35c459e12410b06bca6bedc7010a8ba5f823ee5 Mon Sep 17 00:00:00 2001 From: Johan Junik Jo Date: Thu, 10 Oct 2019 17:54:00 +0900 Subject: [PATCH 1/3] add accumulate --- cc/imgproc/imgproc.cc | 40 +++++++ cc/imgproc/imgproc.h | 8 ++ cc/imgproc/imgprocBindings.h | 54 +++++++++ lib/typings/cv.d.ts | 8 ++ test/tests/imgproc/imgprocTests.js | 182 +++++++++++++++++++++++++++++ 5 files changed, 292 insertions(+) diff --git a/cc/imgproc/imgproc.cc b/cc/imgproc/imgproc.cc index cb890010b..fddf6b666 100644 --- a/cc/imgproc/imgproc.cc +++ b/cc/imgproc/imgproc.cc @@ -53,6 +53,14 @@ NAN_MODULE_INIT(Imgproc::Init) { Nan::SetMethod(target, "gaussianBlurAsync", GaussianBlurAsync); Nan::SetMethod(target, "medianBlur", MedianBlur); Nan::SetMethod(target, "medianBlurAsync", MedianBlurAsync); + Nan::SetMethod(target, "accumulate", Accumulate); + Nan::SetMethod(target, "accumulateAsync", AccumulateAsync); + Nan::SetMethod(target, "accumulateProduct", AccumulateProduct); + Nan::SetMethod(target, "accumulateProductAsync", AccumulateProductAsync); + Nan::SetMethod(target, "accumulateSquare", AccumulateSquare); + Nan::SetMethod(target, "accumulateSquareAsync", AccumulateSquareAsync); + Nan::SetMethod(target, "accumulateWeighted", AccumulateWeighted); + Nan::SetMethod(target, "accumulateWeightedAsync", AccumulateWeightedAsync); Moments::Init(target); @@ -391,4 +399,36 @@ NAN_METHOD(Imgproc::MedianBlurAsync) { FF::asyncBinding("Imgproc", "MedianBlur", info); } +NAN_METHOD(Imgproc::Accumulate) { + FF::syncBinding("Imgproc", "Accumulate", info); +} + +NAN_METHOD(Imgproc::AccumulateAsync) { + FF::asyncBinding("Imgproc", "Accumulate", info); +} + +NAN_METHOD(Imgproc::AccumulateProduct) { + FF::syncBinding("Imgproc", "AccumulateProduct", info); +} + +NAN_METHOD(Imgproc::AccumulateProductAsync) { + FF::asyncBinding("Imgproc", "AccumulateProduct", info); +} + +NAN_METHOD(Imgproc::AccumulateSquare) { + FF::syncBinding("Imgproc", "AccumulateSquare", info); +} + +NAN_METHOD(Imgproc::AccumulateSquareAsync) { + FF::asyncBinding("Imgproc", "AccumulateSquare", info); +} + +NAN_METHOD(Imgproc::AccumulateWeighted) { + FF::syncBinding("Imgproc", "AccumulateWeighted", info); +} + +NAN_METHOD(Imgproc::AccumulateWeightedAsync) { + FF::asyncBinding("Imgproc", "AccumulateWeighted", info); +} + #endif \ No newline at end of file diff --git a/cc/imgproc/imgproc.h b/cc/imgproc/imgproc.h index 583893368..ba79c53a8 100644 --- a/cc/imgproc/imgproc.h +++ b/cc/imgproc/imgproc.h @@ -41,6 +41,14 @@ class Imgproc { static NAN_METHOD(GaussianBlurAsync); static NAN_METHOD(MedianBlur); static NAN_METHOD(MedianBlurAsync); + static NAN_METHOD(Accumulate); + static NAN_METHOD(AccumulateAsync); + static NAN_METHOD(AccumulateProduct); + static NAN_METHOD(AccumulateProductAsync); + static NAN_METHOD(AccumulateSquare); + static NAN_METHOD(AccumulateSquareAsync); + static NAN_METHOD(AccumulateWeighted); + static NAN_METHOD(AccumulateWeightedAsync); }; #endif diff --git a/cc/imgproc/imgprocBindings.h b/cc/imgproc/imgprocBindings.h index a35bd67cd..9970ed0ca 100644 --- a/cc/imgproc/imgprocBindings.h +++ b/cc/imgproc/imgprocBindings.h @@ -204,6 +204,60 @@ namespace ImgprocBindings { }; }; }; + + class Accumulate : public CvBinding { + public: + void setup() { + auto src = req(); + auto dst = req(); + auto mask = opt("mask", cv::noArray().getMat()); + + executeBinding = [=]() { + cv::accumulate(src->ref(), dst->ref(), mask->ref()); + }; + }; + }; + + class AccumulateProduct : public CvBinding { + public: + void setup() { + auto src1 = req(); + auto src2 = req(); + auto dst = req(); + auto mask = opt("mask", cv::noArray().getMat()); + + executeBinding = [=]() { + cv::accumulateProduct(src1->ref(), src2->ref(), dst->ref(), mask->ref()); + }; + }; + }; + + class AccumulateSquare : public CvBinding { + public: + void setup() { + auto src = req(); + auto dst = req(); + auto mask = opt("mask", cv::noArray().getMat()); + + executeBinding = [=]() { + cv::accumulateSquare(src->ref(), dst->ref(), mask->ref()); + }; + }; + }; + + class AccumulateWeighted : public CvBinding { + public: + void setup() { + auto src = req(); + auto dst = req(); + auto alpha = req(); + auto mask = opt("mask", cv::noArray().getMat()); + + executeBinding = [=]() { + cv::accumulateWeighted(src->ref(), dst->ref(), alpha->ref(), mask->ref()); + }; + }; + }; } #endif \ No newline at end of file diff --git a/lib/typings/cv.d.ts b/lib/typings/cv.d.ts index 83460c04a..4b0bf58e9 100644 --- a/lib/typings/cv.d.ts +++ b/lib/typings/cv.d.ts @@ -19,6 +19,14 @@ export interface HistAxes { ranges: number[]; } +export function accumulate(src: Mat, dst: Mat, mask?: Mat): void; +export function accumulateAsync(src: Mat, dst: Mat, mask?: Mat): Promise; +export function accumulateProduct(src1: Mat, src2: Mat, dst: Mat, mask?: Mat): void; +export function accumulateProductAsync(src1: Mat, src2:Mat, dst: Mat, mask?: Mat): Promise; +export function accumulateSquare(src: Mat, dst: Mat, mask?: Mat): void; +export function accumulateSquareAsync(src: Mat, dst: Mat, mask?: Mat): Promise; +export function accumulateWeighted(src: Mat, dst: Mat, alpha: number, mask?: Mat): void; +export function accumulateWeightedAsync(src: Mat, dst: Mat, alpha: number, mask?: Mat): Promise; export function addWeighted(mat: Mat, alpha: number, mat2: Mat, beta: number, gamma: number, dtype?: number): Mat; export function addWeightedAsync(mat: Mat, alpha: number, mat2: Mat, beta: number, gamma: number, dtype?: number): Promise; export function applyColorMap(src: Mat, colormap: number | Mat): Mat; diff --git a/test/tests/imgproc/imgprocTests.js b/test/tests/imgproc/imgprocTests.js index d5ce58945..2a6990645 100644 --- a/test/tests/imgproc/imgprocTests.js +++ b/test/tests/imgproc/imgprocTests.js @@ -397,4 +397,186 @@ module.exports = ({ cv, utils, getTestImg }) => { } }); + describe('accumulate', () => { + const srcData = [ + [[1, 2, 3], [4, 5, 6]], + [[7, 8, 9], [10, 11, 12]] + ] + const dstData = [ + [[1, 1, 1], [1, 1, 1]], + [[1, 1, 1], [1, 1, 1]] + ] + const maskData = [ + [255, 0], + [0, 255] + ] + const expectedData = [ + [[2, 3, 4], [1, 1, 1]], + [[1, 1, 1], [11, 12, 13]] + ] + const src = new cv.Mat(srcData, cv.CV_8UC3) + let dst + const mask = new cv.Mat(maskData, cv.CV_8UC1) + + generateAPITests({ + getDut: () => cv, + methodName: 'accumulate', + beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), + getRequiredArgs: () => ([ + src, + dst, + mask + ]), + expectOutput: () => { + channelIndices = ['x', 'y', 'z'] + for (let row = 0; row < dst.rows; row++) { + for (let col = 0; col < dst.cols; col++) { + for (let channel = 0; channel < dst.channels; channel++) { + expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + } + } + } + } + }); + }); + + describe('accumulateProduct', () => { + const srcData1 = [ + [[1, 2, 3], [4, 5, 6]], + [[7, 8, 9], [10, 11, 12]] + ] + const srcData2 = [ + [[2, 2, 2], [2, 2, 2]], + [[2, 2, 2], [2, 2, 2]] + ] + const dstData = [ + [[1, 1, 1], [1, 1, 1]], + [[1, 1, 1], [1, 1, 1]] + ] + const maskData = [ + [255, 0], + [0, 255] + ] + const expectedData = [ + [[3, 5, 7], [1, 1, 1]], + [[1, 1, 1], [21, 23, 25]] + ] + + const src1 = new cv.Mat(srcData1, cv.CV_8UC3) + const src2 = new cv.Mat(srcData2, cv.CV_8UC3) + let dst + const mask = new cv.Mat(maskData, cv.CV_8UC1) + + generateAPITests({ + getDut: () => cv, + methodName: 'accumulateProduct', + beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), + getRequiredArgs: () => ([ + src1, + src2, + dst, + mask + ]), + expectOutput: () => { + channelIndices = ['x', 'y', 'z'] + for (let row = 0; row < dst.rows; row++) { + for (let col = 0; col < dst.cols; col++) { + for (let channel = 0; channel < dst.channels; channel++) { + expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + } + } + } + } + }); + }); + + describe('accumulateSquare', () => { + const srcData = [ + [[1, 2, 3], [4, 5, 6]], + [[7, 8, 9], [10, 11, 12]] + ] + const dstData = [ + [[1, 1, 1], [1, 1, 1]], + [[1, 1, 1], [1, 1, 1]] + ] + const maskData = [ + [255, 0], + [0, 255] + ] + const expectedData = [ + [[2, 5, 10], [1, 1, 1]], + [[1, 1, 1], [101, 122, 145]] + ] + + const src = new cv.Mat(srcData, cv.CV_8UC3) + let dst + const mask = new cv.Mat(maskData, cv.CV_8UC1) + + generateAPITests({ + getDut: () => cv, + methodName: 'accumulateSquare', + beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), + getRequiredArgs: () => ([ + src, + dst, + mask + ]), + expectOutput: () => { + channelIndices = ['x', 'y', 'z'] + for (let row = 0; row < dst.rows; row++) { + for (let col = 0; col < dst.cols; col++) { + for (let channel = 0; channel < dst.channels; channel++) { + expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + } + } + } + } + }); + }); + + describe('accumulateWeighted', () => { + const srcData = [ + [[1, 2, 3], [4, 5, 6]], + [[7, 8, 9], [10, 11, 12]] + ] + const dstData = [ + [[1, 1, 1], [1, 1, 1]], + [[1, 1, 1], [1, 1, 1]] + ] + const alpha = 0.7 + const maskData = [ + [255, 0], + [0, 255] + ] + const expectedData = [ + [[(1 - alpha) * 1 + alpha * 1, (1 - alpha) * 1 + alpha * 2, (1 - alpha) * 1 + alpha * 3], [1, 1, 1]], + [[1, 1, 1], [(1 - alpha) * 1 + alpha * 10, (1 - alpha) * 1 + alpha * 11, (1 - alpha) * 1 + alpha * 12]] + ] + + const src = new cv.Mat(srcData, cv.CV_8UC3) + let dst + const mask = new cv.Mat(maskData, cv.CV_8UC1) + + generateAPITests({ + getDut: () => cv, + methodName: 'accumulateWeighted', + beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), + getRequiredArgs: () => ([ + src, + dst, + alpha, + mask + ]), + expectOutput: () => { + channelIndices = ['x', 'y', 'z'] + for (let row = 0; row < dst.rows; row++) { + for (let col = 0; col < dst.cols; col++) { + for (let channel = 0; channel < dst.channels; channel++) { + expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + } + } + } + } + }); + }); }; From 852a9e36522e345849874eaf6c1236fcb82c2867 Mon Sep 17 00:00:00 2001 From: Johan Junik Jo Date: Mon, 14 Oct 2019 13:30:32 +0900 Subject: [PATCH 2/3] 1. change function to class 2. add mat class member function 3. swap function parameter --- cc/imgproc/MatImgproc.cc | 40 +++++++++++++++++ cc/imgproc/MatImgproc.h | 8 ++++ cc/imgproc/imgprocBindings.h | 69 ++++++++++++++++++++++-------- lib/typings/Mat.d.ts | 8 ++++ lib/typings/cv.d.ts | 16 +++---- test/tests/imgproc/imgprocTests.js | 56 +++++++++++++----------- 6 files changed, 148 insertions(+), 49 deletions(-) diff --git a/cc/imgproc/MatImgproc.cc b/cc/imgproc/MatImgproc.cc index 48c7a20cc..d3625b8f1 100644 --- a/cc/imgproc/MatImgproc.cc +++ b/cc/imgproc/MatImgproc.cc @@ -120,6 +120,14 @@ void MatImgproc::Init(v8::Local ctor) { Nan::SetPrototypeMethod(ctor, "gaussianBlurAsync", GaussianBlurAsync); Nan::SetPrototypeMethod(ctor, "medianBlur", MedianBlur); Nan::SetPrototypeMethod(ctor, "medianBlurAsync", MedianBlurAsync); + Nan::SetPrototypeMethod(ctor, "accumulate", Accumulate); + Nan::SetPrototypeMethod(ctor, "accumulateAsync", AccumulateAsync); + Nan::SetPrototypeMethod(ctor, "accumulateProduct", AccumulateProduct); + Nan::SetPrototypeMethod(ctor, "accumulateProductAsync", AccumulateProductAsync); + Nan::SetPrototypeMethod(ctor, "accumulateSquare", AccumulateSquare); + Nan::SetPrototypeMethod(ctor, "accumulateSquareAsync", AccumulateSquareAsync); + Nan::SetPrototypeMethod(ctor, "accumulateWeighted", AccumulateWeighted); + Nan::SetPrototypeMethod(ctor, "accumulateWeightedAsync", AccumulateWeightedAsync); }; NAN_METHOD(MatImgproc::DrawContours) { @@ -972,4 +980,36 @@ NAN_METHOD(MatImgproc::MedianBlurAsync) { Mat::asyncBinding("MedianBlur", info); } +NAN_METHOD(MatImgproc::Accumulate) { + Mat::syncBinding("Accumulate", info); +} + +NAN_METHOD(MatImgproc::AccumulateAsync) { + Mat::asyncBinding("Accumulate", info); +} + +NAN_METHOD(MatImgproc::AccumulateProduct) { + Mat::syncBinding("AccumulateProduct", info); +} + +NAN_METHOD(MatImgproc::AccumulateProductAsync) { + Mat::asyncBinding("AccumulateProduct", info); +} + +NAN_METHOD(MatImgproc::AccumulateSquare) { + Mat::syncBinding("AccumulateSquare", info); +} + +NAN_METHOD(MatImgproc::AccumulateSquareAsync) { + Mat::asyncBinding("AccumulateSquare", info); +} + +NAN_METHOD(MatImgproc::AccumulateWeighted) { + Mat::syncBinding("AccumulateWeighted", info); +} + +NAN_METHOD(MatImgproc::AccumulateWeightedAsync) { + Mat::asyncBinding("AccumulateWeighted", info); +} + #endif \ No newline at end of file diff --git a/cc/imgproc/MatImgproc.h b/cc/imgproc/MatImgproc.h index 5e8039268..729de7d17 100644 --- a/cc/imgproc/MatImgproc.h +++ b/cc/imgproc/MatImgproc.h @@ -124,6 +124,14 @@ class MatImgproc { static NAN_METHOD(GaussianBlurAsync); static NAN_METHOD(MedianBlur); static NAN_METHOD(MedianBlurAsync); + static NAN_METHOD(Accumulate); + static NAN_METHOD(AccumulateAsync); + static NAN_METHOD(AccumulateProduct); + static NAN_METHOD(AccumulateProductAsync); + static NAN_METHOD(AccumulateSquare); + static NAN_METHOD(AccumulateSquareAsync); + static NAN_METHOD(AccumulateWeighted); + static NAN_METHOD(AccumulateWeightedAsync); }; #endif \ No newline at end of file diff --git a/cc/imgproc/imgprocBindings.h b/cc/imgproc/imgprocBindings.h index 9970ed0ca..7b44929cf 100644 --- a/cc/imgproc/imgprocBindings.h +++ b/cc/imgproc/imgprocBindings.h @@ -205,58 +205,93 @@ namespace ImgprocBindings { }; }; - class Accumulate : public CvBinding { + class Accumulate : public CvClassMethodBinding { public: - void setup() { + cv::Mat dst; + + void createBinding(std::shared_ptr> self) { auto src = req(); - auto dst = req(); auto mask = opt("mask", cv::noArray().getMat()); - executeBinding = [=]() { - cv::accumulate(src->ref(), dst->ref(), mask->ref()); + auto depth = self->ref().depth(); + if (depth != CV_32F && depth != CV_64F) + throw std::runtime_error("dst must have a depth of CV_32F or CV_64F - mat depth:" + std::to_string(depth)); + cv::accumulate(src->ref(), self->ref(), mask->ref()); + dst = self->ref(); }; }; + + v8::Local getReturnValue() { + return Mat::Converter::wrap(dst); + }; }; - class AccumulateProduct : public CvBinding { + class AccumulateProduct : public CvClassMethodBinding { public: - void setup() { + cv::Mat dst; + + void createBinding(std::shared_ptr> self) { auto src1 = req(); auto src2 = req(); - auto dst = req(); auto mask = opt("mask", cv::noArray().getMat()); executeBinding = [=]() { - cv::accumulateProduct(src1->ref(), src2->ref(), dst->ref(), mask->ref()); + auto depth = self->ref().depth(); + if (depth != CV_32F && depth != CV_64F) + throw std::runtime_error("dst must have a depth of CV_32F or CV_64F - mat depth:" + std::to_string(depth)); + cv::accumulateProduct(src1->ref(), src2->ref(), self->ref(), mask->ref()); + dst = self->ref(); }; }; + + v8::Local getReturnValue() { + return Mat::Converter::wrap(dst); + }; }; - class AccumulateSquare : public CvBinding { + class AccumulateSquare : public CvClassMethodBinding { public: - void setup() { + cv::Mat dst; + + void createBinding(std::shared_ptr> self) { auto src = req(); - auto dst = req(); auto mask = opt("mask", cv::noArray().getMat()); executeBinding = [=]() { - cv::accumulateSquare(src->ref(), dst->ref(), mask->ref()); + auto depth = self->ref().depth(); + if (depth != CV_32F && depth != CV_64F) + throw std::runtime_error("dst must have a depth of CV_32F or CV_64F - mat depth:" + std::to_string(depth)); + cv::accumulateSquare(src->ref(), self->ref(), mask->ref()); + dst = self->ref(); }; }; + + v8::Local getReturnValue() { + return Mat::Converter::wrap(dst); + }; }; - class AccumulateWeighted : public CvBinding { + class AccumulateWeighted : public CvClassMethodBinding { public: - void setup() { + cv::Mat dst; + + void createBinding(std::shared_ptr> self) { auto src = req(); - auto dst = req(); auto alpha = req(); auto mask = opt("mask", cv::noArray().getMat()); executeBinding = [=]() { - cv::accumulateWeighted(src->ref(), dst->ref(), alpha->ref(), mask->ref()); + auto depth = self->ref().depth(); + if (depth != CV_32F && depth != CV_64F) + throw std::runtime_error("dst must have a depth of CV_32F or CV_64F - mat depth:" + std::to_string(depth)); + cv::accumulateWeighted(src->ref(), self->ref(), alpha->ref(), mask->ref()); + dst = self->ref(); }; }; + + v8::Local getReturnValue() { + return Mat::Converter::wrap(dst); + }; }; } diff --git a/lib/typings/Mat.d.ts b/lib/typings/Mat.d.ts index c12bc64ec..91a094724 100644 --- a/lib/typings/Mat.d.ts +++ b/lib/typings/Mat.d.ts @@ -35,6 +35,14 @@ export class Mat { constructor(data: Buffer, rows: number, cols: number, type?: number); abs(): Mat; absdiff(otherMat: Mat): Mat; + accumulate(src: Mat, mask?: Mat): Mat; + accumulateAsync(src: Mat, mask?: Mat): Promise; + accumulateProduct(src1: Mat, src2: Mat, mask?: Mat): Mat; + accumulateProductAsync(src1: Mat, src2:Mat, mask?: Mat): Promise; + accumulateSquare(src: Mat, mask?: Mat): Mat; + accumulateSquareAsync(src: Mat, mask?: Mat): Promise; + accumulateWeighted(src: Mat, alpha: number, mask?: Mat): Mat; + accumulateWeightedAsync(src: Mat, alpha: number, mask?: Mat): Promise; adaptiveThreshold(maxVal: number, adaptiveMethod: number, thresholdType: number, blockSize: number, C: number): Mat; adaptiveThresholdAsync(maxVal: number, adaptiveMethod: number, thresholdType: number, blockSize: number, C: number): Promise; add(otherMat: Mat): Mat; diff --git a/lib/typings/cv.d.ts b/lib/typings/cv.d.ts index 4b0bf58e9..38c5ad171 100644 --- a/lib/typings/cv.d.ts +++ b/lib/typings/cv.d.ts @@ -19,14 +19,14 @@ export interface HistAxes { ranges: number[]; } -export function accumulate(src: Mat, dst: Mat, mask?: Mat): void; -export function accumulateAsync(src: Mat, dst: Mat, mask?: Mat): Promise; -export function accumulateProduct(src1: Mat, src2: Mat, dst: Mat, mask?: Mat): void; -export function accumulateProductAsync(src1: Mat, src2:Mat, dst: Mat, mask?: Mat): Promise; -export function accumulateSquare(src: Mat, dst: Mat, mask?: Mat): void; -export function accumulateSquareAsync(src: Mat, dst: Mat, mask?: Mat): Promise; -export function accumulateWeighted(src: Mat, dst: Mat, alpha: number, mask?: Mat): void; -export function accumulateWeightedAsync(src: Mat, dst: Mat, alpha: number, mask?: Mat): Promise; +export function accumulate(dst: Mat, src: Mat, mask?: Mat): Mat; +export function accumulateAsync(dst: Mat, src: Mat, mask?: Mat): Promise; +export function accumulateProduct(dst: Mat, src1: Mat, src2: Mat, mask?: Mat): Mat; +export function accumulateProductAsync(dst: Mat, src1: Mat, src2:Mat, mask?: Mat): Promise; +export function accumulateSquare(dst: Mat, src: Mat, mask?: Mat): Mat; +export function accumulateSquareAsync(dst: Mat, src: Mat, mask?: Mat): Promise; +export function accumulateWeighted(dst: Mat, src: Mat, alpha: number, mask?: Mat): Mat; +export function accumulateWeightedAsync(dst: Mat, src: Mat, alpha: number, mask?: Mat): Promise; export function addWeighted(mat: Mat, alpha: number, mat2: Mat, beta: number, gamma: number, dtype?: number): Mat; export function addWeightedAsync(mat: Mat, alpha: number, mat2: Mat, beta: number, gamma: number, dtype?: number): Promise; export function applyColorMap(src: Mat, colormap: number | Mat): Mat; diff --git a/test/tests/imgproc/imgprocTests.js b/test/tests/imgproc/imgprocTests.js index 2a6990645..bac4988ed 100644 --- a/test/tests/imgproc/imgprocTests.js +++ b/test/tests/imgproc/imgprocTests.js @@ -421,18 +421,20 @@ module.exports = ({ cv, utils, getTestImg }) => { generateAPITests({ getDut: () => cv, methodName: 'accumulate', + classNameSpace: 'Mat', + methodNameSpace: 'Imgproc', beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), getRequiredArgs: () => ([ - src, dst, + src, mask ]), - expectOutput: () => { + expectOutput: res => { channelIndices = ['x', 'y', 'z'] - for (let row = 0; row < dst.rows; row++) { - for (let col = 0; col < dst.cols; col++) { - for (let channel = 0; channel < dst.channels; channel++) { - expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + for (let row = 0; row < res.rows; row++) { + for (let col = 0; col < res.cols; col++) { + for (let channel = 0; channel < res.channels; channel++) { + expect(res.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); } } } @@ -470,19 +472,21 @@ module.exports = ({ cv, utils, getTestImg }) => { generateAPITests({ getDut: () => cv, methodName: 'accumulateProduct', + classNameSpace: 'Mat', + methodNameSpace: 'Imgproc', beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), getRequiredArgs: () => ([ + dst, src1, src2, - dst, mask ]), - expectOutput: () => { + expectOutput: res => { channelIndices = ['x', 'y', 'z'] - for (let row = 0; row < dst.rows; row++) { - for (let col = 0; col < dst.cols; col++) { - for (let channel = 0; channel < dst.channels; channel++) { - expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + for (let row = 0; row < res.rows; row++) { + for (let col = 0; col < res.cols; col++) { + for (let channel = 0; channel < res.channels; channel++) { + expect(res.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); } } } @@ -515,18 +519,20 @@ module.exports = ({ cv, utils, getTestImg }) => { generateAPITests({ getDut: () => cv, methodName: 'accumulateSquare', + classNameSpace: 'Mat', + methodNameSpace: 'Imgproc', beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), getRequiredArgs: () => ([ - src, dst, + src, mask ]), - expectOutput: () => { + expectOutput: res => { channelIndices = ['x', 'y', 'z'] - for (let row = 0; row < dst.rows; row++) { - for (let col = 0; col < dst.cols; col++) { - for (let channel = 0; channel < dst.channels; channel++) { - expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + for (let row = 0; row < res.rows; row++) { + for (let col = 0; col < res.cols; col++) { + for (let channel = 0; channel < res.channels; channel++) { + expect(res.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); } } } @@ -560,19 +566,21 @@ module.exports = ({ cv, utils, getTestImg }) => { generateAPITests({ getDut: () => cv, methodName: 'accumulateWeighted', + classNameSpace: 'Mat', + methodNameSpace: 'Imgproc', beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), getRequiredArgs: () => ([ - src, dst, + src, alpha, mask ]), - expectOutput: () => { + expectOutput: res => { channelIndices = ['x', 'y', 'z'] - for (let row = 0; row < dst.rows; row++) { - for (let col = 0; col < dst.cols; col++) { - for (let channel = 0; channel < dst.channels; channel++) { - expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + for (let row = 0; row < res.rows; row++) { + for (let col = 0; col < res.cols; col++) { + for (let channel = 0; channel < res.channels; channel++) { + expect(res.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); } } } From 0284d299996191f056a5319e0803b0115483502c Mon Sep 17 00:00:00 2001 From: Johan Junik Jo Date: Fri, 18 Oct 2019 18:25:35 +0900 Subject: [PATCH 3/3] 1. Mat class method binding was removed and matched with the orignal opencv signature. 2. Added a unit test for situations where dst depth exceptions occur. --- cc/imgproc/MatImgproc.cc | 40 ---------------- cc/imgproc/MatImgproc.h | 8 ---- cc/imgproc/imgprocBindings.h | 74 ++++++++++-------------------- lib/typings/cv.d.ts | 16 +++---- test/tests/imgproc/imgprocTests.js | 72 ++++++++++++++++++----------- 5 files changed, 77 insertions(+), 133 deletions(-) diff --git a/cc/imgproc/MatImgproc.cc b/cc/imgproc/MatImgproc.cc index d3625b8f1..48c7a20cc 100644 --- a/cc/imgproc/MatImgproc.cc +++ b/cc/imgproc/MatImgproc.cc @@ -120,14 +120,6 @@ void MatImgproc::Init(v8::Local ctor) { Nan::SetPrototypeMethod(ctor, "gaussianBlurAsync", GaussianBlurAsync); Nan::SetPrototypeMethod(ctor, "medianBlur", MedianBlur); Nan::SetPrototypeMethod(ctor, "medianBlurAsync", MedianBlurAsync); - Nan::SetPrototypeMethod(ctor, "accumulate", Accumulate); - Nan::SetPrototypeMethod(ctor, "accumulateAsync", AccumulateAsync); - Nan::SetPrototypeMethod(ctor, "accumulateProduct", AccumulateProduct); - Nan::SetPrototypeMethod(ctor, "accumulateProductAsync", AccumulateProductAsync); - Nan::SetPrototypeMethod(ctor, "accumulateSquare", AccumulateSquare); - Nan::SetPrototypeMethod(ctor, "accumulateSquareAsync", AccumulateSquareAsync); - Nan::SetPrototypeMethod(ctor, "accumulateWeighted", AccumulateWeighted); - Nan::SetPrototypeMethod(ctor, "accumulateWeightedAsync", AccumulateWeightedAsync); }; NAN_METHOD(MatImgproc::DrawContours) { @@ -980,36 +972,4 @@ NAN_METHOD(MatImgproc::MedianBlurAsync) { Mat::asyncBinding("MedianBlur", info); } -NAN_METHOD(MatImgproc::Accumulate) { - Mat::syncBinding("Accumulate", info); -} - -NAN_METHOD(MatImgproc::AccumulateAsync) { - Mat::asyncBinding("Accumulate", info); -} - -NAN_METHOD(MatImgproc::AccumulateProduct) { - Mat::syncBinding("AccumulateProduct", info); -} - -NAN_METHOD(MatImgproc::AccumulateProductAsync) { - Mat::asyncBinding("AccumulateProduct", info); -} - -NAN_METHOD(MatImgproc::AccumulateSquare) { - Mat::syncBinding("AccumulateSquare", info); -} - -NAN_METHOD(MatImgproc::AccumulateSquareAsync) { - Mat::asyncBinding("AccumulateSquare", info); -} - -NAN_METHOD(MatImgproc::AccumulateWeighted) { - Mat::syncBinding("AccumulateWeighted", info); -} - -NAN_METHOD(MatImgproc::AccumulateWeightedAsync) { - Mat::asyncBinding("AccumulateWeighted", info); -} - #endif \ No newline at end of file diff --git a/cc/imgproc/MatImgproc.h b/cc/imgproc/MatImgproc.h index 729de7d17..5e8039268 100644 --- a/cc/imgproc/MatImgproc.h +++ b/cc/imgproc/MatImgproc.h @@ -124,14 +124,6 @@ class MatImgproc { static NAN_METHOD(GaussianBlurAsync); static NAN_METHOD(MedianBlur); static NAN_METHOD(MedianBlurAsync); - static NAN_METHOD(Accumulate); - static NAN_METHOD(AccumulateAsync); - static NAN_METHOD(AccumulateProduct); - static NAN_METHOD(AccumulateProductAsync); - static NAN_METHOD(AccumulateSquare); - static NAN_METHOD(AccumulateSquareAsync); - static NAN_METHOD(AccumulateWeighted); - static NAN_METHOD(AccumulateWeightedAsync); }; #endif \ No newline at end of file diff --git a/cc/imgproc/imgprocBindings.h b/cc/imgproc/imgprocBindings.h index 7b44929cf..5d761c7f5 100644 --- a/cc/imgproc/imgprocBindings.h +++ b/cc/imgproc/imgprocBindings.h @@ -205,93 +205,69 @@ namespace ImgprocBindings { }; }; - class Accumulate : public CvClassMethodBinding { - public: - cv::Mat dst; - - void createBinding(std::shared_ptr> self) { + class Accumulate : public CvBinding { + public: + void setup() { auto src = req(); + auto dst = req(); auto mask = opt("mask", cv::noArray().getMat()); executeBinding = [=]() { - auto depth = self->ref().depth(); + auto depth = dst->ref().depth(); if (depth != CV_32F && depth != CV_64F) - throw std::runtime_error("dst must have a depth of CV_32F or CV_64F - mat depth:" + std::to_string(depth)); - cv::accumulate(src->ref(), self->ref(), mask->ref()); - dst = self->ref(); + throw std::runtime_error("dst must has a depth of CV_32F or CV_64F"); + cv::accumulate(src->ref(), dst->ref(), mask->ref()); }; }; - - v8::Local getReturnValue() { - return Mat::Converter::wrap(dst); - }; }; - class AccumulateProduct : public CvClassMethodBinding { + class AccumulateProduct : public CvBinding { public: - cv::Mat dst; - - void createBinding(std::shared_ptr> self) { + void setup() { auto src1 = req(); auto src2 = req(); + auto dst = req(); auto mask = opt("mask", cv::noArray().getMat()); executeBinding = [=]() { - auto depth = self->ref().depth(); + auto depth = dst->ref().depth(); if (depth != CV_32F && depth != CV_64F) - throw std::runtime_error("dst must have a depth of CV_32F or CV_64F - mat depth:" + std::to_string(depth)); - cv::accumulateProduct(src1->ref(), src2->ref(), self->ref(), mask->ref()); - dst = self->ref(); + throw std::runtime_error("dst must has a depth of CV_32F or CV_64F"); + cv::accumulateProduct(src1->ref(), src2->ref(), dst->ref(), mask->ref()); }; }; - - v8::Local getReturnValue() { - return Mat::Converter::wrap(dst); - }; }; - class AccumulateSquare : public CvClassMethodBinding { + class AccumulateSquare : public CvBinding { public: - cv::Mat dst; - - void createBinding(std::shared_ptr> self) { + void setup() { auto src = req(); + auto dst = req(); auto mask = opt("mask", cv::noArray().getMat()); executeBinding = [=]() { - auto depth = self->ref().depth(); + auto depth = dst->ref().depth(); if (depth != CV_32F && depth != CV_64F) - throw std::runtime_error("dst must have a depth of CV_32F or CV_64F - mat depth:" + std::to_string(depth)); - cv::accumulateSquare(src->ref(), self->ref(), mask->ref()); - dst = self->ref(); + throw std::runtime_error("dst must has a depth of CV_32F or CV_64F"); + cv::accumulateSquare(src->ref(), dst->ref(), mask->ref()); }; }; - - v8::Local getReturnValue() { - return Mat::Converter::wrap(dst); - }; }; - class AccumulateWeighted : public CvClassMethodBinding { + class AccumulateWeighted : public CvBinding { public: - cv::Mat dst; - - void createBinding(std::shared_ptr> self) { + void setup() { auto src = req(); + auto dst = req(); auto alpha = req(); auto mask = opt("mask", cv::noArray().getMat()); executeBinding = [=]() { - auto depth = self->ref().depth(); + auto depth = dst->ref().depth(); if (depth != CV_32F && depth != CV_64F) - throw std::runtime_error("dst must have a depth of CV_32F or CV_64F - mat depth:" + std::to_string(depth)); - cv::accumulateWeighted(src->ref(), self->ref(), alpha->ref(), mask->ref()); - dst = self->ref(); + throw std::runtime_error("dst must has a depth of CV_32F or CV_64F"); + cv::accumulateWeighted(src->ref(), dst->ref(), alpha->ref(), mask->ref()); }; }; - - v8::Local getReturnValue() { - return Mat::Converter::wrap(dst); - }; }; } diff --git a/lib/typings/cv.d.ts b/lib/typings/cv.d.ts index 38c5ad171..a308eb0cd 100644 --- a/lib/typings/cv.d.ts +++ b/lib/typings/cv.d.ts @@ -19,14 +19,14 @@ export interface HistAxes { ranges: number[]; } -export function accumulate(dst: Mat, src: Mat, mask?: Mat): Mat; -export function accumulateAsync(dst: Mat, src: Mat, mask?: Mat): Promise; -export function accumulateProduct(dst: Mat, src1: Mat, src2: Mat, mask?: Mat): Mat; -export function accumulateProductAsync(dst: Mat, src1: Mat, src2:Mat, mask?: Mat): Promise; -export function accumulateSquare(dst: Mat, src: Mat, mask?: Mat): Mat; -export function accumulateSquareAsync(dst: Mat, src: Mat, mask?: Mat): Promise; -export function accumulateWeighted(dst: Mat, src: Mat, alpha: number, mask?: Mat): Mat; -export function accumulateWeightedAsync(dst: Mat, src: Mat, alpha: number, mask?: Mat): Promise; +export function accumulate(src: Mat, dst: Mat, mask?: Mat): void; +export function accumulateAsync(src: Mat, dst: Mat, mask?: Mat): Promise; +export function accumulateProduct(src1: Mat, src2: Mat, dst: Mat, mask?: Mat): void; +export function accumulateProductAsync(src1: Mat, src2: Mat, dst:Mat, mask?: Mat): Promise; +export function accumulateSquare(src: Mat, dst: Mat, mask?: Mat): void; +export function accumulateSquareAsync(src: Mat, dst: Mat, mask?: Mat): Promise; +export function accumulateWeighted(src: Mat, dst: Mat, alpha: number, mask?: Mat): void; +export function accumulateWeightedAsync(src: Mat, dst: Mat, alpha: number, mask?: Mat): Promise; export function addWeighted(mat: Mat, alpha: number, mat2: Mat, beta: number, gamma: number, dtype?: number): Mat; export function addWeightedAsync(mat: Mat, alpha: number, mat2: Mat, beta: number, gamma: number, dtype?: number): Promise; export function applyColorMap(src: Mat, colormap: number | Mat): Mat; diff --git a/test/tests/imgproc/imgprocTests.js b/test/tests/imgproc/imgprocTests.js index bac4988ed..a8e03e28c 100644 --- a/test/tests/imgproc/imgprocTests.js +++ b/test/tests/imgproc/imgprocTests.js @@ -415,26 +415,30 @@ module.exports = ({ cv, utils, getTestImg }) => { [[1, 1, 1], [11, 12, 13]] ] const src = new cv.Mat(srcData, cv.CV_8UC3) + const dstDepth8 = new cv.Mat(dstData, cv.CV_8UC3) let dst const mask = new cv.Mat(maskData, cv.CV_8UC1) + + it('should throw if dst has not a depth of CV_32F or CV_64F', () => { + expect(() => cv.accumulate(src, dstDepth8)).to.throw('Imgproc::Accumulate - dst must has a depth of CV_32F or CV_64F'); + }); generateAPITests({ getDut: () => cv, methodName: 'accumulate', - classNameSpace: 'Mat', methodNameSpace: 'Imgproc', beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), getRequiredArgs: () => ([ - dst, src, + dst, mask ]), - expectOutput: res => { + expectOutput: () => { channelIndices = ['x', 'y', 'z'] - for (let row = 0; row < res.rows; row++) { - for (let col = 0; col < res.cols; col++) { - for (let channel = 0; channel < res.channels; channel++) { - expect(res.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + for (let row = 0; row < dst.rows; row++) { + for (let col = 0; col < dst.cols; col++) { + for (let channel = 0; channel < dst.channels; channel++) { + expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); } } } @@ -467,26 +471,30 @@ module.exports = ({ cv, utils, getTestImg }) => { const src1 = new cv.Mat(srcData1, cv.CV_8UC3) const src2 = new cv.Mat(srcData2, cv.CV_8UC3) let dst + const dstDepth8 = new cv.Mat(dstData, cv.CV_8UC3) const mask = new cv.Mat(maskData, cv.CV_8UC1) + it('should throw if dst has not a depth of CV_32F or CV_64F', () => { + expect(() => cv.accumulateProduct(src1, src2, dstDepth8)).to.throw('Imgproc::AccumulateProduct - dst must has a depth of CV_32F or CV_64F'); + }); + generateAPITests({ getDut: () => cv, methodName: 'accumulateProduct', - classNameSpace: 'Mat', methodNameSpace: 'Imgproc', beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), getRequiredArgs: () => ([ - dst, src1, src2, + dst, mask ]), - expectOutput: res => { + expectOutput: () => { channelIndices = ['x', 'y', 'z'] - for (let row = 0; row < res.rows; row++) { - for (let col = 0; col < res.cols; col++) { - for (let channel = 0; channel < res.channels; channel++) { - expect(res.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + for (let row = 0; row < dst.rows; row++) { + for (let col = 0; col < dst.cols; col++) { + for (let channel = 0; channel < dst.channels; channel++) { + expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); } } } @@ -514,25 +522,29 @@ module.exports = ({ cv, utils, getTestImg }) => { const src = new cv.Mat(srcData, cv.CV_8UC3) let dst + const dstDepth8 = new cv.Mat(dstData, cv.CV_8UC3) const mask = new cv.Mat(maskData, cv.CV_8UC1) + it('should throw if dst has not a depth of CV_32F or CV_64F', () => { + expect(() => cv.accumulateSquare(src, dstDepth8)).to.throw('Imgproc::AccumulateSquare - dst must has a depth of CV_32F or CV_64F'); + }); + generateAPITests({ getDut: () => cv, methodName: 'accumulateSquare', - classNameSpace: 'Mat', methodNameSpace: 'Imgproc', beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), getRequiredArgs: () => ([ - dst, src, + dst, mask ]), - expectOutput: res => { + expectOutput: () => { channelIndices = ['x', 'y', 'z'] - for (let row = 0; row < res.rows; row++) { - for (let col = 0; col < res.cols; col++) { - for (let channel = 0; channel < res.channels; channel++) { - expect(res.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + for (let row = 0; row < dst.rows; row++) { + for (let col = 0; col < dst.cols; col++) { + for (let channel = 0; channel < dst.channels; channel++) { + expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); } } } @@ -561,26 +573,30 @@ module.exports = ({ cv, utils, getTestImg }) => { const src = new cv.Mat(srcData, cv.CV_8UC3) let dst + const dstDepth8 = new cv.Mat(dstData, cv.CV_8UC3) const mask = new cv.Mat(maskData, cv.CV_8UC1) + it('should throw if dst has not a depth of CV_32F or CV_64F', () => { + expect(() => cv.accumulateWeighted(src, dstDepth8, alpha)).to.throw('Imgproc::AccumulateWeighted - dst must has a depth of CV_32F or CV_64F'); + }); + generateAPITests({ getDut: () => cv, methodName: 'accumulateWeighted', - classNameSpace: 'Mat', methodNameSpace: 'Imgproc', beforeHook: () => dst = new cv.Mat(dstData, cv.CV_32FC3), getRequiredArgs: () => ([ - dst, src, + dst, alpha, mask ]), - expectOutput: res => { + expectOutput: () => { channelIndices = ['x', 'y', 'z'] - for (let row = 0; row < res.rows; row++) { - for (let col = 0; col < res.cols; col++) { - for (let channel = 0; channel < res.channels; channel++) { - expect(res.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); + for (let row = 0; row < dst.rows; row++) { + for (let col = 0; col < dst.cols; col++) { + for (let channel = 0; channel < dst.channels; channel++) { + expect(dst.at(row, col)[channelIndices[channel]]).to.be.closeTo(expectedData[row][col][channel], 1e-5); } } }