forked from benpryke/BPTLD
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Fern.cpp
91 lines (70 loc) · 2.69 KB
/
Fern.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/* Copyright 2011 Ben Pryke.
This file is part of Ben Pryke's TLD Implementation available under the
terms of the GNU General Public License as published by the Free Software
Foundation. This software is provided without warranty of ANY kind. */
#include "Fern.h"
Fern::Fern(int nodeNum, float minScale, float maxScale) {
nodeCount = nodeNum;
int leafNodes = (int)pow(2.0f * (float)POWER, nodeCount);
p = new int[leafNodes];
n = new int[leafNodes];
posteriors = new float[leafNodes];
nodes = new TwoBitBPTest*[nodeCount];
// Initialise the features
for (int i = 0; i < nodeCount; i++) {
nodes[i] = new TwoBitBPTest(minScale, maxScale);
}
// Initialise p, n, and posteriors
for (int i = 0; i < leafNodes; i++) {
p[i] = n[i] = 0;
posteriors[i] = 0.0f;
}
}
int Fern::getLeafIndex(IntegralImage *image, int patchX, int patchY, int patchW, int patchH) {
// Limit patch to image area
int width = image->getWidth();
int height = image->getHeight();
// Clamp x and y values between 0 and width and height respectively
patchX = std::max(std::min(patchX, width - 2), 0);
patchY = std::max(std::min(patchY, height - 2), 0);
// Limit width and height values to (width - patchX) and (height - patchY)
// respectively
patchW = std::min(patchW, width - patchX);
patchH = std::min(patchH, height - patchY);
// Apply all tests to find the leaf index this patch falls into
int leaf = 0;
for (int i = 0; i < nodeCount; i++) {
leaf = leaf | (nodes[i]->test(image, patchX, patchY, patchW, patchH) << i * (int)POWER);
}
return leaf;
}
void Fern::train(IntegralImage *image, int patchX, int patchY, int patchW, int patchH, int patchClass) {
// Apply all tests to find the leaf index this patch falls into
int leaf = getLeafIndex(image, patchX, patchY, patchW, patchH);
// Increment the number of positive or negative patches that fell into
// this leaf
if (patchClass == 0) {
n[leaf]++;
}
else {
p[leaf]++;
}
// Compute the posterior likelihood of a positive class for this leaf
if (p[leaf] > 0) {
posteriors[leaf] = (float)p[leaf] / (float)(p[leaf] + n[leaf]);
}
}
float Fern::classify(IntegralImage *image, int patchX, int patchY, int patchW, int patchH) {
// Return the precomputed posterior likelihood of a positive class for
// this leaf
return posteriors[getLeafIndex(image, patchX, patchY, patchW, patchH)];
}
Fern::~Fern() {
for (int i = 0; i < nodeCount; i++) {
delete nodes[i];
}
delete [] nodes;
delete [] p;
delete [] n;
delete [] posteriors;
}