Bug Summary

File:ccv_dpm.c
Warning:line 1764, column 10
Although the value stored to 't' is used in the enclosing expression, the value is never actually read from 't'

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-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -menable-no-infs -menable-no-nans -fapprox-func -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +sse2 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/liu/buildslave/linux-x64-runtests/build/lib -resource-dir /usr/local/lib/clang/14.0.0 -I . -I /usr/local/cuda/include -D HAVE_CBLAS -D HAVE_LIBPNG -D HAVE_LIBJPEG -D HAVE_FFTW3 -D HAVE_PTHREAD -D HAVE_LIBLINEAR -D HAVE_TESSERACT -D HAVE_AVCODEC -D HAVE_AVFORMAT -D HAVE_AVUTIL -D HAVE_SWSCALE -D USE_DISPATCH -D HAVE_SSE2 -D HAVE_GSL -D HAVE_CUDA -D HAVE_CUDNN -D HAVE_NCCL -D USE_SYSTEM_CUB -I /usr/local/include -internal-isystem /usr/local/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -fdebug-compilation-dir=/home/liu/buildslave/linux-x64-runtests/build/lib -ferror-limit 19 -fblocks -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/liu/buildslave/public_html/analyze/2022-06-22-151334-490440-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, (int)(pyr[next]->rows / pow(scale, i)), (int)(pyr[next]->cols / pow(scale, i)), 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, rows * CCV_DPM_WINDOW_SIZE(8), cols * CCV_DPM_WINDOW_SIZE(8), 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;
Although the value stored to 't' is used in the enclosing expression, the value is never actually read from 't'
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)
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__); }))
;
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++)
2295 {
2296 int rows, cols;
2297 fscanf(r, "%d %d", &rows, &cols);
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]);
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) + 15) & -16) + (((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) + 15) & -16) + (((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) + 15) & -16) + (((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) + 15) & -16) + (((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) + 15) & -16) + (((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) + 15) & -16) + (((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) + 15) & -16) + (((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) + 15) & -16) + (((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}