Bug Summary

File:ccv_bbf.c
Warning:line 1266, column 39
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ccv_bbf.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -mrelocation-model static -mthread-model posix -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fno-trapping-math -ffp-contract=fast -ffast-math -ffinite-math-only -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -target-feature +sse2 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -resource-dir /usr/local/lib/clang/8.0.0 -I . -I /usr/local/cuda/include -D HAVE_CBLAS -D HAVE_LIBPNG -D HAVE_LIBJPEG -D HAVE_FFTW3 -D HAVE_PTHREAD -D HAVE_UCONTEXT -D HAVE_LIBLINEAR -D HAVE_TESSERACT -D HAVE_AVCODEC -D HAVE_AVFORMAT -D HAVE_AVUTIL -D HAVE_SWSCALE -D USE_DISPATCH -D HAVE_SSE2 -D HAVE_GSL -D HAVE_CUDA -D HAVE_CUDNN -D HAVE_NCCL -I /usr/local/include -internal-isystem /usr/local/include -internal-isystem /usr/local/lib/clang/8.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -fdebug-compilation-dir /home/liu/buildslave/linux-x64-runtests/build/lib -ferror-limit 19 -fmessage-length 0 -fblocks -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -o /home/liu/buildslave/public_html/analyze/2019-05-04-163002-105371-1 -x c ccv_bbf.c -faddrsig
1#include "ccv.h"
2#include "ccv_internal.h"
3#include <sys/time.h>
4#ifdef HAVE_GSL1
5#include <gsl/gsl_rng.h>
6#include <gsl/gsl_randist.h>
7#endif
8#ifdef USE_OPENMP
9#include <omp.h>
10#endif
11
12const ccv_bbf_param_t ccv_bbf_default_params = {
13 .interval = 5,
14 .min_neighbors = 2,
15 .accurate = 1,
16 .flags = 0,
17 .size = {
18 24,
19 24,
20 },
21};
22
23#define _ccv_width_padding(x)(((x) + 3) & -4) (((x) + 3) & -4)
24
25static inline int _ccv_run_bbf_feature(ccv_bbf_feature_t* feature, int* step, unsigned char** u8)
26{
27#define pf_at(i) (*(u8[feature->pz[i]] + feature->px[i] + feature->py[i] * step[feature->pz[i]]))
28#define nf_at(i) (*(u8[feature->nz[i]] + feature->nx[i] + feature->ny[i] * step[feature->nz[i]]))
29 unsigned char pmin = pf_at(0), nmax = nf_at(0);
30 /* check if every point in P > every point in N, and take a shortcut */
31 if (pmin <= nmax)
32 return 0;
33 int i;
34 for (i = 1; i < feature->size; i++)
35 {
36 if (feature->pz[i] >= 0)
37 {
38 int p = pf_at(i);
39 if (p < pmin)
40 {
41 if (p <= nmax)
42 return 0;
43 pmin = p;
44 }
45 }
46 if (feature->nz[i] >= 0)
47 {
48 int n = nf_at(i);
49 if (n > nmax)
50 {
51 if (pmin <= n)
52 return 0;
53 nmax = n;
54 }
55 }
56 }
57#undef pf_at
58#undef nf_at
59 return 1;
60}
61
62static int _ccv_read_bbf_stage_classifier(const char* file, ccv_bbf_stage_classifier_t* classifier)
63{
64 FILE* r = fopen(file, "r");
65 if (r == 0) return -1;
66 int stat = 0;
67 stat |= fscanf(r, "%d", &classifier->count);
68 union { float fl; int i; } fli;
69 stat |= fscanf(r, "%d", &fli.i);
70 classifier->threshold = fli.fl;
71 classifier->feature = (ccv_bbf_feature_t*)ccmallocmalloc(classifier->count * sizeof(ccv_bbf_feature_t));
72 classifier->alpha = (float*)ccmallocmalloc(classifier->count * 2 * sizeof(float));
73 int i, j;
74 for (i = 0; i < classifier->count; i++)
75 {
76 stat |= fscanf(r, "%d", &classifier->feature[i].size);
77 for (j = 0; j < classifier->feature[i].size; j++)
78 {
79 stat |= fscanf(r, "%d %d %d", &classifier->feature[i].px[j], &classifier->feature[i].py[j], &classifier->feature[i].pz[j]);
80 stat |= fscanf(r, "%d %d %d", &classifier->feature[i].nx[j], &classifier->feature[i].ny[j], &classifier->feature[i].nz[j]);
81 }
82 union { float fl; int i; } flia, flib;
83 stat |= fscanf(r, "%d %d", &flia.i, &flib.i);
84 classifier->alpha[i * 2] = flia.fl;
85 classifier->alpha[i * 2 + 1] = flib.fl;
86 }
87 fclose(r);
88 return 0;
89}
90
91#ifdef HAVE_GSL1
92
93static unsigned int _ccv_bbf_time_measure()
94{
95 struct timeval tv;
96 gettimeofday(&tv, 0);
97 return tv.tv_sec * 1000000 + tv.tv_usec;
98}
99
100#define less_than(a, b, aux) ((a) < (b))
101CCV_IMPLEMENT_QSORT(_ccv_sort_32f, float, less_than)void _ccv_sort_32f(float *array, size_t total, int aux) { int
isort_thresh = 7; float t; int sp = 0; struct { float *lb; float
*ub; } stack[48]; if( total <= 1 ) return; stack[0].lb = array
; stack[0].ub = array + (total - 1); while( sp >= 0 ) { float
* left = stack[sp].lb; float* right = stack[sp--].ub; for(;;)
{ int i, n = (int)(right - left) + 1, m; float* ptr; float* ptr2
; if( n <= isort_thresh ) { insert_sort: for( ptr = left +
1; ptr <= right; ptr++ ) { for( ptr2 = ptr; ptr2 > left
&& less_than(ptr2[0],ptr2[-1], aux); ptr2--) (((t)) =
((ptr2[0])), ((ptr2[0])) = ((ptr2[-1])), ((ptr2[-1])) = ((t)
)); } break; } else { float* left0; float* left1; float* right0
; float* right1; float* pivot; float* a; float* b; float* c; int
swap_cnt = 0; left0 = left; right0 = right; pivot = left + (
n/2); if( n > 40 ) { int d = n / 8; a = left, b = left + d
, c = left + 2*d; left = less_than(*a, *b, aux) ? (less_than(
*b, *c, aux) ? b : (less_than(*a, *c, aux) ? c : a)) : (less_than
(*c, *b, aux) ? b : (less_than(*a, *c, aux) ? a : c)); a = pivot
- d, b = pivot, c = pivot + d; pivot = less_than(*a, *b, aux
) ? (less_than(*b, *c, aux) ? b : (less_than(*a, *c, aux) ? c
: a)) : (less_than(*c, *b, aux) ? b : (less_than(*a, *c, aux
) ? a : c)); a = right - 2*d, b = right - d, c = right; right
= less_than(*a, *b, aux) ? (less_than(*b, *c, aux) ? b : (less_than
(*a, *c, aux) ? c : a)) : (less_than(*c, *b, aux) ? b : (less_than
(*a, *c, aux) ? a : c)); } a = left, b = pivot, c = right; pivot
= less_than(*a, *b, aux) ? (less_than(*b, *c, aux) ? b : (less_than
(*a, *c, aux) ? c : a)) : (less_than(*c, *b, aux) ? b : (less_than
(*a, *c, aux) ? a : c)); if( pivot != left0 ) { (((t)) = ((*pivot
)), ((*pivot)) = ((*left0)), ((*left0)) = ((t))); pivot = left0
; } left = left1 = left0 + 1; right = right1 = right0; for(;;
) { while( left <= right && !less_than(*pivot, *left
, aux) ) { if( !less_than(*left, *pivot, aux) ) { if( left >
left1 ) (((t)) = ((*left1)), ((*left1)) = ((*left)), ((*left
)) = ((t))); swap_cnt = 1; left1++; } left++; } while( left <=
right && !less_than(*right, *pivot, aux) ) { if( !less_than
(*pivot, *right, aux) ) { if( right < right1 ) (((t)) = ((
*right1)), ((*right1)) = ((*right)), ((*right)) = ((t))); swap_cnt
= 1; right1--; } right--; } if( left > right ) break; (((
t)) = ((*left)), ((*left)) = ((*right)), ((*right)) = ((t)));
swap_cnt = 1; left++; right--; } if( swap_cnt == 0 ) { left =
left0, right = right0; goto insert_sort; } n = ({ typeof ((int
)(left1 - left0)) _a = ((int)(left1 - left0)); typeof ((int)(
left - left1)) _b = ((int)(left - left1)); (_a < _b) ? _a :
_b; }); for( i = 0; i < n; i++ ) (((t)) = ((left0[i])), (
(left0[i])) = ((left[i-n])), ((left[i-n])) = ((t))); n = ({ typeof
((int)(right0 - right1)) _a = ((int)(right0 - right1)); typeof
((int)(right1 - right)) _b = ((int)(right1 - right)); (_a <
_b) ? _a : _b; }); for( i = 0; i < n; i++ ) (((t)) = ((left
[i])), ((left[i])) = ((right0[i-n+1])), ((right0[i-n+1])) = (
(t))); n = (int)(left - left1); m = (int)(right1 - right); if
( n > 1 ) { if( m > 1 ) { if( n > m ) { stack[++sp].
lb = left0; stack[sp].ub = left0 + n - 1; left = right0 - m +
1, right = right0; } else { stack[++sp].lb = right0 - m + 1;
stack[sp].ub = right0; left = left0, right = left0 + n - 1; }
} else left = left0, right = left0 + n - 1; } else if( m >
1 ) left = right0 - m + 1, right = right0; else break; } } }
}
102#undef less_than
103
104static void _ccv_bbf_eval_data(ccv_bbf_stage_classifier_t* classifier, unsigned char** posdata, int posnum, unsigned char** negdata, int negnum, ccv_size_t size, float* peval, float* neval)
105{
106 int i, j;
107 int steps[] = { _ccv_width_padding(size.width)(((size.width) + 3) & -4),
108 _ccv_width_padding(size.width >> 1)(((size.width >> 1) + 3) & -4),
109 _ccv_width_padding(size.width >> 2)(((size.width >> 2) + 3) & -4) };
110 int isizs0 = steps[0] * size.height;
111 int isizs01 = isizs0 + steps[1] * (size.height >> 1);
112 for (i = 0; i < posnum; i++)
113 {
114 unsigned char* u8[] = { posdata[i], posdata[i] + isizs0, posdata[i] + isizs01 };
115 float sum = 0;
116 float* alpha = classifier->alpha;
117 ccv_bbf_feature_t* feature = classifier->feature;
118 for (j = 0; j < classifier->count; ++j, alpha += 2, ++feature)
119 sum += alpha[_ccv_run_bbf_feature(feature, steps, u8)];
120 peval[i] = sum;
121 }
122 for (i = 0; i < negnum; i++)
123 {
124 unsigned char* u8[] = { negdata[i], negdata[i] + isizs0, negdata[i] + isizs01 };
125 float sum = 0;
126 float* alpha = classifier->alpha;
127 ccv_bbf_feature_t* feature = classifier->feature;
128 for (j = 0; j < classifier->count; ++j, alpha += 2, ++feature)
129 sum += alpha[_ccv_run_bbf_feature(feature, steps, u8)];
130 neval[i] = sum;
131 }
132}
133
134static int _ccv_prune_positive_data(ccv_bbf_classifier_cascade_t* cascade, unsigned char** posdata, int posnum, ccv_size_t size)
135{
136 float* peval = (float*)ccmallocmalloc(posnum * sizeof(float));
137 int i, j, k, rpos = posnum;
138 for (i = 0; i < cascade->count; i++)
139 {
140 _ccv_bbf_eval_data(cascade->stage_classifier + i, posdata, rpos, 0, 0, size, peval, 0);
141 k = 0;
142 for (j = 0; j < rpos; j++)
143 if (peval[j] >= cascade->stage_classifier[i].threshold)
144 {
145 posdata[k] = posdata[j];
146 ++k;
147 } else {
148 ccfreefree(posdata[j]);
149 }
150 rpos = k;
151 }
152 ccfreefree(peval);
153 return rpos;
154}
155
156static int _ccv_prepare_background_data(ccv_bbf_classifier_cascade_t* cascade, char** bgfiles, int bgnum, unsigned char** negdata, int negnum)
157{
158 int t, i, j, k, q;
159 int negperbg;
160 int negtotal = 0;
161 int steps[] = { _ccv_width_padding(cascade->size.width)(((cascade->size.width) + 3) & -4),
162 _ccv_width_padding(cascade->size.width >> 1)(((cascade->size.width >> 1) + 3) & -4),
163 _ccv_width_padding(cascade->size.width >> 2)(((cascade->size.width >> 2) + 3) & -4) };
164 int isizs0 = steps[0] * cascade->size.height;
165 int isizs1 = steps[1] * (cascade->size.height >> 1);
166 int isizs2 = steps[2] * (cascade->size.height >> 2);
167 int* idcheck = (int*)ccmallocmalloc(negnum * sizeof(int));
168
169 gsl_rng_env_setup();
170
171 gsl_rng* rng = gsl_rng_alloc(gsl_rng_default);
172 gsl_rng_set(rng, (unsigned long int)idcheck);
173
174 ccv_size_t imgsz = cascade->size;
175 int rneg = negtotal;
176 for (t = 0; negtotal < negnum; t++)
177 {
178 PRINT(CCV_CLI_INFO, "preparing negative data ... 0%%")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("preparing negative data ... 0%%"); fflush(stdout); } } while
(0)
;
179 for (i = 0; i < bgnum; i++)
180 {
181 negperbg = (t < 2) ? (negnum - negtotal) / (bgnum - i) + 1 : negnum - negtotal;
182 ccv_dense_matrix_t* image = 0;
183 ccv_read(bgfiles[i], &image, CCV_IO_GRAY | CCV_IO_ANY_FILE)ccv_read_impl(bgfiles[i], &image, CCV_IO_GRAY | CCV_IO_ANY_FILE
, 0, 0, 0)
;
184 assert((image->type & CCV_C1) && (image->type & CCV_8U))((void) sizeof (((image->type & CCV_C1) && (image
->type & CCV_8U)) ? 1 : 0), __extension__ ({ if ((image
->type & CCV_C1) && (image->type & CCV_8U
)) ; else __assert_fail ("(image->type & CCV_C1) && (image->type & CCV_8U)"
, "ccv_bbf.c", 184, __extension__ __PRETTY_FUNCTION__); }))
;
185 if (image == 0)
186 {
187 PRINT(CCV_CLI_ERROR, "\n%s file corrupted\n", bgfiles[i])do { if ((CCV_CLI_ERROR & ccv_cli_get_output_levels())) {
printf("\n%s file corrupted\n", bgfiles[i]); fflush(stdout);
} } while (0)
;
188 continue;
189 }
190 if (t % 2 != 0)
191 ccv_flip(image, 0, 0, CCV_FLIP_X);
192 if (t % 4 >= 2)
193 ccv_flip(image, 0, 0, CCV_FLIP_Y);
194 ccv_bbf_param_t params = { .interval = 3, .min_neighbors = 0, .accurate = 1, .flags = 0, .size = cascade->size };
195 ccv_array_t* detected = ccv_bbf_detect_objects(image, &cascade, 1, params);
196 memset(idcheck, 0, ccv_min(detected->rnum, negperbg)({ typeof (detected->rnum) _a = (detected->rnum); typeof
(negperbg) _b = (negperbg); (_a < _b) ? _a : _b; })
* sizeof(int));
197 for (j = 0; j < ccv_min(detected->rnum, negperbg)({ typeof (detected->rnum) _a = (detected->rnum); typeof
(negperbg) _b = (negperbg); (_a < _b) ? _a : _b; })
; j++)
198 {
199 int r = gsl_rng_uniform_int(rng, detected->rnum);
200 int flag = 1;
201 ccv_rect_t* rect = (ccv_rect_t*)ccv_array_get(detected, r)((void*)(((char*)((detected)->data)) + (size_t)(detected)->
rsize * (size_t)(r)))
;
202 while (flag) {
203 flag = 0;
204 for (k = 0; k < j; k++)
205 if (r == idcheck[k])
206 {
207 flag = 1;
208 r = gsl_rng_uniform_int(rng, detected->rnum);
209 break;
210 }
211 rect = (ccv_rect_t*)ccv_array_get(detected, r)((void*)(((char*)((detected)->data)) + (size_t)(detected)->
rsize * (size_t)(r)))
;
212 if ((rect->x < 0) || (rect->y < 0) || (rect->width + rect->x > image->cols) || (rect->height + rect->y > image->rows))
213 {
214 flag = 1;
215 r = gsl_rng_uniform_int(rng, detected->rnum);
216 }
217 }
218 idcheck[j] = r;
219 ccv_dense_matrix_t* temp = 0;
220 ccv_dense_matrix_t* imgs0 = 0;
221 ccv_dense_matrix_t* imgs1 = 0;
222 ccv_dense_matrix_t* imgs2 = 0;
223 ccv_slice(image, (ccv_matrix_t**)&temp, 0, rect->y, rect->x, rect->height, rect->width);
224 ccv_resample(temp, &imgs0, 0, imgsz.height, imgsz.width, CCV_INTER_AREA);
225 assert(imgs0->step == steps[0])((void) sizeof ((imgs0->step == steps[0]) ? 1 : 0), __extension__
({ if (imgs0->step == steps[0]) ; else __assert_fail ("imgs0->step == steps[0]"
, "ccv_bbf.c", 225, __extension__ __PRETTY_FUNCTION__); }))
;
226 ccv_matrix_free(temp);
227 ccv_sample_down(imgs0, &imgs1, 0, 0, 0);
228 assert(imgs1->step == steps[1])((void) sizeof ((imgs1->step == steps[1]) ? 1 : 0), __extension__
({ if (imgs1->step == steps[1]) ; else __assert_fail ("imgs1->step == steps[1]"
, "ccv_bbf.c", 228, __extension__ __PRETTY_FUNCTION__); }))
;
229 ccv_sample_down(imgs1, &imgs2, 0, 0, 0);
230 assert(imgs2->step == steps[2])((void) sizeof ((imgs2->step == steps[2]) ? 1 : 0), __extension__
({ if (imgs2->step == steps[2]) ; else __assert_fail ("imgs2->step == steps[2]"
, "ccv_bbf.c", 230, __extension__ __PRETTY_FUNCTION__); }))
;
231
232 negdata[negtotal] = (unsigned char*)ccmallocmalloc(isizs0 + isizs1 + isizs2);
233 unsigned char* u8s0 = negdata[negtotal];
234 unsigned char* u8s1 = negdata[negtotal] + isizs0;
235 unsigned char* u8s2 = negdata[negtotal] + isizs0 + isizs1;
236 unsigned char* u8[] = { u8s0, u8s1, u8s2 };
237 memcpy(u8s0, imgs0->data.u8, imgs0->rows * imgs0->step);
238 ccv_matrix_free(imgs0);
239 memcpy(u8s1, imgs1->data.u8, imgs1->rows * imgs1->step);
240 ccv_matrix_free(imgs1);
241 memcpy(u8s2, imgs2->data.u8, imgs2->rows * imgs2->step);
242 ccv_matrix_free(imgs2);
243
244 flag = 1;
245 ccv_bbf_stage_classifier_t* classifier = cascade->stage_classifier;
246 for (k = 0; k < cascade->count; ++k, ++classifier)
247 {
248 float sum = 0;
249 float* alpha = classifier->alpha;
250 ccv_bbf_feature_t* feature = classifier->feature;
251 for (q = 0; q < classifier->count; ++q, alpha += 2, ++feature)
252 sum += alpha[_ccv_run_bbf_feature(feature, steps, u8)];
253 if (sum < classifier->threshold)
254 {
255 flag = 0;
256 break;
257 }
258 }
259 if (!flag)
260 ccfreefree(negdata[negtotal]);
261 else {
262 ++negtotal;
263 if (negtotal >= negnum)
264 break;
265 }
266 }
267 ccv_array_free(detected);
268 ccv_matrix_free(image);
269 ccv_drain_cache();
270 PRINT(CCV_CLI_INFO, "\rpreparing negative data ... %2d%%", 100 * negtotal / negnum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\rpreparing negative data ... %2d%%", 100 * negtotal / negnum
); fflush(stdout); } } while (0)
;
271 fflush(0);
272 if (negtotal >= negnum)
273 break;
274 }
275 if (rneg == negtotal)
276 break;
277 rneg = negtotal;
278 PRINT(CCV_CLI_INFO, "\nentering additional round %d\n", t + 1)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\nentering additional round %d\n", t + 1); fflush(stdout); }
} while (0)
;
279 }
280 gsl_rng_free(rng);
281 ccfreefree(idcheck);
282 ccv_drain_cache();
283 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
284 return negtotal;
285}
286
287static void _ccv_prepare_positive_data(ccv_dense_matrix_t** posimg, unsigned char** posdata, ccv_size_t size, int posnum)
288{
289 PRINT(CCV_CLI_INFO, "preparing positive data ... 0%%")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("preparing positive data ... 0%%"); fflush(stdout); } } while
(0)
;
290 int i;
291 for (i = 0; i < posnum; i++)
292 {
293 ccv_dense_matrix_t* imgs0 = posimg[i];
294 ccv_dense_matrix_t* imgs1 = 0;
295 ccv_dense_matrix_t* imgs2 = 0;
296 assert((imgs0->type & CCV_C1) && (imgs0->type & CCV_8U) && imgs0->rows == size.height && imgs0->cols == size.width)((void) sizeof (((imgs0->type & CCV_C1) && (imgs0
->type & CCV_8U) && imgs0->rows == size.height
&& imgs0->cols == size.width) ? 1 : 0), __extension__
({ if ((imgs0->type & CCV_C1) && (imgs0->type
& CCV_8U) && imgs0->rows == size.height &&
imgs0->cols == size.width) ; else __assert_fail ("(imgs0->type & CCV_C1) && (imgs0->type & CCV_8U) && imgs0->rows == size.height && imgs0->cols == size.width"
, "ccv_bbf.c", 296, __extension__ __PRETTY_FUNCTION__); }))
;
297 ccv_sample_down(imgs0, &imgs1, 0, 0, 0);
298 ccv_sample_down(imgs1, &imgs2, 0, 0, 0);
299 int isizs0 = imgs0->rows * imgs0->step;
300 int isizs1 = imgs1->rows * imgs1->step;
301 int isizs2 = imgs2->rows * imgs2->step;
302
303 posdata[i] = (unsigned char*)ccmallocmalloc(isizs0 + isizs1 + isizs2);
304 memcpy(posdata[i], imgs0->data.u8, isizs0);
305 memcpy(posdata[i] + isizs0, imgs1->data.u8, isizs1);
306 memcpy(posdata[i] + isizs0 + isizs1, imgs2->data.u8, isizs2);
307
308 PRINT(CCV_CLI_INFO, "\rpreparing positive data ... %2d%%", 100 * (i + 1) / posnum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\rpreparing positive data ... %2d%%", 100 * (i + 1) / posnum
); fflush(stdout); } } while (0)
;
309 fflush(0);
310
311 ccv_matrix_free(imgs1);
312 ccv_matrix_free(imgs2);
313 }
314 ccv_drain_cache();
315 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
316}
317
318typedef struct {
319 double fitness;
320 int pk, nk;
321 int age;
322 double error;
323 ccv_bbf_feature_t feature;
324} ccv_bbf_gene_t;
325
326static inline void _ccv_bbf_genetic_fitness(ccv_bbf_gene_t* gene)
327{
328 gene->fitness = (1 - gene->error) * exp(-0.01 * gene->age) * exp((gene->pk + gene->nk) * log(1.015));
329}
330
331static inline int _ccv_bbf_exist_gene_feature(ccv_bbf_gene_t* gene, int x, int y, int z)
332{
333 int i;
334 for (i = 0; i < gene->pk; i++)
335 if (z == gene->feature.pz[i] && x == gene->feature.px[i] && y == gene->feature.py[i])
336 return 1;
337 for (i = 0; i < gene->nk; i++)
338 if (z == gene->feature.nz[i] && x == gene->feature.nx[i] && y == gene->feature.ny[i])
339 return 1;
340 return 0;
341}
342
343static inline void _ccv_bbf_randomize_gene(gsl_rng* rng, ccv_bbf_gene_t* gene, int* rows, int* cols)
344{
345 int i;
346 do {
347 gene->pk = gsl_rng_uniform_int(rng, CCV_BBF_POINT_MAX(8) - 1) + 1;
348 gene->nk = gsl_rng_uniform_int(rng, CCV_BBF_POINT_MAX(8) - 1) + 1;
349 } while (gene->pk + gene->nk < CCV_BBF_POINT_MIN(3)); /* a hard restriction of at least 3 points have to be examed */
350 gene->feature.size = ccv_max(gene->pk, gene->nk)({ typeof (gene->pk) _a = (gene->pk); typeof (gene->
nk) _b = (gene->nk); (_a > _b) ? _a : _b; })
;
351 gene->age = 0;
352 for (i = 0; i < CCV_BBF_POINT_MAX(8); i++)
353 {
354 gene->feature.pz[i] = -1;
355 gene->feature.nz[i] = -1;
356 }
357 int x, y, z;
358 for (i = 0; i < gene->pk; i++)
359 {
360 do {
361 z = gsl_rng_uniform_int(rng, 3);
362 x = gsl_rng_uniform_int(rng, cols[z]);
363 y = gsl_rng_uniform_int(rng, rows[z]);
364 } while (_ccv_bbf_exist_gene_feature(gene, x, y, z));
365 gene->feature.pz[i] = z;
366 gene->feature.px[i] = x;
367 gene->feature.py[i] = y;
368 }
369 for (i = 0; i < gene->nk; i++)
370 {
371 do {
372 z = gsl_rng_uniform_int(rng, 3);
373 x = gsl_rng_uniform_int(rng, cols[z]);
374 y = gsl_rng_uniform_int(rng, rows[z]);
375 } while ( _ccv_bbf_exist_gene_feature(gene, x, y, z));
376 gene->feature.nz[i] = z;
377 gene->feature.nx[i] = x;
378 gene->feature.ny[i] = y;
379 }
380}
381
382static inline double _ccv_bbf_error_rate(ccv_bbf_feature_t* feature, unsigned char** posdata, int posnum, unsigned char** negdata, int negnum, ccv_size_t size, double* pw, double* nw)
383{
384 int i;
385 int steps[] = { _ccv_width_padding(size.width)(((size.width) + 3) & -4),
386 _ccv_width_padding(size.width >> 1)(((size.width >> 1) + 3) & -4),
387 _ccv_width_padding(size.width >> 2)(((size.width >> 2) + 3) & -4) };
388 int isizs0 = steps[0] * size.height;
389 int isizs01 = isizs0 + steps[1] * (size.height >> 1);
390 double error = 0;
391 for (i = 0; i < posnum; i++)
392 {
393 unsigned char* u8[] = { posdata[i], posdata[i] + isizs0, posdata[i] + isizs01 };
394 if (!_ccv_run_bbf_feature(feature, steps, u8))
395 error += pw[i];
396 }
397 for (i = 0; i < negnum; i++)
398 {
399 unsigned char* u8[] = { negdata[i], negdata[i] + isizs0, negdata[i] + isizs01 };
400 if ( _ccv_run_bbf_feature(feature, steps, u8))
401 error += nw[i];
402 }
403 return error;
404}
405
406#define less_than(fit1, fit2, aux) ((fit1).fitness >= (fit2).fitness)
407static CCV_IMPLEMENT_QSORT(_ccv_bbf_genetic_qsort, ccv_bbf_gene_t, less_than)void _ccv_bbf_genetic_qsort(ccv_bbf_gene_t *array, size_t total
, int aux) { int isort_thresh = 7; ccv_bbf_gene_t t; int sp =
0; struct { ccv_bbf_gene_t *lb; ccv_bbf_gene_t *ub; } stack[
48]; if( total <= 1 ) return; stack[0].lb = array; stack[0
].ub = array + (total - 1); while( sp >= 0 ) { ccv_bbf_gene_t
* left = stack[sp].lb; ccv_bbf_gene_t* right = stack[sp--].ub
; for(;;) { int i, n = (int)(right - left) + 1, m; ccv_bbf_gene_t
* ptr; ccv_bbf_gene_t* ptr2; if( n <= isort_thresh ) { insert_sort
: for( ptr = left + 1; ptr <= right; ptr++ ) { for( ptr2 =
ptr; ptr2 > left && less_than(ptr2[0],ptr2[-1], aux
); ptr2--) (((t)) = ((ptr2[0])), ((ptr2[0])) = ((ptr2[-1])), (
(ptr2[-1])) = ((t))); } break; } else { ccv_bbf_gene_t* left0
; ccv_bbf_gene_t* left1; ccv_bbf_gene_t* right0; ccv_bbf_gene_t
* right1; ccv_bbf_gene_t* pivot; ccv_bbf_gene_t* a; ccv_bbf_gene_t
* b; ccv_bbf_gene_t* c; int swap_cnt = 0; left0 = left; right0
= right; pivot = left + (n/2); if( n > 40 ) { int d = n /
8; a = left, b = left + d, c = left + 2*d; left = less_than(
*a, *b, aux) ? (less_than(*b, *c, aux) ? b : (less_than(*a, *
c, aux) ? c : a)) : (less_than(*c, *b, aux) ? b : (less_than(
*a, *c, aux) ? a : c)); a = pivot - d, b = pivot, c = pivot +
d; pivot = less_than(*a, *b, aux) ? (less_than(*b, *c, aux) ?
b : (less_than(*a, *c, aux) ? c : a)) : (less_than(*c, *b, aux
) ? b : (less_than(*a, *c, aux) ? a : c)); a = right - 2*d, b
= right - d, c = right; right = less_than(*a, *b, aux) ? (less_than
(*b, *c, aux) ? b : (less_than(*a, *c, aux) ? c : a)) : (less_than
(*c, *b, aux) ? b : (less_than(*a, *c, aux) ? a : c)); } a = left
, b = pivot, c = right; pivot = less_than(*a, *b, aux) ? (less_than
(*b, *c, aux) ? b : (less_than(*a, *c, aux) ? c : a)) : (less_than
(*c, *b, aux) ? b : (less_than(*a, *c, aux) ? a : c)); if( pivot
!= left0 ) { (((t)) = ((*pivot)), ((*pivot)) = ((*left0)), (
(*left0)) = ((t))); pivot = left0; } left = left1 = left0 + 1
; right = right1 = right0; for(;;) { while( left <= right &&
!less_than(*pivot, *left, aux) ) { if( !less_than(*left, *pivot
, aux) ) { if( left > left1 ) (((t)) = ((*left1)), ((*left1
)) = ((*left)), ((*left)) = ((t))); swap_cnt = 1; left1++; } left
++; } while( left <= right && !less_than(*right, *
pivot, aux) ) { if( !less_than(*pivot, *right, aux) ) { if( right
< right1 ) (((t)) = ((*right1)), ((*right1)) = ((*right))
, ((*right)) = ((t))); swap_cnt = 1; right1--; } right--; } if
( left > right ) break; (((t)) = ((*left)), ((*left)) = ((
*right)), ((*right)) = ((t))); swap_cnt = 1; left++; right--;
} if( swap_cnt == 0 ) { left = left0, right = right0; goto insert_sort
; } n = ({ typeof ((int)(left1 - left0)) _a = ((int)(left1 - left0
)); typeof ((int)(left - left1)) _b = ((int)(left - left1)); (
_a < _b) ? _a : _b; }); for( i = 0; i < n; i++ ) (((t))
= ((left0[i])), ((left0[i])) = ((left[i-n])), ((left[i-n])) =
((t))); n = ({ typeof ((int)(right0 - right1)) _a = ((int)(right0
- right1)); typeof ((int)(right1 - right)) _b = ((int)(right1
- right)); (_a < _b) ? _a : _b; }); for( i = 0; i < n;
i++ ) (((t)) = ((left[i])), ((left[i])) = ((right0[i-n+1])),
((right0[i-n+1])) = ((t))); n = (int)(left - left1); m = (int
)(right1 - right); if( n > 1 ) { if( m > 1 ) { if( n >
m ) { stack[++sp].lb = left0; stack[sp].ub = left0 + n - 1; left
= right0 - m + 1, right = right0; } else { stack[++sp].lb = right0
- m + 1; stack[sp].ub = right0; left = left0, right = left0 +
n - 1; } } else left = left0, right = left0 + n - 1; } else if
( m > 1 ) left = right0 - m + 1, right = right0; else break
; } } } }
408#undef less_than
409
410static ccv_bbf_feature_t _ccv_bbf_genetic_optimize(unsigned char** posdata, int posnum, unsigned char** negdata, int negnum, int ftnum, ccv_size_t size, double* pw, double* nw)
411{
412 ccv_bbf_feature_t best;
413 /* seed (random method) */
414 gsl_rng_env_setup();
415 gsl_rng* rng = gsl_rng_alloc(gsl_rng_default);
416 union { unsigned long int li; double db; } dbli;
417 dbli.db = pw[0] + nw[0];
418 gsl_rng_set(rng, dbli.li);
419 int i, j;
420 int pnum = ftnum * 100;
421 assert(pnum > 0)((void) sizeof ((pnum > 0) ? 1 : 0), __extension__ ({ if (
pnum > 0) ; else __assert_fail ("pnum > 0", "ccv_bbf.c"
, 421, __extension__ __PRETTY_FUNCTION__); }))
;
422 ccv_bbf_gene_t* gene = (ccv_bbf_gene_t*)ccmallocmalloc(pnum * sizeof(ccv_bbf_gene_t));
423 int rows[] = { size.height, size.height >> 1, size.height >> 2 };
424 int cols[] = { size.width, size.width >> 1, size.width >> 2 };
425 for (i = 0; i < pnum; i++)
426 _ccv_bbf_randomize_gene(rng, &gene[i], rows, cols);
427 unsigned int timer = _ccv_bbf_time_measure();
428#ifdef USE_OPENMP
429#pragma omp parallel for private(i) schedule(dynamic)
430#endif
431 for (i = 0; i < pnum; i++)
432 gene[i].error = _ccv_bbf_error_rate(&gene[i].feature, posdata, posnum, negdata, negnum, size, pw, nw);
433 timer = _ccv_bbf_time_measure() - timer;
434 for (i = 0; i < pnum; i++)
435 _ccv_bbf_genetic_fitness(&gene[i]);
436 double best_err = 1;
437 int rnum = ftnum * 39; /* number of randomize */
438 int mnum = ftnum * 40; /* number of mutation */
439 int hnum = ftnum * 20; /* number of hybrid */
440 /* iteration stop crit : best no change in 40 iterations */
441 int it = 0, t;
442 for (t = 0 ; it < 40; ++it, ++t)
443 {
444 int min_id = 0;
445 double min_err = gene[0].error;
446 for (i = 1; i < pnum; i++)
447 if (gene[i].error < min_err)
448 {
449 min_id = i;
450 min_err = gene[i].error;
451 }
452 min_err = gene[min_id].error = _ccv_bbf_error_rate(&gene[min_id].feature, posdata, posnum, negdata, negnum, size, pw, nw);
453 if (min_err < best_err)
454 {
455 best_err = min_err;
456 memcpy(&best, &gene[min_id].feature, sizeof(best));
457 PRINT(CCV_CLI_INFO, "best bbf feature with error %f\n|-size: %d\n|-positive point: ", best_err, best.size)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("best bbf feature with error %f\n|-size: %d\n|-positive point: "
, best_err, best.size); fflush(stdout); } } while (0)
;
458 for (i = 0; i < best.size; i++)
459 PRINT(CCV_CLI_INFO, "(%d %d %d), ", best.px[i], best.py[i], best.pz[i])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("(%d %d %d), ", best.px[i], best.py[i], best.pz[i]); fflush(
stdout); } } while (0)
;
460 PRINT(CCV_CLI_INFO, "\n|-negative point: ")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n|-negative point: "); fflush(stdout); } } while (0)
;
461 for (i = 0; i < best.size; i++)
462 PRINT(CCV_CLI_INFO, "(%d %d %d), ", best.nx[i], best.ny[i], best.nz[i])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("(%d %d %d), ", best.nx[i], best.ny[i], best.nz[i]); fflush(
stdout); } } while (0)
;
463 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
464 it = 0;
465 }
466 PRINT(CCV_CLI_INFO, "minimum error achieved in round %d(%d) : %f with %d ms\n", t, it, min_err, timer / 1000)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("minimum error achieved in round %d(%d) : %f with %d ms\n", t
, it, min_err, timer / 1000); fflush(stdout); } } while (0)
;
467 _ccv_bbf_genetic_qsort(gene, pnum, 0);
468 for (i = 0; i < ftnum; i++)
469 ++gene[i].age;
470 for (i = ftnum; i < ftnum + mnum; i++)
471 {
472 int parent = gsl_rng_uniform_int(rng, ftnum);
473 memcpy(gene + i, gene + parent, sizeof(ccv_bbf_gene_t));
474 /* three mutation strategy : 1. add, 2. remove, 3. refine */
475 int pnm, pn = gsl_rng_uniform_int(rng, 2);
476 int* pnk[] = { &gene[i].pk, &gene[i].nk };
477 int* pnx[] = { gene[i].feature.px, gene[i].feature.nx };
478 int* pny[] = { gene[i].feature.py, gene[i].feature.ny };
479 int* pnz[] = { gene[i].feature.pz, gene[i].feature.nz };
480 int x, y, z;
481 int victim, decay = 1;
482 do {
483 switch (gsl_rng_uniform_int(rng, 3))
484 {
485 case 0: /* add */
486 if (gene[i].pk == CCV_BBF_POINT_MAX(8) && gene[i].nk == CCV_BBF_POINT_MAX(8))
487 break;
488 while (*pnk[pn] + 1 > CCV_BBF_POINT_MAX(8))
489 pn = gsl_rng_uniform_int(rng, 2);
490 do {
491 z = gsl_rng_uniform_int(rng, 3);
492 x = gsl_rng_uniform_int(rng, cols[z]);
493 y = gsl_rng_uniform_int(rng, rows[z]);
494 } while (_ccv_bbf_exist_gene_feature(&gene[i], x, y, z));
495 pnz[pn][*pnk[pn]] = z;
496 pnx[pn][*pnk[pn]] = x;
497 pny[pn][*pnk[pn]] = y;
498 ++(*pnk[pn]);
499 gene[i].feature.size = ccv_max(gene[i].pk, gene[i].nk)({ typeof (gene[i].pk) _a = (gene[i].pk); typeof (gene[i].nk)
_b = (gene[i].nk); (_a > _b) ? _a : _b; })
;
500 decay = gene[i].age = 0;
501 break;
502 case 1: /* remove */
503 if (gene[i].pk + gene[i].nk <= CCV_BBF_POINT_MIN(3)) /* at least 3 points have to be examed */
504 break;
505 while (*pnk[pn] - 1 <= 0) // || *pnk[pn] + *pnk[!pn] - 1 < CCV_BBF_POINT_MIN)
506 pn = gsl_rng_uniform_int(rng, 2);
507 victim = gsl_rng_uniform_int(rng, *pnk[pn]);
508 for (j = victim; j < *pnk[pn] - 1; j++)
509 {
510 pnz[pn][j] = pnz[pn][j + 1];
511 pnx[pn][j] = pnx[pn][j + 1];
512 pny[pn][j] = pny[pn][j + 1];
513 }
514 pnz[pn][*pnk[pn] - 1] = -1;
515 --(*pnk[pn]);
516 gene[i].feature.size = ccv_max(gene[i].pk, gene[i].nk)({ typeof (gene[i].pk) _a = (gene[i].pk); typeof (gene[i].nk)
_b = (gene[i].nk); (_a > _b) ? _a : _b; })
;
517 decay = gene[i].age = 0;
518 break;
519 case 2: /* refine */
520 pnm = gsl_rng_uniform_int(rng, *pnk[pn]);
521 do {
522 z = gsl_rng_uniform_int(rng, 3);
523 x = gsl_rng_uniform_int(rng, cols[z]);
524 y = gsl_rng_uniform_int(rng, rows[z]);
525 } while (_ccv_bbf_exist_gene_feature(&gene[i], x, y, z));
526 pnz[pn][pnm] = z;
527 pnx[pn][pnm] = x;
528 pny[pn][pnm] = y;
529 decay = gene[i].age = 0;
530 break;
531 }
532 } while (decay);
533 }
534 for (i = ftnum + mnum; i < ftnum + mnum + hnum; i++)
535 {
536 /* hybrid strategy: taking positive points from dad, negative points from mum */
537 int dad, mum;
538 do {
539 dad = gsl_rng_uniform_int(rng, ftnum);
540 mum = gsl_rng_uniform_int(rng, ftnum);
541 } while (dad == mum || gene[dad].pk + gene[mum].nk < CCV_BBF_POINT_MIN(3)); /* at least 3 points have to be examed */
542 for (j = 0; j < CCV_BBF_POINT_MAX(8); j++)
543 {
544 gene[i].feature.pz[j] = -1;
545 gene[i].feature.nz[j] = -1;
546 }
547 gene[i].pk = gene[dad].pk;
548 for (j = 0; j < gene[i].pk; j++)
549 {
550 gene[i].feature.pz[j] = gene[dad].feature.pz[j];
551 gene[i].feature.px[j] = gene[dad].feature.px[j];
552 gene[i].feature.py[j] = gene[dad].feature.py[j];
553 }
554 gene[i].nk = gene[mum].nk;
555 for (j = 0; j < gene[i].nk; j++)
556 {
557 gene[i].feature.nz[j] = gene[mum].feature.nz[j];
558 gene[i].feature.nx[j] = gene[mum].feature.nx[j];
559 gene[i].feature.ny[j] = gene[mum].feature.ny[j];
560 }
561 gene[i].feature.size = ccv_max(gene[i].pk, gene[i].nk)({ typeof (gene[i].pk) _a = (gene[i].pk); typeof (gene[i].nk)
_b = (gene[i].nk); (_a > _b) ? _a : _b; })
;
562 gene[i].age = 0;
563 }
564 for (i = ftnum + mnum + hnum; i < ftnum + mnum + hnum + rnum; i++)
565 _ccv_bbf_randomize_gene(rng, &gene[i], rows, cols);
566 timer = _ccv_bbf_time_measure();
567#ifdef USE_OPENMP
568#pragma omp parallel for private(i) schedule(dynamic)
569#endif
570 for (i = 0; i < pnum; i++)
571 gene[i].error = _ccv_bbf_error_rate(&gene[i].feature, posdata, posnum, negdata, negnum, size, pw, nw);
572 timer = _ccv_bbf_time_measure() - timer;
573 for (i = 0; i < pnum; i++)
574 _ccv_bbf_genetic_fitness(&gene[i]);
575 }
576 ccfreefree(gene);
577 gsl_rng_free(rng);
578 return best;
579}
580
581#define less_than(fit1, fit2, aux) ((fit1).error < (fit2).error)
582static CCV_IMPLEMENT_QSORT(_ccv_bbf_best_qsort, ccv_bbf_gene_t, less_than)void _ccv_bbf_best_qsort(ccv_bbf_gene_t *array, size_t total,
int aux) { int isort_thresh = 7; ccv_bbf_gene_t t; int sp = 0
; struct { ccv_bbf_gene_t *lb; ccv_bbf_gene_t *ub; } stack[48
]; if( total <= 1 ) return; stack[0].lb = array; stack[0].
ub = array + (total - 1); while( sp >= 0 ) { ccv_bbf_gene_t
* left = stack[sp].lb; ccv_bbf_gene_t* right = stack[sp--].ub
; for(;;) { int i, n = (int)(right - left) + 1, m; ccv_bbf_gene_t
* ptr; ccv_bbf_gene_t* ptr2; if( n <= isort_thresh ) { insert_sort
: for( ptr = left + 1; ptr <= right; ptr++ ) { for( ptr2 =
ptr; ptr2 > left && less_than(ptr2[0],ptr2[-1], aux
); ptr2--) (((t)) = ((ptr2[0])), ((ptr2[0])) = ((ptr2[-1])), (
(ptr2[-1])) = ((t))); } break; } else { ccv_bbf_gene_t* left0
; ccv_bbf_gene_t* left1; ccv_bbf_gene_t* right0; ccv_bbf_gene_t
* right1; ccv_bbf_gene_t* pivot; ccv_bbf_gene_t* a; ccv_bbf_gene_t
* b; ccv_bbf_gene_t* c; int swap_cnt = 0; left0 = left; right0
= right; pivot = left + (n/2); if( n > 40 ) { int d = n /
8; a = left, b = left + d, c = left + 2*d; left = less_than(
*a, *b, aux) ? (less_than(*b, *c, aux) ? b : (less_than(*a, *
c, aux) ? c : a)) : (less_than(*c, *b, aux) ? b : (less_than(
*a, *c, aux) ? a : c)); a = pivot - d, b = pivot, c = pivot +
d; pivot = less_than(*a, *b, aux) ? (less_than(*b, *c, aux) ?
b : (less_than(*a, *c, aux) ? c : a)) : (less_than(*c, *b, aux
) ? b : (less_than(*a, *c, aux) ? a : c)); a = right - 2*d, b
= right - d, c = right; right = less_than(*a, *b, aux) ? (less_than
(*b, *c, aux) ? b : (less_than(*a, *c, aux) ? c : a)) : (less_than
(*c, *b, aux) ? b : (less_than(*a, *c, aux) ? a : c)); } a = left
, b = pivot, c = right; pivot = less_than(*a, *b, aux) ? (less_than
(*b, *c, aux) ? b : (less_than(*a, *c, aux) ? c : a)) : (less_than
(*c, *b, aux) ? b : (less_than(*a, *c, aux) ? a : c)); if( pivot
!= left0 ) { (((t)) = ((*pivot)), ((*pivot)) = ((*left0)), (
(*left0)) = ((t))); pivot = left0; } left = left1 = left0 + 1
; right = right1 = right0; for(;;) { while( left <= right &&
!less_than(*pivot, *left, aux) ) { if( !less_than(*left, *pivot
, aux) ) { if( left > left1 ) (((t)) = ((*left1)), ((*left1
)) = ((*left)), ((*left)) = ((t))); swap_cnt = 1; left1++; } left
++; } while( left <= right && !less_than(*right, *
pivot, aux) ) { if( !less_than(*pivot, *right, aux) ) { if( right
< right1 ) (((t)) = ((*right1)), ((*right1)) = ((*right))
, ((*right)) = ((t))); swap_cnt = 1; right1--; } right--; } if
( left > right ) break; (((t)) = ((*left)), ((*left)) = ((
*right)), ((*right)) = ((t))); swap_cnt = 1; left++; right--;
} if( swap_cnt == 0 ) { left = left0, right = right0; goto insert_sort
; } n = ({ typeof ((int)(left1 - left0)) _a = ((int)(left1 - left0
)); typeof ((int)(left - left1)) _b = ((int)(left - left1)); (
_a < _b) ? _a : _b; }); for( i = 0; i < n; i++ ) (((t))
= ((left0[i])), ((left0[i])) = ((left[i-n])), ((left[i-n])) =
((t))); n = ({ typeof ((int)(right0 - right1)) _a = ((int)(right0
- right1)); typeof ((int)(right1 - right)) _b = ((int)(right1
- right)); (_a < _b) ? _a : _b; }); for( i = 0; i < n;
i++ ) (((t)) = ((left[i])), ((left[i])) = ((right0[i-n+1])),
((right0[i-n+1])) = ((t))); n = (int)(left - left1); m = (int
)(right1 - right); if( n > 1 ) { if( m > 1 ) { if( n >
m ) { stack[++sp].lb = left0; stack[sp].ub = left0 + n - 1; left
= right0 - m + 1, right = right0; } else { stack[++sp].lb = right0
- m + 1; stack[sp].ub = right0; left = left0, right = left0 +
n - 1; } } else left = left0, right = left0 + n - 1; } else if
( m > 1 ) left = right0 - m + 1, right = right0; else break
; } } } }
583#undef less_than
584
585static ccv_bbf_gene_t _ccv_bbf_best_gene(ccv_bbf_gene_t* gene, int pnum, int point_min, unsigned char** posdata, int posnum, unsigned char** negdata, int negnum, ccv_size_t size, double* pw, double* nw)
586{
587 int i;
588 unsigned int timer = _ccv_bbf_time_measure();
589#ifdef USE_OPENMP
590#pragma omp parallel for private(i) schedule(dynamic)
591#endif
592 for (i = 0; i < pnum; i++)
593 gene[i].error = _ccv_bbf_error_rate(&gene[i].feature, posdata, posnum, negdata, negnum, size, pw, nw);
594 timer = _ccv_bbf_time_measure() - timer;
595 _ccv_bbf_best_qsort(gene, pnum, 0);
596 int min_id = 0;
597 double min_err = gene[0].error;
598 for (i = 0; i < pnum; i++)
599 if (gene[i].nk + gene[i].pk >= point_min)
600 {
601 min_id = i;
602 min_err = gene[i].error;
603 break;
604 }
605 PRINT(CCV_CLI_INFO, "local best bbf feature with error %f\n|-size: %d\n|-positive point: ", min_err, gene[min_id].feature.size)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("local best bbf feature with error %f\n|-size: %d\n|-positive point: "
, min_err, gene[min_id].feature.size); fflush(stdout); } } while
(0)
;
606 for (i = 0; i < gene[min_id].feature.size; i++)
607 PRINT(CCV_CLI_INFO, "(%d %d %d), ", gene[min_id].feature.px[i], gene[min_id].feature.py[i], gene[min_id].feature.pz[i])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("(%d %d %d), ", gene[min_id].feature.px[i], gene[min_id].feature
.py[i], gene[min_id].feature.pz[i]); fflush(stdout); } } while
(0)
;
608 PRINT(CCV_CLI_INFO, "\n|-negative point: ")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n|-negative point: "); fflush(stdout); } } while (0)
;
609 for (i = 0; i < gene[min_id].feature.size; i++)
610 PRINT(CCV_CLI_INFO, "(%d %d %d), ", gene[min_id].feature.nx[i], gene[min_id].feature.ny[i], gene[min_id].feature.nz[i])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("(%d %d %d), ", gene[min_id].feature.nx[i], gene[min_id].feature
.ny[i], gene[min_id].feature.nz[i]); fflush(stdout); } } while
(0)
;
611 PRINT(CCV_CLI_INFO, "\nthe computation takes %d ms\n", timer / 1000)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\nthe computation takes %d ms\n", timer / 1000); fflush(stdout
); } } while (0)
;
612 return gene[min_id];
613}
614
615static ccv_bbf_feature_t _ccv_bbf_convex_optimize(unsigned char** posdata, int posnum, unsigned char** negdata, int negnum, ccv_bbf_feature_t* best_feature, ccv_size_t size, double* pw, double* nw)
616{
617 ccv_bbf_gene_t best_gene;
618 /* seed (random method) */
619 gsl_rng_env_setup();
620 gsl_rng* rng = gsl_rng_alloc(gsl_rng_default);
621 union { unsigned long int li; double db; } dbli;
622 dbli.db = pw[0] + nw[0];
623 gsl_rng_set(rng, dbli.li);
624 int i, j, k, q, p, g, t;
625 int rows[] = { size.height, size.height >> 1, size.height >> 2 };
626 int cols[] = { size.width, size.width >> 1, size.width >> 2 };
627 int pnum = rows[0] * cols[0] + rows[1] * cols[1] + rows[2] * cols[2];
628 ccv_bbf_gene_t* gene = (ccv_bbf_gene_t*)ccmallocmalloc((pnum * (CCV_BBF_POINT_MAX(8) * 2 + 1) * 2 + CCV_BBF_POINT_MAX(8) * 2 + 1) * sizeof(ccv_bbf_gene_t));
629 if (best_feature == 0)
630 {
631 /* bootstrapping the best feature, start from two pixels, one for positive, one for negative
632 * the bootstrapping process go like this: first, it will assign a random pixel as positive
633 * and enumerate every possible pixel as negative, and pick the best one. Then, enumerate every
634 * possible pixel as positive, and pick the best one, until it converges */
635 memset(&best_gene, 0, sizeof(ccv_bbf_gene_t));
636 for (i = 0; i < CCV_BBF_POINT_MAX(8); i++)
637 best_gene.feature.pz[i] = best_gene.feature.nz[i] = -1;
638 best_gene.pk = 1;
639 best_gene.nk = 0;
640 best_gene.feature.size = 1;
641 best_gene.feature.pz[0] = gsl_rng_uniform_int(rng, 3);
642 best_gene.feature.px[0] = gsl_rng_uniform_int(rng, cols[best_gene.feature.pz[0]]);
643 best_gene.feature.py[0] = gsl_rng_uniform_int(rng, rows[best_gene.feature.pz[0]]);
644 for (t = 0; ; ++t)
645 {
646 g = 0;
647 if (t % 2 == 0)
648 {
649 for (i = 0; i < 3; i++)
650 for (j = 0; j < cols[i]; j++)
651 for (k = 0; k < rows[i]; k++)
652 if (i != best_gene.feature.pz[0] || j != best_gene.feature.px[0] || k != best_gene.feature.py[0])
653 {
654 gene[g] = best_gene;
655 gene[g].pk = gene[g].nk = 1;
656 gene[g].feature.nz[0] = i;
657 gene[g].feature.nx[0] = j;
658 gene[g].feature.ny[0] = k;
659 g++;
660 }
661 } else {
662 for (i = 0; i < 3; i++)
663 for (j = 0; j < cols[i]; j++)
664 for (k = 0; k < rows[i]; k++)
665 if (i != best_gene.feature.nz[0] || j != best_gene.feature.nx[0] || k != best_gene.feature.ny[0])
666 {
667 gene[g] = best_gene;
668 gene[g].pk = gene[g].nk = 1;
669 gene[g].feature.pz[0] = i;
670 gene[g].feature.px[0] = j;
671 gene[g].feature.py[0] = k;
672 g++;
673 }
674 }
675 PRINT(CCV_CLI_INFO, "bootstrapping round : %d\n", t)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("bootstrapping round : %d\n", t); fflush(stdout); } } while (
0)
;
676 ccv_bbf_gene_t local_gene = _ccv_bbf_best_gene(gene, g, 2, posdata, posnum, negdata, negnum, size, pw, nw);
677 if (local_gene.error >= best_gene.error - 1e-10)
678 break;
679 best_gene = local_gene;
680 }
681 } else {
682 best_gene.feature = *best_feature;
683 best_gene.pk = best_gene.nk = best_gene.feature.size;
684 for (i = 0; i < CCV_BBF_POINT_MAX(8); i++)
685 if (best_feature->pz[i] == -1)
686 {
687 best_gene.pk = i;
688 break;
689 }
690 for (i = 0; i < CCV_BBF_POINT_MAX(8); i++)
691 if (best_feature->nz[i] == -1)
692 {
693 best_gene.nk = i;
694 break;
695 }
696 }
697 /* after bootstrapping, the float search technique will do the following permutations:
698 * a). add a new point to positive or negative
699 * b). remove a point from positive or negative
700 * c). move an existing point in positive or negative to another position
701 * the three rules applied exhaustively, no heuristic used. */
702 for (t = 0; ; ++t)
703 {
704 g = 0;
705 for (i = 0; i < 3; i++)
706 for (j = 0; j < cols[i]; j++)
707 for (k = 0; k < rows[i]; k++)
708 if (!_ccv_bbf_exist_gene_feature(&best_gene, j, k, i))
709 {
710 /* add positive point */
711 if (best_gene.pk < CCV_BBF_POINT_MAX(8) - 1)
712 {
713 gene[g] = best_gene;
714 gene[g].feature.pz[gene[g].pk] = i;
715 gene[g].feature.px[gene[g].pk] = j;
716 gene[g].feature.py[gene[g].pk] = k;
717 gene[g].pk++;
718 gene[g].feature.size = ccv_max(gene[g].pk, gene[g].nk)({ typeof (gene[g].pk) _a = (gene[g].pk); typeof (gene[g].nk)
_b = (gene[g].nk); (_a > _b) ? _a : _b; })
;
719 g++;
720 }
721 /* add negative point */
722 if (best_gene.nk < CCV_BBF_POINT_MAX(8) - 1)
723 {
724 gene[g] = best_gene;
725 gene[g].feature.nz[gene[g].nk] = i;
726 gene[g].feature.nx[gene[g].nk] = j;
727 gene[g].feature.ny[gene[g].nk] = k;
728 gene[g].nk++;
729 gene[g].feature.size = ccv_max(gene[g].pk, gene[g].nk)({ typeof (gene[g].pk) _a = (gene[g].pk); typeof (gene[g].nk)
_b = (gene[g].nk); (_a > _b) ? _a : _b; })
;
730 g++;
731 }
732 /* refine positive point */
733 for (q = 0; q < best_gene.pk; q++)
734 {
735 gene[g] = best_gene;
736 gene[g].feature.pz[q] = i;
737 gene[g].feature.px[q] = j;
738 gene[g].feature.py[q] = k;
739 g++;
740 }
741 /* add positive point, remove negative point */
742 if (best_gene.pk < CCV_BBF_POINT_MAX(8) - 1 && best_gene.nk > 1)
743 {
744 for (q = 0; q < best_gene.nk; q++)
745 {
746 gene[g] = best_gene;
747 gene[g].feature.pz[gene[g].pk] = i;
748 gene[g].feature.px[gene[g].pk] = j;
749 gene[g].feature.py[gene[g].pk] = k;
750 gene[g].pk++;
751 for (p = q; p < best_gene.nk - 1; p++)
752 {
753 gene[g].feature.nz[p] = gene[g].feature.nz[p + 1];
754 gene[g].feature.nx[p] = gene[g].feature.nx[p + 1];
755 gene[g].feature.ny[p] = gene[g].feature.ny[p + 1];
756 }
757 gene[g].feature.nz[gene[g].nk - 1] = -1;
758 gene[g].nk--;
759 gene[g].feature.size = ccv_max(gene[g].pk, gene[g].nk)({ typeof (gene[g].pk) _a = (gene[g].pk); typeof (gene[g].nk)
_b = (gene[g].nk); (_a > _b) ? _a : _b; })
;
760 g++;
761 }
762 }
763 /* refine negative point */
764 for (q = 0; q < best_gene.nk; q++)
765 {
766 gene[g] = best_gene;
767 gene[g].feature.nz[q] = i;
768 gene[g].feature.nx[q] = j;
769 gene[g].feature.ny[q] = k;
770 g++;
771 }
772 /* add negative point, remove positive point */
773 if (best_gene.pk > 1 && best_gene.nk < CCV_BBF_POINT_MAX(8) - 1)
774 {
775 for (q = 0; q < best_gene.pk; q++)
776 {
777 gene[g] = best_gene;
778 gene[g].feature.nz[gene[g].nk] = i;
779 gene[g].feature.nx[gene[g].nk] = j;
780 gene[g].feature.ny[gene[g].nk] = k;
781 gene[g].nk++;
782 for (p = q; p < best_gene.pk - 1; p++)
783 {
784 gene[g].feature.pz[p] = gene[g].feature.pz[p + 1];
785 gene[g].feature.px[p] = gene[g].feature.px[p + 1];
786 gene[g].feature.py[p] = gene[g].feature.py[p + 1];
787 }
788 gene[g].feature.pz[gene[g].pk - 1] = -1;
789 gene[g].pk--;
790 gene[g].feature.size = ccv_max(gene[g].pk, gene[g].nk)({ typeof (gene[g].pk) _a = (gene[g].pk); typeof (gene[g].nk)
_b = (gene[g].nk); (_a > _b) ? _a : _b; })
;
791 g++;
792 }
793 }
794 }
795 if (best_gene.pk > 1)
796 for (q = 0; q < best_gene.pk; q++)
797 {
798 gene[g] = best_gene;
799 for (i = q; i < best_gene.pk - 1; i++)
800 {
801 gene[g].feature.pz[i] = gene[g].feature.pz[i + 1];
802 gene[g].feature.px[i] = gene[g].feature.px[i + 1];
803 gene[g].feature.py[i] = gene[g].feature.py[i + 1];
804 }
805 gene[g].feature.pz[gene[g].pk - 1] = -1;
806 gene[g].pk--;
807 gene[g].feature.size = ccv_max(gene[g].pk, gene[g].nk)({ typeof (gene[g].pk) _a = (gene[g].pk); typeof (gene[g].nk)
_b = (gene[g].nk); (_a > _b) ? _a : _b; })
;
808 g++;
809 }
810 if (best_gene.nk > 1)
811 for (q = 0; q < best_gene.nk; q++)
812 {
813 gene[g] = best_gene;
814 for (i = q; i < best_gene.nk - 1; i++)
815 {
816 gene[g].feature.nz[i] = gene[g].feature.nz[i + 1];
817 gene[g].feature.nx[i] = gene[g].feature.nx[i + 1];
818 gene[g].feature.ny[i] = gene[g].feature.ny[i + 1];
819 }
820 gene[g].feature.nz[gene[g].nk - 1] = -1;
821 gene[g].nk--;
822 gene[g].feature.size = ccv_max(gene[g].pk, gene[g].nk)({ typeof (gene[g].pk) _a = (gene[g].pk); typeof (gene[g].nk)
_b = (gene[g].nk); (_a > _b) ? _a : _b; })
;
823 g++;
824 }
825 gene[g] = best_gene;
826 g++;
827 PRINT(CCV_CLI_INFO, "float search round : %d\n", t)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("float search round : %d\n", t); fflush(stdout); } } while (
0)
;
828 ccv_bbf_gene_t local_gene = _ccv_bbf_best_gene(gene, g, CCV_BBF_POINT_MIN(3), posdata, posnum, negdata, negnum, size, pw, nw);
829 if (local_gene.error >= best_gene.error - 1e-10)
830 break;
831 best_gene = local_gene;
832 }
833 ccfreefree(gene);
834 gsl_rng_free(rng);
835 return best_gene.feature;
836}
837
838static int _ccv_write_bbf_stage_classifier(const char* file, ccv_bbf_stage_classifier_t* classifier)
839{
840 FILE* w = fopen(file, "wb");
841 if (w == 0) return -1;
842 fprintf(w, "%d\n", classifier->count);
843 union { float fl; int i; } fli;
844 fli.fl = classifier->threshold;
845 fprintf(w, "%d\n", fli.i);
846 int i, j;
847 for (i = 0; i < classifier->count; i++)
848 {
849 fprintf(w, "%d\n", classifier->feature[i].size);
850 for (j = 0; j < classifier->feature[i].size; j++)
851 {
852 fprintf(w, "%d %d %d\n", classifier->feature[i].px[j], classifier->feature[i].py[j], classifier->feature[i].pz[j]);
853 fprintf(w, "%d %d %d\n", classifier->feature[i].nx[j], classifier->feature[i].ny[j], classifier->feature[i].nz[j]);
854 }
855 union { float fl; int i; } flia, flib;
856 flia.fl = classifier->alpha[i * 2];
857 flib.fl = classifier->alpha[i * 2 + 1];
858 fprintf(w, "%d %d\n", flia.i, flib.i);
859 }
860 fclose(w);
861 return 0;
862}
863
864static int _ccv_read_background_data(const char* file, unsigned char** negdata, int* negnum, ccv_size_t size)
865{
866 int stat = 0;
867 FILE* r = fopen(file, "rb");
868 if (r == 0) return -1;
869 stat |= fread(negnum, sizeof(int), 1, r);
870 int i;
871 int isizs012 = _ccv_width_padding(size.width)(((size.width) + 3) & -4) * size.height +
872 _ccv_width_padding(size.width >> 1)(((size.width >> 1) + 3) & -4) * (size.height >> 1) +
873 _ccv_width_padding(size.width >> 2)(((size.width >> 2) + 3) & -4) * (size.height >> 2);
874 for (i = 0; i < *negnum; i++)
875 {
876 negdata[i] = (unsigned char*)ccmallocmalloc(isizs012);
877 stat |= fread(negdata[i], 1, isizs012, r);
878 }
879 fclose(r);
880 return 0;
881}
882
883static int _ccv_write_background_data(const char* file, unsigned char** negdata, int negnum, ccv_size_t size)
884{
885 FILE* w = fopen(file, "w");
886 if (w == 0) return -1;
887 fwrite(&negnum, sizeof(int), 1, w);
888 int i;
889 int isizs012 = _ccv_width_padding(size.width)(((size.width) + 3) & -4) * size.height +
890 _ccv_width_padding(size.width >> 1)(((size.width >> 1) + 3) & -4) * (size.height >> 1) +
891 _ccv_width_padding(size.width >> 2)(((size.width >> 2) + 3) & -4) * (size.height >> 2);
892 for (i = 0; i < negnum; i++)
893 fwrite(negdata[i], 1, isizs012, w);
894 fclose(w);
895 return 0;
896}
897
898static int _ccv_resume_bbf_cascade_training_state(const char* file, int* i, int* k, int* bg, double* pw, double* nw, int posnum, int negnum)
899{
900 int stat = 0;
901 FILE* r = fopen(file, "r");
902 if (r == 0) return -1;
903 stat |= fscanf(r, "%d %d %d", i, k, bg);
904 int j;
905 union { double db; int i[2]; } dbi;
906 for (j = 0; j < posnum; j++)
907 {
908 stat |= fscanf(r, "%d %d", &dbi.i[0], &dbi.i[1]);
909 pw[j] = dbi.db;
910 }
911 for (j = 0; j < negnum; j++)
912 {
913 stat |= fscanf(r, "%d %d", &dbi.i[0], &dbi.i[1]);
914 nw[j] = dbi.db;
915 }
916 fclose(r);
917 return 0;
918}
919
920static int _ccv_save_bbf_cacade_training_state(const char* file, int i, int k, int bg, double* pw, double* nw, int posnum, int negnum)
921{
922 FILE* w = fopen(file, "w");
923 if (w == 0) return -1;
924 fprintf(w, "%d %d %d\n", i, k, bg);
925 int j;
926 union { double db; int i[2]; } dbi;
927 for (j = 0; j < posnum; ++j)
928 {
929 dbi.db = pw[j];
930 fprintf(w, "%d %d ", dbi.i[0], dbi.i[1]);
931 }
932 fprintf(w, "\n");
933 for (j = 0; j < negnum; ++j)
934 {
935 dbi.db = nw[j];
936 fprintf(w, "%d %d ", dbi.i[0], dbi.i[1]);
937 }
938 fprintf(w, "\n");
939 fclose(w);
940 return 0;
941}
942
943void ccv_bbf_classifier_cascade_new(ccv_dense_matrix_t** posimg, int posnum, char** bgfiles, int bgnum, int negnum, ccv_size_t size, const char* dir, ccv_bbf_new_param_t params)
944{
945 int i, j, k;
946 /* allocate memory for usage */
947 ccv_bbf_classifier_cascade_t* cascade = (ccv_bbf_classifier_cascade_t*)ccmallocmalloc(sizeof(ccv_bbf_classifier_cascade_t));
948 cascade->count = 0;
949 cascade->size = size;
950 cascade->stage_classifier = (ccv_bbf_stage_classifier_t*)ccmallocmalloc(sizeof(ccv_bbf_stage_classifier_t));
951 unsigned char** posdata = (unsigned char**)ccmallocmalloc(posnum * sizeof(unsigned char*));
952 unsigned char** negdata = (unsigned char**)ccmallocmalloc(negnum * sizeof(unsigned char*));
953 double* pw = (double*)ccmallocmalloc(posnum * sizeof(double));
954 double* nw = (double*)ccmallocmalloc(negnum * sizeof(double));
955 float* peval = (float*)ccmallocmalloc(posnum * sizeof(float));
956 float* neval = (float*)ccmallocmalloc(negnum * sizeof(float));
957 double inv_balance_k = 1. / params.balance_k;
958 /* balance factor k, and weighted with 0.01 */
959 params.balance_k *= 0.01;
960 inv_balance_k *= 0.01;
961
962 int steps[] = { _ccv_width_padding(cascade->size.width)(((cascade->size.width) + 3) & -4),
963 _ccv_width_padding(cascade->size.width >> 1)(((cascade->size.width >> 1) + 3) & -4),
964 _ccv_width_padding(cascade->size.width >> 2)(((cascade->size.width >> 2) + 3) & -4) };
965 int isizs0 = steps[0] * cascade->size.height;
966 int isizs01 = isizs0 + steps[1] * (cascade->size.height >> 1);
967
968 i = 0;
969 k = 0;
970 int bg = 0;
971 int cacheK = 10;
972 /* state resume code */
973 char buf[1024];
974 sprintf(buf, "%s/stat.txt", dir);
975 _ccv_resume_bbf_cascade_training_state(buf, &i, &k, &bg, pw, nw, posnum, negnum);
976 if (i > 0)
977 {
978 cascade->count = i;
979 ccfreefree(cascade->stage_classifier);
980 cascade->stage_classifier = (ccv_bbf_stage_classifier_t*)ccmallocmalloc(i * sizeof(ccv_bbf_stage_classifier_t));
981 for (j = 0; j < i; j++)
982 {
983 sprintf(buf, "%s/stage-%d.txt", dir, j);
984 _ccv_read_bbf_stage_classifier(buf, &cascade->stage_classifier[j]);
985 }
986 }
987 if (k > 0)
988 cacheK = k;
989 int rpos, rneg = 0;
990 if (bg)
991 {
992 sprintf(buf, "%s/negs.txt", dir);
993 _ccv_read_background_data(buf, negdata, &rneg, cascade->size);
994 }
995
996 for (; i < params.layer; i++)
997 {
998 if (!bg)
999 {
1000 rneg = _ccv_prepare_background_data(cascade, bgfiles, bgnum, negdata, negnum);
1001 /* save state of background data */
1002 sprintf(buf, "%s/negs.txt", dir);
1003 _ccv_write_background_data(buf, negdata, rneg, cascade->size);
1004 bg = 1;
1005 }
1006 double totalw;
1007 /* save state of cascade : level, weight etc. */
1008 sprintf(buf, "%s/stat.txt", dir);
1009 _ccv_save_bbf_cacade_training_state(buf, i, k, bg, pw, nw, posnum, negnum);
1010 ccv_bbf_stage_classifier_t classifier;
1011 if (k > 0)
1012 {
1013 /* resume state of classifier */
1014 sprintf( buf, "%s/stage-%d.txt", dir, i );
1015 _ccv_read_bbf_stage_classifier(buf, &classifier);
1016 } else {
1017 /* initialize classifier */
1018 for (j = 0; j < posnum; j++)
1019 pw[j] = params.balance_k;
1020 for (j = 0; j < rneg; j++)
1021 nw[j] = inv_balance_k;
1022 classifier.count = k;
1023 classifier.threshold = 0;
1024 classifier.feature = (ccv_bbf_feature_t*)ccmallocmalloc(cacheK * sizeof(ccv_bbf_feature_t));
1025 classifier.alpha = (float*)ccmallocmalloc(cacheK * 2 * sizeof(float));
1026 }
1027 _ccv_prepare_positive_data(posimg, posdata, cascade->size, posnum);
1028 rpos = _ccv_prune_positive_data(cascade, posdata, posnum, cascade->size);
1029 PRINT(CCV_CLI_INFO, "%d postivie data and %d negative data in training\n", rpos, rneg)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("%d postivie data and %d negative data in training\n", rpos,
rneg); fflush(stdout); } } while (0)
;
1030 /* reweight to 1.00 */
1031 totalw = 0;
1032 for (j = 0; j < rpos; j++)
1033 totalw += pw[j];
1034 for (j = 0; j < rneg; j++)
1035 totalw += nw[j];
1036 for (j = 0; j < rpos; j++)
1037 pw[j] = pw[j] / totalw;
1038 for (j = 0; j < rneg; j++)
1039 nw[j] = nw[j] / totalw;
1040 for (; ; k++)
1041 {
1042 /* get overall true-positive, false-positive rate and threshold */
1043 double tp = 0, fp = 0, etp = 0, efp = 0;
1044 _ccv_bbf_eval_data(&classifier, posdata, rpos, negdata, rneg, cascade->size, peval, neval);
1045 _ccv_sort_32f(peval, rpos, 0);
1046 classifier.threshold = peval[(int)((1. - params.pos_crit) * rpos)] - 1e-6;
1047 for (j = 0; j < rpos; j++)
1048 {
1049 if (peval[j] >= 0)
1050 ++tp;
1051 if (peval[j] >= classifier.threshold)
1052 ++etp;
1053 }
1054 tp /= rpos; etp /= rpos;
1055 for (j = 0; j < rneg; j++)
1056 {
1057 if (neval[j] >= 0)
1058 ++fp;
1059 if (neval[j] >= classifier.threshold)
1060 ++efp;
1061 }
1062 fp /= rneg; efp /= rneg;
1063 PRINT(CCV_CLI_INFO, "stage classifier real TP rate : %f, FP rate : %f\n", tp, fp)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("stage classifier real TP rate : %f, FP rate : %f\n", tp, fp
); fflush(stdout); } } while (0)
;
1064 PRINT(CCV_CLI_INFO, "stage classifier TP rate : %f, FP rate : %f at threshold : %f\n", etp, efp, classifier.threshold)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("stage classifier TP rate : %f, FP rate : %f at threshold : %f\n"
, etp, efp, classifier.threshold); fflush(stdout); } } while (
0)
;
1065 if (k > 0)
1066 {
1067 /* save classifier state */
1068 sprintf(buf, "%s/stage-%d.txt", dir, i);
1069 _ccv_write_bbf_stage_classifier(buf, &classifier);
1070 sprintf(buf, "%s/stat.txt", dir);
1071 _ccv_save_bbf_cacade_training_state(buf, i, k, bg, pw, nw, posnum, negnum);
1072 }
1073 if (etp > params.pos_crit && efp < params.neg_crit)
1074 break;
1075 /* TODO: more post-process is needed in here */
1076
1077 /* select the best feature in current distribution through genetic algorithm optimization */
1078 ccv_bbf_feature_t best;
1079 if (params.optimizer == CCV_BBF_GENETIC_OPT)
1080 {
1081 best = _ccv_bbf_genetic_optimize(posdata, rpos, negdata, rneg, params.feature_number, cascade->size, pw, nw);
1082 } else if (params.optimizer == CCV_BBF_FLOAT_OPT) {
1083 best = _ccv_bbf_convex_optimize(posdata, rpos, negdata, rneg, 0, cascade->size, pw, nw);
1084 } else {
1085 best = _ccv_bbf_genetic_optimize(posdata, rpos, negdata, rneg, params.feature_number, cascade->size, pw, nw);
1086 best = _ccv_bbf_convex_optimize(posdata, rpos, negdata, rneg, &best, cascade->size, pw, nw);
1087 }
1088 double err = _ccv_bbf_error_rate(&best, posdata, rpos, negdata, rneg, cascade->size, pw, nw);
1089 double rw = (1 - err) / err;
1090 totalw = 0;
1091 /* reweight */
1092 for (j = 0; j < rpos; j++)
1093 {
1094 unsigned char* u8[] = { posdata[j], posdata[j] + isizs0, posdata[j] + isizs01 };
1095 if (!_ccv_run_bbf_feature(&best, steps, u8))
1096 pw[j] *= rw;
1097 pw[j] *= params.balance_k;
1098 totalw += pw[j];
1099 }
1100 for (j = 0; j < rneg; j++)
1101 {
1102 unsigned char* u8[] = { negdata[j], negdata[j] + isizs0, negdata[j] + isizs01 };
1103 if (_ccv_run_bbf_feature(&best, steps, u8))
1104 nw[j] *= rw;
1105 nw[j] *= inv_balance_k;
1106 totalw += nw[j];
1107 }
1108 for (j = 0; j < rpos; j++)
1109 pw[j] = pw[j] / totalw;
1110 for (j = 0; j < rneg; j++)
1111 nw[j] = nw[j] / totalw;
1112 double c = log(rw);
1113 PRINT(CCV_CLI_INFO, "coefficient of feature %d: %f\n", k + 1, c)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("coefficient of feature %d: %f\n", k + 1, c); fflush(stdout)
; } } while (0)
;
1114 classifier.count = k + 1;
1115 /* resizing classifier */
1116 if (k >= cacheK)
1117 {
1118 ccv_bbf_feature_t* feature = (ccv_bbf_feature_t*)ccmallocmalloc(cacheK * 2 * sizeof(ccv_bbf_feature_t));
1119 memcpy(feature, classifier.feature, cacheK * sizeof(ccv_bbf_feature_t));
1120 ccfreefree(classifier.feature);
1121 float* alpha = (float*)ccmallocmalloc(cacheK * 4 * sizeof(float));
1122 memcpy(alpha, classifier.alpha, cacheK * 2 * sizeof(float));
1123 ccfreefree(classifier.alpha);
1124 classifier.feature = feature;
1125 classifier.alpha = alpha;
1126 cacheK *= 2;
1127 }
1128 /* setup new feature */
1129 classifier.feature[k] = best;
1130 classifier.alpha[k * 2] = -c;
1131 classifier.alpha[k * 2 + 1] = c;
1132 }
1133 cascade->count = i + 1;
1134 ccv_bbf_stage_classifier_t* stage_classifier = (ccv_bbf_stage_classifier_t*)ccmallocmalloc(cascade->count * sizeof(ccv_bbf_stage_classifier_t));
1135 memcpy(stage_classifier, cascade->stage_classifier, i * sizeof(ccv_bbf_stage_classifier_t));
1136 ccfreefree(cascade->stage_classifier);
1137 stage_classifier[i] = classifier;
1138 cascade->stage_classifier = stage_classifier;
1139 k = 0;
1140 bg = 0;
1141 for (j = 0; j < rpos; j++)
1142 ccfreefree(posdata[j]);
1143 for (j = 0; j < rneg; j++)
1144 ccfreefree(negdata[j]);
1145 }
1146
1147 ccfreefree(neval);
1148 ccfreefree(peval);
1149 ccfreefree(nw);
1150 ccfreefree(pw);
1151 ccfreefree(negdata);
1152 ccfreefree(posdata);
1153 ccfreefree(cascade);
1154}
1155#else
1156void ccv_bbf_classifier_cascade_new(ccv_dense_matrix_t** posimg, int posnum, char** bgfiles, int bgnum, int negnum, ccv_size_t size, const char* dir, ccv_bbf_new_param_t params)
1157{
1158 fprintf(stderrstderr, " ccv_bbf_classifier_cascade_new requires libgsl support, please compile ccv with libgsl.\n");
1159}
1160#endif
1161
1162static int _ccv_is_equal(const void* _r1, const void* _r2, void* data)
1163{
1164 const ccv_comp_t* r1 = (const ccv_comp_t*)_r1;
1165 const ccv_comp_t* r2 = (const ccv_comp_t*)_r2;
1166 int distance = (int)(r1->rect.width * 0.25 + 0.5);
1167
1168 return r2->rect.x <= r1->rect.x + distance &&
1169 r2->rect.x >= r1->rect.x - distance &&
1170 r2->rect.y <= r1->rect.y + distance &&
1171 r2->rect.y >= r1->rect.y - distance &&
1172 r2->rect.width <= (int)(r1->rect.width * 1.5 + 0.5) &&
1173 (int)(r2->rect.width * 1.5 + 0.5) >= r1->rect.width;
1174}
1175
1176static int _ccv_is_equal_same_class(const void* _r1, const void* _r2, void* data)
1177{
1178 const ccv_comp_t* r1 = (const ccv_comp_t*)_r1;
1179 const ccv_comp_t* r2 = (const ccv_comp_t*)_r2;
1180 int distance = (int)(r1->rect.width * 0.25 + 0.5);
1181
1182 return r2->classification.id == r1->classification.id &&
1183 r2->rect.x <= r1->rect.x + distance &&
1184 r2->rect.x >= r1->rect.x - distance &&
1185 r2->rect.y <= r1->rect.y + distance &&
1186 r2->rect.y >= r1->rect.y - distance &&
1187 r2->rect.width <= (int)(r1->rect.width * 1.5 + 0.5) &&
1188 (int)(r2->rect.width * 1.5 + 0.5) >= r1->rect.width;
1189}
1190
1191ccv_array_t* ccv_bbf_detect_objects(ccv_dense_matrix_t* a, ccv_bbf_classifier_cascade_t** _cascade, int count, ccv_bbf_param_t params)
1192{
1193 int hr = a->rows / params.size.height;
1194 int wr = a->cols / params.size.width;
1195 double scale = pow(2., 1. / (params.interval + 1.));
1196 int next = params.interval + 1;
1197 int scale_upto = (int)(log((double)ccv_min(hr, wr)({ typeof (hr) _a = (hr); typeof (wr) _b = (wr); (_a < _b)
? _a : _b; })
) / log(scale));
1
Assuming '_a' is >= '_b'
2
'?' condition is false
1198 ccv_dense_matrix_t** pyr = (ccv_dense_matrix_t**)alloca((scale_upto + next * 2) * 4 * sizeof(ccv_dense_matrix_t*))__builtin_alloca ((scale_upto + next * 2) * 4 * sizeof(ccv_dense_matrix_t
*))
;
1199 memset(pyr, 0, (scale_upto + next * 2) * 4 * sizeof(ccv_dense_matrix_t*));
1200 if (params.size.height != _cascade[0]->size.height || params.size.width != _cascade[0]->size.width)
3
Assuming the condition is false
4
Assuming the condition is false
5
Taking false branch
1201 ccv_resample(a, &pyr[0], 0, a->rows * _cascade[0]->size.height / params.size.height, a->cols * _cascade[0]->size.width / params.size.width, CCV_INTER_AREA);
1202 else
1203 pyr[0] = a;
1204 int i, j, k, t, x, y, q;
1205 for (i = 1; i < ccv_min(params.interval + 1, scale_upto + next * 2)({ typeof (params.interval + 1) _a = (params.interval + 1); typeof
(scale_upto + next * 2) _b = (scale_upto + next * 2); (_a <
_b) ? _a : _b; })
; i++)
6
Assuming '_a' is >= '_b'
7
'?' condition is false
8
Assuming the condition is false
9
Loop condition is false. Execution continues on line 1207
1206 ccv_resample(pyr[0], &pyr[i * 4], 0, (int)(pyr[0]->rows / pow(scale, i)), (int)(pyr[0]->cols / pow(scale, i)), CCV_INTER_AREA);
1207 for (i = next; i < scale_upto + next * 2; i++)
10
Loop condition is false. Execution continues on line 1209
1208 ccv_sample_down(pyr[i * 4 - next * 4], &pyr[i * 4], 0, 0, 0);
1209 if (params.accurate)
11
Assuming the condition is false
12
Taking false branch
1210 for (i = next * 2; i < scale_upto + next * 2; i++)
1211 {
1212 ccv_sample_down(pyr[i * 4 - next * 4], &pyr[i * 4 + 1], 0, 1, 0);
1213 ccv_sample_down(pyr[i * 4 - next * 4], &pyr[i * 4 + 2], 0, 0, 1);
1214 ccv_sample_down(pyr[i * 4 - next * 4], &pyr[i * 4 + 3], 0, 1, 1);
1215 }
1216 ccv_array_t* idx_seq;
1217 ccv_array_t* seq = ccv_array_new(sizeof(ccv_comp_t), 64, 0);
1218 ccv_array_t* seq2 = ccv_array_new(sizeof(ccv_comp_t), 64, 0);
1219 ccv_array_t* result_seq = ccv_array_new(sizeof(ccv_comp_t), 64, 0);
1220 /* detect in multi scale */
1221 for (t = 0; t < count; t++)
13
Assuming 't' is < 'count'
14
Loop condition is true. Entering loop body
1222 {
1223 ccv_bbf_classifier_cascade_t* cascade = _cascade[t];
1224 float scale_x = (float) params.size.width / (float) cascade->size.width;
1225 float scale_y = (float) params.size.height / (float) cascade->size.height;
1226 ccv_array_clear(seq);
1227 for (i = 0; i < scale_upto; i++)
15
Assuming 'i' is < 'scale_upto'
16
Loop condition is true. Entering loop body
1228 {
1229 int dx[] = {0, 1, 0, 1};
1230 int dy[] = {0, 0, 1, 1};
1231 int i_rows = pyr[i * 4 + next * 8]->rows - (cascade->size.height >> 2);
1232 int steps[] = { pyr[i * 4]->step, pyr[i * 4 + next * 4]->step, pyr[i * 4 + next * 8]->step };
1233 int i_cols = pyr[i * 4 + next * 8]->cols - (cascade->size.width >> 2);
1234 int paddings[] = { pyr[i * 4]->step * 4 - i_cols * 4,
1235 pyr[i * 4 + next * 4]->step * 2 - i_cols * 2,
1236 pyr[i * 4 + next * 8]->step - i_cols };
1237 for (q = 0; q < (params.accurate ? 4 : 1); q++)
17
'?' condition is false
18
Loop condition is true. Entering loop body
1238 {
1239 unsigned char* u8[] = { pyr[i * 4]->data.u8 + dx[q] * 2 + dy[q] * pyr[i * 4]->step * 2, pyr[i * 4 + next * 4]->data.u8 + dx[q] + dy[q] * pyr[i * 4 + next * 4]->step, pyr[i * 4 + next * 8 + q]->data.u8 };
1240 for (y = 0; y < i_rows; y++)
19
Assuming 'y' is < 'i_rows'
20
Loop condition is true. Entering loop body
1241 {
1242 for (x = 0; x < i_cols; x++)
21
Assuming 'x' is < 'i_cols'
22
Loop condition is true. Entering loop body
1243 {
1244 float sum;
23
'sum' declared without an initial value
1245 int flag = 1;
1246 ccv_bbf_stage_classifier_t* classifier = cascade->stage_classifier;
1247 for (j = 0; j < cascade->count; ++j, ++classifier)
24
Assuming the condition is false
25
Loop condition is false. Execution continues on line 1260
1248 {
1249 sum = 0;
1250 float* alpha = classifier->alpha;
1251 ccv_bbf_feature_t* feature = classifier->feature;
1252 for (k = 0; k < classifier->count; ++k, alpha += 2, ++feature)
1253 sum += alpha[_ccv_run_bbf_feature(feature, steps, u8)];
1254 if (sum < classifier->threshold)
1255 {
1256 flag = 0;
1257 break;
1258 }
1259 }
1260 if (flag)
26
Taking true branch
1261 {
1262 ccv_comp_t comp;
1263 comp.rect = ccv_rect((int)((x * 4 + dx[q] * 2) * scale_x + 0.5), (int)((y * 4 + dy[q] * 2) * scale_y + 0.5), (int)(cascade->size.width * scale_x + 0.5), (int)(cascade->size.height * scale_y + 0.5));
1264 comp.neighbors = 1;
1265 comp.classification.id = t;
1266 comp.classification.confidence = sum;
27
Assigned value is garbage or undefined
1267 ccv_array_push(seq, &comp);
1268 }
1269 u8[0] += 4;
1270 u8[1] += 2;
1271 u8[2] += 1;
1272 }
1273 u8[0] += paddings[0];
1274 u8[1] += paddings[1];
1275 u8[2] += paddings[2];
1276 }
1277 }
1278 scale_x *= scale;
1279 scale_y *= scale;
1280 }
1281
1282 /* the following code from OpenCV's haar feature implementation */
1283 if(params.min_neighbors == 0)
1284 {
1285 for (i = 0; i < seq->rnum; i++)
1286 {
1287 ccv_comp_t* comp = (ccv_comp_t*)ccv_array_get(seq, i)((void*)(((char*)((seq)->data)) + (size_t)(seq)->rsize *
(size_t)(i)))
;
1288 ccv_array_push(result_seq, comp);
1289 }
1290 } else {
1291 idx_seq = 0;
1292 ccv_array_clear(seq2);
1293 // group retrieved rectangles in order to filter out noise
1294 int ncomp = ccv_array_group(seq, &idx_seq, _ccv_is_equal_same_class, 0);
1295 ccv_comp_t* comps = (ccv_comp_t*)ccmallocmalloc((ncomp + 1) * sizeof(ccv_comp_t));
1296 memset(comps, 0, (ncomp + 1) * sizeof(ccv_comp_t));
1297
1298 // count number of neighbors
1299 for(i = 0; i < seq->rnum; i++)
1300 {
1301 ccv_comp_t r1 = *(ccv_comp_t*)ccv_array_get(seq, i)((void*)(((char*)((seq)->data)) + (size_t)(seq)->rsize *
(size_t)(i)))
;
1302 int idx = *(int*)ccv_array_get(idx_seq, i)((void*)(((char*)((idx_seq)->data)) + (size_t)(idx_seq)->
rsize * (size_t)(i)))
;
1303
1304 if (comps[idx].neighbors == 0)
1305 comps[idx].classification.confidence = r1.classification.confidence;
1306
1307 ++comps[idx].neighbors;
1308
1309 comps[idx].rect.x += r1.rect.x;
1310 comps[idx].rect.y += r1.rect.y;
1311 comps[idx].rect.width += r1.rect.width;
1312 comps[idx].rect.height += r1.rect.height;
1313 comps[idx].classification.id = r1.classification.id;
1314 comps[idx].classification.confidence = ccv_max(comps[idx].classification.confidence, r1.classification.confidence)({ typeof (comps[idx].classification.confidence) _a = (comps[
idx].classification.confidence); typeof (r1.classification.confidence
) _b = (r1.classification.confidence); (_a > _b) ? _a : _b
; })
;
1315 }
1316
1317 // calculate average bounding box
1318 for(i = 0; i < ncomp; i++)
1319 {
1320 int n = comps[i].neighbors;
1321 if(n >= params.min_neighbors)
1322 {
1323 ccv_comp_t comp;
1324 comp.rect.x = (comps[i].rect.x * 2 + n) / (2 * n);
1325 comp.rect.y = (comps[i].rect.y * 2 + n) / (2 * n);
1326 comp.rect.width = (comps[i].rect.width * 2 + n) / (2 * n);
1327 comp.rect.height = (comps[i].rect.height * 2 + n) / (2 * n);
1328 comp.neighbors = comps[i].neighbors;
1329 comp.classification.id = comps[i].classification.id;
1330 comp.classification.confidence = comps[i].classification.confidence;
1331 ccv_array_push(seq2, &comp);
1332 }
1333 }
1334
1335 // filter out small face rectangles inside large face rectangles
1336 for(i = 0; i < seq2->rnum; i++)
1337 {
1338 ccv_comp_t r1 = *(ccv_comp_t*)ccv_array_get(seq2, i)((void*)(((char*)((seq2)->data)) + (size_t)(seq2)->rsize
* (size_t)(i)))
;
1339 int flag = 1;
1340
1341 for(j = 0; j < seq2->rnum; j++)
1342 {
1343 ccv_comp_t r2 = *(ccv_comp_t*)ccv_array_get(seq2, j)((void*)(((char*)((seq2)->data)) + (size_t)(seq2)->rsize
* (size_t)(j)))
;
1344 int distance = (int)(r2.rect.width * 0.25 + 0.5);
1345
1346 if(i != j &&
1347 r1.classification.id == r2.classification.id &&
1348 r1.rect.x >= r2.rect.x - distance &&
1349 r1.rect.y >= r2.rect.y - distance &&
1350 r1.rect.x + r1.rect.width <= r2.rect.x + r2.rect.width + distance &&
1351 r1.rect.y + r1.rect.height <= r2.rect.y + r2.rect.height + distance &&
1352 (r2.neighbors > ccv_max(3, r1.neighbors)({ typeof (3) _a = (3); typeof (r1.neighbors) _b = (r1.neighbors
); (_a > _b) ? _a : _b; })
|| r1.neighbors < 3))
1353 {
1354 flag = 0;
1355 break;
1356 }
1357 }
1358
1359 if(flag)
1360 ccv_array_push(result_seq, &r1);
1361 }
1362 ccv_array_free(idx_seq);
1363 ccfreefree(comps);
1364 }
1365 }
1366
1367 ccv_array_free(seq);
1368 ccv_array_free(seq2);
1369
1370 ccv_array_t* result_seq2;
1371 /* the following code from OpenCV's haar feature implementation */
1372 if (params.flags & CCV_BBF_NO_NESTED)
1373 {
1374 result_seq2 = ccv_array_new(sizeof(ccv_comp_t), 64, 0);
1375 idx_seq = 0;
1376 // group retrieved rectangles in order to filter out noise
1377 int ncomp = ccv_array_group(result_seq, &idx_seq, _ccv_is_equal, 0);
1378 ccv_comp_t* comps = (ccv_comp_t*)ccmallocmalloc((ncomp + 1) * sizeof(ccv_comp_t));
1379 memset(comps, 0, (ncomp + 1) * sizeof(ccv_comp_t));
1380
1381 // count number of neighbors
1382 for(i = 0; i < result_seq->rnum; i++)
1383 {
1384 ccv_comp_t r1 = *(ccv_comp_t*)ccv_array_get(result_seq, i)((void*)(((char*)((result_seq)->data)) + (size_t)(result_seq
)->rsize * (size_t)(i)))
;
1385 int idx = *(int*)ccv_array_get(idx_seq, i)((void*)(((char*)((idx_seq)->data)) + (size_t)(idx_seq)->
rsize * (size_t)(i)))
;
1386
1387 if (comps[idx].neighbors == 0 || comps[idx].classification.confidence < r1.classification.confidence)
1388 {
1389 comps[idx].classification.confidence = r1.classification.confidence;
1390 comps[idx].neighbors = 1;
1391 comps[idx].rect = r1.rect;
1392 comps[idx].classification.id = r1.classification.id;
1393 }
1394 }
1395
1396 // calculate average bounding box
1397 for(i = 0; i < ncomp; i++)
1398 if(comps[i].neighbors)
1399 ccv_array_push(result_seq2, &comps[i]);
1400
1401 ccv_array_free(result_seq);
1402 ccfreefree(comps);
1403 } else {
1404 result_seq2 = result_seq;
1405 }
1406
1407 for (i = 1; i < scale_upto + next * 2; i++)
1408 ccv_matrix_free(pyr[i * 4]);
1409 if (params.accurate)
1410 for (i = next * 2; i < scale_upto + next * 2; i++)
1411 {
1412 ccv_matrix_free(pyr[i * 4 + 1]);
1413 ccv_matrix_free(pyr[i * 4 + 2]);
1414 ccv_matrix_free(pyr[i * 4 + 3]);
1415 }
1416 if (params.size.height != _cascade[0]->size.height || params.size.width != _cascade[0]->size.width)
1417 ccv_matrix_free(pyr[0]);
1418
1419 return result_seq2;
1420}
1421
1422ccv_bbf_classifier_cascade_t* ccv_bbf_read_classifier_cascade(const char* directory)
1423{
1424 char buf[1024];
1425 sprintf(buf, "%s/cascade.txt", directory);
1426 int s, i;
1427 FILE* r = fopen(buf, "r");
1428 if (r == 0)
1429 return 0;
1430 ccv_bbf_classifier_cascade_t* cascade = (ccv_bbf_classifier_cascade_t*)ccmallocmalloc(sizeof(ccv_bbf_classifier_cascade_t));
1431 s = fscanf(r, "%d %d %d", &cascade->count, &cascade->size.width, &cascade->size.height);
1432 assert(s > 0)((void) sizeof ((s > 0) ? 1 : 0), __extension__ ({ if (s >
0) ; else __assert_fail ("s > 0", "ccv_bbf.c", 1432, __extension__
__PRETTY_FUNCTION__); }))
;
1433 cascade->stage_classifier = (ccv_bbf_stage_classifier_t*)ccmallocmalloc(cascade->count * sizeof(ccv_bbf_stage_classifier_t));
1434 for (i = 0; i < cascade->count; i++)
1435 {
1436 sprintf(buf, "%s/stage-%d.txt", directory, i);
1437 if (_ccv_read_bbf_stage_classifier(buf, &cascade->stage_classifier[i]) < 0)
1438 {
1439 cascade->count = i;
1440 break;
1441 }
1442 }
1443 fclose(r);
1444 return cascade;
1445}
1446
1447ccv_bbf_classifier_cascade_t* ccv_bbf_classifier_cascade_read_binary(char* s)
1448{
1449 int i;
1450 ccv_bbf_classifier_cascade_t* cascade = (ccv_bbf_classifier_cascade_t*)ccmallocmalloc(sizeof(ccv_bbf_classifier_cascade_t));
1451 memcpy(&cascade->count, s, sizeof(cascade->count)); s += sizeof(cascade->count);
1452 memcpy(&cascade->size.width, s, sizeof(cascade->size.width)); s += sizeof(cascade->size.width);
1453 memcpy(&cascade->size.height, s, sizeof(cascade->size.height)); s += sizeof(cascade->size.height);
1454 ccv_bbf_stage_classifier_t* classifier = cascade->stage_classifier = (ccv_bbf_stage_classifier_t*)ccmallocmalloc(cascade->count * sizeof(ccv_bbf_stage_classifier_t));
1455 for (i = 0; i < cascade->count; i++, classifier++)
1456 {
1457 memcpy(&classifier->count, s, sizeof(classifier->count)); s += sizeof(classifier->count);
1458 memcpy(&classifier->threshold, s, sizeof(classifier->threshold)); s += sizeof(classifier->threshold);
1459 classifier->feature = (ccv_bbf_feature_t*)ccmallocmalloc(classifier->count * sizeof(ccv_bbf_feature_t));
1460 classifier->alpha = (float*)ccmallocmalloc(classifier->count * 2 * sizeof(float));
1461 memcpy(classifier->feature, s, classifier->count * sizeof(ccv_bbf_feature_t)); s += classifier->count * sizeof(ccv_bbf_feature_t);
1462 memcpy(classifier->alpha, s, classifier->count * 2 * sizeof(float)); s += classifier->count * 2 * sizeof(float);
1463 }
1464 return cascade;
1465
1466}
1467
1468int ccv_bbf_classifier_cascade_write_binary(ccv_bbf_classifier_cascade_t* cascade, char* s, int slen)
1469{
1470 int i;
1471 int len = sizeof(cascade->count) + sizeof(cascade->size.width) + sizeof(cascade->size.height);
1472 ccv_bbf_stage_classifier_t* classifier = cascade->stage_classifier;
1473 for (i = 0; i < cascade->count; i++, classifier++)
1474 len += sizeof(classifier->count) + sizeof(classifier->threshold) + classifier->count * sizeof(ccv_bbf_feature_t) + classifier->count * 2 * sizeof(float);
1475 if (slen >= len)
1476 {
1477 memcpy(s, &cascade->count, sizeof(cascade->count)); s += sizeof(cascade->count);
1478 memcpy(s, &cascade->size.width, sizeof(cascade->size.width)); s += sizeof(cascade->size.width);
1479 memcpy(s, &cascade->size.height, sizeof(cascade->size.height)); s += sizeof(cascade->size.height);
1480 classifier = cascade->stage_classifier;
1481 for (i = 0; i < cascade->count; i++, classifier++)
1482 {
1483 memcpy(s, &classifier->count, sizeof(classifier->count)); s += sizeof(classifier->count);
1484 memcpy(s, &classifier->threshold, sizeof(classifier->threshold)); s += sizeof(classifier->threshold);
1485 memcpy(s, classifier->feature, classifier->count * sizeof(ccv_bbf_feature_t)); s += classifier->count * sizeof(ccv_bbf_feature_t);
1486 memcpy(s, classifier->alpha, classifier->count * 2 * sizeof(float)); s += classifier->count * 2 * sizeof(float);
1487 }
1488 }
1489 return len;
1490}
1491
1492void ccv_bbf_classifier_cascade_free(ccv_bbf_classifier_cascade_t* cascade)
1493{
1494 int i;
1495 for (i = 0; i < cascade->count; ++i)
1496 {
1497 ccfreefree(cascade->stage_classifier[i].feature);
1498 ccfreefree(cascade->stage_classifier[i].alpha);
1499 }
1500 ccfreefree(cascade->stage_classifier);
1501 ccfreefree(cascade);
1502}