New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

tfjs-image-recognition-base

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tfjs-image-recognition-base - npm Package Compare versions

Comparing version 0.0.0 to 0.1.0

build/classes/Box.d.ts

41

build/classes/BoundingBox.d.ts

@@ -1,33 +0,10 @@

import { Rect } from './Rect';
import { Dimensions } from './types';
export declare class BoundingBox {
private _left;
private _top;
private _right;
private _bottom;
constructor(_left: number, _top: number, _right: number, _bottom: number);
readonly left: number;
readonly top: number;
readonly right: number;
readonly bottom: number;
readonly width: number;
readonly height: number;
readonly area: number;
toSquare(): BoundingBox;
round(): BoundingBox;
padAtBorders(imageHeight: number, imageWidth: number): {
dy: number;
edy: number;
dx: number;
edx: number;
y: number;
ey: number;
x: number;
ex: number;
w: number;
h: number;
};
calibrate(region: BoundingBox): BoundingBox;
rescale(s: Dimensions | number): BoundingBox;
toRect(): Rect;
import { Box } from './Box';
export interface IBoundingBox {
left: number;
top: number;
right: number;
bottom: number;
}
export declare class BoundingBox extends Box<BoundingBox> implements IBoundingBox {
constructor(left: number, top: number, right: number, bottom: number);
}

@@ -1,118 +0,11 @@

import { isDimensions } from '../utils';
import { Rect } from './Rect';
var BoundingBox = /** @class */ (function () {
function BoundingBox(_left, _top, _right, _bottom) {
this._left = _left;
this._top = _top;
this._right = _right;
this._bottom = _bottom;
import * as tslib_1 from "tslib";
import { Box } from './Box';
var BoundingBox = /** @class */ (function (_super) {
tslib_1.__extends(BoundingBox, _super);
function BoundingBox(left, top, right, bottom) {
return _super.call(this, { left: left, top: top, right: right, bottom: bottom }) || this;
}
Object.defineProperty(BoundingBox.prototype, "left", {
get: function () {
return this._left;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundingBox.prototype, "top", {
get: function () {
return this._top;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundingBox.prototype, "right", {
get: function () {
return this._right;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundingBox.prototype, "bottom", {
get: function () {
return this._bottom;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundingBox.prototype, "width", {
get: function () {
return this.right - this.left;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundingBox.prototype, "height", {
get: function () {
return this.bottom - this.top;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundingBox.prototype, "area", {
get: function () {
return this.width * this.height;
},
enumerable: true,
configurable: true
});
BoundingBox.prototype.toSquare = function () {
var _a = this, left = _a.left, top = _a.top, right = _a.right, bottom = _a.bottom;
var off = (Math.abs(this.width - this.height) / 2);
if (this.width < this.height) {
left -= off;
right += off;
}
if (this.height < this.width) {
top -= off;
bottom += off;
}
return new BoundingBox(left, top, right, bottom);
};
BoundingBox.prototype.round = function () {
return new BoundingBox(Math.round(this.left), Math.round(this.top), Math.round(this.right), Math.round(this.bottom));
};
BoundingBox.prototype.padAtBorders = function (imageHeight, imageWidth) {
var w = this.width + 1;
var h = this.height + 1;
var dx = 1;
var dy = 1;
var edx = w;
var edy = h;
var x = this.left;
var y = this.top;
var ex = this.right;
var ey = this.bottom;
if (ex > imageWidth) {
edx = -ex + imageWidth + w;
ex = imageWidth;
}
if (ey > imageHeight) {
edy = -ey + imageHeight + h;
ey = imageHeight;
}
if (x < 1) {
edy = 2 - x;
x = 1;
}
if (y < 1) {
edy = 2 - y;
y = 1;
}
return { dy: dy, edy: edy, dx: dx, edx: edx, y: y, ey: ey, x: x, ex: ex, w: w, h: h };
};
BoundingBox.prototype.calibrate = function (region) {
return new BoundingBox(this.left + (region.left * this.width), this.top + (region.top * this.height), this.right + (region.right * this.width), this.bottom + (region.bottom * this.height)).toSquare().round();
};
BoundingBox.prototype.rescale = function (s) {
var scaleX = isDimensions(s) ? s.width : s;
var scaleY = isDimensions(s) ? s.height : s;
return new BoundingBox(this.left * scaleX, this.top * scaleY, this.right * scaleX, this.bottom * scaleY);
};
BoundingBox.prototype.toRect = function () {
return new Rect(this.left, this.top, this.width, this.height);
};
return BoundingBox;
}());
}(Box));
export { BoundingBox };
//# sourceMappingURL=BoundingBox.js.map

@@ -0,5 +1,8 @@

export * from './Box';
export * from './BoundingBox';
export * from './LabeledBox';
export * from './ObjectDetection';
export * from './Point';
export * from './PredictedBox';
export * from './Rect';
export * from './types';

@@ -0,5 +1,8 @@

export * from './Box';
export * from './BoundingBox';
export * from './LabeledBox';
export * from './ObjectDetection';
export * from './Point';
export * from './PredictedBox';
export * from './Rect';
//# sourceMappingURL=index.js.map

@@ -1,2 +0,2 @@

import { BoundingBox } from './BoundingBox';
import { Box } from './Box';
export interface IRect {

@@ -8,15 +8,4 @@ x: number;

}
export declare class Rect implements IRect {
x: number;
y: number;
width: number;
height: number;
export declare class Rect extends Box<Rect> implements IRect {
constructor(x: number, y: number, width: number, height: number);
readonly right: number;
readonly bottom: number;
toSquare(): Rect;
pad(padX: number, padY: number): Rect;
floor(): Rect;
toBoundingBox(): BoundingBox;
clipAtImageBorders(imgWidth: number, imgHeight: number): Rect;
}

@@ -1,59 +0,11 @@

import { BoundingBox } from './BoundingBox';
var Rect = /** @class */ (function () {
import * as tslib_1 from "tslib";
import { Box } from './Box';
var Rect = /** @class */ (function (_super) {
tslib_1.__extends(Rect, _super);
function Rect(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
return _super.call(this, { x: x, y: y, width: width, height: height }) || this;
}
Object.defineProperty(Rect.prototype, "right", {
get: function () {
return this.x + this.width;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Rect.prototype, "bottom", {
get: function () {
return this.y + this.height;
},
enumerable: true,
configurable: true
});
Rect.prototype.toSquare = function () {
var _a = this, x = _a.x, y = _a.y, width = _a.width, height = _a.height;
var diff = Math.abs(width - height);
if (width < height) {
x -= (diff / 2);
width += diff;
}
if (height < width) {
y -= (diff / 2);
height += diff;
}
return new Rect(x, y, width, height);
};
Rect.prototype.pad = function (padX, padY) {
var _a = this, x = _a.x, y = _a.y, width = _a.width, height = _a.height;
return new Rect(x - (padX / 2), y - (padY / 2), width + padX, height + padY);
};
Rect.prototype.floor = function () {
return new Rect(Math.floor(this.x), Math.floor(this.y), Math.floor(this.width), Math.floor(this.height));
};
Rect.prototype.toBoundingBox = function () {
return new BoundingBox(this.x, this.y, this.x + this.width, this.y + this.height);
};
Rect.prototype.clipAtImageBorders = function (imgWidth, imgHeight) {
var _a = this, x = _a.x, y = _a.y, right = _a.right, bottom = _a.bottom;
var clippedX = Math.max(x, 0);
var clippedY = Math.max(y, 0);
var newWidth = right - clippedX;
var newHeight = bottom - clippedY;
var clippedWidth = Math.min(newWidth, imgWidth - clippedX);
var clippedHeight = Math.min(newHeight, imgHeight - clippedY);
return (new Rect(clippedX, clippedY, clippedWidth, clippedHeight)).floor();
};
return Rect;
}());
}(Box));
export { Rect };
//# sourceMappingURL=Rect.js.map

@@ -1,1 +0,1 @@

export declare function imageToSquare(input: HTMLImageElement | HTMLCanvasElement, inputSize: number): HTMLCanvasElement;
export declare function imageToSquare(input: HTMLImageElement | HTMLCanvasElement, inputSize: number, centerImage?: boolean): HTMLCanvasElement;
import { createCanvas, createCanvasFromMedia } from './createCanvas';
import { getContext2dOrThrow } from './getContext2dOrThrow';
import { getMediaDimensions } from './getMediaDimensions';
export function imageToSquare(input, inputSize) {
export function imageToSquare(input, inputSize, centerImage) {
if (centerImage === void 0) { centerImage = false; }
if (!(input instanceof HTMLImageElement || input instanceof HTMLCanvasElement)) {

@@ -14,5 +15,8 @@ throw new Error('imageToSquare - expected arg0 to be HTMLImageElement | HTMLCanvasElement');

var inputCanvas = input instanceof HTMLCanvasElement ? input : createCanvasFromMedia(input);
getContext2dOrThrow(targetCanvas).drawImage(inputCanvas, 0, 0, width, height);
var offset = Math.abs(width - height) / 2;
var dx = centerImage && width < height ? offset : 0;
var dy = centerImage && height < width ? offset : 0;
getContext2dOrThrow(targetCanvas).drawImage(inputCanvas, dx, dy, width, height);
return targetCanvas;
}
//# sourceMappingURL=imageToSquare.js.map
import * as tf from '@tensorflow/tfjs-core';
import { Point } from '../classes/Point';
import { Dimensions } from '../classes/types';
import { TResolvedNetInput } from './types';
export declare class NetInput {
private _inputs;
private _imageTensors;
private _canvases;
private _isManaged;
private _isBatchInput;
private _batchSize;
private _treatAsBatchInput;
private _inputDimensions;
private _paddings;
private _inputSize;
constructor(inputs: tf.Tensor4D | Array<TResolvedNetInput>, isBatchInput?: boolean, keepCanvases?: boolean);
readonly inputs: tf.Tensor3D[];
constructor(inputs: Array<TResolvedNetInput>, treatAsBatchInput?: boolean);
readonly imageTensors: Array<tf.Tensor3D | tf.Tensor4D>;
readonly canvases: HTMLCanvasElement[];
readonly isManaged: boolean;
readonly isBatchInput: boolean;
readonly batchSize: number;
readonly inputDimensions: number[][];
readonly paddings: Point[];
readonly inputSize: number;
readonly relativePaddings: Point[];
readonly inputSize: number | undefined;
readonly reshapedInputDimensions: Dimensions[];
getInput(batchIdx: number): tf.Tensor3D | tf.Tensor4D | HTMLCanvasElement;
getInputDimensions(batchIdx: number): number[];
getInputHeight(batchIdx: number): number;
getInputWidth(batchIdx: number): number;
getPaddings(batchIdx: number): Point;
getRelativePaddings(batchIdx: number): Point;
getReshapedInputDimensions(batchIdx: number): Dimensions;
toBatchTensor(inputSize: number, isCenterInputs?: boolean): tf.Tensor4D;
/**
* By setting the isManaged flag, all newly created tensors will be
* automatically disposed after the batch tensor has been created
* Create a batch tensor from all input canvases and tensors
* with size [batchSize, inputSize, inputSize, 3].
*
* @param inputSize Height and width of the tensor.
* @param isCenterImage (optional, default: false) If true, add an equal amount of padding on
* both sides of the minor dimension oof the image.
* @returns The batch tensor.
*/
managed(): this;
dispose(): void;
toBatchTensor(inputSize: number, isCenterInputs?: boolean): tf.Tensor4D;
}
import * as tf from '@tensorflow/tfjs-core';
import { Point } from '../classes/Point';
import { padToSquare } from '../ops/padToSquare';
import { isTensor3D, isTensor4D } from '../utils';
import { computeReshapedDimensions } from '../utils';
import { computeReshapedDimensions, isTensor3D, isTensor4D, range } from '../utils';
import { createCanvasFromMedia } from './createCanvas';
import { imageToSquare } from './imageToSquare';
var NetInput = /** @class */ (function () {
function NetInput(inputs, isBatchInput, keepCanvases) {
if (isBatchInput === void 0) { isBatchInput = false; }
if (keepCanvases === void 0) { keepCanvases = false; }
function NetInput(inputs, treatAsBatchInput) {
if (treatAsBatchInput === void 0) { treatAsBatchInput = false; }
var _this = this;
this._inputs = [];
this._imageTensors = [];
this._canvases = [];
this._isManaged = false;
this._isBatchInput = false;
this._treatAsBatchInput = false;
this._inputDimensions = [];
this._paddings = [];
if (isTensor4D(inputs)) {
this._inputs = tf.unstack(inputs);
if (!Array.isArray(inputs)) {
throw new Error("NetInput.constructor - expected inputs to be an Array of TResolvedNetInput or to be instanceof tf.Tensor4D, instead have " + inputs);
}
if (Array.isArray(inputs)) {
this._inputs = inputs.map(function (input, idx) {
if (isTensor3D(input)) {
// TODO: make sure not to dispose original tensors passed in by the user
return tf.clone(input);
this._treatAsBatchInput = treatAsBatchInput;
this._batchSize = inputs.length;
inputs.forEach(function (input, idx) {
if (isTensor3D(input)) {
_this._imageTensors[idx] = input;
_this._inputDimensions[idx] = input.shape;
return;
}
if (isTensor4D(input)) {
var batchSize = input.shape[0];
if (batchSize !== 1) {
throw new Error("NetInput - tf.Tensor4D with batchSize " + batchSize + " passed, but not supported in input array");
}
if (isTensor4D(input)) {
var shape = input.shape;
var batchSize = shape[0];
if (batchSize !== 1) {
throw new Error("NetInput - tf.Tensor4D with batchSize " + batchSize + " passed, but not supported in input array");
}
return input.reshape(shape.slice(1));
}
var canvas = input instanceof HTMLCanvasElement ? input : createCanvasFromMedia(input);
if (keepCanvases) {
_this._canvases[idx] = canvas;
}
return tf.fromPixels(canvas);
});
}
this._isBatchInput = this.batchSize > 1 || isBatchInput;
this._inputDimensions = this._inputs.map(function (t) { return t.shape; });
_this._imageTensors[idx] = input;
_this._inputDimensions[idx] = input.shape.slice(1);
return;
}
var canvas = input instanceof HTMLCanvasElement ? input : createCanvasFromMedia(input);
_this._canvases[idx] = canvas;
_this._inputDimensions[idx] = [canvas.height, canvas.width, 3];
});
}
Object.defineProperty(NetInput.prototype, "inputs", {
Object.defineProperty(NetInput.prototype, "imageTensors", {
get: function () {
return this._inputs;
return this._imageTensors;
},

@@ -59,12 +53,5 @@ enumerable: true,

});
Object.defineProperty(NetInput.prototype, "isManaged", {
get: function () {
return this._isManaged;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NetInput.prototype, "isBatchInput", {
get: function () {
return this._isBatchInput;
return this.batchSize > 1 || this._treatAsBatchInput;
},

@@ -76,3 +63,3 @@ enumerable: true,

get: function () {
return this._inputs.length;
return this._batchSize;
},

@@ -89,9 +76,2 @@ enumerable: true,

});
Object.defineProperty(NetInput.prototype, "paddings", {
get: function () {
return this._paddings;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NetInput.prototype, "inputSize", {

@@ -104,14 +84,6 @@ get: function () {

});
Object.defineProperty(NetInput.prototype, "relativePaddings", {
get: function () {
var _this = this;
return Array(this.inputs.length).fill(0).map(function (_, batchIdx) { return _this.getRelativePaddings(batchIdx); });
},
enumerable: true,
configurable: true
});
Object.defineProperty(NetInput.prototype, "reshapedInputDimensions", {
get: function () {
var _this = this;
return Array(this.inputs.length).fill(0).map(function (_, batchIdx) { return _this.getReshapedInputDimensions(batchIdx); });
return range(this.batchSize, 0, 1).map(function (_, batchIdx) { return _this.getReshapedInputDimensions(batchIdx); });
},

@@ -121,2 +93,5 @@ enumerable: true,

});
NetInput.prototype.getInput = function (batchIdx) {
return this.canvases[batchIdx] || this.imageTensors[batchIdx];
};
NetInput.prototype.getInputDimensions = function (batchIdx) {

@@ -131,8 +106,2 @@ return this._inputDimensions[batchIdx];

};
NetInput.prototype.getPaddings = function (batchIdx) {
return this._paddings[batchIdx];
};
NetInput.prototype.getRelativePaddings = function (batchIdx) {
return new Point((this.getPaddings(batchIdx).x + this.getInputWidth(batchIdx)) / this.getInputWidth(batchIdx), (this.getPaddings(batchIdx).y + this.getInputHeight(batchIdx)) / this.getInputHeight(batchIdx));
};
NetInput.prototype.getReshapedInputDimensions = function (batchIdx) {

@@ -146,2 +115,11 @@ if (typeof this.inputSize !== 'number') {

};
/**
* Create a batch tensor from all input canvases and tensors
* with size [batchSize, inputSize, inputSize, 3].
*
* @param inputSize Height and width of the tensor.
* @param isCenterImage (optional, default: false) If true, add an equal amount of padding on
* both sides of the minor dimension oof the image.
* @returns The batch tensor.
*/
NetInput.prototype.toBatchTensor = function (inputSize, isCenterInputs) {

@@ -152,31 +130,21 @@ var _this = this;

return tf.tidy(function () {
var inputTensors = _this._inputs.map(function (inputTensor) {
var _a = inputTensor.shape, originalHeight = _a[0], originalWidth = _a[1];
var imgTensor = inputTensor.expandDims().toFloat();
imgTensor = padToSquare(imgTensor, isCenterInputs);
var _b = imgTensor.shape.slice(1), heightAfterPadding = _b[0], widthAfterPadding = _b[1];
if (heightAfterPadding !== inputSize || widthAfterPadding !== inputSize) {
imgTensor = tf.image.resizeBilinear(imgTensor, [inputSize, inputSize]);
var inputTensors = range(_this.batchSize, 0, 1).map(function (batchIdx) {
var input = _this.getInput(batchIdx);
if (input instanceof tf.Tensor) {
var imgTensor = isTensor4D(input) ? input : input.expandDims();
imgTensor = padToSquare(imgTensor, isCenterInputs);
if (imgTensor.shape[1] !== inputSize || imgTensor.shape[2] !== inputSize) {
imgTensor = tf.image.resizeBilinear(imgTensor, [inputSize, inputSize]);
}
return imgTensor.as3D(inputSize, inputSize, 3);
}
_this._paddings.push(new Point(widthAfterPadding - originalWidth, heightAfterPadding - originalHeight));
return imgTensor;
if (input instanceof HTMLCanvasElement) {
return tf.fromPixels(imageToSquare(input, inputSize, isCenterInputs));
}
throw new Error("toBatchTensor - at batchIdx " + batchIdx + ", expected input to be instanceof tf.Tensor or instanceof HTMLCanvasElement, instead have " + input);
});
var batchTensor = tf.stack(inputTensors).as4D(_this.batchSize, inputSize, inputSize, 3);
if (_this.isManaged) {
_this.dispose();
}
var batchTensor = tf.stack(inputTensors.map(function (t) { return t.toFloat(); })).as4D(_this.batchSize, inputSize, inputSize, 3);
return batchTensor;
});
};
/**
* By setting the isManaged flag, all newly created tensors will be
* automatically disposed after the batch tensor has been created
*/
NetInput.prototype.managed = function () {
this._isManaged = true;
return this;
};
NetInput.prototype.dispose = function () {
this._inputs.forEach(function (t) { return t.dispose(); });
};
return NetInput;

@@ -183,0 +151,0 @@ }());

@@ -8,6 +8,4 @@ import { NetInput } from './NetInput';

* @param input The input, which can be a media element or an array of different media elements.
* @param manageCreatedInput If a new NetInput instance is created from the inputs, this flag
* determines, whether to set the NetInput as managed or not.
* @returns A NetInput instance, which can be passed into one of the neural networks.
*/
export declare function toNetInput(inputs: TNetInput, manageCreatedInput?: boolean, keepCanvases?: boolean): Promise<NetInput>;
export declare function toNetInput(inputs: TNetInput): Promise<NetInput>;

@@ -12,11 +12,7 @@ import * as tslib_1 from "tslib";

* @param input The input, which can be a media element or an array of different media elements.
* @param manageCreatedInput If a new NetInput instance is created from the inputs, this flag
* determines, whether to set the NetInput as managed or not.
* @returns A NetInput instance, which can be passed into one of the neural networks.
*/
export function toNetInput(inputs, manageCreatedInput, keepCanvases) {
if (manageCreatedInput === void 0) { manageCreatedInput = false; }
if (keepCanvases === void 0) { keepCanvases = false; }
export function toNetInput(inputs) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var afterCreate, inputArgArray, getIdxHint, inputArray;
var inputArgArray, getIdxHint, inputArray;
return tslib_1.__generator(this, function (_a) {

@@ -28,8 +24,2 @@ switch (_a.label) {

}
afterCreate = function (netInput) { return manageCreatedInput
? netInput.managed()
: netInput; };
if (isTensor4D(inputs)) {
return [2 /*return*/, afterCreate(new NetInput(inputs))];
}
inputArgArray = Array.isArray(inputs)

@@ -63,3 +53,3 @@ ? inputs

_a.sent();
return [2 /*return*/, afterCreate(new NetInput(inputArray, Array.isArray(inputs), keepCanvases))];
return [2 /*return*/, new NetInput(inputArray, Array.isArray(inputs))];
}

@@ -66,0 +56,0 @@ });

@@ -1,2 +0,2 @@

import { BoundingBox } from '../classes/BoundingBox';
export declare function iou(box1: BoundingBox, box2: BoundingBox, isIOU?: boolean): number;
import { Box } from '../classes/Box';
export declare function iou(box1: Box, box2: Box, isIOU?: boolean): number;

@@ -1,2 +0,2 @@

import { BoundingBox } from '../classes/BoundingBox';
export declare function nonMaxSuppression(boxes: BoundingBox[], scores: number[], iouThreshold: number, isIOU?: boolean): number[];
import { Box } from '../classes/Box';
export declare function nonMaxSuppression(boxes: Box[], scores: number[], iouThreshold: number, isIOU?: boolean): number[];

@@ -6,5 +6,6 @@ import * as tf from '@tensorflow/tfjs-core';

* @param imgTensor The image tensor.
* @param isCenterImage (optional, default: false) If true, add padding on both sides of the image, such that the image.
* @param isCenterImage (optional, default: false) If true, add an equal amount of padding on
* both sides of the minor dimension oof the image.
* @returns The padded tensor with width === height.
*/
export declare function padToSquare(imgTensor: tf.Tensor4D, isCenterImage?: boolean): tf.Tensor4D;

@@ -6,3 +6,4 @@ import * as tf from '@tensorflow/tfjs-core';

* @param imgTensor The image tensor.
* @param isCenterImage (optional, default: false) If true, add padding on both sides of the image, such that the image.
* @param isCenterImage (optional, default: false) If true, add an equal amount of padding on
* both sides of the minor dimension oof the image.
* @returns The padded tensor with width === height.

@@ -9,0 +10,0 @@ */

@@ -0,8 +1,9 @@

import * as tf from '@tensorflow/tfjs-core';
import { Point } from '../classes/Point';
import { Dimensions } from '../classes/types';
export declare function isTensor(tensor: any, dim: number): boolean;
export declare function isTensor1D(tensor: any): boolean;
export declare function isTensor2D(tensor: any): boolean;
export declare function isTensor3D(tensor: any): boolean;
export declare function isTensor4D(tensor: any): boolean;
export declare function isTensor1D(tensor: any): tensor is tf.Tensor1D;
export declare function isTensor2D(tensor: any): tensor is tf.Tensor2D;
export declare function isTensor3D(tensor: any): tensor is tf.Tensor3D;
export declare function isTensor4D(tensor: any): tensor is tf.Tensor4D;
export declare function isFloat(num: number): boolean;

@@ -17,1 +18,4 @@ export declare function isEven(num: number): boolean;

export declare function getCenterPoint(pts: Point[]): Point;
export declare function range(num: number, start: number, step: number): number[];
export declare function isValidNumber(num: any): boolean;
export declare function isValidProbablitiy(num: any): boolean;

@@ -44,2 +44,11 @@ import * as tf from '@tensorflow/tfjs-core';

}
export function range(num, start, step) {
return Array(num).fill(0).map(function (_, i) { return start + (i * step); });
}
export function isValidNumber(num) {
return !!num && num !== Infinity && num !== -Infinity && !isNaN(num) || num === 0;
}
export function isValidProbablitiy(num) {
return isValidNumber(num) && 0 <= num && num <= 1.0;
}
//# sourceMappingURL=index.js.map
const dataFiles = [
'test/*.png',
'test/*.json'
].map(pattern => ({

@@ -4,0 +5,0 @@ pattern,

{
"name": "tfjs-image-recognition-base",
"version": "0.0.0",
"version": "0.1.0",
"description": "A shared codebase for face-api.js and tfjs-tiny-yolo-v2.",

@@ -5,0 +5,0 @@ "main": "./build/index.js",

@@ -1,118 +0,14 @@

import { isDimensions } from '../utils';
import { Rect } from './Rect';
import { Dimensions } from './types';
import { Box } from './Box';
export class BoundingBox {
constructor(
private _left: number,
private _top: number,
private _right: number,
private _bottom: number
) {}
export interface IBoundingBox {
left: number
top: number
right: number
bottom: number
}
public get left() : number {
return this._left
export class BoundingBox extends Box<BoundingBox> implements IBoundingBox {
constructor(left: number, top: number, right: number, bottom: number) {
super({ left, top, right, bottom })
}
public get top() : number {
return this._top
}
public get right() : number {
return this._right
}
public get bottom() : number {
return this._bottom
}
public get width() : number {
return this.right - this.left
}
public get height() : number {
return this.bottom - this.top
}
public get area() : number {
return this.width * this.height
}
public toSquare(): BoundingBox {
let { left, top, right, bottom } = this
const off = (Math.abs(this.width - this.height) / 2)
if (this.width < this.height) {
left -= off
right += off
}
if (this.height < this.width) {
top -= off
bottom += off
}
return new BoundingBox(left, top, right, bottom)
}
public round(): BoundingBox {
return new BoundingBox(
Math.round(this.left),
Math.round(this.top),
Math.round(this.right),
Math.round(this.bottom)
)
}
public padAtBorders(imageHeight: number, imageWidth: number) {
const w = this.width + 1
const h = this.height + 1
let dx = 1
let dy = 1
let edx = w
let edy = h
let x = this.left
let y = this.top
let ex = this.right
let ey = this.bottom
if (ex > imageWidth) {
edx = -ex + imageWidth + w
ex = imageWidth
}
if (ey > imageHeight) {
edy = -ey + imageHeight + h
ey = imageHeight
}
if (x < 1) {
edy = 2 - x
x = 1
}
if (y < 1) {
edy = 2 - y
y = 1
}
return { dy, edy, dx, edx, y, ey, x, ex, w, h }
}
public calibrate(region: BoundingBox) {
return new BoundingBox(
this.left + (region.left * this.width),
this.top + (region.top * this.height),
this.right + (region.right * this.width),
this.bottom + (region.bottom * this.height)
).toSquare().round()
}
public rescale(s: Dimensions | number) {
const scaleX = isDimensions(s) ? (s as Dimensions).width : s as number
const scaleY = isDimensions(s) ? (s as Dimensions).height : s as number
return new BoundingBox(this.left * scaleX, this.top * scaleY, this.right * scaleX, this.bottom * scaleY)
}
public toRect(): Rect {
return new Rect(this.left, this.top, this.width, this.height)
}
}

@@ -0,5 +1,8 @@

export * from './Box'
export * from './BoundingBox'
export * from './LabeledBox'
export * from './ObjectDetection'
export * from './Point'
export * from './PredictedBox'
export * from './Rect'
export * from './types'

@@ -1,2 +0,2 @@

import { BoundingBox } from './BoundingBox';
import { Box } from './Box';

@@ -10,67 +10,6 @@ export interface IRect {

export class Rect implements IRect {
public x: number
public y: number
public width: number
public height: number
export class Rect extends Box<Rect> implements IRect {
constructor(x: number, y: number, width: number, height: number) {
this.x = x
this.y = y
this.width = width
this.height = height
super({ x, y, width, height })
}
public get right() {
return this.x + this.width
}
public get bottom() {
return this.y + this.height
}
public toSquare(): Rect {
let { x, y, width, height } = this
const diff = Math.abs(width - height)
if (width < height) {
x -= (diff / 2)
width += diff
}
if (height < width) {
y -= (diff / 2)
height += diff
}
return new Rect(x, y, width, height)
}
public pad(padX: number, padY: number): Rect {
let { x, y, width, height } = this
return new Rect(x - (padX / 2), y - (padY / 2), width + padX, height + padY)
}
public floor(): Rect {
return new Rect(
Math.floor(this.x),
Math.floor(this.y),
Math.floor(this.width),
Math.floor(this.height)
)
}
public toBoundingBox(): BoundingBox {
return new BoundingBox(this.x, this.y, this.x + this.width, this.y + this.height)
}
public clipAtImageBorders(imgWidth: number, imgHeight: number): Rect {
const { x, y, right, bottom } = this
const clippedX = Math.max(x, 0)
const clippedY = Math.max(y, 0)
const newWidth = right - clippedX
const newHeight = bottom - clippedY
const clippedWidth = Math.min(newWidth, imgWidth - clippedX)
const clippedHeight = Math.min(newHeight, imgHeight - clippedY)
return (new Rect(clippedX, clippedY, clippedWidth, clippedHeight)).floor()
}
}

@@ -5,3 +5,3 @@ import { createCanvas, createCanvasFromMedia } from './createCanvas';

export function imageToSquare(input: HTMLImageElement | HTMLCanvasElement, inputSize: number) {
export function imageToSquare(input: HTMLImageElement | HTMLCanvasElement, inputSize: number, centerImage: boolean = false) {

@@ -19,5 +19,9 @@ if (!(input instanceof HTMLImageElement || input instanceof HTMLCanvasElement)) {

const inputCanvas = input instanceof HTMLCanvasElement ? input : createCanvasFromMedia(input)
getContext2dOrThrow(targetCanvas).drawImage(inputCanvas, 0, 0, width, height)
const offset = Math.abs(width - height) / 2
const dx = centerImage && width < height ? offset : 0
const dy = centerImage && height < width ? offset : 0
getContext2dOrThrow(targetCanvas).drawImage(inputCanvas, dx, dy, width, height)
return targetCanvas
}
import * as tf from '@tensorflow/tfjs-core';
import { Point } from '../classes/Point';
import { Dimensions } from '../classes/types';
import { padToSquare } from '../ops/padToSquare';
import { isTensor3D, isTensor4D } from '../utils';
import { computeReshapedDimensions } from '../utils';
import { computeReshapedDimensions, isTensor3D, isTensor4D, range } from '../utils';
import { createCanvasFromMedia } from './createCanvas';
import { imageToSquare } from './imageToSquare';
import { TResolvedNetInput } from './types';
export class NetInput {
private _inputs: tf.Tensor3D[] = []
private _imageTensors: Array<tf.Tensor3D | tf.Tensor4D> = []
private _canvases: HTMLCanvasElement[] = []
private _isManaged: boolean = false
private _isBatchInput: boolean = false
private _batchSize: number
private _treatAsBatchInput: boolean = false
private _inputDimensions: number[][] = []
private _paddings: Point[] = []
private _inputSize: number
constructor(
inputs: tf.Tensor4D | Array<TResolvedNetInput>,
isBatchInput: boolean = false,
keepCanvases: boolean = false
inputs: Array<TResolvedNetInput>,
treatAsBatchInput: boolean = false
) {
if (isTensor4D(inputs)) {
this._inputs = tf.unstack(inputs as tf.Tensor4D) as tf.Tensor3D[]
if (!Array.isArray(inputs)) {
throw new Error(`NetInput.constructor - expected inputs to be an Array of TResolvedNetInput or to be instanceof tf.Tensor4D, instead have ${inputs}`)
}
if (Array.isArray(inputs)) {
this._inputs = inputs.map((input, idx) => {
if (isTensor3D(input)) {
// TODO: make sure not to dispose original tensors passed in by the user
return tf.clone(input as tf.Tensor3D)
}
this._treatAsBatchInput = treatAsBatchInput
this._batchSize = inputs.length
if (isTensor4D(input)) {
const shape = (input as tf.Tensor4D).shape
const batchSize = shape[0]
if (batchSize !== 1) {
throw new Error(`NetInput - tf.Tensor4D with batchSize ${batchSize} passed, but not supported in input array`)
}
inputs.forEach((input, idx) => {
return (input as tf.Tensor4D).reshape(shape.slice(1) as [number, number, number]) as tf.Tensor3D
}
if (isTensor3D(input)) {
this._imageTensors[idx] = input
this._inputDimensions[idx] = input.shape
return
}
const canvas = input instanceof HTMLCanvasElement ? input : createCanvasFromMedia(input as HTMLImageElement | HTMLVideoElement)
if (keepCanvases) {
this._canvases[idx] = canvas
if (isTensor4D(input)) {
const batchSize = input.shape[0]
if (batchSize !== 1) {
throw new Error(`NetInput - tf.Tensor4D with batchSize ${batchSize} passed, but not supported in input array`)
}
return tf.fromPixels(canvas)
})
}
this._isBatchInput = this.batchSize > 1 || isBatchInput
this._inputDimensions = this._inputs.map(t => t.shape)
this._imageTensors[idx] = input
this._inputDimensions[idx] = input.shape.slice(1)
return
}
const canvas = input instanceof HTMLCanvasElement ? input : createCanvasFromMedia(input as HTMLImageElement | HTMLVideoElement)
this._canvases[idx] = canvas
this._inputDimensions[idx] = [canvas.height, canvas.width, 3]
})
}
public get inputs(): tf.Tensor3D[] {
return this._inputs
public get imageTensors(): Array<tf.Tensor3D | tf.Tensor4D> {
return this._imageTensors
}

@@ -67,12 +63,8 @@

public get isManaged(): boolean {
return this._isManaged
}
public get isBatchInput(): boolean {
return this._isBatchInput
return this.batchSize > 1 || this._treatAsBatchInput
}
public get batchSize(): number {
return this._inputs.length
return this._batchSize
}

@@ -84,18 +76,8 @@

public get paddings(): Point[] {
return this._paddings
}
public get inputSize(): number {
public get inputSize(): number | undefined {
return this._inputSize
}
public get relativePaddings(): Point[] {
return Array(this.inputs.length).fill(0).map(
(_, batchIdx) => this.getRelativePaddings(batchIdx)
)
}
public get reshapedInputDimensions(): Dimensions[] {
return Array(this.inputs.length).fill(0).map(
return range(this.batchSize, 0, 1).map(
(_, batchIdx) => this.getReshapedInputDimensions(batchIdx)

@@ -105,2 +87,6 @@ )

public getInput(batchIdx: number): tf.Tensor3D | tf.Tensor4D | HTMLCanvasElement {
return this.canvases[batchIdx] || this.imageTensors[batchIdx]
}
public getInputDimensions(batchIdx: number): number[] {

@@ -118,13 +104,2 @@ return this._inputDimensions[batchIdx]

public getPaddings(batchIdx: number): Point {
return this._paddings[batchIdx]
}
public getRelativePaddings(batchIdx: number): Point {
return new Point(
(this.getPaddings(batchIdx).x + this.getInputWidth(batchIdx)) / this.getInputWidth(batchIdx),
(this.getPaddings(batchIdx).y + this.getInputHeight(batchIdx)) / this.getInputHeight(batchIdx)
)
}
public getReshapedInputDimensions(batchIdx: number): Dimensions {

@@ -140,2 +115,11 @@ if (typeof this.inputSize !== 'number') {

/**
* Create a batch tensor from all input canvases and tensors
* with size [batchSize, inputSize, inputSize, 3].
*
* @param inputSize Height and width of the tensor.
* @param isCenterImage (optional, default: false) If true, add an equal amount of padding on
* both sides of the minor dimension oof the image.
* @returns The batch tensor.
*/
public toBatchTensor(inputSize: number, isCenterInputs: boolean = true): tf.Tensor4D {

@@ -147,43 +131,28 @@

const inputTensors = this._inputs.map((inputTensor: tf.Tensor3D) => {
const [originalHeight, originalWidth] = inputTensor.shape
const inputTensors = range(this.batchSize, 0, 1).map(batchIdx => {
const input = this.getInput(batchIdx)
let imgTensor = inputTensor.expandDims().toFloat() as tf.Tensor4D
imgTensor = padToSquare(imgTensor, isCenterInputs)
if (input instanceof tf.Tensor) {
let imgTensor = isTensor4D(input) ? input : input.expandDims<tf.Rank.R4>()
imgTensor = padToSquare(imgTensor, isCenterInputs)
const [heightAfterPadding, widthAfterPadding] = imgTensor.shape.slice(1)
if (imgTensor.shape[1] !== inputSize || imgTensor.shape[2] !== inputSize) {
imgTensor = tf.image.resizeBilinear(imgTensor, [inputSize, inputSize])
}
if (heightAfterPadding !== inputSize || widthAfterPadding !== inputSize) {
imgTensor = tf.image.resizeBilinear(imgTensor, [inputSize, inputSize])
return imgTensor.as3D(inputSize, inputSize, 3)
}
this._paddings.push(new Point(
widthAfterPadding - originalWidth,
heightAfterPadding - originalHeight
))
return imgTensor
if (input instanceof HTMLCanvasElement) {
return tf.fromPixels(imageToSquare(input, inputSize, isCenterInputs))
}
throw new Error(`toBatchTensor - at batchIdx ${batchIdx}, expected input to be instanceof tf.Tensor or instanceof HTMLCanvasElement, instead have ${input}`)
})
const batchTensor = tf.stack(inputTensors).as4D(this.batchSize, inputSize, inputSize, 3)
const batchTensor = tf.stack(inputTensors.map(t => t.toFloat())).as4D(this.batchSize, inputSize, inputSize, 3)
if (this.isManaged) {
this.dispose()
}
return batchTensor
})
}
/**
* By setting the isManaged flag, all newly created tensors will be
* automatically disposed after the batch tensor has been created
*/
public managed() {
this._isManaged = true
return this
}
public dispose() {
this._inputs.forEach(t => t.dispose())
}
}

@@ -1,3 +0,1 @@

import * as tf from '@tensorflow/tfjs-core';
import { isTensor3D, isTensor4D } from '../utils';

@@ -15,11 +13,5 @@ import { awaitMediaLoaded } from './awaitMediaLoaded';

* @param input The input, which can be a media element or an array of different media elements.
* @param manageCreatedInput If a new NetInput instance is created from the inputs, this flag
* determines, whether to set the NetInput as managed or not.
* @returns A NetInput instance, which can be passed into one of the neural networks.
*/
export async function toNetInput(
inputs: TNetInput,
manageCreatedInput: boolean = false,
keepCanvases: boolean = false
): Promise<NetInput> {
export async function toNetInput(inputs: TNetInput): Promise<NetInput> {
if (inputs instanceof NetInput) {

@@ -29,10 +21,2 @@ return inputs

const afterCreate = (netInput: NetInput) => manageCreatedInput
? netInput.managed()
: netInput
if (isTensor4D(inputs)) {
return afterCreate(new NetInput(inputs as tf.Tensor4D))
}
let inputArgArray = Array.isArray(inputs)

@@ -74,3 +58,3 @@ ? inputs

return afterCreate(new NetInput(inputArray, Array.isArray(inputs), keepCanvases))
return new NetInput(inputArray, Array.isArray(inputs))
}

@@ -1,4 +0,4 @@

import { BoundingBox } from '../classes/BoundingBox';
import { Box } from '../classes/Box';
export function iou(box1: BoundingBox, box2: BoundingBox, isIOU: boolean = true) {
export function iou(box1: Box, box2: Box, isIOU: boolean = true) {
const width = Math.max(0.0, Math.min(box1.right, box2.right) - Math.max(box1.left, box2.left))

@@ -5,0 +5,0 @@ const height = Math.max(0.0, Math.min(box1.bottom, box2.bottom) - Math.max(box1.top, box2.top))

@@ -1,6 +0,6 @@

import { BoundingBox } from '../classes/BoundingBox';
import { Box } from '../classes/Box';
import { iou } from './iou';
export function nonMaxSuppression(
boxes: BoundingBox[],
boxes: Box[],
scores: number[],

@@ -7,0 +7,0 @@ iouThreshold: number,

@@ -7,3 +7,4 @@ import * as tf from '@tensorflow/tfjs-core';

* @param imgTensor The image tensor.
* @param isCenterImage (optional, default: false) If true, add padding on both sides of the image, such that the image.
* @param isCenterImage (optional, default: false) If true, add an equal amount of padding on
* both sides of the minor dimension oof the image.
* @returns The padded tensor with width === height.

@@ -10,0 +11,0 @@ */

@@ -10,15 +10,15 @@ import * as tf from '@tensorflow/tfjs-core';

export function isTensor1D(tensor: any) {
export function isTensor1D(tensor: any): tensor is tf.Tensor1D {
return isTensor(tensor, 1)
}
export function isTensor2D(tensor: any) {
export function isTensor2D(tensor: any): tensor is tf.Tensor2D {
return isTensor(tensor, 2)
}
export function isTensor3D(tensor: any) {
export function isTensor3D(tensor: any): tensor is tf.Tensor3D {
return isTensor(tensor, 3)
}
export function isTensor4D(tensor: any) {
export function isTensor4D(tensor: any): tensor is tf.Tensor4D {
return isTensor(tensor, 4)

@@ -55,2 +55,14 @@ }

.div(new Point(pts.length, pts.length))
}
export function range(num: number, start: number, step: number): number[] {
return Array(num).fill(0).map((_, i) => start + (i * step))
}
export function isValidNumber(num: any) {
return !!num && num !== Infinity && num !== -Infinity && !isNaN(num) || num === 0
}
export function isValidProbablitiy(num: any) {
return isValidNumber(num) && 0 <= num && num <= 1.0
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc