forked from liuliu/ccv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ccv.h
2317 lines (2119 loc) · 98.2 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
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**********************************************************
* 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>
#define _WITH_GETLINE
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
#include <math.h>
#include <assert.h>
#if !defined(__OpenBSD__) && !defined(__FreeBSD__)
#include <alloca.h>
#endif
#define CCV_PI (3.141592653589793)
#define ccmalloc malloc
#define cccalloc calloc
#define ccrealloc realloc
#define ccfree free
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/param.h>
#if defined(__APPLE__) || defined(BSD) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
#define ccmemalign posix_memalign
#else
#define ccmemalign(memptr, alignment, size) (*memptr = memalign(alignment, size))
#endif
#else
#define ccmemalign(memptr, alignment, size) (*memptr = ccmalloc(size))
#endif
/* Doxygen will ignore these, otherwise it has problem to process warn_unused_result directly. */
#define CCV_WARN_UNUSED(x) x __attribute__((warn_unused_result))
enum {
CCV_8U = 0x01000,
CCV_32S = 0x02000,
CCV_32F = 0x04000,
CCV_64S = 0x08000,
CCV_64F = 0x10000,
};
enum {
CCV_C1 = 0x001,
CCV_C2 = 0x002,
CCV_C3 = 0x003,
CCV_C4 = 0x004,
};
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) & 0xFF000)
#define CCV_GET_DATA_TYPE_SIZE(x) _ccv_get_data_type_size[CCV_GET_DATA_TYPE(x) >> 12]
#define CCV_MAX_CHANNEL (0xFFF)
#define CCV_GET_CHANNEL(x) ((x) & 0xFFF)
#define CCV_ALL_DATA_TYPE (CCV_8U | CCV_32S | CCV_32F | CCV_64S | CCV_64F)
enum {
CCV_MATRIX_DENSE = 0x0100000,
CCV_MATRIX_SPARSE = 0x0200000,
CCV_MATRIX_CSR = 0x0400000,
CCV_MATRIX_CSC = 0x0800000,
};
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
CCV_NO_DATA_ALLOC = 0x10000000, // matrix is allocated as header only, but with no data section, therefore, you have to free the data section separately
};
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 = 0x01000000,
CCV_DENSE_VECTOR = 0x02000000,
};
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;
/**
* @defgroup ccv_cache cache mechanism
* This class implements a trie-based LRU cache that is then used for ccv application-wide cache in [ccv_memory.c](/lib/ccv-memory).
* @{
*/
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 */
/**
* Setup a cache strcture to work with.
* @param cache The allocated cache.
* @param up The upper limit of cache size in bytes.
* @param cache_types The number of cache types in this one cache instance.
* @param ffree The function that will be used to free cached object.
*/
void ccv_cache_init(ccv_cache_t* cache, size_t up, int cache_types, ccv_cache_index_free_f ffree, ...);
/**
* Get an object from cache for its signature. 0 if cannot find the object.
* @param cache The cache.
* @param sign The signature.
* @param type The type of the object.
* @return The pointer to the object.
*/
void* ccv_cache_get(ccv_cache_t* cache, uint64_t sign, uint8_t* type);
/**
* Put an object to cache with its signature, size, and type
* @param cache The cache.
* @param sign The signature.
* @param x The pointer to the object.
* @param size The size of the object.
* @param type The type of the object.
* @return 0 - success, 1 - replace, -1 - failure.
*/
int ccv_cache_put(ccv_cache_t* cache, uint64_t sign, void* x, uint32_t size, uint8_t type);
/**
* Get an object from cache for its signature and then remove that object from the cache. 0 if cannot find the object.
* @param cache The cache.
* @param sign The signature.
* @param type The type of the object.
* @return The pointer to the object.
*/
void* ccv_cache_out(ccv_cache_t* cache, uint64_t sign, uint8_t* type);
/**
* Delete an object from cache for its signature and free it.
* @param cache The cache.
* @param sign The signature.
* @return -1 if cannot find the object, otherwise return 0.
*/
int ccv_cache_delete(ccv_cache_t* cache, uint64_t sign);
/**
* Clean up the cache, free all objects inside and other memory space occupied.
* @param cache The cache.
*/
void ccv_cache_cleanup(ccv_cache_t* cache);
/**
* For current implementation (trie-based LRU cache), it is an alias for ccv_cache_cleanup.
* @param cache The 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))
/**
* @defgroup ccv_memory memory alloc/dealloc
* @{
*/
#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))
/**
* Check the input matrix, if it is the allowed type, return it, otherwise create one with prefer_type.
* @param x The matrix to check.
* @param rows Rows of the matrix.
* @param cols Columns of the matrix.
* @param types Allowed types, it can be a mask of multiple types, e.g. CCV_8U | CCV_32S allows both 8-bit unsigned integer type and 32-bit signed integer type.
* @param prefer_type The default type, it can be only one type.
* @param sig The signature, using 0 if you don't know what it is.
* @return The returned matrix object that satisfies the requirements.
*/
CCV_WARN_UNUSED(ccv_dense_matrix_t*) ccv_dense_matrix_renew(ccv_dense_matrix_t* x, int rows, int cols, int types, int prefer_type, uint64_t sig);
/**
* Create a dense matrix with rows, cols, and type.
* @param rows Rows of the matrix.
* @param cols Columns of the matrix.
* @param type Matrix supports 4 data types - CCV_8U, CCV_32S, CCV_64S, CCV_32F, CCV_64F and up to 255 channels. e.g. CCV_32F | 31 will create a matrix with float (32-bit float point) data type with 31 channels (the default type for ccv_hog).
* @param data If 0, ccv will create the matrix by allocating memory itself. Otherwise, it will use the memory region referenced by 'data'.
* @param sig The signature, using 0 if you don't know what it is.
* @return The newly created matrix object.
*/
CCV_WARN_UNUSED(ccv_dense_matrix_t*) ccv_dense_matrix_new(int rows, int cols, int type, void* data, uint64_t sig);
/**
* This method will return a dense matrix allocated on stack, with a data pointer to a custom memory region.
* @param rows Rows of the matrix.
* @param cols Columns of the matrix.
* @param type The type of matrix.
* @param data The data pointer that stores the actual matrix, it cannot be 0.
* @param sig The signature, using 0 if you don't know what it is.
* @return static matrix structs.
*/
ccv_dense_matrix_t ccv_dense_matrix(int rows, int cols, int type, void* data, uint64_t sig);
/**
* Mark the current matrix as mutable. Under the hood, it will set matrix signature to 0, and mark the matrix as non-collectable.
* @param mat The supplied matrix that will be marked as mutable.
*/
void ccv_make_matrix_mutable(ccv_matrix_t* mat);
/**
* Mark the current matrix as immutable. Under the hood, it will generate a signature for the matrix, and mark it as non-collectable. For the convention, if the matrix is marked as immutable, you shouldn't change the content of the matrix, otherwise it will cause surprising behavior. If you want to change the content of the matrix, mark it as mutable first.
* @param mat The supplied matrix that will be marked as immutable.
**/
void ccv_make_matrix_immutable(ccv_matrix_t* mat);
/**
* Create a sparse matrix. ccv uses a double hash table for memory-efficient and quick-access sparse matrix.
* @param rows Rows of the matrix.
* @param cols Columns of the matrix.
* @param type The type of the matrix, the same as dense matrix.
* @param major Either CCV_SPARSE_ROW_MAJOR or CCV_SPARSE_COL_MAJOR, it determines the underlying data structure of the sparse matrix (either using row or column as the first-level hash table).
* @param sig The signature, using 0 if you don't know what it is.
* @return The newly created sparse matrix object.
*/
CCV_WARN_UNUSED(ccv_sparse_matrix_t*) ccv_sparse_matrix_new(int rows, int cols, int type, int major, uint64_t sig);
/**
* Skip garbage-collecting process and free the matrix immediately.
* @param mat The matrix.
*/
void ccv_matrix_free_immediately(ccv_matrix_t* mat);
/**
* In principal, you should always use this method to free a matrix. If you enabled cache in ccv, this method won't immediately free up memory space of the matrix. Instead, it will push the matrix to a cache if applicable so that if you want to create the same matrix again, ccv can shortcut the required matrix/image processing and return it from the cache.
* @param mat The matrix.
*/
void ccv_matrix_free(ccv_matrix_t* mat);
/**
* Generate a matrix signature based on input message and other signatures. This is the core method for ccv cache. In short, ccv does a given image processing by first generating an appropriate signature for that operation. It requires 1). an operation-specific message, which can be generated by concatenate the operation name and parameters. 2). the signature of input matrix(es). After that, ccv will look-up matrix in cache with the newly generated signature. If it exists, ccv will return that matrix and skip the whole operation.
* @param msg The concatenated message.
* @param len Message length.
* @param sig_start The input matrix(es) signature, end the list with 0.
* @return The generated 64-bit signature.
*/
uint64_t ccv_cache_generate_signature(const char* msg, int len, uint64_t sig_start, ...);
#define CCV_DEFAULT_CACHE_SIZE (1024 * 1024 * 64)
/**
* Drain up the cache.
*/
void ccv_drain_cache(void);
/**
* Drain up and disable the application-wide cache.
*/
void ccv_disable_cache(void);
/**
* Enable a application-wide cache for ccv at default memory bound (64MiB).
*/
void ccv_enable_default_cache(void);
/**
* Enable a application-wide cache for ccv. The cache is bounded by given memory size.
* @param size The upper limit of the cache, in bytes.
*/
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); }
/** @} */
/**
* @defgroup ccv_io basic IO utilities
* @{
*/
enum {
// modifier for converting to gray-scale
CCV_IO_GRAY = 0x100,
// modifier for converting to color
CCV_IO_RGB_COLOR = 0x300,
};
enum {
// modifier for not copy the data over when read raw in-memory data
CCV_IO_NO_COPY = 0x10000,
};
enum {
// read self-describe in-memory data
CCV_IO_ANY_STREAM = 0x010,
CCV_IO_BMP_STREAM = 0x011,
CCV_IO_JPEG_STREAM = 0x012,
CCV_IO_PNG_STREAM = 0x013,
CCV_IO_PLAIN_STREAM = 0x014,
CCV_IO_DEFLATE_STREAM = 0x015,
// 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_ANY_RAW = 0x040,
CCV_IO_RGB_RAW = 0x041,
CCV_IO_RGBA_RAW = 0x042,
CCV_IO_ARGB_RAW = 0x043,
CCV_IO_BGR_RAW = 0x044,
CCV_IO_BGRA_RAW = 0x045,
CCV_IO_ABGR_RAW = 0x046,
CCV_IO_GRAY_RAW = 0x047,
};
enum {
CCV_IO_FINAL = 0x00,
CCV_IO_CONTINUE,
CCV_IO_ERROR,
CCV_IO_ATTEMPTED,
CCV_IO_UNKNOWN,
};
/**
* @file ccv_doxygen.h
* @fn int ccv_read(const char* in, ccv_dense_matrix_t** x, int type)
* Read image from a file. This function has soft dependencies on [LibJPEG](http://libjpeg.sourceforge.net/) and [LibPNG](http://www.libpng.org/pub/png/libpng.html). No these libraries, no JPEG nor PNG read support. However, ccv does support BMP read natively (it is a simple format after all).
* @param in The file name.
* @param x The output image.
* @param type CCV_IO_ANY_FILE, accept any file format. CCV_IO_GRAY, convert to grayscale image. CCV_IO_RGB_COLOR, convert to color image.
*/
/**
* @fn int ccv_read(const void* data, ccv_dense_matrix_t** x, int type, int size)
* Read image from a a region of memory that conforms a specific image format. This function has soft dependencies on [LibJPEG](http://libjpeg.sourceforge.net/) and [LibPNG](http://www.libpng.org/pub/png/libpng.html). No these libraries, no JPEG nor PNG read support. However, ccv does support BMP read natively (it is a simple format after all).
* @param data The data memory.
* @param x The output image.
* @param type CCV_IO_ANY_STREAM, accept any file format. CCV_IO_GRAY, convert to grayscale image. CCV_IO_RGB_COLOR, convert to color image.
* @param size The size of that data memory region.
*/
/**
* @fn int ccv_read(const void* data, ccv_dense_matrix_t** x, int type, int rows, int cols, int scanline)
* Read image from a region of memory that assumes specific layout (RGB, GRAY, BGR, RGBA, ARGB, RGBA, ABGR, BGRA). By default, this method will create a matrix and copy data over to that matrix. With CCV_IO_NO_COPY, it will create a matrix that has data block pointing to the original data memory region. It is your responsibility to release that data memory at an appropriate time after release the matrix.
* @param data The data memory.
* @param x The output image.
* @param type CCV_IO_ANY_RAW, CCV_IO_RGB_RAW, CCV_IO_BGR_RAW, CCV_IO_RGBA_RAW, CCV_IO_ARGB_RAW, CCV_IO_BGRA_RAW, CCV_IO_ABGR_RAW, CCV_IO_GRAY_RAW. These in conjunction can be used with CCV_IO_NO_COPY.
* @param rows How many rows in the given data memory region.
* @param cols How many columns in the given data memory region.
* @param scanline The size of a single column in the given data memory region (or known as "bytes per row").
*/
int ccv_read_impl(const void* 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
/**
* Write image to a file. This function has soft dependencies on [LibJPEG](http://libjpeg.sourceforge.net/) and [LibPNG](http://www.libpng.org/pub/png/libpng.html). No these libraries, no JPEG nor PNG write support.
* @param mat The input image.
* @param out The file name.
* @param len The output bytes.
* @param type CCV_IO_PNG_FILE, save to PNG format. CCV_IO_JPEG_FILE, save to JPEG format.
* @param conf configuration.
*/
int ccv_write(ccv_dense_matrix_t* mat, char* out, int* len, int type, void* conf);
/** @} */
/**
* @defgroup ccv_algebra linear algebra
* @{
*/
double ccv_trace(ccv_matrix_t* mat);
enum {
CCV_L1_NORM = 0x01, // |dx| + |dy|
CCV_L2_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);
/**
* Normalize a matrix and return the normalize factor.
* @param a The input matrix.
* @param b The output matrix.
* @param btype The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
* @param flag CCV_L1 or CCV_L2, for L1 or L2 normalization.
* @return L1 or L2 sum.
*/
double ccv_normalize(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int flag);
/**
* Generate the [Summed Area Table](https://en.wikipedia.org/wiki/Summed_area_table).
* @param a The input matrix.
* @param b The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
* @param padding_pattern CCV_NO_PADDING - the first row and the first column in the output matrix is the same as the input matrix. CCV_PADDING_ZERO - the first row and the first column in the output matrix is zero, thus, the output matrix size is 1 larger than the input matrix.
*/
void ccv_sat(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int padding_pattern);
/**
* Dot product of two matrix.
* @param a The input matrix.
* @param b The other input matrix.
* @return Dot product.
*/
double ccv_dot(ccv_matrix_t* a, ccv_matrix_t* b);
/**
* Return the sum of all elements in the matrix.
* @param mat The input matrix.
* @param flag CCV_UNSIGNED - compute fabs(x) of the elements first and then sum up. CCV_SIGNED - compute the sum normally.
*/
double ccv_sum(ccv_matrix_t* mat, int flag);
/**
* Return the sum of all elements in the matrix.
* @param mat The input matrix.
* @return Element variance of the input matrix.
*/
double ccv_variance(ccv_matrix_t* mat);
/**
* Do element-wise matrix multiplication.
* @param a The input matrix.
* @param b The input matrix.
* @param c The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
*/
void ccv_multiply(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** c, int type);
/**
* Matrix addition.
* @param a The input matrix.
* @param b The input matrix.
* @param c The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
*/
void ccv_add(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** c, int type);
/**
* Matrix subtraction.
* @param a The input matrix.
* @param b The input matrix.
* @param c The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
*/
void ccv_subtract(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** c, int type);
/**
* Scale given matrix by factor of **ds**.
* @param a The input matrix.
* @param b The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
* @param ds The scale factor, `b = a * ds`
*/
void ccv_scale(ccv_matrix_t* a, ccv_matrix_t** b, int type, double ds);
enum {
CCV_A_TRANSPOSE = 0x01,
CCV_B_TRANSPOSE = 0X02,
CCV_C_TRANSPOSE = 0X04,
};
/**
* General purpose matrix multiplication. This function has a hard dependency on [cblas](http://www.netlib.org/blas/) library.
*
* As general as it is, it computes:
*
* alpha * A * B + beta * C
*
* whereas A, B, C are matrix, and alpha, beta are scalar.
*
* @param a The input matrix.
* @param b The input matrix.
* @param alpha The multiplication factor.
* @param c The input matrix.
* @param beta The multiplication factor.
* @param transpose CCV_A_TRANSPOSE, CCV_B_TRANSPOSE to indicate if matrix A or B need to be transposed first before multiplication.
* @param d The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
*/
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);
/** @} */
typedef struct {
int left;
int top;
int right;
int bottom;
} ccv_margin_t;
inline static ccv_margin_t ccv_margin(int left, int top, int right, int bottom)
{
ccv_margin_t margin;
margin.left = left;
margin.top = top;
margin.right = right;
margin.bottom = bottom;
return margin;
}
/* matrix build blocks / utility functions ccv_util.c */
/**
* @defgroup ccv_util data structure utilities
* @{
*/
/**
* Check and get dense matrix from general matrix structure.
* @param mat A general matrix.
*/
ccv_dense_matrix_t* ccv_get_dense_matrix(ccv_matrix_t* mat);
/**
* Check and get sparse matrix from general matrix structure.
* @param mat A general matrix.
*/
ccv_sparse_matrix_t* ccv_get_sparse_matrix(ccv_matrix_t* mat);
/**
* Get vector for a sparse matrix.
* @param mat The sparse matrix.
* @param index The index of that vector.
*/
ccv_dense_vector_t* ccv_get_sparse_matrix_vector(ccv_sparse_matrix_t* mat, int index);
/**
* Get cell from a sparse matrix.
* @param mat The sparse matrix.
* @param row The row index.
* @param col The column index.
*/
ccv_matrix_cell_t ccv_get_sparse_matrix_cell(ccv_sparse_matrix_t* mat, int row, int col);
/**
* Set cell for a sparse matrix.
* @param mat The sparse matrix.
* @param row The row index.
* @param col The column index.
* @param data The data pointer.
*/
void ccv_set_sparse_matrix_cell(ccv_sparse_matrix_t* mat, int row, int col, void* data);
/**
* Transform a sparse matrix into compressed representation.
* @param mat The sparse matrix.
* @param csm The compressed matrix.
*/
void ccv_compress_sparse_matrix(ccv_sparse_matrix_t* mat, ccv_compressed_sparse_matrix_t** csm);
/**
* Transform a compressed matrix into a sparse matrix.
* @param csm The compressed matrix.
* @param smt The sparse matrix.
*/
void ccv_decompress_sparse_matrix(ccv_compressed_sparse_matrix_t* csm, ccv_sparse_matrix_t** smt);
/**
* Offset input matrix by x, y.
* @param a The input matrix.
* @param b The output matrix.
* @param btype The type of output matrix, if 0, ccv will use the input matrix type.
* @param y b(0, 0) = a(x, y).
* @param x b(0, 0) = a(x, y).
*/
void ccv_move(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int y, int x);
/**
* Compare if two matrix are equal (with type). Return 0 if it is.
* @param a The input matrix a.
* @param b The input matrix b.
*/
int ccv_matrix_eq(ccv_matrix_t* a, ccv_matrix_t* b);
/**
* Slice an input matrix given x, y and row, column size.
* @param a The input matrix.
* @param b The output matrix.
* @param btype The type of output matrix, if 0, ccv will use the input matrix type.
* @param y y coordinate.
* @param x x coordinate.
* @param rows Row size of targeted matrix.
* @param cols Column size of targeted matrix.
*/
void ccv_slice(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int y, int x, int rows, int cols);
/**
* Add border to the input matrix.
* @param a The input matrix.
* @param b The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
* @param margin Left, top, right, bottom width for the border.
*/
void ccv_border(ccv_matrix_t* a, ccv_matrix_t** b, int type, ccv_margin_t margin);
/**
* Convert a input matrix into a matrix within visual range, so that one can output it into PNG file for inspection.
* @param a The input matrix.
* @param b The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
*/
void ccv_visualize(ccv_matrix_t* a, ccv_matrix_t** b, int type);
/**
* If a given matrix has multiple channels, this function will compute a new matrix that each cell in the new matrix is the sum of all channels in the same cell of the given matrix.
* @param a The input matrix.
* @param b The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
* @param flag ccv reserved this for now.
*/
void ccv_flatten(ccv_matrix_t* a, ccv_matrix_t** b, int type, int flag);
/**
* Zero out a given matrix.
* @param mat The given matrix.
*/
void ccv_zero(ccv_matrix_t* mat);
/**
* Compute a new matrix that each element is first left shifted and then right shifted.
* @param a The input matrix.
* @param b The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
* @param lr Left shift amount.
* @param rr Right shift amount.
*/
void ccv_shift(ccv_matrix_t* a, ccv_matrix_t** b, int type, int lr, int rr);
/**
* Check if any nan value in the given matrix, and return its position.
* @param a The given matrix.
*/
int ccv_any_nan(ccv_matrix_t *a);
/**
* Return a temporary ccv_dense_matrix_t matrix that is pointing to a given matrix data section but with different rows and cols. Useful to use part of the given matrix do computations without paying memory copy performance penalty.
* @param a The given matrix.
* @param y The y offset to the given matrix.
* @param x The x offset to the given matrix.
* @param rows The number of rows of the new matrix.
* @param cols The number of cols of the new matrix.
*/
ccv_dense_matrix_t ccv_reshape(ccv_dense_matrix_t* a, int y, int x, int rows, int cols);
// 32-bit float to 16-bit float
void ccv_float_to_half_precision(float* f, uint16_t* h, size_t len);
void ccv_half_precision_to_float(uint16_t* h, float* f, size_t len);
/* 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;
/**
* Create a new, self-growing array.
* @param rnum The initial capacity of the array.
* @param rsize The size of each element in the array.
* @param sig The signature for this array.
*/
CCV_WARN_UNUSED(ccv_array_t*) ccv_array_new(int rsize, int rnum, uint64_t sig);
/**
* Push a new element into the array.
* @param array The array.
* @param r The pointer to new element, it will then be copied into the array.
*/
void ccv_array_push(ccv_array_t* array, const void* r);
typedef int(*ccv_array_group_f)(const void*, const void*, void*);
/**
* Group elements in the array from its similarity.
* @param array The array.
* @param index The output index, same group element will have the same index.
* @param gfunc int ccv_array_group_f(const void* a, const void* b, void* data). Return 1 if a and b are in the same group.
* @param data Any extra user data.
*/
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);
/**
* Zero out the array, it won't change the array->rnum however.
* @param array The array.
*/
void ccv_array_zero(ccv_array_t* array);
/**
* Clear the array, it will reset the array->rnum to 0.
* @param array The array.
*/
void ccv_array_clear(ccv_array_t* array);
/**
* Free up the array immediately.
* @param array The array.
*/
void ccv_array_free_immediately(ccv_array_t* array);
/**
* Free up the array. If array's signature is non-zero, we may put it into cache so that later on, we can shortcut and return this array directly.
* @param array The array.
*/
void ccv_array_free(ccv_array_t* array);
/**
* Get a specific element from an array
* @param a The array.
* @param i The index of the element in the array.
*/
#define ccv_array_get(a, i) (((char*)((a)->data)) + (size_t)(a)->rsize * (size_t)(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 {
float x, y;
} ccv_decimal_point_t;
inline static ccv_decimal_point_t ccv_decimal_point(float x, float y)
{
ccv_decimal_point_t point;
point.x = x;
point.y = y;
return point;
}
typedef struct {
float x, y, a, b;
float roll, pitch, yaw;
} ccv_decimal_pose_t;
inline static ccv_decimal_pose_t ccv_decimal_pose(float x, float y, float a, float b, float roll, float pitch, float yaw)
{
ccv_decimal_pose_t pose;
pose.x = x;
pose.y = y;
pose.a = a;
pose.b = b;
pose.roll = roll;
pose.pitch = pitch;
pose.yaw = yaw;
return pose;
}
typedef struct {
ccv_rect_t rect;
int size;
ccv_array_t* set;
long m10, m01, m11, m20, m02;
} ccv_contour_t;
/**
* Create a new contour object.
* @param set The initial capacity of the contour.
*/
ccv_contour_t* ccv_contour_new(int set);
/**
* Push a point into the contour object.
* @param contour The contour.
* @param point The point.
*/
void ccv_contour_push(ccv_contour_t* contour, ccv_point_t point);
/**
* Free up the contour object.
* @param contour The contour.
*/
void ccv_contour_free(ccv_contour_t* contour);
/** @} */
/* numerical algorithms ccv_numeric.c */
/**
* @defgroup ccv_numeric numerical algorithms
* @{
*/
/* 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_dense_matrix_t* a, ccv_dense_matrix_t** vector, ccv_dense_matrix_t** lambda, int type, double epsilon);
typedef struct {
double interp; /**< Interpolate value. */
double extrap; /**< Extrapolate value. */
int max_iter; /**< Maximum iterations. */
double ratio; /**< Increase ratio. */
double rho; /**< Decrease ratio. */
double sig; /**< Sigma. */
} ccv_minimize_param_t;
extern const ccv_minimize_param_t ccv_minimize_default_params;
typedef int(*ccv_minimize_f)(const ccv_dense_matrix_t* x, double* f, ccv_dense_matrix_t* df, void*);
/**
* Linear-search to minimize function with partial derivatives. It is formed after [minimize.m](http://www.gatsby.ucl.ac.uk/~edward/code/minimize/example.html).
* @param x The input vector.
* @param length The length of line.
* @param red The step size.
* @param func (int ccv_minimize_f)(const ccv_dense_matrix_t* x, double* f, ccv_dense_matrix_t* df, void* data). Compute the function value, and its partial derivatives.
* @param params A **ccv_minimize_param_t** structure that defines various aspect of the minimize function.
* @param data Any extra user data.
*/
void ccv_minimize(ccv_dense_matrix_t* x, int length, double red, ccv_minimize_f func, ccv_minimize_param_t params, void* data);
/**
* Convolve on dense matrix a with dense matrix b. This function has a soft dependency on [FFTW3](http://fftw.org/). If no FFTW3 exists, ccv will use [KissFFT](http://sourceforge.net/projects/kissfft/) shipped with it. FFTW3 is about 35% faster than KissFFT.
* @param a Dense matrix a.
* @param b Dense matrix b.
* @param d The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
* @param padding_pattern ccv doesn't support padding pattern for now.
*/
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*);
/**
* Fill a given dense matrix with a kernel function.
* @param x The matrix to be filled with.
* @param func (double ccv_filter_kernel_f(double x, double y, void* data), compute the value with given x, y.
* @param data Any extra user data.
*/
void ccv_filter_kernel(ccv_dense_matrix_t* x, ccv_filter_kernel_f func, void* data);
/* modern numerical algorithms */
/**
* [Distance transform](https://en.wikipedia.org/wiki/Distance_transform). The current implementation follows [Distance Transforms of Sampled Functions](http://www.cs.cornell.edu/~dph/papers/dt.pdf). The dynamic programming technique has O(n) time complexity.
* @param a The input matrix.
* @param b The output matrix.
* @param type The type of output matrix, if 0, ccv will try to match the input matrix for appropriate type.
* @param x The x coordinate offset.
* @param x_type The type of output x coordinate offset, if 0, ccv will default to CCV_32S | CCV_C1.
* @param y The y coordinate offset.
* @param y_type The type of output x coordinate offset, if 0, ccv will default to CCV_32S | CCV_C1.
* @param dx The x coefficient.