Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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