Bug Summary

File:ccv_dpm.c
Warning:line 2298, column 3
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior

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_dpm.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-20-143410-95304-1 -x c ccv_dpm.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_multifit.h>
7#include <gsl/gsl_randist.h>
8#endif
9#ifdef USE_OPENMP
10#include <omp.h>
11#endif
12#ifdef HAVE_LIBLINEAR1
13#include <linear.h>
14#endif
15
16const ccv_dpm_param_t ccv_dpm_default_params = {
17 .interval = 8,
18 .min_neighbors = 1,
19 .flags = 0,
20 .threshold = 0.6, // 0.8
21};
22
23#define CCV_DPM_WINDOW_SIZE(8) (8)
24
25static int _ccv_dpm_scale_upto(ccv_dense_matrix_t* a, ccv_dpm_mixture_model_t** _model, int count, int interval)
26{
27 int c, i;
28 ccv_size_t size = ccv_size(a->cols, a->rows);
29 for (c = 0; c < count; c++)
30 {
31 ccv_dpm_mixture_model_t* model = _model[c];
32 for (i = 0; i < model->count; i++)
33 {
34 size.width = ccv_min(model->root[i].root.w->cols * CCV_DPM_WINDOW_SIZE, size.width)({ typeof (model->root[i].root.w->cols * (8)) _a = (model
->root[i].root.w->cols * (8)); typeof (size.width) _b =
(size.width); (_a < _b) ? _a : _b; })
;
35 size.height = ccv_min(model->root[i].root.w->rows * CCV_DPM_WINDOW_SIZE, size.height)({ typeof (model->root[i].root.w->rows * (8)) _a = (model
->root[i].root.w->rows * (8)); typeof (size.height) _b =
(size.height); (_a < _b) ? _a : _b; })
;
36 }
37 }
38 int hr = a->rows / size.height;
39 int wr = a->cols / size.width;
40 double scale = pow(2.0, 1.0 / (interval + 1.0));
41 int next = interval + 1;
42 return (int)(log((double)ccv_min(hr, wr)({ typeof (hr) _a = (hr); typeof (wr) _b = (wr); (_a < _b)
? _a : _b; })
) / log(scale)) - next;
43}
44
45static void _ccv_dpm_feature_pyramid(ccv_dense_matrix_t* a, ccv_dense_matrix_t** pyr, int scale_upto, int interval)
46{
47 int next = interval + 1;
48 double scale = pow(2.0, 1.0 / (interval + 1.0));
49 memset(pyr, 0, (scale_upto + next * 2) * sizeof(ccv_dense_matrix_t*));
50 pyr[next] = a;
51 int i;
52 for (i = 1; i <= interval; i++)
53 ccv_resample(pyr[next], &pyr[next + i], 0, (double)(int)(pyr[next]->rows / pow(scale, i)) / (double)pyr[next]->rows, (double)(int)(pyr[next]->cols / pow(scale, i)) / (double)pyr[next]->cols, CCV_INTER_AREA);
54 for (i = next; i < scale_upto + next; i++)
55 ccv_sample_down(pyr[i], &pyr[i + next], 0, 0, 0);
56 ccv_dense_matrix_t* hog;
57 /* a more efficient way to generate up-scaled hog (using smaller size) */
58 for (i = 0; i < next; i++)
59 {
60 hog = 0;
61 ccv_hog(pyr[i + next], &hog, 0, 9, CCV_DPM_WINDOW_SIZE(8) / 2 /* this is */);
62 pyr[i] = hog;
63 }
64 hog = 0;
65 ccv_hog(pyr[next], &hog, 0, 9, CCV_DPM_WINDOW_SIZE(8));
66 pyr[next] = hog;
67 for (i = next + 1; i < scale_upto + next * 2; i++)
68 {
69 hog = 0;
70 ccv_hog(pyr[i], &hog, 0, 9, CCV_DPM_WINDOW_SIZE(8));
71 ccv_matrix_free(pyr[i]);
72 pyr[i] = hog;
73 }
74}
75
76static void _ccv_dpm_compute_score(ccv_dpm_root_classifier_t* root_classifier, ccv_dense_matrix_t* hog, ccv_dense_matrix_t* hog2x, ccv_dense_matrix_t** _response, ccv_dense_matrix_t** part_feature, ccv_dense_matrix_t** dx, ccv_dense_matrix_t** dy)
77{
78 ccv_dense_matrix_t* response = 0;
79 ccv_filter(hog, root_classifier->root.w, &response, 0, CCV_NO_PADDING);
80 ccv_dense_matrix_t* root_feature = 0;
81 ccv_flatten(response, (ccv_matrix_t**)&root_feature, 0, 0);
82 ccv_matrix_free(response);
83 *_response = root_feature;
84 if (hog2x == 0)
85 return;
86 ccv_make_matrix_mutable(root_feature);
87 int rwh = (root_classifier->root.w->rows - 1) / 2, rww = (root_classifier->root.w->cols - 1) / 2;
88 int rwh_1 = root_classifier->root.w->rows / 2, rww_1 = root_classifier->root.w->cols / 2;
89 int i, x, y;
90 for (i = 0; i < root_classifier->count; i++)
91 {
92 ccv_dpm_part_classifier_t* part = root_classifier->part + i;
93 ccv_dense_matrix_t* response = 0;
94 ccv_filter(hog2x, part->w, &response, 0, CCV_NO_PADDING);
95 ccv_dense_matrix_t* feature = 0;
96 ccv_flatten(response, (ccv_matrix_t**)&feature, 0, 0);
97 ccv_matrix_free(response);
98 part_feature[i] = dx[i] = dy[i] = 0;
99 ccv_distance_transform(feature, &part_feature[i], 0, &dx[i], 0, &dy[i], 0, part->dx, part->dy, part->dxx, part->dyy, CCV_NEGATIVE | CCV_GSEDT);
100 ccv_matrix_free(feature);
101 int pwh = (part->w->rows - 1) / 2, pww = (part->w->cols - 1) / 2;
102 int offy = part->y + pwh - rwh * 2;
103 int miny = pwh, maxy = part_feature[i]->rows - part->w->rows + pwh;
104 int offx = part->x + pww - rww * 2;
105 int minx = pww, maxx = part_feature[i]->cols - part->w->cols + pww;
106 float* f_ptr = (float*)ccv_get_dense_matrix_cell_by(CCV_32F | CCV_C1, root_feature, rwh, 0, 0)(((CCV_32F | CCV_C1) & CCV_32S) ? (void*)((root_feature)->
data.i32 + ((rwh) * (root_feature)->cols + (0)) * ((CCV_32F
| CCV_C1) & 0xFFF) + (0)) : (((CCV_32F | CCV_C1) & CCV_32F
) ? (void*)((root_feature)->data.f32+ ((rwh) * (root_feature
)->cols + (0)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)) :
(((CCV_32F | CCV_C1) & CCV_64S) ? (void*)((root_feature)
->data.i64+ ((rwh) * (root_feature)->cols + (0)) * ((CCV_32F
| CCV_C1) & 0xFFF) + (0)) : (((CCV_32F | CCV_C1) & CCV_64F
) ? (void*)((root_feature)->data.f64 + ((rwh) * (root_feature
)->cols + (0)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)) :
(void*)((root_feature)->data.u8 + (rwh) * (root_feature)->
step + (0) * ((CCV_32F | CCV_C1) & 0xFFF) + (0))))))
;
107 for (y = rwh; y < root_feature->rows - rwh_1; y++)
108 {
109 int iy = ccv_clamp(y * 2 + offy, miny, maxy)({ typeof (miny) _a = (miny); typeof (maxy) _b = (maxy); typeof
(y * 2 + offy) _x = (y * 2 + offy); (_x < _a) ? _a : ((_x
> _b) ? _b : _x); })
;
110 for (x = rww; x < root_feature->cols - rww_1; x++)
111 {
112 int ix = ccv_clamp(x * 2 + offx, minx, maxx)({ typeof (minx) _a = (minx); typeof (maxx) _b = (maxx); typeof
(x * 2 + offx) _x = (x * 2 + offx); (_x < _a) ? _a : ((_x
> _b) ? _b : _x); })
;
113 f_ptr[x] -= ccv_get_dense_matrix_cell_value_by(CCV_32F | CCV_C1, part_feature[i], iy, ix, 0)(((CCV_32F | CCV_C1) & CCV_32S) ? (part_feature[i])->data
.i32[((iy) * (part_feature[i])->cols + (ix)) * ((CCV_32F |
CCV_C1) & 0xFFF) + (0)] : (((CCV_32F | CCV_C1) & CCV_32F
) ? (part_feature[i])->data.f32[((iy) * (part_feature[i])->
cols + (ix)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)] : (((CCV_32F
| CCV_C1) & CCV_64S) ? (part_feature[i])->data.i64[((
iy) * (part_feature[i])->cols + (ix)) * ((CCV_32F | CCV_C1
) & 0xFFF) + (0)] : (((CCV_32F | CCV_C1) & CCV_64F) ?
(part_feature[i])->data.f64[((iy) * (part_feature[i])->
cols + (ix)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)] : (part_feature
[i])->data.u8[(iy) * (part_feature[i])->step + (ix) * (
(CCV_32F | CCV_C1) & 0xFFF) + (0)]))))
;
114 }
115 f_ptr += root_feature->cols;
116 }
117 }
118}
119
120#ifdef HAVE_LIBLINEAR1
121#ifdef HAVE_GSL1
122
123static uint64_t _ccv_dpm_time_measure()
124{
125 struct timeval tv;
126 gettimeofday(&tv, 0);
127 return tv.tv_sec * 1000000 + tv.tv_usec;
128}
129
130#define less_than(fn1, fn2, aux) ((fn1).value >= (fn2).value)
131static CCV_IMPLEMENT_QSORT(_ccv_dpm_aspect_qsort, struct feature_node, less_than)void _ccv_dpm_aspect_qsort(struct feature_node *array, size_t
total, int aux) { int isort_thresh = 7; struct feature_node t
; int sp = 0; struct { struct feature_node *lb; struct feature_node
*ub; } stack[48]; if( total <= 1 ) return; stack[0].lb = array
; stack[0].ub = array + (total - 1); while( sp >= 0 ) { struct
feature_node* left = stack[sp].lb; struct feature_node* right
= stack[sp--].ub; for(;;) { int i, n = (int)(right - left) +
1, m; struct feature_node* ptr; struct feature_node* 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 { struct feature_node* left0; struct feature_node* left1
; struct feature_node* right0; struct feature_node* right1; struct
feature_node* pivot; struct feature_node* a; struct feature_node
* b; struct feature_node* 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
; } } } }
132#undef less_than
133
134#define less_than(a1, a2, aux) ((a1) < (a2))
135static CCV_IMPLEMENT_QSORT(_ccv_dpm_area_qsort, int, less_than)void _ccv_dpm_area_qsort(int *array, size_t total, int aux) {
int isort_thresh = 7; int t; int sp = 0; struct { int *lb; int
*ub; } stack[48]; if( total <= 1 ) return; stack[0].lb = array
; stack[0].ub = array + (total - 1); while( sp >= 0 ) { int
* left = stack[sp].lb; int* right = stack[sp--].ub; for(;;) {
int i, n = (int)(right - left) + 1, m; int* ptr; int* 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 { int* left0; int* left1; int* right0; int* right1; int
* pivot; int* a; int* b; int* 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
; } } } }
136#undef less_than
137
138#define less_than(s1, s2, aux) ((s1) < (s2))
139static CCV_IMPLEMENT_QSORT(_ccv_dpm_score_qsort, double, less_than)void _ccv_dpm_score_qsort(double *array, size_t total, int aux
) { int isort_thresh = 7; double t; int sp = 0; struct { double
*lb; double *ub; } stack[48]; if( total <= 1 ) return; stack
[0].lb = array; stack[0].ub = array + (total - 1); while( sp >=
0 ) { double* left = stack[sp].lb; double* right = stack[sp--
].ub; for(;;) { int i, n = (int)(right - left) + 1, m; double
* ptr; double* 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 { double* left0; double
* left1; double* right0; double* right1; double* pivot; double
* a; double* b; double* 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
; } } } }
140#undef less_than
141
142static ccv_dpm_mixture_model_t* _ccv_dpm_model_copy(ccv_dpm_mixture_model_t* _model)
143{
144 ccv_dpm_mixture_model_t* model = (ccv_dpm_mixture_model_t*)ccmallocmalloc(sizeof(ccv_dpm_mixture_model_t));
145 model->count = _model->count;
146 model->root = (ccv_dpm_root_classifier_t*)ccmallocmalloc(sizeof(ccv_dpm_root_classifier_t) * model->count);
147 int i, j;
148 memcpy(model->root, _model->root, sizeof(ccv_dpm_root_classifier_t) * model->count);
149 for (i = 0; i < model->count; i++)
150 {
151 ccv_dpm_root_classifier_t* _root = _model->root + i;
152 ccv_dpm_root_classifier_t* root = model->root + i;
153 root->root.w = ccv_dense_matrix_new(_root->root.w->rows, _root->root.w->cols, CCV_32F | 31, 0, 0);
154 memcpy(root->root.w->data.u8, _root->root.w->data.u8, _root->root.w->rows * _root->root.w->step);
155 ccv_make_matrix_immutable(root->root.w);
156 ccv_dpm_part_classifier_t* _part = _root->part;
157 ccv_dpm_part_classifier_t* part = root->part = (ccv_dpm_part_classifier_t*)ccmallocmalloc(sizeof(ccv_dpm_part_classifier_t) * root->count);
158 memcpy(part, _part, sizeof(ccv_dpm_part_classifier_t) * root->count);
159 for (j = 0; j < root->count; j++)
160 {
161 part[j].w = ccv_dense_matrix_new(_part[j].w->rows, _part[j].w->cols, CCV_32F | 31, 0, 0);
162 memcpy(part[j].w->data.u8, _part[j].w->data.u8, _part[j].w->rows * _part[j].w->step);
163 ccv_make_matrix_immutable(part[j].w);
164 }
165 }
166 return model;
167}
168
169static void _ccv_dpm_write_checkpoint(ccv_dpm_mixture_model_t* model, int done, const char* dir)
170{
171 char swpfile[1024];
172 sprintf(swpfile, "%s.swp", dir);
173 FILE* w = fopen(swpfile, "w+");
174 if (!w)
175 return;
176 if (done)
177 fprintf(w, ".\n");
178 else
179 fprintf(w, ",\n");
180 int i, j, x, y, ch, count = 0;
181 for (i = 0; i < model->count; i++)
182 {
183 if (model->root[i].root.w == 0)
184 break;
185 count++;
186 }
187 if (done)
188 fprintf(w, "%d\n", model->count);
189 else
190 fprintf(w, "%d %d\n", model->count, count);
191 for (i = 0; i < count; i++)
192 {
193 ccv_dpm_root_classifier_t* root_classifier = model->root + i;
194 fprintf(w, "%d %d\n", root_classifier->root.w->rows, root_classifier->root.w->cols);
195 fprintf(w, "%a %a %a %a\n", root_classifier->beta, root_classifier->alpha[0], root_classifier->alpha[1], root_classifier->alpha[2]);
196 ch = CCV_GET_CHANNEL(root_classifier->root.w->type)((root_classifier->root.w->type) & 0xFFF);
197 for (y = 0; y < root_classifier->root.w->rows; y++)
198 {
199 for (x = 0; x < root_classifier->root.w->cols * ch; x++)
200 fprintf(w, "%a ", root_classifier->root.w->data.f32[y * root_classifier->root.w->cols * ch + x]);
201 fprintf(w, "\n");
202 }
203 fprintf(w, "%d\n", root_classifier->count);
204 for (j = 0; j < root_classifier->count; j++)
205 {
206 ccv_dpm_part_classifier_t* part_classifier = root_classifier->part + j;
207 fprintf(w, "%d %d %d\n", part_classifier->x, part_classifier->y, part_classifier->z);
208 fprintf(w, "%la %la %la %la\n", part_classifier->dx, part_classifier->dy, part_classifier->dxx, part_classifier->dyy);
209 fprintf(w, "%a %a %a %a %a %a\n", part_classifier->alpha[0], part_classifier->alpha[1], part_classifier->alpha[2], part_classifier->alpha[3], part_classifier->alpha[4], part_classifier->alpha[5]);
210 fprintf(w, "%d %d %d\n", part_classifier->w->rows, part_classifier->w->cols, part_classifier->counterpart);
211 ch = CCV_GET_CHANNEL(part_classifier->w->type)((part_classifier->w->type) & 0xFFF);
212 for (y = 0; y < part_classifier->w->rows; y++)
213 {
214 for (x = 0; x < part_classifier->w->cols * ch; x++)
215 fprintf(w, "%a ", part_classifier->w->data.f32[y * part_classifier->w->cols * ch + x]);
216 fprintf(w, "\n");
217 }
218 }
219 }
220 fclose(w);
221 rename(swpfile, dir);
222}
223
224static void _ccv_dpm_read_checkpoint(ccv_dpm_mixture_model_t* model, const char* dir)
225{
226 FILE* r = fopen(dir, "r");
227 if (!r)
228 return;
229 int count;
230 char flag;
231 fscanf(r, "%c", &flag);
232 assert(flag == ',')((void) sizeof ((flag == ',') ? 1 : 0), __extension__ ({ if (
flag == ',') ; else __assert_fail ("flag == ','", "ccv_dpm.c"
, 232, __extension__ __PRETTY_FUNCTION__); }))
;
233 fscanf(r, "%d %d", &model->count, &count);
234 ccv_dpm_root_classifier_t* root_classifier = (ccv_dpm_root_classifier_t*)ccmallocmalloc(sizeof(ccv_dpm_root_classifier_t) * count);
235 memset(root_classifier, 0, sizeof(ccv_dpm_root_classifier_t) * count);
236 int i, j, k;
237 for (i = 0; i < count; i++)
238 {
239 int rows, cols;
240 fscanf(r, "%d %d", &rows, &cols);
241 fscanf(r, "%f %f %f %f", &root_classifier[i].beta, &root_classifier[i].alpha[0], &root_classifier[i].alpha[1], &root_classifier[i].alpha[2]);
242 root_classifier[i].root.w = ccv_dense_matrix_new(rows, cols, CCV_32F | 31, 0, 0);
243 for (j = 0; j < rows * cols * 31; j++)
244 fscanf(r, "%f", &root_classifier[i].root.w->data.f32[j]);
245 ccv_make_matrix_immutable(root_classifier[i].root.w);
246 fscanf(r, "%d", &root_classifier[i].count);
247 if (root_classifier[i].count <= 0)
248 {
249 root_classifier[i].part = 0;
250 continue;
251 }
252 ccv_dpm_part_classifier_t* part_classifier = (ccv_dpm_part_classifier_t*)ccmallocmalloc(sizeof(ccv_dpm_part_classifier_t) * root_classifier[i].count);
253 for (j = 0; j < root_classifier[i].count; j++)
254 {
255 fscanf(r, "%d %d %d", &part_classifier[j].x, &part_classifier[j].y, &part_classifier[j].z);
256 fscanf(r, "%lf %lf %lf %lf", &part_classifier[j].dx, &part_classifier[j].dy, &part_classifier[j].dxx, &part_classifier[j].dyy);
257 fscanf(r, "%f %f %f %f %f %f", &part_classifier[j].alpha[0], &part_classifier[j].alpha[1], &part_classifier[j].alpha[2], &part_classifier[j].alpha[3], &part_classifier[j].alpha[4], &part_classifier[j].alpha[5]);
258 fscanf(r, "%d %d %d", &rows, &cols, &part_classifier[j].counterpart);
259 part_classifier[j].w = ccv_dense_matrix_new(rows, cols, CCV_32F | 31, 0, 0);
260 for (k = 0; k < rows * cols * 31; k++)
261 fscanf(r, "%f", &part_classifier[j].w->data.f32[k]);
262 ccv_make_matrix_immutable(part_classifier[j].w);
263 }
264 root_classifier[i].part = part_classifier;
265 }
266 model->root = root_classifier;
267 fclose(r);
268}
269
270static void _ccv_dpm_mixture_model_cleanup(ccv_dpm_mixture_model_t* model)
271{
272 /* this is different because it doesn't compress to a continuous memory region */
273 int i, j;
274 for (i = 0; i < model->count; i++)
275 {
276 ccv_dpm_root_classifier_t* root_classifier = model->root + i;
277 for (j = 0; j < root_classifier->count; j++)
278 {
279 ccv_dpm_part_classifier_t* part_classifier = root_classifier->part + j;
280 ccv_matrix_free(part_classifier->w);
281 }
282 if (root_classifier->count > 0)
283 ccfreefree(root_classifier->part);
284 if (root_classifier->root.w != 0)
285 ccv_matrix_free(root_classifier->root.w);
286 }
287 ccfreefree(model->root);
288 model->count = 0;
289 model->root = 0;
290}
291
292static const int _ccv_dpm_sym_lut[] = { 2, 3, 0, 1,
293 4 + 0, 4 + 8, 4 + 7, 4 + 6, 4 + 5, 4 + 4, 4 + 3, 4 + 2, 4 + 1,
294 13 + 9, 13 + 8, 13 + 7, 13 + 6, 13 + 5, 13 + 4, 13 + 3, 13 + 2, 13 + 1, 13, 13 + 17, 13 + 16, 13 + 15, 13 + 14, 13 + 13, 13 + 12, 13 + 11, 13 + 10 };
295
296static void _ccv_dpm_check_root_classifier_symmetry(ccv_dense_matrix_t* w)
297{
298 assert(CCV_GET_CHANNEL(w->type) == 31 && CCV_GET_DATA_TYPE(w->type) == CCV_32F)((void) sizeof ((((w->type) & 0xFFF) == 31 && (
(w->type) & 0xFF000) == CCV_32F) ? 1 : 0), __extension__
({ if (((w->type) & 0xFFF) == 31 && ((w->type
) & 0xFF000) == CCV_32F) ; else __assert_fail ("CCV_GET_CHANNEL(w->type) == 31 && CCV_GET_DATA_TYPE(w->type) == CCV_32F"
, "ccv_dpm.c", 298, __extension__ __PRETTY_FUNCTION__); }))
;
299 float *w_ptr = w->data.f32;
300 int i, j, k;
301 for (i = 0; i < w->rows; i++)
302 {
303 for (j = 0; j < w->cols; j++)
304 {
305 for (k = 0; k < 31; k++)
306 {
307 double v = fabs(w_ptr[j * 31 + k] - w_ptr[(w->cols - 1 - j) * 31 + _ccv_dpm_sym_lut[k]]);
308 if (v > 0.002)
309 PRINT(CCV_CLI_INFO, "symmetric violation at (%d, %d, %d), off by: %f\n", i, j, k, v)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("symmetric violation at (%d, %d, %d), off by: %f\n", i, j, k
, v); fflush(stdout); } } while (0)
;
310 }
311 }
312 w_ptr += w->cols * 31;
313 }
314}
315
316typedef struct {
317 int id;
318 int count;
319 float score;
320 int x, y;
321 float scale_x, scale_y;
322 ccv_dpm_part_classifier_t root;
323 ccv_dpm_part_classifier_t* part;
324} ccv_dpm_feature_vector_t;
325
326static void _ccv_dpm_collect_examples_randomly(gsl_rng* rng, ccv_array_t** negex, char** bgfiles, int bgnum, int negnum, int components, int* rows, int* cols, int grayscale)
327{
328 int i, j;
329 for (i = 0; i < components; i++)
330 negex[i] = ccv_array_new(sizeof(ccv_dpm_feature_vector_t), negnum, 0);
331 int mrows = rows[0], mcols = cols[0];
332 for (i = 1; i < components; i++)
333 {
334 mrows = ccv_max(mrows, rows[i])({ typeof (mrows) _a = (mrows); typeof (rows[i]) _b = (rows[i
]); (_a > _b) ? _a : _b; })
;
335 mcols = ccv_max(mcols, cols[i])({ typeof (mcols) _a = (mcols); typeof (cols[i]) _b = (cols[i
]); (_a > _b) ? _a : _b; })
;
336 }
337 FLUSH(CCV_CLI_INFO, " - generating negative examples for all models : 0 / %d", negnum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - generating negative examples for all models : 0 / %d"
, negnum); fflush(stdout); } } while (0)
;
338 while (negex[0]->rnum < negnum)
339 {
340 double p = (double)negnum / (double)bgnum;
341 for (i = 0; i < bgnum; i++)
342 if (gsl_rng_uniform(rng) < p)
343 {
344 ccv_dense_matrix_t* image = 0;
345 ccv_read(bgfiles[i], &image, (grayscale ? CCV_IO_GRAY : 0) | CCV_IO_ANY_FILE)ccv_read_impl(bgfiles[i], &image, (grayscale ? CCV_IO_GRAY
: 0) | CCV_IO_ANY_FILE, 0, 0, 0)
;
346 assert(image != 0)((void) sizeof ((image != 0) ? 1 : 0), __extension__ ({ if (image
!= 0) ; else __assert_fail ("image != 0", "ccv_dpm.c", 346, __extension__
__PRETTY_FUNCTION__); }))
;
347 if (image->rows - mrows * CCV_DPM_WINDOW_SIZE(8) < 0 ||
348 image->cols - mcols * CCV_DPM_WINDOW_SIZE(8) < 0)
349 {
350 ccv_matrix_free(image);
351 continue;
352 }
353 int y = gsl_rng_uniform_int(rng, image->rows - mrows * CCV_DPM_WINDOW_SIZE(8) + 1);
354 int x = gsl_rng_uniform_int(rng, image->cols - mcols * CCV_DPM_WINDOW_SIZE(8) + 1);
355 for (j = 0; j < components; j++)
356 {
357 ccv_dense_matrix_t* slice = 0;
358 ccv_slice(image, (ccv_matrix_t**)&slice, 0, y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE(8) + 1) / 2, x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE(8) + 1) / 2, rows[j] * CCV_DPM_WINDOW_SIZE(8), cols[j] * CCV_DPM_WINDOW_SIZE(8));
359 assert(y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 >= 0 &&((void) sizeof ((y + ((mrows - rows[j]) * (8) + 1) / 2 >= 0
&& y + ((mrows - rows[j]) * (8) + 1) / 2 + rows[j] *
(8) <= image->rows && x + ((mcols - cols[j]) *
(8) + 1) / 2 >= 0 && x + ((mcols - cols[j]) * (8)
+ 1) / 2 + cols[j] * (8) <= image->cols) ? 1 : 0), __extension__
({ if (y + ((mrows - rows[j]) * (8) + 1) / 2 >= 0 &&
y + ((mrows - rows[j]) * (8) + 1) / 2 + rows[j] * (8) <= image
->rows && x + ((mcols - cols[j]) * (8) + 1) / 2 >=
0 && x + ((mcols - cols[j]) * (8) + 1) / 2 + cols[j]
* (8) <= image->cols) ; else __assert_fail ("y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 >= 0 && y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 + rows[j] * CCV_DPM_WINDOW_SIZE <= image->rows && x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 >= 0 && x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 + cols[j] * CCV_DPM_WINDOW_SIZE <= image->cols"
, "ccv_dpm.c", 362, __extension__ __PRETTY_FUNCTION__); }))
360 y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 + rows[j] * CCV_DPM_WINDOW_SIZE <= image->rows &&((void) sizeof ((y + ((mrows - rows[j]) * (8) + 1) / 2 >= 0
&& y + ((mrows - rows[j]) * (8) + 1) / 2 + rows[j] *
(8) <= image->rows && x + ((mcols - cols[j]) *
(8) + 1) / 2 >= 0 && x + ((mcols - cols[j]) * (8)
+ 1) / 2 + cols[j] * (8) <= image->cols) ? 1 : 0), __extension__
({ if (y + ((mrows - rows[j]) * (8) + 1) / 2 >= 0 &&
y + ((mrows - rows[j]) * (8) + 1) / 2 + rows[j] * (8) <= image
->rows && x + ((mcols - cols[j]) * (8) + 1) / 2 >=
0 && x + ((mcols - cols[j]) * (8) + 1) / 2 + cols[j]
* (8) <= image->cols) ; else __assert_fail ("y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 >= 0 && y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 + rows[j] * CCV_DPM_WINDOW_SIZE <= image->rows && x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 >= 0 && x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 + cols[j] * CCV_DPM_WINDOW_SIZE <= image->cols"
, "ccv_dpm.c", 362, __extension__ __PRETTY_FUNCTION__); }))
361 x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 >= 0 &&((void) sizeof ((y + ((mrows - rows[j]) * (8) + 1) / 2 >= 0
&& y + ((mrows - rows[j]) * (8) + 1) / 2 + rows[j] *
(8) <= image->rows && x + ((mcols - cols[j]) *
(8) + 1) / 2 >= 0 && x + ((mcols - cols[j]) * (8)
+ 1) / 2 + cols[j] * (8) <= image->cols) ? 1 : 0), __extension__
({ if (y + ((mrows - rows[j]) * (8) + 1) / 2 >= 0 &&
y + ((mrows - rows[j]) * (8) + 1) / 2 + rows[j] * (8) <= image
->rows && x + ((mcols - cols[j]) * (8) + 1) / 2 >=
0 && x + ((mcols - cols[j]) * (8) + 1) / 2 + cols[j]
* (8) <= image->cols) ; else __assert_fail ("y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 >= 0 && y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 + rows[j] * CCV_DPM_WINDOW_SIZE <= image->rows && x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 >= 0 && x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 + cols[j] * CCV_DPM_WINDOW_SIZE <= image->cols"
, "ccv_dpm.c", 362, __extension__ __PRETTY_FUNCTION__); }))
362 x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 + cols[j] * CCV_DPM_WINDOW_SIZE <= image->cols)((void) sizeof ((y + ((mrows - rows[j]) * (8) + 1) / 2 >= 0
&& y + ((mrows - rows[j]) * (8) + 1) / 2 + rows[j] *
(8) <= image->rows && x + ((mcols - cols[j]) *
(8) + 1) / 2 >= 0 && x + ((mcols - cols[j]) * (8)
+ 1) / 2 + cols[j] * (8) <= image->cols) ? 1 : 0), __extension__
({ if (y + ((mrows - rows[j]) * (8) + 1) / 2 >= 0 &&
y + ((mrows - rows[j]) * (8) + 1) / 2 + rows[j] * (8) <= image
->rows && x + ((mcols - cols[j]) * (8) + 1) / 2 >=
0 && x + ((mcols - cols[j]) * (8) + 1) / 2 + cols[j]
* (8) <= image->cols) ; else __assert_fail ("y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 >= 0 && y + ((mrows - rows[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 + rows[j] * CCV_DPM_WINDOW_SIZE <= image->rows && x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 >= 0 && x + ((mcols - cols[j]) * CCV_DPM_WINDOW_SIZE + 1) / 2 + cols[j] * CCV_DPM_WINDOW_SIZE <= image->cols"
, "ccv_dpm.c", 362, __extension__ __PRETTY_FUNCTION__); }))
;
363 ccv_dense_matrix_t* hog = 0;
364 ccv_hog(slice, &hog, 0, 9, CCV_DPM_WINDOW_SIZE(8));
365 ccv_matrix_free(slice);
366 ccv_dpm_feature_vector_t vector = {
367 .id = j,
368 .count = 0,
369 .part = 0,
370 };
371 ccv_make_matrix_mutable(hog);
372 assert(hog->rows == rows[j] && hog->cols == cols[j] && CCV_GET_CHANNEL(hog->type) == 31 && CCV_GET_DATA_TYPE(hog->type) == CCV_32F)((void) sizeof ((hog->rows == rows[j] && hog->cols
== cols[j] && ((hog->type) & 0xFFF) == 31 &&
((hog->type) & 0xFF000) == CCV_32F) ? 1 : 0), __extension__
({ if (hog->rows == rows[j] && hog->cols == cols
[j] && ((hog->type) & 0xFFF) == 31 && (
(hog->type) & 0xFF000) == CCV_32F) ; else __assert_fail
("hog->rows == rows[j] && hog->cols == cols[j] && CCV_GET_CHANNEL(hog->type) == 31 && CCV_GET_DATA_TYPE(hog->type) == CCV_32F"
, "ccv_dpm.c", 372, __extension__ __PRETTY_FUNCTION__); }))
;
373 vector.root.w = hog;
374 ccv_array_push(negex[j], &vector);
375 }
376 ccv_matrix_free(image);
377 FLUSH(CCV_CLI_INFO, " - generating negative examples for all models : %d / %d", negex[0]->rnum, negnum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - generating negative examples for all models : %d / %d"
, negex[0]->rnum, negnum); fflush(stdout); } } while (0)
;
378 if (negex[0]->rnum >= negnum)
379 break;
380 }
381 }
382}
383
384static ccv_array_t* _ccv_dpm_summon_examples_by_rectangle(char** posfiles, ccv_rect_t* bboxes, int posnum, int id, int rows, int cols, int grayscale)
385{
386 int i;
387 FLUSH(CCV_CLI_INFO, " - generating positive examples for model %d : 0 / %d", id, posnum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - generating positive examples for model %d : 0 / %d"
, id, posnum); fflush(stdout); } } while (0)
;
388 ccv_array_t* posv = ccv_array_new(sizeof(ccv_dpm_feature_vector_t), posnum, 0);
389 for (i = 0; i < posnum; i++)
390 {
391 ccv_rect_t bbox = bboxes[i];
392 int mcols = (int)(sqrtf(bbox.width * bbox.height * cols / (float)rows) + 0.5);
393 int mrows = (int)(sqrtf(bbox.width * bbox.height * rows / (float)cols) + 0.5);
394 bbox.x = bbox.x + (bbox.width - mcols) / 2;
395 bbox.y = bbox.y + (bbox.height - mrows) / 2;
396 bbox.width = mcols;
397 bbox.height = mrows;
398 ccv_dpm_feature_vector_t vector = {
399 .id = id,
400 .count = 0,
401 .part = 0,
402 };
403 // resolution is too low to be useful
404 if (mcols * 2 < cols * CCV_DPM_WINDOW_SIZE(8) || mrows * 2 < rows * CCV_DPM_WINDOW_SIZE(8))
405 {
406 vector.root.w = 0;
407 ccv_array_push(posv, &vector);
408 continue;
409 }
410 ccv_dense_matrix_t* image = 0;
411 ccv_read(posfiles[i], &image, (grayscale ? CCV_IO_GRAY : 0) | CCV_IO_ANY_FILE)ccv_read_impl(posfiles[i], &image, (grayscale ? CCV_IO_GRAY
: 0) | CCV_IO_ANY_FILE, 0, 0, 0)
;
412 assert(image != 0)((void) sizeof ((image != 0) ? 1 : 0), __extension__ ({ if (image
!= 0) ; else __assert_fail ("image != 0", "ccv_dpm.c", 412, __extension__
__PRETTY_FUNCTION__); }))
;
413 ccv_dense_matrix_t* up2x = 0;
414 ccv_sample_up(image, &up2x, 0, 0, 0);
415 ccv_matrix_free(image);
416 ccv_dense_matrix_t* slice = 0;
417 ccv_slice(up2x, (ccv_matrix_t**)&slice, 0, bbox.y * 2, bbox.x * 2, bbox.height * 2, bbox.width * 2);
418 ccv_matrix_free(up2x);
419 ccv_dense_matrix_t* resize = 0;
420 ccv_resample(slice, &resize, 0, (double)(rows * CCV_DPM_WINDOW_SIZE(8)) / (double)slice->rows, (double)(cols * CCV_DPM_WINDOW_SIZE(8)) / (double)slice->cols, CCV_INTER_AREA);
421 ccv_matrix_free(slice);
422 ccv_dense_matrix_t* hog = 0;
423 ccv_hog(resize, &hog, 0, 9, CCV_DPM_WINDOW_SIZE(8));
424 ccv_matrix_free(resize);
425 ccv_make_matrix_mutable(hog);
426 assert(hog->rows == rows && hog->cols == cols && CCV_GET_CHANNEL(hog->type) == 31 && CCV_GET_DATA_TYPE(hog->type) == CCV_32F)((void) sizeof ((hog->rows == rows && hog->cols
== cols && ((hog->type) & 0xFFF) == 31 &&
((hog->type) & 0xFF000) == CCV_32F) ? 1 : 0), __extension__
({ if (hog->rows == rows && hog->cols == cols &&
((hog->type) & 0xFFF) == 31 && ((hog->type
) & 0xFF000) == CCV_32F) ; else __assert_fail ("hog->rows == rows && hog->cols == cols && CCV_GET_CHANNEL(hog->type) == 31 && CCV_GET_DATA_TYPE(hog->type) == CCV_32F"
, "ccv_dpm.c", 426, __extension__ __PRETTY_FUNCTION__); }))
;
427 vector.root.w = hog;
428 ccv_array_push(posv, &vector);
429 FLUSH(CCV_CLI_INFO, " - generating positive examples for model %d : %d / %d", id, i + 1, posnum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - generating positive examples for model %d : %d / %d"
, id, i + 1, posnum); fflush(stdout); } } while (0)
;
430 }
431 return posv;
432}
433
434static void _ccv_dpm_initialize_root_classifier(gsl_rng* rng, ccv_dpm_root_classifier_t* root_classifier, int label, int cnum, int* poslabels, ccv_array_t* posex, int* neglabels, ccv_array_t* negex, double C, int symmetric, int grayscale)
435{
436 int i, j, x, y, k, l;
437 int cols = root_classifier->root.w->cols;
438 int cols2c = (cols + 1) / 2;
439 int rows = root_classifier->root.w->rows;
440 PRINT(CCV_CLI_INFO, " - creating initial model %d at %dx%d\n", label + 1, cols, rows)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - creating initial model %d at %dx%d\n", label + 1, cols, rows
); fflush(stdout); } } while (0)
;
441 struct problem prob;
442 prob.n = symmetric ? 31 * cols2c * rows + 1 : 31 * cols * rows + 1;
443 prob.bias = symmetric ? 0.5 : 1.0; // for symmetric, since we only pass half features in, need to set bias to be half too
444 // new version (1.91) of liblinear uses double instead of int (1.8) for prob.y, cannot cast for that.
445 prob.y = malloc(sizeof(prob.y[0]) * (cnum + negex->rnum) * (!!symmetric + 1));
446 prob.x = (struct feature_node**)malloc(sizeof(struct feature_node*) * (cnum + negex->rnum) * (!!symmetric + 1));
447 FLUSH(CCV_CLI_INFO, " - converting examples to liblinear format: %d / %d", 0, (cnum + negex->rnum) * (!!symmetric + 1))do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - converting examples to liblinear format: %d / %d"
, 0, (cnum + negex->rnum) * (!!symmetric + 1)); fflush(stdout
); } } while (0)
;
448 l = 0;
449 for (i = 0; i < posex->rnum; i++)
450 if (poslabels[i] == label)
451 {
452 ccv_dense_matrix_t* hog = ((ccv_dpm_feature_vector_t*)ccv_array_get(posex, i)((void*)(((char*)((posex)->data)) + (size_t)(posex)->rsize
* (size_t)(i)))
)->root.w;
453 if (!hog)
454 continue;
455 struct feature_node* features;
456 if (symmetric)
457 {
458 features = (struct feature_node*)malloc(sizeof(struct feature_node) * (31 * cols2c * rows + 2));
459 float* hptr = hog->data.f32;
460 j = 0;
461 for (y = 0; y < rows; y++)
462 {
463 for (x = 0; x < cols2c; x++)
464 for (k = 0; k < 31; k++)
465 {
466 features[j].index = j + 1;
467 features[j].value = hptr[x * 31 + k];
468 ++j;
469 }
470 hptr += hog->cols * 31;
471 }
472 features[j].index = j + 1;
473 features[j].value = prob.bias;
474 features[j + 1].index = -1;
475 prob.x[l] = features;
476 prob.y[l] = 1;
477 ++l;
478 features = (struct feature_node*)malloc(sizeof(struct feature_node) * (31 * cols2c * rows + 2));
479 hptr = hog->data.f32;
480 j = 0;
481 for (y = 0; y < rows; y++)
482 {
483 for (x = 0; x < cols2c; x++)
484 for (k = 0; k < 31; k++)
485 {
486 features[j].index = j + 1;
487 features[j].value = hptr[(cols - 1 - x) * 31 + _ccv_dpm_sym_lut[k]];
488 ++j;
489 }
490 hptr += hog->cols * 31;
491 }
492 features[j].index = j + 1;
493 features[j].value = prob.bias;
494 features[j + 1].index = -1;
495 prob.x[l] = features;
496 prob.y[l] = 1;
497 ++l;
498 } else {
499 features = (struct feature_node*)malloc(sizeof(struct feature_node) * (31 * cols * rows + 2));
500 for (j = 0; j < rows * cols * 31; j++)
501 {
502 features[j].index = j + 1;
503 features[j].value = hog->data.f32[j];
504 }
505 features[31 * rows * cols].index = 31 * rows * cols + 1;
506 features[31 * rows * cols].value = prob.bias;
507 features[31 * rows * cols + 1].index = -1;
508 prob.x[l] = features;
509 prob.y[l] = 1;
510 ++l;
511 }
512 FLUSH(CCV_CLI_INFO, " - converting examples to liblinear format: %d / %d", l, (cnum + negex->rnum) * (!!symmetric + 1))do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - converting examples to liblinear format: %d / %d"
, l, (cnum + negex->rnum) * (!!symmetric + 1)); fflush(stdout
); } } while (0)
;
513 }
514 for (i = 0; i < negex->rnum; i++)
515 if (neglabels[i] == label)
516 {
517 ccv_dense_matrix_t* hog = ((ccv_dpm_feature_vector_t*)ccv_array_get(negex, i)((void*)(((char*)((negex)->data)) + (size_t)(negex)->rsize
* (size_t)(i)))
)->root.w;
518 struct feature_node* features;
519 if (symmetric)
520 {
521 features = (struct feature_node*)malloc(sizeof(struct feature_node) * (31 * cols2c * rows + 2));
522 float* hptr = hog->data.f32;
523 j = 0;
524 for (y = 0; y < rows; y++)
525 {
526 for (x = 0; x < cols2c; x++)
527 for (k = 0; k < 31; k++)
528 {
529 features[j].index = j + 1;
530 features[j].value = hptr[x * 31 + k];
531 ++j;
532 }
533 hptr += hog->cols * 31;
534 }
535 features[j].index = j + 1;
536 features[j].value = prob.bias;
537 features[j + 1].index = -1;
538 prob.x[l] = features;
539 prob.y[l] = -1;
540 ++l;
541 features = (struct feature_node*)malloc(sizeof(struct feature_node) * (31 * cols2c * rows + 2));
542 hptr = hog->data.f32;
543 j = 0;
544 for (y = 0; y < rows; y++)
545 {
546 for (x = 0; x < cols2c; x++)
547 for (k = 0; k < 31; k++)
548 {
549 features[j].index = j + 1;
550 features[j].value = hptr[(cols - 1 - x) * 31 + _ccv_dpm_sym_lut[k]];
551 ++j;
552 }
553 hptr += hog->cols * 31;
554 }
555 features[j].index = j + 1;
556 features[j].value = prob.bias;
557 features[j + 1].index = -1;
558 prob.x[l] = features;
559 prob.y[l] = -1;
560 ++l;
561 } else {
562 features = (struct feature_node*)malloc(sizeof(struct feature_node) * (31 * cols * rows + 2));
563 for (j = 0; j < 31 * rows * cols; j++)
564 {
565 features[j].index = j + 1;
566 features[j].value = hog->data.f32[j];
567 }
568 features[31 * rows * cols].index = 31 * rows * cols + 1;
569 features[31 * rows * cols].value = prob.bias;
570 features[31 * rows * cols + 1].index = -1;
571 prob.x[l] = features;
572 prob.y[l] = -1;
573 ++l;
574 }
575 FLUSH(CCV_CLI_INFO, " - converting examples to liblinear format: %d / %d", l, (cnum + negex->rnum) * (!!symmetric + 1))do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - converting examples to liblinear format: %d / %d"
, l, (cnum + negex->rnum) * (!!symmetric + 1)); fflush(stdout
); } } while (0)
;
576 }
577 prob.l = l;
578 PRINT(CCV_CLI_INFO, "\n - generated %d examples with %d dimensions each\n"do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n - generated %d examples with %d dimensions each\n" " - running liblinear for initial linear SVM model (L2-regularized, L1-loss)\n"
, prob.l, prob.n); fflush(stdout); } } while (0)
579 " - running liblinear for initial linear SVM model (L2-regularized, L1-loss)\n", prob.l, prob.n)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n - generated %d examples with %d dimensions each\n" " - running liblinear for initial linear SVM model (L2-regularized, L1-loss)\n"
, prob.l, prob.n); fflush(stdout); } } while (0)
;
580 struct parameter linear_parameters = { .solver_type = L2R_L1LOSS_SVC_DUAL,
581 .eps = 1e-1,
582 .C = C,
583 .nr_weight = 0,
584 .weight_label = 0,
585 .weight = 0 };
586 const char* err = check_parameter(&prob, &linear_parameters);
587 if (err)
588 {
589 PRINT(CCV_CLI_ERROR, " - ERROR: cannot pass check parameter: %s\n", err)do { if ((CCV_CLI_ERROR & ccv_cli_get_output_levels())) {
printf(" - ERROR: cannot pass check parameter: %s\n", err); fflush
(stdout); } } while (0)
;
590 exit(-1);
591 }
592 struct model* linear = train(&prob, &linear_parameters);
593 assert(linear != 0)((void) sizeof ((linear != 0) ? 1 : 0), __extension__ ({ if (
linear != 0) ; else __assert_fail ("linear != 0", "ccv_dpm.c"
, 593, __extension__ __PRETTY_FUNCTION__); }))
;
594 PRINT(CCV_CLI_INFO, " - model->label[0]: %d, model->nr_class: %d, model->nr_feature: %d\n", linear->label[0], linear->nr_class, linear->nr_feature)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - model->label[0]: %d, model->nr_class: %d, model->nr_feature: %d\n"
, linear->label[0], linear->nr_class, linear->nr_feature
); fflush(stdout); } } while (0)
;
595 if (symmetric)
596 {
597 float* wptr = root_classifier->root.w->data.f32;
598 for (y = 0; y < rows; y++)
599 {
600 for (x = 0; x < cols2c; x++)
601 for (k = 0; k < 31; k++)
602 wptr[(cols - 1 - x) * 31 + _ccv_dpm_sym_lut[k]] = wptr[x * 31 + k] = linear->w[(y * cols2c + x) * 31 + k];
603 wptr += cols * 31;
604 }
605 // since for symmetric, lsvm only computed half features, to compensate that, we doubled the constant.
606 root_classifier->beta = linear->w[31 * rows * cols2c] * 2.0;
607 } else {
608 for (j = 0; j < 31 * rows * cols; j++)
609 root_classifier->root.w->data.f32[j] = linear->w[j];
610 root_classifier->beta = linear->w[31 * rows * cols];
611 }
612 free_and_destroy_model(&linear);
613 free(prob.y);
614 for (j = 0; j < prob.l; j++)
615 free(prob.x[j]);
616 free(prob.x);
617 ccv_make_matrix_immutable(root_classifier->root.w);
618}
619
620static void _ccv_dpm_initialize_part_classifiers(ccv_dpm_root_classifier_t* root_classifier, int parts, int symmetric)
621{
622 int i, j, k, x, y;
623 ccv_dense_matrix_t* w = 0;
624 ccv_sample_up(root_classifier->root.w, &w, 0, 0, 0);
625 ccv_make_matrix_mutable(w);
626 root_classifier->count = parts;
627 root_classifier->part = (ccv_dpm_part_classifier_t*)ccmallocmalloc(sizeof(ccv_dpm_part_classifier_t) * parts);
628 memset(root_classifier->part, 0, sizeof(ccv_dpm_part_classifier_t) * parts);
629 double area = w->rows * w->cols / (double)parts;
630 for (i = 0; i < parts;)
631 {
632 ccv_dpm_part_classifier_t* part_classifier = root_classifier->part + i;
633 int dx = 0, dy = 0, dw = 0, dh = 0, sym = 0;
634 double dsum = -1.0; // absolute value, thus, -1.0 is enough
635#define slice_and_update_if_needed(y, x, l, n, s){ ccv_dense_matrix_t* slice = 0; ccv_slice(w, (ccv_matrix_t**
)&slice, 0, y, x, l, n); double sum = ccv_sum(slice, CCV_UNSIGNED
) / (double)(l * n); if (sum > dsum) { dsum = sum; dx = x;
dy = y; dw = n; dh = l; sym = s; } ccv_matrix_free(slice); }
\
636 { \
637 ccv_dense_matrix_t* slice = 0; \
638 ccv_slice(w, (ccv_matrix_t**)&slice, 0, y, x, l, n); \
639 double sum = ccv_sum(slice, CCV_UNSIGNED) / (double)(l * n); \
640 if (sum > dsum) \
641 { \
642 dsum = sum; \
643 dx = x; \
644 dy = y; \
645 dw = n; \
646 dh = l; \
647 sym = s; \
648 } \
649 ccv_matrix_free(slice); \
650 }
651 for (j = 1; (j < area + 1) && (j * 3 <= w->rows * 2); j++)
652 {
653 k = (int)(area / j + 0.5);
654 if (k < 1 || k * 3 > w->cols * 2)
655 continue;
656 if (j > k * 2 || k > j * 2)
657 continue;
658 if (symmetric)
659 {
660 if (k % 2 == w->cols % 2) // can be symmetric in horizontal center
661 {
662 x = (w->cols - k) / 2;
663 for (y = 0; y < w->rows - j + 1; y++)
664 slice_and_update_if_needed(y, x, j, k, 0){ ccv_dense_matrix_t* slice = 0; ccv_slice(w, (ccv_matrix_t**
)&slice, 0, y, x, j, k); double sum = ccv_sum(slice, CCV_UNSIGNED
) / (double)(j * k); if (sum > dsum) { dsum = sum; dx = x;
dy = y; dw = k; dh = j; sym = 0; } ccv_matrix_free(slice); }
;
665 }
666 if (i < parts - 1) // have 2 locations
667 {
668 for (y = 0; y < w->rows - j + 1; y++)
669 for (x = 0; x <= w->cols / 2 - k /* to avoid overlapping */; x++)
670 slice_and_update_if_needed(y, x, j, k, 1){ ccv_dense_matrix_t* slice = 0; ccv_slice(w, (ccv_matrix_t**
)&slice, 0, y, x, j, k); double sum = ccv_sum(slice, CCV_UNSIGNED
) / (double)(j * k); if (sum > dsum) { dsum = sum; dx = x;
dy = y; dw = k; dh = j; sym = 1; } ccv_matrix_free(slice); }
;
671 }
672 } else {
673 for (y = 0; y < w->rows - j + 1; y++)
674 for (x = 0; x < w->cols - k + 1; x++)
675 slice_and_update_if_needed(y, x, j, k, 0){ ccv_dense_matrix_t* slice = 0; ccv_slice(w, (ccv_matrix_t**
)&slice, 0, y, x, j, k); double sum = ccv_sum(slice, CCV_UNSIGNED
) / (double)(j * k); if (sum > dsum) { dsum = sum; dx = x;
dy = y; dw = k; dh = j; sym = 0; } ccv_matrix_free(slice); }
;
676 }
677 }
678 PRINT(CCV_CLI_INFO, " ---- part %d(%d) %dx%d at (%d,%d), entropy: %lf\n", i + 1, parts, dw, dh, dx, dy, dsum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" ---- part %d(%d) %dx%d at (%d,%d), entropy: %lf\n", i + 1,
parts, dw, dh, dx, dy, dsum); fflush(stdout); } } while (0)
;
679 part_classifier->dx = 0;
680 part_classifier->dy = 0;
681 part_classifier->dxx = 0.1f;
682 part_classifier->dyy = 0.1f;
683 part_classifier->x = dx;
684 part_classifier->y = dy;
685 part_classifier->z = 1;
686 part_classifier->w = 0;
687 ccv_slice(w, (ccv_matrix_t**)&part_classifier->w, 0, dy, dx, dh, dw);
688 ccv_make_matrix_immutable(part_classifier->w);
689 /* clean up the region we selected */
690 float* w_ptr = (float*)ccv_get_dense_matrix_cell_by(CCV_32F | 31, w, dy, dx, 0)(((CCV_32F | 31) & CCV_32S) ? (void*)((w)->data.i32 + (
(dy) * (w)->cols + (dx)) * ((CCV_32F | 31) & 0xFFF) + (
0)) : (((CCV_32F | 31) & CCV_32F) ? (void*)((w)->data.
f32+ ((dy) * (w)->cols + (dx)) * ((CCV_32F | 31) & 0xFFF
) + (0)) : (((CCV_32F | 31) & CCV_64S) ? (void*)((w)->
data.i64+ ((dy) * (w)->cols + (dx)) * ((CCV_32F | 31) &
0xFFF) + (0)) : (((CCV_32F | 31) & CCV_64F) ? (void*)((w
)->data.f64 + ((dy) * (w)->cols + (dx)) * ((CCV_32F | 31
) & 0xFFF) + (0)) : (void*)((w)->data.u8 + (dy) * (w)->
step + (dx) * ((CCV_32F | 31) & 0xFFF) + (0))))))
;
691 for (y = 0; y < dh; y++)
692 {
693 for (x = 0; x < dw * 31; x++)
694 w_ptr[x] = 0;
695 w_ptr += w->cols * 31;
696 }
697 i++;
698 if (symmetric && sym) // add counter-part
699 {
700 dx = w->cols - (dx + dw);
701 PRINT(CCV_CLI_INFO, " ---- part %d(%d) %dx%d at (%d,%d), entropy: %lf\n", i + 1, parts, dw, dh, dx, dy, dsum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" ---- part %d(%d) %dx%d at (%d,%d), entropy: %lf\n", i + 1,
parts, dw, dh, dx, dy, dsum); fflush(stdout); } } while (0)
;
702 part_classifier[1].dx = 0;
703 part_classifier[1].dy = 0;
704 part_classifier[1].dxx = 0.1f;
705 part_classifier[1].dyy = 0.1f;
706 part_classifier[1].x = dx;
707 part_classifier[1].y = dy;
708 part_classifier[1].z = 1;
709 part_classifier[1].w = 0;
710 ccv_slice(w, (ccv_matrix_t**)&part_classifier[1].w, 0, dy, dx, dh, dw);
711 ccv_make_matrix_immutable(part_classifier[1].w);
712 /* clean up the region we selected */
713 float* w_ptr = (float*)ccv_get_dense_matrix_cell_by(CCV_32F | 31, w, dy, dx, 0)(((CCV_32F | 31) & CCV_32S) ? (void*)((w)->data.i32 + (
(dy) * (w)->cols + (dx)) * ((CCV_32F | 31) & 0xFFF) + (
0)) : (((CCV_32F | 31) & CCV_32F) ? (void*)((w)->data.
f32+ ((dy) * (w)->cols + (dx)) * ((CCV_32F | 31) & 0xFFF
) + (0)) : (((CCV_32F | 31) & CCV_64S) ? (void*)((w)->
data.i64+ ((dy) * (w)->cols + (dx)) * ((CCV_32F | 31) &
0xFFF) + (0)) : (((CCV_32F | 31) & CCV_64F) ? (void*)((w
)->data.f64 + ((dy) * (w)->cols + (dx)) * ((CCV_32F | 31
) & 0xFFF) + (0)) : (void*)((w)->data.u8 + (dy) * (w)->
step + (dx) * ((CCV_32F | 31) & 0xFFF) + (0))))))
;
714 for (y = 0; y < dh; y++)
715 {
716 for (x = 0; x < dw * 31; x++)
717 w_ptr[x] = 0;
718 w_ptr += w->cols * 31;
719 }
720 part_classifier[0].counterpart = i;
721 part_classifier[1].counterpart = i - 1;
722 i++;
723 } else {
724 part_classifier->counterpart = -1;
725 }
726 }
727 ccv_matrix_free(w);
728}
729
730static void _ccv_dpm_initialize_feature_vector_on_pattern(ccv_dpm_feature_vector_t* vector, ccv_dpm_root_classifier_t* root, int id)
731{
732 int i;
733 vector->id = id;
734 vector->count = root->count;
735 vector->part = (ccv_dpm_part_classifier_t*)ccmallocmalloc(sizeof(ccv_dpm_part_classifier_t) * root->count);
736 vector->root.w = ccv_dense_matrix_new(root->root.w->rows, root->root.w->cols, CCV_32F | 31, 0, 0);
737 for (i = 0; i < vector->count; i++)
738 {
739 vector->part[i].x = root->part[i].x;
740 vector->part[i].y = root->part[i].y;
741 vector->part[i].z = root->part[i].z;
742 vector->part[i].w = ccv_dense_matrix_new(root->part[i].w->rows, root->part[i].w->cols, CCV_32F | 31, 0, 0);
743 }
744}
745
746static void _ccv_dpm_feature_vector_cleanup(ccv_dpm_feature_vector_t* vector)
747{
748 int i;
749 if (vector->root.w)
750 ccv_matrix_free(vector->root.w);
751 for (i = 0; i < vector->count; i++)
752 ccv_matrix_free(vector->part[i].w);
753 if (vector->part)
754 ccfreefree(vector->part);
755}
756
757static void _ccv_dpm_feature_vector_free(ccv_dpm_feature_vector_t* vector)
758{
759 _ccv_dpm_feature_vector_cleanup(vector);
760 ccfreefree(vector);
761}
762
763static double _ccv_dpm_vector_score(ccv_dpm_mixture_model_t* model, ccv_dpm_feature_vector_t* v)
764{
765 if (v->id < 0 || v->id >= model->count)
766 return 0;
767 ccv_dpm_root_classifier_t* root_classifier = model->root + v->id;
768 double score = root_classifier->beta;
769 int i, k, ch = CCV_GET_CHANNEL(v->root.w->type)((v->root.w->type) & 0xFFF);
770 assert(ch == 31)((void) sizeof ((ch == 31) ? 1 : 0), __extension__ ({ if (ch ==
31) ; else __assert_fail ("ch == 31", "ccv_dpm.c", 770, __extension__
__PRETTY_FUNCTION__); }))
;
771 float *vptr = v->root.w->data.f32;
772 float *wptr = root_classifier->root.w->data.f32;
773 for (i = 0; i < v->root.w->rows * v->root.w->cols * ch; i++)
774 score += wptr[i] * vptr[i];
775 assert(v->count == root_classifier->count || (v->count == 0 && v->part == 0))((void) sizeof ((v->count == root_classifier->count || (
v->count == 0 && v->part == 0)) ? 1 : 0), __extension__
({ if (v->count == root_classifier->count || (v->count
== 0 && v->part == 0)) ; else __assert_fail ("v->count == root_classifier->count || (v->count == 0 && v->part == 0)"
, "ccv_dpm.c", 775, __extension__ __PRETTY_FUNCTION__); }))
;
776 for (k = 0; k < v->count; k++)
777 {
778 ccv_dpm_part_classifier_t* part_classifier = root_classifier->part + k;
779 ccv_dpm_part_classifier_t* part_vector = v->part + k;
780 score -= part_classifier->dx * part_vector->dx;
781 score -= part_classifier->dxx * part_vector->dxx;
782 score -= part_classifier->dy * part_vector->dy;
783 score -= part_classifier->dyy * part_vector->dyy;
784 vptr = part_vector->w->data.f32;
785 wptr = part_classifier->w->data.f32;
786 for (i = 0; i < part_vector->w->rows * part_vector->w->cols * ch; i++)
787 score += wptr[i] * vptr[i];
788 }
789 return score;
790}
791
792static void _ccv_dpm_collect_feature_vector(ccv_dpm_feature_vector_t* v, float score, int x, int y, ccv_dense_matrix_t* pyr, ccv_dense_matrix_t* detail, ccv_dense_matrix_t** dx, ccv_dense_matrix_t** dy)
793{
794 v->score = score;
795 v->x = x;
796 v->y = y;
797 ccv_zero(v->root.w);
798 int rwh = (v->root.w->rows - 1) / 2, rww = (v->root.w->cols - 1) / 2;
799 int i, ix, iy, ch = CCV_GET_CHANNEL(v->root.w->type)((v->root.w->type) & 0xFFF);
800 float* h_ptr = (float*)ccv_get_dense_matrix_cell_by(CCV_32F | ch, pyr, y - rwh, x - rww, 0)(((CCV_32F | ch) & CCV_32S) ? (void*)((pyr)->data.i32 +
((y - rwh) * (pyr)->cols + (x - rww)) * ((CCV_32F | ch) &
0xFFF) + (0)) : (((CCV_32F | ch) & CCV_32F) ? (void*)((pyr
)->data.f32+ ((y - rwh) * (pyr)->cols + (x - rww)) * ((
CCV_32F | ch) & 0xFFF) + (0)) : (((CCV_32F | ch) & CCV_64S
) ? (void*)((pyr)->data.i64+ ((y - rwh) * (pyr)->cols +
(x - rww)) * ((CCV_32F | ch) & 0xFFF) + (0)) : (((CCV_32F
| ch) & CCV_64F) ? (void*)((pyr)->data.f64 + ((y - rwh
) * (pyr)->cols + (x - rww)) * ((CCV_32F | ch) & 0xFFF
) + (0)) : (void*)((pyr)->data.u8 + (y - rwh) * (pyr)->
step + (x - rww) * ((CCV_32F | ch) & 0xFFF) + (0))))))
;
801 float* w_ptr = v->root.w->data.f32;
802 for (iy = 0; iy < v->root.w->rows; iy++)
803 {
804 memcpy(w_ptr, h_ptr, v->root.w->cols * ch * sizeof(float));
805 h_ptr += pyr->cols * ch;
806 w_ptr += v->root.w->cols * ch;
807 }
808 for (i = 0; i < v->count; i++)
809 {
810 ccv_dpm_part_classifier_t* part = v->part + i;
811 int pww = (part->w->cols - 1) / 2, pwh = (part->w->rows - 1) / 2;
812 int offy = part->y + pwh - rwh * 2;
813 int offx = part->x + pww - rww * 2;
814 iy = ccv_clamp(y * 2 + offy, pwh, detail->rows - part->w->rows + pwh)({ typeof (pwh) _a = (pwh); typeof (detail->rows - part->
w->rows + pwh) _b = (detail->rows - part->w->rows
+ pwh); typeof (y * 2 + offy) _x = (y * 2 + offy); (_x < _a
) ? _a : ((_x > _b) ? _b : _x); })
;
815 ix = ccv_clamp(x * 2 + offx, pww, detail->cols - part->w->cols + pww)({ typeof (pww) _a = (pww); typeof (detail->cols - part->
w->cols + pww) _b = (detail->cols - part->w->cols
+ pww); typeof (x * 2 + offx) _x = (x * 2 + offx); (_x < _a
) ? _a : ((_x > _b) ? _b : _x); })
;
816 int ry = ccv_get_dense_matrix_cell_value_by(CCV_32S | CCV_C1, dy[i], iy, ix, 0)(((CCV_32S | CCV_C1) & CCV_32S) ? (dy[i])->data.i32[((
iy) * (dy[i])->cols + (ix)) * ((CCV_32S | CCV_C1) & 0xFFF
) + (0)] : (((CCV_32S | CCV_C1) & CCV_32F) ? (dy[i])->
data.f32[((iy) * (dy[i])->cols + (ix)) * ((CCV_32S | CCV_C1
) & 0xFFF) + (0)] : (((CCV_32S | CCV_C1) & CCV_64S) ?
(dy[i])->data.i64[((iy) * (dy[i])->cols + (ix)) * ((CCV_32S
| CCV_C1) & 0xFFF) + (0)] : (((CCV_32S | CCV_C1) & CCV_64F
) ? (dy[i])->data.f64[((iy) * (dy[i])->cols + (ix)) * (
(CCV_32S | CCV_C1) & 0xFFF) + (0)] : (dy[i])->data.u8[
(iy) * (dy[i])->step + (ix) * ((CCV_32S | CCV_C1) & 0xFFF
) + (0)]))))
;
817 int rx = ccv_get_dense_matrix_cell_value_by(CCV_32S | CCV_C1, dx[i], iy, ix, 0)(((CCV_32S | CCV_C1) & CCV_32S) ? (dx[i])->data.i32[((
iy) * (dx[i])->cols + (ix)) * ((CCV_32S | CCV_C1) & 0xFFF
) + (0)] : (((CCV_32S | CCV_C1) & CCV_32F) ? (dx[i])->
data.f32[((iy) * (dx[i])->cols + (ix)) * ((CCV_32S | CCV_C1
) & 0xFFF) + (0)] : (((CCV_32S | CCV_C1) & CCV_64S) ?
(dx[i])->data.i64[((iy) * (dx[i])->cols + (ix)) * ((CCV_32S
| CCV_C1) & 0xFFF) + (0)] : (((CCV_32S | CCV_C1) & CCV_64F
) ? (dx[i])->data.f64[((iy) * (dx[i])->cols + (ix)) * (
(CCV_32S | CCV_C1) & 0xFFF) + (0)] : (dx[i])->data.u8[
(iy) * (dx[i])->step + (ix) * ((CCV_32S | CCV_C1) & 0xFFF
) + (0)]))))
;
818 part->dx = rx; // I am not sure if I need to flip the sign or not (confirmed, it should be this way)
819 part->dy = ry;
820 part->dxx = rx * rx;
821 part->dyy = ry * ry;
822 // deal with out-of-bound error
823 int start_y = ccv_max(0, iy - ry - pwh)({ typeof (0) _a = (0); typeof (iy - ry - pwh) _b = (iy - ry -
pwh); (_a > _b) ? _a : _b; })
;
824 assert(start_y < detail->rows)((void) sizeof ((start_y < detail->rows) ? 1 : 0), __extension__
({ if (start_y < detail->rows) ; else __assert_fail ("start_y < detail->rows"
, "ccv_dpm.c", 824, __extension__ __PRETTY_FUNCTION__); }))
;
825 int start_x = ccv_max(0, ix - rx - pww)({ typeof (0) _a = (0); typeof (ix - rx - pww) _b = (ix - rx -
pww); (_a > _b) ? _a : _b; })
;
826 assert(start_x < detail->cols)((void) sizeof ((start_x < detail->cols) ? 1 : 0), __extension__
({ if (start_x < detail->cols) ; else __assert_fail ("start_x < detail->cols"
, "ccv_dpm.c", 826, __extension__ __PRETTY_FUNCTION__); }))
;
827 int end_y = ccv_min(detail->rows, iy - ry - pwh + part->w->rows)({ typeof (detail->rows) _a = (detail->rows); typeof (iy
- ry - pwh + part->w->rows) _b = (iy - ry - pwh + part
->w->rows); (_a < _b) ? _a : _b; })
;
828 assert(end_y >= 0)((void) sizeof ((end_y >= 0) ? 1 : 0), __extension__ ({ if
(end_y >= 0) ; else __assert_fail ("end_y >= 0", "ccv_dpm.c"
, 828, __extension__ __PRETTY_FUNCTION__); }))
;
829 int end_x = ccv_min(detail->cols, ix - rx - pww + part->w->cols)({ typeof (detail->cols) _a = (detail->cols); typeof (ix
- rx - pww + part->w->cols) _b = (ix - rx - pww + part
->w->cols); (_a < _b) ? _a : _b; })
;
830 assert(end_x >= 0)((void) sizeof ((end_x >= 0) ? 1 : 0), __extension__ ({ if
(end_x >= 0) ; else __assert_fail ("end_x >= 0", "ccv_dpm.c"
, 830, __extension__ __PRETTY_FUNCTION__); }))
;
831 h_ptr = (float*)ccv_get_dense_matrix_cell_by(CCV_32F | ch, detail, start_y, start_x, 0)(((CCV_32F | ch) & CCV_32S) ? (void*)((detail)->data.i32
+ ((start_y) * (detail)->cols + (start_x)) * ((CCV_32F | ch
) & 0xFFF) + (0)) : (((CCV_32F | ch) & CCV_32F) ? (void
*)((detail)->data.f32+ ((start_y) * (detail)->cols + (start_x
)) * ((CCV_32F | ch) & 0xFFF) + (0)) : (((CCV_32F | ch) &
CCV_64S) ? (void*)((detail)->data.i64+ ((start_y) * (detail
)->cols + (start_x)) * ((CCV_32F | ch) & 0xFFF) + (0))
: (((CCV_32F | ch) & CCV_64F) ? (void*)((detail)->data
.f64 + ((start_y) * (detail)->cols + (start_x)) * ((CCV_32F
| ch) & 0xFFF) + (0)) : (void*)((detail)->data.u8 + (
start_y) * (detail)->step + (start_x) * ((CCV_32F | ch) &
0xFFF) + (0))))))
;
832 ccv_zero(v->part[i].w);
833 w_ptr = (float*)ccv_get_dense_matrix_cell_by(CCV_32F | ch, part->w, start_y - (iy - ry - pwh), start_x - (ix - rx - pww), 0)(((CCV_32F | ch) & CCV_32S) ? (void*)((part->w)->data
.i32 + ((start_y - (iy - ry - pwh)) * (part->w)->cols +
(start_x - (ix - rx - pww))) * ((CCV_32F | ch) & 0xFFF) +
(0)) : (((CCV_32F | ch) & CCV_32F) ? (void*)((part->w
)->data.f32+ ((start_y - (iy - ry - pwh)) * (part->w)->
cols + (start_x - (ix - rx - pww))) * ((CCV_32F | ch) & 0xFFF
) + (0)) : (((CCV_32F | ch) & CCV_64S) ? (void*)((part->
w)->data.i64+ ((start_y - (iy - ry - pwh)) * (part->w)->
cols + (start_x - (ix - rx - pww))) * ((CCV_32F | ch) & 0xFFF
) + (0)) : (((CCV_32F | ch) & CCV_64F) ? (void*)((part->
w)->data.f64 + ((start_y - (iy - ry - pwh)) * (part->w)
->cols + (start_x - (ix - rx - pww))) * ((CCV_32F | ch) &
0xFFF) + (0)) : (void*)((part->w)->data.u8 + (start_y -
(iy - ry - pwh)) * (part->w)->step + (start_x - (ix - rx
- pww)) * ((CCV_32F | ch) & 0xFFF) + (0))))))
;
834 for (iy = start_y; iy < end_y; iy++)
835 {
836 memcpy(w_ptr, h_ptr, (end_x - start_x) * ch * sizeof(float));
837 h_ptr += detail->cols * ch;
838 w_ptr += part->w->cols * ch;
839 }
840 }
841}
842
843static ccv_dpm_feature_vector_t* _ccv_dpm_collect_best(ccv_dense_matrix_t* image, ccv_dpm_mixture_model_t* model, ccv_rect_t bbox, double overlap, ccv_dpm_param_t params)
844{
845 int i, j, k, x, y;
846 double scale = pow(2.0, 1.0 / (params.interval + 1.0));
847 int next = params.interval + 1;
848 int scale_upto = _ccv_dpm_scale_upto(image, &model, 1, params.interval);
849 if (scale_upto < 0)
850 return 0;
851 ccv_dense_matrix_t** pyr = (ccv_dense_matrix_t**)alloca((scale_upto + next * 2) * sizeof(ccv_dense_matrix_t*))__builtin_alloca ((scale_upto + next * 2) * sizeof(ccv_dense_matrix_t
*))
;
852 _ccv_dpm_feature_pyramid(image, pyr, scale_upto, params.interval);
853 float best = -FLT_MAX3.40282347e+38F;
854 ccv_dpm_feature_vector_t* v = 0;
855 for (i = 0; i < model->count; i++)
856 {
857 ccv_dpm_root_classifier_t* root_classifier = model->root + i;
858 double scale_x = 1.0;
859 double scale_y = 1.0;
860 for (j = next; j < scale_upto + next * 2; j++)
861 {
862 ccv_size_t size = ccv_size((int)(root_classifier->root.w->cols * CCV_DPM_WINDOW_SIZE(8) * scale_x + 0.5), (int)(root_classifier->root.w->rows * CCV_DPM_WINDOW_SIZE(8) * scale_y + 0.5));
863 if (ccv_min((double)(size.width * size.height), (double)(bbox.width * bbox.height))({ typeof ((double)(size.width * size.height)) _a = ((double)
(size.width * size.height)); typeof ((double)(bbox.width * bbox
.height)) _b = ((double)(bbox.width * bbox.height)); (_a <
_b) ? _a : _b; })
/
864 ccv_max((double)(bbox.width * bbox.height), (double)(size.width * size.height))({ typeof ((double)(bbox.width * bbox.height)) _a = ((double)
(bbox.width * bbox.height)); typeof ((double)(size.width * size
.height)) _b = ((double)(size.width * size.height)); (_a >
_b) ? _a : _b; })
< overlap)
865 {
866 scale_x *= scale;
867 scale_y *= scale;
868 continue;
869 }
870 ccv_dense_matrix_t* root_feature = 0;
871 ccv_dense_matrix_t* part_feature[CCV_DPM_PART_MAX(10)];
872 ccv_dense_matrix_t* dx[CCV_DPM_PART_MAX(10)];
873 ccv_dense_matrix_t* dy[CCV_DPM_PART_MAX(10)];
874 _ccv_dpm_compute_score(root_classifier, pyr[j], pyr[j - next], &root_feature, part_feature, dx, dy);
875 int rwh = (root_classifier->root.w->rows - 1) / 2, rww = (root_classifier->root.w->cols - 1) / 2;
876 int rwh_1 = root_classifier->root.w->rows / 2, rww_1 = root_classifier->root.w->cols / 2;
877 float* f_ptr = (float*)ccv_get_dense_matrix_cell_by(CCV_32F | CCV_C1, root_feature, rwh, 0, 0)(((CCV_32F | CCV_C1) & CCV_32S) ? (void*)((root_feature)->
data.i32 + ((rwh) * (root_feature)->cols + (0)) * ((CCV_32F
| CCV_C1) & 0xFFF) + (0)) : (((CCV_32F | CCV_C1) & CCV_32F
) ? (void*)((root_feature)->data.f32+ ((rwh) * (root_feature
)->cols + (0)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)) :
(((CCV_32F | CCV_C1) & CCV_64S) ? (void*)((root_feature)
->data.i64+ ((rwh) * (root_feature)->cols + (0)) * ((CCV_32F
| CCV_C1) & 0xFFF) + (0)) : (((CCV_32F | CCV_C1) & CCV_64F
) ? (void*)((root_feature)->data.f64 + ((rwh) * (root_feature
)->cols + (0)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)) :
(void*)((root_feature)->data.u8 + (rwh) * (root_feature)->
step + (0) * ((CCV_32F | CCV_C1) & 0xFFF) + (0))))))
;
878 for (y = rwh; y < root_feature->rows - rwh_1; y++)
879 {
880 for (x = rww; x < root_feature->cols - rww_1; x++)
881 {
882 ccv_rect_t rect = ccv_rect((int)((x - rww) * CCV_DPM_WINDOW_SIZE(8) * scale_x + 0.5), (int)((y - rwh) * CCV_DPM_WINDOW_SIZE(8) * scale_y + 0.5), (int)(root_classifier->root.w->cols * CCV_DPM_WINDOW_SIZE(8) * scale_x + 0.5), (int)(root_classifier->root.w->rows * CCV_DPM_WINDOW_SIZE(8) * scale_y + 0.5));
883 if ((double)(ccv_max(0, ccv_min(rect.x + rect.width, bbox.x + bbox.width) - ccv_max(rect.x, bbox.x))({ typeof (0) _a = (0); typeof (({ typeof (rect.x + rect.width
) _a = (rect.x + rect.width); typeof (bbox.x + bbox.width) _b
= (bbox.x + bbox.width); (_a < _b) ? _a : _b; }) - ({ typeof
(rect.x) _a = (rect.x); typeof (bbox.x) _b = (bbox.x); (_a >
_b) ? _a : _b; })) _b = (({ typeof (rect.x + rect.width) _a =
(rect.x + rect.width); typeof (bbox.x + bbox.width) _b = (bbox
.x + bbox.width); (_a < _b) ? _a : _b; }) - ({ typeof (rect
.x) _a = (rect.x); typeof (bbox.x) _b = (bbox.x); (_a > _b
) ? _a : _b; })); (_a > _b) ? _a : _b; })
*
884 ccv_max(0, ccv_min(rect.y + rect.height, bbox.y + bbox.height) - ccv_max(rect.y, bbox.y))({ typeof (0) _a = (0); typeof (({ typeof (rect.y + rect.height
) _a = (rect.y + rect.height); typeof (bbox.y + bbox.height) _b
= (bbox.y + bbox.height); (_a < _b) ? _a : _b; }) - ({ typeof
(rect.y) _a = (rect.y); typeof (bbox.y) _b = (bbox.y); (_a >
_b) ? _a : _b; })) _b = (({ typeof (rect.y + rect.height) _a
= (rect.y + rect.height); typeof (bbox.y + bbox.height) _b =
(bbox.y + bbox.height); (_a < _b) ? _a : _b; }) - ({ typeof
(rect.y) _a = (rect.y); typeof (bbox.y) _b = (bbox.y); (_a >
_b) ? _a : _b; })); (_a > _b) ? _a : _b; })
) /
885 (double)ccv_max(rect.width * rect.height, bbox.width * bbox.height)({ typeof (rect.width * rect.height) _a = (rect.width * rect.
height); typeof (bbox.width * bbox.height) _b = (bbox.width *
bbox.height); (_a > _b) ? _a : _b; })
>= overlap && f_ptr[x] > best)
886 {
887 // initialize v
888 if (v == 0)
889 {
890 v = (ccv_dpm_feature_vector_t*)ccmallocmalloc(sizeof(ccv_dpm_feature_vector_t));
891 _ccv_dpm_initialize_feature_vector_on_pattern(v, root_classifier, i);
892 }
893 // if it is another kind, cleanup and reinitialize
894 if (v->id != i)
895 {
896 _ccv_dpm_feature_vector_cleanup(v);
897 _ccv_dpm_initialize_feature_vector_on_pattern(v, root_classifier, i);
898 }
899 _ccv_dpm_collect_feature_vector(v, f_ptr[x] + root_classifier->beta, x, y, pyr[j], pyr[j - next], dx, dy);
900 v->scale_x = scale_x;
901 v->scale_y = scale_y;
902 best = f_ptr[x];
903 }
904 }
905 f_ptr += root_feature->cols;
906 }
907 for (k = 0; k < root_classifier->count; k++)
908 {
909 ccv_matrix_free(part_feature[k]);
910 ccv_matrix_free(dx[k]);
911 ccv_matrix_free(dy[k]);
912 }
913 ccv_matrix_free(root_feature);
914 scale_x *= scale;
915 scale_y *= scale;
916 }
917 }
918 for (i = 0; i < scale_upto + next * 2; i++)
919 ccv_matrix_free(pyr[i]);
920 return v;
921}
922
923static ccv_array_t* _ccv_dpm_collect_all(gsl_rng* rng, ccv_dense_matrix_t* image, ccv_dpm_mixture_model_t* model, ccv_dpm_param_t params, float threshold)
924{
925 int i, j, k, x, y;
926 double scale = pow(2.0, 1.0 / (params.interval + 1.0));
927 int next = params.interval + 1;
928 int scale_upto = _ccv_dpm_scale_upto(image, &model, 1, params.interval);
929 if (scale_upto < 0)
930 return 0;
931 ccv_dense_matrix_t** pyr = (ccv_dense_matrix_t**)alloca((scale_upto + next * 2) * sizeof(ccv_dense_matrix_t*))__builtin_alloca ((scale_upto + next * 2) * sizeof(ccv_dense_matrix_t
*))
;
932 _ccv_dpm_feature_pyramid(image, pyr, scale_upto, params.interval);
933 ccv_array_t* av = ccv_array_new(sizeof(ccv_dpm_feature_vector_t*), 64, 0);
934 int enough = 64 / model->count;
935 int* order = (int*)alloca(sizeof(int) * model->count)__builtin_alloca (sizeof(int) * model->count);
936 for (i = 0; i < model->count; i++)
937 order[i] = i;
938 gsl_ran_shuffle(rng, order, model->count, sizeof(int));
939 for (i = 0; i < model->count; i++)
940 {
941 ccv_dpm_root_classifier_t* root_classifier = model->root + order[i];
942 double scale_x = 1.0;
943 double scale_y = 1.0;
944 for (j = next; j < scale_upto + next * 2; j++)
945 {
946 ccv_dense_matrix_t* root_feature = 0;
947 ccv_dense_matrix_t* part_feature[CCV_DPM_PART_MAX(10)];
948 ccv_dense_matrix_t* dx[CCV_DPM_PART_MAX(10)];
949 ccv_dense_matrix_t* dy[CCV_DPM_PART_MAX(10)];
950 _ccv_dpm_compute_score(root_classifier, pyr[j], pyr[j - next], &root_feature, part_feature, dx, dy);
951 int rwh = (root_classifier->root.w->rows - 1) / 2, rww = (root_classifier->root.w->cols - 1) / 2;
952 int rwh_1 = root_classifier->root.w->rows / 2, rww_1 = root_classifier->root.w->cols / 2;
953 float* f_ptr = (float*)ccv_get_dense_matrix_cell_by(CCV_32F | CCV_C1, root_feature, rwh, 0, 0)(((CCV_32F | CCV_C1) & CCV_32S) ? (void*)((root_feature)->
data.i32 + ((rwh) * (root_feature)->cols + (0)) * ((CCV_32F
| CCV_C1) & 0xFFF) + (0)) : (((CCV_32F | CCV_C1) & CCV_32F
) ? (void*)((root_feature)->data.f32+ ((rwh) * (root_feature
)->cols + (0)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)) :
(((CCV_32F | CCV_C1) & CCV_64S) ? (void*)((root_feature)
->data.i64+ ((rwh) * (root_feature)->cols + (0)) * ((CCV_32F
| CCV_C1) & 0xFFF) + (0)) : (((CCV_32F | CCV_C1) & CCV_64F
) ? (void*)((root_feature)->data.f64 + ((rwh) * (root_feature
)->cols + (0)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)) :
(void*)((root_feature)->data.u8 + (rwh) * (root_feature)->
step + (0) * ((CCV_32F | CCV_C1) & 0xFFF) + (0))))))
;
954 for (y = rwh; y < root_feature->rows - rwh_1; y++)
955 {
956 for (x = rww; x < root_feature->cols - rww_1; x++)
957 if (f_ptr[x] + root_classifier->beta > threshold)
958 {
959 // initialize v
960 ccv_dpm_feature_vector_t* v = (ccv_dpm_feature_vector_t*)ccmallocmalloc(sizeof(ccv_dpm_feature_vector_t));
961 _ccv_dpm_initialize_feature_vector_on_pattern(v, root_classifier, order[i]);
962 _ccv_dpm_collect_feature_vector(v, f_ptr[x] + root_classifier->beta, x, y, pyr[j], pyr[j - next], dx, dy);
963 v->scale_x = scale_x;
964 v->scale_y = scale_y;
965 ccv_array_push(av, &v);
966 if (av->rnum >= enough * (i + 1))
967 break;
968 }
969 f_ptr += root_feature->cols;
970 if (av->rnum >= enough * (i + 1))
971 break;
972 }
973 for (k = 0; k < root_classifier->count; k++)
974 {
975 ccv_matrix_free(part_feature[k]);
976 ccv_matrix_free(dx[k]);
977 ccv_matrix_free(dy[k]);
978 }
979 ccv_matrix_free(root_feature);
980 scale_x *= scale;
981 scale_y *= scale;
982 if (av->rnum >= enough * (i + 1))
983 break;
984 }
985 }
986 for (i = 0; i < scale_upto + next * 2; i++)
987 ccv_matrix_free(pyr[i]);
988 return av;
989}
990
991static void _ccv_dpm_collect_from_background(ccv_array_t* av, gsl_rng* rng, char** bgfiles, int bgnum, ccv_dpm_mixture_model_t* model, ccv_dpm_new_param_t params, float threshold)
992{
993 int i, j;
994 int* order = (int*)ccmallocmalloc(sizeof(int) * bgnum);
995 for (i = 0; i < bgnum; i++)
996 order[i] = i;
997 gsl_ran_shuffle(rng, order, bgnum, sizeof(int));
998 for (i = 0; i < bgnum; i++)
999 {
1000 FLUSH(CCV_CLI_INFO, " - collecting negative examples -- (%d%%)", av->rnum * 100 / params.negative_cache_size)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - collecting negative examples -- (%d%%)"
, av->rnum * 100 / params.negative_cache_size); fflush(stdout
); } } while (0)
;
1001 ccv_dense_matrix_t* image = 0;
1002 ccv_read(bgfiles[order[i]], &image, (params.grayscale ? CCV_IO_GRAY : 0) | CCV_IO_ANY_FILE)ccv_read_impl(bgfiles[order[i]], &image, (params.grayscale
? CCV_IO_GRAY : 0) | CCV_IO_ANY_FILE, 0, 0, 0)
;
1003 ccv_array_t* at = _ccv_dpm_collect_all(rng, image, model, params.detector, threshold);
1004 if (at)
1005 {
1006 for (j = 0; j < at->rnum; j++)
1007 ccv_array_push(av, ccv_array_get(at, j)((void*)(((char*)((at)->data)) + (size_t)(at)->rsize * (
size_t)(j)))
);
1008 ccv_array_free(at);
1009 }
1010 ccv_matrix_free(image);
1011 if (av->rnum >= params.negative_cache_size)
1012 break;
1013 }
1014 ccfreefree(order);
1015}
1016
1017static void _ccv_dpm_initialize_root_rectangle_estimator(ccv_dpm_mixture_model_t* model, char** posfiles, ccv_rect_t* bboxes, int posnum, ccv_dpm_new_param_t params)
1018{
1019 int i, j, k, c;
1020 ccv_dpm_feature_vector_t** posv = (ccv_dpm_feature_vector_t**)ccmallocmalloc(sizeof(ccv_dpm_feature_vector_t*) * posnum);
1021 int* num_per_model = (int*)alloca(sizeof(int) * model->count)__builtin_alloca (sizeof(int) * model->count);
1022 memset(num_per_model, 0, sizeof(int) * model->count);
1023 FLUSH(CCV_CLI_INFO, " - collecting responses from positive examples : 0%%")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - collecting responses from positive examples : 0%%"
); fflush(stdout); } } while (0)
;
1024 for (i = 0; i < posnum; i++)
1025 {
1026 FLUSH(CCV_CLI_INFO, " - collecting responses from positive examples : %d%%", i * 100 / posnum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - collecting responses from positive examples : %d%%"
, i * 100 / posnum); fflush(stdout); } } while (0)
;
1027 ccv_dense_matrix_t* image = 0;
1028 ccv_read(posfiles[i], &image, (params.grayscale ? CCV_IO_GRAY : 0) | CCV_IO_ANY_FILE)ccv_read_impl(posfiles[i], &image, (params.grayscale ? CCV_IO_GRAY
: 0) | CCV_IO_ANY_FILE, 0, 0, 0)
;
1029 posv[i] = _ccv_dpm_collect_best(image, model, bboxes[i], params.include_overlap, params.detector);
1030 if (posv[i])
1031 ++num_per_model[posv[i]->id];
1032 ccv_matrix_free(image);
1033 }
1034 // this will estimate new x, y, and scale
1035 PRINT(CCV_CLI_INFO, "\n - linear regression for x, y, and scale drifting\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n - linear regression for x, y, and scale drifting\n"); fflush
(stdout); } } while (0)
;
1036 for (i = 0; i < model->count; i++)
1037 {
1038 ccv_dpm_root_classifier_t* root_classifier = model->root + i;
1039 gsl_matrix* X = gsl_matrix_alloc(num_per_model[i], root_classifier->count * 2 + 1);
1040 gsl_vector* y[3];
1041 y[0] = gsl_vector_alloc(num_per_model[i]);
1042 y[1] = gsl_vector_alloc(num_per_model[i]);
1043 y[2] = gsl_vector_alloc(num_per_model[i]);
1044 gsl_vector* z = gsl_vector_alloc(root_classifier->count * 2 + 1);
1045 gsl_matrix* cov = gsl_matrix_alloc(root_classifier->count * 2 + 1, root_classifier->count * 2 + 1);;
1046 c = 0;
1047 for (j = 0; j < posnum; j++)
1048 {
1049 ccv_dpm_feature_vector_t* v = posv[j];
1050 if (v && v->id == i)
1051 {
1052 gsl_matrix_set(X, c, 0, 1.0);
1053 for (k = 0; k < v->count; k++)
1054 {
1055 gsl_matrix_set(X, c, k * 2 + 1, v->part[k].dx);
1056 gsl_matrix_set(X, c, k * 2 + 2, v->part[k].dy);
1057 }
1058 ccv_rect_t bbox = bboxes[j];
1059 gsl_vector_set(y[0], c, (bbox.x + bbox.width * 0.5) / (v->scale_x * CCV_DPM_WINDOW_SIZE(8)) - v->x);
1060 gsl_vector_set(y[1], c, (bbox.y + bbox.height * 0.5) / (v->scale_y * CCV_DPM_WINDOW_SIZE(8)) - v->y);
1061 gsl_vector_set(y[2], c, sqrt((bbox.width * bbox.height) / (root_classifier->root.w->rows * v->scale_x * CCV_DPM_WINDOW_SIZE(8) * root_classifier->root.w->cols * v->scale_y * CCV_DPM_WINDOW_SIZE(8))) - 1.0);
1062 ++c;
1063 }
1064 }
1065 gsl_multifit_linear_workspace* workspace = gsl_multifit_linear_alloc(num_per_model[i], root_classifier->count * 2 + 1);
1066 double chisq;
1067 for (j = 0; j < 3; j++)
1068 {
1069 gsl_multifit_linear(X, y[j], z, cov, &chisq, workspace);
1070 root_classifier->alpha[j] = params.discard_estimating_constant ? 0 : gsl_vector_get(z, 0);
1071 for (k = 0; k < root_classifier->count; k++)
1072 {
1073 ccv_dpm_part_classifier_t* part_classifier = root_classifier->part + k;
1074 part_classifier->alpha[j * 2] = gsl_vector_get(z, k * 2 + 1);
1075 part_classifier->alpha[j * 2 + 1] = gsl_vector_get(z, k * 2 + 2);
1076 }
1077 }
1078 gsl_multifit_linear_free(workspace);
1079 gsl_matrix_free(cov);
1080 gsl_vector_free(z);
1081 gsl_vector_free(y[0]);
1082 gsl_vector_free(y[1]);
1083 gsl_vector_free(y[2]);
1084 gsl_matrix_free(X);
1085 }
1086 for (i = 0; i < posnum; i++)
1087 if (posv[i])
1088 _ccv_dpm_feature_vector_free(posv[i]);
1089 ccfreefree(posv);
1090}
1091
1092static void _ccv_dpm_regularize_mixture_model(ccv_dpm_mixture_model_t* model, int i, double regz)
1093{
1094 int k;
1095 ccv_dpm_root_classifier_t* root_classifier = model->root + i;
1096 int ch = CCV_GET_CHANNEL(root_classifier->root.w->type)((root_classifier->root.w->type) & 0xFFF);
1097 ccv_make_matrix_mutable(root_classifier->root.w);
1098 float *wptr = root_classifier->root.w->data.f32;
1099 for (i = 0; i < root_classifier->root.w->rows * root_classifier->root.w->cols * ch; i++)
1100 wptr[i] -= regz * wptr[i];
1101 ccv_make_matrix_immutable(root_classifier->root.w);
1102 root_classifier->beta -= regz * root_classifier->beta;
1103 for (k = 0; k < root_classifier->count; k++)
1104 {
1105 ccv_dpm_part_classifier_t* part_classifier = root_classifier->part + k;
1106 ccv_make_matrix_mutable(part_classifier->w);
1107 wptr = part_classifier->w->data.f32;
1108 for (i = 0; i < part_classifier->w->rows * part_classifier->w->cols * ch; i++)
1109 wptr[i] -= regz * wptr[i];
1110 ccv_make_matrix_immutable(part_classifier->w);
1111 part_classifier->dx -= regz * part_classifier->dx;
1112 part_classifier->dxx -= regz * part_classifier->dxx;
1113 part_classifier->dy -= regz * part_classifier->dy;
1114 part_classifier->dyy -= regz * part_classifier->dyy;
1115 part_classifier->dxx = ccv_max(0.01, part_classifier->dxx)({ typeof (0.01) _a = (0.01); typeof (part_classifier->dxx
) _b = (part_classifier->dxx); (_a > _b) ? _a : _b; })
;
1116 part_classifier->dyy = ccv_max(0.01, part_classifier->dyy)({ typeof (0.01) _a = (0.01); typeof (part_classifier->dyy
) _b = (part_classifier->dyy); (_a > _b) ? _a : _b; })
;
1117 }
1118}
1119
1120static void _ccv_dpm_stochastic_gradient_descent(ccv_dpm_mixture_model_t* model, ccv_dpm_feature_vector_t* v, double y, double alpha, double Cn, int symmetric)
1121{
1122 if (v->id < 0 || v->id >= model->count)
1123 return;
1124 ccv_dpm_root_classifier_t* root_classifier = model->root + v->id;
1125 int i, j, k, c, ch = CCV_GET_CHANNEL(v->root.w->type)((v->root.w->type) & 0xFFF);
1126 assert(ch == 31)((void) sizeof ((ch == 31) ? 1 : 0), __extension__ ({ if (ch ==
31) ; else __assert_fail ("ch == 31", "ccv_dpm.c", 1126, __extension__
__PRETTY_FUNCTION__); }))
;
1127 assert(v->root.w->rows == root_classifier->root.w->rows && v->root.w->cols == root_classifier->root.w->cols)((void) sizeof ((v->root.w->rows == root_classifier->
root.w->rows && v->root.w->cols == root_classifier
->root.w->cols) ? 1 : 0), __extension__ ({ if (v->root
.w->rows == root_classifier->root.w->rows &&
v->root.w->cols == root_classifier->root.w->cols
) ; else __assert_fail ("v->root.w->rows == root_classifier->root.w->rows && v->root.w->cols == root_classifier->root.w->cols"
, "ccv_dpm.c", 1127, __extension__ __PRETTY_FUNCTION__); }))
;
1128 float *vptr = v->root.w->data.f32;
1129 ccv_make_matrix_mutable(root_classifier->root.w);
1130 float *wptr = root_classifier->root.w->data.f32;
1131 if (symmetric)
1132 {
1133 for (i = 0; i < v->root.w->rows; i++)
1134 {
1135 for (j = 0; j < v->root.w->cols; j++)
1136 for (c = 0; c < ch; c++)
1137 {
1138 wptr[j * ch + c] += alpha * y * Cn * vptr[j * ch + c];
1139 wptr[j * ch + c] += alpha * y * Cn * vptr[(v->root.w->cols - 1 - j) * ch + _ccv_dpm_sym_lut[c]];
1140 }
1141 vptr += v->root.w->cols * ch;
1142 wptr += root_classifier->root.w->cols * ch;
1143 }
1144 root_classifier->beta += alpha * y * Cn * 2.0;
1145 } else {
1146 for (i = 0; i < v->root.w->rows * v->root.w->cols * ch; i++)
1147 wptr[i] += alpha * y * Cn * vptr[i];
1148 root_classifier->beta += alpha * y * Cn;
1149 }
1150 ccv_make_matrix_immutable(root_classifier->root.w);
1151 assert(v->count == root_classifier->count)((void) sizeof ((v->count == root_classifier->count) ? 1
: 0), __extension__ ({ if (v->count == root_classifier->
count) ; else __assert_fail ("v->count == root_classifier->count"
, "ccv_dpm.c", 1151, __extension__ __PRETTY_FUNCTION__); }))
;
1152 for (k = 0; k < v->count; k++)
1153 {
1154 ccv_dpm_part_classifier_t* part_classifier = root_classifier->part + k;
1155 ccv_make_matrix_mutable(part_classifier->w);
1156 ccv_dpm_part_classifier_t* part_vector = v->part + k;
1157 assert(part_vector->w->rows == part_classifier->w->rows && part_vector->w->cols == part_classifier->w->cols)((void) sizeof ((part_vector->w->rows == part_classifier
->w->rows && part_vector->w->cols == part_classifier
->w->cols) ? 1 : 0), __extension__ ({ if (part_vector->
w->rows == part_classifier->w->rows && part_vector
->w->cols == part_classifier->w->cols) ; else __assert_fail
("part_vector->w->rows == part_classifier->w->rows && part_vector->w->cols == part_classifier->w->cols"
, "ccv_dpm.c", 1157, __extension__ __PRETTY_FUNCTION__); }))
;
1158 part_classifier->dx -= alpha * y * Cn * part_vector->dx;
1159 part_classifier->dxx -= alpha * y * Cn * part_vector->dxx;
1160 part_classifier->dxx = ccv_max(part_classifier->dxx, 0.01)({ typeof (part_classifier->dxx) _a = (part_classifier->
dxx); typeof (0.01) _b = (0.01); (_a > _b) ? _a : _b; })
;
1161 part_classifier->dy -= alpha * y * Cn * part_vector->dy;
1162 part_classifier->dyy -= alpha * y * Cn * part_vector->dyy;
1163 part_classifier->dyy = ccv_max(part_classifier->dyy, 0.01)({ typeof (part_classifier->dyy) _a = (part_classifier->
dyy); typeof (0.01) _b = (0.01); (_a > _b) ? _a : _b; })
;
1164 vptr = part_vector->w->data.f32;
1165 wptr = part_classifier->w->data.f32;
1166 if (symmetric)
1167 {
1168 // 2x converge on everything for symmetric feature
1169 if (part_classifier->counterpart == -1)
1170 {
1171 part_classifier->dx += /* flip the sign on x-axis (symmetric) */ alpha * y * Cn * part_vector->dx;
1172 part_classifier->dxx -= alpha * y * Cn * part_vector->dxx;
1173 part_classifier->dxx = ccv_max(part_classifier->dxx, 0.01)({ typeof (part_classifier->dxx) _a = (part_classifier->
dxx); typeof (0.01) _b = (0.01); (_a > _b) ? _a : _b; })
;
1174 part_classifier->dy -= alpha * y * Cn * part_vector->dy;
1175 part_classifier->dyy -= alpha * y * Cn * part_vector->dyy;
1176 part_classifier->dyy = ccv_max(part_classifier->dyy, 0.01)({ typeof (part_classifier->dyy) _a = (part_classifier->
dyy); typeof (0.01) _b = (0.01); (_a > _b) ? _a : _b; })
;
1177 for (i = 0; i < part_vector->w->rows; i++)
1178 {
1179 for (j = 0; j < part_vector->w->cols; j++)
1180 for (c = 0; c < ch; c++)
1181 {
1182 wptr[j * ch + c] += alpha * y * Cn * vptr[j * ch + c];
1183 wptr[j * ch + c] += alpha * y * Cn * vptr[(part_vector->w->cols - 1 - j) * ch + _ccv_dpm_sym_lut[c]];
1184 }
1185 vptr += part_vector->w->cols * ch;
1186 wptr += part_classifier->w->cols * ch;
1187 }
1188 } else {
1189 ccv_dpm_part_classifier_t* other_part_classifier = root_classifier->part + part_classifier->counterpart;
1190 assert(part_vector->w->rows == other_part_classifier->w->rows && part_vector->w->cols == other_part_classifier->w->cols)((void) sizeof ((part_vector->w->rows == other_part_classifier
->w->rows && part_vector->w->cols == other_part_classifier
->w->cols) ? 1 : 0), __extension__ ({ if (part_vector->
w->rows == other_part_classifier->w->rows &&
part_vector->w->cols == other_part_classifier->w->
cols) ; else __assert_fail ("part_vector->w->rows == other_part_classifier->w->rows && part_vector->w->cols == other_part_classifier->w->cols"
, "ccv_dpm.c", 1190, __extension__ __PRETTY_FUNCTION__); }))
;
1191 other_part_classifier->dx += /* flip the sign on x-axis (symmetric) */ alpha * y * Cn * part_vector->dx;
1192 other_part_classifier->dxx -= alpha * y * Cn * part_vector->dxx;
1193 other_part_classifier->dxx = ccv_max(other_part_classifier->dxx, 0.01)({ typeof (other_part_classifier->dxx) _a = (other_part_classifier
->dxx); typeof (0.01) _b = (0.01); (_a > _b) ? _a : _b;
})
;
1194 other_part_classifier->dy -= alpha * y * Cn * part_vector->dy;
1195 other_part_classifier->dyy -= alpha * y * Cn * part_vector->dyy;
1196 other_part_classifier->dyy = ccv_max(other_part_classifier->dyy, 0.01)({ typeof (other_part_classifier->dyy) _a = (other_part_classifier
->dyy); typeof (0.01) _b = (0.01); (_a > _b) ? _a : _b;
})
;
1197 for (i = 0; i < part_vector->w->rows; i++)
1198 {
1199 for (j = 0; j < part_vector->w->cols * ch; j++)
1200 wptr[j] += alpha * y * Cn * vptr[j];
1201 vptr += part_vector->w->cols * ch;
1202 wptr += part_classifier->w->cols * ch;
1203 }
1204 vptr = part_vector->w->data.f32;
1205 wptr = other_part_classifier->w->data.f32;
1206 for (i = 0; i < part_vector->w->rows; i++)
1207 {
1208 for (j = 0; j < part_vector->w->cols; j++)
1209 for (c = 0; c < ch; c++)
1210 wptr[j * ch + c] += alpha * y * Cn * vptr[(part_vector->w->cols - 1 - j) * ch + _ccv_dpm_sym_lut[c]];
1211 vptr += part_vector->w->cols * ch;
1212 wptr += other_part_classifier->w->cols * ch;
1213 }
1214 }
1215 } else {
1216 for (i = 0; i < part_vector->w->rows * part_vector->w->cols * ch; i++)
1217 wptr[i] += alpha * y * Cn * vptr[i];
1218 }
1219 ccv_make_matrix_immutable(part_classifier->w);
1220 }
1221}
1222
1223static void _ccv_dpm_write_gradient_descent_progress(int i, int j, const char* dir)
1224{
1225 char swpfile[1024];
1226 sprintf(swpfile, "%s.swp", dir);
1227 FILE* w = fopen(swpfile, "w+");
1228 if (!w)
1229 return;
1230 fprintf(w, "%d %d\n", i, j);
1231 fclose(w);
1232 rename(swpfile, dir);
1233}
1234
1235static void _ccv_dpm_read_gradient_descent_progress(int* i, int* j, const char* dir)
1236{
1237 FILE* r = fopen(dir, "r");
1238 if (!r)
1239 return;
1240 fscanf(r, "%d %d", i, j);
1241 fclose(r);
1242}
1243
1244static void _ccv_dpm_write_feature_vector(FILE* w, ccv_dpm_feature_vector_t* v)
1245{
1246 int j, x, y, ch;
1247 if (v)
1248 {
1249 fprintf(w, "%d %d %d\n", v->id, v->root.w->rows, v->root.w->cols);
1250 ch = CCV_GET_CHANNEL(v->root.w->type)((v->root.w->type) & 0xFFF);
1251 for (y = 0; y < v->root.w->rows; y++)
1252 {
1253 for (x = 0; x < v->root.w->cols * ch; x++)
1254 fprintf(w, "%a ", v->root.w->data.f32[y * v->root.w->cols * ch + x]);
1255 fprintf(w, "\n");
1256 }
1257 fprintf(w, "%d %a\n", v->count, v->score);
1258 for (j = 0; j < v->count; j++)
1259 {
1260 ccv_dpm_part_classifier_t* part_classifier = v->part + j;
1261 fprintf(w, "%la %la %la %la\n", part_classifier->dx, part_classifier->dy, part_classifier->dxx, part_classifier->dyy);
1262 fprintf(w, "%d %d %d\n", part_classifier->x, part_classifier->y, part_classifier->z);
1263 fprintf(w, "%d %d\n", part_classifier->w->rows, part_classifier->w->cols);
1264 ch = CCV_GET_CHANNEL(part_classifier->w->type)((part_classifier->w->type) & 0xFFF);
1265 for (y = 0; y < part_classifier->w->rows; y++)
1266 {
1267 for (x = 0; x < part_classifier->w->cols * ch; x++)
1268 fprintf(w, "%a ", part_classifier->w->data.f32[y * part_classifier->w->cols * ch + x]);
1269 fprintf(w, "\n");
1270 }
1271 }
1272 } else {
1273 fprintf(w, "0 0 0\n");
1274 }
1275}
1276
1277static ccv_dpm_feature_vector_t* _ccv_dpm_read_feature_vector(FILE* r)
1278{
1279 int id, rows, cols, j, k;
1280 fscanf(r, "%d %d %d", &id, &rows, &cols);
1281 if (rows == 0 && cols == 0)
1282 return 0;
1283 ccv_dpm_feature_vector_t* v = (ccv_dpm_feature_vector_t*)ccmallocmalloc(sizeof(ccv_dpm_feature_vector_t));
1284 v->id = id;
1285 v->root.w = ccv_dense_matrix_new(rows, cols, CCV_32F | 31, 0, 0);
1286 for (j = 0; j < rows * cols * 31; j++)
1287 fscanf(r, "%f", &v->root.w->data.f32[j]);
1288 fscanf(r, "%d %f", &v->count, &v->score);
1289 v->part = (ccv_dpm_part_classifier_t*)ccmallocmalloc(sizeof(ccv_dpm_part_classifier_t) * v->count);
1290 for (j = 0; j < v->count; j++)
1291 {
1292 ccv_dpm_part_classifier_t* part_classifier = v->part + j;
1293 fscanf(r, "%lf %lf %lf %lf", &part_classifier->dx, &part_classifier->dy, &part_classifier->dxx, &part_classifier->dyy);
1294 fscanf(r, "%d %d %d", &part_classifier->x, &part_classifier->y, &part_classifier->z);
1295 fscanf(r, "%d %d", &rows, &cols);
1296 part_classifier->w = ccv_dense_matrix_new(rows, cols, CCV_32F | 31, 0, 0);
1297 for (k = 0; k < rows * cols * 31; k++)
1298 fscanf(r, "%f", &part_classifier->w->data.f32[k]);
1299 }
1300 return v;
1301}
1302
1303static void _ccv_dpm_write_positive_feature_vectors(ccv_dpm_feature_vector_t** vs, int n, const char* dir)
1304{
1305 FILE* w = fopen(dir, "w+");
1306 if (!w)
1307 return;
1308 fprintf(w, "%d\n", n);
1309 int i;
1310 for (i = 0; i < n; i++)
1311 _ccv_dpm_write_feature_vector(w, vs[i]);
1312 fclose(w);
1313}
1314
1315static int _ccv_dpm_read_positive_feature_vectors(ccv_dpm_feature_vector_t** vs, int _n, const char* dir)
1316{
1317 FILE* r = fopen(dir, "r");
1318 if (!r)
1319 return -1;
1320 int n;
1321 fscanf(r, "%d", &n);
1322 assert(n == _n)((void) sizeof ((n == _n) ? 1 : 0), __extension__ ({ if (n ==
_n) ; else __assert_fail ("n == _n", "ccv_dpm.c", 1322, __extension__
__PRETTY_FUNCTION__); }))
;
1323 int i;
1324 for (i = 0; i < n; i++)
1325 vs[i] = _ccv_dpm_read_feature_vector(r);
1326 fclose(r);
1327 return 0;
1328}
1329
1330static void _ccv_dpm_write_negative_feature_vectors(ccv_array_t* negv, int negative_cache_size, const char* dir)
1331{
1332 FILE* w = fopen(dir, "w+");
1333 if (!w)
1334 return;
1335 fprintf(w, "%d %d\n", negative_cache_size, negv->rnum);
1336 int i;
1337 for (i = 0; i < negv->rnum; i++)
1338 {
1339 ccv_dpm_feature_vector_t* v = *(ccv_dpm_feature_vector_t**)ccv_array_get(negv, i)((void*)(((char*)((negv)->data)) + (size_t)(negv)->rsize
* (size_t)(i)))
;
1340 _ccv_dpm_write_feature_vector(w, v);
1341 }
1342 fclose(w);
1343}
1344
1345static int _ccv_dpm_read_negative_feature_vectors(ccv_array_t** _negv, int _negative_cache_size, const char* dir)
1346{
1347 FILE* r = fopen(dir, "r");
1348 if (!r)
1349 return -1;
1350 int negative_cache_size, negnum;
1351 fscanf(r, "%d %d", &negative_cache_size, &negnum);
1352 assert(negative_cache_size == _negative_cache_size)((void) sizeof ((negative_cache_size == _negative_cache_size)
? 1 : 0), __extension__ ({ if (negative_cache_size == _negative_cache_size
) ; else __assert_fail ("negative_cache_size == _negative_cache_size"
, "ccv_dpm.c", 1352, __extension__ __PRETTY_FUNCTION__); }))
;
1353 ccv_array_t* negv = *_negv = ccv_array_new(sizeof(ccv_dpm_feature_vector_t*), negnum, 0);
1354 int i;
1355 for (i = 0; i < negnum; i++)
1356 {
1357 ccv_dpm_feature_vector_t* v = _ccv_dpm_read_feature_vector(r);
1358 assert(v)((void) sizeof ((v) ? 1 : 0), __extension__ ({ if (v) ; else __assert_fail
("v", "ccv_dpm.c", 1358, __extension__ __PRETTY_FUNCTION__);
}))
;
1359 ccv_array_push(negv, &v);
1360 }
1361 fclose(r);
1362 return 0;
1363}
1364
1365static void _ccv_dpm_adjust_model_constant(ccv_dpm_mixture_model_t* model, int k, ccv_dpm_feature_vector_t** posv, int posnum, double percentile)
1366{
1367 int i, j;
1368 double* scores = (double*)ccmallocmalloc(posnum * sizeof(double));
1369 j = 0;
1370 for (i = 0; i < posnum; i++)
1371 if (posv[i] && posv[i]->id == k)
1372 {
1373 scores[j] = _ccv_dpm_vector_score(model, posv[i]);
1374 j++;
1375 }
1376 _ccv_dpm_score_qsort(scores, j, 0);
1377 float adjust = scores[ccv_clamp((int)(percentile * j), 0, j - 1)({ typeof (0) _a = (0); typeof (j - 1) _b = (j - 1); typeof (
(int)(percentile * j)) _x = ((int)(percentile * j)); (_x <
_a) ? _a : ((_x > _b) ? _b : _x); })
];
1378 // adjust to percentile
1379 model->root[k].beta -= adjust;
1380 PRINT(CCV_CLI_INFO, " - tune model %d constant for %f\n", k + 1, -adjust)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - tune model %d constant for %f\n", k + 1, -adjust); fflush
(stdout); } } while (0)
;
1381 ccfreefree(scores);
1382}
1383
1384static void _ccv_dpm_check_params(ccv_dpm_new_param_t params)
1385{
1386 assert(params.components > 0)((void) sizeof ((params.components > 0) ? 1 : 0), __extension__
({ if (params.components > 0) ; else __assert_fail ("params.components > 0"
, "ccv_dpm.c", 1386, __extension__ __PRETTY_FUNCTION__); }))
;
1387 assert(params.parts > 0)((void) sizeof ((params.parts > 0) ? 1 : 0), __extension__
({ if (params.parts > 0) ; else __assert_fail ("params.parts > 0"
, "ccv_dpm.c", 1387, __extension__ __PRETTY_FUNCTION__); }))
;
1388 assert(params.grayscale == 0 || params.grayscale == 1)((void) sizeof ((params.grayscale == 0 || params.grayscale ==
1) ? 1 : 0), __extension__ ({ if (params.grayscale == 0 || params
.grayscale == 1) ; else __assert_fail ("params.grayscale == 0 || params.grayscale == 1"
, "ccv_dpm.c", 1388, __extension__ __PRETTY_FUNCTION__); }))
;
1389 assert(params.symmetric == 0 || params.symmetric == 1)((void) sizeof ((params.symmetric == 0 || params.symmetric ==
1) ? 1 : 0), __extension__ ({ if (params.symmetric == 0 || params
.symmetric == 1) ; else __assert_fail ("params.symmetric == 0 || params.symmetric == 1"
, "ccv_dpm.c", 1389, __extension__ __PRETTY_FUNCTION__); }))
;
1390 assert(params.min_area > 100)((void) sizeof ((params.min_area > 100) ? 1 : 0), __extension__
({ if (params.min_area > 100) ; else __assert_fail ("params.min_area > 100"
, "ccv_dpm.c", 1390, __extension__ __PRETTY_FUNCTION__); }))
;
1391 assert(params.max_area > params.min_area)((void) sizeof ((params.max_area > params.min_area) ? 1 : 0
), __extension__ ({ if (params.max_area > params.min_area)
; else __assert_fail ("params.max_area > params.min_area"
, "ccv_dpm.c", 1391, __extension__ __PRETTY_FUNCTION__); }))
;
1392 assert(params.iterations >= 0)((void) sizeof ((params.iterations >= 0) ? 1 : 0), __extension__
({ if (params.iterations >= 0) ; else __assert_fail ("params.iterations >= 0"
, "ccv_dpm.c", 1392, __extension__ __PRETTY_FUNCTION__); }))
;
1393 assert(params.data_minings >= 0)((void) sizeof ((params.data_minings >= 0) ? 1 : 0), __extension__
({ if (params.data_minings >= 0) ; else __assert_fail ("params.data_minings >= 0"
, "ccv_dpm.c", 1393, __extension__ __PRETTY_FUNCTION__); }))
;
1394 assert(params.relabels >= 0)((void) sizeof ((params.relabels >= 0) ? 1 : 0), __extension__
({ if (params.relabels >= 0) ; else __assert_fail ("params.relabels >= 0"
, "ccv_dpm.c", 1394, __extension__ __PRETTY_FUNCTION__); }))
;
1395 assert(params.negative_cache_size > 0)((void) sizeof ((params.negative_cache_size > 0) ? 1 : 0),
__extension__ ({ if (params.negative_cache_size > 0) ; else
__assert_fail ("params.negative_cache_size > 0", "ccv_dpm.c"
, 1395, __extension__ __PRETTY_FUNCTION__); }))
;
1396 assert(params.include_overlap > 0.1)((void) sizeof ((params.include_overlap > 0.1) ? 1 : 0), __extension__
({ if (params.include_overlap > 0.1) ; else __assert_fail
("params.include_overlap > 0.1", "ccv_dpm.c", 1396, __extension__
__PRETTY_FUNCTION__); }))
;
1397 assert(params.alpha > 0 && params.alpha < 1)((void) sizeof ((params.alpha > 0 && params.alpha <
1) ? 1 : 0), __extension__ ({ if (params.alpha > 0 &&
params.alpha < 1) ; else __assert_fail ("params.alpha > 0 && params.alpha < 1"
, "ccv_dpm.c", 1397, __extension__ __PRETTY_FUNCTION__); }))
;
1398 assert(params.alpha_ratio > 0 && params.alpha_ratio < 1)((void) sizeof ((params.alpha_ratio > 0 && params.
alpha_ratio < 1) ? 1 : 0), __extension__ ({ if (params.alpha_ratio
> 0 && params.alpha_ratio < 1) ; else __assert_fail
("params.alpha_ratio > 0 && params.alpha_ratio < 1"
, "ccv_dpm.c", 1398, __extension__ __PRETTY_FUNCTION__); }))
;
1399 assert(params.C > 0)((void) sizeof ((params.C > 0) ? 1 : 0), __extension__ ({ if
(params.C > 0) ; else __assert_fail ("params.C > 0", "ccv_dpm.c"
, 1399, __extension__ __PRETTY_FUNCTION__); }))
;
1400 assert(params.balance > 0)((void) sizeof ((params.balance > 0) ? 1 : 0), __extension__
({ if (params.balance > 0) ; else __assert_fail ("params.balance > 0"
, "ccv_dpm.c", 1400, __extension__ __PRETTY_FUNCTION__); }))
;
1401 assert(params.percentile_breakdown > 0 && params.percentile_breakdown <= 1)((void) sizeof ((params.percentile_breakdown > 0 &&
params.percentile_breakdown <= 1) ? 1 : 0), __extension__
({ if (params.percentile_breakdown > 0 && params.
percentile_breakdown <= 1) ; else __assert_fail ("params.percentile_breakdown > 0 && params.percentile_breakdown <= 1"
, "ccv_dpm.c", 1401, __extension__ __PRETTY_FUNCTION__); }))
;
1402 assert(params.detector.interval > 0)((void) sizeof ((params.detector.interval > 0) ? 1 : 0), __extension__
({ if (params.detector.interval > 0) ; else __assert_fail
("params.detector.interval > 0", "ccv_dpm.c", 1402, __extension__
__PRETTY_FUNCTION__); }))
;
1403}
1404
1405#define MINI_BATCH(10) (10)
1406#define REGQ(100) (100)
1407
1408static ccv_dpm_mixture_model_t* _ccv_dpm_optimize_root_mixture_model(gsl_rng* rng, ccv_dpm_mixture_model_t* model, ccv_array_t** posex, ccv_array_t** negex, int relabels, double balance, double C, double previous_alpha, double alpha_ratio, int iterations, int symmetric)
1409{
1410 int i, j, k, t, c;
1411 for (i = 0; i < model->count - 1; i++)
1412 assert(posex[i]->rnum == posex[i + 1]->rnum && negex[i]->rnum == negex[i + 1]->rnum)((void) sizeof ((posex[i]->rnum == posex[i + 1]->rnum &&
negex[i]->rnum == negex[i + 1]->rnum) ? 1 : 0), __extension__
({ if (posex[i]->rnum == posex[i + 1]->rnum &&
negex[i]->rnum == negex[i + 1]->rnum) ; else __assert_fail
("posex[i]->rnum == posex[i + 1]->rnum && negex[i]->rnum == negex[i + 1]->rnum"
, "ccv_dpm.c", 1412, __extension__ __PRETTY_FUNCTION__); }))
;
1413 int posnum = posex[0]->rnum;
1414 int negnum = negex[0]->rnum;
1415 int* label = (int*)ccmallocmalloc(sizeof(int) * (posnum + negnum));
1416 int* order = (int*)ccmallocmalloc(sizeof(int) * (posnum + negnum));
1417 double previous_positive_loss = 0, previous_negative_loss = 0, positive_loss = 0, negative_loss = 0, loss = 0;
1418 double regz_rate = C;
1419 for (c = 0; c < relabels; c++)
1420 {
1421 int* pos_prog = (int*)alloca(sizeof(int) * model->count)__builtin_alloca (sizeof(int) * model->count);
1422 memset(pos_prog, 0, sizeof(int) * model->count);
1423 for (i = 0; i < posnum; i++)
1424 {
1425 int best = -1;
1426 double best_score = -DBL_MAX1.7976931348623157e+308;
1427 for (k = 0; k < model->count; k++)
1428 {
1429 ccv_dpm_feature_vector_t* v = (ccv_dpm_feature_vector_t*)ccv_array_get(posex[k], i)((void*)(((char*)((posex[k])->data)) + (size_t)(posex[k])->
rsize * (size_t)(i)))
;
1430 if (v->root.w == 0)
1431 continue;
1432 double score = _ccv_dpm_vector_score(model, v); // the loss for mini-batch method (computed on model)
1433 if (score > best_score)
1434 {
1435 best = k;
1436 best_score = score;
1437 }
1438 }
1439 label[i] = best;
1440 if (best >= 0)
1441 ++pos_prog[best];
1442 }
1443 PRINT(CCV_CLI_INFO, " - positive examples divided by components for root model optimizing : %d", pos_prog[0])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - positive examples divided by components for root model optimizing : %d"
, pos_prog[0]); fflush(stdout); } } while (0)
;
1444 for (i = 1; i < model->count; i++)
1445 PRINT(CCV_CLI_INFO, ", %d", pos_prog[i])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(", %d", pos_prog[i]); fflush(stdout); } } while (0)
;
1446 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
1447 int* neg_prog = (int*)alloca(sizeof(int) * model->count)__builtin_alloca (sizeof(int) * model->count);
1448 memset(neg_prog, 0, sizeof(int) * model->count);
1449 for (i = 0; i < negnum; i++)
1450 {
1451 int best = gsl_rng_uniform_int(rng, model->count);
1452 label[i + posnum] = best;
1453 ++neg_prog[best];
1454 }
1455 PRINT(CCV_CLI_INFO, " - negative examples divided by components for root model optimizing : %d", neg_prog[0])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - negative examples divided by components for root model optimizing : %d"
, neg_prog[0]); fflush(stdout); } } while (0)
;
1456 for (i = 1; i < model->count; i++)
1457 PRINT(CCV_CLI_INFO, ", %d", neg_prog[i])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(", %d", neg_prog[i]); fflush(stdout); } } while (0)
;
1458 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
1459 ccv_dpm_mixture_model_t* _model;
1460 double alpha = previous_alpha;
1461 previous_positive_loss = previous_negative_loss = 0;
1462 for (t = 0; t < iterations; t++)
1463 {
1464 for (i = 0; i < posnum + negnum; i++)
1465 order[i] = i;
1466 gsl_ran_shuffle(rng, order, posnum + negnum, sizeof(int));
1467 for (j = 0; j < model->count; j++)
1468 {
1469 double pos_weight = sqrt((double)neg_prog[j] / pos_prog[j] * balance); // positive weight
1470 double neg_weight = sqrt((double)pos_prog[j] / neg_prog[j] / balance); // negative weight
1471 _model = _ccv_dpm_model_copy(model);
1472 int l = 0;
1473 for (i = 0; i < posnum + negnum; i++)
1474 {
1475 k = order[i];
1476 if (label[k] == j)
1477 {
1478 assert(label[k] < model->count)((void) sizeof ((label[k] < model->count) ? 1 : 0), __extension__
({ if (label[k] < model->count) ; else __assert_fail (
"label[k] < model->count", "ccv_dpm.c", 1478, __extension__
__PRETTY_FUNCTION__); }))
;
1479 if (k < posnum)
1480 {
1481 ccv_dpm_feature_vector_t* v = (ccv_dpm_feature_vector_t*)ccv_array_get(posex[label[k]], k)((void*)(((char*)((posex[label[k]])->data)) + (size_t)(posex
[label[k]])->rsize * (size_t)(k)))
;
1482 assert(v->root.w)((void) sizeof ((v->root.w) ? 1 : 0), __extension__ ({ if (
v->root.w) ; else __assert_fail ("v->root.w", "ccv_dpm.c"
, 1482, __extension__ __PRETTY_FUNCTION__); }))
;
1483 double score = _ccv_dpm_vector_score(model, v); // the loss for mini-batch method (computed on model)
1484 assert(!isnan(score))((void) sizeof ((!__builtin_isnan (score)) ? 1 : 0), __extension__
({ if (!__builtin_isnan (score)) ; else __assert_fail ("!isnan(score)"
, "ccv_dpm.c", 1484, __extension__ __PRETTY_FUNCTION__); }))
;
1485 assert(v->id == j)((void) sizeof ((v->id == j) ? 1 : 0), __extension__ ({ if
(v->id == j) ; else __assert_fail ("v->id == j", "ccv_dpm.c"
, 1485, __extension__ __PRETTY_FUNCTION__); }))
;
1486 if (score <= 1)
1487 _ccv_dpm_stochastic_gradient_descent(_model, v, 1, alpha * pos_weight, regz_rate, symmetric);
1488 } else {
1489 ccv_dpm_feature_vector_t* v = (ccv_dpm_feature_vector_t*)ccv_array_get(negex[label[k]], k - posnum)((void*)(((char*)((negex[label[k]])->data)) + (size_t)(negex
[label[k]])->rsize * (size_t)(k - posnum)))
;
1490 double score = _ccv_dpm_vector_score(model, v);
1491 assert(!isnan(score))((void) sizeof ((!__builtin_isnan (score)) ? 1 : 0), __extension__
({ if (!__builtin_isnan (score)) ; else __assert_fail ("!isnan(score)"
, "ccv_dpm.c", 1491, __extension__ __PRETTY_FUNCTION__); }))
;
1492 assert(v->id == j)((void) sizeof ((v->id == j) ? 1 : 0), __extension__ ({ if
(v->id == j) ; else __assert_fail ("v->id == j", "ccv_dpm.c"
, 1492, __extension__ __PRETTY_FUNCTION__); }))
;
1493 if (score >= -1)
1494 _ccv_dpm_stochastic_gradient_descent(_model, v, -1, alpha * neg_weight, regz_rate, symmetric);
1495 }
1496 ++l;
1497 if (l % REGQ(100) == REGQ(100) - 1)
1498 _ccv_dpm_regularize_mixture_model(_model, j, 1.0 - pow(1.0 - alpha / (double)((pos_prog[j] + neg_prog[j]) * (!!symmetric + 1)), REGQ(100)));
1499 if (l % MINI_BATCH(10) == MINI_BATCH(10) - 1)
1500 {
1501 // mimicking mini-batch way of doing things
1502 _ccv_dpm_mixture_model_cleanup(model);
1503 ccfreefree(model);
1504 model = _model;
1505 _model = _ccv_dpm_model_copy(model);
1506 }
1507 }
1508 }
1509 _ccv_dpm_regularize_mixture_model(_model, j, 1.0 - pow(1.0 - alpha / (double)((pos_prog[j] + neg_prog[j]) * (!!symmetric + 1)), (((pos_prog[j] + neg_prog[j]) % REGQ(100)) + 1) % (REGQ(100) + 1)));
1510 _ccv_dpm_mixture_model_cleanup(model);
1511 ccfreefree(model);
1512 model = _model;
1513 }
1514 // compute the loss
1515 positive_loss = negative_loss = loss = 0;
1516 int posvn = 0;
1517 for (i = 0; i < posnum; i++)
1518 {
1519 if (label[i] < 0)
1520 continue;
1521 assert(label[i] < model->count)((void) sizeof ((label[i] < model->count) ? 1 : 0), __extension__
({ if (label[i] < model->count) ; else __assert_fail (
"label[i] < model->count", "ccv_dpm.c", 1521, __extension__
__PRETTY_FUNCTION__); }))
;
1522 ccv_dpm_feature_vector_t* v = (ccv_dpm_feature_vector_t*)ccv_array_get(posex[label[i]], i)((void*)(((char*)((posex[label[i]])->data)) + (size_t)(posex
[label[i]])->rsize * (size_t)(i)))
;
1523 if (v->root.w)
1524 {
1525 double score = _ccv_dpm_vector_score(model, v);
1526 assert(!isnan(score))((void) sizeof ((!__builtin_isnan (score)) ? 1 : 0), __extension__
({ if (!__builtin_isnan (score)) ; else __assert_fail ("!isnan(score)"
, "ccv_dpm.c", 1526, __extension__ __PRETTY_FUNCTION__); }))
;
1527 double hinge_loss = ccv_max(0, 1.0 - score)({ typeof (0) _a = (0); typeof (1.0 - score) _b = (1.0 - score
); (_a > _b) ? _a : _b; })
;
1528 positive_loss += hinge_loss;
1529 double pos_weight = sqrt((double)neg_prog[v->id] / pos_prog[v->id] * balance); // positive weight
1530 loss += pos_weight * hinge_loss;
1531 ++posvn;
1532 }
1533 }
1534 for (i = 0; i < negnum; i++)
1535 {
1536 if (label[i + posnum] < 0)
1537 continue;
1538 assert(label[i + posnum] < model->count)((void) sizeof ((label[i + posnum] < model->count) ? 1 :
0), __extension__ ({ if (label[i + posnum] < model->count
) ; else __assert_fail ("label[i + posnum] < model->count"
, "ccv_dpm.c", 1538, __extension__ __PRETTY_FUNCTION__); }))
;
1539 ccv_dpm_feature_vector_t* v = (ccv_dpm_feature_vector_t*)ccv_array_get(negex[label[i + posnum]], i)((void*)(((char*)((negex[label[i + posnum]])->data)) + (size_t
)(negex[label[i + posnum]])->rsize * (size_t)(i)))
;
1540 double score = _ccv_dpm_vector_score(model, v);
1541 assert(!isnan(score))((void) sizeof ((!__builtin_isnan (score)) ? 1 : 0), __extension__
({ if (!__builtin_isnan (score)) ; else __assert_fail ("!isnan(score)"
, "ccv_dpm.c", 1541, __extension__ __PRETTY_FUNCTION__); }))
;
1542 double hinge_loss = ccv_max(0, 1.0 + score)({ typeof (0) _a = (0); typeof (1.0 + score) _b = (1.0 + score
); (_a > _b) ? _a : _b; })
;
1543 negative_loss += hinge_loss;
1544 double neg_weight = sqrt((double)pos_prog[v->id] / neg_prog[v->id] / balance); // negative weight
1545 loss += neg_weight * hinge_loss;
1546 }
1547 loss = loss / (posvn + negnum);
1548 positive_loss = positive_loss / posvn;
1549 negative_loss = negative_loss / negnum;
1550 FLUSH(CCV_CLI_INFO, " - with loss %.5lf (positive %.5lf, negative %.5f) at rate %.5lf %d | %d -- %d%%", loss, positive_loss, negative_loss, alpha, posvn, negnum, (t + 1) * 100 / iterations)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - with loss %.5lf (positive %.5lf, negative %.5f) at rate %.5lf %d | %d -- %d%%"
, loss, positive_loss, negative_loss, alpha, posvn, negnum, (
t + 1) * 100 / iterations); fflush(stdout); } } while (0)
;
1551 // check symmetric property of generated root feature
1552 if (symmetric)
1553 for (i = 0; i < model->count; i++)
1554 {
1555 ccv_dpm_root_classifier_t* root_classifier = model->root + i;
1556 _ccv_dpm_check_root_classifier_symmetry(root_classifier->root.w);
1557 }
1558 if (fabs(previous_positive_loss - positive_loss) < 1e-5 &&
1559 fabs(previous_negative_loss - negative_loss) < 1e-5)
1560 {
1561 PRINT(CCV_CLI_INFO, "\n - aborting iteration at %d because we didn't gain much", t + 1)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n - aborting iteration at %d because we didn't gain much",
t + 1); fflush(stdout); } } while (0)
;
1562 break;
1563 }
1564 previous_positive_loss = positive_loss;
1565 previous_negative_loss = negative_loss;
1566 alpha *= alpha_ratio; // it will decrease with each iteration
1567 }
1568 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
1569 }
1570 ccfreefree(order);
1571 ccfreefree(label);
1572 return model;
1573}
1574
1575void ccv_dpm_mixture_model_new(char** posfiles, ccv_rect_t* bboxes, int posnum, char** bgfiles, int bgnum, int negnum, const char* dir, ccv_dpm_new_param_t params)
1576{
1577 int t, d, c, i, j, k, p;
1578 _ccv_dpm_check_params(params);
1579 assert(params.negative_cache_size <= negnum && params.negative_cache_size > REGQ && params.negative_cache_size > MINI_BATCH)((void) sizeof ((params.negative_cache_size <= negnum &&
params.negative_cache_size > (100) && params.negative_cache_size
> (10)) ? 1 : 0), __extension__ ({ if (params.negative_cache_size
<= negnum && params.negative_cache_size > (100
) && params.negative_cache_size > (10)) ; else __assert_fail
("params.negative_cache_size <= negnum && params.negative_cache_size > REGQ && params.negative_cache_size > MINI_BATCH"
, "ccv_dpm.c", 1579, __extension__ __PRETTY_FUNCTION__); }))
;
1580 PRINT(CCV_CLI_INFO, "with %d positive examples and %d negative examples\n"do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("with %d positive examples and %d negative examples\n" "negative examples are are going to be collected from %d background images\n"
, posnum, negnum, bgnum); fflush(stdout); } } while (0)
1581 "negative examples are are going to be collected from %d background images\n",do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("with %d positive examples and %d negative examples\n" "negative examples are are going to be collected from %d background images\n"
, posnum, negnum, bgnum); fflush(stdout); } } while (0)
1582 posnum, negnum, bgnum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("with %d positive examples and %d negative examples\n" "negative examples are are going to be collected from %d background images\n"
, posnum, negnum, bgnum); fflush(stdout); } } while (0)
;
1583 PRINT(CCV_CLI_INFO, "use symmetric property? %s\n", params.symmetric ? "yes" : "no")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("use symmetric property? %s\n", params.symmetric ? "yes" : "no"
); fflush(stdout); } } while (0)
;
1584 PRINT(CCV_CLI_INFO, "use color? %s\n", params.grayscale ? "no" : "yes")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("use color? %s\n", params.grayscale ? "no" : "yes"); fflush(
stdout); } } while (0)
;
1585 PRINT(CCV_CLI_INFO, "negative examples cache size : %d\n", params.negative_cache_size)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("negative examples cache size : %d\n", params.negative_cache_size
); fflush(stdout); } } while (0)
;
1586 PRINT(CCV_CLI_INFO, "%d components and %d parts\n", params.components, params.parts)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("%d components and %d parts\n", params.components, params.parts
); fflush(stdout); } } while (0)
;
1587 PRINT(CCV_CLI_INFO, "expected %d root relabels, %d relabels, %d data minings and %d iterations\n", params.root_relabels, params.relabels, params.data_minings, params.iterations)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("expected %d root relabels, %d relabels, %d data minings and %d iterations\n"
, params.root_relabels, params.relabels, params.data_minings,
params.iterations); fflush(stdout); } } while (0)
;
1588 PRINT(CCV_CLI_INFO, "include overlap : %lf\n"do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("include overlap : %lf\n" "alpha : %lf\n" "alpha decreasing ratio : %lf\n"
"C : %lf\n" "balance ratio : %lf\n" "------------------------\n"
, params.include_overlap, params.alpha, params.alpha_ratio, params
.C, params.balance); fflush(stdout); } } while (0)
1589 "alpha : %lf\n"do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("include overlap : %lf\n" "alpha : %lf\n" "alpha decreasing ratio : %lf\n"
"C : %lf\n" "balance ratio : %lf\n" "------------------------\n"
, params.include_overlap, params.alpha, params.alpha_ratio, params
.C, params.balance); fflush(stdout); } } while (0)
1590 "alpha decreasing ratio : %lf\n"do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("include overlap : %lf\n" "alpha : %lf\n" "alpha decreasing ratio : %lf\n"
"C : %lf\n" "balance ratio : %lf\n" "------------------------\n"
, params.include_overlap, params.alpha, params.alpha_ratio, params
.C, params.balance); fflush(stdout); } } while (0)
1591 "C : %lf\n"do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("include overlap : %lf\n" "alpha : %lf\n" "alpha decreasing ratio : %lf\n"
"C : %lf\n" "balance ratio : %lf\n" "------------------------\n"
, params.include_overlap, params.alpha, params.alpha_ratio, params
.C, params.balance); fflush(stdout); } } while (0)
1592 "balance ratio : %lf\n"do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("include overlap : %lf\n" "alpha : %lf\n" "alpha decreasing ratio : %lf\n"
"C : %lf\n" "balance ratio : %lf\n" "------------------------\n"
, params.include_overlap, params.alpha, params.alpha_ratio, params
.C, params.balance); fflush(stdout); } } while (0)
1593 "------------------------\n",do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("include overlap : %lf\n" "alpha : %lf\n" "alpha decreasing ratio : %lf\n"
"C : %lf\n" "balance ratio : %lf\n" "------------------------\n"
, params.include_overlap, params.alpha, params.alpha_ratio, params
.C, params.balance); fflush(stdout); } } while (0)
1594 params.include_overlap, params.alpha, params.alpha_ratio, params.C, params.balance)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("include overlap : %lf\n" "alpha : %lf\n" "alpha decreasing ratio : %lf\n"
"C : %lf\n" "balance ratio : %lf\n" "------------------------\n"
, params.include_overlap, params.alpha, params.alpha_ratio, params
.C, params.balance); fflush(stdout); } } while (0)
;
1595 gsl_rng_env_setup();
1596 gsl_rng* rng = gsl_rng_alloc(gsl_rng_default);
1597 gsl_rng_set(rng, *(unsigned long int*)&params);
1598 ccv_dpm_mixture_model_t* model = (ccv_dpm_mixture_model_t*)ccmallocmalloc(sizeof(ccv_dpm_mixture_model_t));
1599 memset(model, 0, sizeof(ccv_dpm_mixture_model_t));
1600 struct feature_node* fn = (struct feature_node*)ccmallocmalloc(sizeof(struct feature_node) * posnum);
1601 for (i = 0; i < posnum; i++)
1602 {
1603 assert(bboxes[i].width > 0 && bboxes[i].height > 0)((void) sizeof ((bboxes[i].width > 0 && bboxes[i].
height > 0) ? 1 : 0), __extension__ ({ if (bboxes[i].width
> 0 && bboxes[i].height > 0) ; else __assert_fail
("bboxes[i].width > 0 && bboxes[i].height > 0"
, "ccv_dpm.c", 1603, __extension__ __PRETTY_FUNCTION__); }))
;
1604 fn[i].value = (float)bboxes[i].width / (float)bboxes[i].height;
1605 fn[i].index = i;
1606 }
1607 char checkpoint[512];
1608 char initcheckpoint[512];
1609 sprintf(checkpoint, "%s/model", dir);
1610 sprintf(initcheckpoint, "%s/init.model", dir);
1611 _ccv_dpm_aspect_qsort(fn, posnum, 0);
1612 double mean = 0;
1613 for (i = 0; i < posnum; i++)
1614 mean += fn[i].value;
1615 mean /= posnum;
1616 double variance = 0;
1617 for (i = 0; i < posnum; i++)
1618 variance += (fn[i].value - mean) * (fn[i].value - mean);
1619 variance /= posnum;
1620 PRINT(CCV_CLI_INFO, "global mean: %lf, & variance: %lf\ninterclass mean(variance):", mean, variance)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("global mean: %lf, & variance: %lf\ninterclass mean(variance):"
, mean, variance); fflush(stdout); } } while (0)
;
1621 int* mnum = (int*)alloca(sizeof(int) * params.components)__builtin_alloca (sizeof(int) * params.components);
1622 int outnum = posnum, innum = 0;
1623 for (i = 0; i < params.components; i++)
1624 {
1625 mnum[i] = (int)((double)outnum / (double)(params.components - i) + 0.5);
1626 double mean = 0;
1627 for (j = innum; j < innum + mnum[i]; j++)
1628 mean += fn[j].value;
1629 mean /= mnum[i];
1630 double variance = 0;
1631 for (j = innum; j < innum + mnum[i]; j++)
1632 variance += (fn[j].value - mean) * (fn[j].value - mean);
1633 variance /= mnum[i];
1634 PRINT(CCV_CLI_INFO, " %lf(%lf)", mean, variance)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" %lf(%lf)", mean, variance); fflush(stdout); } } while (0)
;
1635 outnum -= mnum[i];
1636 innum += mnum[i];
1637 }
1638 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
1639 int* areas = (int*)ccmallocmalloc(sizeof(int) * posnum);
1640 for (i = 0; i < posnum; i++)
1641 areas[i] = bboxes[i].width * bboxes[i].height;
1642 _ccv_dpm_area_qsort(areas, posnum, 0);
1643 // so even the object is 1/4 in size, we can still detect them (in detection phase, we start at 2x image)
1644 int area = ccv_clamp(areas[(int)(posnum * 0.2 + 0.5)], params.min_area, params.max_area)({ typeof (params.min_area) _a = (params.min_area); typeof (params
.max_area) _b = (params.max_area); typeof (areas[(int)(posnum
* 0.2 + 0.5)]) _x = (areas[(int)(posnum * 0.2 + 0.5)]); (_x <
_a) ? _a : ((_x > _b) ? _b : _x); })
;
1645 ccfreefree(areas);
1646 innum = 0;
1647 _ccv_dpm_read_checkpoint(model, checkpoint);
1648 if (model->count <= 0)
1649 {
1650 /* initialize root mixture model with liblinear */
1651 model->count = params.components;
1652 model->root = (ccv_dpm_root_classifier_t*)ccmallocmalloc(sizeof(ccv_dpm_root_classifier_t) * model->count);
1653 memset(model->root, 0, sizeof(ccv_dpm_root_classifier_t) * model->count);
1654 }
1655 PRINT(CCV_CLI_INFO, "computing root mixture model dimensions: ")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("computing root mixture model dimensions: "); fflush(stdout)
; } } while (0)
;
1656 fflush(stdoutstdout);
1657 int* poslabels = (int*)ccmallocmalloc(sizeof(int) * posnum);
1658 int* rows = (int*)alloca(sizeof(int) * params.components)__builtin_alloca (sizeof(int) * params.components);
1659 int* cols = (int*)alloca(sizeof(int) * params.components)__builtin_alloca (sizeof(int) * params.components);
1660 for (i = 0; i < params.components; i++)
1661 {
1662 double aspect = 0;
1663 for (j = innum; j < innum + mnum[i]; j++)
1664 {
1665 aspect += fn[j].value;
1666 poslabels[fn[j].index] = i; // setup labels
1667 }
1668 aspect /= mnum[i];
1669 cols[i] = ccv_max((int)(sqrtf(area / aspect) * aspect / CCV_DPM_WINDOW_SIZE + 0.5), 1)({ typeof ((int)(sqrtf(area / aspect) * aspect / (8) + 0.5)) _a
= ((int)(sqrtf(area / aspect) * aspect / (8) + 0.5)); typeof
(1) _b = (1); (_a > _b) ? _a : _b; })
;
1670 rows[i] = ccv_max((int)(sqrtf(area / aspect) / CCV_DPM_WINDOW_SIZE + 0.5), 1)({ typeof ((int)(sqrtf(area / aspect) / (8) + 0.5)) _a = ((int
)(sqrtf(area / aspect) / (8) + 0.5)); typeof (1) _b = (1); (_a
> _b) ? _a : _b; })
;
1671 if (i < params.components - 1)
1672 PRINT(CCV_CLI_INFO, "%dx%d, ", cols[i], rows[i])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("%dx%d, ", cols[i], rows[i]); fflush(stdout); } } while (0)
;
1673 else
1674 PRINT(CCV_CLI_INFO, "%dx%d\n", cols[i], rows[i])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("%dx%d\n", cols[i], rows[i]); fflush(stdout); } } while (0)
;
1675 fflush(stdoutstdout);
1676 innum += mnum[i];
1677 }
1678 ccfreefree(fn);
1679 int corrupted = 1;
1680 for (i = 0; i < params.components; i++)
1681 if (model->root[i].root.w)
1682 {
1683 PRINT(CCV_CLI_INFO, "skipping root mixture model initialization for model %d(%d)\n", i + 1, params.components)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("skipping root mixture model initialization for model %d(%d)\n"
, i + 1, params.components); fflush(stdout); } } while (0)
;
1684 corrupted = 0;
1685 } else
1686 break;
1687 if (corrupted)
1688 {
1689 PRINT(CCV_CLI_INFO, "root mixture model initialization corrupted, reboot\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("root mixture model initialization corrupted, reboot\n"); fflush
(stdout); } } while (0)
;
1690 ccv_array_t** posex = (ccv_array_t**)alloca(sizeof(ccv_array_t*) * params.components)__builtin_alloca (sizeof(ccv_array_t*) * params.components);
1691 for (i = 0; i < params.components; i++)
1692 posex[i] = _ccv_dpm_summon_examples_by_rectangle(posfiles, bboxes, posnum, i, rows[i], cols[i], params.grayscale);
1693 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
1694 ccv_array_t** negex = (ccv_array_t**)alloca(sizeof(ccv_array_t*) * params.components)__builtin_alloca (sizeof(ccv_array_t*) * params.components);
1695 _ccv_dpm_collect_examples_randomly(rng, negex, bgfiles, bgnum, negnum, params.components, rows, cols, params.grayscale);
1696 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
1697 int* neglabels = (int*)ccmallocmalloc(sizeof(int) * negex[0]->rnum);
1698 for (i = 0; i < negex[0]->rnum; i++)
1699 neglabels[i] = gsl_rng_uniform_int(rng, params.components);
1700 for (i = 0; i < params.components; i++)
1701 {
1702 ccv_dpm_root_classifier_t* root_classifier = model->root + i;
1703 root_classifier->root.w = ccv_dense_matrix_new(rows[i], cols[i], CCV_32F | 31, 0, 0);
1704 PRINT(CCV_CLI_INFO, "initializing root mixture model for model %d(%d)\n", i + 1, params.components)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("initializing root mixture model for model %d(%d)\n", i + 1,
params.components); fflush(stdout); } } while (0)
;
1705 _ccv_dpm_initialize_root_classifier(rng, root_classifier, i, mnum[i], poslabels, posex[i], neglabels, negex[i], params.C, params.symmetric, params.grayscale);
1706 }
1707 ccfreefree(neglabels);
1708 ccfreefree(poslabels);
1709 // check symmetric property of generated root feature
1710 if (params.symmetric)
1711 for (i = 0; i < params.components; i++)
1712 {
1713 ccv_dpm_root_classifier_t* root_classifier = model->root + i;
1714 _ccv_dpm_check_root_classifier_symmetry(root_classifier->root.w);
1715 }
1716 if (params.components > 1)
1717 {
1718 /* TODO: coordinate-descent for lsvm */
1719 PRINT(CCV_CLI_INFO, "optimizing root mixture model with coordinate-descent approach\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("optimizing root mixture model with coordinate-descent approach\n"
); fflush(stdout); } } while (0)
;
1720 model = _ccv_dpm_optimize_root_mixture_model(rng, model, posex, negex, params.root_relabels, params.balance, params.C, params.alpha, params.alpha_ratio, params.iterations, params.symmetric);
1721 } else {
1722 PRINT(CCV_CLI_INFO, "components == 1, skipped coordinate-descent to optimize root mixture model\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("components == 1, skipped coordinate-descent to optimize root mixture model\n"
); fflush(stdout); } } while (0)
;
1723 }
1724 for (i = 0; i < params.components; i++)
1725 {
1726 for (j = 0; j < posex[i]->rnum; j++)
1727 _ccv_dpm_feature_vector_cleanup((ccv_dpm_feature_vector_t*)ccv_array_get(posex[i], j)((void*)(((char*)((posex[i])->data)) + (size_t)(posex[i])->
rsize * (size_t)(j)))
);
1728 ccv_array_free(posex[i]);
1729 for (j = 0; j < negex[i]->rnum; j++)
1730 _ccv_dpm_feature_vector_cleanup((ccv_dpm_feature_vector_t*)ccv_array_get(negex[i], j)((void*)(((char*)((negex[i])->data)) + (size_t)(negex[i])->
rsize * (size_t)(j)))
);
1731 ccv_array_free(negex[i]);
1732 }
1733 } else {
1734 ccfreefree(poslabels);
1735 }
1736 _ccv_dpm_write_checkpoint(model, 0, checkpoint);
1737 /* initialize part filter */
1738 PRINT(CCV_CLI_INFO, "initializing part filters\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("initializing part filters\n"); fflush(stdout); } } while (0
)
;
1739 for (i = 0; i < params.components; i++)
1740 {
1741 if (model->root[i].count > 0)
1742 {
1743 PRINT(CCV_CLI_INFO, " - skipping part filters initialization for model %d(%d)\n", i + 1, params.components)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - skipping part filters initialization for model %d(%d)\n"
, i + 1, params.components); fflush(stdout); } } while (0)
;
1744 } else {
1745 PRINT(CCV_CLI_INFO, " - initializing part filters for model %d(%d)\n", i + 1, params.components)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - initializing part filters for model %d(%d)\n", i + 1, params
.components); fflush(stdout); } } while (0)
;
1746 _ccv_dpm_initialize_part_classifiers(model->root + i, params.parts, params.symmetric);
1747 _ccv_dpm_write_checkpoint(model, 0, checkpoint);
1748 _ccv_dpm_write_checkpoint(model, 0, initcheckpoint);
1749 }
1750 }
1751 _ccv_dpm_write_checkpoint(model, 0, checkpoint);
1752 /* optimize both root filter and part filters with stochastic gradient descent */
1753 PRINT(CCV_CLI_INFO, "optimizing root filter & part filters with stochastic gradient descent\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("optimizing root filter & part filters with stochastic gradient descent\n"
); fflush(stdout); } } while (0)
;
1754 char gradient_progress_checkpoint[512];
1755 sprintf(gradient_progress_checkpoint, "%s/gradient_descent_progress", dir);
1756 char feature_vector_checkpoint[512];
1757 sprintf(feature_vector_checkpoint, "%s/positive_vectors", dir);
1758 char neg_vector_checkpoint[512];
1759 sprintf(neg_vector_checkpoint, "%s/negative_vectors", dir);
1760 ccv_dpm_feature_vector_t** posv = (ccv_dpm_feature_vector_t**)ccmallocmalloc(posnum * sizeof(ccv_dpm_feature_vector_t*));
1761 int* order = (int*)ccmallocmalloc(sizeof(int) * (posnum + params.negative_cache_size + 64 /* the magical number for maximum negative examples collected per image */));
1762 double previous_positive_loss = 0, previous_negative_loss = 0, positive_loss = 0, negative_loss = 0, loss = 0;
1763 // need to re-weight for each examples
1764 c = d = t = 0;
1765 ccv_array_t* negv = 0;
1766 if (0 == _ccv_dpm_read_negative_feature_vectors(&negv, params.negative_cache_size, neg_vector_checkpoint))
1767 PRINT(CCV_CLI_INFO, " - read collected negative responses from last interrupted process\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - read collected negative responses from last interrupted process\n"
); fflush(stdout); } } while (0)
;
1768 _ccv_dpm_read_gradient_descent_progress(&c, &d, gradient_progress_checkpoint);
1769 for (; c < params.relabels; c++)
1770 {
1771 double regz_rate = params.C;
1772 ccv_dpm_mixture_model_t* _model;
1773 if (0 == _ccv_dpm_read_positive_feature_vectors(posv, posnum, feature_vector_checkpoint))
1774 {
1775 PRINT(CCV_CLI_INFO, " - read collected positive responses from last interrupted process\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - read collected positive responses from last interrupted process\n"
); fflush(stdout); } } while (0)
;
1776 } else {
1777 FLUSH(CCV_CLI_INFO, " - collecting responses from positive examples : 0%%")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - collecting responses from positive examples : 0%%"
); fflush(stdout); } } while (0)
;
1778 for (i = 0; i < posnum; i++)
1779 {
1780 FLUSH(CCV_CLI_INFO, " - collecting responses from positive examples : %d%%", i * 100 / posnum)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - collecting responses from positive examples : %d%%"
, i * 100 / posnum); fflush(stdout); } } while (0)
;
1781 ccv_dense_matrix_t* image = 0;
1782 ccv_read(posfiles[i], &image, (params.grayscale ? CCV_IO_GRAY : 0) | CCV_IO_ANY_FILE)ccv_read_impl(posfiles[i], &image, (params.grayscale ? CCV_IO_GRAY
: 0) | CCV_IO_ANY_FILE, 0, 0, 0)
;
1783 posv[i] = _ccv_dpm_collect_best(image, model, bboxes[i], params.include_overlap, params.detector);
1784 ccv_matrix_free(image);
1785 }
1786 FLUSH(CCV_CLI_INFO, " - collecting responses from positive examples : 100%%\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - collecting responses from positive examples : 100%%\n"
); fflush(stdout); } } while (0)
;
1787 _ccv_dpm_write_positive_feature_vectors(posv, posnum, feature_vector_checkpoint);
1788 }
1789 int* posvnum = (int*)alloca(sizeof(int) * model->count)__builtin_alloca (sizeof(int) * model->count);
1790 memset(posvnum, 0, sizeof(int) * model->count);
1791 for (i = 0; i < posnum; i++)
1792 if (posv[i])
1793 {
1794 assert(posv[i]->id >= 0 && posv[i]->id < model->count)((void) sizeof ((posv[i]->id >= 0 && posv[i]->
id < model->count) ? 1 : 0), __extension__ ({ if (posv[
i]->id >= 0 && posv[i]->id < model->count
) ; else __assert_fail ("posv[i]->id >= 0 && posv[i]->id < model->count"
, "ccv_dpm.c", 1794, __extension__ __PRETTY_FUNCTION__); }))
;
1795 ++posvnum[posv[i]->id];
1796 }
1797 PRINT(CCV_CLI_INFO, " - positive examples divided by components : %d", posvnum[0])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - positive examples divided by components : %d", posvnum[0
]); fflush(stdout); } } while (0)
;
1798 for (i = 1; i < model->count; i++)
1799 PRINT(CCV_CLI_INFO, ", %d", posvnum[i])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(", %d", posvnum[i]); fflush(stdout); } } while (0)
;
1800 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
1801 params.detector.threshold = 0;
1802 for (; d < params.data_minings; d++)
1803 {
1804 // the cache is used up now, collect again
1805 _ccv_dpm_write_gradient_descent_progress(c, d, gradient_progress_checkpoint);
1806 double alpha = params.alpha;
1807 if (negv)
1808 {
1809 ccv_array_t* av = ccv_array_new(sizeof(ccv_dpm_feature_vector_t*), 64, 0);
1810 for (j = 0; j < negv->rnum; j++)
1811 {
1812 ccv_dpm_feature_vector_t* v = *(ccv_dpm_feature_vector_t**)ccv_array_get(negv, j)((void*)(((char*)((negv)->data)) + (size_t)(negv)->rsize
* (size_t)(j)))
;
1813 double score = _ccv_dpm_vector_score(model, v);
1814 assert(!isnan(score))((void) sizeof ((!__builtin_isnan (score)) ? 1 : 0), __extension__
({ if (!__builtin_isnan (score)) ; else __assert_fail ("!isnan(score)"
, "ccv_dpm.c", 1814, __extension__ __PRETTY_FUNCTION__); }))
;
1815 if (score >= -1)
1816 ccv_array_push(av, &v);
1817 else
1818 _ccv_dpm_feature_vector_free(v);
1819 }
1820 ccv_array_free(negv);
1821 negv = av;
1822 } else {
1823 negv = ccv_array_new(sizeof(ccv_dpm_feature_vector_t*), 64, 0);
1824 }
1825 FLUSH(CCV_CLI_INFO, " - collecting negative examples -- (0%%)")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - collecting negative examples -- (0%%)"
); fflush(stdout); } } while (0)
;
1826 if (negv->rnum < params.negative_cache_size)
1827 _ccv_dpm_collect_from_background(negv, rng, bgfiles, bgnum, model, params, 0);
1828 _ccv_dpm_write_negative_feature_vectors(negv, params.negative_cache_size, neg_vector_checkpoint);
1829 FLUSH(CCV_CLI_INFO, " - collecting negative examples -- (100%%)\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - collecting negative examples -- (100%%)\n"
); fflush(stdout); } } while (0)
;
1830 int* negvnum = (int*)alloca(sizeof(int) * model->count)__builtin_alloca (sizeof(int) * model->count);
1831 memset(negvnum, 0, sizeof(int) * model->count);
1832 for (i = 0; i < negv->rnum; i++)
1833 {
1834 ccv_dpm_feature_vector_t* v = *(ccv_dpm_feature_vector_t**)ccv_array_get(negv, i)((void*)(((char*)((negv)->data)) + (size_t)(negv)->rsize
* (size_t)(i)))
;
1835 assert(v->id >= 0 && v->id < model->count)((void) sizeof ((v->id >= 0 && v->id < model
->count) ? 1 : 0), __extension__ ({ if (v->id >= 0 &&
v->id < model->count) ; else __assert_fail ("v->id >= 0 && v->id < model->count"
, "ccv_dpm.c", 1835, __extension__ __PRETTY_FUNCTION__); }))
;
1836 ++negvnum[v->id];
1837 }
1838 if (negv->rnum <= ccv_max(params.negative_cache_size / 2, ccv_max(REGQ, MINI_BATCH))({ typeof (params.negative_cache_size / 2) _a = (params.negative_cache_size
/ 2); typeof (({ typeof ((100)) _a = ((100)); typeof ((10)) _b
= ((10)); (_a > _b) ? _a : _b; })) _b = (({ typeof ((100)
) _a = ((100)); typeof ((10)) _b = ((10)); (_a > _b) ? _a :
_b; })); (_a > _b) ? _a : _b; })
)
1839 {
1840 for (i = 0; i < model->count; i++)
1841 // we cannot get sufficient negatives, adjust constant and abort for next round
1842 _ccv_dpm_adjust_model_constant(model, i, posv, posnum, params.percentile_breakdown);
1843 continue;
1844 }
1845 PRINT(CCV_CLI_INFO, " - negative examples divided by components : %d", negvnum[0])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - negative examples divided by components : %d", negvnum[0
]); fflush(stdout); } } while (0)
;
1846 for (i = 1; i < model->count; i++)
1847 PRINT(CCV_CLI_INFO, ", %d", negvnum[i])do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(", %d", negvnum[i]); fflush(stdout); } } while (0)
;
1848 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
1849 previous_positive_loss = previous_negative_loss = 0;
1850 uint64_t elapsed_time = _ccv_dpm_time_measure();
1851 assert(negv->rnum < params.negative_cache_size + 64)((void) sizeof ((negv->rnum < params.negative_cache_size
+ 64) ? 1 : 0), __extension__ ({ if (negv->rnum < params
.negative_cache_size + 64) ; else __assert_fail ("negv->rnum < params.negative_cache_size + 64"
, "ccv_dpm.c", 1851, __extension__ __PRETTY_FUNCTION__); }))
;
1852 for (t = 0; t < params.iterations; t++)
1853 {
1854 for (p = 0; p < model->count; p++)
1855 {
1856 // if don't have enough negnum or posnum, aborting
1857 if (negvnum[p] <= ccv_max(params.negative_cache_size / (model->count * 3), ccv_max(REGQ, MINI_BATCH))({ typeof (params.negative_cache_size / (model->count * 3)
) _a = (params.negative_cache_size / (model->count * 3)); typeof
(({ typeof ((100)) _a = ((100)); typeof ((10)) _b = ((10)); (
_a > _b) ? _a : _b; })) _b = (({ typeof ((100)) _a = ((100
)); typeof ((10)) _b = ((10)); (_a > _b) ? _a : _b; })); (
_a > _b) ? _a : _b; })
||
1858 posvnum[p] <= ccv_max(REGQ, MINI_BATCH)({ typeof ((100)) _a = ((100)); typeof ((10)) _b = ((10)); (_a
> _b) ? _a : _b; })
)
1859 continue;
1860 double pos_weight = sqrt((double)negvnum[p] / posvnum[p] * params.balance); // positive weight
1861 double neg_weight = sqrt((double)posvnum[p] / negvnum[p] / params.balance); // negative weight
1862 _model = _ccv_dpm_model_copy(model);
1863 for (i = 0; i < posnum + negv->rnum; i++)
1864 order[i] = i;
1865 gsl_ran_shuffle(rng, order, posnum + negv->rnum, sizeof(int));
1866 int l = 0;
1867 for (i = 0; i < posnum + negv->rnum; i++)
1868 {
1869 k = order[i];
1870 if (k < posnum)
1871 {
1872 if (posv[k] == 0 || posv[k]->id != p)
1873 continue;
1874 double score = _ccv_dpm_vector_score(model, posv[k]); // the loss for mini-batch method (computed on model)
1875 assert(!isnan(score))((void) sizeof ((!__builtin_isnan (score)) ? 1 : 0), __extension__
({ if (!__builtin_isnan (score)) ; else __assert_fail ("!isnan(score)"
, "ccv_dpm.c", 1875, __extension__ __PRETTY_FUNCTION__); }))
;
1876 if (score <= 1)
1877 _ccv_dpm_stochastic_gradient_descent(_model, posv[k], 1, alpha * pos_weight, regz_rate, params.symmetric);
1878 } else {
1879 ccv_dpm_feature_vector_t* v = *(ccv_dpm_feature_vector_t**)ccv_array_get(negv, k - posnum)((void*)(((char*)((negv)->data)) + (size_t)(negv)->rsize
* (size_t)(k - posnum)))
;
1880 if (v->id != p)
1881 continue;
1882 double score = _ccv_dpm_vector_score(model, v);
1883 assert(!isnan(score))((void) sizeof ((!__builtin_isnan (score)) ? 1 : 0), __extension__
({ if (!__builtin_isnan (score)) ; else __assert_fail ("!isnan(score)"
, "ccv_dpm.c", 1883, __extension__ __PRETTY_FUNCTION__); }))
;
1884 if (score >= -1)
1885 _ccv_dpm_stochastic_gradient_descent(_model, v, -1, alpha * neg_weight, regz_rate, params.symmetric);
1886 }
1887 ++l;
1888 if (l % REGQ(100) == REGQ(100) - 1)
1889 _ccv_dpm_regularize_mixture_model(_model, p, 1.0 - pow(1.0 - alpha / (double)((posvnum[p] + negvnum[p]) * (!!params.symmetric + 1)), REGQ(100)));
1890 if (l % MINI_BATCH(10) == MINI_BATCH(10) - 1)
1891 {
1892 // mimicking mini-batch way of doing things
1893 _ccv_dpm_mixture_model_cleanup(model);
1894 ccfreefree(model);
1895 model = _model;
1896 _model = _ccv_dpm_model_copy(model);
1897 }
1898 }
1899 _ccv_dpm_regularize_mixture_model(_model, p, 1.0 - pow(1.0 - alpha / (double)((posvnum[p] + negvnum[p]) * (!!params.symmetric + 1)), (((posvnum[p] + negvnum[p]) % REGQ(100)) + 1) % (REGQ(100) + 1)));
1900 _ccv_dpm_mixture_model_cleanup(model);
1901 ccfreefree(model);
1902 model = _model;
1903 }
1904 // compute the loss
1905 int posvn = 0;
1906 positive_loss = negative_loss = loss = 0;
1907 for (i = 0; i < posnum; i++)
1908 if (posv[i] != 0)
1909 {
1910 double score = _ccv_dpm_vector_score(model, posv[i]);
1911 assert(!isnan(score))((void) sizeof ((!__builtin_isnan (score)) ? 1 : 0), __extension__
({ if (!__builtin_isnan (score)) ; else __assert_fail ("!isnan(score)"
, "ccv_dpm.c", 1911, __extension__ __PRETTY_FUNCTION__); }))
;
1912 double hinge_loss = ccv_max(0, 1.0 - score)({ typeof (0) _a = (0); typeof (1.0 - score) _b = (1.0 - score
); (_a > _b) ? _a : _b; })
;
1913 positive_loss += hinge_loss;
1914 double pos_weight = sqrt((double)negvnum[posv[i]->id] / posvnum[posv[i]->id] * params.balance); // positive weight
1915 loss += pos_weight * hinge_loss;
1916 ++posvn;
1917 }
1918 for (i = 0; i < negv->rnum; i++)
1919 {
1920 ccv_dpm_feature_vector_t* v = *(ccv_dpm_feature_vector_t**)ccv_array_get(negv, i)((void*)(((char*)((negv)->data)) + (size_t)(negv)->rsize
* (size_t)(i)))
;
1921 double score = _ccv_dpm_vector_score(model, v);
1922 assert(!isnan(score))((void) sizeof ((!__builtin_isnan (score)) ? 1 : 0), __extension__
({ if (!__builtin_isnan (score)) ; else __assert_fail ("!isnan(score)"
, "ccv_dpm.c", 1922, __extension__ __PRETTY_FUNCTION__); }))
;
1923 double hinge_loss = ccv_max(0, 1.0 + score)({ typeof (0) _a = (0); typeof (1.0 + score) _b = (1.0 + score
); (_a > _b) ? _a : _b; })
;
1924 negative_loss += hinge_loss;
1925 double neg_weight = sqrt((double)posvnum[v->id] / negvnum[v->id] / params.balance); // negative weight
1926 loss += neg_weight * hinge_loss;
1927 }
1928 loss = loss / (posvn + negv->rnum);
1929 positive_loss = positive_loss / posvn;
1930 negative_loss = negative_loss / negv->rnum;
1931 FLUSH(CCV_CLI_INFO, " - with loss %.5lf (positive %.5lf, negative %.5f) at rate %.5lf %d | %d -- %d%%", loss, positive_loss, negative_loss, alpha, posvn, negv->rnum, (t + 1) * 100 / params.iterations)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { for
(_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT;
_CCV_PRINT_LOOP++) printf("\b"); for (_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP
< _CCV_PRINT_COUNT; _CCV_PRINT_LOOP++) printf(" "); for (
_CCV_PRINT_LOOP = 0; _CCV_PRINT_LOOP < _CCV_PRINT_COUNT; _CCV_PRINT_LOOP
++) printf("\b"); _CCV_PRINT_COUNT = printf(" - with loss %.5lf (positive %.5lf, negative %.5f) at rate %.5lf %d | %d -- %d%%"
, loss, positive_loss, negative_loss, alpha, posvn, negv->
rnum, (t + 1) * 100 / params.iterations); fflush(stdout); } }
while (0)
;
1932 // check symmetric property of generated root feature
1933 if (params.symmetric)
1934 for (i = 0; i < params.components; i++)
1935 {
1936 ccv_dpm_root_classifier_t* root_classifier = model->root + i;
1937 _ccv_dpm_check_root_classifier_symmetry(root_classifier->root.w);
1938 }
1939 if (fabs(previous_positive_loss - positive_loss) < 1e-5 &&
1940 fabs(previous_negative_loss - negative_loss) < 1e-5)
1941 {
1942 PRINT(CCV_CLI_INFO, "\n - aborting iteration at %d because we didn't gain much", t + 1)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n - aborting iteration at %d because we didn't gain much",
t + 1); fflush(stdout); } } while (0)
;
1943 break;
1944 }
1945 previous_positive_loss = positive_loss;
1946 previous_negative_loss = negative_loss;
1947 alpha *= params.alpha_ratio; // it will decrease with each iteration
1948 }
1949 _ccv_dpm_write_checkpoint(model, 0, checkpoint);
1950 PRINT(CCV_CLI_INFO, "\n - data mining %d takes %.2lf seconds at loss %.5lf, %d more to go (%d of %d)\n", d + 1, (double)(_ccv_dpm_time_measure() - elapsed_time) / 1000000.0, loss, params.data_minings - d - 1, c + 1, params.relabels)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n - data mining %d takes %.2lf seconds at loss %.5lf, %d more to go (%d of %d)\n"
, d + 1, (double)(_ccv_dpm_time_measure() - elapsed_time) / 1000000.0
, loss, params.data_minings - d - 1, c + 1, params.relabels);
fflush(stdout); } } while (0)
;
1951 j = 0;
1952 double* scores = (double*)ccmallocmalloc(posnum * sizeof(double));
1953 for (i = 0; i < posnum; i++)
1954 if (posv[i])
1955 {
1956 scores[j] = _ccv_dpm_vector_score(model, posv[i]);
1957 assert(!isnan(scores[j]))((void) sizeof ((!__builtin_isnan (scores[j])) ? 1 : 0), __extension__
({ if (!__builtin_isnan (scores[j])) ; else __assert_fail ("!isnan(scores[j])"
, "ccv_dpm.c", 1957, __extension__ __PRETTY_FUNCTION__); }))
;
1958 j++;
1959 }
1960 _ccv_dpm_score_qsort(scores, j, 0);
1961 ccfreefree(scores);
1962 double breakdown;
1963 PRINT(CCV_CLI_INFO, " - threshold breakdown by percentile")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" - threshold breakdown by percentile"); fflush(stdout); } }
while (0)
;
1964 for (breakdown = params.percentile_breakdown; breakdown < 1.0; breakdown += params.percentile_breakdown)
1965 PRINT(CCV_CLI_INFO, " %0.2lf(%.1f%%)", scores[ccv_clamp((int)(breakdown * j), 0, j - 1)], (1.0 - breakdown) * 100)do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
(" %0.2lf(%.1f%%)", scores[({ typeof (0) _a = (0); typeof (j -
1) _b = (j - 1); typeof ((int)(breakdown * j)) _x = ((int)(breakdown
* j)); (_x < _a) ? _a : ((_x > _b) ? _b : _x); })], (1.0
- breakdown) * 100); fflush(stdout); } } while (0)
;
1966 PRINT(CCV_CLI_INFO, "\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("\n"); fflush(stdout); } } while (0)
;
1967 char persist[512];
1968 sprintf(persist, "%s/model.%d.%d", dir, c, d);
1969 _ccv_dpm_write_checkpoint(model, 0, persist);
1970 }
1971 d = 0;
1972 // if abort, means that we cannot find enough negative examples, try to adjust constant
1973 for (i = 0; i < posnum; i++)
1974 if (posv[i])
1975 _ccv_dpm_feature_vector_free(posv[i]);
1976 remove(feature_vector_checkpoint);
1977 }
1978 if (negv)
1979 {
1980 for (i = 0; i < negv->rnum; i++)
1981 {
1982 ccv_dpm_feature_vector_t* v = *(ccv_dpm_feature_vector_t**)ccv_array_get(negv, i)((void*)(((char*)((negv)->data)) + (size_t)(negv)->rsize
* (size_t)(i)))
;
1983 _ccv_dpm_feature_vector_free(v);
1984 }
1985 ccv_array_free(negv);
1986 }
1987 remove(neg_vector_checkpoint);
1988 ccfreefree(order);
1989 ccfreefree(posv);
1990 PRINT(CCV_CLI_INFO, "root rectangle prediction with linear regression\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("root rectangle prediction with linear regression\n"); fflush
(stdout); } } while (0)
;
1991 _ccv_dpm_initialize_root_rectangle_estimator(model, posfiles, bboxes, posnum, params);
1992 _ccv_dpm_write_checkpoint(model, 1, checkpoint);
1993 PRINT(CCV_CLI_INFO, "done\n")do { if ((CCV_CLI_INFO & ccv_cli_get_output_levels())) { printf
("done\n"); fflush(stdout); } } while (0)
;
1994 remove(gradient_progress_checkpoint);
1995 _ccv_dpm_mixture_model_cleanup(model);
1996 ccfreefree(model);
1997 gsl_rng_free(rng);
1998}
1999#else
2000void ccv_dpm_mixture_model_new(char** posfiles, ccv_rect_t* bboxes, int posnum, char** bgfiles, int bgnum, int negnum, const char* dir, ccv_dpm_new_param_t params)
2001{
2002 fprintf(stderrstderr, " ccv_dpm_classifier_cascade_new requires libgsl and liblinear support, please compile ccv with them.\n");
2003}
2004#endif
2005#else
2006void ccv_dpm_mixture_model_new(char** posfiles, ccv_rect_t* bboxes, int posnum, char** bgfiles, int bgnum, int negnum, const char* dir, ccv_dpm_new_param_t params)
2007{
2008 fprintf(stderrstderr, " ccv_dpm_classifier_cascade_new requires libgsl and liblinear support, please compile ccv with them.\n");
2009}
2010#endif
2011
2012static int _ccv_is_equal(const void* _r1, const void* _r2, void* data)
2013{
2014 const ccv_root_comp_t* r1 = (const ccv_root_comp_t*)_r1;
2015 const ccv_root_comp_t* r2 = (const ccv_root_comp_t*)_r2;
2016 int distance = (int)(ccv_min(r1->rect.width, r1->rect.height)({ typeof (r1->rect.width) _a = (r1->rect.width); typeof
(r1->rect.height) _b = (r1->rect.height); (_a < _b)
? _a : _b; })
* 0.25 + 0.5);
2017
2018 return r2->rect.x <= r1->rect.x + distance &&
2019 r2->rect.x >= r1->rect.x - distance &&
2020 r2->rect.y <= r1->rect.y + distance &&
2021 r2->rect.y >= r1->rect.y - distance &&
2022 r2->rect.width <= (int)(r1->rect.width * 1.5 + 0.5) &&
2023 (int)(r2->rect.width * 1.5 + 0.5) >= r1->rect.width &&
2024 r2->rect.height <= (int)(r1->rect.height * 1.5 + 0.5) &&
2025 (int)(r2->rect.height * 1.5 + 0.5) >= r1->rect.height;
2026}
2027
2028static int _ccv_is_equal_same_class(const void* _r1, const void* _r2, void* data)
2029{
2030 const ccv_root_comp_t* r1 = (const ccv_root_comp_t*)_r1;
2031 const ccv_root_comp_t* r2 = (const ccv_root_comp_t*)_r2;
2032 int distance = (int)(ccv_min(r1->rect.width, r1->rect.height)({ typeof (r1->rect.width) _a = (r1->rect.width); typeof
(r1->rect.height) _b = (r1->rect.height); (_a < _b)
? _a : _b; })
* 0.25 + 0.5);
2033
2034 return r2->classification.id == r1->classification.id &&
2035 r2->rect.x <= r1->rect.x + distance &&
2036 r2->rect.x >= r1->rect.x - distance &&
2037 r2->rect.y <= r1->rect.y + distance &&
2038 r2->rect.y >= r1->rect.y - distance &&
2039 r2->rect.width <= (int)(r1->rect.width * 1.5 + 0.5) &&
2040 (int)(r2->rect.width * 1.5 + 0.5) >= r1->rect.width &&
2041 r2->rect.height <= (int)(r1->rect.height * 1.5 + 0.5) &&
2042 (int)(r2->rect.height * 1.5 + 0.5) >= r1->rect.height;
2043}
2044
2045ccv_array_t* ccv_dpm_detect_objects(ccv_dense_matrix_t* a, ccv_dpm_mixture_model_t** _model, int count, ccv_dpm_param_t params)
2046{
2047 int c, i, j, k, x, y;
2048 double scale = pow(2.0, 1.0 / (params.interval + 1.0));
2049 int next = params.interval + 1;
2050 int scale_upto = _ccv_dpm_scale_upto(a, _model, count, params.interval);
2051 if (scale_upto < 0) // image is too small to be interesting
2052 return 0;
2053 ccv_dense_matrix_t** pyr = (ccv_dense_matrix_t**)alloca((scale_upto + next * 2) * sizeof(ccv_dense_matrix_t*))__builtin_alloca ((scale_upto + next * 2) * sizeof(ccv_dense_matrix_t
*))
;
2054 _ccv_dpm_feature_pyramid(a, pyr, scale_upto, params.interval);
2055 ccv_array_t* idx_seq;
2056 ccv_array_t* seq = ccv_array_new(sizeof(ccv_root_comp_t), 64, 0);
2057 ccv_array_t* seq2 = ccv_array_new(sizeof(ccv_root_comp_t), 64, 0);
2058 ccv_array_t* result_seq = ccv_array_new(sizeof(ccv_root_comp_t), 64, 0);
2059 for (c = 0; c < count; c++)
2060 {
2061 ccv_dpm_mixture_model_t* model = _model[c];
2062 double scale_x = 1.0;
2063 double scale_y = 1.0;
2064 for (i = next; i < scale_upto + next * 2; i++)
2065 {
2066 for (j = 0; j < model->count; j++)
2067 {
2068 ccv_dpm_root_classifier_t* root = model->root + j;
2069 ccv_dense_matrix_t* root_feature = 0;
2070 ccv_dense_matrix_t* part_feature[CCV_DPM_PART_MAX(10)];
2071 ccv_dense_matrix_t* dx[CCV_DPM_PART_MAX(10)];
2072 ccv_dense_matrix_t* dy[CCV_DPM_PART_MAX(10)];
2073 _ccv_dpm_compute_score(root, pyr[i], pyr[i - next], &root_feature, part_feature, dx, dy);
2074 int rwh = (root->root.w->rows - 1) / 2, rww = (root->root.w->cols - 1) / 2;
2075 int rwh_1 = root->root.w->rows / 2, rww_1 = root->root.w->cols / 2;
2076 /* these values are designed to make sure works with odd/even number of rows/cols
2077 * of the root classifier:
2078 * suppose the image is 6x6, and the root classifier is 6x6, the scan area should starts
2079 * at (2,2) and end at (2,2), thus, it is capped by (rwh, rww) to (6 - rwh_1 - 1, 6 - rww_1 - 1)
2080 * this computation works for odd root classifier too (i.e. 5x5) */
2081 float* f_ptr = (float*)ccv_get_dense_matrix_cell_by(CCV_32F | CCV_C1, root_feature, rwh, 0, 0)(((CCV_32F | CCV_C1) & CCV_32S) ? (void*)((root_feature)->
data.i32 + ((rwh) * (root_feature)->cols + (0)) * ((CCV_32F
| CCV_C1) & 0xFFF) + (0)) : (((CCV_32F | CCV_C1) & CCV_32F
) ? (void*)((root_feature)->data.f32+ ((rwh) * (root_feature
)->cols + (0)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)) :
(((CCV_32F | CCV_C1) & CCV_64S) ? (void*)((root_feature)
->data.i64+ ((rwh) * (root_feature)->cols + (0)) * ((CCV_32F
| CCV_C1) & 0xFFF) + (0)) : (((CCV_32F | CCV_C1) & CCV_64F
) ? (void*)((root_feature)->data.f64 + ((rwh) * (root_feature
)->cols + (0)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)) :
(void*)((root_feature)->data.u8 + (rwh) * (root_feature)->
step + (0) * ((CCV_32F | CCV_C1) & 0xFFF) + (0))))))
;
2082 for (y = rwh; y < root_feature->rows - rwh_1; y++)
2083 {
2084 for (x = rww; x < root_feature->cols - rww_1; x++)
2085 if (f_ptr[x] + root->beta > params.threshold)
2086 {
2087 ccv_root_comp_t comp;
2088 comp.neighbors = 1;
2089 comp.classification.id = c + 1;
2090 comp.classification.confidence = f_ptr[x] + root->beta;
2091 comp.pnum = root->count;
2092 float drift_x = root->alpha[0],
2093 drift_y = root->alpha[1],
2094 drift_scale = root->alpha[2];
2095 for (k = 0; k < root->count; k++)
2096 {
2097 ccv_dpm_part_classifier_t* part = root->part + k;
2098 comp.part[k].neighbors = 1;
2099 comp.part[k].classification.id = c;
2100 int pww = (part->w->cols - 1) / 2, pwh = (part->w->rows - 1) / 2;
2101 int offy = part->y + pwh - rwh * 2;
2102 int offx = part->x + pww - rww * 2;
2103 int iy = ccv_clamp(y * 2 + offy, pwh, part_feature[k]->rows - part->w->rows + pwh)({ typeof (pwh) _a = (pwh); typeof (part_feature[k]->rows -
part->w->rows + pwh) _b = (part_feature[k]->rows - part
->w->rows + pwh); typeof (y * 2 + offy) _x = (y * 2 + offy
); (_x < _a) ? _a : ((_x > _b) ? _b : _x); })
;
2104 int ix = ccv_clamp(x * 2 + offx, pww, part_feature[k]->cols - part->w->cols + pww)({ typeof (pww) _a = (pww); typeof (part_feature[k]->cols -
part->w->cols + pww) _b = (part_feature[k]->cols - part
->w->cols + pww); typeof (x * 2 + offx) _x = (x * 2 + offx
); (_x < _a) ? _a : ((_x > _b) ? _b : _x); })
;
2105 int ry = ccv_get_dense_matrix_cell_value_by(CCV_32S | CCV_C1, dy[k], iy, ix, 0)(((CCV_32S | CCV_C1) & CCV_32S) ? (dy[k])->data.i32[((
iy) * (dy[k])->cols + (ix)) * ((CCV_32S | CCV_C1) & 0xFFF
) + (0)] : (((CCV_32S | CCV_C1) & CCV_32F) ? (dy[k])->
data.f32[((iy) * (dy[k])->cols + (ix)) * ((CCV_32S | CCV_C1
) & 0xFFF) + (0)] : (((CCV_32S | CCV_C1) & CCV_64S) ?
(dy[k])->data.i64[((iy) * (dy[k])->cols + (ix)) * ((CCV_32S
| CCV_C1) & 0xFFF) + (0)] : (((CCV_32S | CCV_C1) & CCV_64F
) ? (dy[k])->data.f64[((iy) * (dy[k])->cols + (ix)) * (
(CCV_32S | CCV_C1) & 0xFFF) + (0)] : (dy[k])->data.u8[
(iy) * (dy[k])->step + (ix) * ((CCV_32S | CCV_C1) & 0xFFF
) + (0)]))))
;
2106 int rx = ccv_get_dense_matrix_cell_value_by(CCV_32S | CCV_C1, dx[k], iy, ix, 0)(((CCV_32S | CCV_C1) & CCV_32S) ? (dx[k])->data.i32[((
iy) * (dx[k])->cols + (ix)) * ((CCV_32S | CCV_C1) & 0xFFF
) + (0)] : (((CCV_32S | CCV_C1) & CCV_32F) ? (dx[k])->
data.f32[((iy) * (dx[k])->cols + (ix)) * ((CCV_32S | CCV_C1
) & 0xFFF) + (0)] : (((CCV_32S | CCV_C1) & CCV_64S) ?
(dx[k])->data.i64[((iy) * (dx[k])->cols + (ix)) * ((CCV_32S
| CCV_C1) & 0xFFF) + (0)] : (((CCV_32S | CCV_C1) & CCV_64F
) ? (dx[k])->data.f64[((iy) * (dx[k])->cols + (ix)) * (
(CCV_32S | CCV_C1) & 0xFFF) + (0)] : (dx[k])->data.u8[
(iy) * (dx[k])->step + (ix) * ((CCV_32S | CCV_C1) & 0xFFF
) + (0)]))))
;
2107 drift_x += part->alpha[0] * rx + part->alpha[1] * ry;
2108 drift_y += part->alpha[2] * rx + part->alpha[3] * ry;
2109 drift_scale += part->alpha[4] * rx + part->alpha[5] * ry;
2110 ry = iy - ry;
2111 rx = ix - rx;
2112 comp.part[k].rect = ccv_rect((int)((rx - pww) * CCV_DPM_WINDOW_SIZE(8) / 2 * scale_x + 0.5), (int)((ry - pwh) * CCV_DPM_WINDOW_SIZE(8) / 2 * scale_y + 0.5), (int)(part->w->cols * CCV_DPM_WINDOW_SIZE(8) / 2 * scale_x + 0.5), (int)(part->w->rows * CCV_DPM_WINDOW_SIZE(8) / 2 * scale_y + 0.5));
2113 comp.part[k].classification.confidence = -ccv_get_dense_matrix_cell_value_by(CCV_32F | CCV_C1, part_feature[k], iy, ix, 0)(((CCV_32F | CCV_C1) & CCV_32S) ? (part_feature[k])->data
.i32[((iy) * (part_feature[k])->cols + (ix)) * ((CCV_32F |
CCV_C1) & 0xFFF) + (0)] : (((CCV_32F | CCV_C1) & CCV_32F
) ? (part_feature[k])->data.f32[((iy) * (part_feature[k])->
cols + (ix)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)] : (((CCV_32F
| CCV_C1) & CCV_64S) ? (part_feature[k])->data.i64[((
iy) * (part_feature[k])->cols + (ix)) * ((CCV_32F | CCV_C1
) & 0xFFF) + (0)] : (((CCV_32F | CCV_C1) & CCV_64F) ?
(part_feature[k])->data.f64[((iy) * (part_feature[k])->
cols + (ix)) * ((CCV_32F | CCV_C1) & 0xFFF) + (0)] : (part_feature
[k])->data.u8[(iy) * (part_feature[k])->step + (ix) * (
(CCV_32F | CCV_C1) & 0xFFF) + (0)]))))
;
2114 }
2115 comp.rect = ccv_rect((int)((x + drift_x) * CCV_DPM_WINDOW_SIZE(8) * scale_x - rww * CCV_DPM_WINDOW_SIZE(8) * scale_x * (1.0 + drift_scale) + 0.5), (int)((y + drift_y) * CCV_DPM_WINDOW_SIZE(8) * scale_y - rwh * CCV_DPM_WINDOW_SIZE(8) * scale_y * (1.0 + drift_scale) + 0.5), (int)(root->root.w->cols * CCV_DPM_WINDOW_SIZE(8) * scale_x * (1.0 + drift_scale) + 0.5), (int)(root->root.w->rows * CCV_DPM_WINDOW_SIZE(8) * scale_y * (1.0 + drift_scale) + 0.5));
2116 ccv_array_push(seq, &comp);
2117 }
2118 f_ptr += root_feature->cols;
2119 }
2120 for (k = 0; k < root->count; k++)
2121 {
2122 ccv_matrix_free(part_feature[k]);
2123 ccv_matrix_free(dx[k]);
2124 ccv_matrix_free(dy[k]);
2125 }
2126 ccv_matrix_free(root_feature);
2127 }
2128 scale_x *= scale;
2129 scale_y *= scale;
2130 }
2131 /* the following code from OpenCV's haar feature implementation */
2132 if (params.min_neighbors == 0)
2133 {
2134 for (i = 0; i < seq->rnum; i++)
2135 {
2136 ccv_root_comp_t* comp = (ccv_root_comp_t*)ccv_array_get(seq, i)((void*)(((char*)((seq)->data)) + (size_t)(seq)->rsize *
(size_t)(i)))
;
2137 ccv_array_push(result_seq, comp);
2138 }
2139 } else {
2140 idx_seq = 0;
2141 ccv_array_clear(seq2);
2142 // group retrieved rectangles in order to filter out noise
2143 int ncomp = ccv_array_group(seq, &idx_seq, _ccv_is_equal_same_class, 0);
2144 ccv_root_comp_t* comps = (ccv_root_comp_t*)ccmallocmalloc((ncomp + 1) * sizeof(ccv_root_comp_t));
2145 memset(comps, 0, (ncomp + 1) * sizeof(ccv_root_comp_t));
2146
2147 // count number of neighbors
2148 for (i = 0; i < seq->rnum; i++)
2149 {
2150 ccv_root_comp_t r1 = *(ccv_root_comp_t*)ccv_array_get(seq, i)((void*)(((char*)((seq)->data)) + (size_t)(seq)->rsize *
(size_t)(i)))
;
2151 int idx = *(int*)ccv_array_get(idx_seq, i)((void*)(((char*)((idx_seq)->data)) + (size_t)(idx_seq)->
rsize * (size_t)(i)))
;
2152
2153 comps[idx].classification.id = r1.classification.id;
2154 comps[idx].pnum = r1.pnum;
2155 if (r1.classification.confidence > comps[idx].classification.confidence || comps[idx].neighbors == 0)
2156 {
2157 comps[idx].rect = r1.rect;
2158 comps[idx].classification.confidence = r1.classification.confidence;
2159 memcpy(comps[idx].part, r1.part, sizeof(ccv_comp_t) * CCV_DPM_PART_MAX(10));
2160 }
2161
2162 ++comps[idx].neighbors;
2163 }
2164
2165 // calculate average bounding box
2166 for (i = 0; i < ncomp; i++)
2167 {
2168 int n = comps[i].neighbors;
2169 if (n >= params.min_neighbors)
2170 ccv_array_push(seq2, comps + i);
2171 }
2172
2173 // filter out large object rectangles contains small object rectangles
2174 for (i = 0; i < seq2->rnum; i++)
2175 {
2176 ccv_root_comp_t* r2 = (ccv_root_comp_t*)ccv_array_get(seq2, i)((void*)(((char*)((seq2)->data)) + (size_t)(seq2)->rsize
* (size_t)(i)))
;
2177 int distance = (int)(ccv_min(r2->rect.width, r2->rect.height)({ typeof (r2->rect.width) _a = (r2->rect.width); typeof
(r2->rect.height) _b = (r2->rect.height); (_a < _b)
? _a : _b; })
* 0.25 + 0.5);
2178 for (j = 0; j < seq2->rnum; j++)
2179 {
2180 ccv_root_comp_t r1 = *(ccv_root_comp_t*)ccv_array_get(seq2, j)((void*)(((char*)((seq2)->data)) + (size_t)(seq2)->rsize
* (size_t)(j)))
;
2181 if (i != j &&
2182 abs(r1.classification.id) == r2->classification.id &&
2183 r1.rect.x >= r2->rect.x - distance &&
2184 r1.rect.y >= r2->rect.y - distance &&
2185 r1.rect.x + r1.rect.width <= r2->rect.x + r2->rect.width + distance &&
2186 r1.rect.y + r1.rect.height <= r2->rect.y + r2->rect.height + distance &&
2187 // if r1 (the smaller one) is better, mute r2
2188 (r2->classification.confidence <= r1.classification.confidence && r2->neighbors < r1.neighbors))
2189 {
2190 r2->classification.id = -r2->classification.id;
2191 break;
2192 }
2193 }
2194 }
2195
2196 // filter out small object rectangles inside large object rectangles
2197 for (i = 0; i < seq2->rnum; i++)
2198 {
2199 ccv_root_comp_t r1 = *(ccv_root_comp_t*)ccv_array_get(seq2, i)((void*)(((char*)((seq2)->data)) + (size_t)(seq2)->rsize
* (size_t)(i)))
;
2200 if (r1.classification.id > 0)
2201 {
2202 int flag = 1;
2203
2204 for (j = 0; j < seq2->rnum; j++)
2205 {
2206 ccv_root_comp_t r2 = *(ccv_root_comp_t*)ccv_array_get(seq2, j)((void*)(((char*)((seq2)->data)) + (size_t)(seq2)->rsize
* (size_t)(j)))
;
2207 int distance = (int)(ccv_min(r2.rect.width, r2.rect.height)({ typeof (r2.rect.width) _a = (r2.rect.width); typeof (r2.rect
.height) _b = (r2.rect.height); (_a < _b) ? _a : _b; })
* 0.25 + 0.5);
2208
2209 if (i != j &&
2210 r1.classification.id == abs(r2.classification.id) &&
2211 r1.rect.x >= r2.rect.x - distance &&
2212 r1.rect.y >= r2.rect.y - distance &&
2213 r1.rect.x + r1.rect.width <= r2.rect.x + r2.rect.width + distance &&
2214 r1.rect.y + r1.rect.height <= r2.rect.y + r2.rect.height + distance &&
2215 (r2.classification.confidence > r1.classification.confidence || r2.neighbors >= r1.neighbors))
2216 {
2217 flag = 0;
2218 break;
2219 }
2220 }
2221
2222 if (flag)
2223 ccv_array_push(result_seq, &r1);
2224 }
2225 }
2226 ccv_array_free(idx_seq);
2227 ccfreefree(comps);
2228 }
2229 }
2230
2231 for (i = 0; i < scale_upto + next * 2; i++)
2232 ccv_matrix_free(pyr[i]);
2233
2234 ccv_array_free(seq);
2235 ccv_array_free(seq2);
2236
2237 ccv_array_t* result_seq2;
2238 /* the following code from OpenCV's haar feature implementation */
2239 if (params.flags & CCV_DPM_NO_NESTED)
2240 {
2241 result_seq2 = ccv_array_new(sizeof(ccv_root_comp_t), 64, 0);
2242 idx_seq = 0;
2243 // group retrieved rectangles in order to filter out noise
2244 int ncomp = ccv_array_group(result_seq, &idx_seq, _ccv_is_equal, 0);
2245 ccv_root_comp_t* comps = (ccv_root_comp_t*)ccmallocmalloc((ncomp + 1) * sizeof(ccv_root_comp_t));
2246 memset(comps, 0, (ncomp + 1) * sizeof(ccv_root_comp_t));
2247
2248 // count number of neighbors
2249 for(i = 0; i < result_seq->rnum; i++)
2250 {
2251 ccv_root_comp_t r1 = *(ccv_root_comp_t*)ccv_array_get(result_seq, i)((void*)(((char*)((result_seq)->data)) + (size_t)(result_seq
)->rsize * (size_t)(i)))
;
2252 int idx = *(int*)ccv_array_get(idx_seq, i)((void*)(((char*)((idx_seq)->data)) + (size_t)(idx_seq)->
rsize * (size_t)(i)))
;
2253
2254 if (comps[idx].neighbors == 0 || comps[idx].classification.confidence < r1.classification.confidence)
2255 {
2256 comps[idx].classification.confidence = r1.classification.confidence;
2257 comps[idx].neighbors = 1;
2258 comps[idx].rect = r1.rect;
2259 comps[idx].classification.id = r1.classification.id;
2260 comps[idx].pnum = r1.pnum;
2261 memcpy(comps[idx].part, r1.part, sizeof(ccv_comp_t) * CCV_DPM_PART_MAX(10));
2262 }
2263 }
2264
2265 // calculate average bounding box
2266 for(i = 0; i < ncomp; i++)
2267 if(comps[i].neighbors)
2268 ccv_array_push(result_seq2, &comps[i]);
2269
2270 ccv_array_free(result_seq);
2271 ccfreefree(comps);
2272 } else {
2273 result_seq2 = result_seq;
2274 }
2275
2276 return result_seq2;
2277}
2278
2279ccv_dpm_mixture_model_t* ccv_dpm_read_mixture_model(const char* directory)
2280{
2281 FILE* r = fopen(directory, "r");
2282 if (r
0.1
'r' is not equal to null
== 0)
1
Taking false branch
2283 return 0;
2284 int count;
2285 char flag;
2286 fscanf(r, "%c", &flag);
2287 assert(flag == '.')((void) sizeof ((flag == '.') ? 1 : 0), __extension__ ({ if (
flag == '.') ; else __assert_fail ("flag == '.'", "ccv_dpm.c"
, 2287, __extension__ __PRETTY_FUNCTION__); }))
;
2
Assuming the condition is true
3
Taking true branch
2288 fscanf(r, "%d", &count);
2289 ccv_dpm_root_classifier_t* root_classifier = (ccv_dpm_root_classifier_t*)ccmallocmalloc(sizeof(ccv_dpm_root_classifier_t) * count);
2290 memset(root_classifier, 0, sizeof(ccv_dpm_root_classifier_t) * count);
2291 int i, j, k;
2292 size_t size = sizeof(ccv_dpm_mixture_model_t) + sizeof(ccv_dpm_root_classifier_t) * count;
2293 /* the format is easy, but I tried to copy all data into one memory region */
2294 for (i = 0; i < count; i++)
4
Assuming 'i' is < 'count'
5
Loop condition is true. Entering loop body
2295 {
2296 int rows, cols;
2297 fscanf(r, "%d %d", &rows, &cols);
6
Assuming this stream operation fails
2298 fscanf(r, "%f %f %f %f", &root_classifier[i].beta, &root_classifier[i].alpha[0], &root_classifier[i].alpha[1], &root_classifier[i].alpha[2]);
7
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior
2299 root_classifier[i].root.w = ccv_dense_matrix_new(rows, cols, CCV_32F | 31, ccmallocmalloc(ccv_compute_dense_matrix_size(rows, cols, CCV_32F | 31)(((sizeof(ccv_dense_matrix_t) + 63) & -64) + (((cols) * _ccv_get_data_type_size
[((CCV_32F | 31) & 0xFF000) >> 12] * ((CCV_32F | 31
) & 0xFFF) + 3) & -4) * (rows))
), 0);
2300 size += ccv_compute_dense_matrix_size(rows, cols, CCV_32F | 31)(((sizeof(ccv_dense_matrix_t) + 63) & -64) + (((cols) * _ccv_get_data_type_size
[((CCV_32F | 31) & 0xFF000) >> 12] * ((CCV_32F | 31
) & 0xFFF) + 3) & -4) * (rows))
;
2301 for (j = 0; j < rows * cols * 31; j++)
2302 fscanf(r, "%f", &root_classifier[i].root.w->data.f32[j]);
2303 ccv_make_matrix_immutable(root_classifier[i].root.w);
2304 fscanf(r, "%d", &root_classifier[i].count);
2305 ccv_dpm_part_classifier_t* part_classifier = (ccv_dpm_part_classifier_t*)ccmallocmalloc(sizeof(ccv_dpm_part_classifier_t) * root_classifier[i].count);
2306 size += sizeof(ccv_dpm_part_classifier_t) * root_classifier[i].count;
2307 for (j = 0; j < root_classifier[i].count; j++)
2308 {
2309 fscanf(r, "%d %d %d", &part_classifier[j].x, &part_classifier[j].y, &part_classifier[j].z);
2310 fscanf(r, "%lf %lf %lf %lf", &part_classifier[j].dx, &part_classifier[j].dy, &part_classifier[j].dxx, &part_classifier[j].dyy);
2311 fscanf(r, "%f %f %f %f %f %f", &part_classifier[j].alpha[0], &part_classifier[j].alpha[1], &part_classifier[j].alpha[2], &part_classifier[j].alpha[3], &part_classifier[j].alpha[4], &part_classifier[j].alpha[5]);
2312 fscanf(r, "%d %d %d", &rows, &cols, &part_classifier[j].counterpart);
2313 part_classifier[j].w = ccv_dense_matrix_new(rows, cols, CCV_32F | 31, ccmallocmalloc(ccv_compute_dense_matrix_size(rows, cols, CCV_32F | 31)(((sizeof(ccv_dense_matrix_t) + 63) & -64) + (((cols) * _ccv_get_data_type_size
[((CCV_32F | 31) & 0xFF000) >> 12] * ((CCV_32F | 31
) & 0xFFF) + 3) & -4) * (rows))
), 0);
2314 size += ccv_compute_dense_matrix_size(rows, cols, CCV_32F | 31)(((sizeof(ccv_dense_matrix_t) + 63) & -64) + (((cols) * _ccv_get_data_type_size
[((CCV_32F | 31) & 0xFF000) >> 12] * ((CCV_32F | 31
) & 0xFFF) + 3) & -4) * (rows))
;
2315 for (k = 0; k < rows * cols * 31; k++)
2316 fscanf(r, "%f", &part_classifier[j].w->data.f32[k]);
2317 ccv_make_matrix_immutable(part_classifier[j].w);
2318 }
2319 root_classifier[i].part = part_classifier;
2320 }
2321 fclose(r);
2322 unsigned char* m = (unsigned char*)ccmallocmalloc(size);
2323 ccv_dpm_mixture_model_t* model = (ccv_dpm_mixture_model_t*)m;
2324 m += sizeof(ccv_dpm_mixture_model_t);
2325 model->count = count;
2326 model->root = (ccv_dpm_root_classifier_t*)m;
2327 m += sizeof(ccv_dpm_root_classifier_t) * model->count;
2328 memcpy(model->root, root_classifier, sizeof(ccv_dpm_root_classifier_t) * model->count);
2329 ccfreefree(root_classifier);
2330 for (i = 0; i < model->count; i++)
2331 {
2332 ccv_dpm_part_classifier_t* part_classifier = model->root[i].part;
2333 model->root[i].part = (ccv_dpm_part_classifier_t*)m;
2334 m += sizeof(ccv_dpm_part_classifier_t) * model->root[i].count;
2335 memcpy(model->root[i].part, part_classifier, sizeof(ccv_dpm_part_classifier_t) * model->root[i].count);
2336 ccfreefree(part_classifier);
2337 }
2338 for (i = 0; i < model->count; i++)
2339 {
2340 ccv_dense_matrix_t* w = model->root[i].root.w;
2341 model->root[i].root.w = (ccv_dense_matrix_t*)m;
2342 m += ccv_compute_dense_matrix_size(w->rows, w->cols, w->type)(((sizeof(ccv_dense_matrix_t) + 63) & -64) + (((w->cols
) * _ccv_get_data_type_size[((w->type) & 0xFF000) >>
12] * ((w->type) & 0xFFF) + 3) & -4) * (w->rows
))
;
2343 memcpy(model->root[i].root.w, w, ccv_compute_dense_matrix_size(w->rows, w->cols, w->type)(((sizeof(ccv_dense_matrix_t) + 63) & -64) + (((w->cols
) * _ccv_get_data_type_size[((w->type) & 0xFF000) >>
12] * ((w->type) & 0xFFF) + 3) & -4) * (w->rows
))
);
2344 model->root[i].root.w->data.u8 = (unsigned char*)(model->root[i].root.w + 1);
2345 ccfreefree(w);
2346 for (j = 0; j < model->root[i].count; j++)
2347 {
2348 w = model->root[i].part[j].w;
2349 model->root[i].part[j].w = (ccv_dense_matrix_t*)m;
2350 m += ccv_compute_dense_matrix_size(w->rows, w->cols, w->type)(((sizeof(ccv_dense_matrix_t) + 63) & -64) + (((w->cols
) * _ccv_get_data_type_size[((w->type) & 0xFF000) >>
12] * ((w->type) & 0xFFF) + 3) & -4) * (w->rows
))
;
2351 memcpy(model->root[i].part[j].w, w, ccv_compute_dense_matrix_size(w->rows, w->cols, w->type)(((sizeof(ccv_dense_matrix_t) + 63) & -64) + (((w->cols
) * _ccv_get_data_type_size[((w->type) & 0xFF000) >>
12] * ((w->type) & 0xFFF) + 3) & -4) * (w->rows
))
);
2352 model->root[i].part[j].w->data.u8 = (unsigned char*)(model->root[i].part[j].w + 1);
2353 ccfreefree(w);
2354 }
2355 }
2356 return model;
2357}
2358
2359void ccv_dpm_mixture_model_free(ccv_dpm_mixture_model_t* model)
2360{
2361 ccfreefree(model);
2362}