Bindings for cv.min and cv.max
Closed this issue · 18 comments
Hello,
Is there a possibility to implement cv.min() and cv.max() that compare 2 img-arrays and return an img containing the minimum or maximum values in all pixels, respectively?
We rely heavily on these functions for a specific development. If there is another alternative to using them that would be of great help as well.
Thank you for this wonderful project.
Docs:
https://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html#min
https://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html#max
Six thumps up in 22 minutes?
That is easy to implement, but I have to find a new job first... and deal with 2 wheelchair kids for 2 more weeks.
9 thumps up after 26 minutes...
you should also start the project 😃
Six thumps up in 22 minutes?
Its my team 😄
That is easy to implement, but I have to find a new job first... and deal with 2 wheelchair kids for 2 more weeks.
No problem, we are very patient and will help you with whatever you need.
LOL
so go shooting star on the project, and I think I can find time to add this simple mapping.
I had just add:
min(src1: Mat, src2: Mat, dst: Mat): Mat;
minAsync(src1: Mat, src2: Mat, dst: Mat): Promise<Mat>;
max(src1: Mat, src2: Mat, dst?: Mat): Mat;
maxAsync(src1: Mat, src2: Mat, dst?: Mat): Promise<Mat>;
can you provide me with a test code to test my mapping ?
for the moment dst
is mandatory, I will make it optional later.
that should be good:
import { expect } from 'chai';
import cv from '@u4/opencv4nodejs';
describe('static Min/Max methods added on 2023-03-03', () => {
const mat1 = new cv.Mat([
[10, 20, 30],
[40, 50, 60],
], cv.CV_8U);
const mat2 = new cv.Mat([
[1, 22, 3],
[4, 55, 66],
], cv.CV_8U);
it('max', () => {
const dest = new cv.Mat([
[0, 0, 0],
[0, 0, 0],
], cv.CV_8U);
const expected = new cv.Mat([
[10, 22, 30],
[40, 55, 66],
], cv.CV_8U);
const dest2 = cv.max(mat1, mat2, dest);
expect(dest2).to.be.deep.equal(expected);
});
it('min', () => {
const dest = new cv.Mat([
[0, 0, 0],
[0, 0, 0],
], cv.CV_8U);
const expected = new cv.Mat([
[1, 20, 3],
[4, 50, 60],
], cv.CV_8U);
const dest2 = cv.min(mat1, mat2, dest);
expect(dest2).to.be.deep.equal(expected);
});
});
static Mat methods 2023-03-03
✔ max
✔ min
is my test correct ?
that should be good:
describe('static Mat methods 2023-03-03', () => { it('max', () => { const mat1 = new cv.Mat([ [10, 20, 30], [40, 50, 60], ], cv.CV_8U); const mat2 = new cv.Mat([ [1, 22, 3], [4, 55, 66], ], cv.CV_8U); const dest = new cv.Mat([ [0, 0, 0], [0, 0, 0], ], cv.CV_8U); const expected = new cv.Mat([ [10, 22, 30], [40, 55, 66], ], cv.CV_8U); const dest2 = cv.max(mat1, mat2, dest); expect(dest2).to.be.deep.equal(expected); }); });
Your example is great.
The code I used had to create a javascript function with a loop and Mat.at() comparisons, which had a huge performance loss.
while (true) {
tmp = marker.copy();
marker = marker.dilate(kernel);
marker = min(thresh, marker);
difference = marker.sub(tmp);
if (difference.countNonZero() <= 0) break;
}
I think of the following alternatives what works best for you.
describe('static Mat methods 2023-03-03', () => {
it('max', () => {
const mat1 = new cv.Mat([
[10, 20, 30],
[40, 50, 60],
], cv.CV_8U);
const mat2 = new cv.Mat([
[1, 22, 3],
[4, 55, 66],
], cv.CV_8U);
const dest = new cv.Mat([
[0, 0, 0],
[0, 0, 0],
], cv.CV_8U);
const expected = new cv.Mat([
[10, 22, 30],
[40, 55, 66],
], cv.CV_8U);
const dest2 = cv.max(mat1, mat2 /* , (dest: cv.Mat || undefined) */);
expect(dest2).to.be.deep.equal(expected);
cv.max(mat1, mat2, dest);
expect(dest).to.be.deep.equal(expected);
const dest3 = mat1.max(mat2);
expect(dest3).to.be.deep.equal(expected);
});
});
static Mat methods 2023-03-03 ✔ max ✔ min
is my test correct ?
Yes. It is possible in this way as well
const mat = new cv.Mat([
[15, 222, 101],
[27, 245, 66],
], cv.CV_8U);
const matMaxByNumber = cv.max(mat, 100);
// matMaxByNumber
[
[100, 222, 101],
[100, 245, 100],
]
const matMinByNumber = cv.min(mat, 100);
// matMinByNumber
[
[15, 100, 100],
[27, 100, 66],
]
This one will not work yet. but that the next step
I need to move to another project,
for now, I can publish a version with the following interface:
// experimental, need improvements / rewrite
export function min(src1: Mat, src2: Mat, dst: Mat): Mat;
export function minAsync(src1: Mat, src2: Mat, dst: Mat): Promise<Mat>;
export function max(src1: Mat, src2: Mat, dst: Mat): Mat;
export function maxAsync(src1: Mat, src2: Mat, dst: Mat): Promise<Mat>;
Errors are currently thrown as strings, I need to fix that too.
That would be perfect. My knowledge in C++ and Node addons is limited, otherwise I would help you with pull requests to further evolve your project. Sorry for taking up your time.
My C++ knowledge is outdated, I stop C/ C++ in 2004 ... so ... you may perform as well as I 😺
So I publish it as Version 6.5.0
Can you try and bench the 6.5.0?
In my scenario it worked like a charm.
while (true) {
tmp = marker.copy();
marker = marker.dilate(kernel);
marker = cv.min(thresh, marker);
difference = marker.sub(tmp);
if (difference.countNonZero() <= 0) break;
}
This is the test case
describe('static Mat methods 2023-03-10', () => {
it('(max) with optional dest', () => {
const mat1 = new cv.Mat([
[10, 20, 30],
[40, 50, 60],
], cv.CV_8U);
const mat2 = new cv.Mat([
[1, 22, 3],
[4, 55, 66],
], cv.CV_8U);
const expectedArray = [
[10, 22, 30],
[40, 55, 66],
];
const arDest2 = cv.max(mat1, mat2).getDataAsArray(); // toArray
expect(arDest2).to.be.deep.equal(expectedArray);
});
it('(max) with dest', () => {
const mat1 = new cv.Mat([
[10, 20, 30],
[40, 50, 60],
], cv.CV_8U);
const mat2 = new cv.Mat([
[1, 22, 3],
[4, 55, 66],
], cv.CV_8U);
const dest = new cv.Mat([
[0, 0, 0],
[0, 0, 0],
], cv.CV_8U);
const expectedArray = [
[10, 22, 30],
[40, 55, 66],
];
cv.max(mat1, mat2, dest);
const arDest = dest.getDataAsArray();
expect(arDest).to.be.deep.equal(expectedArray);
});
it('(min) with optional dest', () => {
const mat1 = new cv.Mat([
[10, 20, 30],
[40, 50, 60],
], cv.CV_8U);
const mat2 = new cv.Mat([
[1, 22, 3],
[4, 55, 66],
], cv.CV_8U);
const expectedArray = [
[1, 20, 3],
[4, 50, 60],
];
const arDest2 = cv.min(mat1, mat2).getDataAsArray(); // toArray
expect(arDest2).to.be.deep.equal(expectedArray);
});
it('(min) with dest', () => {
const mat1 = new cv.Mat([
[10, 20, 30],
[40, 50, 60],
], cv.CV_8U);
const mat2 = new cv.Mat([
[1, 22, 3],
[4, 55, 66],
], cv.CV_8U);
const dest = new cv.Mat([
[0, 0, 0],
[0, 0, 0],
], cv.CV_8U);
const expectedArray = [
[1, 20, 3],
[4, 50, 60],
];
cv.min(mat1, mat2, dest);
const arDest = dest.getDataAsArray();
expect(arDest).to.be.deep.equal(expectedArray);
});
});
Output
static Mat methods 2023-03-10
✔ (max) with optional dest
1) (max) with dest
✔ (min) with optional dest
2) (min) with dest
2 passing (13ms)
2 failing
1) static Mat methods 2023-03-10
(max) with dest:
AssertionError: expected [ [ +0, +0, +0 ], [ +0, +0, +0 ] ] to deeply equal [ [ 10, 22, 30 ], [ 40, 55, 66 ] ]
+ expected - actual
[
[
- 0
- 0
- 0
+ 10
+ 22
+ 30
]
[
- 0
- 0
- 0
+ 40
+ 55
+ 66
]
]
at Context.<anonymous> (test.test.js:50:31)
at processImmediate (node:internal/timers:466:21)
2) static Mat methods 2023-03-10
(min) with dest:
AssertionError: expected [ [ +0, +0, +0 ], [ +0, +0, +0 ] ] to deeply equal [ [ 1, 20, 3 ], [ 4, 50, 60 ] ]
+ expected - actual
[
[
- 0
- 0
- 0
+ 1
+ 20
+ 3
]
[
- 0
- 0
- 0
+ 4
+ 50
+ 60
]
]
at Context.<anonymous> (test.test.js:97:31)
at processImmediate (node:internal/timers:466:21)
that works ?
marker = cv.min(thresh, marker);
The 3rd dest
parameter is currently mandatory.
that should not work.
Use it as you can, for now, open a PR if you want some more change I used to merge them within the week, or the day.
that works ?
marker = cv.min(thresh, marker);
The 3rd
dest
parameter is currently mandatory.
that should not work.Use it as you can, for now, open a PR if you want some more change I used to merge them within the week, or the day.
yes it worked and i believe that changes will not be necessary. Thanks @UrielCh
so I close the issue for now