forked from liuliu/ccv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathccv.h
788 lines (666 loc) · 24.1 KB
/
ccv.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
/**********************************************************
* C-based/Cached/Core Computer Vision Library
* Liu Liu, 2010-02-01
**********************************************************/
#ifndef GUARD_ccv_h
#define GUARD_ccv_h
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
#include <math.h>
#ifdef HAVE_SSE2
#include <xmmintrin.h>
#endif
#include <assert.h>
#include <alloca.h>
#define CCV_PI (3.141592653589793)
#define ccmalloc malloc
#define ccrealloc realloc
#define ccfree free
enum {
CCV_8U = 0x0100,
CCV_32S = 0x0200,
CCV_32F = 0x0400,
CCV_64S = 0x0800,
CCV_64F = 0x1000,
};
enum {
CCV_C1 = 0x01,
CCV_C2 = 0x02,
CCV_C3 = 0x03,
CCV_C4 = 0x04,
};
static const int _ccv_get_data_type_size[] = { -1, 1, 4, -1, 4, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, 8 };
#define CCV_GET_DATA_TYPE(x) ((x) & 0xFF00)
#define CCV_GET_DATA_TYPE_SIZE(x) _ccv_get_data_type_size[CCV_GET_DATA_TYPE(x) >> 8]
#define CCV_MAX_CHANNEL (0xFF)
#define CCV_GET_CHANNEL(x) ((x) & 0xFF)
#define CCV_ALL_DATA_TYPE (CCV_8U | CCV_32S | CCV_32F | CCV_64S | CCV_64F)
enum {
CCV_MATRIX_DENSE = 0x010000,
CCV_MATRIX_SPARSE = 0x020000,
CCV_MATRIX_CSR = 0x040000,
CCV_MATRIX_CSC = 0x080000,
};
enum {
CCV_GARBAGE = 0x80000000, // matrix is in cache (not used by any functions)
CCV_REUSABLE = 0x40000000, // matrix can be recycled
CCV_UNMANAGED = 0x20000000, // matrix is allocated by user, therefore, cannot be freed by ccv_matrix_free/ccv_matrix_free_immediately
};
typedef union {
unsigned char* u8;
int* i32;
float* f32;
int64_t* i64;
double* f64;
} ccv_matrix_cell_t;
typedef struct {
int type;
uint64_t sig;
int refcount;
int rows;
int cols;
int step;
union {
unsigned char u8;
int i32;
float f32;
int64_t i64;
double f64;
void* p;
} tag;
ccv_matrix_cell_t data;
} ccv_dense_matrix_t;
enum {
CCV_SPARSE_VECTOR = 0x00100000,
CCV_DENSE_VECTOR = 0x00200000,
};
typedef struct ccv_dense_vector_t {
int step;
int length;
int index;
int prime;
int load_factor;
ccv_matrix_cell_t data;
int* indice;
struct ccv_dense_vector_t* next;
} ccv_dense_vector_t;
enum {
CCV_SPARSE_ROW_MAJOR = 0x00,
CCV_SPARSE_COL_MAJOR = 0x01,
};
typedef struct {
int type;
uint64_t sig;
int refcount;
int rows;
int cols;
int major;
int prime;
int load_factor;
union {
unsigned char chr;
int i;
float fl;
int64_t l;
double db;
} tag;
ccv_dense_vector_t* vector;
} ccv_sparse_matrix_t;
extern int _ccv_get_sparse_prime[];
#define CCV_GET_SPARSE_PRIME(x) _ccv_get_sparse_prime[(x)]
typedef void ccv_matrix_t;
/* the explicit cache mechanism ccv_cache.c */
/* the new cache is radix tree based, but has a strict memory usage upper bound
* so that you don't have to explicitly call ccv_drain_cache() every time */
typedef void(*ccv_cache_index_free_f)(void*);
typedef union {
struct {
uint64_t bitmap;
uint64_t set;
uint64_t age;
} branch;
struct {
uint64_t sign;
uint64_t off;
uint64_t type;
} terminal;
} ccv_cache_index_t;
typedef struct {
ccv_cache_index_t origin;
uint32_t rnum;
uint32_t age;
size_t up;
size_t size;
ccv_cache_index_free_f ffree[16];
} ccv_cache_t;
/* I made it as generic as possible */
void ccv_cache_init(ccv_cache_t* cache, size_t up, int cache_types, ccv_cache_index_free_f ffree, ...);
void* ccv_cache_get(ccv_cache_t* cache, uint64_t sign, uint8_t* type);
int ccv_cache_put(ccv_cache_t* cache, uint64_t sign, void* x, uint32_t size, uint8_t type);
void* ccv_cache_out(ccv_cache_t* cache, uint64_t sign, uint8_t* type);
int ccv_cache_delete(ccv_cache_t* cache, uint64_t sign);
void ccv_cache_cleanup(ccv_cache_t* cache);
void ccv_cache_close(ccv_cache_t* cache);
/* deprecated methods, often these implemented in another way and no longer suitable for newer computer architecture */
/* 0 */
typedef struct {
int type;
uint64_t sig;
int refcount;
int rows;
int cols;
int nnz;
union {
unsigned char chr;
int i;
float fl;
int64_t l;
double db;
} tag;
int* index;
int* offset;
ccv_matrix_cell_t data;
} ccv_compressed_sparse_matrix_t;
#define ccv_clamp(x, a, b) (((x) < (a)) ? (a) : (((x) > (b)) ? (b) : (x)))
#define ccv_min(a, b) (((a) < (b)) ? (a) : (b))
#define ccv_max(a, b) (((a) > (b)) ? (a) : (b))
/* matrix memory operations ccv_memory.c */
#define ccv_compute_dense_matrix_size(rows, cols, type) (sizeof(ccv_dense_matrix_t) + (((cols) * CCV_GET_DATA_TYPE_SIZE(type) * CCV_GET_CHANNEL(type) + 3) & -4) * (rows))
ccv_dense_matrix_t* __attribute__((warn_unused_result)) ccv_dense_matrix_renew(ccv_dense_matrix_t* x, int rows, int cols, int types, int prefer_type, uint64_t sig);
ccv_dense_matrix_t* __attribute__((warn_unused_result)) ccv_dense_matrix_new(int rows, int cols, int type, void* data, uint64_t sig);
ccv_dense_matrix_t ccv_dense_matrix(int rows, int cols, int type, void* data, uint64_t sig);
void ccv_make_matrix_mutable(ccv_matrix_t* mat);
void ccv_make_matrix_immutable(ccv_matrix_t* mat);
ccv_sparse_matrix_t* __attribute__((warn_unused_result)) ccv_sparse_matrix_new(int rows, int cols, int type, int major, uint64_t sig);
void ccv_matrix_free_immediately(ccv_matrix_t* mat);
void ccv_matrix_free(ccv_matrix_t* mat);
uint64_t ccv_cache_generate_signature(const char* msg, int len, uint64_t sig_start, ...);
#define CCV_DEFAULT_CACHE_SIZE (1024 * 1024 * 64)
void ccv_drain_cache(void);
void ccv_disable_cache(void);
void ccv_enable_default_cache(void);
void ccv_enable_cache(size_t size);
#define ccv_get_dense_matrix_cell_by(type, x, row, col, ch) \
(((type) & CCV_32S) ? (void*)((x)->data.i32 + ((row) * (x)->cols + (col)) * CCV_GET_CHANNEL(type) + (ch)) : \
(((type) & CCV_32F) ? (void*)((x)->data.f32+ ((row) * (x)->cols + (col)) * CCV_GET_CHANNEL(type) + (ch)) : \
(((type) & CCV_64S) ? (void*)((x)->data.i64+ ((row) * (x)->cols + (col)) * CCV_GET_CHANNEL(type) + (ch)) : \
(((type) & CCV_64F) ? (void*)((x)->data.f64 + ((row) * (x)->cols + (col)) * CCV_GET_CHANNEL(type) + (ch)) : \
(void*)((x)->data.u8 + (row) * (x)->step + (col) * CCV_GET_CHANNEL(type) + (ch))))))
#define ccv_get_dense_matrix_cell(x, row, col, ch) ccv_get_dense_matrix_cell_by((x)->type, x, row, col, ch)
/* this is for simplicity in code, I am sick of x->data.f64[i * x->cols + j] stuff, this is clearer, and compiler
* can optimize away the if structures */
#define ccv_get_dense_matrix_cell_value_by(type, x, row, col, ch) \
(((type) & CCV_32S) ? (x)->data.i32[((row) * (x)->cols + (col)) * CCV_GET_CHANNEL(type) + (ch)] : \
(((type) & CCV_32F) ? (x)->data.f32[((row) * (x)->cols + (col)) * CCV_GET_CHANNEL(type) + (ch)] : \
(((type) & CCV_64S) ? (x)->data.i64[((row) * (x)->cols + (col)) * CCV_GET_CHANNEL(type) + (ch)] : \
(((type) & CCV_64F) ? (x)->data.f64[((row) * (x)->cols + (col)) * CCV_GET_CHANNEL(type) + (ch)] : \
(x)->data.u8[(row) * (x)->step + (col) * CCV_GET_CHANNEL(type) + (ch)]))))
#define ccv_get_dense_matrix_cell_value(x, row, col, ch) ccv_get_dense_matrix_cell_value_by((x)->type, x, row, col, ch)
#define ccv_get_value(type, ptr, i) \
(((type) & CCV_32S) ? ((int*)(ptr))[(i)] : \
(((type) & CCV_32F) ? ((float*)(ptr))[(i)] : \
(((type) & CCV_64S) ? ((int64_t*)(ptr))[(i)] : \
(((type) & CCV_64F) ? ((double*)(ptr))[(i)] : \
((unsigned char*)(ptr))[(i)]))))
#define ccv_set_value(type, ptr, i, value, factor) switch (CCV_GET_DATA_TYPE((type))) { \
case CCV_32S: ((int*)(ptr))[(i)] = (int)(value) >> factor; break; \
case CCV_32F: ((float*)(ptr))[(i)] = (float)value; break; \
case CCV_64S: ((int64_t*)(ptr))[(i)] = (int64_t)(value) >> factor; break; \
case CCV_64F: ((double*)(ptr))[(i)] = (double)value; break; \
default: ((unsigned char*)(ptr))[(i)] = ccv_clamp((int)(value) >> factor, 0, 255); }
/* basic io ccv_io.c */
enum {
CCV_IO_GRAY = 0x100,
CCV_IO_RGB_COLOR = 0x300,
};
enum {
// read self-describe in-memory data
CCV_IO_ANY_STREAM = 0x010,
CCV_IO_PLAIN_STREAM = 0x011,
CCV_IO_DEFLATE_STREAM = 0x012,
CCV_IO_JPEG_STREAM = 0x013,
CCV_IO_PNG_STREAM = 0x014,
// read self-describe on-disk data
CCV_IO_ANY_FILE = 0x020,
CCV_IO_BMP_FILE = 0x021,
CCV_IO_JPEG_FILE = 0x022,
CCV_IO_PNG_FILE = 0x023,
CCV_IO_BINARY_FILE = 0x024,
// read not-self-describe in-memory data (a.k.a. raw data)
// you need to specify rows, cols, or scanline for these data
CCV_IO_RGB_RAW = 0x031,
CCV_IO_RGBA_RAW = 0x032,
CCV_IO_ARGB_RAW = 0x033,
CCV_IO_BGR_RAW = 0x034,
CCV_IO_BGRA_RAW = 0x035,
CCV_IO_ABGR_RAW = 0x036,
CCV_IO_GRAY_RAW = 0x037,
};
enum {
CCV_IO_FINAL = 0x00,
CCV_IO_CONTINUE,
CCV_IO_ERROR,
CCV_IO_ATTEMPTED,
};
int ccv_read_impl(const char* in, ccv_dense_matrix_t** x, int type, int rows, int cols, int scanline);
#define ccv_read_n(in, x, type, rows, cols, scanline, ...) \
ccv_read_impl(in, x, type, rows, cols, scanline)
#define ccv_read(in, x, type, ...) \
ccv_read_n(in, x, type, ##__VA_ARGS__, 0, 0, 0)
// this is a way to implement function-signature based dispatch, you can call either
// ccv_read(in, x, type) or ccv_read(in, x, type, rows, cols, scanline)
// notice that you can implement this with va_* functions, but that is not type-safe
int ccv_write(ccv_dense_matrix_t* mat, char* out, int* len, int type, void* conf);
/* basic algebra algorithms ccv_algebra.c */
double ccv_trace(ccv_matrix_t* mat);
enum {
CCV_L2_NORM = 0x01, // |dx| + |dy|
CCV_L1_NORM = 0x02, // sqrt(dx^2 + dy^2)
CCV_GSEDT = 0x04, // Generalized Squared Euclidean Distance Transform:
// a * dx + b * dy + c * dx^2 + d * dy^2, when combined with CCV_L1_NORM:
// a * |dx| + b * |dy| + c * dx^2 + d * dy^2
CCV_NEGATIVE = 0x08, // negative distance computation (from positive (min) to negative (max))
CCV_POSITIVE = 0x00, // positive distance computation (the default)
};
enum {
CCV_NO_PADDING = 0x00,
CCV_PADDING_ZERO = 0x01,
CCV_PADDING_EXTEND = 0x02,
CCV_PADDING_MIRROR = 0x04,
};
enum {
CCV_SIGNED = 0x00,
CCV_UNSIGNED = 0x01,
};
double ccv_norm(ccv_matrix_t* mat, int type);
double ccv_normalize(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int flag);
void ccv_sat(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int padding_pattern);
double ccv_dot(ccv_matrix_t* a, ccv_matrix_t* b);
double ccv_sum(ccv_matrix_t* mat, int flag);
void ccv_multiply(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** c, int type);
void ccv_subtract(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** c, int type);
enum {
CCV_A_TRANSPOSE = 0x01,
CCV_B_TRANSPOSE = 0X02,
CCV_C_TRANSPOSE = 0X04,
};
void ccv_gemm(ccv_matrix_t* a, ccv_matrix_t* b, double alpha, ccv_matrix_t* c, double beta, int transpose, ccv_matrix_t** d, int type);
/* matrix build blocks / utility functions ccv_util.c */
ccv_dense_matrix_t* ccv_get_dense_matrix(ccv_matrix_t* mat);
ccv_sparse_matrix_t* ccv_get_sparse_matrix(ccv_matrix_t* mat);
ccv_dense_vector_t* ccv_get_sparse_matrix_vector(ccv_sparse_matrix_t* mat, int index);
ccv_matrix_cell_t ccv_get_sparse_matrix_cell(ccv_sparse_matrix_t* mat, int row, int col);
void ccv_set_sparse_matrix_cell(ccv_sparse_matrix_t* mat, int row, int col, void* data);
void ccv_compress_sparse_matrix(ccv_sparse_matrix_t* mat, ccv_compressed_sparse_matrix_t** csm);
void ccv_decompress_sparse_matrix(ccv_compressed_sparse_matrix_t* csm, ccv_sparse_matrix_t** smt);
void ccv_move(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int y, int x);
int ccv_matrix_eq(ccv_matrix_t* a, ccv_matrix_t* b);
void ccv_slice(ccv_matrix_t* a, ccv_matrix_t** b, int type, int y, int x, int rows, int cols);
void ccv_visualize(ccv_matrix_t* a, ccv_dense_matrix_t** b, int type);
void ccv_flatten(ccv_matrix_t* a, ccv_matrix_t** b, int type, int flag);
void ccv_zero(ccv_matrix_t* mat);
void ccv_shift(ccv_matrix_t* a, ccv_matrix_t** b, int type, int lr, int rr);
int ccv_any_nan(ccv_matrix_t *a);
/* basic data structures ccv_util.c */
typedef struct {
int width;
int height;
} ccv_size_t;
inline static ccv_size_t ccv_size(int width, int height)
{
ccv_size_t size;
size.width = width;
size.height = height;
return size;
}
inline static int ccv_size_is_zero(ccv_size_t size)
{
return size.width == 0 && size.height == 0;
}
typedef struct {
int x;
int y;
int width;
int height;
} ccv_rect_t;
inline static ccv_rect_t ccv_rect(int x, int y, int width, int height)
{
ccv_rect_t rect;
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
return rect;
}
inline static int ccv_rect_is_zero(ccv_rect_t rect)
{
return rect.x == 0 && rect.y == 0 && rect.width == 0 && rect.height == 0;
}
typedef struct {
int type;
uint64_t sig;
int refcount;
int rnum;
int size;
int rsize;
void* data;
} ccv_array_t;
ccv_array_t* __attribute__((warn_unused_result)) ccv_array_new(int rsize, int rnum, uint64_t sig);
void ccv_array_push(ccv_array_t* array, void* r);
typedef int(*ccv_array_group_f)(const void*, const void*, void*);
int ccv_array_group(ccv_array_t* array, ccv_array_t** index, ccv_array_group_f gfunc, void* data);
void ccv_make_array_immutable(ccv_array_t* array);
void ccv_make_array_mutable(ccv_array_t* array);
void ccv_array_zero(ccv_array_t* array);
void ccv_array_clear(ccv_array_t* array);
void ccv_array_free_immediately(ccv_array_t* array);
void ccv_array_free(ccv_array_t* array);
#define ccv_array_get(a, i) (((char*)((a)->data)) + (a)->rsize * (i))
typedef struct {
int x, y;
} ccv_point_t;
inline static ccv_point_t ccv_point(int x, int y)
{
ccv_point_t point;
point.x = x;
point.y = y;
return point;
}
typedef struct {
ccv_rect_t rect;
int size;
ccv_array_t* set;
long m10, m01, m11, m20, m02;
} ccv_contour_t;
ccv_contour_t* ccv_contour_new(int set);
void ccv_contour_push(ccv_contour_t* contour, ccv_point_t point);
void ccv_contour_free(ccv_contour_t* contour);
/* numerical algorithms ccv_numeric.c */
/* clarification about algebra and numerical algorithms:
* when using the word "algebra", I assume the operation is well established in Mathematic sense
* and can be calculated with a straight-forward, finite sequence of operation. The "numerical"
* in other word, refer to a class of algorithm that can only approximate/or iteratively found the
* solution. Thus, "invert" would be classified as numerical because of the sense that in some case,
* it can only be "approximate" (in least-square sense), so to "solve". */
void ccv_invert(ccv_matrix_t* a, ccv_matrix_t** b, int type);
void ccv_solve(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** d, int type);
void ccv_eigen(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** d, int type);
typedef struct {
double interp;
double extrap;
int max_iter;
double ratio;
double rho;
double sig;
} ccv_minimize_param_t;
typedef int(*ccv_minimize_f)(const ccv_dense_matrix_t* x, double* f, ccv_dense_matrix_t* df, void*);
void ccv_minimize(ccv_dense_matrix_t* x, int length, double red, ccv_minimize_f func, ccv_minimize_param_t params, void* data);
void ccv_filter(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b, ccv_dense_matrix_t** d, int type, int padding_pattern);
typedef double(*ccv_filter_kernel_f)(double x, double y, void*);
void ccv_filter_kernel(ccv_dense_matrix_t* x, ccv_filter_kernel_f func, void* data);
/* modern numerical algorithms */
void ccv_distance_transform(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, ccv_dense_matrix_t** x, int x_type, ccv_dense_matrix_t** y, int y_type, double dx, double dy, double dxx, double dyy, int flag);
void ccv_sparse_coding(ccv_matrix_t* x, int k, ccv_matrix_t** A, int typeA, ccv_matrix_t** y, int typey);
void ccv_compressive_sensing_reconstruct(ccv_matrix_t* a, ccv_matrix_t* x, ccv_matrix_t** y, int type);
/* basic computer vision algorithms / or build blocks ccv_basic.c */
void ccv_sobel(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int dx, int dy);
void ccv_gradient(ccv_dense_matrix_t* a, ccv_dense_matrix_t** theta, int ttype, ccv_dense_matrix_t** m, int mtype, int dx, int dy);
enum {
CCV_FLIP_X = 0x01,
CCV_FLIP_Y = 0x02,
};
void ccv_flip(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int btype, int type);
void ccv_blur(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, double sigma);
enum {
CCV_RGB_TO_YUV = 0x01,
};
void ccv_color_transform(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int flag);
/* resample algorithms ccv_resample.c */
enum {
CCV_INTER_AREA = 0x01,
CCV_INTER_LINEAR = 0X02,
CCV_INTER_CUBIC = 0X03,
CCV_INTER_LANCZOS = 0X04,
};
void ccv_resample(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int btype, int rows, int cols, int type);
void ccv_sample_down(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y);
void ccv_sample_up(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y);
/* classic computer vision algorithms ccv_classic.c */
void ccv_hog(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int b_type, int sbin, int size);
void ccv_canny(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int size, double low_thresh, double high_thresh);
void ccv_close_outline(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type);
/* range: exclusive, return value: inclusive (i.e., threshold = 5, 0~5 is background, 6~range-1 is foreground */
int ccv_otsu(ccv_dense_matrix_t* a, double* outvar, int range);
/* modern computer vision algorithms */
/* SIFT, DAISY, SWT, MSER, DPM, BBF, SGF, SSD, FAST */
/* daisy related methods */
typedef struct {
double radius;
int rad_q_no;
int th_q_no;
int hist_th_q_no;
float normalize_threshold;
int normalize_method;
} ccv_daisy_param_t;
enum {
CCV_DAISY_NORMAL_PARTIAL = 0x01,
CCV_DAISY_NORMAL_FULL = 0x02,
CCV_DAISY_NORMAL_SIFT = 0x03,
};
void ccv_daisy(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, ccv_daisy_param_t params);
/* sift related methods */
typedef struct {
float x, y;
int octave;
int level;
union {
struct {
double a, b;
double c, d;
} affine;
struct {
double scale;
double angle;
} regular;
};
} ccv_keypoint_t;
typedef struct {
int up2x;
int noctaves;
int nlevels;
float edge_threshold;
float peak_threshold;
float norm_threshold;
} ccv_sift_param_t;
void ccv_sift(ccv_dense_matrix_t* a, ccv_array_t** keypoints, ccv_dense_matrix_t** desc, int type, ccv_sift_param_t params);
/* mser related method */
typedef struct {
/* parameters for MSER */
int delta;
int min_area; /* default: 60 */
int direction; /* default: 0, 0 for both, -1 for bright to dark, 1 for dark to bright */
int max_area;
double max_variance;
double min_diversity;
int range; /* from 0 to range, inclusive */
/* parameters for MSCR */
double area_threshold; /* default: 1.01 */
double min_margin; /* default: 0.003 */
int max_evolution;
double edge_blur_sigma; /* default: 1.0 */
} ccv_mser_param_t;
typedef struct {
ccv_rect_t rect;
int size;
long m10, m01, m11, m20, m02;
ccv_point_t keypoint;
} ccv_mser_keypoint_t;
enum {
CCV_BRIGHT_TO_DARK = -1,
CCV_DARK_TO_BRIGHT = 1,
};
ccv_array_t* __attribute__((warn_unused_result)) ccv_mser(ccv_dense_matrix_t* a, ccv_dense_matrix_t* h, ccv_dense_matrix_t** b, int type, ccv_mser_param_t params);
/* swt related method: stroke width transform is relatively new, typically used in text detection */
typedef struct {
int interval; // for scale invariant option
int min_neighbors; // minimal neighbors to make a detection valid, this is for scale-invariant version
int scale_invariant; // enable scale invariant swt (to scale to different sizes and then combine the results)
int direction;
double same_word_thresh[2]; // overlapping more than 0.1 of the bigger one (0), and 0.9 of the smaller one (1)
/* canny parameters */
int size;
int low_thresh;
int high_thresh;
/* geometry filtering parameters */
int max_height;
int min_height;
int min_area;
int letter_occlude_thresh;
double aspect_ratio;
double std_ratio;
/* grouping parameters */
double thickness_ratio;
double height_ratio;
int intensity_thresh;
double distance_ratio;
double intersect_ratio;
double elongate_ratio;
int letter_thresh;
/* break textline into words */
int breakdown;
double breakdown_ratio;
} ccv_swt_param_t;
void ccv_swt(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, ccv_swt_param_t params);
ccv_array_t* __attribute__((warn_unused_result)) ccv_swt_detect_words(ccv_dense_matrix_t* a, ccv_swt_param_t params);
/* I'd like to include Deformable Part Models as a general object detection method in here
* The difference between BBF and DPM:
* ~ BBF is for rigid object detection: banners, box, faces etc.
* ~ DPM is more generalized, can detect people, car, bike (larger inner-class difference) etc.
* ~ BBF is blazing fast (few milliseconds), DPM is relatively slow (around 1 seconds or so) */
#define CCV_DPM_PART_MAX (10)
typedef struct {
ccv_rect_t rect;
int neighbors;
int id;
float confidence;
} ccv_comp_t;
typedef struct {
ccv_rect_t rect;
int neighbors;
int id;
float confidence;
int pnum;
ccv_comp_t part[CCV_DPM_PART_MAX];
} ccv_root_comp_t;
typedef struct {
ccv_dense_matrix_t* w;
double dx, dy, dxx, dyy;
int x, y, z;
int counterpart;
float alpha[6];
} ccv_dpm_part_classifier_t;
typedef struct {
int count;
ccv_dpm_part_classifier_t root;
ccv_dpm_part_classifier_t* part;
float alpha[3], beta;
} ccv_dpm_root_classifier_t;
typedef struct {
int count;
ccv_dpm_root_classifier_t* root;
} ccv_dpm_mixture_model_t;
typedef struct {
int interval;
int min_neighbors;
int flags;
float threshold;
} ccv_dpm_param_t;
typedef struct {
int components;
int parts;
int grayscale;
int symmetric;
int min_area; // 3000
int max_area; // 5000
int iterations;
int data_minings;
int relabels;
int negative_cache_size; // 1000
double include_overlap; // 0.7
double alpha;
double alpha_ratio; // 0.85
double balance; // 1.5
double C;
double percentile_breakdown; // 0.05
ccv_dpm_param_t detector;
} ccv_dpm_new_param_t;
enum {
CCV_DPM_NO_NESTED = 0x10000000,
};
void 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);
ccv_array_t* __attribute__((warn_unused_result)) ccv_dpm_detect_objects(ccv_dense_matrix_t* a, ccv_dpm_mixture_model_t** model, int count, ccv_dpm_param_t params);
ccv_dpm_mixture_model_t* __attribute__((warn_unused_result)) ccv_load_dpm_mixture_model(const char* directory);
void ccv_dpm_mixture_model_free(ccv_dpm_mixture_model_t* model);
/* this is open source implementation of object detection algorithm: brightness binary feature
* it is an extension/modification of original HAAR-like feature with Adaboost, featured faster
* computation and higher accuracy (current highest accuracy close-source face detector is based
* on the same algorithm) */
#define CCV_BBF_POINT_MAX (8)
#define CCV_BBF_POINT_MIN (3)
typedef struct {
int size;
int px[CCV_BBF_POINT_MAX];
int py[CCV_BBF_POINT_MAX];
int pz[CCV_BBF_POINT_MAX];
int nx[CCV_BBF_POINT_MAX];
int ny[CCV_BBF_POINT_MAX];
int nz[CCV_BBF_POINT_MAX];
} ccv_bbf_feature_t;
typedef struct {
int count;
float threshold;
ccv_bbf_feature_t* feature;
float* alpha;
} ccv_bbf_stage_classifier_t;
typedef struct {
int count;
ccv_size_t size;
ccv_bbf_stage_classifier_t* stage_classifier;
} ccv_bbf_classifier_cascade_t;
enum {
CCV_BBF_GENETIC_OPT = 0x01,
CCV_BBF_FLOAT_OPT = 0x02
};
typedef struct {
int interval;
int min_neighbors;
int flags;
int accurate;
ccv_size_t size;
} ccv_bbf_param_t;
typedef struct {
double pos_crit;
double neg_crit;
double balance_k;
int layer;
int feature_number;
int optimizer;
ccv_bbf_param_t detector;
} ccv_bbf_new_param_t;
enum {
CCV_BBF_NO_NESTED = 0x10000000,
};
void ccv_bbf_classifier_cascade_new(ccv_dense_matrix_t** posimg, int posnum, char** bgfiles, int bgnum, int negnum, ccv_size_t size, const char* dir, ccv_bbf_new_param_t params);
ccv_array_t* __attribute__((warn_unused_result)) ccv_bbf_detect_objects(ccv_dense_matrix_t* a, ccv_bbf_classifier_cascade_t** cascade, int count, ccv_bbf_param_t params);
ccv_bbf_classifier_cascade_t* __attribute__((warn_unused_result)) ccv_load_bbf_classifier_cascade(const char* directory);
ccv_bbf_classifier_cascade_t* __attribute__((warn_unused_result)) ccv_bbf_classifier_cascade_read_binary(char* s);
int ccv_bbf_classifier_cascade_write_binary(ccv_bbf_classifier_cascade_t* cascade, char* s, int slen);
void ccv_bbf_classifier_cascade_free(ccv_bbf_classifier_cascade_t* cascade);
/* modern machine learning algorithms */
/* RBM, LLE, APCluster */
#endif