Skip to content

Commit

Permalink
feat: added match template all
Browse files Browse the repository at this point in the history
  • Loading branch information
luckyyyyy committed Feb 3, 2025
1 parent ee90acb commit e5e20a3
Show file tree
Hide file tree
Showing 11 changed files with 334 additions and 39 deletions.
Binary file added demo/20250123-112630.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demo/20250123-112635.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 20 additions & 11 deletions demo/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ function createWorker() {
}

async function main() {
const full = await fs.readFile('./demo/full.jpg');
const image = await fs.readFile('./demo/1.jpg');
const full = await fs.readFile('./demo/20250123-112635.png');
const image = await fs.readFile('./demo/20250123-112630.png');
try {
const a = cv.imdecode(Buffer.from('hello world'));
} catch (error) {
Expand All @@ -28,20 +28,29 @@ async function main() {
cv.imreadAsync('./demo/1.jpg'),
]);


const matched = await image1.matchTemplateAsync(image2, cv.TM_CCOEFF_NORMED);
const minMax = await matched.minMaxLocAsync();
console.time('matchTemplateAllAsync')
const result1 = await image1.matchTemplateAllAsync(image2, cv.TM_CCOEFF_NORMED, 0.8, 0.1);
console.log(result1)
const result = await image3.matchTemplateAllAsync(image4, cv.TM_CCOEFF_NORMED, 0.8, 0.1);
console.log(result)
console.timeEnd('matchTemplateAllAsync')
// const matched2 = await image3.matchTemplateAsync(image4, cv.TM_CCOEFF_NORMED);
// const minMax2 = await matched2.minMaxLocAsync();
console.log(image1.cols, image3.rows, image2.data, minMax)
// console.log(minMax)
const minMax2 = await matched.minMaxLocAsync();
console.log(minMax2)


// console.log(minMax.maxVal * 100);
console.log(image2.size)
matched.release();
// matched2.release();
image1.release();
image2.release();
image3.release();
image4.release();
// console.log(image2.size)
// matched.release();
// // matched2.release();
// image1.release();
// image2.release();
// image3.release();
// image4.release();
// console.log(1)
// console.log(image4)
// const b = cv.imread('./full.jpg');
Expand Down
25 changes: 21 additions & 4 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const IMREAD_IGNORE_ORIENTATION: number
export declare function getTickFrequency(): number
export declare function getBuildInformation(): string
export declare function getTickCount(): number
export declare function imencode(ext: string, img: JSMat): Buffer
export declare function imencodeCallback(ext: string, mat: JSMat, callback: (...args: any[]) => any): void
export declare function imread(path: string, flags?: number | undefined | null): JSMat
export declare function imreadCallback(path: string, callback: (...args: any[]) => any): void
export declare function imdecode(buffer: Buffer): JSMat
Expand All @@ -33,13 +35,21 @@ export interface Size {
width: number
height: number
}
export interface Point {
x: number
y: number
}
export interface Rect {
x: number
y: number
width: number
height: number
}
export interface MinMaxResult {
minVal: number
maxVal: number
minX: number
minY: number
maxX: number
maxY: number
minLoc: Point
maxLoc: Point
}
export type JSMat = Mat
export declare class Mat {
Expand All @@ -50,5 +60,12 @@ export declare class Mat {
get data(): Buffer
matchTemplateCallback(template: Mat, method: number, callback: (...args: any[]) => any): void
minMaxLocCallback(callback: (...args: any[]) => any): void
thresholdCallback(thresh: number, maxval: number, typ: number, callback: (...args: any[]) => any): void
matchTemplateAllCallback(template: Mat, method: number, score: number, nmsThreshold: number, callback: (...args: any[]) => any): void
release(): void
}
export type DNN = Dnn
export declare class Dnn {
constructor()
nmsBoxes(bboxes: Array<Rect>, scores: Array<number>, scoreThreshold: number, nmsThreshold: number, callback: (...args: any[]) => any): void
}
28 changes: 23 additions & 5 deletions main.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,21 @@ export interface Size {
width: number
height: number
}
export interface Point {
x: number
y: number
}
export interface MinMaxResult {
minVal: number
maxVal: number
minX: number
minY: number
maxX: number
maxY: number
minLoc: Point
maxLoc: Point
}
export interface Rect {
x: number
y: number
width: number
height: number
}
export declare function getTickFrequency(): number
export declare function getBuildInformation(): string
Expand All @@ -24,6 +32,9 @@ export declare function imreadAsync(path: string): Promise<Mat>
export declare function imdecode(buffer: Buffer): Mat
export declare function imdecodeCallback(buffer: Buffer, callback: (...args: any[]) => any): void
export declare function imdecodeAsync(buffer: Buffer): Promise<Mat>
export declare function imencode(ext: string, mat: JSMat): Buffer
export declare function imencodeCallback(ext: string, mat: JSMat, callback: (...args: any[]) => any): void
export declare function imencodeAsync(ext: string, mat: JSMat): Promise<Buffer>
export const TM_SQDIFF: number
export const TM_SQDIFF_NORMED: number
export const TM_CCORR: number
Expand All @@ -50,9 +61,16 @@ export declare class Mat {
get cols(): number
get size(): Size
get data(): Buffer
matchTemplateAllCallback(template: Mat, method: number, score: number, nmsThreshold: number, callback: (...args: any[]) => any): void
matchTemplateAllAsync(template: Mat, method: number, score: number, nmsThreshold: number): Promise<Array<Rect>>
matchTemplateCallback(template: Mat, method: number, callback: (...args: any[]) => any): void
matchTemplateAsync(template: Mat, method: number): Promise<MinMaxResult>
matchTemplateAsync(template: Mat, method: number): Promise<Mat>
minMaxLocCallback(callback: (...args: any[]) => any): void
minMaxLocAsync(): Promise<MinMaxResult>
release(): void
}
export type DNN = Dnn
export declare class Dnn {
constructor()
nmsBoxes(bboxes: Array<Rect>, scores: Array<number>, scoreThreshold: number, nmsThreshold: number, callback: (...args: any[]) => any): void
}
4 changes: 4 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ const { promisify } = require('util');

const imdecodeAsync = promisify(cv.imdecodeCallback);
const imreadAsync = promisify(cv.imreadCallback);
const imencodeAsync = promisify(cv.imencodeCallback);

cv.Mat.prototype.matchTemplateAsync = promisify(cv.Mat.prototype.matchTemplateCallback);
cv.Mat.prototype.matchTemplateAllAsync = promisify(cv.Mat.prototype.matchTemplateAllCallback);
cv.Mat.prototype.minMaxLocAsync = promisify(cv.Mat.prototype.minMaxLocCallback);

const cvProxy = new Proxy(cv, {
Expand All @@ -13,6 +15,8 @@ const cvProxy = new Proxy(cv, {
return imdecodeAsync;
} else if (prop === 'imreadAsync') {
return imreadAsync;
} else if (prop === 'imencodeAsync') {
return imencodeAsync;
} else {
return target[prop];
}
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,5 @@
"build": "napi build --release",
"build:debug": "napi build --platform",
"test": "node demo/test.js"
},
"packageManager": "[email protected]"
}
}
76 changes: 76 additions & 0 deletions src/dnn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use opencv::{dnn, core::Vector};
use napi::bindgen_prelude::*;
use napi::{
threadsafe_function::{ThreadsafeFunction, ThreadsafeFunctionCallMode},
};

#[napi(object)]
pub struct Rect {
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
}

#[napi]
pub struct DNN {}

#[napi]
impl DNN {
#[napi(constructor)]
pub fn new() -> Self {
DNN {}
}

#[napi]
pub fn nms_boxes(
&self,
bboxes: Vec<Rect>,
scores: Vec<f64>,
score_threshold: f64,
nms_threshold: f64,
callback: JsFunction,
) -> Result<()> {
let tsfn: ThreadsafeFunction<Result<Vec<i32>>> =
callback.create_threadsafe_function(0, |ctx| Ok(vec![ctx.value]))?;

let mut opencv_bboxes = Vector::new();
for r in bboxes {
opencv_bboxes.push(opencv::core::Rect::new(r.x, r.y, r.width, r.height));
}

let mut opencv_scores = Vector::new();
for s in scores {
opencv_scores.push(s as f32);
}

let score_threshold_f32 = score_threshold as f32;
let nms_threshold_f32 = nms_threshold as f32;

std::thread::spawn(move || {
let mut indices = Vector::new();

let js_result = dnn::nms_boxes(
&opencv_bboxes,
&opencv_scores,
score_threshold_f32,
nms_threshold_f32,
&mut indices,
1.0,
0,
)
.map_err(|e| napi::Error::from_reason(e.to_string()))
.map(|_| {
let mut result = Vec::new();
for i in 0..indices.len() {
result.push(indices.get(i).unwrap());
}
result
});

tsfn.call(Ok(js_result), ThreadsafeFunctionCallMode::Blocking);
});

Ok(())
}
}
34 changes: 33 additions & 1 deletion src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use napi::{
};
use opencv::{
core::Vector,
imgcodecs::{imdecode, imread, IMREAD_COLOR},
imgcodecs::{imdecode, imencode, imread, IMREAD_COLOR},
prelude::*,
};
use crate::{JSMat, OpenCVError};
Expand All @@ -24,6 +24,38 @@ pub fn get_tick_count() -> i64 {
opencv::core::get_tick_count().expect("Failed to get tick count")
}

#[napi(js_name = "imencode")]
pub fn imencode_sync(ext: String, img: &JSMat) -> Result<Buffer> {
let mut buf = Vector::new();
opencv::imgcodecs::imencode(&ext, &img.mat, &mut buf, &Vector::new())
.map_err(OpenCVError)?;
Ok(Buffer::from(buf.to_vec()))
}

#[napi]
pub fn imencode_callback(
ext: String,
#[napi(ts_arg_type = "JSMat")] mat: &JSMat,
callback: JsFunction
) -> Result<()> {
let tsfn: ThreadsafeFunction<Result<Buffer>> =
callback.create_threadsafe_function(0, |ctx| Ok(vec![ctx.value]))?;

let mat = mat.mat.clone();

std::thread::spawn(move || {
let mut buf = Vector::new();
let result = match imencode(&ext, &mat, &mut buf, &Vector::new()) {
Ok(_) => Ok(Buffer::from(buf.to_vec())),
Err(e) => Err(Error::from(OpenCVError(e)))
};

tsfn.call(Ok(result), ThreadsafeFunctionCallMode::Blocking);
});

Ok(())
}

#[napi(js_name = "imread")]
pub fn imread_sync(path: String, flags: Option<i32>) -> Result<JSMat> {
let flags = flags.unwrap_or(IMREAD_COLOR);
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod constants;
mod error;
mod image;
mod mat;
mod dnn;

#[macro_use]
extern crate napi_derive;
Expand All @@ -12,3 +13,4 @@ pub use constants::*;
pub use error::OpenCVError;
pub use image::*;
pub use mat::JSMat;
pub use dnn::*;
Loading

0 comments on commit e5e20a3

Please sign in to comment.