Skip to content

Commit 9cd7dd7

Browse files
committed
add jsdoc
1 parent 7e9f102 commit 9cd7dd7

File tree

1 file changed

+178
-12
lines changed

1 file changed

+178
-12
lines changed

src/webai.js

Lines changed: 178 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ import ort from './ort'
33

44

55
class Model {
6+
/**
7+
* create a base model.
8+
* @param {string} modelURL model URL
9+
* @param {object} sessionOption onnxruntime session options
10+
* @param {(model: Model) => void} init model init function
11+
* @param {(...any) => object} preProcess preprocess function
12+
* @param {(resultsTensors: object, ...any) => any} postProcess postprocess function
13+
* @returns {Promise<Model>} base model object
14+
*/
615
static async create(modelURL, sessionOption = { logSeverityLevel: 4 }, init = null, preProcess = null, postProcess = null) {
716
await WebAI.waitForOpenCV()
817
let model = new this();
@@ -19,6 +28,11 @@ class Model {
1928
return model
2029
}
2130

31+
/**
32+
* base model infer function.
33+
* @param {...any} args model infer paramters
34+
* @returns {any} model infer results
35+
*/
2236
async infer(...args) {
2337
console.time('Infer');
2438

@@ -45,7 +59,17 @@ class Model {
4559
}
4660
}
4761

62+
4863
class CV extends Model {
64+
/**
65+
* create a base CV model.
66+
* @param {string} modelURL model URL
67+
* @param {string} inferConfig model infer config URL
68+
* @param {object} sessionOption onnxruntime session options
69+
* @param {(imgTensor: ort.Tensor, imScaleX: number, imScaleY: number) => object} getFeeds get infer session feeds function
70+
* @param {(resultsTensors: object, ...any) => any} postProcess postprocess function
71+
* @returns {Promise<CV>} base CV model object
72+
*/
4973
static async create(modelURL, inferConfig, sessionOption = { logSeverityLevel: 4 }, getFeeds = null, postProcess = null) {
5074
let model = await super.create(modelURL, sessionOption, null, null, postProcess)
5175
model.loadConfigs(inferConfig);
@@ -55,6 +79,10 @@ class CV extends Model {
5579
return model
5680
}
5781

82+
/**
83+
* load infer configs
84+
* @param {string} inferConfig model infer config URL
85+
*/
5886
loadConfigs(inferConfig) {
5987
let inferConfigs = JSON.parse(WebAI.loadText(inferConfig));
6088
let preProcess = inferConfigs.Preprocess;
@@ -123,6 +151,11 @@ class CV extends Model {
123151
})
124152
}
125153

154+
/**
155+
* model preprocess function.
156+
* @param {...any} args preprocess args
157+
* @returns {object} session infer feeds
158+
*/
126159
preProcess(...args) {
127160
let [imgRGBA, height, width] = args.slice(0, 3)
128161
let imgResize, imScaleX, imScaleY
@@ -169,7 +202,15 @@ class CV extends Model {
169202
}
170203
}
171204

205+
172206
class Det extends CV {
207+
/**
208+
* get session infer feeds.
209+
* @param {ort.Tensor} imgTensor image tensor
210+
* @param {number} imScaleX image scale factor of x axis
211+
* @param {number} imScaleY image scale factor of y axis
212+
* @returns {object} session infer feeds
213+
*/
173214
getFeeds(imgTensor, imScaleX, imScaleY) {
174215
let inputNames = this.session.inputNames;
175216
let _feeds = {
@@ -184,6 +225,12 @@ class Det extends CV {
184225
return feeds
185226
}
186227

228+
/**
229+
* detection postprocess.
230+
* @param {object} resultsTensors result tensors
231+
* @param {...any} args postprocess args
232+
* @returns {{label: string, color: [number, number, number, number], score: number, x1: number, y1: number, x2: number, y2: number}[]} bboxes of the detection
233+
*/
187234
postProcess(resultsTensors, ...args) {
188235
let [height, width, drawThreshold] = args.slice(1, 4)
189236
let bboxesTensor = Object.values(resultsTensors)[0];
@@ -219,16 +266,33 @@ class Det extends CV {
219266
return bboxes
220267
}
221268

269+
/**
270+
* detection infer.
271+
* @param {cv.Mat} imgRGBA RGBA image
272+
* @param {number} drawThreshold threshold of detection
273+
* @returns {{label: string, color: [number, number, number, number], score: number, x1: number, y1: number, x2: number, y2: number}[]} bboxes of the detection
274+
*/
222275
async infer(imgRGBA, drawThreshold = 0.5) {
223276
return super.infer(imgRGBA, imgRGBA.rows, imgRGBA.cols, drawThreshold)
224277
}
225278
}
226279

227280
class Cls extends CV {
281+
/**
282+
* get the feeds of the infer session.
283+
* @param {ort.Tensor} imgTensor image tensor
284+
* @returns {object} feeds of the infer session {x: image tensor}
285+
*/
228286
getFeeds(imgTensor) {
229287
return { x: imgTensor }
230288
}
231289

290+
/**
291+
* classification postprocess.
292+
* @param {object} resultsTensors result tensors
293+
* @param {...any} args postprocess args
294+
* @returns {{label: string, prob: number}[]} probs of the classification
295+
*/
232296
postProcess(resultsTensors, ...args) {
233297
let topK = args[3];
234298
let probsTensor = Object.values(resultsTensors)[0];
@@ -249,16 +313,32 @@ class Cls extends CV {
249313
}
250314
}
251315

316+
/**
317+
* classification infer.
318+
* @param {cv.Mat} imgRGBA RGBA image
319+
* @param {number} topK probs top K
320+
* @returns {{label: string, prob: number}[]} probs of the classification
321+
*/
252322
async infer(imgRGBA, topK = 5) {
253323
return super.infer(imgRGBA, imgRGBA.rows, imgRGBA.cols, topK)
254324
}
255325
}
256326

257327
class Seg extends CV {
328+
/**
329+
* get the feeds of the infer session.
330+
* @param {ort.Tensor} imgTensor image tensor
331+
* @returns {object} feeds of the infer session {x: image tensor}
332+
*/
258333
getFeeds(imgTensor) {
259334
return { x: imgTensor }
260335
}
261336

337+
/**
338+
* segmentation postprocess.
339+
* @param {object} resultsTensors result tensors
340+
* @returns {{gray: cv.Mat, colorRGBA: cv.Mat, colorMap: {label: string, color: [number, number, number, number]}[], delete: method}} segmentation results
341+
*/
262342
postProcess(resultsTensors) {
263343
let segTensor = Object.values(resultsTensors)[0];
264344
let data = segTensor.data
@@ -297,12 +377,22 @@ class Seg extends CV {
297377
}
298378
}
299379

380+
/**
381+
* segmentation infer.
382+
* @param {cv.Mat} imgRGBA RGBA image
383+
* @returns {{gray: cv.Mat, colorRGBA: cv.Mat, colorMap: {label: string, color: [number, number, number, number]}[], delete: method}} segmentation results
384+
*/
300385
infer(imgRGBA) {
301386
return super.infer(imgRGBA, imgRGBA.rows, imgRGBA.cols)
302387
}
303388
}
304389

305390
class WebAI {
391+
/**
392+
* get the index of the max value of the array.
393+
* @param {number[]} arr array
394+
* @returns {number} the index of the max value of the array
395+
*/
306396
static argmax(arr) {
307397
let max = Math.max.apply(null, arr);
308398
let index = arr.findIndex(
@@ -318,6 +408,15 @@ class WebAI {
318408
return index
319409
}
320410

411+
/**
412+
* get image scale.
413+
* @param {number} height image height
414+
* @param {number} width image width
415+
* @param {[number, number]} targetSize target size [h, w]
416+
* @param {boolean} keepRatio is keep the ratio of image size
417+
* @param {boolean} limitMax is limit max size of image
418+
* @returns {[number, number]} [scale factor of x axis, , scale factor of y axis]
419+
*/
321420
static getIMScale(height, width, targetSize, keepRatio, limitMax) {
322421
let imScaleX, imScaleY;
323422
if (keepRatio) {
@@ -343,25 +442,52 @@ class WebAI {
343442
return [imScaleX, imScaleY]
344443
}
345444

445+
/**
446+
* RGBA -> RGB image.
447+
* @param {cv.Mat} imgRGBA RGBA image
448+
* @returns {cv.Mat} RGB image
449+
*/
346450
static rgba2rgb(imgRGBA) {
347451
let imgRGB = new this.cv.Mat();
348452
this.cv.cvtColor(imgRGBA, imgRGB, this.cv.COLOR_RGBA2RGB);
349453
return imgRGB
350454
}
351455

456+
/**
457+
* RGBA -> BGR image.
458+
* @param {cv.Mat} imgRGBA RGBA image
459+
* @returns {cv.Mat} BGR image
460+
*/
352461
static rgba2bgr(imgRGBA) {
353462
let imgBGR = new this.cv.Mat();
354463
this.cv.cvtColor(imgRGBA, imgBGR, this.cv.COLOR_RGBA2BGR);
355464
return imgBGR
356465
}
357466

467+
/**
468+
* image resize.
469+
* @param {cv.Mat} img image mat
470+
* @param {number} height image height
471+
* @param {number} width image width
472+
* @param {[number, number]} targetSize target size [h, w]
473+
* @param {boolean} keepRatio is keep the ratio of image size
474+
* @param {boolean} limitMax is limit max size of image
475+
* @param {number} interp interpolation method
476+
* @returns {[cv.Mat, number, number]} [image resized, scale factor of x axis, , scale factor of y axis]
477+
*/
358478
static resize(img, height, width, targetSize, keepRatio, limitMax, interp) {
359479
let [imScaleX, imScaleY] = this.getIMScale(height, width, targetSize, keepRatio, limitMax);
360480
let imgResize = new this.cv.Mat();
361481
this.cv.resize(img, imgResize, { width: 0, height: 0 }, imScaleX, imScaleY, interp);
362482
return [imgResize, imScaleX, imScaleY]
363483
}
364484

485+
/**
486+
* image center crop.
487+
* @param {cv.Mat} img image mat
488+
* @param {[number, number]} cropSize crop size [h, w]
489+
* @returns {cv.Mat} cropped image
490+
*/
365491
static crop(img, cropSize) {
366492
let imgCrop = img.roi({
367493
x: Math.ceil((img.cols - cropSize[1]) / 2),
@@ -373,29 +499,43 @@ class WebAI {
373499
return imgCrop
374500
}
375501

376-
static normalize(imgRGB, scale, mean, std, isScale) {
377-
imgRGB.convertTo(imgRGB, this.cv.CV_32F);
502+
/**
503+
* image normalize.
504+
* @param {cv.Mat} img image mat
505+
* @param {[number, number, number, number]} scale normalize scale
506+
* @param {[number, number, number, number]} mean normalize mean
507+
* @param {[number, number, number, number]} std normalize std
508+
* @param {boolean} isScale is scale the image
509+
* @returns {cv.Mat} normalized image
510+
*/
511+
static normalize(img, scale, mean, std, isScale) {
512+
img.convertTo(img, this.cv.CV_32F);
378513

379514
if (isScale) {
380-
let imgScale = new this.cv.Mat(imgRGB.rows, imgRGB.cols, this.cv.CV_32FC3, scale);
381-
this.cv.divide(imgRGB, imgScale, imgRGB);
515+
let imgScale = new this.cv.Mat(img.rows, img.cols, this.cv.CV_32FC3, scale);
516+
this.cv.divide(img, imgScale, img);
382517
imgScale.delete();
383518
}
384519

385-
let imgMean = new this.cv.Mat(imgRGB.rows, imgRGB.cols, this.cv.CV_32FC3, mean);
386-
this.cv.subtract(imgRGB, imgMean, imgRGB);
520+
let imgMean = new this.cv.Mat(img.rows, img.cols, this.cv.CV_32FC3, mean);
521+
this.cv.subtract(img, imgMean, img);
387522
imgMean.delete();
388523

389-
let imgStd = new this.cv.Mat(imgRGB.rows, imgRGB.cols, this.cv.CV_32FC3, std);
390-
this.cv.divide(imgRGB, imgStd, imgRGB);
524+
let imgStd = new this.cv.Mat(img.rows, img.cols, this.cv.CV_32FC3, std);
525+
this.cv.divide(img, imgStd, img);
391526
imgStd.delete();
392527

393-
return imgRGB
528+
return img
394529
}
395530

396-
static permute(imgRGB) {
531+
/**
532+
* permute hwc -> chw.
533+
* @param {cv.Mat} img image mat
534+
* @returns {Float32Array} image data
535+
*/
536+
static permute(img) {
397537
let rgbPlanes = new this.cv.MatVector();
398-
this.cv.split(imgRGB, rgbPlanes);
538+
this.cv.split(img, rgbPlanes);
399539
let R = rgbPlanes.get(0);
400540
let G = rgbPlanes.get(1);
401541
let B = rgbPlanes.get(2);
@@ -408,17 +548,27 @@ class WebAI {
408548
R.delete();
409549
G.delete();
410550
B.delete();
411-
imgRGB.delete();
551+
img.delete();
412552
return imgData
413553
}
414554

555+
/**
556+
* load text content.
557+
* @param {string} textURL text URL
558+
* @returns {string} content of the text
559+
*/
415560
static loadText(textURL) {
416561
let xhr = new XMLHttpRequest();
417562
xhr.open('get', textURL, false);
418563
xhr.send(null);
419564
return xhr.responseText
420565
}
421566

567+
/**
568+
* get color map of label list.
569+
* @param {string[]} labelList label list
570+
* @returns {{label: string, color: [number, number, number, number]}[]} color map of label list
571+
*/
422572
static getColorMap(labelList) {
423573
let classNum = labelList.length
424574
let colorMap = []
@@ -444,6 +594,18 @@ class WebAI {
444594
return colorMap
445595
}
446596

597+
/**
598+
* draw bboxes onto the image.
599+
* @param {cv.Mat} img image mat
600+
* @param {{label: string, color: [number, number, number, number], score: number, x1: number, y1: number, x2: number, y2: number}[]} bboxes bboxes of detection
601+
* @param {boolean} withLabel draw with label
602+
* @param {boolean} withScore draw with score
603+
* @param {number} thickness line thickness
604+
* @param {number} lineType line type
605+
* @param {number} fontFace font face
606+
* @param {number} fontScale font scale
607+
* @returns {cv.Mat} drawed image
608+
*/
447609
static drawBBoxes(img, bboxes, withLabel = true, withScore = true, thickness = 2.0, lineType = 8, fontFace = 0, fontScale = 0.7) {
448610
let imgShow = img.clone()
449611
for (let i = 0; i < bboxes.length; i++) {
@@ -462,6 +624,10 @@ class WebAI {
462624
return imgShow
463625
}
464626

627+
/**
628+
* wait for OpenCV loading.
629+
* @returns {Promise<boolean>} promise of opencv.js loaded
630+
*/
465631
static waitForOpenCV() {
466632
return new Promise(resolve => {
467633
if (typeof cv.onRuntimeInitialized == 'undefined') {

0 commit comments

Comments
 (0)