You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

863 lines
38 KiB
JavaScript

/**
* tracking - A modern approach for Computer Vision on the web.
* @author Eduardo Lundgren <edu@rdo.io>
* @version v1.1.3
* @link http://trackingjs.com
* @license BSD
*/
! function(t, r) {
t.tracking = t.tracking || {}, tracking.inherits = function(t, r) {
function n() {}
n.prototype = r.prototype, t.superClass_ = r.prototype, t.prototype = new n, t.prototype.constructor = t, t.base =
function(t, n) {
var e = Array.prototype.slice.call(arguments, 2);
return r.prototype[n].apply(t, e)
}
}, tracking.initUserMedia_ = function(r, n) {
t.navigator.mediaDevices.getUserMedia({
video: !0,
audio: !(!n || !n.audio)
}).then(function(t) {
r.srcObject = t
})["catch"](function(t) {
alert("无法捕获用户照相机,请打开摄像头!");
return;
throw Error("Cannot capture user camera.");
})
}, tracking.isNode = function(t) {
return t.nodeType || this.isWindow(t)
}, tracking.isWindow = function(t) {
return !!(t && t.alert && t.document)
}, tracking.one = function(t, r) {
return this.isNode(t) ? t : (r || document).querySelector(t)
}, tracking.track = function(t, r, n) {
if (t = tracking.one(t), !t) throw new Error("Element not found, try a different element or selector.");
if (!r) throw new Error("Tracker not specified, try `tracking.track(element, new tracking.FaceTracker())`.");
switch (t.nodeName.toLowerCase()) {
case "canvas":
return this.trackCanvas_(t, r, n);
case "img":
return this.trackImg_(t, r, n);
case "video":
return n && n.camera && this.initUserMedia_(t, n), this.trackVideo_(t, r, n);
default:
throw new Error("Element not supported, try in a canvas, img, or video.")
}
}, tracking.trackCanvas_ = function(t, r) {
var n = this,
e = new tracking.TrackerTask(r);
return e.on("run", function() {
n.trackCanvasInternal_(t, r)
}), e.run()
}, tracking.trackCanvasInternal_ = function(t, r) {
var n = t.width,
e = t.height,
a = t.getContext("2d"),
i = a.getImageData(0, 0, n, e);
r.track(i.data, n, e)
}, tracking.trackImg_ = function(t, r) {
var n = t.width,
e = t.height,
a = document.createElement("canvas");
a.width = n, a.height = e;
var i = new tracking.TrackerTask(r);
return i.on("run", function() {
tracking.Canvas.loadImage(a, t.src, 0, 0, n, e, function() {
tracking.trackCanvasInternal_(a, r)
})
}), i.run()
}, tracking.trackVideo_ = function(r, n) {
var e, a, i = document.createElement("canvas"),
o = i.getContext("2d"),
c = function() {
e = r.offsetWidth, a = r.offsetHeight, i.width = e, i.height = a
};
c(), r.addEventListener("resize", c);
var s, g = function() {
s = t.requestAnimationFrame(function() {
if (r.readyState === r.HAVE_ENOUGH_DATA) {
try {
o.drawImage(r, 0, 0, e, a)
} catch (t) {}
tracking.trackCanvasInternal_(i, n)
}
g()
})
},
h = new tracking.TrackerTask(n);
return h.on("stop", function() {
t.cancelAnimationFrame(s)
}), h.on("run", function() {
g()
}), h.run()
}, t.URL || (t.URL = t.URL || t.webkitURL || t.msURL || t.oURL), navigator.getUserMedia || (navigator.getUserMedia =
navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia)
}(window),
function() {
tracking.EventEmitter = function() {}, tracking.EventEmitter.prototype.events_ = null, tracking.EventEmitter.prototype
.addListener = function(t, r) {
if ("function" != typeof r) throw new TypeError("Listener must be a function");
return this.events_ || (this.events_ = {}), this.emit("newListener", t, r), this.events_[t] || (this.events_[
t] = []), this.events_[t].push(r), this
}, tracking.EventEmitter.prototype.listeners = function(t) {
return this.events_ && this.events_[t]
}, tracking.EventEmitter.prototype.emit = function(t) {
var r = this.listeners(t);
if (r) {
for (var n = Array.prototype.slice.call(arguments, 1), e = 0; e < r.length; e++) r[e] && r[e].apply(this, n);
return !0
}
return !1
}, tracking.EventEmitter.prototype.on = tracking.EventEmitter.prototype.addListener, tracking.EventEmitter.prototype
.once = function(t, r) {
var n = this;
n.on(t, function e() {
n.removeListener(t, e), r.apply(this, arguments)
})
}, tracking.EventEmitter.prototype.removeAllListeners = function(t) {
return this.events_ ? (t ? delete this.events_[t] : delete this.events_, this) : this
}, tracking.EventEmitter.prototype.removeListener = function(t, r) {
if ("function" != typeof r) throw new TypeError("Listener must be a function");
if (!this.events_) return this;
var n = this.listeners(t);
if (Array.isArray(n)) {
var e = n.indexOf(r);
if (e < 0) return this;
n.splice(e, 1)
}
return this
}, tracking.EventEmitter.prototype.setMaxListeners = function() {
throw new Error("Not implemented")
}
}(),
function() {
tracking.Canvas = {}, tracking.Canvas.loadImage = function(t, r, n, e, a, i, o) {
var c = this,
s = new window.Image;
s.crossOrigin = "*", s.onload = function() {
var r = t.getContext("2d");
t.width = a, t.height = i, r.drawImage(s, n, e, a, i), o && o.call(c), s = null
}, s.src = r
}
}(),
function() {
tracking.DisjointSet = function(t) {
if (void 0 === t) throw new Error("DisjointSet length not specified.");
this.length = t, this.parent = new Uint32Array(t);
for (var r = 0; r < t; r++) this.parent[r] = r
}, tracking.DisjointSet.prototype.length = null, tracking.DisjointSet.prototype.parent = null, tracking.DisjointSet
.prototype.find = function(t) {
return this.parent[t] === t ? t : this.parent[t] = this.find(this.parent[t])
}, tracking.DisjointSet.prototype.union = function(t, r) {
var n = this.find(t),
e = this.find(r);
this.parent[n] = e
}
}(),
function() {
tracking.Image = {}, tracking.Image.blur = function(t, r, n, e) {
if (e = Math.abs(e), e <= 1) throw new Error("Diameter should be greater than 1.");
for (var a = e / 2, i = Math.ceil(e) + (1 - Math.ceil(e) % 2), o = new Float32Array(i), c = (a + .5) / 3, s = c *
c, g = 1 / Math.sqrt(2 * Math.PI * s), h = -1 / (2 * c * c), k = 0, f = Math.floor(i / 2), u = 0; u <
i; u++) {
var l = u - f,
m = g * Math.exp(l * l * h);
o[u] = m, k += m
}
for (var d = 0; d < o.length; d++) o[d] /= k;
return this.separableConvolve(t, r, n, o, o, !1)
}, tracking.Image.computeIntegralImage = function(t, r, n, e, a, i, o) {
if (arguments.length < 4) throw new Error(
"You should specify at least one output array in the order: sum, square, tilted, sobel.");
var c;
o && (c = tracking.Image.sobel(t, r, n));
for (var s = 0; s < n; s++)
for (var g = 0; g < r; g++) {
var h = s * r * 4 + 4 * g,
k = ~~(.299 * t[h] + .587 * t[h + 1] + .114 * t[h + 2]);
if (e && this.computePixelValueSAT_(e, r, s, g, k), a && this.computePixelValueSAT_(a, r, s, g, k * k), i) {
var f = h - 4 * r,
u = ~~(.299 * t[f] + .587 * t[f + 1] + .114 * t[f + 2]);
this.computePixelValueRSAT_(i, r, s, g, k, u || 0)
}
o && this.computePixelValueSAT_(o, r, s, g, c[h])
}
}, tracking.Image.computePixelValueRSAT_ = function(t, r, n, e, a, i) {
var o = n * r + e;
t[o] = (t[o - r - 1] || 0) + (t[o - r + 1] || 0) - (t[o - r - r] || 0) + a + i
}, tracking.Image.computePixelValueSAT_ = function(t, r, n, e, a) {
var i = n * r + e;
t[i] = (t[i - r] || 0) + (t[i - 1] || 0) + a - (t[i - r - 1] || 0)
}, tracking.Image.grayscale = function(t, r, n, e) {
for (var a = new Uint8ClampedArray(e ? t.length : t.length >> 2), i = 0, o = 0, c = 0; c < n; c++)
for (var s = 0; s < r; s++) {
var g = .299 * t[o] + .587 * t[o + 1] + .114 * t[o + 2];
a[i++] = g, e && (a[i++] = g, a[i++] = g, a[i++] = t[o + 3]), o += 4
}
return a
}, tracking.Image.horizontalConvolve = function(t, r, n, e, a) {
for (var i = e.length, o = Math.floor(i / 2), c = new Float32Array(r * n * 4), s = a ? 1 : 0, g = 0; g < n; g++)
for (var h = 0; h < r; h++) {
for (var k = g, f = h, u = 4 * (g * r + h), l = 0, m = 0, d = 0, v = 0, p = 0; p < i; p++) {
var y = k,
w = Math.min(r - 1, Math.max(0, f + p - o)),
T = 4 * (y * r + w),
x = e[p];
l += t[T] * x, m += t[T + 1] * x, d += t[T + 2] * x, v += t[T + 3] * x
}
c[u] = l, c[u + 1] = m, c[u + 2] = d, c[u + 3] = v + s * (255 - v)
}
return c
}, tracking.Image.verticalConvolve = function(t, r, n, e, a) {
for (var i = e.length, o = Math.floor(i / 2), c = new Float32Array(r * n * 4), s = a ? 1 : 0, g = 0; g < n; g++)
for (var h = 0; h < r; h++) {
for (var k = g, f = h, u = 4 * (g * r + h), l = 0, m = 0, d = 0, v = 0, p = 0; p < i; p++) {
var y = Math.min(n - 1, Math.max(0, k + p - o)),
w = f,
T = 4 * (y * r + w),
x = e[p];
l += t[T] * x, m += t[T + 1] * x, d += t[T + 2] * x, v += t[T + 3] * x
}
c[u] = l, c[u + 1] = m, c[u + 2] = d, c[u + 3] = v + s * (255 - v)
}
return c
}, tracking.Image.separableConvolve = function(t, r, n, e, a, i) {
var o = this.verticalConvolve(t, r, n, a, i);
return this.horizontalConvolve(o, r, n, e, i)
}, tracking.Image.sobel = function(t, r, n) {
t = this.grayscale(t, r, n, !0);
for (var e = new Float32Array(r * n * 4), a = new Float32Array([-1, 0, 1]), i = new Float32Array([1, 2, 1]), o =
this.separableConvolve(t, r, n, a, i), c = this.separableConvolve(t, r, n, i, a), s = 0; s < e.length; s +=
4) {
var g = o[s],
h = c[s],
k = Math.sqrt(h * h + g * g);
e[s] = k, e[s + 1] = k, e[s + 2] = k, e[s + 3] = 255
}
return e
}, tracking.Image.equalizeHist = function(t, r, n) {
for (var e = new Uint8ClampedArray(t.length), a = new Array(256), i = 0; i < 256; i++) a[i] = 0;
for (var i = 0; i < t.length; i++) e[i] = t[i], a[t[i]]++;
for (var o = a[0], i = 0; i < 256; i++) a[i] += o, o = a[i];
for (var c = 255 / t.length, i = 0; i < t.length; i++) e[i] = a[t[i]] * c + .5 | 0;
return e
}
}(),
function() {
tracking.ViolaJones = {}, tracking.ViolaJones.REGIONS_OVERLAP = .5, tracking.ViolaJones.classifiers = {}, tracking
.ViolaJones.detect = function(t, r, n, e, a, i, o, c) {
var s, g = 0,
h = [],
k = new Int32Array(r * n),
f = new Int32Array(r * n),
u = new Int32Array(r * n);
o > 0 && (s = new Int32Array(r * n)), tracking.Image.computeIntegralImage(t, r, n, k, f, u, s);
for (var l = c[0], m = c[1], d = e * a, v = d * l | 0, p = d * m | 0; v < r && p < n;) {
for (var y = d * i + .5 | 0, w = 0; w < n - p; w += y)
for (var T = 0; T < r - v; T += y) o > 0 && this.isTriviallyExcluded(o, s, w, T, r, v, p) || this.evalStages_(
c, k, f, u, w, T, r, v, p, d) && (h[g++] = {
width: v,
height: p,
x: T,
y: w
});
d *= a, v = d * l | 0, p = d * m | 0
}
return this.mergeRectangles_(h)
}, tracking.ViolaJones.isTriviallyExcluded = function(t, r, n, e, a, i, o) {
var c = n * a + e,
s = c + i,
g = c + o * a,
h = g + i,
k = (r[c] - r[s] - r[g] + r[h]) / (i * o * 255);
return k < t
}, tracking.ViolaJones.evalStages_ = function(t, r, n, e, a, i, o, c, s, g) {
var h = 1 / (c * s),
k = a * o + i,
f = k + c,
u = k + s * o,
l = u + c,
m = (r[k] - r[f] - r[u] + r[l]) * h,
d = (n[k] - n[f] - n[u] + n[l]) * h - m * m,
v = 1;
d > 0 && (v = Math.sqrt(d));
for (var p = t.length, y = 2; y < p;) {
for (var w = 0, T = t[y++], x = t[y++]; x--;) {
for (var M = 0, _ = t[y++], C = t[y++], E = 0; E < C; E++) {
var F, B, L, S, A = i + t[y++] * g + .5 | 0,
I = a + t[y++] * g + .5 | 0,
R = t[y++] * g + .5 | 0,
b = t[y++] * g + .5 | 0,
D = t[y++];
_ ? (F = A - b + R + (I + R + b - 1) * o, B = A + (I - 1) * o, L = A - b + (I + b - 1) * o, S = A + R + (I +
R - 1) * o, M += (e[F] + e[B] - e[L] - e[S]) * D) : (F = I * o + A, B = F + R, L = F + b * o, S = L + R,
M += (r[F] - r[B] - r[L] + r[S]) * D)
}
var O = t[y++],
N = t[y++],
j = t[y++];
w += M * h < O * v ? N : j
}
if (w < T) return !1
}
return !0
}, tracking.ViolaJones.mergeRectangles_ = function(t) {
for (var r = new tracking.DisjointSet(t.length), n = 0; n < t.length; n++)
for (var e = t[n], a = 0; a < t.length; a++) {
var i = t[a];
if (tracking.Math.intersectRect(e.x, e.y, e.x + e.width, e.y + e.height, i.x, i.y, i.x + i.width, i.y + i
.height)) {
var o = Math.max(e.x, i.x),
c = Math.max(e.y, i.y),
s = Math.min(e.x + e.width, i.x + i.width),
g = Math.min(e.y + e.height, i.y + i.height),
h = (o - s) * (c - g),
k = e.width * e.height,
f = i.width * i.height;
h / (k * (k / f)) >= this.REGIONS_OVERLAP && h / (f * (k / f)) >= this.REGIONS_OVERLAP && r.union(n, a)
}
}
for (var u = {}, l = 0; l < r.length; l++) {
var m = r.find(l);
u[m] ? (u[m].total++, u[m].width += t[l].width, u[m].height += t[l].height, u[m].x += t[l].x, u[m].y += t[l]
.y) : u[m] = {
total: 1,
width: t[l].width,
height: t[l].height,
x: t[l].x,
y: t[l].y
}
}
var d = [];
return Object.keys(u).forEach(function(t) {
var r = u[t];
d.push({
total: r.total,
width: r.width / r.total + .5 | 0,
height: r.height / r.total + .5 | 0,
x: r.x / r.total + .5 | 0,
y: r.y / r.total + .5 | 0
})
}), d
}
}(),
function() {
tracking.Brief = {}, tracking.Brief.N = 512, tracking.Brief.randomImageOffsets_ = {}, tracking.Brief
.randomWindowOffsets_ = null, tracking.Brief.getDescriptors = function(t, r, n) {
for (var e = new Int32Array((n.length >> 1) * (this.N >> 5)), a = 0, i = this.getRandomOffsets_(r), o = 0, c =
0; c < n.length; c += 2)
for (var s = r * n[c + 1] + n[c], g = 0, h = 0, k = this.N; h < k; h++) t[i[g++] + s] < t[i[g++] + s] && (a |=
1 << (31 & h)), h + 1 & 31 || (e[o++] = a, a = 0);
return e
}, tracking.Brief.match = function(t, r, n, e) {
for (var a = t.length >> 1, i = n.length >> 1, o = new Array(a), c = 0; c < a; c++) {
for (var s = 1 / 0, g = 0, h = 0; h < i; h++) {
for (var k = 0, f = 0, u = this.N >> 5; f < u; f++) k += tracking.Math.hammingWeight(r[c * u + f] ^ e[h * u +
f]);
k < s && (s = k, g = h)
}
o[c] = {
index1: c,
index2: g,
keypoint1: [t[2 * c], t[2 * c + 1]],
keypoint2: [n[2 * g], n[2 * g + 1]],
confidence: 1 - s / this.N
}
}
return o
}, tracking.Brief.reciprocalMatch = function(t, r, n, e) {
var a = [];
if (0 === t.length || 0 === n.length) return a;
for (var i = tracking.Brief.match(t, r, n, e), o = tracking.Brief.match(n, e, t, r), c = 0; c < i.length; c++) o[
i[c].index2].index2 === c && a.push(i[c]);
return a
}, tracking.Brief.getRandomOffsets_ = function(t) {
if (!this.randomWindowOffsets_) {
for (var r = 0, n = new Int32Array(4 * this.N), e = 0; e < this.N; e++) n[r++] = Math.round(tracking.Math
.uniformRandom(-15, 16)), n[r++] = Math.round(tracking.Math.uniformRandom(-15, 16)), n[r++] = Math.round(
tracking.Math.uniformRandom(-15, 16)), n[r++] = Math.round(tracking.Math.uniformRandom(-15, 16));
this.randomWindowOffsets_ = n
}
if (!this.randomImageOffsets_[t]) {
for (var a = 0, i = new Int32Array(2 * this.N), o = 0; o < this.N; o++) i[a++] = this.randomWindowOffsets_[4 *
o] * t + this.randomWindowOffsets_[4 * o + 1], i[a++] = this.randomWindowOffsets_[4 * o + 2] * t + this
.randomWindowOffsets_[4 * o + 3];
this.randomImageOffsets_[t] = i
}
return this.randomImageOffsets_[t]
}
}(),
function() {
tracking.Fast = {}, tracking.Fast.THRESHOLD = 40, tracking.Fast.circles_ = {}, tracking.Fast.findCorners = function(t,
r, n, e) {
var a = this.getCircleOffsets_(r),
i = new Int32Array(16),
o = [];
void 0 === e && (e = this.THRESHOLD);
for (var c = 3; c < n - 3; c++)
for (var s = 3; s < r - 3; s++) {
for (var g = c * r + s, h = t[g], k = 0; k < 16; k++) i[k] = t[g + a[k]];
this.isCorner(h, i, e) && (o.push(s, c), s += 3)
}
return o
}, tracking.Fast.isBrighter = function(t, r, n) {
return t - r > n
}, tracking.Fast.isCorner = function(t, r, n) {
if (this.isTriviallyExcluded(r, t, n)) return !1;
for (var e = 0; e < 16; e++) {
for (var a = !0, i = !0, o = 0; o < 9; o++) {
var c = r[e + o & 15];
if (!this.isBrighter(t, c, n) && (i = !1, a === !1)) break;
if (!this.isDarker(t, c, n) && (a = !1, i === !1)) break
}
if (i || a) return !0
}
return !1
}, tracking.Fast.isDarker = function(t, r, n) {
return r - t > n
}, tracking.Fast.isTriviallyExcluded = function(t, r, n) {
var e = 0,
a = t[8],
i = t[12],
o = t[4],
c = t[0];
return this.isBrighter(c, r, n) && e++, this.isBrighter(o, r, n) && e++, this.isBrighter(a, r, n) && e++, this
.isBrighter(i, r, n) && e++, e < 3 && (e = 0, this.isDarker(c, r, n) && e++, this.isDarker(o, r, n) && e++, this
.isDarker(a, r, n) && e++, this.isDarker(i, r, n) && e++, e < 3)
}, tracking.Fast.getCircleOffsets_ = function(t) {
if (this.circles_[t]) return this.circles_[t];
var r = new Int32Array(16);
return r[0] = -t - t - t, r[1] = r[0] + 1, r[2] = r[1] + t + 1, r[3] = r[2] + t + 1, r[4] = r[3] + t, r[5] = r[
4] + t, r[6] = r[5] + t - 1, r[7] = r[6] + t - 1, r[8] = r[7] - 1, r[9] = r[8] - 1, r[10] = r[9] - t - 1, r[
11] = r[10] - t - 1, r[12] = r[11] - t, r[13] = r[12] - t, r[14] = r[13] - t + 1, r[15] = r[14] - t + 1, this
.circles_[t] = r, r
}
}(),
function() {
tracking.Math = {}, tracking.Math.distance = function(t, r, n, e) {
var a = n - t,
i = e - r;
return Math.sqrt(a * a + i * i)
}, tracking.Math.hammingWeight = function(t) {
return t -= t >> 1 & 1431655765, t = (858993459 & t) + (t >> 2 & 858993459), 16843009 * (t + (t >> 4) &
252645135) >> 24
}, tracking.Math.uniformRandom = function(t, r) {
return t + Math.random() * (r - t)
}, tracking.Math.intersectRect = function(t, r, n, e, a, i, o, c) {
return !(a > n || o < t || i > e || c < r)
}
}(),
function() {
tracking.Matrix = {}, tracking.Matrix.forEach = function(t, r, n, e, a) {
a = a || 1;
for (var i = 0; i < n; i += a)
for (var o = 0; o < r; o += a) {
var c = i * r * 4 + 4 * o;
e.call(this, t[c], t[c + 1], t[c + 2], t[c + 3], c, i, o)
}
}, tracking.Matrix.sub = function(t, r) {
for (var n = tracking.Matrix.clone(t), e = 0; e < n.length; e++)
for (var a = 0; a < n[e].length; a++) n[e][a] -= r[e][a];
return n
}, tracking.Matrix.add = function(t, r) {
for (var n = tracking.Matrix.clone(t), e = 0; e < n.length; e++)
for (var a = 0; a < n[e].length; a++) n[e][a] += r[e][a];
return n
}, tracking.Matrix.clone = function(t, r, n) {
r = r || t[0].length, n = n || t.length;
for (var e = new Array(n), a = n; a--;) {
e[a] = new Array(r);
for (var i = r; i--;) e[a][i] = t[a][i]
}
return e
}, tracking.Matrix.mulScalar = function(t, r) {
for (var n = tracking.Matrix.clone(r), e = 0; e < r.length; e++)
for (var a = 0; a < r[e].length; a++) n[e][a] *= t;
return n
}, tracking.Matrix.transpose = function(t) {
for (var r = new Array(t[0].length), n = 0; n < t[0].length; n++) {
r[n] = new Array(t.length);
for (var e = 0; e < t.length; e++) r[n][e] = t[e][n]
}
return r
}, tracking.Matrix.mul = function(t, r) {
for (var n = new Array(t.length), e = 0; e < t.length; e++) {
n[e] = new Array(r[0].length);
for (var a = 0; a < r[0].length; a++) {
n[e][a] = 0;
for (var i = 0; i < t[0].length; i++) n[e][a] += t[e][i] * r[i][a]
}
}
return n
}, tracking.Matrix.norm = function(t) {
for (var r = 0, n = 0; n < t.length; n++)
for (var e = 0; e < t[n].length; e++) r += t[n][e] * t[n][e];
return Math.sqrt(r)
}, tracking.Matrix.calcCovarMatrix = function(t) {
for (var r = new Array(t.length), n = 0; n < t.length; n++) {
r[n] = [0];
for (var e = 0; e < t[n].length; e++) r[n][0] += t[n][e] / t[n].length
}
for (var a = tracking.Matrix.clone(r), n = 0; n < a.length; n++)
for (var e = 0; e < t[0].length - 1; e++) a[n].push(a[n][0]);
var i = tracking.Matrix.sub(t, a),
o = tracking.Matrix.transpose(i),
c = tracking.Matrix.mul(o, i);
return [c, r]
}
}(),
function() {
tracking.EPnP = {}, tracking.EPnP.solve = function(t, r, n) {}
}(),
function() {
tracking.Tracker = function() {
tracking.Tracker.base(this, "constructor")
}, tracking.inherits(tracking.Tracker, tracking.EventEmitter), tracking.Tracker.prototype.track = function() {}
}(),
function() {
tracking.TrackerTask = function(t) {
if (tracking.TrackerTask.base(this, "constructor"), !t) throw new Error("Tracker instance not specified.");
this.setTracker(t)
}, tracking.inherits(tracking.TrackerTask, tracking.EventEmitter), tracking.TrackerTask.prototype.tracker_ = null,
tracking.TrackerTask.prototype.running_ = !1, tracking.TrackerTask.prototype.getTracker = function() {
return this.tracker_
}, tracking.TrackerTask.prototype.inRunning = function() {
return this.running_
}, tracking.TrackerTask.prototype.setRunning = function(t) {
this.running_ = t
}, tracking.TrackerTask.prototype.setTracker = function(t) {
this.tracker_ = t
}, tracking.TrackerTask.prototype.run = function() {
var t = this;
if (!this.inRunning()) return this.setRunning(!0), this.reemitTrackEvent_ = function(r) {
t.emit("track", r)
}, this.tracker_.on("track", this.reemitTrackEvent_), this.emit("run"), this
}, tracking.TrackerTask.prototype.stop = function() {
if (this.inRunning()) return this.setRunning(!1), this.emit("stop"), this.tracker_.removeListener("track", this
.reemitTrackEvent_), this
}
}(),
function() {
tracking.ColorTracker = function(t) {
tracking.ColorTracker.base(this, "constructor"), "string" == typeof t && (t = [t]), t && (t.forEach(function(t) {
if (!tracking.ColorTracker.getColor(t)) throw new Error(
'Color not valid, try `new tracking.ColorTracker("magenta")`.')
}), this.setColors(t))
}, tracking.inherits(tracking.ColorTracker, tracking.Tracker), tracking.ColorTracker.knownColors_ = {}, tracking
.ColorTracker.neighbours_ = {}, tracking.ColorTracker.registerColor = function(t, r) {
tracking.ColorTracker.knownColors_[t] = r
}, tracking.ColorTracker.getColor = function(t) {
return tracking.ColorTracker.knownColors_[t]
}, tracking.ColorTracker.prototype.colors = ["magenta"], tracking.ColorTracker.prototype.minDimension = 20, tracking
.ColorTracker.prototype.maxDimension = 1 / 0, tracking.ColorTracker.prototype.minGroupSize = 30, tracking
.ColorTracker.prototype.calculateDimensions_ = function(t, r) {
for (var n = -1, e = -1, a = 1 / 0, i = 1 / 0, o = 0; o < r; o += 2) {
var c = t[o],
s = t[o + 1];
c < a && (a = c), c > n && (n = c), s < i && (i = s), s > e && (e = s)
}
return {
width: n - a,
height: e - i,
x: a,
y: i
}
}, tracking.ColorTracker.prototype.getColors = function() {
return this.colors
}, tracking.ColorTracker.prototype.getMinDimension = function() {
return this.minDimension
}, tracking.ColorTracker.prototype.getMaxDimension = function() {
return this.maxDimension
}, tracking.ColorTracker.prototype.getMinGroupSize = function() {
return this.minGroupSize
}, tracking.ColorTracker.prototype.getNeighboursForWidth_ = function(t) {
if (tracking.ColorTracker.neighbours_[t]) return tracking.ColorTracker.neighbours_[t];
var r = new Int32Array(8);
return r[0] = 4 * -t, r[1] = 4 * -t + 4, r[2] = 4, r[3] = 4 * t + 4, r[4] = 4 * t, r[5] = 4 * t - 4, r[6] = -4, r[
7] = 4 * -t - 4, tracking.ColorTracker.neighbours_[t] = r, r
}, tracking.ColorTracker.prototype.mergeRectangles_ = function(t) {
for (var r, n = [], e = this.getMinDimension(), a = this.getMaxDimension(), i = 0; i < t.length; i++) {
var o = t[i];
r = !0;
for (var c = i + 1; c < t.length; c++) {
var s = t[c];
if (tracking.Math.intersectRect(o.x, o.y, o.x + o.width, o.y + o.height, s.x, s.y, s.x + s.width, s.y + s
.height)) {
r = !1;
var g = Math.min(o.x, s.x),
h = Math.min(o.y, s.y),
k = Math.max(o.x + o.width, s.x + s.width),
f = Math.max(o.y + o.height, s.y + s.height);
s.height = f - h, s.width = k - g, s.x = g, s.y = h;
break
}
}
r && o.width >= e && o.height >= e && o.width <= a && o.height <= a && n.push(o)
}
return n
}, tracking.ColorTracker.prototype.setColors = function(t) {
this.colors = t
}, tracking.ColorTracker.prototype.setMinDimension = function(t) {
this.minDimension = t
}, tracking.ColorTracker.prototype.setMaxDimension = function(t) {
this.maxDimension = t
}, tracking.ColorTracker.prototype.setMinGroupSize = function(t) {
this.minGroupSize = t
}, tracking.ColorTracker.prototype.track = function(t, r, n) {
var e = this,
a = this.getColors();
if (!a) throw new Error('Colors not specified, try `new tracking.ColorTracker("magenta")`.');
var i = [];
a.forEach(function(a) {
i = i.concat(e.trackColor_(t, r, n, a))
}), this.emit("track", {
data: i
})
}, tracking.ColorTracker.prototype.trackColor_ = function(n, e, a, i) {
var o, c, s, g, h, k = tracking.ColorTracker.knownColors_[i],
f = new Int32Array(n.length >> 2),
u = new Int8Array(n.length),
l = this.getMinGroupSize(),
m = this.getNeighboursForWidth_(e),
d = new Int32Array(n.length),
v = [],
p = -4;
if (!k) return v;
for (var y = 0; y < a; y++)
for (var w = 0; w < e; w++)
if (p += 4, !u[p]) {
for (o = 0, h = -1, d[++h] = p, d[++h] = y, d[++h] = w, u[p] = 1; h >= 0;)
if (s = d[h--], c = d[h--], g = d[h--], k(n[g], n[g + 1], n[g + 2], n[g + 3], g, c, s)) {
f[o++] = s, f[o++] = c;
for (var T = 0; T < m.length; T++) {
var x = g + m[T],
M = c + t[T],
_ = s + r[T];
!u[x] && M >= 0 && M < a && _ >= 0 && _ < e && (d[++h] = x, d[++h] = M, d[++h] = _, u[x] = 1)
}
} if (o >= l) {
var C = this.calculateDimensions_(f, o);
C && (C.color = i, v.push(C))
}
} return this.mergeRectangles_(v)
}, tracking.ColorTracker.registerColor("cyan", function(t, r, n) {
var e = 50,
a = 70,
i = t - 0,
o = r - 255,
c = n - 255;
return r - t >= e && n - t >= a || i * i + o * o + c * c < 6400
}), tracking.ColorTracker.registerColor("magenta", function(t, r, n) {
var e = 50,
a = t - 255,
i = r - 0,
o = n - 255;
return t - r >= e && n - r >= e || a * a + i * i + o * o < 19600
}), tracking.ColorTracker.registerColor("yellow", function(t, r, n) {
var e = 50,
a = t - 255,
i = r - 255,
o = n - 0;
return t - n >= e && r - n >= e || a * a + i * i + o * o < 1e4
});
var t = new Int32Array([-1, -1, 0, 1, 1, 1, 0, -1]),
r = new Int32Array([0, 1, 1, 1, 0, -1, -1, -1])
}(),
function() {
tracking.ObjectTracker = function(t) {
tracking.ObjectTracker.base(this, "constructor"), t && (Array.isArray(t) || (t = [t]), Array.isArray(t) && t
.forEach(function(r, n) {
if ("string" == typeof r && (t[n] = tracking.ViolaJones.classifiers[r]), !t[n]) throw new Error(
'Object classifier not valid, try `new tracking.ObjectTracker("face")`.')
})), this.setClassifiers(t)
}, tracking.inherits(tracking.ObjectTracker, tracking.Tracker), tracking.ObjectTracker.prototype.edgesDensity = .2,
tracking.ObjectTracker.prototype.initialScale = 1, tracking.ObjectTracker.prototype.scaleFactor = 1.25, tracking
.ObjectTracker.prototype.stepSize = 1.5, tracking.ObjectTracker.prototype.getClassifiers = function() {
return this.classifiers
}, tracking.ObjectTracker.prototype.getEdgesDensity = function() {
return this.edgesDensity
}, tracking.ObjectTracker.prototype.getInitialScale = function() {
return this.initialScale
}, tracking.ObjectTracker.prototype.getScaleFactor = function() {
return this.scaleFactor
}, tracking.ObjectTracker.prototype.getStepSize = function() {
return this.stepSize
}, tracking.ObjectTracker.prototype.track = function(t, r, n) {
var e = this,
a = this.getClassifiers();
if (!a) throw new Error('Object classifier not specified, try `new tracking.ObjectTracker("face")`.');
var i = [];
a.forEach(function(a) {
i = i.concat(tracking.ViolaJones.detect(t, r, n, e.getInitialScale(), e.getScaleFactor(), e.getStepSize(), e
.getEdgesDensity(), a))
}), this.emit("track", {
data: i
})
}, tracking.ObjectTracker.prototype.setClassifiers = function(t) {
this.classifiers = t
}, tracking.ObjectTracker.prototype.setEdgesDensity = function(t) {
this.edgesDensity = t
}, tracking.ObjectTracker.prototype.setInitialScale = function(t) {
this.initialScale = t
}, tracking.ObjectTracker.prototype.setScaleFactor = function(t) {
this.scaleFactor = t
}, tracking.ObjectTracker.prototype.setStepSize = function(t) {
this.stepSize = t
}
}(),
function() {
tracking.LandmarksTracker = function() {
tracking.LandmarksTracker.base(this, "constructor")
}, tracking.inherits(tracking.LandmarksTracker, tracking.ObjectTracker), tracking.LandmarksTracker.prototype.track =
function(t, r, n) {
var e = tracking.ViolaJones.classifiers.face,
a = tracking.ViolaJones.detect(t, r, n, this.getInitialScale(), this.getScaleFactor(), this.getStepSize(), this
.getEdgesDensity(), e),
i = tracking.LBF.align(t, r, n, a);
this.emit("track", {
data: {
faces: a,
landmarks: i
}
})
}
}(),
function() {
tracking.LBF = {}, tracking.LBF.Regressor = function(t) {
this.maxNumStages = t, this.rfs = new Array(t), this.models = new Array(t);
for (var r = 0; r < t; r++) this.rfs[r] = new tracking.LBF.RandomForest(r), this.models[r] = tracking.LBF
.RegressorData[r].models;
this.meanShape = tracking.LBF.LandmarksData
}, tracking.LBF.Regressor.prototype.predict = function(t, r, n, e) {
var a = [],
i = [],
o = [],
c = tracking.Matrix.clone(this.meanShape);
a.push({
data: t,
width: r,
height: n
}), o.push(e), i.push(tracking.LBF.projectShapeToBoundingBox_(c, e));
for (var s = 0; s < this.maxNumStages; s++) {
var g = tracking.LBF.Regressor.deriveBinaryFeat(this.rfs[s], a, i, o, c);
this.applyGlobalPrediction(g, this.models[s], i, o)
}
return i[0]
}, tracking.LBF.Regressor.prototype.applyGlobalPrediction = function(t, r, n, e) {
for (var a = 2 * n[0].length, i = new Array(a / 2), o = 0; o < a / 2; o++) i[o] = [0, 0];
for (var o = 0; o < n.length; o++) {
for (var c = 0; c < a; c++) {
for (var s = 0, g = 0, h = 0;
(h = t[o][g].index) != -1; g++) h <= r[c].nr_feature && (s += r[c].data[h - 1] * t[o][g].value);
c < a / 2 ? i[c][0] = s : i[c - a / 2][1] = s
}
var k = tracking.LBF.similarityTransform_(tracking.LBF.unprojectShapeToBoundingBox_(n[o], e[o]), this
.meanShape),
f = (tracking.Matrix.transpose(k[0]), tracking.LBF.unprojectShapeToBoundingBox_(n[o], e[o]));
f = tracking.Matrix.add(f, i), n[o] = tracking.LBF.projectShapeToBoundingBox_(f, e[o])
}
}, tracking.LBF.Regressor.deriveBinaryFeat = function(t, r, n, e, a) {
for (var i = new Array(r.length), o = 0; o < r.length; o++) {
var c = t.maxNumTrees * t.landmarkNum + 1;
i[o] = new Array(c);
for (var s = 0; s < c; s++) i[o][s] = {}
}
for (var g = 1 << t.maxDepth - 1, o = 0; o < r.length; o++) {
for (var h = tracking.LBF.unprojectShapeToBoundingBox_(n[o], e[o]), k = tracking.LBF.similarityTransform_(h, a),
s = 0; s < t.landmarkNum; s++)
for (var f = 0; f < t.maxNumTrees; f++) {
var u = tracking.LBF.Regressor.getCodeFromTree(t.rfs[s][f], r[o], n[o], e[o], k[0], k[1]),
l = s * t.maxNumTrees + f;
i[o][l].index = g * l + u, i[o][l].value = 1
}
i[o][t.landmarkNum * t.maxNumTrees].index = -1, i[o][t.landmarkNum * t.maxNumTrees].value = -1
}
return i
}, tracking.LBF.Regressor.getCodeFromTree = function(t, r, n, e, a, i) {
for (var o = 0, c = 0;;) {
var s = Math.cos(t.nodes[o].feats[0]) * t.nodes[o].feats[2] * t.maxRadioRadius * e.width,
g = Math.sin(t.nodes[o].feats[0]) * t.nodes[o].feats[2] * t.maxRadioRadius * e.height,
h = Math.cos(t.nodes[o].feats[1]) * t.nodes[o].feats[3] * t.maxRadioRadius * e.width,
k = Math.sin(t.nodes[o].feats[1]) * t.nodes[o].feats[3] * t.maxRadioRadius * e.height,
f = a[0][0] * s + a[0][1] * g,
u = a[1][0] * s + a[1][1] * g,
l = Math.floor(f + n[t.landmarkID][0]),
m = Math.floor(u + n[t.landmarkID][1]);
l = Math.max(0, Math.min(l, r.height - 1)), m = Math.max(0, Math.min(m, r.width - 1));
var d = a[0][0] * h + a[0][1] * k,
v = a[1][0] * h + a[1][1] * k,
p = Math.floor(d + n[t.landmarkID][0]),
y = Math.floor(v + n[t.landmarkID][1]);
p = Math.max(0, Math.min(p, r.height - 1)), y = Math.max(0, Math.min(y, r.width - 1));
var w = Math.floor(r.data[m * r.width + l]) - Math.floor(r.data[y * r.width + p]);
if (o = w < t.nodes[o].thresh ? t.nodes[o].cnodes[0] : t.nodes[o].cnodes[1], 1 == t.nodes[o].is_leafnode) {
c = 1;
for (var T = 0; T < t.leafnodes.length; T++) {
if (t.leafnodes[T] == o) return c;
c++
}
return c
}
}
return c
}
}(),
function() {
tracking.LBF.maxNumStages = 4, tracking.LBF.regressor_ = null, tracking.LBF.align = function(t, r, n, e) {
null == tracking.LBF.regressor_ && (tracking.LBF.regressor_ = new tracking.LBF.Regressor(tracking.LBF
.maxNumStages)), t = tracking.Image.grayscale(t, r, n, !1), t = tracking.Image.equalizeHist(t, r, n);
var a = new Array(e.length);
for (var i in e) {
e[i].height = e[i].width;
var o = {};
o.startX = e[i].x, o.startY = e[i].y, o.width = e[i].width, o.height = e[i].height, a[i] = tracking.LBF
.regressor_.predict(t, r, n, o)
}
return a
}, tracking.LBF.unprojectShapeToBoundingBox_ = function(t, r) {
for (var n = new Array(t.length), e = 0; e < t.length; e++) n[e] = [(t[e][0] - r.startX) / r.width, (t[e][1] - r
.startY) / r.height];
return n
}, tracking.LBF.projectShapeToBoundingBox_ = function(t, r) {
for (var n = new Array(t.length), e = 0; e < t.length; e++) n[e] = [t[e][0] * r.width + r.startX, t[e][1] * r
.height + r.startY
];
return n
}, tracking.LBF.similarityTransform_ = function(t, r) {
for (var n = [0, 0], e = [0, 0], a = 0; a < t.length; a++) n[0] += t[a][0], n[1] += t[a][1], e[0] += r[a][0], e[
1] += r[a][1];
n[0] /= t.length, n[1] /= t.length, e[0] /= r.length, e[1] /= r.length;
for (var i = tracking.Matrix.clone(t), o = tracking.Matrix.clone(r), a = 0; a < t.length; a++) i[a][0] -= n[0], i[
a][1] -= n[1], o[a][0] -= e[0], o[a][1] -= e[1];
var c, s, g, h, k = tracking.Matrix.calcCovarMatrix(i);
c = k[0], g = k[1], k = tracking.Matrix.calcCovarMatrix(o), s = k[0], h = k[1];
var f = Math.sqrt(tracking.Matrix.norm(c)),
u = Math.sqrt(tracking.Matrix.norm(s)),
l = f / u;
i = tracking.Matrix.mulScalar(1 / f, i), o = tracking.Matrix.mulScalar(1 / u, o);
for (var m = 0, d = 0, a = 0; a < t.length; a++) m = m + i[a][1] * o[a][0] - i[a][0] * o[a][1], d = d + i[a][0] *
o[a][0] + i[a][1] * o[a][1];
var v = Math.sqrt(m * m + d * d),
p = m / v,
y = d / v,
w = [
[y, -p],
[p, y]
];
return [w, l]
}, tracking.LBF.RandomForest = function(t) {
this.maxNumTrees = tracking.LBF.RegressorData[t].max_numtrees, this.landmarkNum = tracking.LBF.RegressorData[t]
.num_landmark, this.maxDepth = tracking.LBF.RegressorData[t].max_depth, this.stages = tracking.LBF
.RegressorData[t].stages, this.rfs = new Array(this.landmarkNum);
for (var r = 0; r < this.landmarkNum; r++) {
this.rfs[r] = new Array(this.maxNumTrees);
for (var n = 0; n < this.maxNumTrees; n++) this.rfs[r][n] = new tracking.LBF.Tree(t, r, n)
}
}, tracking.LBF.Tree = function(t, r, n) {
var e = tracking.LBF.RegressorData[t].landmarks[r][n];
this.maxDepth = e.max_depth, this.maxNumNodes = e.max_numnodes, this.nodes = e.nodes, this.landmarkID = e
.landmark_id, this.numLeafnodes = e.num_leafnodes, this.numNodes = e.num_nodes, this.maxNumFeats = e
.max_numfeats, this.maxRadioRadius = e.max_radio_radius, this.leafnodes = e.id_leafnodes
}
}();