Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor tracker to be class based + Add types #48

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 91 additions & 83 deletions ItemTracked.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var uuidv4 = require('uuid/v4');
var computeBearingIn360 = require('./utils').computeBearingIn360
var computeVelocityVector = require('./utils').computeVelocityVector
const { v4: uuidv4 } = require("uuid");
var computeBearingIn360 = require("./utils").computeBearingIn360;
var computeVelocityVector = require("./utils").computeVelocityVector;

// Properties example
// {
Expand All @@ -15,10 +15,13 @@ var computeVelocityVector = require('./utils').computeVelocityVector
/** The maximum length of the item history. */
exports.ITEM_HISTORY_MAX_LENGTH = 15;

// Use a simple incremental unique id for the display
var idDisplay = 0;

exports.ItemTracked = function(properties, frameNb, unMatchedFramesTolerance, fastDelete){
exports.ItemTracked = function (
properties,
frameNb,
unMatchedFramesTolerance,
fastDelete,
idDisplay
) {
var DEFAULT_UNMATCHEDFRAMES_TOLERANCE = unMatchedFramesTolerance;
var itemTracked = {};
// ==== Private =====
Expand Down Expand Up @@ -49,27 +52,26 @@ exports.ItemTracked = function(properties, frameNb, unMatchedFramesTolerance, fa
y: properties.y,
w: properties.w,
h: properties.h,
confidence: properties.confidence
confidence: properties.confidence,
});
if(itemTracked.itemHistory.length >= exports.ITEM_HISTORY_MAX_LENGTH) {
if (itemTracked.itemHistory.length >= exports.ITEM_HISTORY_MAX_LENGTH) {
itemTracked.itemHistory.shift();
}
itemTracked.velocity = {
dx: 0,
dy: 0
dy: 0,
};
itemTracked.nbTimeMatched = 1;
// Assign an unique id to each Item tracked
itemTracked.id = uuidv4();
// Use an simple id for the display and debugging
itemTracked.idDisplay = idDisplay;
idDisplay++
// Give me a new location / size
itemTracked.update = function(properties, frameNb){
itemTracked.update = function (properties, frameNb) {
// if it was zombie and disappear frame was set, reset it to null
if(this.disappearFrame) {
if (this.disappearFrame) {
this.disappearFrame = null;
this.disappearArea = {}
this.disappearArea = {};
}
this.isZombie = false;
this.nbTimeMatched += 1;
Expand All @@ -83,155 +85,161 @@ exports.ItemTracked = function(properties, frameNb, unMatchedFramesTolerance, fa
y: this.y,
w: this.w,
h: this.h,
confidence: this.confidence
confidence: this.confidence,
});
if(itemTracked.itemHistory.length >= exports.ITEM_HISTORY_MAX_LENGTH) {
if (itemTracked.itemHistory.length >= exports.ITEM_HISTORY_MAX_LENGTH) {
itemTracked.itemHistory.shift();
}
this.name = properties.name;
if(this.nameCount[properties.name]) {
if (this.nameCount[properties.name]) {
this.nameCount[properties.name]++;
} else {
this.nameCount[properties.name] = 1;
}
// Reset dying counter
this.frameUnmatchedLeftBeforeDying = DEFAULT_UNMATCHEDFRAMES_TOLERANCE
this.frameUnmatchedLeftBeforeDying = DEFAULT_UNMATCHEDFRAMES_TOLERANCE;
// Compute new velocityVector based on last positions history
this.velocity = this.updateVelocityVector();
}
itemTracked.makeAvailable = function() {
};
itemTracked.makeAvailable = function () {
this.available = true;
return this;
}
itemTracked.makeUnavailable = function() {
};
itemTracked.makeUnavailable = function () {
this.available = false;
return this;
}
itemTracked.countDown = function(frameNb) {
};
itemTracked.countDown = function (frameNb) {
// Set frame disappear number
if(this.disappearFrame === null) {
if (this.disappearFrame === null) {
this.disappearFrame = frameNb;
this.disappearArea = {
x: this.x,
y: this.y,
w: this.w,
h: this.h
}
h: this.h,
};
}
this.frameUnmatchedLeftBeforeDying--;
this.isZombie = true;
// If it was matched less than 1 time, it should die quick
if(this.fastDelete && this.nbTimeMatched <= 1) {
if (this.fastDelete && this.nbTimeMatched <= 1) {
this.frameUnmatchedLeftBeforeDying = -1;
}
}
itemTracked.updateTheoricalPositionAndSize = function() {
};
itemTracked.updateTheoricalPositionAndSize = function () {
this.itemHistory.push({
x: this.x,
y: this.y,
w: this.w,
h: this.h,
confidence: this.confidence
confidence: this.confidence,
});
if(itemTracked.itemHistory.length >= exports.ITEM_HISTORY_MAX_LENGTH) {
if (itemTracked.itemHistory.length >= exports.ITEM_HISTORY_MAX_LENGTH) {
itemTracked.itemHistory.shift();
}
this.x = this.x + this.velocity.dx
this.y = this.y + this.velocity.dy
}
this.x = this.x + this.velocity.dx;
this.y = this.y + this.velocity.dy;
};

itemTracked.predictNextPosition = function() {
itemTracked.predictNextPosition = function () {
return {
x : this.x + this.velocity.dx,
y : this.y + this.velocity.dy,
x: this.x + this.velocity.dx,
y: this.y + this.velocity.dy,
w: this.w,
h: this.h
h: this.h,
};
}
};

itemTracked.isDead = function() {
itemTracked.isDead = function () {
return this.frameUnmatchedLeftBeforeDying < 0;
}
};
// Velocity vector based on the last 15 frames
itemTracked.updateVelocityVector = function() {
if(exports.ITEM_HISTORY_MAX_LENGTH <= 2) {
return { dx: undefined, dy: undefined, }
itemTracked.updateVelocityVector = function () {
if (exports.ITEM_HISTORY_MAX_LENGTH <= 2) {
return { dx: undefined, dy: undefined };
}

if(this.itemHistory.length <= exports.ITEM_HISTORY_MAX_LENGTH) {
if (this.itemHistory.length <= exports.ITEM_HISTORY_MAX_LENGTH) {
const start = this.itemHistory[0];
const end = this.itemHistory[this.itemHistory.length - 1];
return computeVelocityVector(start, end, this.itemHistory.length);
} else {
const start = this.itemHistory[this.itemHistory.length - exports.ITEM_HISTORY_MAX_LENGTH];
const start =
this.itemHistory[
this.itemHistory.length - exports.ITEM_HISTORY_MAX_LENGTH
];
const end = this.itemHistory[this.itemHistory.length - 1];
return computeVelocityVector(start, end, exports.ITEM_HISTORY_MAX_LENGTH);
}
}
};

itemTracked.getMostlyMatchedName = function() {
itemTracked.getMostlyMatchedName = function () {
var nameMostlyMatchedOccurences = 0;
var nameMostlyMatched = '';
var nameMostlyMatched = "";
Object.keys(this.nameCount).map((name) => {
if(this.nameCount[name] > nameMostlyMatchedOccurences) {
if (this.nameCount[name] > nameMostlyMatchedOccurences) {
nameMostlyMatched = name;
nameMostlyMatchedOccurences = this.nameCount[name]
nameMostlyMatchedOccurences = this.nameCount[name];
}
})
});
return nameMostlyMatched;
}
};

itemTracked.toJSONDebug = function(roundInt = true) {
itemTracked.toJSONDebug = function (roundInt = true) {
return {
id: this.id,
idDisplay: this.idDisplay,
x: (roundInt ? parseInt(this.x, 10) : this.x),
y: (roundInt ? parseInt(this.y, 10) : this.y),
w: (roundInt ? parseInt(this.w, 10) : this.w),
h: (roundInt ? parseInt(this.h, 10) : this.h),
x: roundInt ? parseInt(this.x, 10) : this.x,
y: roundInt ? parseInt(this.y, 10) : this.y,
w: roundInt ? parseInt(this.w, 10) : this.w,
h: roundInt ? parseInt(this.h, 10) : this.h,
confidence: Math.round(this.confidence * 100) / 100,
// Here we negate dy to be in "normal" carthesian coordinates
bearing: parseInt(computeBearingIn360(this.velocity.dx, - this.velocity.dy)),
bearing: parseInt(
computeBearingIn360(this.velocity.dx, -this.velocity.dy)
),
name: this.getMostlyMatchedName(),
isZombie: this.isZombie,
appearFrame: this.appearFrame,
disappearFrame: this.disappearFrame
}
}
disappearFrame: this.disappearFrame,
};
};

itemTracked.toJSON = function(roundInt = true) {
itemTracked.toJSON = function (roundInt = true) {
return {
id: this.idDisplay,
x: (roundInt ? parseInt(this.x, 10) : this.x),
y: (roundInt ? parseInt(this.y, 10) : this.y),
w: (roundInt ? parseInt(this.w, 10) : this.w),
h: (roundInt ? parseInt(this.h, 10) : this.h),
x: roundInt ? parseInt(this.x, 10) : this.x,
y: roundInt ? parseInt(this.y, 10) : this.y,
w: roundInt ? parseInt(this.w, 10) : this.w,
h: roundInt ? parseInt(this.h, 10) : this.h,
confidence: Math.round(this.confidence * 100) / 100,
// Here we negate dy to be in "normal" carthesian coordinates
bearing: parseInt(computeBearingIn360(this.velocity.dx, - this.velocity.dy), 10),
bearing: parseInt(
computeBearingIn360(this.velocity.dx, -this.velocity.dy),
10
),
name: this.getMostlyMatchedName(),
isZombie: this.isZombie
}
}
isZombie: this.isZombie,
};
};

itemTracked.toMOT = function(frameIndex) {
return `${frameIndex},${this.idDisplay},${this.x - this.w / 2},${this.y - this.h / 2},${this.w},${this.h},${this.confidence / 100},-1,-1,-1`;
}
itemTracked.toMOT = function (frameIndex) {
return `${frameIndex},${this.idDisplay},${this.x - this.w / 2},${
this.y - this.h / 2
},${this.w},${this.h},${this.confidence / 100},-1,-1,-1`;
};

itemTracked.toJSONGenericInfo = function() {
itemTracked.toJSONGenericInfo = function () {
return {
id: this.id,
idDisplay: this.idDisplay,
appearFrame: this.appearFrame,
disappearFrame: this.disappearFrame,
disappearArea: this.disappearArea,
nbActiveFrame: this.disappearFrame - this.appearFrame,
name: this.getMostlyMatchedName()
}
}
name: this.getMostlyMatchedName(),
};
};
return itemTracked;
};

exports.reset = function() {
idDisplay = 0;
}
Loading