Bug Summary

File:ccv_bbf.c
Warning:line 829, column 43
The left operand of '-' is a garbage value

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)
1
Assuming 'best_feature' is not equal to null
2
Taking false branch
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++)
3
Loop condition is true. Entering loop body
685 if (best_feature->pz[i] == -1)
4
Assuming the condition is true
5
Taking true branch
686 {
687 best_gene.pk = i;
688 break;
6
Execution continues on line 690
689 }
690 for (i = 0; i < CCV_BBF_POINT_MAX(8); i++)
7
Loop condition is true. Entering loop body
691 if (best_feature->nz[i] == -1)
8
Assuming the condition is true
9
Taking true branch
692 {
693 best_gene.nk = i;
694 break;
10
Execution continues on line 702
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)
11
Loop condition is true. Entering loop body
703 {
704 g = 0;
705 for (i = 0; i < 3; i++)
12
Loop condition is true. Entering loop body
15
Loop condition is true. Entering loop body
18
Loop condition is true. Entering loop body
21
Loop condition is false. Execution continues on line 795
706 for (j = 0; j < cols[i]; j++)
13
Assuming the condition is false
14
Loop condition is false. Execution continues on line 705
16
Assuming the condition is false
17
Loop condition is false. Execution continues on line 705
19
Assuming the condition is false
20
Loop condition is false. Execution continues on line 705
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)
22
Taking false branch
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)
23
Taking false branch
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)
;
24
Assuming the condition is false
25
Taking false branch
26
Loop condition is false. Exiting loop
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)
27
The left operand of '-' is a garbage value
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));
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)
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++)
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++)
1208 ccv_sample_down(pyr[i * 4 - next * 4], &pyr[i * 4], 0, 0, 0);
1209 if (params.accurate)
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++)
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++)
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++)
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++)
1241 {
1242 for (x = 0; x < i_cols; x++)
1243 {
1244 float sum;
1245 int flag = 1;
1246 ccv_bbf_stage_classifier_t* classifier = cascade->stage_classifier;
1247 for (j = 0; j < cascade->count; ++j, ++classifier)
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)
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;
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}