Bug Summary

File:ccv_tld.c
Warning:line 959, column 44
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ccv_tld.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -menable-no-infs -menable-no-nans -fapprox-func -funsafe-math-optimizations -fno-signed-zeros -mreassociate -freciprocal-math -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -complex-range=basic -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +sse2 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/liu/actions-runner/_work/ccv/ccv/lib -fcoverage-compilation-dir=/home/liu/actions-runner/_work/ccv/ccv/lib -resource-dir /usr/local/lib/clang/19 -I . -I /usr/local/cuda/include -D HAVE_CBLAS -D HAVE_LIBPNG -D HAVE_LIBJPEG -D HAVE_FFTW3 -D HAVE_PTHREAD -D HAVE_LIBLINEAR -D HAVE_TESSERACT -D HAVE_AVCODEC -D HAVE_AVFORMAT -D HAVE_AVUTIL -D HAVE_SWSCALE -D HAVE_SSE2 -D HAVE_GSL -D HAVE_CUDA -D HAVE_CUDNN -D HAVE_NCCL -D USE_SYSTEM_CUB -I /usr/local/include -internal-isystem /usr/local/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/liu/actions-runner/_work/ccv/ccv/_analyze/2024-12-11-002137-427142-1 -x c ccv_tld.c
1#include "ccv.h"
2#include "ccv_internal.h"
3#include "3rdparty/sfmt/SFMT.h"
4#include "3rdparty/dsfmt/dSFMT.h"
5
6const ccv_tld_param_t ccv_tld_default_params = {
7 .win_size = {
8 15,
9 15,
10 },
11 .level = 5,
12 .min_forward_backward_error = 100,
13 .min_eigen = 0.025,
14 .min_win = 20,
15 .interval = 3,
16 .shift = 0.1,
17 .top_n = 100,
18 .rotation = 0,
19 .include_overlap = 0.7,
20 .exclude_overlap = 0.2,
21 .structs = 40,
22 .features = 18,
23 .validate_set = 0.5,
24 .nnc_same = 0.95,
25 .nnc_thres = 0.65,
26 .nnc_verify = 0.7,
27 .nnc_beyond = 0.8,
28 .nnc_collect = 0.5,
29 .bad_patches = 100,
30 .new_deform = 20,
31 .track_deform = 10,
32 .new_deform_angle = 20,
33 .track_deform_angle = 10,
34 .new_deform_scale = 0.02,
35 .track_deform_scale = 0.02,
36 .new_deform_shift = 0.02,
37 .track_deform_shift = 0.02,
38};
39
40#define TLD_GRID_SPARSITY(10) (10)
41#define TLD_PATCH_SIZE(10) (10)
42
43static CCV_IMPLEMENT_MEDIAN(_ccv_tld_median, float)float _ccv_tld_median(float* buf, int low, int high) { float w
; int middle, ll, hh; int median = (low + high) / 2; for (;;)
{ if (high <= low) return buf[median]; if (high == low + 1
) { if (buf[low] > buf[high]) ((w) = (buf[low]), (buf[low]
) = (buf[high]), (buf[high]) = (w)); return buf[median]; } middle
= (low + high) / 2; if (buf[middle] > buf[high]) ((w) = (
buf[middle]), (buf[middle]) = (buf[high]), (buf[high]) = (w))
; if (buf[low] > buf[high]) ((w) = (buf[low]), (buf[low]) =
(buf[high]), (buf[high]) = (w)); if (buf[middle] > buf[low
]) ((w) = (buf[middle]), (buf[middle]) = (buf[low]), (buf[low
]) = (w)); ((w) = (buf[middle]), (buf[middle]) = (buf[low + 1
]), (buf[low + 1]) = (w)); ll = low + 1; hh = high; for (;;) {
do ll++; while (buf[low] > buf[ll]); do hh--; while (buf[
hh] > buf[low]); if (hh < ll) break; ((w) = (buf[ll]), (
buf[ll]) = (buf[hh]), (buf[hh]) = (w)); } ((w) = (buf[low]), (
buf[low]) = (buf[hh]), (buf[hh]) = (w)); if (hh <= median)
low = ll; else if (hh >= median) high = hh - 1; } }
44
45static float _ccv_tld_norm_cross_correlate(ccv_dense_matrix_t* r0, ccv_dense_matrix_t* r1)
46{
47 assert(CCV_GET_CHANNEL(r0->type) == CCV_C1 && CCV_GET_DATA_TYPE(r0->type) == CCV_8U)((void) sizeof ((((r0->type) & 0xFFF) == CCV_C1 &&
((r0->type) & 0xFF000) == CCV_8U) ? 1 : 0), __extension__
({ if (((r0->type) & 0xFFF) == CCV_C1 && ((r0
->type) & 0xFF000) == CCV_8U) ; else __assert_fail ("CCV_GET_CHANNEL(r0->type) == CCV_C1 && CCV_GET_DATA_TYPE(r0->type) == CCV_8U"
, "ccv_tld.c", 47, __extension__ __PRETTY_FUNCTION__); }))
;
48 assert(CCV_GET_CHANNEL(r1->type) == CCV_C1 && CCV_GET_DATA_TYPE(r1->type) == CCV_8U)((void) sizeof ((((r1->type) & 0xFFF) == CCV_C1 &&
((r1->type) & 0xFF000) == CCV_8U) ? 1 : 0), __extension__
({ if (((r1->type) & 0xFFF) == CCV_C1 && ((r1
->type) & 0xFF000) == CCV_8U) ; else __assert_fail ("CCV_GET_CHANNEL(r1->type) == CCV_C1 && CCV_GET_DATA_TYPE(r1->type) == CCV_8U"
, "ccv_tld.c", 48, __extension__ __PRETTY_FUNCTION__); }))
;
49 assert(r0->rows == r1->rows && r0->cols == r1->cols)((void) sizeof ((r0->rows == r1->rows && r0->
cols == r1->cols) ? 1 : 0), __extension__ ({ if (r0->rows
== r1->rows && r0->cols == r1->cols) ; else
__assert_fail ("r0->rows == r1->rows && r0->cols == r1->cols"
, "ccv_tld.c", 49, __extension__ __PRETTY_FUNCTION__); }))
;
50 int x, y;
51 int sum0 = 0, sum1 = 0;
52 unsigned char* r0_ptr = r0->data.u8;
53 unsigned char* r1_ptr = r1->data.u8;
54 for (y = 0; y < r0->rows; y++)
55 {
56 for (x = 0; x < r0->cols; x++)
57 {
58 sum0 += r0_ptr[x];
59 sum1 += r1_ptr[x];
60 }
61 r0_ptr += r0->step;
62 r1_ptr += r1->step;
63 }
64 r0_ptr = r0->data.u8;
65 r1_ptr = r1->data.u8;
66 float mr0 = (float)sum0 / (r0->rows * r0->cols);
67 float mr1 = (float)sum1 / (r1->rows * r1->cols);
68 float r0r1 = 0, r0r0 = 0, r1r1 = 0;
69 for (y = 0; y < r0->rows; y++)
70 {
71 for (x = 0; x < r0->cols; x++)
72 {
73 float r0f = r0_ptr[x] - mr0;
74 float r1f = r1_ptr[x] - mr1;
75 r0r1 += r0f * r1f;
76 r0r0 += r0f * r0f;
77 r1r1 += r1f * r1f;
78 }
79 r0_ptr += r0->step;
80 r1_ptr += r1->step;
81 }
82 if (r0r0 * r1r1 < 1e-6)
83 return 0;
84 return r0r1 / sqrtf(r0r0 * r1r1);
85}
86
87static ccv_rect_t _ccv_tld_short_term_track(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b, ccv_rect_t box, ccv_tld_param_t params)
88{
89 ccv_rect_t newbox = ccv_rect(0, 0, 0, 0);
90 ccv_array_t* point_a = ccv_array_new(sizeof(ccv_decimal_point_t), (TLD_GRID_SPARSITY(10) - 1) * (TLD_GRID_SPARSITY(10) - 1), 0);
91 float gapx = (float)box.width / TLD_GRID_SPARSITY(10);
92 float gapy = (float)box.height / TLD_GRID_SPARSITY(10);
93 float x, y;
94 for (x = gapx * 0.5; x < box.width; x += gapx)
95 for (y = gapy * 0.5; y < box.height; y += gapy)
96 {
97 ccv_decimal_point_t point = ccv_decimal_point(box.x + x, box.y + y);
98 ccv_array_push(point_a, &point);
99 }
100 if (point_a->rnum <= 0)
101 {
102 ccv_array_free(point_a);
103 return newbox;
104 }
105 ccv_array_t* point_b = 0;
106 ccv_optical_flow_lucas_kanade(a, b, point_a, &point_b, params.win_size, params.level, params.min_eigen);
107 if (point_b->rnum <= 0)
108 {
109 ccv_array_free(point_b);
110 ccv_array_free(point_a);
111 return newbox;
112 }
113 ccv_array_t* point_c = 0;
114 ccv_optical_flow_lucas_kanade(b, a, point_b, &point_c, params.win_size, params.level, params.min_eigen);
115 // compute forward-backward error
116 ccv_dense_matrix_t* r0 = (ccv_dense_matrix_t*)alloca(ccv_compute_dense_matrix_size(TLD_PATCH_SIZE, TLD_PATCH_SIZE, CCV_8U | CCV_C1))__builtin_alloca ((((sizeof(ccv_dense_matrix_t) + 63) & -
64) + ((((10)) * _ccv_get_data_type_size[((CCV_8U | CCV_C1) &
0xFF000) >> 12] * ((CCV_8U | CCV_C1) & 0xFFF) + 3)
& -4) * ((10))))
;
117 ccv_dense_matrix_t* r1 = (ccv_dense_matrix_t*)alloca(ccv_compute_dense_matrix_size(TLD_PATCH_SIZE, TLD_PATCH_SIZE, CCV_8U | CCV_C1))__builtin_alloca ((((sizeof(ccv_dense_matrix_t) + 63) & -
64) + ((((10)) * _ccv_get_data_type_size[((CCV_8U | CCV_C1) &
0xFF000) >> 12] * ((CCV_8U | CCV_C1) & 0xFFF) + 3)
& -4) * ((10))))
;
118 r0 = ccv_dense_matrix_new(TLD_PATCH_SIZE(10), TLD_PATCH_SIZE(10), CCV_8U | CCV_C1, r0, 0);
119 r1 = ccv_dense_matrix_new(TLD_PATCH_SIZE(10), TLD_PATCH_SIZE(10), CCV_8U | CCV_C1, r1, 0);
120 int i, j, k, size;
121 int* wrt = (int*)alloca(sizeof(int) * point_a->rnum)__builtin_alloca (sizeof(int) * point_a->rnum);
122 { // will reclaim the stack
123 float* fberr = (float*)alloca(sizeof(float) * point_a->rnum)__builtin_alloca (sizeof(float) * point_a->rnum);
124 float* sim = (float*)alloca(sizeof(float) * point_a->rnum)__builtin_alloca (sizeof(float) * point_a->rnum);
125 for (i = 0, k = 0; i < point_a->rnum; i++)
126 {
127 ccv_decimal_point_t* p0 = (ccv_decimal_point_t*)ccv_array_get(point_a, i)((void*)(((char*)((point_a)->data)) + (size_t)(point_a)->
rsize * (size_t)(i)))
;
128 ccv_decimal_point_with_status_t* p1 = (ccv_decimal_point_with_status_t*)ccv_array_get(point_b, i)((void*)(((char*)((point_b)->data)) + (size_t)(point_b)->
rsize * (size_t)(i)))
;
129 ccv_decimal_point_with_status_t* p2 = (ccv_decimal_point_with_status_t*)ccv_array_get(point_c, i)((void*)(((char*)((point_c)->data)) + (size_t)(point_c)->
rsize * (size_t)(i)))
;
130 if (p1->status && p2->status &&
131 p1->point.x >= 0 && p1->point.x < a->cols && p1->point.y >= 0 && p1->point.y < a->rows &&
132 p2->point.x >= 0 && p2->point.x < a->cols && p2->point.y >= 0 && p2->point.y < a->rows)
133 {
134 fberr[k] = (p2->point.x - p0->x) * (p2->point.x - p0->x) + (p2->point.y - p0->y) * (p2->point.y - p0->y);
135 ccv_decimal_slice(a, &r0, 0, p0->y - (TLD_PATCH_SIZE(10) - 1) * 0.5, p0->x - (TLD_PATCH_SIZE(10) - 1) * 0.5, TLD_PATCH_SIZE(10), TLD_PATCH_SIZE(10));
136 ccv_decimal_slice(b, &r1, 0, p1->point.y - (TLD_PATCH_SIZE(10) - 1) * 0.5, p1->point.x - (TLD_PATCH_SIZE(10) - 1) * 0.5, TLD_PATCH_SIZE(10), TLD_PATCH_SIZE(10));
137 sim[k] = _ccv_tld_norm_cross_correlate(r0, r1);
138 wrt[k] = i;
139 ++k;
140 }
141 }
142 ccv_array_free(point_c);
143 if (k == 0)
144 {
145 // early termination because we don't have qualified tracking points
146 ccv_array_free(point_b);
147 ccv_array_free(point_a);
148 return newbox;
149 }
150 size = k;
151 float simmd = _ccv_tld_median(sim, 0, size - 1);
152 for (i = 0, k = 0; i < size; i++)
153 if (sim[i] > simmd)
154 {
155 fberr[k] = fberr[i];
156 wrt[k] = wrt[i];
157 ++k;
158 }
159 size = k;
160 float fberrmd = _ccv_tld_median(fberr, 0, size - 1);
161 if (fberrmd >= params.min_forward_backward_error)
162 {
163 // early termination because we don't have qualified tracking points
164 ccv_array_free(point_b);
165 ccv_array_free(point_a);
166 return newbox;
167 }
168 size = k;
169 for (i = 0, k = 0; i < size; i++)
170 if (fberr[i] <= fberrmd)
171 wrt[k++] = wrt[i];
172 size = k;
173 if (k == 0)
174 {
175 // early termination because we don't have qualified tracking points
176 ccv_array_free(point_b);
177 ccv_array_free(point_a);
178 return newbox;
179 }
180 } // reclaim stack
181 float dx, dy;
182 { // will reclaim the stack
183 float* offx = (float*)alloca(sizeof(float) * size)__builtin_alloca (sizeof(float) * size);
184 float* offy = (float*)alloca(sizeof(float) * size)__builtin_alloca (sizeof(float) * size);
185 for (i = 0; i < size; i++)
186 {
187 ccv_decimal_point_t* p0 = (ccv_decimal_point_t*)ccv_array_get(point_a, wrt[i])((void*)(((char*)((point_a)->data)) + (size_t)(point_a)->
rsize * (size_t)(wrt[i])))
;
188 ccv_decimal_point_t* p1 = (ccv_decimal_point_t*)ccv_array_get(point_b, wrt[i])((void*)(((char*)((point_b)->data)) + (size_t)(point_b)->
rsize * (size_t)(wrt[i])))
;
189 offx[i] = p1->x - p0->x;
190 offy[i] = p1->y - p0->y;
191 }
192 dx = _ccv_tld_median(offx, 0, size - 1);
193 dy = _ccv_tld_median(offy, 0, size - 1);
194 } // reclaim stack
195 if (size > 1)
196 {
197 float* s = (float*)alloca(sizeof(float) * size * (size - 1) / 2)__builtin_alloca (sizeof(float) * size * (size - 1) / 2);
198 k = 0;
199 for (i = 0; i < size - 1; i++)
200 {
201 ccv_decimal_point_t* p0i = (ccv_decimal_point_t*)ccv_array_get(point_a, wrt[i])((void*)(((char*)((point_a)->data)) + (size_t)(point_a)->
rsize * (size_t)(wrt[i])))
;
202 ccv_decimal_point_t* p1i = (ccv_decimal_point_t*)ccv_array_get(point_b, wrt[i])((void*)(((char*)((point_b)->data)) + (size_t)(point_b)->
rsize * (size_t)(wrt[i])))
;
203 for (j = i + 1; j < size; j++)
204 {
205 ccv_decimal_point_t* p0j = (ccv_decimal_point_t*)ccv_array_get(point_a, wrt[j])((void*)(((char*)((point_a)->data)) + (size_t)(point_a)->
rsize * (size_t)(wrt[j])))
;
206 ccv_decimal_point_t* p1j = (ccv_decimal_point_t*)ccv_array_get(point_b, wrt[j])((void*)(((char*)((point_b)->data)) + (size_t)(point_b)->
rsize * (size_t)(wrt[j])))
;
207 s[k] = sqrtf(((p1i->x - p1j->x) * (p1i->x - p1j->x) + (p1i->y - p1j->y) * (p1i->y - p1j->y)) /
208 ((p0i->x - p0j->x) * (p0i->x - p0j->x) + (p0i->y - p0j->y) * (p0i->y - p0j->y)));
209 ++k;
210 }
211 }
212 assert(size * (size - 1) / 2 == k)((void) sizeof ((size * (size - 1) / 2 == k) ? 1 : 0), __extension__
({ if (size * (size - 1) / 2 == k) ; else __assert_fail ("size * (size - 1) / 2 == k"
, "ccv_tld.c", 212, __extension__ __PRETTY_FUNCTION__); }))
;
213 float ds = _ccv_tld_median(s, 0, size * (size - 1) / 2 - 1);
214 newbox.x = (int)(box.x + dx - box.width * (ds - 1.0) * 0.5 + 0.5);
215 newbox.y = (int)(box.y + dy - box.height * (ds - 1.0) * 0.5 + 0.5);
216 newbox.width = (int)(box.width * ds + 0.5);
217 newbox.height = (int)(box.height * ds + 0.5);
218 } else {
219 newbox.width = box.width;
220 newbox.height = box.height;
221 newbox.x = (int)(box.x + dx + 0.5);
222 newbox.y = (int)(box.y + dy + 0.5);
223 }
224 ccv_array_free(point_b);
225 ccv_array_free(point_a);
226 return newbox;
227}
228
229static inline float _ccv_tld_rect_intersect(const ccv_rect_t r1, const ccv_rect_t r2)
230{
231 int intersect = ccv_max(0, ccv_min(r1.x + r1.width, r2.x + r2.width) - ccv_max(r1.x, r2.x))({ typeof (0) _a = (0); typeof (({ typeof (r1.x + r1.width) _a
= (r1.x + r1.width); typeof (r2.x + r2.width) _b = (r2.x + r2
.width); (_a < _b) ? _a : _b; }) - ({ typeof (r1.x) _a = (
r1.x); typeof (r2.x) _b = (r2.x); (_a > _b) ? _a : _b; }))
_b = (({ typeof (r1.x + r1.width) _a = (r1.x + r1.width); typeof
(r2.x + r2.width) _b = (r2.x + r2.width); (_a < _b) ? _a :
_b; }) - ({ typeof (r1.x) _a = (r1.x); typeof (r2.x) _b = (r2
.x); (_a > _b) ? _a : _b; })); (_a > _b) ? _a : _b; })
* ccv_max(0, ccv_min(r1.y + r1.height, r2.y + r2.height) - ccv_max(r1.y, r2.y))({ typeof (0) _a = (0); typeof (({ typeof (r1.y + r1.height) _a
= (r1.y + r1.height); typeof (r2.y + r2.height) _b = (r2.y +
r2.height); (_a < _b) ? _a : _b; }) - ({ typeof (r1.y) _a
= (r1.y); typeof (r2.y) _b = (r2.y); (_a > _b) ? _a : _b;
})) _b = (({ typeof (r1.y + r1.height) _a = (r1.y + r1.height
); typeof (r2.y + r2.height) _b = (r2.y + r2.height); (_a <
_b) ? _a : _b; }) - ({ typeof (r1.y) _a = (r1.y); typeof (r2
.y) _b = (r2.y); (_a > _b) ? _a : _b; })); (_a > _b) ? _a
: _b; })
;
232 return (float)intersect / (r1.width * r1.height + r2.width * r2.height - intersect);
233}
234
235#define for_each_size(new_width, new_height, box_width, box_height, interval, image_width, image_height){ double scale235 = pow(2.0, 1.0 / (interval + 1.0)); int scale_upto235
= (int)(log((double)({ typeof ((double)image_width / box_width
) _a = ((double)image_width / box_width); typeof ((double)image_height
/ box_height) _b = ((double)image_height / box_height); (_a <
_b) ? _a : _b; })) / log(scale235)); int s235; double ss235 =
1.0; for (s235 = 0; s235 < scale_upto235; s235++) { int new_width
= (int)(box_width * ss235 + 0.5); int new_height = (int)(box_height
* ss235 + 0.5); ss235 *= scale235; if (new_width > image_width
|| new_height > image_height) break;
\
236 { \
237 double INTERNAL_CATCH_UNIQUE_NAME(scale)scale237 = pow(2.0, 1.0 / (interval + 1.0)); \
238 int INTERNAL_CATCH_UNIQUE_NAME(scale_upto)scale_upto238 = (int)(log((double)ccv_min((double)image_width / box_width, (double)image_height / box_height)({ typeof ((double)image_width / box_width) _a = ((double)image_width
/ box_width); typeof ((double)image_height / box_height) _b =
((double)image_height / box_height); (_a < _b) ? _a : _b;
})
) / log(INTERNAL_CATCH_UNIQUE_NAME(scale)scale238)); \
239 int INTERNAL_CATCH_UNIQUE_NAME(s)s239; \
240 double INTERNAL_CATCH_UNIQUE_NAME(ss)ss240 = 1.0; \
241 for (INTERNAL_CATCH_UNIQUE_NAME(s)s241 = 0; INTERNAL_CATCH_UNIQUE_NAME(s)s241 < INTERNAL_CATCH_UNIQUE_NAME(scale_upto)scale_upto241; INTERNAL_CATCH_UNIQUE_NAME(s)s241++) \
242 { \
243 int new_width = (int)(box_width * INTERNAL_CATCH_UNIQUE_NAME(ss)ss243 + 0.5); \
244 int new_height = (int)(box_height * INTERNAL_CATCH_UNIQUE_NAME(ss)ss244 + 0.5); \
245 INTERNAL_CATCH_UNIQUE_NAME(ss)ss245 *= INTERNAL_CATCH_UNIQUE_NAME(scale)scale245; \
246 if (new_width > image_width || new_height > image_height) \
247 break;
248#define end_for_each_size} } } }
249
250#define for_each_box(new_comp, box_width, box_height, interval, shift, image_width, image_height){ { double scale250 = pow(2.0, 1.0 / (interval + 1.0)); int scale_upto250
= (int)(log((double)({ typeof ((double)image_width / box_width
) _a = ((double)image_width / box_width); typeof ((double)image_height
/ box_height) _b = ((double)image_height / box_height); (_a <
_b) ? _a : _b; })) / log(scale250)); int s250; double ss250 =
1.0; for (s250 = 0; s250 < scale_upto250; s250++) { int width250
= (int)(box_width * ss250 + 0.5); int height250 = (int)(box_height
* ss250 + 0.5); ss250 *= scale250; if (width250 > image_width
|| height250 > image_height) break; float x250, y250; int
min_side250 = ({ typeof (width250) _a = (width250); typeof (
height250) _b = (height250); (_a < _b) ? _a : _b; }); int piy250
= -1; for (y250 = 0; y250 < image_height - height250 - 0.5
; y250 += shift * min_side250) { int iy250 = (int)(y250 + 0.5
); if (iy250 == piy250) continue; piy250 = iy250; int pix250 =
-1; for (x250 = 0; x250 < image_width - width250 - 0.5; x250
+= shift * min_side250) { int ix250 = (int)(x250 + 0.5); if (
ix250 == pix250) continue; pix250 = ix250; ccv_comp_t new_comp
; new_comp.rect = ccv_rect(ix250, iy250, width250, height250)
; new_comp.classification.id = s250;
\
251 { \
252 for_each_size(INTERNAL_CATCH_UNIQUE_NAME(width), INTERNAL_CATCH_UNIQUE_NAME(height), box_width, box_height, interval, image_width, image_height){ double scale252 = pow(2.0, 1.0 / (interval + 1.0)); int scale_upto252
= (int)(log((double)({ typeof ((double)image_width / box_width
) _a = ((double)image_width / box_width); typeof ((double)image_height
/ box_height) _b = ((double)image_height / box_height); (_a <
_b) ? _a : _b; })) / log(scale252)); int s252; double ss252 =
1.0; for (s252 = 0; s252 < scale_upto252; s252++) { int width252
= (int)(box_width * ss252 + 0.5); int height252 = (int)(box_height
* ss252 + 0.5); ss252 *= scale252; if (width252 > image_width
|| height252 > image_height) break;
\
253 float INTERNAL_CATCH_UNIQUE_NAME(x)x253, INTERNAL_CATCH_UNIQUE_NAME(y)y253; \
254 int INTERNAL_CATCH_UNIQUE_NAME(min_side)min_side254 = ccv_min(INTERNAL_CATCH_UNIQUE_NAME(width), INTERNAL_CATCH_UNIQUE_NAME(height))({ typeof (width254) _a = (width254); typeof (height254) _b =
(height254); (_a < _b) ? _a : _b; })
; \
255 int INTERNAL_CATCH_UNIQUE_NAME(piy)piy255 = -1; \
256 for (INTERNAL_CATCH_UNIQUE_NAME(y)y256 = 0; \
257 INTERNAL_CATCH_UNIQUE_NAME(y)y257 < image_height - INTERNAL_CATCH_UNIQUE_NAME(height)height257 - 0.5; \
258 INTERNAL_CATCH_UNIQUE_NAME(y)y258 += shift * INTERNAL_CATCH_UNIQUE_NAME(min_side)min_side258) /* min_side is exposed by for_each_size, and because the ubiquity of this macro, its name gets leaked */ \
259 { \
260 int INTERNAL_CATCH_UNIQUE_NAME(iy)iy260 = (int)(INTERNAL_CATCH_UNIQUE_NAME(y)y260 + 0.5); \
261 if (INTERNAL_CATCH_UNIQUE_NAME(iy)iy261 == INTERNAL_CATCH_UNIQUE_NAME(piy)piy261) \
262 continue; \
263 INTERNAL_CATCH_UNIQUE_NAME(piy)piy263 = INTERNAL_CATCH_UNIQUE_NAME(iy)iy263; \
264 int INTERNAL_CATCH_UNIQUE_NAME(pix)pix264 = -1; \
265 for (INTERNAL_CATCH_UNIQUE_NAME(x)x265 = 0; \
266 INTERNAL_CATCH_UNIQUE_NAME(x)x266 < image_width - INTERNAL_CATCH_UNIQUE_NAME(width)width266 - 0.5; \
267 INTERNAL_CATCH_UNIQUE_NAME(x)x267 += shift * INTERNAL_CATCH_UNIQUE_NAME(min_side)min_side267) \
268 { \
269 int INTERNAL_CATCH_UNIQUE_NAME(ix)ix269 = (int)(INTERNAL_CATCH_UNIQUE_NAME(x)x269 + 0.5); \
270 if (INTERNAL_CATCH_UNIQUE_NAME(ix)ix270 == INTERNAL_CATCH_UNIQUE_NAME(pix)pix270) \
271 continue; \
272 INTERNAL_CATCH_UNIQUE_NAME(pix)pix272 = INTERNAL_CATCH_UNIQUE_NAME(ix)ix272; \
273 ccv_comp_t new_comp; \
274 new_comp.rect = ccv_rect(INTERNAL_CATCH_UNIQUE_NAME(ix)ix274, INTERNAL_CATCH_UNIQUE_NAME(iy)iy274, INTERNAL_CATCH_UNIQUE_NAME(width)width274, INTERNAL_CATCH_UNIQUE_NAME(height)height274); \
275 new_comp.classification.id = INTERNAL_CATCH_UNIQUE_NAME(s)s275;
276#define end_for_each_box} } } } } } } end_for_each_size} } }
277
278static void _ccv_tld_box_percolate_down(ccv_array_t* good, int i)
279{
280 for (;;)
281 {
282 int left = 2 * (i + 1) - 1;
283 int right = 2 * (i + 1);
284 int smallest = i;
285 ccv_comp_t* smallest_comp = (ccv_comp_t*)ccv_array_get(good, smallest)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(smallest)))
;
286 if (left < good->rnum)
287 {
288 ccv_comp_t* left_comp = (ccv_comp_t*)ccv_array_get(good, left)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(left)))
;
289 if (left_comp->classification.confidence < smallest_comp->classification.confidence)
290 smallest = left;
291 }
292 if (right < good->rnum)
293 {
294 ccv_comp_t* right_comp = (ccv_comp_t*)ccv_array_get(good, right)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(right)))
;
295 if (right_comp->classification.confidence < smallest_comp->classification.confidence)
296 smallest = right;
297 }
298 if (smallest == i)
299 break;
300 ccv_comp_t c = *(ccv_comp_t*)ccv_array_get(good, smallest)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(smallest)))
;
301 *(ccv_comp_t*)ccv_array_get(good, smallest)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(smallest)))
= *(ccv_comp_t*)ccv_array_get(good, i)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(i)))
;
302 *(ccv_comp_t*)ccv_array_get(good, i)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(i)))
= c;
303 i = smallest;
304 }
305}
306
307static void _ccv_tld_box_percolate_up(ccv_array_t* good, int smallest)
308{
309 for (;;)
310 {
311 int one = smallest;
312 int parent = (smallest + 1) / 2 - 1;
313 if (parent < 0)
314 break;
315 ccv_comp_t* parent_comp = (ccv_comp_t*)ccv_array_get(good, parent)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(parent)))
;
316 ccv_comp_t* smallest_comp = (ccv_comp_t*)ccv_array_get(good, smallest)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(smallest)))
;
317 if (smallest_comp->classification.confidence < parent_comp->classification.confidence)
318 {
319 smallest = parent;
320 smallest_comp = parent_comp;
321 }
322 // if current one is no smaller than the parent one, stop
323 if (smallest == one)
324 break;
325 ccv_comp_t c = *(ccv_comp_t*)ccv_array_get(good, smallest)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(smallest)))
;
326 *(ccv_comp_t*)ccv_array_get(good, smallest)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(smallest)))
= *(ccv_comp_t*)ccv_array_get(good, one)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(one)))
;
327 *(ccv_comp_t*)ccv_array_get(good, one)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(one)))
= c;
328 int other = 2 * (parent + 1) - !(one & 1);
329 if (other < good->rnum)
330 {
331 ccv_comp_t* other_comp = (ccv_comp_t*)ccv_array_get(good, other)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(other)))
;
332 // if current one is no smaller than the other one, stop, and this requires a percolating down
333 if (other_comp->classification.confidence < smallest_comp->classification.confidence)
334 break;
335 }
336 }
337 // have to percolating down to avoid it is bigger than the other side of the sub-tree
338 _ccv_tld_box_percolate_down(good, smallest);
339}
340
341static ccv_comp_t _ccv_tld_generate_box_for(ccv_size_t image_size, ccv_size_t input_size, ccv_rect_t box, int gcap, ccv_array_t** good, ccv_array_t** bad, ccv_tld_param_t params)
342{
343 assert(gcap > 0)((void) sizeof ((gcap > 0) ? 1 : 0), __extension__ ({ if (
gcap > 0) ; else __assert_fail ("gcap > 0", "ccv_tld.c"
, 343, __extension__ __PRETTY_FUNCTION__); }))
;
344 ccv_array_t* agood = *good = ccv_array_new(sizeof(ccv_comp_t), gcap, 0);
345 ccv_array_t* abad = *bad = ccv_array_new(sizeof(ccv_comp_t), 64, 0);
346 double max_overlap = -DBL_MAX1.7976931348623157e+308;
347 ccv_comp_t best_box = {
348 .classification = {
349 .id = 0,
350 },
351 .rect = ccv_rect(0, 0, 0, 0),
352 };
353 int i = 0;
354 for_each_box(comp, input_size.width, input_size.height, params.interval, params.shift, image_size.width, image_size.height){ { double scale354 = pow(2.0, 1.0 / (params.interval + 1.0))
; int scale_upto354 = (int)(log((double)({ typeof ((double)image_size
.width / input_size.width) _a = ((double)image_size.width / input_size
.width); typeof ((double)image_size.height / input_size.height
) _b = ((double)image_size.height / input_size.height); (_a <
_b) ? _a : _b; })) / log(scale354)); int s354; double ss354 =
1.0; for (s354 = 0; s354 < scale_upto354; s354++) { int width354
= (int)(input_size.width * ss354 + 0.5); int height354 = (int
)(input_size.height * ss354 + 0.5); ss354 *= scale354; if (width354
> image_size.width || height354 > image_size.height) break
; float x354, y354; int min_side354 = ({ typeof (width354) _a
= (width354); typeof (height354) _b = (height354); (_a < _b
) ? _a : _b; }); int piy354 = -1; for (y354 = 0; y354 < image_size
.height - height354 - 0.5; y354 += params.shift * min_side354
) { int iy354 = (int)(y354 + 0.5); if (iy354 == piy354) continue
; piy354 = iy354; int pix354 = -1; for (x354 = 0; x354 < image_size
.width - width354 - 0.5; x354 += params.shift * min_side354) {
int ix354 = (int)(x354 + 0.5); if (ix354 == pix354) continue
; pix354 = ix354; ccv_comp_t comp; comp.rect = ccv_rect(ix354
, iy354, width354, height354); comp.classification.id = s354;
355 double overlap = _ccv_tld_rect_intersect(comp.rect, box);
356 comp.neighbors = i++;
357 comp.classification.confidence = overlap;
358 if (overlap > params.include_overlap)
359 {
360 if (overlap > max_overlap)
361 {
362 max_overlap = overlap;
363 best_box = comp;
364 }
365 if (agood->rnum < gcap)
366 {
367 ccv_array_push(agood, &comp);
368 _ccv_tld_box_percolate_up(agood, agood->rnum - 1);
369 } else {
370 ccv_comp_t* p = (ccv_comp_t*)ccv_array_get(agood, 0)((void*)(((char*)((agood)->data)) + (size_t)(agood)->rsize
* (size_t)(0)))
;
371 if (overlap > p->classification.confidence)
372 {
373 *(ccv_comp_t*)ccv_array_get(agood, 0)((void*)(((char*)((agood)->data)) + (size_t)(agood)->rsize
* (size_t)(0)))
= comp;
374 _ccv_tld_box_percolate_down(agood, 0);
375 }
376 }
377 } else if (overlap < params.exclude_overlap)
378 ccv_array_push(abad, &comp);
379 end_for_each_box} } } } };
380 best_box.neighbors = i;
381 return best_box;
382}
383
384static void _ccv_tld_ferns_feature_for(ccv_ferns_t* ferns, ccv_dense_matrix_t* a, ccv_comp_t box, uint32_t* fern, dsfmt_t* dsfmt, float deform_angle, float deform_scale, float deform_shift)
385{
386 assert(box.rect.x >= 0 && box.rect.x < a->cols)((void) sizeof ((box.rect.x >= 0 && box.rect.x <
a->cols) ? 1 : 0), __extension__ ({ if (box.rect.x >= 0
&& box.rect.x < a->cols) ; else __assert_fail (
"box.rect.x >= 0 && box.rect.x < a->cols", "ccv_tld.c"
, 386, __extension__ __PRETTY_FUNCTION__); }))
;
387 assert(box.rect.y >= 0 && box.rect.y < a->rows)((void) sizeof ((box.rect.y >= 0 && box.rect.y <
a->rows) ? 1 : 0), __extension__ ({ if (box.rect.y >= 0
&& box.rect.y < a->rows) ; else __assert_fail (
"box.rect.y >= 0 && box.rect.y < a->rows", "ccv_tld.c"
, 387, __extension__ __PRETTY_FUNCTION__); }))
;
388 assert(box.rect.x + box.rect.width <= a->cols)((void) sizeof ((box.rect.x + box.rect.width <= a->cols
) ? 1 : 0), __extension__ ({ if (box.rect.x + box.rect.width <=
a->cols) ; else __assert_fail ("box.rect.x + box.rect.width <= a->cols"
, "ccv_tld.c", 388, __extension__ __PRETTY_FUNCTION__); }))
;
389 assert(box.rect.y + box.rect.height <= a->rows)((void) sizeof ((box.rect.y + box.rect.height <= a->rows
) ? 1 : 0), __extension__ ({ if (box.rect.y + box.rect.height
<= a->rows) ; else __assert_fail ("box.rect.y + box.rect.height <= a->rows"
, "ccv_tld.c", 389, __extension__ __PRETTY_FUNCTION__); }))
;
390 if (!dsfmt)
391 {
392 ccv_dense_matrix_t roi = ccv_dense_matrix(box.rect.height, box.rect.width, CCV_GET_DATA_TYPE(a->type)((a->type) & 0xFF000) | CCV_GET_CHANNEL(a->type)((a->type) & 0xFFF), ccv_get_dense_matrix_cell(a, box.rect.y, box.rect.x, 0)((((a)->type) & CCV_32S) ? (void*)((a)->data.i32 + (
(box.rect.y) * (a)->cols + (box.rect.x)) * (((a)->type)
& 0xFFF) + (0)) : ((((a)->type) & CCV_32F) ? (void
*)((a)->data.f32+ ((box.rect.y) * (a)->cols + (box.rect
.x)) * (((a)->type) & 0xFFF) + (0)) : ((((a)->type)
& CCV_64S) ? (void*)((a)->data.i64+ ((box.rect.y) * (
a)->cols + (box.rect.x)) * (((a)->type) & 0xFFF) + (
0)) : ((((a)->type) & CCV_64F) ? (void*)((a)->data.
f64 + ((box.rect.y) * (a)->cols + (box.rect.x)) * (((a)->
type) & 0xFFF) + (0)) : (void*)((a)->data.u8 + (box.rect
.y) * (a)->step + (box.rect.x) * (((a)->type) & 0xFFF
) + (0))))))
, 0);
393 roi.step = a->step;
394 ccv_ferns_feature(ferns, &roi, box.classification.id, fern);
395 } else {
396 float rotate_x = (deform_angle * 2 * dsfmt_genrand_close_open(dsfmt) - deform_angle) * CCV_PI(3.141592653589793) / 180;
397 float rotate_y = (deform_angle * 2 * dsfmt_genrand_close_open(dsfmt) - deform_angle) * CCV_PI(3.141592653589793) / 180;
398 float rotate_z = (deform_angle * 2 * dsfmt_genrand_close_open(dsfmt) - deform_angle) * CCV_PI(3.141592653589793) / 180;
399 float scale = 1 + deform_scale - deform_scale * 2 * dsfmt_genrand_close_open(dsfmt);
400 float m00 = cosf(rotate_z) * scale;
401 float m01 = cosf(rotate_y) * sinf(rotate_z) * scale;
402 float m02 = (deform_shift * 2 * dsfmt_genrand_close_open(dsfmt) - deform_shift) * box.rect.width;
403 float m10 = (sinf(rotate_y) * cosf(rotate_z) - cosf(rotate_x) * sinf(rotate_z)) * scale;
404 float m11 = (sinf(rotate_y) * sinf(rotate_z) + cosf(rotate_x) * cosf(rotate_z)) * scale;
405 float m12 = (deform_shift * dsfmt_genrand_close_open(dsfmt) - deform_shift) * box.rect.height;
406 float m20 = (sinf(rotate_y) * cosf(rotate_z) + sinf(rotate_x) * sinf(rotate_z)) * scale;
407 float m21 = (sinf(rotate_y) * sinf(rotate_z) - sinf(rotate_x) * cosf(rotate_z)) * scale;
408 float m22 = cosf(rotate_x) * cosf(rotate_y);
409 ccv_decimal_point_t p00 = ccv_perspective_transform_apply(ccv_decimal_point(0, 0), ccv_size(box.rect.width, box.rect.height), m00, m01, m02, m10, m11, m12, m20, m21, m22);
410 ccv_decimal_point_t p01 = ccv_perspective_transform_apply(ccv_decimal_point(box.rect.width, 0), ccv_size(box.rect.width, box.rect.height), m00, m01, m02, m10, m11, m12, m20, m21, m22);
411 ccv_decimal_point_t p10 = ccv_perspective_transform_apply(ccv_decimal_point(0, box.rect.height), ccv_size(box.rect.width, box.rect.height), m00, m01, m02, m10, m11, m12, m20, m21, m22);
412 ccv_decimal_point_t p11 = ccv_perspective_transform_apply(ccv_decimal_point(box.rect.width, box.rect.height), ccv_size(box.rect.width, box.rect.height), m00, m01, m02, m10, m11, m12, m20, m21, m22);
413 int padding_top = (int)(ccv_max(0, -ccv_min(p00.y, p01.y))({ typeof (0) _a = (0); typeof (-({ typeof (p00.y) _a = (p00.
y); typeof (p01.y) _b = (p01.y); (_a < _b) ? _a : _b; })) _b
= (-({ typeof (p00.y) _a = (p00.y); typeof (p01.y) _b = (p01
.y); (_a < _b) ? _a : _b; })); (_a > _b) ? _a : _b; })
+ 0.5) + 5;
414 padding_top = box.rect.y - ccv_max(box.rect.y - padding_top, 0)({ typeof (box.rect.y - padding_top) _a = (box.rect.y - padding_top
); typeof (0) _b = (0); (_a > _b) ? _a : _b; })
;
415 int padding_right = (int)(ccv_max(0, ccv_max(p01.x, p11.x) - box.rect.width)({ typeof (0) _a = (0); typeof (({ typeof (p01.x) _a = (p01.x
); typeof (p11.x) _b = (p11.x); (_a > _b) ? _a : _b; }) - box
.rect.width) _b = (({ typeof (p01.x) _a = (p01.x); typeof (p11
.x) _b = (p11.x); (_a > _b) ? _a : _b; }) - box.rect.width
); (_a > _b) ? _a : _b; })
+ 0.5) + 5;
416 padding_right = ccv_min(box.rect.x + box.rect.width + padding_right, a->cols)({ typeof (box.rect.x + box.rect.width + padding_right) _a = (
box.rect.x + box.rect.width + padding_right); typeof (a->cols
) _b = (a->cols); (_a < _b) ? _a : _b; })
- (box.rect.x + box.rect.width);
417 int padding_bottom = (int)(ccv_max(0, ccv_max(p10.y, p11.y) - box.rect.height)({ typeof (0) _a = (0); typeof (({ typeof (p10.y) _a = (p10.y
); typeof (p11.y) _b = (p11.y); (_a > _b) ? _a : _b; }) - box
.rect.height) _b = (({ typeof (p10.y) _a = (p10.y); typeof (p11
.y) _b = (p11.y); (_a > _b) ? _a : _b; }) - box.rect.height
); (_a > _b) ? _a : _b; })
+ 0.5) + 5;
418 padding_bottom = ccv_min(box.rect.y + box.rect.height + padding_bottom, a->rows)({ typeof (box.rect.y + box.rect.height + padding_bottom) _a =
(box.rect.y + box.rect.height + padding_bottom); typeof (a->
rows) _b = (a->rows); (_a < _b) ? _a : _b; })
- (box.rect.y + box.rect.height);
419 int padding_left = (int)(ccv_max(0, -ccv_min(p00.x, p10.x))({ typeof (0) _a = (0); typeof (-({ typeof (p00.x) _a = (p00.
x); typeof (p10.x) _b = (p10.x); (_a < _b) ? _a : _b; })) _b
= (-({ typeof (p00.x) _a = (p00.x); typeof (p10.x) _b = (p10
.x); (_a < _b) ? _a : _b; })); (_a > _b) ? _a : _b; })
+ 0.5) + 5;
420 padding_left = box.rect.x - ccv_max(box.rect.x - padding_left, 0)({ typeof (box.rect.x - padding_left) _a = (box.rect.x - padding_left
); typeof (0) _b = (0); (_a > _b) ? _a : _b; })
;
421 ccv_rect_t hull = ccv_rect(box.rect.x - padding_left, box.rect.y - padding_top,
422 box.rect.width + padding_left + padding_right,
423 box.rect.height + padding_top + padding_bottom);
424 assert(hull.x >= 0 && hull.x < a->cols)((void) sizeof ((hull.x >= 0 && hull.x < a->
cols) ? 1 : 0), __extension__ ({ if (hull.x >= 0 &&
hull.x < a->cols) ; else __assert_fail ("hull.x >= 0 && hull.x < a->cols"
, "ccv_tld.c", 424, __extension__ __PRETTY_FUNCTION__); }))
;
425 assert(hull.y >= 0 && hull.y < a->rows)((void) sizeof ((hull.y >= 0 && hull.y < a->
rows) ? 1 : 0), __extension__ ({ if (hull.y >= 0 &&
hull.y < a->rows) ; else __assert_fail ("hull.y >= 0 && hull.y < a->rows"
, "ccv_tld.c", 425, __extension__ __PRETTY_FUNCTION__); }))
;
426 assert(hull.x + hull.width <= a->cols)((void) sizeof ((hull.x + hull.width <= a->cols) ? 1 : 0
), __extension__ ({ if (hull.x + hull.width <= a->cols)
; else __assert_fail ("hull.x + hull.width <= a->cols"
, "ccv_tld.c", 426, __extension__ __PRETTY_FUNCTION__); }))
;
427 assert(hull.y + hull.height <= a->rows)((void) sizeof ((hull.y + hull.height <= a->rows) ? 1 :
0), __extension__ ({ if (hull.y + hull.height <= a->rows
) ; else __assert_fail ("hull.y + hull.height <= a->rows"
, "ccv_tld.c", 427, __extension__ __PRETTY_FUNCTION__); }))
;
428 ccv_dense_matrix_t roi = ccv_dense_matrix(hull.height, hull.width, CCV_GET_DATA_TYPE(a->type)((a->type) & 0xFF000) | CCV_GET_CHANNEL(a->type)((a->type) & 0xFFF), ccv_get_dense_matrix_cell(a, hull.y, hull.x, 0)((((a)->type) & CCV_32S) ? (void*)((a)->data.i32 + (
(hull.y) * (a)->cols + (hull.x)) * (((a)->type) & 0xFFF
) + (0)) : ((((a)->type) & CCV_32F) ? (void*)((a)->
data.f32+ ((hull.y) * (a)->cols + (hull.x)) * (((a)->type
) & 0xFFF) + (0)) : ((((a)->type) & CCV_64S) ? (void
*)((a)->data.i64+ ((hull.y) * (a)->cols + (hull.x)) * (
((a)->type) & 0xFFF) + (0)) : ((((a)->type) & CCV_64F
) ? (void*)((a)->data.f64 + ((hull.y) * (a)->cols + (hull
.x)) * (((a)->type) & 0xFFF) + (0)) : (void*)((a)->
data.u8 + (hull.y) * (a)->step + (hull.x) * (((a)->type
) & 0xFFF) + (0))))))
, 0);
429 roi.step = a->step;
430 ccv_dense_matrix_t* b = 0;
431 ccv_perspective_transform(&roi, &b, 0, m00, m01, m02, m10, m11, m12, m20, m21, m22);
432 roi = ccv_dense_matrix(box.rect.height, box.rect.width, CCV_GET_DATA_TYPE(b->type)((b->type) & 0xFF000) | CCV_GET_CHANNEL(b->type)((b->type) & 0xFFF), ccv_get_dense_matrix_cell(b, padding_top, padding_left, 0)((((b)->type) & CCV_32S) ? (void*)((b)->data.i32 + (
(padding_top) * (b)->cols + (padding_left)) * (((b)->type
) & 0xFFF) + (0)) : ((((b)->type) & CCV_32F) ? (void
*)((b)->data.f32+ ((padding_top) * (b)->cols + (padding_left
)) * (((b)->type) & 0xFFF) + (0)) : ((((b)->type) &
CCV_64S) ? (void*)((b)->data.i64+ ((padding_top) * (b)->
cols + (padding_left)) * (((b)->type) & 0xFFF) + (0)) :
((((b)->type) & CCV_64F) ? (void*)((b)->data.f64 +
((padding_top) * (b)->cols + (padding_left)) * (((b)->
type) & 0xFFF) + (0)) : (void*)((b)->data.u8 + (padding_top
) * (b)->step + (padding_left) * (((b)->type) & 0xFFF
) + (0))))))
, 0);
433 roi.step = b->step;
434 ccv_ferns_feature(ferns, &roi, box.classification.id, fern);
435 ccv_matrix_free(b);
436 }
437}
438
439static void _ccv_tld_fetch_patch(ccv_tld_t* tld, ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, ccv_rect_t box)
440{
441 if (box.width == tld->patch.width && box.height == tld->patch.height)
442 ccv_slice(a, (ccv_matrix_t**)b, type, box.y, box.x, box.height, box.width);
443 else {
444 assert((box.width >= tld->patch.width && box.height >= tld->patch.height) ||((void) sizeof (((box.width >= tld->patch.width &&
box.height >= tld->patch.height) || (box.width <= tld
->patch.width && box.height <= tld->patch.height
)) ? 1 : 0), __extension__ ({ if ((box.width >= tld->patch
.width && box.height >= tld->patch.height) || (
box.width <= tld->patch.width && box.height <=
tld->patch.height)) ; else __assert_fail ("(box.width >= tld->patch.width && box.height >= tld->patch.height) || (box.width <= tld->patch.width && box.height <= tld->patch.height)"
, "ccv_tld.c", 445, __extension__ __PRETTY_FUNCTION__); }))
445 (box.width <= tld->patch.width && box.height <= tld->patch.height))((void) sizeof (((box.width >= tld->patch.width &&
box.height >= tld->patch.height) || (box.width <= tld
->patch.width && box.height <= tld->patch.height
)) ? 1 : 0), __extension__ ({ if ((box.width >= tld->patch
.width && box.height >= tld->patch.height) || (
box.width <= tld->patch.width && box.height <=
tld->patch.height)) ; else __assert_fail ("(box.width >= tld->patch.width && box.height >= tld->patch.height) || (box.width <= tld->patch.width && box.height <= tld->patch.height)"
, "ccv_tld.c", 445, __extension__ __PRETTY_FUNCTION__); }))
;
446 ccv_dense_matrix_t* c = 0;
447 ccv_slice(a, (ccv_matrix_t**)&c, type, box.y, box.x, box.height, box.width);
448 ccv_resample(c, b, type, tld->patch.height, tld->patch.width, CCV_INTER_AREA | CCV_INTER_CUBIC);
449 ccv_matrix_free(c);
450 }
451}
452
453static double _ccv_tld_box_variance(ccv_dense_matrix_t* sat, ccv_dense_matrix_t* sqsat, ccv_rect_t box)
454{
455 assert(CCV_GET_DATA_TYPE(sat->type) == CCV_32S)((void) sizeof ((((sat->type) & 0xFF000) == CCV_32S) ?
1 : 0), __extension__ ({ if (((sat->type) & 0xFF000) ==
CCV_32S) ; else __assert_fail ("CCV_GET_DATA_TYPE(sat->type) == CCV_32S"
, "ccv_tld.c", 455, __extension__ __PRETTY_FUNCTION__); }))
;
456 assert(CCV_GET_DATA_TYPE(sqsat->type) == CCV_64S)((void) sizeof ((((sqsat->type) & 0xFF000) == CCV_64S)
? 1 : 0), __extension__ ({ if (((sqsat->type) & 0xFF000
) == CCV_64S) ; else __assert_fail ("CCV_GET_DATA_TYPE(sqsat->type) == CCV_64S"
, "ccv_tld.c", 456, __extension__ __PRETTY_FUNCTION__); }))
;
457 int tls = (box.x > 0 && box.y > 0) ? sat->data.i32[box.x - 1 + (box.y - 1) * sat->cols] : 0;
458 int trs = (box.y > 0) ? sat->data.i32[box.x + box.width - 1 + (box.y - 1) * sat->cols] : 0;
459 int bls = (box.x > 0) ? sat->data.i32[box.x - 1 + (box.y + box.height - 1) * sat->cols] : 0;
460 int brs = sat->data.i32[box.x + box.width - 1 + (box.y + box.height - 1) * sat->cols];
461 double mean = (double)(brs - trs - bls + tls) / (box.width * box.height);
462 int64_t tlsq = (box.x > 0 && box.y > 0) ? sqsat->data.i64[box.x - 1 + (box.y - 1) * sqsat->cols] : 0;
463 int64_t trsq = (box.y > 0) ? sqsat->data.i64[box.x + box.width - 1 + (box.y - 1) * sqsat->cols] : 0;
464 int64_t blsq = (box.x > 0) ? sqsat->data.i64[box.x - 1 + (box.y + box.height - 1) * sqsat->cols] : 0;
465 int64_t brsq = sqsat->data.i64[box.x + box.width - 1 + (box.y + box.height - 1) * sqsat->cols];
466 double variance = (double)(brsq - trsq - blsq + tlsq) / (box.width * box.height);
467 variance = variance - mean * mean;
468 assert(variance >= 0)((void) sizeof ((variance >= 0) ? 1 : 0), __extension__ ({
if (variance >= 0) ; else __assert_fail ("variance >= 0"
, "ccv_tld.c", 468, __extension__ __PRETTY_FUNCTION__); }))
;
469 return variance;
470}
471
472static float _ccv_tld_sv_classify(ccv_tld_t* tld, ccv_dense_matrix_t* a, int pnum, int nnum, int* anyp, int* anyn)
473{
474 assert(a->rows == tld->patch.height && a->cols == tld->patch.width)((void) sizeof ((a->rows == tld->patch.height &&
a->cols == tld->patch.width) ? 1 : 0), __extension__ (
{ if (a->rows == tld->patch.height && a->cols
== tld->patch.width) ; else __assert_fail ("a->rows == tld->patch.height && a->cols == tld->patch.width"
, "ccv_tld.c", 474, __extension__ __PRETTY_FUNCTION__); }))
;
475 int i;
476 pnum = (pnum <= 0) ? tld->sv[1]->rnum : ccv_min(pnum, tld->sv[1]->rnum)({ typeof (pnum) _a = (pnum); typeof (tld->sv[1]->rnum)
_b = (tld->sv[1]->rnum); (_a < _b) ? _a : _b; })
;
477 if (pnum == 0)
478 return 0;
479 nnum = (nnum <= 0) ? tld->sv[0]->rnum : ccv_min(nnum, tld->sv[0]->rnum)({ typeof (nnum) _a = (nnum); typeof (tld->sv[0]->rnum)
_b = (tld->sv[0]->rnum); (_a < _b) ? _a : _b; })
;
480 if (nnum == 0)
481 return 1;
482 float maxp = -1;
483 for (i = 0; i < pnum; i++)
484 {
485 ccv_dense_matrix_t* b = *(ccv_dense_matrix_t**)ccv_array_get(tld->sv[1], i)((void*)(((char*)((tld->sv[1])->data)) + (size_t)(tld->
sv[1])->rsize * (size_t)(i)))
;
486 float nnc = _ccv_tld_norm_cross_correlate(a, b);
487 if (nnc > maxp)
488 maxp = nnc;
489 }
490 maxp = (maxp + 1) * 0.5; // make it in 0~1 range
491 if (anyp)
492 *anyp = (maxp > tld->params.nnc_same);
493 float maxn = -1;
494 for (i = 0; i < nnum; i++)
495 {
496 ccv_dense_matrix_t* b = *(ccv_dense_matrix_t**)ccv_array_get(tld->sv[0], i)((void*)(((char*)((tld->sv[0])->data)) + (size_t)(tld->
sv[0])->rsize * (size_t)(i)))
;
497 float nnc = _ccv_tld_norm_cross_correlate(a, b);
498 if (nnc > maxn)
499 maxn = nnc;
500 }
501 maxn = (maxn + 1) * 0.5; // make it in 0~1 range
502 if (anyn)
503 *anyn = (maxn > tld->params.nnc_same);
504 return (1 - maxn) / (2 - maxn - maxp);
505}
506
507// return 0 means that we will retain the given example (thus, you don't want to free it)
508static int _ccv_tld_sv_correct(ccv_tld_t* tld, ccv_dense_matrix_t* a, int y)
509{
510 int anyp, anyn;
511 if (y == 1 && tld->sv[1]->rnum == 0)
512 {
513 ccv_array_push(tld->sv[1], &a);
514 return 0;
515 }
516 float conf = _ccv_tld_sv_classify(tld, a, 0, 0, &anyp, &anyn);
517 if (y == 1 && conf < tld->params.nnc_thres)
518 {
519 ccv_array_push(tld->sv[1], &a);
520 return 0;
521 } else if (y == 0 && conf > tld->params.nnc_collect) {
522 ccv_array_push(tld->sv[0], &a);
523 return 0;
524 }
525 return -1;
526}
527
528static void _ccv_tld_check_params(ccv_tld_param_t params)
529{
530 assert(params.top_n > 0)((void) sizeof ((params.top_n > 0) ? 1 : 0), __extension__
({ if (params.top_n > 0) ; else __assert_fail ("params.top_n > 0"
, "ccv_tld.c", 530, __extension__ __PRETTY_FUNCTION__); }))
;
531 assert(params.structs > 0)((void) sizeof ((params.structs > 0) ? 1 : 0), __extension__
({ if (params.structs > 0) ; else __assert_fail ("params.structs > 0"
, "ccv_tld.c", 531, __extension__ __PRETTY_FUNCTION__); }))
;
532 assert(params.features > 0 && params.features <= 32)((void) sizeof ((params.features > 0 && params.features
<= 32) ? 1 : 0), __extension__ ({ if (params.features >
0 && params.features <= 32) ; else __assert_fail (
"params.features > 0 && params.features <= 32",
"ccv_tld.c", 532, __extension__ __PRETTY_FUNCTION__); }))
;
533 assert(params.win_size.width > 0 && params.win_size.height > 0)((void) sizeof ((params.win_size.width > 0 && params
.win_size.height > 0) ? 1 : 0), __extension__ ({ if (params
.win_size.width > 0 && params.win_size.height >
0) ; else __assert_fail ("params.win_size.width > 0 && params.win_size.height > 0"
, "ccv_tld.c", 533, __extension__ __PRETTY_FUNCTION__); }))
;
534 assert((params.win_size.width & 1) == 1 && (params.win_size.height & 1) == 1)((void) sizeof (((params.win_size.width & 1) == 1 &&
(params.win_size.height & 1) == 1) ? 1 : 0), __extension__
({ if ((params.win_size.width & 1) == 1 && (params
.win_size.height & 1) == 1) ; else __assert_fail ("(params.win_size.width & 1) == 1 && (params.win_size.height & 1) == 1"
, "ccv_tld.c", 534, __extension__ __PRETTY_FUNCTION__); }))
;
535 assert(params.level >= 0)((void) sizeof ((params.level >= 0) ? 1 : 0), __extension__
({ if (params.level >= 0) ; else __assert_fail ("params.level >= 0"
, "ccv_tld.c", 535, __extension__ __PRETTY_FUNCTION__); }))
;
536 assert(params.min_eigen > 0)((void) sizeof ((params.min_eigen > 0) ? 1 : 0), __extension__
({ if (params.min_eigen > 0) ; else __assert_fail ("params.min_eigen > 0"
, "ccv_tld.c", 536, __extension__ __PRETTY_FUNCTION__); }))
;
537 assert(params.min_forward_backward_error > 0)((void) sizeof ((params.min_forward_backward_error > 0) ? 1
: 0), __extension__ ({ if (params.min_forward_backward_error
> 0) ; else __assert_fail ("params.min_forward_backward_error > 0"
, "ccv_tld.c", 537, __extension__ __PRETTY_FUNCTION__); }))
;
538 assert(params.bad_patches > 0)((void) sizeof ((params.bad_patches > 0) ? 1 : 0), __extension__
({ if (params.bad_patches > 0) ; else __assert_fail ("params.bad_patches > 0"
, "ccv_tld.c", 538, __extension__ __PRETTY_FUNCTION__); }))
;
539 assert(params.interval >= 0)((void) sizeof ((params.interval >= 0) ? 1 : 0), __extension__
({ if (params.interval >= 0) ; else __assert_fail ("params.interval >= 0"
, "ccv_tld.c", 539, __extension__ __PRETTY_FUNCTION__); }))
;
540 assert(params.shift > 0 && params.shift < 1)((void) sizeof ((params.shift > 0 && params.shift <
1) ? 1 : 0), __extension__ ({ if (params.shift > 0 &&
params.shift < 1) ; else __assert_fail ("params.shift > 0 && params.shift < 1"
, "ccv_tld.c", 540, __extension__ __PRETTY_FUNCTION__); }))
;
541 assert(params.validate_set > 0 && params.validate_set < 1)((void) sizeof ((params.validate_set > 0 && params
.validate_set < 1) ? 1 : 0), __extension__ ({ if (params.validate_set
> 0 && params.validate_set < 1) ; else __assert_fail
("params.validate_set > 0 && params.validate_set < 1"
, "ccv_tld.c", 541, __extension__ __PRETTY_FUNCTION__); }))
;
542 assert(params.nnc_same > 0.5 && params.nnc_same < 1)((void) sizeof ((params.nnc_same > 0.5 && params.nnc_same
< 1) ? 1 : 0), __extension__ ({ if (params.nnc_same > 0.5
&& params.nnc_same < 1) ; else __assert_fail ("params.nnc_same > 0.5 && params.nnc_same < 1"
, "ccv_tld.c", 542, __extension__ __PRETTY_FUNCTION__); }))
;
543 assert(params.nnc_thres > 0.5 && params.nnc_thres < 1)((void) sizeof ((params.nnc_thres > 0.5 && params.
nnc_thres < 1) ? 1 : 0), __extension__ ({ if (params.nnc_thres
> 0.5 && params.nnc_thres < 1) ; else __assert_fail
("params.nnc_thres > 0.5 && params.nnc_thres < 1"
, "ccv_tld.c", 543, __extension__ __PRETTY_FUNCTION__); }))
;
544 assert(params.nnc_verify > 0.5 && params.nnc_verify < 1)((void) sizeof ((params.nnc_verify > 0.5 && params
.nnc_verify < 1) ? 1 : 0), __extension__ ({ if (params.nnc_verify
> 0.5 && params.nnc_verify < 1) ; else __assert_fail
("params.nnc_verify > 0.5 && params.nnc_verify < 1"
, "ccv_tld.c", 544, __extension__ __PRETTY_FUNCTION__); }))
;
545 assert(params.nnc_beyond > 0.5 && params.nnc_beyond < 1)((void) sizeof ((params.nnc_beyond > 0.5 && params
.nnc_beyond < 1) ? 1 : 0), __extension__ ({ if (params.nnc_beyond
> 0.5 && params.nnc_beyond < 1) ; else __assert_fail
("params.nnc_beyond > 0.5 && params.nnc_beyond < 1"
, "ccv_tld.c", 545, __extension__ __PRETTY_FUNCTION__); }))
;
546 assert(params.nnc_collect >= 0.5 && params.nnc_collect < 1)((void) sizeof ((params.nnc_collect >= 0.5 && params
.nnc_collect < 1) ? 1 : 0), __extension__ ({ if (params.nnc_collect
>= 0.5 && params.nnc_collect < 1) ; else __assert_fail
("params.nnc_collect >= 0.5 && params.nnc_collect < 1"
, "ccv_tld.c", 546, __extension__ __PRETTY_FUNCTION__); }))
;
547 assert(params.new_deform > 0)((void) sizeof ((params.new_deform > 0) ? 1 : 0), __extension__
({ if (params.new_deform > 0) ; else __assert_fail ("params.new_deform > 0"
, "ccv_tld.c", 547, __extension__ __PRETTY_FUNCTION__); }))
;
548 assert(params.track_deform > 0)((void) sizeof ((params.track_deform > 0) ? 1 : 0), __extension__
({ if (params.track_deform > 0) ; else __assert_fail ("params.track_deform > 0"
, "ccv_tld.c", 548, __extension__ __PRETTY_FUNCTION__); }))
;
549 assert(params.new_deform_angle > 0)((void) sizeof ((params.new_deform_angle > 0) ? 1 : 0), __extension__
({ if (params.new_deform_angle > 0) ; else __assert_fail (
"params.new_deform_angle > 0", "ccv_tld.c", 549, __extension__
__PRETTY_FUNCTION__); }))
;
550 assert(params.track_deform_angle > 0)((void) sizeof ((params.track_deform_angle > 0) ? 1 : 0), __extension__
({ if (params.track_deform_angle > 0) ; else __assert_fail
("params.track_deform_angle > 0", "ccv_tld.c", 550, __extension__
__PRETTY_FUNCTION__); }))
;
551 assert(params.new_deform_scale > 0)((void) sizeof ((params.new_deform_scale > 0) ? 1 : 0), __extension__
({ if (params.new_deform_scale > 0) ; else __assert_fail (
"params.new_deform_scale > 0", "ccv_tld.c", 551, __extension__
__PRETTY_FUNCTION__); }))
;
552 assert(params.track_deform_scale > 0)((void) sizeof ((params.track_deform_scale > 0) ? 1 : 0), __extension__
({ if (params.track_deform_scale > 0) ; else __assert_fail
("params.track_deform_scale > 0", "ccv_tld.c", 552, __extension__
__PRETTY_FUNCTION__); }))
;
553 assert(params.new_deform_shift > 0)((void) sizeof ((params.new_deform_shift > 0) ? 1 : 0), __extension__
({ if (params.new_deform_shift > 0) ; else __assert_fail (
"params.new_deform_shift > 0", "ccv_tld.c", 553, __extension__
__PRETTY_FUNCTION__); }))
;
554 assert(params.track_deform_shift > 0)((void) sizeof ((params.track_deform_shift > 0) ? 1 : 0), __extension__
({ if (params.track_deform_shift > 0) ; else __assert_fail
("params.track_deform_shift > 0", "ccv_tld.c", 554, __extension__
__PRETTY_FUNCTION__); }))
;
555 assert(params.rotation >= 0)((void) sizeof ((params.rotation >= 0) ? 1 : 0), __extension__
({ if (params.rotation >= 0) ; else __assert_fail ("params.rotation >= 0"
, "ccv_tld.c", 555, __extension__ __PRETTY_FUNCTION__); }))
;
556}
557
558static float _ccv_tld_ferns_compute_threshold(ccv_ferns_t* ferns, float ferns_thres, ccv_dense_matrix_t* ga, ccv_dense_matrix_t* sat, ccv_dense_matrix_t* sqsat, double var_thres, ccv_array_t* bad, int starter)
559{
560 int i;
561 uint32_t* fern = (uint32_t*)alloca(sizeof(uint32_t) * ferns->structs)__builtin_alloca (sizeof(uint32_t) * ferns->structs);
562 for (i = starter; i < bad->rnum; i++)
563 {
564 ccv_comp_t* box = (ccv_comp_t*)ccv_array_get(bad, i)((void*)(((char*)((bad)->data)) + (size_t)(bad)->rsize *
(size_t)(i)))
;
565 if (_ccv_tld_box_variance(sat, sqsat, box->rect) > var_thres)
566 {
567 _ccv_tld_ferns_feature_for(ferns, ga, *box, fern, 0, 0, 0, 0);
568 float c = ccv_ferns_predict(ferns, fern);
569 if (c > ferns_thres)
570 ferns_thres = c;
571 }
572 }
573 return ferns_thres;
574}
575
576static float _ccv_tld_nnc_compute_threshold(ccv_tld_t* tld, float nnc_thres, ccv_dense_matrix_t* ga, ccv_dense_matrix_t* sat, ccv_dense_matrix_t* sqsat, double var_thres, ccv_array_t* bad, int starter)
577{
578 int i;
579 dsfmt_t* dsfmt = (dsfmt_t*)tld->dsfmt;
580 for (i = starter; i < bad->rnum; i++)
581 {
582 ccv_comp_t* box = (ccv_comp_t*)ccv_array_get(bad, i)((void*)(((char*)((bad)->data)) + (size_t)(bad)->rsize *
(size_t)(i)))
;
583 if (_ccv_tld_box_variance(sat, sqsat, box->rect) > var_thres)
584 {
585 if (dsfmt_genrand_close_open(dsfmt) <= 0.1) // only pick 1 / 10 sample for this
586 {
587 ccv_dense_matrix_t* b = 0;
588 _ccv_tld_fetch_patch(tld, ga, &b, 0, box->rect);
589 float c = _ccv_tld_sv_classify(tld, b, 0, 0, 0, 0);
590 ccv_matrix_free(b);
591 if (c > nnc_thres)
592 nnc_thres = c;
593 }
594 }
595 }
596 return nnc_thres;
597}
598
599ccv_tld_t* ccv_tld_new(ccv_dense_matrix_t* a, ccv_rect_t box, ccv_tld_param_t params)
600{
601 _ccv_tld_check_params(params);
602 ccv_size_t patch = ccv_size((int)(sqrtf(params.min_win * params.min_win * (float)box.width / box.height) + 0.5),
603 (int)(sqrtf(params.min_win * params.min_win * (float)box.height / box.width) + 0.5));
604 ccv_array_t* good = 0;
605 ccv_array_t* bad = 0;
606 ccv_comp_t best_box = _ccv_tld_generate_box_for(ccv_size(a->cols, a->rows), patch, box, 20, &good, &bad, params);
607 ccv_tld_t* tld = (ccv_tld_t*)ccmallocmalloc(sizeof(ccv_tld_t) + sizeof(uint32_t) * (params.structs * best_box.neighbors - 1));
608 tld->patch = patch;
609 tld->params = params;
610 tld->nnc_verify_thres = params.nnc_verify;
611 tld->frame_signature = a->sig;
612 tld->sfmt = ccmallocmalloc(sizeof(sfmt_t));
613 tld->dsfmt = ccmallocmalloc(sizeof(dsfmt_t));
614 tld->box.rect = box;
615 {
616 double scale = pow(2.0, 1.0 / (params.interval + 1.0));
617 int scale_upto = (int)(log((double)ccv_min((double)a->cols / patch.width, (double)a->rows / patch.height)({ typeof ((double)a->cols / patch.width) _a = ((double)a->
cols / patch.width); typeof ((double)a->rows / patch.height
) _b = ((double)a->rows / patch.height); (_a < _b) ? _a
: _b; })
) / log(scale));
618 ccv_size_t* scales = (ccv_size_t*)alloca(sizeof(ccv_size_t) * scale_upto)__builtin_alloca (sizeof(ccv_size_t) * scale_upto);
619 int is = 0;
620 for_each_size(width, height, patch.width, patch.height, params.interval, a->cols, a->rows){ double scale620 = pow(2.0, 1.0 / (params.interval + 1.0)); int
scale_upto620 = (int)(log((double)({ typeof ((double)a->cols
/ patch.width) _a = ((double)a->cols / patch.width); typeof
((double)a->rows / patch.height) _b = ((double)a->rows
/ patch.height); (_a < _b) ? _a : _b; })) / log(scale620)
); int s620; double ss620 = 1.0; for (s620 = 0; s620 < scale_upto620
; s620++) { int width = (int)(patch.width * ss620 + 0.5); int
height = (int)(patch.height * ss620 + 0.5); ss620 *= scale620
; if (width > a->cols || height > a->rows) break;
621 scales[is] = ccv_size(width, height);
622 ++is;
623 end_for_each_size} };
624 tld->ferns = ccv_ferns_new(params.structs, params.features, is, scales);
625 }
626 tld->sv[0] = ccv_array_new(sizeof(ccv_dense_matrix_t*), 64, 0);
627 tld->sv[1] = ccv_array_new(sizeof(ccv_dense_matrix_t*), 64, 0);
628 sfmt_t* sfmt = (sfmt_t*)tld->sfmt;
629 sfmt_init_gen_rand(sfmt, (uint32_t)(uintptr_t)a);
630 sfmt_genrand_shuffle(sfmt, ccv_array_get(bad, 0)((void*)(((char*)((bad)->data)) + (size_t)(bad)->rsize *
(size_t)(0)))
, bad->rnum, bad->rsize);
631 int badex = (bad->rnum + 1) / 2;
632 int i, j, k = good->rnum;
633 // inflate good so that it can be used many times for the deformation
634 for (i = 0; i < params.new_deform; i++)
635 for (j = 0; j < k; j++)
636 {
637 // needs to get it out first, otherwise the pointer may be invalid
638 // soon (when we realloc the array in push).
639 ccv_comp_t box = *(ccv_comp_t*)ccv_array_get(good, j)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(j)))
;
640 ccv_array_push(good, &box);
641 }
642 int* idx = (int*)ccmallocmalloc(sizeof(int) * (badex + good->rnum));
643 for (i = 0; i < badex + good->rnum; i++)
644 idx[i] = i;
645 sfmt_genrand_shuffle(sfmt, idx, badex + good->rnum, sizeof(int));
646 // train the fern classifier
647 ccv_dense_matrix_t* ga = 0;
648 ccv_blur(a, &ga, 0, 1.5);
649 ccv_dense_matrix_t* b = 0;
650 _ccv_tld_fetch_patch(tld, ga, &b, 0, best_box.rect);
651 tld->var_thres = ccv_variance(b) * 0.5;
652 ccv_array_push(tld->sv[1], &b);
653 ccv_dense_matrix_t* sat = 0;
654 ccv_sat(a, &sat, 0, CCV_NO_PADDING);
655 ccv_dense_matrix_t* sq = 0;
656 ccv_multiply(a, a, (ccv_matrix_t**)&sq, 0);
657 ccv_dense_matrix_t* sqsat = 0;
658 ccv_sat(sq, &sqsat, 0, CCV_NO_PADDING);
659 ccv_matrix_free(sq);
660 dsfmt_t* dsfmt = (dsfmt_t*)tld->dsfmt;
661 dsfmt_init_gen_rand(dsfmt, (uint32_t)(uintptr_t)tld);
662 { // save stack fr alloca
663 uint32_t* fern = (uint32_t*)alloca(sizeof(uint32_t) * tld->ferns->structs)__builtin_alloca (sizeof(uint32_t) * tld->ferns->structs
)
;
664 for (i = 0; i < 2; i++) // run twice to take into account when warm up, we missed a few examples
665 {
666 for (j = 0; j < badex + good->rnum; j++)
667 {
668 k = idx[j];
669 if (k < badex)
670 {
671 ccv_comp_t* box = (ccv_comp_t*)ccv_array_get(bad, k)((void*)(((char*)((bad)->data)) + (size_t)(bad)->rsize *
(size_t)(k)))
;
672 assert(box->neighbors >= 0 && box->neighbors < best_box.neighbors)((void) sizeof ((box->neighbors >= 0 && box->
neighbors < best_box.neighbors) ? 1 : 0), __extension__ ({
if (box->neighbors >= 0 && box->neighbors <
best_box.neighbors) ; else __assert_fail ("box->neighbors >= 0 && box->neighbors < best_box.neighbors"
, "ccv_tld.c", 672, __extension__ __PRETTY_FUNCTION__); }))
;
673 if (_ccv_tld_box_variance(sat, sqsat, box->rect) > tld->var_thres * 0.5)
674 {
675 _ccv_tld_ferns_feature_for(tld->ferns, ga, *box, fern, 0, 0, 0, 0);
676 // fix the thresholding for negative
677 if (ccv_ferns_predict(tld->ferns, fern) >= tld->ferns->threshold)
678 ccv_ferns_correct(tld->ferns, fern, 0, 2);
679 }
680 } else {
681 ccv_comp_t* box = (ccv_comp_t*)ccv_array_get(good, k - badex)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(k - badex)))
;
682 _ccv_tld_ferns_feature_for(tld->ferns, ga, *box, fern, dsfmt, params.new_deform_angle, params.new_deform_scale, params.new_deform_shift);
683 // fix the thresholding for positive
684 if (ccv_ferns_predict(tld->ferns, fern) <= tld->ferns->threshold)
685 ccv_ferns_correct(tld->ferns, fern, 1, 2);
686 }
687 }
688 }
689 } // reclaim stack
690 tld->ferns_thres = _ccv_tld_ferns_compute_threshold(tld->ferns, tld->ferns->threshold, ga, sat, sqsat, tld->var_thres * 0.5, bad, badex);
691 ccv_array_free(good);
692 ccfreefree(idx);
693 // train the nearest-neighbor classifier
694 for (i = 0, k = 0; i < bad->rnum && k < params.bad_patches; i++)
695 {
696 ccv_comp_t* box = (ccv_comp_t*)ccv_array_get(bad, i)((void*)(((char*)((bad)->data)) + (size_t)(bad)->rsize *
(size_t)(i)))
;
697 if (_ccv_tld_box_variance(sat, sqsat, box->rect) > tld->var_thres * 0.5)
698 {
699 ccv_dense_matrix_t* b = 0;
700 _ccv_tld_fetch_patch(tld, ga, &b, 0, box->rect);
701 if (_ccv_tld_sv_correct(tld, b, 0) != 0)
702 ccv_matrix_free(b);
703 ++k;
704 }
705 }
706 tld->nnc_thres = _ccv_tld_nnc_compute_threshold(tld, tld->params.nnc_thres, ga, sat, sqsat, tld->var_thres * 0.5, bad, badex);
707 tld->nnc_thres = ccv_min(tld->nnc_thres, params.nnc_beyond)({ typeof (tld->nnc_thres) _a = (tld->nnc_thres); typeof
(params.nnc_beyond) _b = (params.nnc_beyond); (_a < _b) ?
_a : _b; })
;
708 ccv_matrix_free(sqsat);
709 ccv_matrix_free(sat);
710 ccv_matrix_free(ga);
711 ccv_array_free(bad);
712 // init tld params
713 tld->found = 1; // assume last time has found (we just started)
714 tld->verified = 1; // assume last frame is verified tracking
715 // top is ccv_tld_feature_t, and its continuous memory region for a feature
716 tld->top = ccv_array_new(sizeof(ccv_comp_t), params.top_n, 0);
717 tld->top->rnum = 0;
718 tld->count = 0;
719 return tld;
720}
721
722static int _ccv_tld_quick_learn(ccv_tld_t* tld, ccv_dense_matrix_t* ga, ccv_dense_matrix_t* sat, ccv_dense_matrix_t* sqsat, ccv_comp_t dd)
723{
724 ccv_dense_matrix_t* b = 0;
725 float scale = sqrtf((float)(dd.rect.width * dd.rect.height) / (tld->patch.width * tld->patch.height));
726 // regularize the rect to conform patch's aspect ratio
727 dd.rect = ccv_rect((int)(dd.rect.x + (dd.rect.width - tld->patch.width * scale) + 0.5),
728 (int)(dd.rect.y + (dd.rect.height - tld->patch.height * scale) + 0.5),
729 (int)(tld->patch.width * scale + 0.5),
730 (int)(tld->patch.height * scale + 0.5));
731 _ccv_tld_fetch_patch(tld, ga, &b, 0, dd.rect);
732 double variance = ccv_variance(b);
733 int anyp, anyn;
734 float c = _ccv_tld_sv_classify(tld, b, 0, 0, &anyp, &anyn);
735 ccv_matrix_free(b);
736 if (c > tld->params.nnc_collect && !anyn && variance > tld->var_thres)
737 {
738 ccv_array_t* good = 0;
739 ccv_array_t* bad = 0;
740 ccv_comp_t best_box = _ccv_tld_generate_box_for(ccv_size(ga->cols, ga->rows), tld->patch, dd.rect, 10, &good, &bad, tld->params);
741 int i, j, k = good->rnum;
742 // inflate good boxes to take into account deformations
743 for (i = 0; i < tld->params.track_deform; i++)
744 for (j = 0; j < k; j++)
745 {
746 // needs to get it out first, otherwise the pointer may be invalid
747 // soon (when we realloc the array in push).
748 ccv_comp_t box = *(ccv_comp_t*)ccv_array_get(good, j)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(j)))
;
749 ccv_array_push(good, &box);
750 }
751 sfmt_t* sfmt = (sfmt_t*)tld->sfmt;
752 sfmt_genrand_shuffle(sfmt, ccv_array_get(bad, 0)((void*)(((char*)((bad)->data)) + (size_t)(bad)->rsize *
(size_t)(0)))
, bad->rnum, bad->rsize);
753 int badex = (bad->rnum * 4 + 3) / 6; // only use 2 / 3 bad example for quick learn
754 int* idx = (int*)ccmallocmalloc(sizeof(int) * (badex + good->rnum));
755 for (i = 0; i < badex + good->rnum; i++)
756 idx[i] = i;
757 sfmt_genrand_shuffle(sfmt, idx, badex + good->rnum, sizeof(int));
758 dsfmt_t* dsfmt = (dsfmt_t*)tld->dsfmt;
759 uint32_t* fern = (uint32_t*)ccmallocmalloc(sizeof(uint32_t) * tld->ferns->structs * (badex + 1));
760 int r0 = tld->count % (tld->params.rotation + 1), r1 = tld->params.rotation + 1;
761 // train the fern classifier
762 for (i = 0; i < 2; i++) // run it twice to take into account the cases we missed when warm up
763 {
764 uint32_t* pfern = fern + tld->ferns->structs;
765 for (j = 0; j < badex + good->rnum; j++)
766 {
767 k = idx[j];
768 if (k < badex)
769 {
770 ccv_comp_t *box = (ccv_comp_t*)ccv_array_get(bad, k)((void*)(((char*)((bad)->data)) + (size_t)(bad)->rsize *
(size_t)(k)))
;
771 if (i == 0)
772 {
773 assert(box->neighbors >= 0 && box->neighbors < best_box.neighbors)((void) sizeof ((box->neighbors >= 0 && box->
neighbors < best_box.neighbors) ? 1 : 0), __extension__ ({
if (box->neighbors >= 0 && box->neighbors <
best_box.neighbors) ; else __assert_fail ("box->neighbors >= 0 && box->neighbors < best_box.neighbors"
, "ccv_tld.c", 773, __extension__ __PRETTY_FUNCTION__); }))
;
774 if (box->neighbors % r1 == r0 &&
775 _ccv_tld_box_variance(sat, sqsat, box->rect) > tld->var_thres)
776 {
777 // put them in order for faster access the next round
778 memcpy(pfern, tld->fern_buffer + box->neighbors * tld->ferns->structs, sizeof(uint32_t) * tld->ferns->structs);
779 // fix the thresholding for negative
780 if (ccv_ferns_predict(tld->ferns, pfern) >= tld->ferns->threshold)
781 ccv_ferns_correct(tld->ferns, pfern, 0, 2); // just feel like to use 2
782 pfern += tld->ferns->structs;
783 } else
784 box->neighbors = -1;
785 } else {
786 if (box->neighbors < 0)
787 continue;
788 if (ccv_ferns_predict(tld->ferns, pfern) >= tld->ferns->threshold)
789 ccv_ferns_correct(tld->ferns, pfern, 0, 2); // just feel like to use 2
790 pfern += tld->ferns->structs;
791 }
792 } else {
793 ccv_comp_t *box = (ccv_comp_t*)ccv_array_get(good, k - badex)((void*)(((char*)((good)->data)) + (size_t)(good)->rsize
* (size_t)(k - badex)))
;
794 _ccv_tld_ferns_feature_for(tld->ferns, ga, *box, fern, dsfmt, tld->params.track_deform_angle, tld->params.track_deform_scale, tld->params.track_deform_shift);
795 // fix the thresholding for positive
796 if (ccv_ferns_predict(tld->ferns, fern) <= tld->ferns_thres)
797 ccv_ferns_correct(tld->ferns, fern, 1, 1);
798 }
799 }
800 }
801 ccfreefree(fern);
802 ccv_array_free(bad);
803 ccv_array_free(good);
804 ccfreefree(idx);
805 // train the nearest-neighbor classifier
806 ccv_dense_matrix_t* b = 0;
807 _ccv_tld_fetch_patch(tld, ga, &b, 0, best_box.rect);
808 if (_ccv_tld_sv_correct(tld, b, 1) != 0)
809 ccv_matrix_free(b);
810 for (i = 0; i < tld->top->rnum; i++)
811 {
812 ccv_comp_t* box = (ccv_comp_t*)ccv_array_get(tld->top, i)((void*)(((char*)((tld->top)->data)) + (size_t)(tld->
top)->rsize * (size_t)(i)))
;
813 if (_ccv_tld_rect_intersect(box->rect, best_box.rect) < tld->params.exclude_overlap)
814 {
815 ccv_dense_matrix_t* b = 0;
816 _ccv_tld_fetch_patch(tld, ga, &b, 0, box->rect);
817 if (_ccv_tld_sv_correct(tld, b, 0) != 0)
818 ccv_matrix_free(b);
819 }
820 }
821 // shuffle them
822 sfmt_genrand_shuffle(sfmt, ccv_array_get(tld->sv[0], 0)((void*)(((char*)((tld->sv[0])->data)) + (size_t)(tld->
sv[0])->rsize * (size_t)(0)))
, tld->sv[0]->rnum, sizeof(ccv_dense_matrix_t*));
823 sfmt_genrand_shuffle(sfmt, ccv_array_get(tld->sv[1], 0)((void*)(((char*)((tld->sv[1])->data)) + (size_t)(tld->
sv[1])->rsize * (size_t)(0)))
, tld->sv[1]->rnum, sizeof(ccv_dense_matrix_t*));
824 return 0;
825 }
826 return -1;
827}
828
829static ccv_array_t* _ccv_tld_long_term_detect(ccv_tld_t* tld, ccv_dense_matrix_t* ga, ccv_dense_matrix_t* sat, ccv_dense_matrix_t* sqsat, ccv_tld_info_t* info)
830{
831 int i = 0, r0 = tld->count % (tld->params.rotation + 1), r1 = tld->params.rotation + 1;
832 tld->top->rnum = 0;
833 uint32_t* fern = tld->fern_buffer;
834 for_each_box(box, tld->patch.width, tld->patch.height, tld->params.interval, tld->params.shift, ga->cols, ga->rows){ { double scale834 = pow(2.0, 1.0 / (tld->params.interval
+ 1.0)); int scale_upto834 = (int)(log((double)({ typeof ((double
)ga->cols / tld->patch.width) _a = ((double)ga->cols
/ tld->patch.width); typeof ((double)ga->rows / tld->
patch.height) _b = ((double)ga->rows / tld->patch.height
); (_a < _b) ? _a : _b; })) / log(scale834)); int s834; double
ss834 = 1.0; for (s834 = 0; s834 < scale_upto834; s834++)
{ int width834 = (int)(tld->patch.width * ss834 + 0.5); int
height834 = (int)(tld->patch.height * ss834 + 0.5); ss834
*= scale834; if (width834 > ga->cols || height834 >
ga->rows) break; float x834, y834; int min_side834 = ({ typeof
(width834) _a = (width834); typeof (height834) _b = (height834
); (_a < _b) ? _a : _b; }); int piy834 = -1; for (y834 = 0
; y834 < ga->rows - height834 - 0.5; y834 += tld->params
.shift * min_side834) { int iy834 = (int)(y834 + 0.5); if (iy834
== piy834) continue; piy834 = iy834; int pix834 = -1; for (x834
= 0; x834 < ga->cols - width834 - 0.5; x834 += tld->
params.shift * min_side834) { int ix834 = (int)(x834 + 0.5); if
(ix834 == pix834) continue; pix834 = ix834; ccv_comp_t box; box
.rect = ccv_rect(ix834, iy834, width834, height834); box.classification
.id = s834;
835 if (i % r1 == r0 &&
836 _ccv_tld_box_variance(sat, sqsat, box.rect) > tld->var_thres)
837 {
838 _ccv_tld_ferns_feature_for(tld->ferns, ga, box, fern, 0, 0, 0, 0);
839 box.classification.confidence = ccv_ferns_predict(tld->ferns, fern);
840 if (box.classification.confidence > tld->ferns_thres)
841 {
842 if (tld->top->rnum < tld->params.top_n)
843 {
844 ccv_array_push(tld->top, &box);
845 _ccv_tld_box_percolate_up(tld->top, tld->top->rnum - 1);
846 } else {
847 ccv_comp_t* top_box = (ccv_comp_t*)ccv_array_get(tld->top, 0)((void*)(((char*)((tld->top)->data)) + (size_t)(tld->
top)->rsize * (size_t)(0)))
;
848 if (top_box->classification.confidence < box.classification.confidence)
849 {
850 *(ccv_comp_t*)ccv_array_get(tld->top, 0)((void*)(((char*)((tld->top)->data)) + (size_t)(tld->
top)->rsize * (size_t)(0)))
= box;
851 _ccv_tld_box_percolate_down(tld->top, 0);
852 }
853 }
854 }
855 }
856 fern += tld->ferns->structs;
857 ++i;
858 end_for_each_box} } } } };
859 ccv_array_t* seq = ccv_array_new(sizeof(ccv_comp_t), tld->top->rnum, 0);
860 for (i = 0; i < tld->top->rnum; i++)
861 {
862 ccv_comp_t* box = (ccv_comp_t*)ccv_array_get(tld->top, i)((void*)(((char*)((tld->top)->data)) + (size_t)(tld->
top)->rsize * (size_t)(i)))
;
863 int anyp = 0, anyn = 0;
864 ccv_dense_matrix_t* b = 0;
865 _ccv_tld_fetch_patch(tld, ga, &b, 0, box->rect);
866 float c = _ccv_tld_sv_classify(tld, b, 0, 0, &anyp, &anyn);
867 if (c > tld->nnc_thres)
868 {
869 // save only the conservative confidence (50% samples)
870 box->classification.confidence = _ccv_tld_sv_classify(tld, b, ccv_max((int)(tld->sv[1]->rnum * tld->params.validate_set + 0.5), 1)({ typeof ((int)(tld->sv[1]->rnum * tld->params.validate_set
+ 0.5)) _a = ((int)(tld->sv[1]->rnum * tld->params.
validate_set + 0.5)); typeof (1) _b = (1); (_a > _b) ? _a :
_b; })
, 0, &anyp, &anyn);
871 ccv_array_push(seq, box);
872 }
873 ccv_matrix_free(b);
874 }
875 return seq;
876}
877
878static int _ccv_is_equal(const void* _r1, const void* _r2, void* data)
879{
880 const ccv_comp_t* r1 = (const ccv_comp_t*)_r1;
881 const ccv_comp_t* r2 = (const ccv_comp_t*)_r2;
882 return _ccv_tld_rect_intersect(r1->rect, r2->rect) > 0.5;
883}
884
885// since there is no refcount syntax for ccv yet, we won't implicitly retain any matrix in ccv_tld_t
886// instead, you should pass the previous frame and the current frame into the track function
887ccv_comp_t ccv_tld_track_object(ccv_tld_t* tld, ccv_dense_matrix_t* a, ccv_dense_matrix_t* b, ccv_tld_info_t* info)
888{
889 ccv_comp_t result;
890 int tracked = 0;
891 int verified = 0;
892 assert(tld->frame_signature == a->sig)((void) sizeof ((tld->frame_signature == a->sig) ? 1 : 0
), __extension__ ({ if (tld->frame_signature == a->sig)
; else __assert_fail ("tld->frame_signature == a->sig"
, "ccv_tld.c", 892, __extension__ __PRETTY_FUNCTION__); }))
;
1
Assuming field 'frame_signature' is equal to field 'sig'
2
Taking true branch
893 ccv_dense_matrix_t* gb = 0;
894 ccv_blur(b, &gb, 0, 1.5);
895 if (info)
3
Assuming 'info' is null
4
Taking false branch
896 info->perform_track = tld->found;
897 if (tld->found)
5
Assuming field 'found' is 0
6
Taking false branch
898 {
899 result.rect = _ccv_tld_short_term_track(a, b, tld->box.rect, tld->params);
900 if (!ccv_rect_is_zero(result.rect))
901 {
902 float scale = sqrtf((float)(result.rect.width * result.rect.height) / (tld->patch.width * tld->patch.height));
903 // regularize the rect to conform patch's aspect ratio
904 result.rect = ccv_rect((int)(result.rect.x + (result.rect.width - tld->patch.width * scale) + 0.5),
905 (int)(result.rect.y + (result.rect.height - tld->patch.height * scale) + 0.5),
906 (int)(tld->patch.width * scale + 0.5),
907 (int)(tld->patch.height * scale + 0.5));
908 tracked = 1;
909 verified = tld->verified; // inherit it is verified from last frame
910 int anyp = 0, anyn = 0;
911 ccv_dense_matrix_t* c = 0;
912 _ccv_tld_fetch_patch(tld, gb, &c, 0, result.rect);
913 result.classification.confidence = _ccv_tld_sv_classify(tld, c, 0, 0, &anyp, &anyn);
914 ccv_matrix_free(c);
915 if (result.classification.confidence > tld->nnc_verify_thres)
916 verified = 1;
917 }
918 }
919 if (info
6.1
'info' is null
)
7
Taking false branch
920 info->track_success = tracked;
921 ccv_dense_matrix_t* sat = 0;
922 ccv_sat(b, &sat, 0, CCV_NO_PADDING);
923 ccv_dense_matrix_t* sq = 0;
924 ccv_multiply(b, b, (ccv_matrix_t**)&sq, 0);
925 ccv_dense_matrix_t* sqsat = 0;
926 ccv_sat(sq, &sqsat, 0, CCV_NO_PADDING);
927 ccv_matrix_free(sq);
928 ccv_array_t* dd = _ccv_tld_long_term_detect(tld, gb, sat, sqsat, info);
929 if (info
7.1
'info' is null
)
8
Taking false branch
930 {
931 info->ferns_detects = tld->top->rnum;
932 info->nnc_detects = dd->rnum;
933 }
934 int i;
935 // cluster detected result
936 if (dd->rnum > 1)
9
Assuming field 'rnum' is > 1
10
Taking true branch
937 {
938 ccv_array_t* idx_dd = 0;
939 // group retrieved rectangles in order to filter out noise
940 int ncomp = ccv_array_group(dd, &idx_dd, _ccv_is_equal, 0);
941 ccv_comp_t* comps = (ccv_comp_t*)ccmallocmalloc(ncomp * sizeof(ccv_comp_t));
942 memset(comps, 0, ncomp * sizeof(ccv_comp_t));
11
The value 0 is assigned to field 'neighbors'
943 for (i = 0; i < dd->rnum; i++)
12
Assuming 'i' is >= field 'rnum'
13
Loop condition is false. Execution continues on line 954
944 {
945 ccv_comp_t r1 = *(ccv_comp_t*)ccv_array_get(dd, i)((void*)(((char*)((dd)->data)) + (size_t)(dd)->rsize * (
size_t)(i)))
;
946 int idx = *(int*)ccv_array_get(idx_dd, i)((void*)(((char*)((idx_dd)->data)) + (size_t)(idx_dd)->
rsize * (size_t)(i)))
;
947 ++comps[idx].neighbors;
948 comps[idx].rect.x += r1.rect.x;
949 comps[idx].rect.y += r1.rect.y;
950 comps[idx].rect.width += r1.rect.width;
951 comps[idx].rect.height += r1.rect.height;
952 comps[idx].classification.confidence += r1.classification.confidence;
953 }
954 ccv_array_clear(dd);
955 for(i = 0; i < ncomp; i++)
14
Assuming 'i' is < 'ncomp'
15
Loop condition is true. Entering loop body
956 {
957 int n = comps[i].neighbors;
16
'n' initialized to 0
958 ccv_comp_t comp;
959 comp.rect.x = (comps[i].rect.x * 2 + n) / (2 * n);
17
Division by zero
960 comp.rect.y = (comps[i].rect.y * 2 + n) / (2 * n);
961 comp.rect.width = (comps[i].rect.width * 2 + n) / (2 * n);
962 comp.rect.height = (comps[i].rect.height * 2 + n) / (2 * n);
963 comp.neighbors = comps[i].neighbors;
964 comp.classification.confidence = comps[i].classification.confidence / n;
965 ccv_array_push(dd, &comp);
966 }
967 ccv_array_free(idx_dd);
968 ccfreefree(comps);
969 }
970 if (info)
971 {
972 info->clustered_detects = dd->rnum;
973 info->confident_matches = info->close_matches = 0;
974 }
975 if (tracked)
976 {
977 if (dd->rnum > 0)
978 {
979 ccv_comp_t* ddcomp = 0;
980 int confident_matches = 0;
981 for (i = 0; i < dd->rnum; i++)
982 {
983 ccv_comp_t* comp = (ccv_comp_t*)ccv_array_get(dd, i)((void*)(((char*)((dd)->data)) + (size_t)(dd)->rsize * (
size_t)(i)))
;
984 if (_ccv_tld_rect_intersect(result.rect, comp->rect) < 0.5 && comp->classification.confidence > result.classification.confidence)
985 {
986 ++confident_matches;
987 ddcomp = comp;
988 }
989 }
990 if (info)
991 info->confident_matches = confident_matches;
992 if (confident_matches == 1)
993 {
994 // only one match, reinitialize tracking
995 result = *ddcomp;
996 // but the result is not a valid tracking
997 verified = 0;
998 } else {
999 // too much confident matches, we will focus on close matches instead
1000 int close_matches = 0;
1001 ccv_rect_t ddc = ccv_rect(0, 0, 0, 0);
1002 for (i = 0; i < dd->rnum; i++)
1003 {
1004 ccv_comp_t* comp = (ccv_comp_t*)ccv_array_get(dd, i)((void*)(((char*)((dd)->data)) + (size_t)(dd)->rsize * (
size_t)(i)))
;
1005 if (_ccv_tld_rect_intersect(result.rect, comp->rect) > 0.7)
1006 {
1007 ddc.y += comp->rect.y;
1008 ddc.x += comp->rect.x;
1009 ddc.height += comp->rect.height;
1010 ddc.width += comp->rect.width;
1011 ++close_matches;
1012 }
1013 }
1014 if (info)
1015 info->close_matches = close_matches;
1016 if (close_matches > 0)
1017 {
1018 // reweight the tracking result
1019 result.rect.x = (20 * result.rect.x + ddc.x * 2 + close_matches + 10) / (20 + 2 * close_matches);
1020 result.rect.y = (20 * result.rect.y + ddc.y * 2 + close_matches + 10) / (20 + 2 * close_matches);
1021 result.rect.width = (20 * result.rect.width + ddc.width * 2 + close_matches + 10) / (20 + 2 * close_matches);
1022 result.rect.height = (20 * result.rect.height + ddc.height * 2 + close_matches + 10) / (20 + 2 * close_matches);
1023 }
1024 }
1025 }
1026 } else if (dd->rnum == 1) {
1027 // only reinitialize tracker when detection result is exactly one
1028 result = *(ccv_comp_t*)ccv_array_get(dd, 0)((void*)(((char*)((dd)->data)) + (size_t)(dd)->rsize * (
size_t)(0)))
;
1029 tld->found = 1;
1030 } else {
1031 // failed to found anything
1032 tld->found = 0;
1033 }
1034 ccv_array_free(dd);
1035 if (info)
1036 info->perform_learn = verified;
1037 if (verified)
1038 verified = (_ccv_tld_quick_learn(tld, gb, sat, sqsat, result) == 0);
1039 ccv_matrix_free(sqsat);
1040 ccv_matrix_free(sat);
1041 ccv_matrix_free(gb);
1042 tld->verified = verified;
1043 tld->box = result;
1044 tld->frame_signature = b->sig;
1045 ++tld->count;
1046 return result;
1047}
1048
1049void ccv_tld_free(ccv_tld_t* tld)
1050{
1051 int i;
1052 ccfreefree(tld->dsfmt);
1053 ccfreefree(tld->sfmt);
1054 for (i = 0; i < tld->sv[0]->rnum; i++)
1055 ccv_matrix_free(*(ccv_dense_matrix_t**)ccv_array_get(tld->sv[0], i)((void*)(((char*)((tld->sv[0])->data)) + (size_t)(tld->
sv[0])->rsize * (size_t)(i)))
);
1056 ccv_array_free(tld->sv[0]);
1057 for (i = 0; i < tld->sv[1]->rnum; i++)
1058 ccv_matrix_free(*(ccv_dense_matrix_t**)ccv_array_get(tld->sv[1], i)((void*)(((char*)((tld->sv[1])->data)) + (size_t)(tld->
sv[1])->rsize * (size_t)(i)))
);
1059 ccv_array_free(tld->sv[1]);
1060 ccv_array_free(tld->top);
1061 ccv_ferns_free(tld->ferns);
1062 ccfreefree(tld);
1063}