imagecore 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. data/.gitignore +24 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +2 -0
  4. data/ext/imagecore/analyze_image.cxx +58 -0
  5. data/ext/imagecore/analyze_image.h +6 -0
  6. data/ext/imagecore/extconf.rb +9 -0
  7. data/ext/imagecore/imagecore.cxx +34 -0
  8. data/ext/opencv/core/___.c +3 -0
  9. data/ext/opencv/core/alloc.cpp +697 -0
  10. data/ext/opencv/core/array.cpp +3206 -0
  11. data/ext/opencv/core/datastructs.cpp +4064 -0
  12. data/ext/opencv/core/extconf.rb +22 -0
  13. data/ext/opencv/core/matrix.cpp +3777 -0
  14. data/ext/opencv/core/precomp.hpp +216 -0
  15. data/ext/opencv/core/system.cpp +832 -0
  16. data/ext/opencv/core/tables.cpp +3512 -0
  17. data/ext/opencv/highgui/___.c +3 -0
  18. data/ext/opencv/highgui/bitstrm.cpp +582 -0
  19. data/ext/opencv/highgui/bitstrm.hpp +182 -0
  20. data/ext/opencv/highgui/extconf.rb +28 -0
  21. data/ext/opencv/highgui/grfmt_base.cpp +128 -0
  22. data/ext/opencv/highgui/grfmt_base.hpp +113 -0
  23. data/ext/opencv/highgui/grfmt_bmp.cpp +564 -0
  24. data/ext/opencv/highgui/grfmt_bmp.hpp +99 -0
  25. data/ext/opencv/highgui/grfmt_exr.hpp +113 -0
  26. data/ext/opencv/highgui/grfmt_imageio.hpp +56 -0
  27. data/ext/opencv/highgui/grfmt_jpeg.cpp +622 -0
  28. data/ext/opencv/highgui/grfmt_jpeg.hpp +90 -0
  29. data/ext/opencv/highgui/grfmt_jpeg2000.cpp +529 -0
  30. data/ext/opencv/highgui/grfmt_jpeg2000.hpp +95 -0
  31. data/ext/opencv/highgui/grfmt_png.cpp +406 -0
  32. data/ext/opencv/highgui/grfmt_png.hpp +101 -0
  33. data/ext/opencv/highgui/grfmt_pxm.cpp +513 -0
  34. data/ext/opencv/highgui/grfmt_pxm.hpp +92 -0
  35. data/ext/opencv/highgui/grfmt_sunras.cpp +425 -0
  36. data/ext/opencv/highgui/grfmt_sunras.hpp +105 -0
  37. data/ext/opencv/highgui/grfmt_tiff.cpp +718 -0
  38. data/ext/opencv/highgui/grfmt_tiff.hpp +136 -0
  39. data/ext/opencv/highgui/grfmts.hpp +56 -0
  40. data/ext/opencv/highgui/loadsave.cpp +535 -0
  41. data/ext/opencv/highgui/precomp.hpp +223 -0
  42. data/ext/opencv/highgui/utils.cpp +689 -0
  43. data/ext/opencv/highgui/utils.hpp +128 -0
  44. data/ext/opencv/imgproc/___.c +3 -0
  45. data/ext/opencv/imgproc/_geom.h +72 -0
  46. data/ext/opencv/imgproc/color.cpp +3179 -0
  47. data/ext/opencv/imgproc/contours.cpp +1780 -0
  48. data/ext/opencv/imgproc/extconf.rb +11 -0
  49. data/ext/opencv/imgproc/filter.cpp +3063 -0
  50. data/ext/opencv/imgproc/precomp.hpp +159 -0
  51. data/ext/opencv/imgproc/shapedescr.cpp +1306 -0
  52. data/ext/opencv/imgproc/smooth.cpp +1566 -0
  53. data/ext/opencv/imgproc/tables.cpp +214 -0
  54. data/ext/opencv/imgproc/thresh.cpp +636 -0
  55. data/ext/opencv/imgproc/utils.cpp +242 -0
  56. data/ext/opencv/include/opencv2/core/core.hpp +4344 -0
  57. data/ext/opencv/include/opencv2/core/core_c.h +1885 -0
  58. data/ext/opencv/include/opencv2/core/internal.hpp +710 -0
  59. data/ext/opencv/include/opencv2/core/mat.hpp +2557 -0
  60. data/ext/opencv/include/opencv2/core/operations.hpp +3623 -0
  61. data/ext/opencv/include/opencv2/core/types_c.h +1875 -0
  62. data/ext/opencv/include/opencv2/core/version.hpp +58 -0
  63. data/ext/opencv/include/opencv2/highgui/highgui.hpp +198 -0
  64. data/ext/opencv/include/opencv2/highgui/highgui_c.h +506 -0
  65. data/ext/opencv/include/opencv2/imgproc/imgproc.hpp +1139 -0
  66. data/ext/opencv/include/opencv2/imgproc/imgproc_c.h +783 -0
  67. data/ext/opencv/include/opencv2/imgproc/types_c.h +538 -0
  68. data/imagecore.gemspec +20 -0
  69. data/lib/imagecore.rb +16 -0
  70. data/lib/imagecore/version.rb +3 -0
  71. metadata +119 -0
@@ -0,0 +1,22 @@
1
+ require 'mkmf'
2
+
3
+ # not valid for C++ code
4
+ $warnflags = ($warnflags.split - %w(-Wdeclaration-after-statement -Wimplicit-function-declaration)) * ' '
5
+
6
+ # OpenCV includes
7
+ $INCFLAGS << ' -I ../include'
8
+
9
+ # Find stuff
10
+ #if have_library('jpeg')
11
+ #$defs.push '-DHAVE_JPEG'
12
+ #end
13
+
14
+ #if have_library('tiff')
15
+ #$defs.push '-DHAVE_TIFF'
16
+ #end
17
+
18
+ # Sources
19
+
20
+ #dir_config("imagecore")
21
+ create_header('cvconfig.h')
22
+ create_makefile("opencv_core")
@@ -0,0 +1,3777 @@
1
+ /*M///////////////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
+ //
5
+ // By downloading, copying, installing or using the software you agree to this license.
6
+ // If you do not agree to this license, do not download, install,
7
+ // copy or use the software.
8
+ //
9
+ //
10
+ // License Agreement
11
+ // For Open Source Computer Vision Library
12
+ //
13
+ // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14
+ // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15
+ // Third party copyrights are property of their respective owners.
16
+ //
17
+ // Redistribution and use in source and binary forms, with or without modification,
18
+ // are permitted provided that the following conditions are met:
19
+ //
20
+ // * Redistribution's of source code must retain the above copyright notice,
21
+ // this list of conditions and the following disclaimer.
22
+ //
23
+ // * Redistribution's in binary form must reproduce the above copyright notice,
24
+ // this list of conditions and the following disclaimer in the documentation
25
+ // and/or other materials provided with the distribution.
26
+ //
27
+ // * The name of the copyright holders may not be used to endorse or promote products
28
+ // derived from this software without specific prior written permission.
29
+ //
30
+ // This software is provided by the copyright holders and contributors "as is" and
31
+ // any express or implied warranties, including, but not limited to, the implied
32
+ // warranties of merchantability and fitness for a particular purpose are disclaimed.
33
+ // In no event shall the Intel Corporation or contributors be liable for any direct,
34
+ // indirect, incidental, special, exemplary, or consequential damages
35
+ // (including, but not limited to, procurement of substitute goods or services;
36
+ // loss of use, data, or profits; or business interruption) however caused
37
+ // and on any theory of liability, whether in contract, strict liability,
38
+ // or tort (including negligence or otherwise) arising in any way out of
39
+ // the use of this software, even if advised of the possibility of such damage.
40
+ //
41
+ //M*/
42
+
43
+ #include "precomp.hpp"
44
+
45
+ /****************************************************************************************\
46
+ * [scaled] Identity matrix initialization *
47
+ \****************************************************************************************/
48
+
49
+ namespace cv {
50
+
51
+ void swap( Mat& a, Mat& b )
52
+ {
53
+ std::swap(a.flags, b.flags);
54
+ std::swap(a.dims, b.dims);
55
+ std::swap(a.rows, b.rows);
56
+ std::swap(a.cols, b.cols);
57
+ std::swap(a.data, b.data);
58
+ std::swap(a.refcount, b.refcount);
59
+ std::swap(a.datastart, b.datastart);
60
+ std::swap(a.dataend, b.dataend);
61
+ std::swap(a.datalimit, b.datalimit);
62
+ std::swap(a.allocator, b.allocator);
63
+
64
+ std::swap(a.size.p, b.size.p);
65
+ std::swap(a.step.p, b.step.p);
66
+ std::swap(a.step.buf[0], b.step.buf[0]);
67
+ std::swap(a.step.buf[1], b.step.buf[1]);
68
+
69
+ if( a.step.p == b.step.buf )
70
+ {
71
+ a.step.p = a.step.buf;
72
+ a.size.p = &a.rows;
73
+ }
74
+
75
+ if( b.step.p == a.step.buf )
76
+ {
77
+ b.step.p = b.step.buf;
78
+ b.size.p = &b.rows;
79
+ }
80
+ }
81
+
82
+
83
+ static inline void setSize( Mat& m, int _dims, const int* _sz,
84
+ const size_t* _steps, bool autoSteps=false )
85
+ {
86
+ CV_Assert( 0 <= _dims && _dims <= CV_MAX_DIM );
87
+ if( m.dims != _dims )
88
+ {
89
+ if( m.step.p != m.step.buf )
90
+ {
91
+ fastFree(m.step.p);
92
+ m.step.p = m.step.buf;
93
+ m.size.p = &m.rows;
94
+ }
95
+ if( _dims > 2 )
96
+ {
97
+ m.step.p = (size_t*)fastMalloc(_dims*sizeof(m.step.p[0]) + (_dims+1)*sizeof(m.size.p[0]));
98
+ m.size.p = (int*)(m.step.p + _dims) + 1;
99
+ m.size.p[-1] = _dims;
100
+ m.rows = m.cols = -1;
101
+ }
102
+ }
103
+
104
+ m.dims = _dims;
105
+ if( !_sz )
106
+ return;
107
+
108
+ size_t esz = CV_ELEM_SIZE(m.flags), total = esz;
109
+ int i;
110
+ for( i = _dims-1; i >= 0; i-- )
111
+ {
112
+ int s = _sz[i];
113
+ CV_Assert( s >= 0 );
114
+ m.size.p[i] = s;
115
+
116
+ if( _steps )
117
+ m.step.p[i] = i < _dims-1 ? _steps[i] : esz;
118
+ else if( autoSteps )
119
+ {
120
+ m.step.p[i] = total;
121
+ int64 total1 = (int64)total*s;
122
+ if( (uint64)total1 != (size_t)total1 )
123
+ CV_Error( CV_StsOutOfRange, "The total matrix size does not fit to \"size_t\" type" );
124
+ total = (size_t)total1;
125
+ }
126
+ }
127
+
128
+ if( _dims == 1 )
129
+ {
130
+ m.dims = 2;
131
+ m.cols = 1;
132
+ m.step[1] = esz;
133
+ }
134
+ }
135
+
136
+ static void updateContinuityFlag(Mat& m)
137
+ {
138
+ int i, j;
139
+ for( i = 0; i < m.dims; i++ )
140
+ {
141
+ if( m.size[i] > 1 )
142
+ break;
143
+ }
144
+
145
+ for( j = m.dims-1; j > i; j-- )
146
+ {
147
+ if( m.step[j]*m.size[j] < m.step[j-1] )
148
+ break;
149
+ }
150
+
151
+ int64 t = (int64)m.step[0]*m.size[0];
152
+ if( j <= i && t == (int)t )
153
+ m.flags |= Mat::CONTINUOUS_FLAG;
154
+ else
155
+ m.flags &= ~Mat::CONTINUOUS_FLAG;
156
+ }
157
+
158
+ static void finalizeHdr(Mat& m)
159
+ {
160
+ updateContinuityFlag(m);
161
+ int d = m.dims;
162
+ if( d > 2 )
163
+ m.rows = m.cols = -1;
164
+ if( m.data )
165
+ {
166
+ m.datalimit = m.datastart + m.size[0]*m.step[0];
167
+ if( m.size[0] > 0 )
168
+ {
169
+ m.dataend = m.data + m.size[d-1]*m.step[d-1];
170
+ for( int i = 0; i < d-1; i++ )
171
+ m.dataend += (m.size[i] - 1)*m.step[i];
172
+ }
173
+ else
174
+ m.dataend = m.datalimit;
175
+ }
176
+ else
177
+ m.dataend = m.datalimit = 0;
178
+ }
179
+
180
+
181
+ void Mat::create(int d, const int* _sizes, int _type)
182
+ {
183
+ int i;
184
+ CV_Assert(0 <= d && _sizes && d <= CV_MAX_DIM && _sizes);
185
+ _type = CV_MAT_TYPE(_type);
186
+
187
+ if( data && (d == dims || (d == 1 && dims <= 2)) && _type == type() )
188
+ {
189
+ if( d == 2 && rows == _sizes[0] && cols == _sizes[1] )
190
+ return;
191
+ for( i = 0; i < d; i++ )
192
+ if( size[i] != _sizes[i] )
193
+ break;
194
+ if( i == d && (d > 1 || size[1] == 1))
195
+ return;
196
+ }
197
+
198
+ release();
199
+ if( d == 0 )
200
+ return;
201
+ flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL;
202
+ setSize(*this, d, _sizes, 0, allocator == 0);
203
+
204
+ if( total() > 0 )
205
+ {
206
+ if( !allocator )
207
+ {
208
+ size_t total = alignSize(step.p[0]*size.p[0], (int)sizeof(*refcount));
209
+ data = datastart = (uchar*)fastMalloc(total + (int)sizeof(*refcount));
210
+ refcount = (int*)(data + total);
211
+ *refcount = 1;
212
+ }
213
+ else
214
+ {
215
+ allocator->allocate(dims, size, _type, refcount, datastart, data, step.p);
216
+ CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
217
+ }
218
+ }
219
+
220
+ finalizeHdr(*this);
221
+ }
222
+
223
+ void Mat::copySize(const Mat& m)
224
+ {
225
+ setSize(*this, m.dims, 0, 0);
226
+ for( int i = 0; i < dims; i++ )
227
+ {
228
+ size[i] = m.size[i];
229
+ step[i] = m.step[i];
230
+ }
231
+ }
232
+
233
+ void Mat::deallocate()
234
+ {
235
+ if( allocator )
236
+ allocator->deallocate(refcount, datastart, data);
237
+ else
238
+ {
239
+ CV_DbgAssert(refcount != 0);
240
+ fastFree(datastart);
241
+ }
242
+ }
243
+
244
+
245
+ Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
246
+ : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0),
247
+ datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
248
+ {
249
+ CV_Assert( m.dims >= 2 );
250
+ if( m.dims > 2 )
251
+ {
252
+ AutoBuffer<Range> rs(m.dims);
253
+ rs[0] = rowRange;
254
+ rs[1] = colRange;
255
+ for( int i = 2; i < m.dims; i++ )
256
+ rs[i] = Range::all();
257
+ *this = m(rs);
258
+ return;
259
+ }
260
+
261
+ *this = m;
262
+ if( rowRange != Range::all() && rowRange != Range(0,rows) )
263
+ {
264
+ CV_Assert( 0 <= rowRange.start && rowRange.start <= rowRange.end && rowRange.end <= m.rows );
265
+ rows = rowRange.size();
266
+ data += step*rowRange.start;
267
+ flags |= SUBMATRIX_FLAG;
268
+ }
269
+
270
+ if( colRange != Range::all() && colRange != Range(0,cols) )
271
+ {
272
+ CV_Assert( 0 <= colRange.start && colRange.start <= colRange.end && colRange.end <= m.cols );
273
+ cols = colRange.size();
274
+ data += colRange.start*elemSize();
275
+ flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1;
276
+ flags |= SUBMATRIX_FLAG;
277
+ }
278
+
279
+ if( rows == 1 )
280
+ flags |= CONTINUOUS_FLAG;
281
+
282
+ if( rows <= 0 || cols <= 0 )
283
+ {
284
+ release();
285
+ rows = cols = 0;
286
+ }
287
+ }
288
+
289
+
290
+ Mat::Mat(const Mat& m, const Rect& roi)
291
+ : flags(m.flags), dims(2), rows(roi.height), cols(roi.width),
292
+ data(m.data + roi.y*m.step[0]), refcount(m.refcount),
293
+ datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit),
294
+ allocator(m.allocator), size(&rows)
295
+ {
296
+ CV_Assert( m.dims <= 2 );
297
+ flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1;
298
+ flags |= roi.height == 1 ? CONTINUOUS_FLAG : 0;
299
+
300
+ size_t esz = CV_ELEM_SIZE(flags);
301
+ data += roi.x*esz;
302
+ CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols &&
303
+ 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows );
304
+ if( refcount )
305
+ CV_XADD(refcount, 1);
306
+ if( roi.width < m.cols || roi.height < m.rows )
307
+ flags |= SUBMATRIX_FLAG;
308
+
309
+ step[0] = m.step[0]; step[1] = esz;
310
+
311
+ if( rows <= 0 || cols <= 0 )
312
+ {
313
+ release();
314
+ rows = cols = 0;
315
+ }
316
+ }
317
+
318
+
319
+ Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _steps)
320
+ : flags(MAGIC_VAL|CV_MAT_TYPE(_type)), dims(0),
321
+ rows(0), cols(0), data((uchar*)_data), refcount(0),
322
+ datastart((uchar*)_data), dataend((uchar*)_data), datalimit((uchar*)_data),
323
+ allocator(0), size(&rows)
324
+ {
325
+ setSize(*this, _dims, _sizes, _steps, true);
326
+ finalizeHdr(*this);
327
+ }
328
+
329
+
330
+ Mat::Mat(const Mat& m, const Range* ranges)
331
+ : flags(m.flags), dims(0), rows(0), cols(0), data(0), refcount(0),
332
+ datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
333
+ {
334
+ int i, d = m.dims;
335
+
336
+ CV_Assert(ranges);
337
+ for( i = 0; i < d; i++ )
338
+ {
339
+ Range r = ranges[i];
340
+ CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) );
341
+ }
342
+ *this = m;
343
+ for( i = 0; i < d; i++ )
344
+ {
345
+ Range r = ranges[i];
346
+ if( r != Range::all() && r != Range(0, size.p[i]))
347
+ {
348
+ size.p[i] = r.end - r.start;
349
+ data += r.start*step.p[i];
350
+ flags |= SUBMATRIX_FLAG;
351
+ }
352
+ }
353
+ updateContinuityFlag(*this);
354
+ }
355
+
356
+
357
+ Mat::Mat(const CvMatND* m, bool copyData)
358
+ : flags(MAGIC_VAL|CV_MAT_TYPE(m->type)), dims(0), rows(0), cols(0),
359
+ data((uchar*)m->data.ptr), refcount(0),
360
+ datastart((uchar*)m->data.ptr), allocator(0),
361
+ size(&rows)
362
+ {
363
+ int _sizes[CV_MAX_DIM];
364
+ size_t _steps[CV_MAX_DIM];
365
+
366
+ int i, d = m->dims;
367
+ for( i = 0; i < d; i++ )
368
+ {
369
+ _sizes[i] = m->dim[i].size;
370
+ _steps[i] = m->dim[i].step;
371
+ }
372
+
373
+ setSize(*this, d, _sizes, _steps);
374
+ finalizeHdr(*this);
375
+
376
+ if( copyData )
377
+ {
378
+ Mat temp(*this);
379
+ temp.copyTo(*this);
380
+ }
381
+ }
382
+
383
+
384
+ Mat Mat::diag(int d) const
385
+ {
386
+ CV_Assert( dims <= 2 );
387
+ Mat m = *this;
388
+ size_t esz = elemSize();
389
+ int len;
390
+
391
+ if( d >= 0 )
392
+ {
393
+ len = std::min(cols - d, rows);
394
+ m.data += esz*d;
395
+ }
396
+ else
397
+ {
398
+ len = std::min(rows + d, cols);
399
+ m.data -= step[0]*d;
400
+ }
401
+ CV_DbgAssert( len > 0 );
402
+
403
+ m.size[0] = m.rows = len;
404
+ m.size[1] = m.cols = 1;
405
+ m.step[0] += (len > 1 ? esz : 0);
406
+
407
+ if( m.rows > 1 )
408
+ m.flags &= ~CONTINUOUS_FLAG;
409
+ else
410
+ m.flags |= CONTINUOUS_FLAG;
411
+
412
+ if( size() != Size(1,1) )
413
+ m.flags |= SUBMATRIX_FLAG;
414
+
415
+ return m;
416
+ }
417
+
418
+
419
+ Mat::Mat(const IplImage* img, bool copyData)
420
+ : flags(MAGIC_VAL), dims(2), rows(0), cols(0),
421
+ data(0), refcount(0), datastart(0), dataend(0), allocator(0), size(&rows)
422
+ {
423
+ CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0);
424
+
425
+ int depth = IPL2CV_DEPTH(img->depth);
426
+ size_t esz;
427
+ step[0] = img->widthStep;
428
+
429
+ if(!img->roi)
430
+ {
431
+ CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL);
432
+ flags = MAGIC_VAL + CV_MAKETYPE(depth, img->nChannels);
433
+ rows = img->height; cols = img->width;
434
+ datastart = data = (uchar*)img->imageData;
435
+ esz = CV_ELEM_SIZE(flags);
436
+ }
437
+ else
438
+ {
439
+ CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL || img->roi->coi != 0);
440
+ bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE;
441
+ flags = MAGIC_VAL + CV_MAKETYPE(depth, selectedPlane ? 1 : img->nChannels);
442
+ rows = img->roi->height; cols = img->roi->width;
443
+ esz = CV_ELEM_SIZE(flags);
444
+ data = datastart = (uchar*)img->imageData +
445
+ (selectedPlane ? (img->roi->coi - 1)*step*img->height : 0) +
446
+ img->roi->yOffset*step[0] + img->roi->xOffset*esz;
447
+ }
448
+ datalimit = datastart + step.p[0]*rows;
449
+ dataend = datastart + step.p[0]*(rows-1) + esz*cols;
450
+ flags |= (cols*esz == step.p[0] || rows == 1 ? CONTINUOUS_FLAG : 0);
451
+ step[1] = esz;
452
+
453
+ if( copyData )
454
+ {
455
+ Mat m = *this;
456
+ release();
457
+ if( !img->roi || !img->roi->coi ||
458
+ img->dataOrder == IPL_DATA_ORDER_PLANE)
459
+ m.copyTo(*this);
460
+ else
461
+ {
462
+ int ch[] = {img->roi->coi - 1, 0};
463
+ create(m.rows, m.cols, m.type());
464
+ mixChannels(&m, 1, this, 1, ch, 1);
465
+ }
466
+ }
467
+ }
468
+
469
+
470
+ Mat::operator IplImage() const
471
+ {
472
+ CV_Assert( dims <= 2 );
473
+ IplImage img;
474
+ cvInitImageHeader(&img, size(), cvIplDepth(flags), channels());
475
+ cvSetData(&img, data, (int)step[0]);
476
+ return img;
477
+ }
478
+
479
+
480
+ void Mat::pop_back(size_t nelems)
481
+ {
482
+ CV_Assert( nelems <= (size_t)size.p[0] );
483
+
484
+ if( isSubmatrix() )
485
+ *this = rowRange(0, size.p[0] - (int)nelems);
486
+ else
487
+ {
488
+ size.p[0] -= (int)nelems;
489
+ dataend -= nelems*step.p[0];
490
+ /*if( size.p[0] <= 1 )
491
+ {
492
+ if( dims <= 2 )
493
+ flags |= CONTINUOUS_FLAG;
494
+ else
495
+ updateContinuityFlag(*this);
496
+ }*/
497
+ }
498
+ }
499
+
500
+
501
+ void Mat::push_back_(const void* elem)
502
+ {
503
+ int r = size.p[0];
504
+ if( isSubmatrix() || dataend + step.p[0] > datalimit )
505
+ reserve( std::max(r + 1, (r*3+1)/2) );
506
+
507
+ size_t esz = elemSize();
508
+ memcpy(data + r*step.p[0], elem, esz);
509
+ size.p[0] = r + 1;
510
+ dataend += step.p[0];
511
+ if( esz < step.p[0] )
512
+ flags &= ~CONTINUOUS_FLAG;
513
+ }
514
+
515
+ void Mat::reserve(size_t nelems)
516
+ {
517
+ const size_t MIN_SIZE = 64;
518
+
519
+ CV_Assert( (int)nelems >= 0 );
520
+ if( !isSubmatrix() && data + step.p[0]*nelems <= datalimit )
521
+ return;
522
+
523
+ int r = size.p[0];
524
+
525
+ if( (size_t)r >= nelems )
526
+ return;
527
+
528
+ size.p[0] = std::max((int)nelems, 1);
529
+ size_t newsize = total()*elemSize();
530
+
531
+ if( newsize < MIN_SIZE )
532
+ size.p[0] = (int)((MIN_SIZE + newsize - 1)*nelems/newsize);
533
+
534
+ Mat m(dims, size.p, type());
535
+ size.p[0] = r;
536
+ if( r > 0 )
537
+ {
538
+ Mat mpart = m.rowRange(0, r);
539
+ copyTo(mpart);
540
+ }
541
+
542
+ *this = m;
543
+ size.p[0] = r;
544
+ dataend = data + step.p[0]*r;
545
+ }
546
+
547
+
548
+ void Mat::resize(size_t nelems)
549
+ {
550
+ int saveRows = size.p[0];
551
+ if( saveRows == (int)nelems )
552
+ return;
553
+ CV_Assert( (int)nelems >= 0 );
554
+
555
+ if( isSubmatrix() || data + step.p[0]*nelems > datalimit )
556
+ reserve(nelems);
557
+
558
+ size.p[0] = (int)nelems;
559
+ dataend += (size.p[0] - saveRows)*step.p[0];
560
+
561
+ //updateContinuityFlag(*this);
562
+ }
563
+
564
+
565
+ void Mat::resize(size_t nelems, const Scalar& s)
566
+ {
567
+ int saveRows = size.p[0];
568
+ resize(nelems);
569
+
570
+ if( size.p[0] > saveRows )
571
+ {
572
+ Mat part = rowRange(saveRows, size.p[0]);
573
+ part = s;
574
+ }
575
+ }
576
+
577
+ void Mat::push_back(const Mat& elems)
578
+ {
579
+ int r = size.p[0], delta = elems.size.p[0];
580
+ if( delta == 0 )
581
+ return;
582
+ if( this == &elems )
583
+ {
584
+ Mat tmp = elems;
585
+ push_back(tmp);
586
+ return;
587
+ }
588
+ if( !data )
589
+ {
590
+ *this = elems.clone();
591
+ return;
592
+ }
593
+
594
+ size.p[0] = elems.size.p[0];
595
+ bool eq = size == elems.size;
596
+ size.p[0] = r;
597
+ if( !eq )
598
+ CV_Error(CV_StsUnmatchedSizes, "");
599
+ if( type() != elems.type() )
600
+ CV_Error(CV_StsUnmatchedFormats, "");
601
+
602
+ if( isSubmatrix() || dataend + step.p[0]*delta > datalimit )
603
+ reserve( std::max(r + delta, (r*3+1)/2) );
604
+
605
+ size.p[0] += delta;
606
+ dataend += step.p[0]*delta;
607
+
608
+ //updateContinuityFlag(*this);
609
+
610
+ if( isContinuous() && elems.isContinuous() )
611
+ memcpy(data + r*step.p[0], elems.data, elems.total()*elems.elemSize());
612
+ else
613
+ {
614
+ Mat part = rowRange(r, r + delta);
615
+ elems.copyTo(part);
616
+ }
617
+ }
618
+
619
+
620
+ Mat cvarrToMat(const CvArr* arr, bool copyData,
621
+ bool /*allowND*/, int coiMode)
622
+ {
623
+ if( !arr )
624
+ return Mat();
625
+ if( CV_IS_MAT(arr) )
626
+ return Mat((const CvMat*)arr, copyData );
627
+ if( CV_IS_MATND(arr) )
628
+ return Mat((const CvMatND*)arr, copyData );
629
+ if( CV_IS_IMAGE(arr) )
630
+ {
631
+ const IplImage* iplimg = (const IplImage*)arr;
632
+ if( coiMode == 0 && iplimg->roi && iplimg->roi->coi > 0 )
633
+ CV_Error(CV_BadCOI, "COI is not supported by the function");
634
+ return Mat(iplimg, copyData);
635
+ }
636
+ if( CV_IS_SEQ(arr) )
637
+ {
638
+ CvSeq* seq = (CvSeq*)arr;
639
+ CV_Assert(seq->total > 0 && CV_ELEM_SIZE(seq->flags) == seq->elem_size);
640
+ if(!copyData && seq->first->next == seq->first)
641
+ return Mat(seq->total, 1, CV_MAT_TYPE(seq->flags), seq->first->data);
642
+ Mat buf(seq->total, 1, CV_MAT_TYPE(seq->flags));
643
+ cvCvtSeqToArray(seq, buf.data, CV_WHOLE_SEQ);
644
+ return buf;
645
+ }
646
+ CV_Error(CV_StsBadArg, "Unknown array type");
647
+ return Mat();
648
+ }
649
+
650
+ void Mat::locateROI( Size& wholeSize, Point& ofs ) const
651
+ {
652
+ CV_Assert( dims <= 2 && step[0] > 0 );
653
+ size_t esz = elemSize(), minstep;
654
+ ptrdiff_t delta1 = data - datastart, delta2 = dataend - datastart;
655
+
656
+ if( delta1 == 0 )
657
+ ofs.x = ofs.y = 0;
658
+ else
659
+ {
660
+ ofs.y = (int)(delta1/step[0]);
661
+ ofs.x = (int)((delta1 - step[0]*ofs.y)/esz);
662
+ CV_DbgAssert( data == datastart + ofs.y*step[0] + ofs.x*esz );
663
+ }
664
+ minstep = (ofs.x + cols)*esz;
665
+ wholeSize.height = (int)((delta2 - minstep)/step[0] + 1);
666
+ wholeSize.height = std::max(wholeSize.height, ofs.y + rows);
667
+ wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz);
668
+ wholeSize.width = std::max(wholeSize.width, ofs.x + cols);
669
+ }
670
+
671
+ Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright )
672
+ {
673
+ CV_Assert( dims <= 2 && step[0] > 0 );
674
+ Size wholeSize; Point ofs;
675
+ size_t esz = elemSize();
676
+ locateROI( wholeSize, ofs );
677
+ int row1 = std::max(ofs.y - dtop, 0), row2 = std::min(ofs.y + rows + dbottom, wholeSize.height);
678
+ int col1 = std::max(ofs.x - dleft, 0), col2 = std::min(ofs.x + cols + dright, wholeSize.width);
679
+ data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
680
+ rows = row2 - row1; cols = col2 - col1;
681
+ size.p[0] = rows; size.p[1] = cols;
682
+ if( esz*cols == step[0] || rows == 1 )
683
+ flags |= CONTINUOUS_FLAG;
684
+ else
685
+ flags &= ~CONTINUOUS_FLAG;
686
+ return *this;
687
+ }
688
+
689
+ }
690
+
691
+ void cv::extractImageCOI(const CvArr* arr, OutputArray _ch, int coi)
692
+ {
693
+ Mat mat = cvarrToMat(arr, false, true, 1);
694
+ _ch.create(mat.dims, mat.size, mat.depth());
695
+ Mat ch = _ch.getMat();
696
+ if(coi < 0)
697
+ {
698
+ CV_Assert( CV_IS_IMAGE(arr) );
699
+ coi = cvGetImageCOI((const IplImage*)arr)-1;
700
+ }
701
+ CV_Assert(0 <= coi && coi < mat.channels());
702
+ int _pairs[] = { coi, 0 };
703
+ mixChannels( &mat, 1, &ch, 1, _pairs, 1 );
704
+ }
705
+
706
+ void cv::insertImageCOI(InputArray _ch, CvArr* arr, int coi)
707
+ {
708
+ Mat ch = _ch.getMat(), mat = cvarrToMat(arr, false, true, 1);
709
+ if(coi < 0)
710
+ {
711
+ CV_Assert( CV_IS_IMAGE(arr) );
712
+ coi = cvGetImageCOI((const IplImage*)arr)-1;
713
+ }
714
+ CV_Assert(ch.size == mat.size && ch.depth() == mat.depth() && 0 <= coi && coi < mat.channels());
715
+ int _pairs[] = { 0, coi };
716
+ mixChannels( &ch, 1, &mat, 1, _pairs, 1 );
717
+ }
718
+
719
+ namespace cv
720
+ {
721
+
722
+ Mat Mat::reshape(int new_cn, int new_rows) const
723
+ {
724
+ int cn = channels();
725
+ Mat hdr = *this;
726
+
727
+ if( dims > 2 && new_rows == 0 && new_cn != 0 && size[dims-1]*cn % new_cn == 0 )
728
+ {
729
+ hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
730
+ hdr.step[dims-1] = CV_ELEM_SIZE(hdr.flags);
731
+ hdr.size[dims-1] = hdr.size[dims-1]*cn / new_cn;
732
+ return hdr;
733
+ }
734
+
735
+ CV_Assert( dims <= 2 );
736
+
737
+ if( new_cn == 0 )
738
+ new_cn = cn;
739
+
740
+ int total_width = cols * cn;
741
+
742
+ if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 )
743
+ new_rows = rows * total_width / new_cn;
744
+
745
+ if( new_rows != 0 && new_rows != rows )
746
+ {
747
+ int total_size = total_width * rows;
748
+ if( !isContinuous() )
749
+ CV_Error( CV_BadStep,
750
+ "The matrix is not continuous, thus its number of rows can not be changed" );
751
+
752
+ if( (unsigned)new_rows > (unsigned)total_size )
753
+ CV_Error( CV_StsOutOfRange, "Bad new number of rows" );
754
+
755
+ total_width = total_size / new_rows;
756
+
757
+ if( total_width * new_rows != total_size )
758
+ CV_Error( CV_StsBadArg, "The total number of matrix elements "
759
+ "is not divisible by the new number of rows" );
760
+
761
+ hdr.rows = new_rows;
762
+ hdr.step[0] = total_width * elemSize1();
763
+ }
764
+
765
+ int new_width = total_width / new_cn;
766
+
767
+ if( new_width * new_cn != total_width )
768
+ CV_Error( CV_BadNumChannels,
769
+ "The total width is not divisible by the new number of channels" );
770
+
771
+ hdr.cols = new_width;
772
+ hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
773
+ hdr.step[1] = CV_ELEM_SIZE(hdr.flags);
774
+ return hdr;
775
+ }
776
+
777
+
778
+ int Mat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) const
779
+ {
780
+ return (depth() == _depth || _depth <= 0) &&
781
+ (isContinuous() || !_requireContinuous) &&
782
+ ((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) || (cols == _elemChannels))) ||
783
+ (dims == 3 && channels() == 1 && size.p[2] == _elemChannels && (size.p[0] == 1 || size.p[1] == 1) &&
784
+ (isContinuous() || step.p[1] == step.p[2]*size.p[2])))
785
+ ? (int)(total()*channels()/_elemChannels) : -1;
786
+ }
787
+
788
+
789
+ void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
790
+ {
791
+ int i, depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
792
+ CV_Assert(cn <= 4);
793
+ switch(depth)
794
+ {
795
+ case CV_8U:
796
+ {
797
+ uchar* buf = (uchar*)_buf;
798
+ for(i = 0; i < cn; i++)
799
+ buf[i] = saturate_cast<uchar>(s.val[i]);
800
+ for(; i < unroll_to; i++)
801
+ buf[i] = buf[i-cn];
802
+ }
803
+ break;
804
+ case CV_8S:
805
+ {
806
+ schar* buf = (schar*)_buf;
807
+ for(i = 0; i < cn; i++)
808
+ buf[i] = saturate_cast<schar>(s.val[i]);
809
+ for(; i < unroll_to; i++)
810
+ buf[i] = buf[i-cn];
811
+ }
812
+ break;
813
+ case CV_16U:
814
+ {
815
+ ushort* buf = (ushort*)_buf;
816
+ for(i = 0; i < cn; i++)
817
+ buf[i] = saturate_cast<ushort>(s.val[i]);
818
+ for(; i < unroll_to; i++)
819
+ buf[i] = buf[i-cn];
820
+ }
821
+ break;
822
+ case CV_16S:
823
+ {
824
+ short* buf = (short*)_buf;
825
+ for(i = 0; i < cn; i++)
826
+ buf[i] = saturate_cast<short>(s.val[i]);
827
+ for(; i < unroll_to; i++)
828
+ buf[i] = buf[i-cn];
829
+ }
830
+ break;
831
+ case CV_32S:
832
+ {
833
+ int* buf = (int*)_buf;
834
+ for(i = 0; i < cn; i++)
835
+ buf[i] = saturate_cast<int>(s.val[i]);
836
+ for(; i < unroll_to; i++)
837
+ buf[i] = buf[i-cn];
838
+ }
839
+ break;
840
+ case CV_32F:
841
+ {
842
+ float* buf = (float*)_buf;
843
+ for(i = 0; i < cn; i++)
844
+ buf[i] = saturate_cast<float>(s.val[i]);
845
+ for(; i < unroll_to; i++)
846
+ buf[i] = buf[i-cn];
847
+ }
848
+ break;
849
+ case CV_64F:
850
+ {
851
+ double* buf = (double*)_buf;
852
+ for(i = 0; i < cn; i++)
853
+ buf[i] = saturate_cast<double>(s.val[i]);
854
+ for(; i < unroll_to; i++)
855
+ buf[i] = buf[i-cn];
856
+ break;
857
+ }
858
+ default:
859
+ CV_Error(CV_StsUnsupportedFormat,"");
860
+ }
861
+ }
862
+
863
+
864
+ /*************************************************************************************************\
865
+ Input/Output Array
866
+ \*************************************************************************************************/
867
+
868
+ _InputArray::_InputArray() : flags(0), obj(0) {}
869
+ _InputArray::_InputArray(const Mat& m) : flags(MAT), obj((void*)&m) {}
870
+ _InputArray::_InputArray(const vector<Mat>& vec) : flags(STD_VECTOR_MAT), obj((void*)&vec) {}
871
+ _InputArray::_InputArray(const double& val) : flags(MATX+CV_64F), obj((void*)&val), sz(Size(1,1)) {}
872
+ _InputArray::_InputArray(const MatExpr& expr) : flags(EXPR), obj((void*)&expr) {}
873
+
874
+ Mat _InputArray::getMat(int i) const
875
+ {
876
+ int k = kind();
877
+
878
+ if( k == MAT )
879
+ {
880
+ CV_Assert( i < 0 );
881
+ return *(const Mat*)obj;
882
+ }
883
+
884
+ if( k == EXPR )
885
+ {
886
+ CV_Assert( i < 0 );
887
+ return (Mat)*((const MatExpr*)obj);
888
+ }
889
+
890
+ if( k == MATX )
891
+ {
892
+ CV_Assert( i < 0 );
893
+ return Mat(sz, flags, obj);
894
+ }
895
+
896
+ if( k == STD_VECTOR )
897
+ {
898
+ CV_Assert( i < 0 );
899
+ int t = CV_MAT_TYPE(flags);
900
+ const vector<uchar>& v = *(const vector<uchar>*)obj;
901
+
902
+ return !v.empty() ? Mat(size(), t, (void*)&v[0]) : Mat();
903
+ }
904
+
905
+ if( k == NONE )
906
+ return Mat();
907
+
908
+ if( k == STD_VECTOR_VECTOR )
909
+ {
910
+ int t = type(i);
911
+ const vector<vector<uchar> >& vv = *(const vector<vector<uchar> >*)obj;
912
+ CV_Assert( 0 <= i && i < (int)vv.size() );
913
+ const vector<uchar>& v = vv[i];
914
+
915
+ return !v.empty() ? Mat(size(i), t, (void*)&v[0]) : Mat();
916
+ }
917
+
918
+ CV_Assert( k == STD_VECTOR_MAT );
919
+ //if( k == STD_VECTOR_MAT )
920
+ {
921
+ const vector<Mat>& v = *(const vector<Mat>*)obj;
922
+ CV_Assert( 0 <= i && i < (int)v.size() );
923
+
924
+ return v[i];
925
+ }
926
+ }
927
+
928
+
929
+ void _InputArray::getMatVector(vector<Mat>& mv) const
930
+ {
931
+ int k = kind();
932
+
933
+ if( k == MAT )
934
+ {
935
+ const Mat& m = *(const Mat*)obj;
936
+ int i, n = (int)m.size[0];
937
+ mv.resize(n);
938
+
939
+ for( i = 0; i < n; i++ )
940
+ mv[i] = m.dims == 2 ? Mat(1, m.cols, m.type(), (void*)m.ptr(i)) :
941
+ Mat(m.dims-1, &m.size[1], m.type(), (void*)m.ptr(i), &m.step[1]);
942
+ return;
943
+ }
944
+
945
+ if( k == EXPR )
946
+ {
947
+ Mat m = *(const MatExpr*)obj;
948
+ int i, n = m.size[0];
949
+ mv.resize(n);
950
+
951
+ for( i = 0; i < n; i++ )
952
+ mv[i] = m.row(i);
953
+ return;
954
+ }
955
+
956
+ if( k == MATX )
957
+ {
958
+ size_t i, n = sz.height, esz = CV_ELEM_SIZE(flags);
959
+ mv.resize(n);
960
+
961
+ for( i = 0; i < n; i++ )
962
+ mv[i] = Mat(1, sz.width, CV_MAT_TYPE(flags), (uchar*)obj + esz*sz.width*i);
963
+ return;
964
+ }
965
+
966
+ if( k == STD_VECTOR )
967
+ {
968
+ const vector<uchar>& v = *(const vector<uchar>*)obj;
969
+
970
+ size_t i, n = v.size(), esz = CV_ELEM_SIZE(flags);
971
+ int t = CV_MAT_DEPTH(flags), cn = CV_MAT_CN(flags);
972
+ mv.resize(n);
973
+
974
+ for( i = 0; i < n; i++ )
975
+ mv[i] = Mat(1, cn, t, (void*)(&v[0] + esz*i));
976
+ return;
977
+ }
978
+
979
+ if( k == NONE )
980
+ {
981
+ mv.clear();
982
+ return;
983
+ }
984
+
985
+ if( k == STD_VECTOR_VECTOR )
986
+ {
987
+ const vector<vector<uchar> >& vv = *(const vector<vector<uchar> >*)obj;
988
+ int i, n = (int)vv.size();
989
+ int t = CV_MAT_TYPE(flags);
990
+ mv.resize(n);
991
+
992
+ for( i = 0; i < n; i++ )
993
+ {
994
+ const vector<uchar>& v = vv[i];
995
+ mv[i] = Mat(size(i), t, (void*)&v[0]);
996
+ }
997
+ return;
998
+ }
999
+
1000
+ CV_Assert( k == STD_VECTOR_MAT );
1001
+ //if( k == STD_VECTOR_MAT )
1002
+ {
1003
+ const vector<Mat>& v = *(const vector<Mat>*)obj;
1004
+ mv.resize(v.size());
1005
+ std::copy(v.begin(), v.end(), mv.begin());
1006
+ return;
1007
+ }
1008
+ }
1009
+
1010
+ int _InputArray::kind() const
1011
+ {
1012
+ return flags & -(1 << KIND_SHIFT);
1013
+ }
1014
+
1015
+ Size _InputArray::size(int i) const
1016
+ {
1017
+ int k = kind();
1018
+
1019
+ if( k == MAT )
1020
+ {
1021
+ CV_Assert( i < 0 );
1022
+ return ((const Mat*)obj)->size();
1023
+ }
1024
+
1025
+ if( k == EXPR )
1026
+ {
1027
+ CV_Assert( i < 0 );
1028
+ return ((const MatExpr*)obj)->size();
1029
+ }
1030
+
1031
+ if( k == MATX )
1032
+ {
1033
+ CV_Assert( i < 0 );
1034
+ return sz;
1035
+ }
1036
+
1037
+ if( k == STD_VECTOR )
1038
+ {
1039
+ CV_Assert( i < 0 );
1040
+ const vector<uchar>& v = *(const vector<uchar>*)obj;
1041
+ const vector<int>& iv = *(const vector<int>*)obj;
1042
+ size_t szb = v.size(), szi = iv.size();
1043
+ return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1);
1044
+ }
1045
+
1046
+ if( k == NONE )
1047
+ return Size();
1048
+
1049
+ if( k == STD_VECTOR_VECTOR )
1050
+ {
1051
+ const vector<vector<uchar> >& vv = *(const vector<vector<uchar> >*)obj;
1052
+ if( i < 0 )
1053
+ return vv.empty() ? Size() : Size((int)vv.size(), 1);
1054
+ CV_Assert( i < (int)vv.size() );
1055
+ const vector<vector<int> >& ivv = *(const vector<vector<int> >*)obj;
1056
+
1057
+ size_t szb = vv[i].size(), szi = ivv[i].size();
1058
+ return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1);
1059
+ }
1060
+
1061
+ CV_Assert( k == STD_VECTOR_MAT );
1062
+ //if( k == STD_VECTOR_MAT )
1063
+ {
1064
+ const vector<Mat>& vv = *(const vector<Mat>*)obj;
1065
+ if( i < 0 )
1066
+ return vv.empty() ? Size() : Size((int)vv.size(), 1);
1067
+ CV_Assert( i < (int)vv.size() );
1068
+
1069
+ return vv[i].size();
1070
+ }
1071
+ }
1072
+
1073
+ size_t _InputArray::total(int i) const
1074
+ {
1075
+ return size(i).area();
1076
+ }
1077
+
1078
+ int _InputArray::type(int i) const
1079
+ {
1080
+ int k = kind();
1081
+
1082
+ if( k == MAT )
1083
+ return ((const Mat*)obj)->type();
1084
+
1085
+ if( k == EXPR )
1086
+ return ((const MatExpr*)obj)->type();
1087
+
1088
+ if( k == MATX || k == STD_VECTOR || k == STD_VECTOR_VECTOR )
1089
+ return CV_MAT_TYPE(flags);
1090
+
1091
+ if( k == NONE )
1092
+ return -1;
1093
+
1094
+ CV_Assert( k == STD_VECTOR_MAT );
1095
+ //if( k == STD_VECTOR_MAT )
1096
+ {
1097
+ const vector<Mat>& vv = *(const vector<Mat>*)obj;
1098
+ CV_Assert( i < (int)vv.size() );
1099
+
1100
+ return vv[i >= 0 ? i : 0].type();
1101
+ }
1102
+ }
1103
+
1104
+ int _InputArray::depth(int i) const
1105
+ {
1106
+ return CV_MAT_DEPTH(type(i));
1107
+ }
1108
+
1109
+ int _InputArray::channels(int i) const
1110
+ {
1111
+ return CV_MAT_CN(type(i));
1112
+ }
1113
+
1114
+ bool _InputArray::empty() const
1115
+ {
1116
+ int k = kind();
1117
+
1118
+ if( k == MAT )
1119
+ return ((const Mat*)obj)->empty();
1120
+
1121
+ if( k == EXPR )
1122
+ return false;
1123
+
1124
+ if( k == MATX )
1125
+ return false;
1126
+
1127
+ if( k == STD_VECTOR )
1128
+ {
1129
+ const vector<uchar>& v = *(const vector<uchar>*)obj;
1130
+ return v.empty();
1131
+ }
1132
+
1133
+ if( k == NONE )
1134
+ return true;
1135
+
1136
+ if( k == STD_VECTOR_VECTOR )
1137
+ {
1138
+ const vector<vector<uchar> >& vv = *(const vector<vector<uchar> >*)obj;
1139
+ return vv.empty();
1140
+ }
1141
+
1142
+ CV_Assert( k == STD_VECTOR_MAT );
1143
+ //if( k == STD_VECTOR_MAT )
1144
+ {
1145
+ const vector<Mat>& vv = *(const vector<Mat>*)obj;
1146
+ return vv.empty();
1147
+ }
1148
+ }
1149
+
1150
+
1151
+ _OutputArray::_OutputArray() {}
1152
+ _OutputArray::_OutputArray(Mat& m) : _InputArray(m) {}
1153
+ _OutputArray::_OutputArray(vector<Mat>& vec) : _InputArray(vec) {}
1154
+
1155
+ bool _OutputArray::fixedSize() const
1156
+ {
1157
+ int k = kind();
1158
+ return k == MATX;
1159
+ }
1160
+
1161
+ bool _OutputArray::fixedType() const
1162
+ {
1163
+ int k = kind();
1164
+ return k != MAT && k != STD_VECTOR_MAT;
1165
+ }
1166
+
1167
+ void _OutputArray::create(Size _sz, int type, int i, bool allowTransposed, int fixedDepthMask) const
1168
+ {
1169
+ int k = kind();
1170
+ if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
1171
+ {
1172
+ ((Mat*)obj)->create(_sz, type);
1173
+ return;
1174
+ }
1175
+ int sz[] = {_sz.height, _sz.width};
1176
+ create(2, sz, type, i, allowTransposed, fixedDepthMask);
1177
+ }
1178
+
1179
+ void _OutputArray::create(int rows, int cols, int type, int i, bool allowTransposed, int fixedDepthMask) const
1180
+ {
1181
+ int k = kind();
1182
+ if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
1183
+ {
1184
+ ((Mat*)obj)->create(rows, cols, type);
1185
+ return;
1186
+ }
1187
+ int sz[] = {rows, cols};
1188
+ create(2, sz, type, i, allowTransposed, fixedDepthMask);
1189
+ }
1190
+
1191
+ void _OutputArray::create(int dims, const int* size, int type, int i, bool allocateVector, int fixedDepthMask) const
1192
+ {
1193
+ int k = kind();
1194
+ type = CV_MAT_TYPE(type);
1195
+
1196
+ if( k == MAT )
1197
+ {
1198
+ CV_Assert( i < 0 );
1199
+ Mat& m = *(Mat*)obj;
1200
+ if( allocateVector )
1201
+ {
1202
+ if( !m.isContinuous() )
1203
+ m.release();
1204
+
1205
+ if( dims == 2 && m.dims == 2 && m.data &&
1206
+ m.type() == type && m.rows == size[1] && m.cols == size[0] )
1207
+ return;
1208
+ }
1209
+ m.create(dims, size, type);
1210
+ return;
1211
+ }
1212
+
1213
+ if( k == MATX )
1214
+ {
1215
+ CV_Assert( i < 0 );
1216
+ int type0 = CV_MAT_TYPE(flags);
1217
+ CV_Assert( type == type0 || (CV_MAT_CN(type) == 1 && ((1 << type0) & fixedDepthMask) != 0) );
1218
+ CV_Assert( dims == 2 && ((size[0] == sz.height && size[1] == sz.width) ||
1219
+ (allocateVector && size[0] == sz.width && size[1] == sz.height)));
1220
+ return;
1221
+ }
1222
+
1223
+ if( k == STD_VECTOR || k == STD_VECTOR_VECTOR )
1224
+ {
1225
+ CV_Assert( dims == 2 && (size[0] == 1 || size[1] == 1 || size[0]*size[1] == 0) );
1226
+ size_t len = size[0]*size[1] > 0 ? size[0] + size[1] - 1 : 0;
1227
+ vector<uchar>* v = (vector<uchar>*)obj;
1228
+
1229
+ if( k == STD_VECTOR_VECTOR )
1230
+ {
1231
+ vector<vector<uchar> >& vv = *(vector<vector<uchar> >*)obj;
1232
+ if( i < 0 )
1233
+ {
1234
+ vv.resize(len);
1235
+ return;
1236
+ }
1237
+ CV_Assert( i < (int)vv.size() );
1238
+ v = &vv[i];
1239
+ }
1240
+ else
1241
+ CV_Assert( i < 0 );
1242
+
1243
+ int type0 = CV_MAT_TYPE(flags);
1244
+ CV_Assert( type == type0 || (CV_MAT_CN(type) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) );
1245
+
1246
+ int esz = CV_ELEM_SIZE(type0);
1247
+ switch( esz )
1248
+ {
1249
+ case 1:
1250
+ ((vector<uchar>*)v)->resize(len);
1251
+ break;
1252
+ case 2:
1253
+ ((vector<Vec2b>*)v)->resize(len);
1254
+ break;
1255
+ case 3:
1256
+ ((vector<Vec3b>*)v)->resize(len);
1257
+ break;
1258
+ case 4:
1259
+ ((vector<int>*)v)->resize(len);
1260
+ break;
1261
+ case 6:
1262
+ ((vector<Vec3s>*)v)->resize(len);
1263
+ break;
1264
+ case 8:
1265
+ ((vector<Vec2i>*)v)->resize(len);
1266
+ break;
1267
+ case 12:
1268
+ ((vector<Vec3i>*)v)->resize(len);
1269
+ break;
1270
+ case 16:
1271
+ ((vector<Vec4i>*)v)->resize(len);
1272
+ break;
1273
+ case 24:
1274
+ ((vector<Vec6i>*)v)->resize(len);
1275
+ break;
1276
+ case 32:
1277
+ ((vector<Vec8i>*)v)->resize(len);
1278
+ break;
1279
+ case 36:
1280
+ ((vector<Vec<int, 9> >*)v)->resize(len);
1281
+ break;
1282
+ case 48:
1283
+ ((vector<Vec<int, 12> >*)v)->resize(len);
1284
+ break;
1285
+ case 64:
1286
+ ((vector<Vec<int, 16> >*)v)->resize(len);
1287
+ break;
1288
+ case 128:
1289
+ ((vector<Vec<int, 32> >*)v)->resize(len);
1290
+ break;
1291
+ case 256:
1292
+ ((vector<Vec<int, 64> >*)v)->resize(len);
1293
+ break;
1294
+ case 512:
1295
+ ((vector<Vec<int, 128> >*)v)->resize(len);
1296
+ break;
1297
+ default:
1298
+ CV_Error_(CV_StsBadArg, ("Vectors with element size %d are not supported. Please, modify OutputArray::create()\n", esz));
1299
+ }
1300
+ return;
1301
+ }
1302
+
1303
+ if( k == NONE )
1304
+ {
1305
+ CV_Error(CV_StsNullPtr, "create() called for the missing output array" );
1306
+ return;
1307
+ }
1308
+
1309
+ CV_Assert( k == STD_VECTOR_MAT );
1310
+ //if( k == STD_VECTOR_MAT )
1311
+ {
1312
+ vector<Mat>& v = *(vector<Mat>*)obj;
1313
+
1314
+ if( i < 0 )
1315
+ {
1316
+ CV_Assert( dims == 2 && (size[0] == 1 || size[1] == 1 || size[0]*size[1] == 0) );
1317
+ size_t len = size[0]*size[1] > 0 ? size[0] + size[1] - 1 : 0;
1318
+
1319
+ v.resize(len);
1320
+ return;
1321
+ }
1322
+
1323
+ CV_Assert( i < (int)v.size() );
1324
+ Mat& m = v[i];
1325
+
1326
+ if( allocateVector )
1327
+ {
1328
+ if( !m.isContinuous() )
1329
+ m.release();
1330
+
1331
+ if( dims == 2 && m.dims == 2 && m.data &&
1332
+ m.type() == type && m.rows == size[1] && m.cols == size[0] )
1333
+ return;
1334
+ }
1335
+ m.create(dims, size, type);
1336
+ }
1337
+ }
1338
+
1339
+ void _OutputArray::release() const
1340
+ {
1341
+ int k = kind();
1342
+
1343
+ if( k == MAT )
1344
+ {
1345
+ ((Mat*)obj)->release();
1346
+ return;
1347
+ }
1348
+
1349
+ if( k == NONE )
1350
+ return;
1351
+
1352
+ if( k == STD_VECTOR )
1353
+ {
1354
+ create(Size(), CV_MAT_TYPE(flags));
1355
+ return;
1356
+ }
1357
+
1358
+ if( k == STD_VECTOR_VECTOR )
1359
+ {
1360
+ ((vector<vector<uchar> >*)obj)->clear();
1361
+ return;
1362
+ }
1363
+
1364
+ CV_Assert( k == STD_VECTOR_MAT );
1365
+ //if( k == STD_VECTOR_MAT )
1366
+ {
1367
+ ((vector<Mat>*)obj)->clear();
1368
+ }
1369
+ }
1370
+
1371
+ void _OutputArray::clear() const
1372
+ {
1373
+ int k = kind();
1374
+
1375
+ if( k == MAT )
1376
+ {
1377
+ ((Mat*)obj)->resize(0);
1378
+ return;
1379
+ }
1380
+
1381
+ release();
1382
+ }
1383
+
1384
+ bool _OutputArray::needed() const
1385
+ {
1386
+ return kind() != NONE;
1387
+ }
1388
+
1389
+ Mat& _OutputArray::getMatRef(int i) const
1390
+ {
1391
+ int k = kind();
1392
+ if( i < 0 )
1393
+ {
1394
+ CV_Assert( k == MAT );
1395
+ return *(Mat*)obj;
1396
+ }
1397
+ else
1398
+ {
1399
+ CV_Assert( k == STD_VECTOR_MAT );
1400
+ vector<Mat>& v = *(vector<Mat>*)obj;
1401
+ CV_Assert( i < (int)v.size() );
1402
+ return v[i];
1403
+ }
1404
+ }
1405
+
1406
+ static _OutputArray _none;
1407
+ OutputArray noArray() { return _none; }
1408
+
1409
+ }
1410
+
1411
+ /*************************************************************************************************\
1412
+ Matrix Operations
1413
+ \*************************************************************************************************/
1414
+
1415
+ void cv::hconcat(const Mat* src, size_t nsrc, OutputArray _dst)
1416
+ {
1417
+ if( nsrc == 0 || !src )
1418
+ {
1419
+ _dst.release();
1420
+ return;
1421
+ }
1422
+
1423
+ int totalCols = 0, cols = 0;
1424
+ size_t i;
1425
+ for( i = 0; i < nsrc; i++ )
1426
+ {
1427
+ CV_Assert( !src[i].empty() && src[i].dims <= 2 &&
1428
+ src[i].rows == src[0].rows &&
1429
+ src[i].type() == src[0].type());
1430
+ totalCols += src[i].cols;
1431
+ }
1432
+ _dst.create( src[0].rows, totalCols, src[0].type());
1433
+ Mat dst = _dst.getMat();
1434
+ for( i = 0; i < nsrc; i++ )
1435
+ {
1436
+ Mat dpart = dst(Rect(cols, 0, src[i].cols, src[i].rows));
1437
+ src[i].copyTo(dpart);
1438
+ cols += src[i].cols;
1439
+ }
1440
+ }
1441
+
1442
+ void cv::hconcat(InputArray src1, InputArray src2, OutputArray dst)
1443
+ {
1444
+ Mat src[] = {src1.getMat(), src2.getMat()};
1445
+ hconcat(src, 2, dst);
1446
+ }
1447
+
1448
+ void cv::hconcat(InputArray _src, OutputArray dst)
1449
+ {
1450
+ vector<Mat> src;
1451
+ _src.getMatVector(src);
1452
+ hconcat(!src.empty() ? &src[0] : 0, src.size(), dst);
1453
+ }
1454
+
1455
+ void cv::vconcat(const Mat* src, size_t nsrc, OutputArray _dst)
1456
+ {
1457
+ if( nsrc == 0 || !src )
1458
+ {
1459
+ _dst.release();
1460
+ return;
1461
+ }
1462
+
1463
+ int totalRows = 0, rows = 0;
1464
+ size_t i;
1465
+ for( i = 0; i < nsrc; i++ )
1466
+ {
1467
+ CV_Assert( !src[i].empty() && src[i].dims <= 2 &&
1468
+ src[i].cols == src[0].cols &&
1469
+ src[i].type() == src[0].type());
1470
+ totalRows += src[i].rows;
1471
+ }
1472
+ _dst.create( totalRows, src[0].cols, src[0].type());
1473
+ Mat dst = _dst.getMat();
1474
+ for( i = 0; i < nsrc; i++ )
1475
+ {
1476
+ Mat dpart(dst, Rect(0, rows, src[i].cols, src[i].rows));
1477
+ src[i].copyTo(dpart);
1478
+ rows += src[i].rows;
1479
+ }
1480
+ }
1481
+
1482
+ void cv::vconcat(InputArray src1, InputArray src2, OutputArray dst)
1483
+ {
1484
+ Mat src[] = {src1.getMat(), src2.getMat()};
1485
+ vconcat(src, 2, dst);
1486
+ }
1487
+
1488
+ void cv::vconcat(InputArray _src, OutputArray dst)
1489
+ {
1490
+ vector<Mat> src;
1491
+ _src.getMatVector(src);
1492
+ vconcat(!src.empty() ? &src[0] : 0, src.size(), dst);
1493
+ }
1494
+
1495
+ //////////////////////////////////////// set identity ////////////////////////////////////////////
1496
+ void cv::setIdentity( InputOutputArray _m, const Scalar& s )
1497
+ {
1498
+ Mat m = _m.getMat();
1499
+ CV_Assert( m.dims <= 2 );
1500
+ int i, j, rows = m.rows, cols = m.cols, type = m.type();
1501
+
1502
+ if( type == CV_32FC1 )
1503
+ {
1504
+ float* data = (float*)m.data;
1505
+ float val = (float)s[0];
1506
+ size_t step = m.step/sizeof(data[0]);
1507
+
1508
+ for( i = 0; i < rows; i++, data += step )
1509
+ {
1510
+ for( j = 0; j < cols; j++ )
1511
+ data[j] = 0;
1512
+ if( i < cols )
1513
+ data[i] = val;
1514
+ }
1515
+ }
1516
+ else if( type == CV_64FC1 )
1517
+ {
1518
+ double* data = (double*)m.data;
1519
+ double val = s[0];
1520
+ size_t step = m.step/sizeof(data[0]);
1521
+
1522
+ for( i = 0; i < rows; i++, data += step )
1523
+ {
1524
+ for( j = 0; j < cols; j++ )
1525
+ data[j] = j == i ? val : 0;
1526
+ }
1527
+ }
1528
+ else
1529
+ {
1530
+ m = Scalar(0);
1531
+ m.diag() = s;
1532
+ }
1533
+ }
1534
+
1535
+ //////////////////////////////////////////// trace ///////////////////////////////////////////
1536
+
1537
+ cv::Scalar cv::trace( InputArray _m )
1538
+ {
1539
+ Mat m = _m.getMat();
1540
+ CV_Assert( m.dims <= 2 );
1541
+ int i, type = m.type();
1542
+ int nm = std::min(m.rows, m.cols);
1543
+
1544
+ if( type == CV_32FC1 )
1545
+ {
1546
+ const float* ptr = (const float*)m.data;
1547
+ size_t step = m.step/sizeof(ptr[0]) + 1;
1548
+ double _s = 0;
1549
+ for( i = 0; i < nm; i++ )
1550
+ _s += ptr[i*step];
1551
+ return _s;
1552
+ }
1553
+
1554
+ if( type == CV_64FC1 )
1555
+ {
1556
+ const double* ptr = (const double*)m.data;
1557
+ size_t step = m.step/sizeof(ptr[0]) + 1;
1558
+ double _s = 0;
1559
+ for( i = 0; i < nm; i++ )
1560
+ _s += ptr[i*step];
1561
+ return _s;
1562
+ }
1563
+
1564
+ return cv::sum(m.diag());
1565
+ }
1566
+
1567
+ ////////////////////////////////////// transpose /////////////////////////////////////////
1568
+
1569
+ namespace cv
1570
+ {
1571
+
1572
+ template<typename T> static void
1573
+ transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz )
1574
+ {
1575
+ int i, j, m = sz.width, n = sz.height;
1576
+
1577
+ for( i = 0; i <= m - 4; i += 4 )
1578
+ {
1579
+ T* d0 = (T*)(dst + dstep*i);
1580
+ T* d1 = (T*)(dst + dstep*(i+1));
1581
+ T* d2 = (T*)(dst + dstep*(i+2));
1582
+ T* d3 = (T*)(dst + dstep*(i+3));
1583
+
1584
+ for( j = 0; j <= n - 4; j += 4 )
1585
+ {
1586
+ const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
1587
+ const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
1588
+ const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
1589
+ const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
1590
+
1591
+ d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
1592
+ d1[j] = s0[1]; d1[j+1] = s1[1]; d1[j+2] = s2[1]; d1[j+3] = s3[1];
1593
+ d2[j] = s0[2]; d2[j+1] = s1[2]; d2[j+2] = s2[2]; d2[j+3] = s3[2];
1594
+ d3[j] = s0[3]; d3[j+1] = s1[3]; d3[j+2] = s2[3]; d3[j+3] = s3[3];
1595
+ }
1596
+
1597
+ for( ; j < n; j++ )
1598
+ {
1599
+ const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
1600
+ d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3];
1601
+ }
1602
+ }
1603
+
1604
+ for( ; i < m; i++ )
1605
+ {
1606
+ T* d0 = (T*)(dst + dstep*i);
1607
+
1608
+ for( j = 0; j <= n - 4; j += 4 )
1609
+ {
1610
+ const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
1611
+ const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
1612
+ const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
1613
+ const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
1614
+
1615
+ d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
1616
+ }
1617
+
1618
+ for( ; j < n; j++ )
1619
+ {
1620
+ const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
1621
+ d0[j] = s0[0];
1622
+ }
1623
+ }
1624
+ }
1625
+
1626
+ template<typename T> static void
1627
+ transposeI_( uchar* data, size_t step, int n )
1628
+ {
1629
+ int i, j;
1630
+ for( i = 0; i < n; i++ )
1631
+ {
1632
+ T* row = (T*)(data + step*i);
1633
+ uchar* data1 = data + i*sizeof(T);
1634
+ for( j = i+1; j < n; j++ )
1635
+ std::swap( row[j], *(T*)(data1 + step*j) );
1636
+ }
1637
+ }
1638
+
1639
+ typedef void (*TransposeFunc)( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz );
1640
+ typedef void (*TransposeInplaceFunc)( uchar* data, size_t step, int n );
1641
+
1642
+ #define DEF_TRANSPOSE_FUNC(suffix, type) \
1643
+ static void transpose_##suffix( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) \
1644
+ { transpose_<type>(src, sstep, dst, dstep, sz); } \
1645
+ \
1646
+ static void transposeI_##suffix( uchar* data, size_t step, int n ) \
1647
+ { transposeI_<type>(data, step, n); }
1648
+
1649
+ DEF_TRANSPOSE_FUNC(8u, uchar)
1650
+ DEF_TRANSPOSE_FUNC(16u, ushort)
1651
+ DEF_TRANSPOSE_FUNC(8uC3, Vec3b)
1652
+ DEF_TRANSPOSE_FUNC(32s, int)
1653
+ DEF_TRANSPOSE_FUNC(16uC3, Vec3s)
1654
+ DEF_TRANSPOSE_FUNC(32sC2, Vec2i)
1655
+ DEF_TRANSPOSE_FUNC(32sC3, Vec3i)
1656
+ DEF_TRANSPOSE_FUNC(32sC4, Vec4i)
1657
+ DEF_TRANSPOSE_FUNC(32sC6, Vec6i)
1658
+ DEF_TRANSPOSE_FUNC(32sC8, Vec8i)
1659
+
1660
+ static TransposeFunc transposeTab[] =
1661
+ {
1662
+ 0, transpose_8u, transpose_16u, transpose_8uC3, transpose_32s, 0, transpose_16uC3, 0,
1663
+ transpose_32sC2, 0, 0, 0, transpose_32sC3, 0, 0, 0, transpose_32sC4,
1664
+ 0, 0, 0, 0, 0, 0, 0, transpose_32sC6, 0, 0, 0, 0, 0, 0, 0, transpose_32sC8
1665
+ };
1666
+
1667
+ static TransposeInplaceFunc transposeInplaceTab[] =
1668
+ {
1669
+ 0, transposeI_8u, transposeI_16u, transposeI_8uC3, transposeI_32s, 0, transposeI_16uC3, 0,
1670
+ transposeI_32sC2, 0, 0, 0, transposeI_32sC3, 0, 0, 0, transposeI_32sC4,
1671
+ 0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8
1672
+ };
1673
+
1674
+ }
1675
+
1676
+ void cv::transpose( InputArray _src, OutputArray _dst )
1677
+ {
1678
+ Mat src = _src.getMat();
1679
+ size_t esz = src.elemSize();
1680
+ CV_Assert( src.dims <= 2 && esz <= (size_t)32 );
1681
+
1682
+ _dst.create(src.cols, src.rows, src.type());
1683
+ Mat dst = _dst.getMat();
1684
+
1685
+ if( dst.data == src.data )
1686
+ {
1687
+ TransposeInplaceFunc func = transposeInplaceTab[esz];
1688
+ CV_Assert( func != 0 );
1689
+ func( dst.data, dst.step, dst.rows );
1690
+ }
1691
+ else
1692
+ {
1693
+ TransposeFunc func = transposeTab[esz];
1694
+ CV_Assert( func != 0 );
1695
+ func( src.data, src.step, dst.data, dst.step, src.size() );
1696
+ }
1697
+ }
1698
+
1699
+
1700
+ void cv::completeSymm( InputOutputArray _m, bool LtoR )
1701
+ {
1702
+ Mat m = _m.getMat();
1703
+ CV_Assert( m.dims <= 2 );
1704
+
1705
+ int i, j, nrows = m.rows, type = m.type();
1706
+ int j0 = 0, j1 = nrows;
1707
+ CV_Assert( m.rows == m.cols );
1708
+
1709
+ if( type == CV_32FC1 || type == CV_32SC1 )
1710
+ {
1711
+ int* data = (int*)m.data;
1712
+ size_t step = m.step/sizeof(data[0]);
1713
+ for( i = 0; i < nrows; i++ )
1714
+ {
1715
+ if( !LtoR ) j1 = i; else j0 = i+1;
1716
+ for( j = j0; j < j1; j++ )
1717
+ data[i*step + j] = data[j*step + i];
1718
+ }
1719
+ }
1720
+ else if( type == CV_64FC1 )
1721
+ {
1722
+ double* data = (double*)m.data;
1723
+ size_t step = m.step/sizeof(data[0]);
1724
+ for( i = 0; i < nrows; i++ )
1725
+ {
1726
+ if( !LtoR ) j1 = i; else j0 = i+1;
1727
+ for( j = j0; j < j1; j++ )
1728
+ data[i*step + j] = data[j*step + i];
1729
+ }
1730
+ }
1731
+ else
1732
+ CV_Error( CV_StsUnsupportedFormat, "" );
1733
+ }
1734
+
1735
+
1736
+ cv::Mat cv::Mat::cross(InputArray _m) const
1737
+ {
1738
+ Mat m = _m.getMat();
1739
+ int t = type(), d = CV_MAT_DEPTH(t);
1740
+ CV_Assert( dims <= 2 && m.dims <= 2 && size() == m.size() && t == m.type() &&
1741
+ ((rows == 3 && cols == 1) || (cols*channels() == 3 && rows == 1)));
1742
+ Mat result(rows, cols, t);
1743
+
1744
+ if( d == CV_32F )
1745
+ {
1746
+ const float *a = (const float*)data, *b = (const float*)m.data;
1747
+ float* c = (float*)result.data;
1748
+ size_t lda = rows > 1 ? step/sizeof(a[0]) : 1;
1749
+ size_t ldb = rows > 1 ? m.step/sizeof(b[0]) : 1;
1750
+
1751
+ c[0] = a[lda] * b[ldb*2] - a[lda*2] * b[ldb];
1752
+ c[1] = a[lda*2] * b[0] - a[0] * b[ldb*2];
1753
+ c[2] = a[0] * b[ldb] - a[lda] * b[0];
1754
+ }
1755
+ else if( d == CV_64F )
1756
+ {
1757
+ const double *a = (const double*)data, *b = (const double*)m.data;
1758
+ double* c = (double*)result.data;
1759
+ size_t lda = rows > 1 ? step/sizeof(a[0]) : 1;
1760
+ size_t ldb = rows > 1 ? m.step/sizeof(b[0]) : 1;
1761
+
1762
+ c[0] = a[lda] * b[ldb*2] - a[lda*2] * b[ldb];
1763
+ c[1] = a[lda*2] * b[0] - a[0] * b[ldb*2];
1764
+ c[2] = a[0] * b[ldb] - a[lda] * b[0];
1765
+ }
1766
+
1767
+ return result;
1768
+ }
1769
+
1770
+
1771
+ ////////////////////////////////////////// reduce ////////////////////////////////////////////
1772
+
1773
+ namespace cv
1774
+ {
1775
+
1776
+ template<typename T, typename ST, class Op> static void
1777
+ reduceR_( const Mat& srcmat, Mat& dstmat )
1778
+ {
1779
+ typedef typename Op::rtype WT;
1780
+ Size size = srcmat.size();
1781
+ size.width *= srcmat.channels();
1782
+ AutoBuffer<WT> buffer(size.width);
1783
+ WT* buf = buffer;
1784
+ ST* dst = (ST*)dstmat.data;
1785
+ const T* src = (const T*)srcmat.data;
1786
+ size_t srcstep = srcmat.step/sizeof(src[0]);
1787
+ int i;
1788
+ Op op;
1789
+
1790
+ for( i = 0; i < size.width; i++ )
1791
+ buf[i] = src[i];
1792
+
1793
+ for( ; --size.height; )
1794
+ {
1795
+ src += srcstep;
1796
+ for( i = 0; i <= size.width - 4; i += 4 )
1797
+ {
1798
+ WT s0, s1;
1799
+ s0 = op(buf[i], (WT)src[i]);
1800
+ s1 = op(buf[i+1], (WT)src[i+1]);
1801
+ buf[i] = s0; buf[i+1] = s1;
1802
+
1803
+ s0 = op(buf[i+2], (WT)src[i+2]);
1804
+ s1 = op(buf[i+3], (WT)src[i+3]);
1805
+ buf[i+2] = s0; buf[i+3] = s1;
1806
+ }
1807
+
1808
+ for( ; i < size.width; i++ )
1809
+ buf[i] = op(buf[i], (WT)src[i]);
1810
+ }
1811
+
1812
+ for( i = 0; i < size.width; i++ )
1813
+ dst[i] = (ST)buf[i];
1814
+ }
1815
+
1816
+
1817
+ template<typename T, typename ST, class Op> static void
1818
+ reduceC_( const Mat& srcmat, Mat& dstmat )
1819
+ {
1820
+ typedef typename Op::rtype WT;
1821
+ Size size = srcmat.size();
1822
+ int i, k, cn = srcmat.channels();
1823
+ size.width *= cn;
1824
+ Op op;
1825
+
1826
+ for( int y = 0; y < size.height; y++ )
1827
+ {
1828
+ const T* src = (const T*)(srcmat.data + srcmat.step*y);
1829
+ ST* dst = (ST*)(dstmat.data + dstmat.step*y);
1830
+ if( size.width == cn )
1831
+ for( k = 0; k < cn; k++ )
1832
+ dst[k] = src[k];
1833
+ else
1834
+ {
1835
+ for( k = 0; k < cn; k++ )
1836
+ {
1837
+ WT a0 = src[k], a1 = src[k+cn];
1838
+ for( i = 2*cn; i <= size.width - 4*cn; i += 4*cn )
1839
+ {
1840
+ a0 = op(a0, (WT)src[i+k]);
1841
+ a1 = op(a1, (WT)src[i+k+cn]);
1842
+ a0 = op(a0, (WT)src[i+k+cn*2]);
1843
+ a1 = op(a1, (WT)src[i+k+cn*3]);
1844
+ }
1845
+
1846
+ for( ; i < size.width; i += cn )
1847
+ {
1848
+ a0 = op(a0, (WT)src[i]);
1849
+ }
1850
+ a0 = op(a0, a1);
1851
+ dst[k] = (ST)a0;
1852
+ }
1853
+ }
1854
+ }
1855
+ }
1856
+
1857
+ typedef void (*ReduceFunc)( const Mat& src, Mat& dst );
1858
+
1859
+ }
1860
+
1861
+ void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype)
1862
+ {
1863
+ Mat src = _src.getMat();
1864
+ CV_Assert( src.dims <= 2 );
1865
+ int op0 = op;
1866
+ int stype = src.type(), sdepth = src.depth(), cn = src.channels();
1867
+ if( dtype < 0 )
1868
+ dtype = _dst.fixedType() ? _dst.type() : stype;
1869
+ int ddepth = CV_MAT_DEPTH(dtype);
1870
+
1871
+ _dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1,
1872
+ CV_MAKETYPE(dtype >= 0 ? dtype : stype, cn));
1873
+ Mat dst = _dst.getMat(), temp = dst;
1874
+
1875
+ CV_Assert( op == CV_REDUCE_SUM || op == CV_REDUCE_MAX ||
1876
+ op == CV_REDUCE_MIN || op == CV_REDUCE_AVG );
1877
+ CV_Assert( src.channels() == dst.channels() );
1878
+
1879
+ if( op == CV_REDUCE_AVG )
1880
+ {
1881
+ op = CV_REDUCE_SUM;
1882
+ if( sdepth < CV_32S && ddepth < CV_32S )
1883
+ {
1884
+ temp.create(dst.rows, dst.cols, CV_32SC(cn));
1885
+ ddepth = CV_32S;
1886
+ }
1887
+ }
1888
+
1889
+ ReduceFunc func = 0;
1890
+ if( dim == 0 )
1891
+ {
1892
+ if( op == CV_REDUCE_SUM )
1893
+ {
1894
+ if(sdepth == CV_8U && ddepth == CV_32S)
1895
+ func = reduceR_<uchar,int,OpAdd<int> >;
1896
+ else if(sdepth == CV_8U && ddepth == CV_32F)
1897
+ func = reduceR_<uchar,float,OpAdd<int> >;
1898
+ else if(sdepth == CV_8U && ddepth == CV_64F)
1899
+ func = reduceR_<uchar,double,OpAdd<int> >;
1900
+ else if(sdepth == CV_16U && ddepth == CV_32F)
1901
+ func = reduceR_<ushort,float,OpAdd<float> >;
1902
+ else if(sdepth == CV_16U && ddepth == CV_64F)
1903
+ func = reduceR_<ushort,double,OpAdd<double> >;
1904
+ else if(sdepth == CV_16S && ddepth == CV_32F)
1905
+ func = reduceR_<short,float,OpAdd<float> >;
1906
+ else if(sdepth == CV_16S && ddepth == CV_64F)
1907
+ func = reduceR_<short,double,OpAdd<double> >;
1908
+ else if(sdepth == CV_32F && ddepth == CV_32F)
1909
+ func = reduceR_<float,float,OpAdd<float> >;
1910
+ else if(sdepth == CV_32F && ddepth == CV_64F)
1911
+ func = reduceR_<float,double,OpAdd<double> >;
1912
+ else if(sdepth == CV_64F && ddepth == CV_64F)
1913
+ func = reduceR_<double,double,OpAdd<double> >;
1914
+ }
1915
+ else if(op == CV_REDUCE_MAX)
1916
+ {
1917
+ if(sdepth == CV_8U && ddepth == CV_8U)
1918
+ func = reduceR_<uchar, uchar, OpMax<uchar> >;
1919
+ else if(sdepth == CV_16U && ddepth == CV_16U)
1920
+ func = reduceR_<ushort, ushort, OpMax<ushort> >;
1921
+ else if(sdepth == CV_16S && ddepth == CV_16S)
1922
+ func = reduceR_<short, short, OpMax<short> >;
1923
+ else if(sdepth == CV_32F && ddepth == CV_32F)
1924
+ func = reduceR_<float, float, OpMax<float> >;
1925
+ else if(sdepth == CV_64F && ddepth == CV_64F)
1926
+ func = reduceR_<double, double, OpMax<double> >;
1927
+ }
1928
+ else if(op == CV_REDUCE_MIN)
1929
+ {
1930
+ if(sdepth == CV_8U && ddepth == CV_8U)
1931
+ func = reduceR_<uchar, uchar, OpMin<uchar> >;
1932
+ else if(sdepth == CV_16U && ddepth == CV_16U)
1933
+ func = reduceR_<ushort, ushort, OpMin<ushort> >;
1934
+ else if(sdepth == CV_16S && ddepth == CV_16S)
1935
+ func = reduceR_<short, short, OpMin<short> >;
1936
+ else if(sdepth == CV_32F && ddepth == CV_32F)
1937
+ func = reduceR_<float, float, OpMin<float> >;
1938
+ else if(sdepth == CV_64F && ddepth == CV_64F)
1939
+ func = reduceR_<double, double, OpMin<double> >;
1940
+ }
1941
+ }
1942
+ else
1943
+ {
1944
+ if(op == CV_REDUCE_SUM)
1945
+ {
1946
+ if(sdepth == CV_8U && ddepth == CV_32S)
1947
+ func = reduceC_<uchar,int,OpAdd<int> >;
1948
+ else if(sdepth == CV_8U && ddepth == CV_32F)
1949
+ func = reduceC_<uchar,float,OpAdd<int> >;
1950
+ else if(sdepth == CV_8U && ddepth == CV_64F)
1951
+ func = reduceC_<uchar,double,OpAdd<int> >;
1952
+ else if(sdepth == CV_16U && ddepth == CV_32F)
1953
+ func = reduceC_<ushort,float,OpAdd<float> >;
1954
+ else if(sdepth == CV_16U && ddepth == CV_64F)
1955
+ func = reduceC_<ushort,double,OpAdd<double> >;
1956
+ else if(sdepth == CV_16S && ddepth == CV_32F)
1957
+ func = reduceC_<short,float,OpAdd<float> >;
1958
+ else if(sdepth == CV_16S && ddepth == CV_64F)
1959
+ func = reduceC_<short,double,OpAdd<double> >;
1960
+ else if(sdepth == CV_32F && ddepth == CV_32F)
1961
+ func = reduceC_<float,float,OpAdd<float> >;
1962
+ else if(sdepth == CV_32F && ddepth == CV_64F)
1963
+ func = reduceC_<float,double,OpAdd<double> >;
1964
+ else if(sdepth == CV_64F && ddepth == CV_64F)
1965
+ func = reduceC_<double,double,OpAdd<double> >;
1966
+ }
1967
+ else if(op == CV_REDUCE_MAX)
1968
+ {
1969
+ if(sdepth == CV_8U && ddepth == CV_8U)
1970
+ func = reduceC_<uchar, uchar, OpMax<uchar> >;
1971
+ else if(sdepth == CV_16U && ddepth == CV_16U)
1972
+ func = reduceC_<ushort, ushort, OpMax<ushort> >;
1973
+ else if(sdepth == CV_16S && ddepth == CV_16S)
1974
+ func = reduceC_<short, short, OpMax<short> >;
1975
+ else if(sdepth == CV_32F && ddepth == CV_32F)
1976
+ func = reduceC_<float, float, OpMax<float> >;
1977
+ else if(sdepth == CV_64F && ddepth == CV_64F)
1978
+ func = reduceC_<double, double, OpMax<double> >;
1979
+ }
1980
+ else if(op == CV_REDUCE_MIN)
1981
+ {
1982
+ if(sdepth == CV_8U && ddepth == CV_8U)
1983
+ func = reduceC_<uchar, uchar, OpMin<uchar> >;
1984
+ else if(sdepth == CV_16U && ddepth == CV_16U)
1985
+ func = reduceC_<ushort, ushort, OpMin<ushort> >;
1986
+ else if(sdepth == CV_16S && ddepth == CV_16S)
1987
+ func = reduceC_<short, short, OpMin<short> >;
1988
+ else if(sdepth == CV_32F && ddepth == CV_32F)
1989
+ func = reduceC_<float, float, OpMin<float> >;
1990
+ else if(sdepth == CV_64F && ddepth == CV_64F)
1991
+ func = reduceC_<double, double, OpMin<double> >;
1992
+ }
1993
+ }
1994
+
1995
+ if( !func )
1996
+ CV_Error( CV_StsUnsupportedFormat,
1997
+ "Unsupported combination of input and output array formats" );
1998
+
1999
+ func( src, temp );
2000
+
2001
+ if( op0 == CV_REDUCE_AVG )
2002
+ temp.convertTo(dst, dst.type(), 1./(dim == 0 ? src.rows : src.cols));
2003
+ }
2004
+
2005
+
2006
+ //////////////////////////////////////// sort ///////////////////////////////////////////
2007
+
2008
+ namespace cv
2009
+ {
2010
+
2011
+ template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
2012
+ {
2013
+ AutoBuffer<T> buf;
2014
+ T* bptr;
2015
+ int i, j, n, len;
2016
+ bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
2017
+ bool inplace = src.data == dst.data;
2018
+ bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;
2019
+
2020
+ if( sortRows )
2021
+ n = src.rows, len = src.cols;
2022
+ else
2023
+ {
2024
+ n = src.cols, len = src.rows;
2025
+ buf.allocate(len);
2026
+ }
2027
+ bptr = (T*)buf;
2028
+
2029
+ for( i = 0; i < n; i++ )
2030
+ {
2031
+ T* ptr = bptr;
2032
+ if( sortRows )
2033
+ {
2034
+ T* dptr = (T*)(dst.data + dst.step*i);
2035
+ if( !inplace )
2036
+ {
2037
+ const T* sptr = (const T*)(src.data + src.step*i);
2038
+ for( j = 0; j < len; j++ )
2039
+ dptr[j] = sptr[j];
2040
+ }
2041
+ ptr = dptr;
2042
+ }
2043
+ else
2044
+ {
2045
+ for( j = 0; j < len; j++ )
2046
+ ptr[j] = ((const T*)(src.data + src.step*j))[i];
2047
+ }
2048
+ std::sort( ptr, ptr + len, LessThan<T>() );
2049
+ if( sortDescending )
2050
+ for( j = 0; j < len/2; j++ )
2051
+ std::swap(ptr[j], ptr[len-1-j]);
2052
+ if( !sortRows )
2053
+ for( j = 0; j < len; j++ )
2054
+ ((T*)(dst.data + dst.step*j))[i] = ptr[j];
2055
+ }
2056
+ }
2057
+
2058
+
2059
+ template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
2060
+ {
2061
+ AutoBuffer<T> buf;
2062
+ AutoBuffer<int> ibuf;
2063
+ T* bptr;
2064
+ int* _iptr;
2065
+ int i, j, n, len;
2066
+ bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
2067
+ bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;
2068
+
2069
+ CV_Assert( src.data != dst.data );
2070
+
2071
+ if( sortRows )
2072
+ n = src.rows, len = src.cols;
2073
+ else
2074
+ {
2075
+ n = src.cols, len = src.rows;
2076
+ buf.allocate(len);
2077
+ ibuf.allocate(len);
2078
+ }
2079
+ bptr = (T*)buf;
2080
+ _iptr = (int*)ibuf;
2081
+
2082
+ for( i = 0; i < n; i++ )
2083
+ {
2084
+ T* ptr = bptr;
2085
+ int* iptr = _iptr;
2086
+
2087
+ if( sortRows )
2088
+ {
2089
+ ptr = (T*)(src.data + src.step*i);
2090
+ iptr = (int*)(dst.data + dst.step*i);
2091
+ }
2092
+ else
2093
+ {
2094
+ for( j = 0; j < len; j++ )
2095
+ ptr[j] = ((const T*)(src.data + src.step*j))[i];
2096
+ }
2097
+ for( j = 0; j < len; j++ )
2098
+ iptr[j] = j;
2099
+ std::sort( iptr, iptr + len, LessThanIdx<T>(ptr) );
2100
+ if( sortDescending )
2101
+ for( j = 0; j < len/2; j++ )
2102
+ std::swap(iptr[j], iptr[len-1-j]);
2103
+ if( !sortRows )
2104
+ for( j = 0; j < len; j++ )
2105
+ ((int*)(dst.data + dst.step*j))[i] = iptr[j];
2106
+ }
2107
+ }
2108
+
2109
+ typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags);
2110
+
2111
+ }
2112
+
2113
+ void cv::sort( InputArray _src, OutputArray _dst, int flags )
2114
+ {
2115
+ static SortFunc tab[] =
2116
+ {
2117
+ sort_<uchar>, sort_<schar>, sort_<ushort>, sort_<short>,
2118
+ sort_<int>, sort_<float>, sort_<double>, 0
2119
+ };
2120
+ Mat src = _src.getMat();
2121
+ SortFunc func = tab[src.depth()];
2122
+ CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 );
2123
+ _dst.create( src.size(), src.type() );
2124
+ Mat dst = _dst.getMat();
2125
+ func( src, dst, flags );
2126
+ }
2127
+
2128
+ void cv::sortIdx( InputArray _src, OutputArray _dst, int flags )
2129
+ {
2130
+ static SortFunc tab[] =
2131
+ {
2132
+ sortIdx_<uchar>, sortIdx_<schar>, sortIdx_<ushort>, sortIdx_<short>,
2133
+ sortIdx_<int>, sortIdx_<float>, sortIdx_<double>, 0
2134
+ };
2135
+ Mat src = _src.getMat();
2136
+ SortFunc func = tab[src.depth()];
2137
+ CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 );
2138
+
2139
+ Mat dst = _dst.getMat();
2140
+ if( dst.data == src.data )
2141
+ _dst.release();
2142
+ _dst.create( src.size(), CV_32S );
2143
+ dst = _dst.getMat();
2144
+ func( src, dst, flags );
2145
+ }
2146
+
2147
+
2148
+ ////////////////////////////////////////// kmeans ////////////////////////////////////////////
2149
+
2150
+ namespace cv
2151
+ {
2152
+
2153
+ static void generateRandomCenter(const vector<Vec2f>& box, float* center, RNG& rng)
2154
+ {
2155
+ size_t j, dims = box.size();
2156
+ float margin = 1.f/dims;
2157
+ for( j = 0; j < dims; j++ )
2158
+ center[j] = ((float)rng*(1.f+margin*2.f)-margin)*(box[j][1] - box[j][0]) + box[j][0];
2159
+ }
2160
+
2161
+
2162
+ static inline float distance(const float* a, const float* b, int n)
2163
+ {
2164
+ int j = 0; float d = 0.f;
2165
+ #if CV_SSE
2166
+ if( USE_SSE2 )
2167
+ {
2168
+ float CV_DECL_ALIGNED(16) buf[4];
2169
+ __m128 d0 = _mm_setzero_ps(), d1 = _mm_setzero_ps();
2170
+
2171
+ for( ; j <= n - 8; j += 8 )
2172
+ {
2173
+ __m128 t0 = _mm_sub_ps(_mm_loadu_ps(a + j), _mm_loadu_ps(b + j));
2174
+ __m128 t1 = _mm_sub_ps(_mm_loadu_ps(a + j + 4), _mm_loadu_ps(b + j + 4));
2175
+ d0 = _mm_add_ps(d0, _mm_mul_ps(t0, t0));
2176
+ d1 = _mm_add_ps(d1, _mm_mul_ps(t1, t1));
2177
+ }
2178
+ _mm_store_ps(buf, _mm_add_ps(d0, d1));
2179
+ d = buf[0] + buf[1] + buf[2] + buf[3];
2180
+ }
2181
+ else
2182
+ #endif
2183
+ {
2184
+ for( ; j <= n - 4; j += 4 )
2185
+ {
2186
+ float t0 = a[j] - b[j], t1 = a[j+1] - b[j+1], t2 = a[j+2] - b[j+2], t3 = a[j+3] - b[j+3];
2187
+ d += t0*t0 + t1*t1 + t2*t2 + t3*t3;
2188
+ }
2189
+ }
2190
+
2191
+ for( ; j < n; j++ )
2192
+ {
2193
+ float t = a[j] - b[j];
2194
+ d += t*t;
2195
+ }
2196
+ return d;
2197
+ }
2198
+
2199
+ /*
2200
+ k-means center initialization using the following algorithm:
2201
+ Arthur & Vassilvitskii (2007) k-means++: The Advantages of Careful Seeding
2202
+ */
2203
+ static void generateCentersPP(const Mat& _data, Mat& _out_centers,
2204
+ int K, RNG& rng, int trials)
2205
+ {
2206
+ int i, j, k, dims = _data.cols, N = _data.rows;
2207
+ const float* data = _data.ptr<float>(0);
2208
+ size_t step = _data.step/sizeof(data[0]);
2209
+ vector<int> _centers(K);
2210
+ int* centers = &_centers[0];
2211
+ vector<float> _dist(N*3);
2212
+ float* dist = &_dist[0], *tdist = dist + N, *tdist2 = tdist + N;
2213
+ double sum0 = 0;
2214
+
2215
+ centers[0] = (unsigned)rng % N;
2216
+
2217
+ for( i = 0; i < N; i++ )
2218
+ {
2219
+ dist[i] = distance(data + step*i, data + step*centers[0], dims);
2220
+ sum0 += dist[i];
2221
+ }
2222
+
2223
+ for( k = 1; k < K; k++ )
2224
+ {
2225
+ double bestSum = DBL_MAX;
2226
+ int bestCenter = -1;
2227
+
2228
+ for( j = 0; j < trials; j++ )
2229
+ {
2230
+ double p = (double)rng*sum0, s = 0;
2231
+ for( i = 0; i < N-1; i++ )
2232
+ if( (p -= dist[i]) <= 0 )
2233
+ break;
2234
+ int ci = i;
2235
+ for( i = 0; i < N; i++ )
2236
+ {
2237
+ tdist2[i] = std::min(distance(data + step*i, data + step*ci, dims), dist[i]);
2238
+ s += tdist2[i];
2239
+ }
2240
+
2241
+ if( s < bestSum )
2242
+ {
2243
+ bestSum = s;
2244
+ bestCenter = ci;
2245
+ std::swap(tdist, tdist2);
2246
+ }
2247
+ }
2248
+ centers[k] = bestCenter;
2249
+ sum0 = bestSum;
2250
+ std::swap(dist, tdist);
2251
+ }
2252
+
2253
+ for( k = 0; k < K; k++ )
2254
+ {
2255
+ const float* src = data + step*centers[k];
2256
+ float* dst = _out_centers.ptr<float>(k);
2257
+ for( j = 0; j < dims; j++ )
2258
+ dst[j] = src[j];
2259
+ }
2260
+ }
2261
+
2262
+ }
2263
+
2264
+ double cv::kmeans( InputArray _data, int K,
2265
+ InputOutputArray _bestLabels,
2266
+ TermCriteria criteria, int attempts,
2267
+ int flags, OutputArray _centers )
2268
+ {
2269
+ const int SPP_TRIALS = 3;
2270
+ Mat data = _data.getMat();
2271
+ int N = data.rows > 1 ? data.rows : data.cols;
2272
+ int dims = (data.rows > 1 ? data.cols : 1)*data.channels();
2273
+ int type = data.depth();
2274
+
2275
+ attempts = std::max(attempts, 1);
2276
+ CV_Assert( data.dims <= 2 && type == CV_32F && K > 0 );
2277
+
2278
+ _bestLabels.create(N, 1, CV_32S, -1, true);
2279
+
2280
+ Mat _labels, best_labels = _bestLabels.getMat();
2281
+ if( flags & CV_KMEANS_USE_INITIAL_LABELS )
2282
+ {
2283
+ CV_Assert( (best_labels.cols == 1 || best_labels.rows == 1) &&
2284
+ best_labels.cols*best_labels.rows == N &&
2285
+ best_labels.type() == CV_32S &&
2286
+ best_labels.isContinuous());
2287
+ best_labels.copyTo(_labels);
2288
+ }
2289
+ else
2290
+ {
2291
+ if( !((best_labels.cols == 1 || best_labels.rows == 1) &&
2292
+ best_labels.cols*best_labels.rows == N &&
2293
+ best_labels.type() == CV_32S &&
2294
+ best_labels.isContinuous()))
2295
+ best_labels.create(N, 1, CV_32S);
2296
+ _labels.create(best_labels.size(), best_labels.type());
2297
+ }
2298
+ int* labels = _labels.ptr<int>();
2299
+
2300
+ Mat centers(K, dims, type), old_centers(K, dims, type);
2301
+ vector<int> counters(K);
2302
+ vector<Vec2f> _box(dims);
2303
+ Vec2f* box = &_box[0];
2304
+
2305
+ double best_compactness = DBL_MAX, compactness = 0;
2306
+ RNG& rng = theRNG();
2307
+ int a, iter, i, j, k;
2308
+
2309
+ if( criteria.type & TermCriteria::EPS )
2310
+ criteria.epsilon = std::max(criteria.epsilon, 0.);
2311
+ else
2312
+ criteria.epsilon = FLT_EPSILON;
2313
+ criteria.epsilon *= criteria.epsilon;
2314
+
2315
+ if( criteria.type & TermCriteria::COUNT )
2316
+ criteria.maxCount = std::min(std::max(criteria.maxCount, 2), 100);
2317
+ else
2318
+ criteria.maxCount = 100;
2319
+
2320
+ if( K == 1 )
2321
+ {
2322
+ attempts = 1;
2323
+ criteria.maxCount = 2;
2324
+ }
2325
+
2326
+ const float* sample = data.ptr<float>(0);
2327
+ for( j = 0; j < dims; j++ )
2328
+ box[j] = Vec2f(sample[j], sample[j]);
2329
+
2330
+ for( i = 1; i < N; i++ )
2331
+ {
2332
+ sample = data.ptr<float>(i);
2333
+ for( j = 0; j < dims; j++ )
2334
+ {
2335
+ float v = sample[j];
2336
+ box[j][0] = std::min(box[j][0], v);
2337
+ box[j][1] = std::max(box[j][1], v);
2338
+ }
2339
+ }
2340
+
2341
+ for( a = 0; a < attempts; a++ )
2342
+ {
2343
+ double max_center_shift = DBL_MAX;
2344
+ for( iter = 0; iter < criteria.maxCount && max_center_shift > criteria.epsilon; iter++ )
2345
+ {
2346
+ swap(centers, old_centers);
2347
+
2348
+ if( iter == 0 && (a > 0 || !(flags & KMEANS_USE_INITIAL_LABELS)) )
2349
+ {
2350
+ if( flags & KMEANS_PP_CENTERS )
2351
+ generateCentersPP(data, centers, K, rng, SPP_TRIALS);
2352
+ else
2353
+ {
2354
+ for( k = 0; k < K; k++ )
2355
+ generateRandomCenter(_box, centers.ptr<float>(k), rng);
2356
+ }
2357
+ }
2358
+ else
2359
+ {
2360
+ if( iter == 0 && a == 0 && (flags & KMEANS_USE_INITIAL_LABELS) )
2361
+ {
2362
+ for( i = 0; i < N; i++ )
2363
+ CV_Assert( (unsigned)labels[i] < (unsigned)K );
2364
+ }
2365
+
2366
+ // compute centers
2367
+ centers = Scalar(0);
2368
+ for( k = 0; k < K; k++ )
2369
+ counters[k] = 0;
2370
+
2371
+ for( i = 0; i < N; i++ )
2372
+ {
2373
+ sample = data.ptr<float>(i);
2374
+ k = labels[i];
2375
+ float* center = centers.ptr<float>(k);
2376
+ for( j = 0; j <= dims - 4; j += 4 )
2377
+ {
2378
+ float t0 = center[j] + sample[j];
2379
+ float t1 = center[j+1] + sample[j+1];
2380
+
2381
+ center[j] = t0;
2382
+ center[j+1] = t1;
2383
+
2384
+ t0 = center[j+2] + sample[j+2];
2385
+ t1 = center[j+3] + sample[j+3];
2386
+
2387
+ center[j+2] = t0;
2388
+ center[j+3] = t1;
2389
+ }
2390
+ for( ; j < dims; j++ )
2391
+ center[j] += sample[j];
2392
+ counters[k]++;
2393
+ }
2394
+
2395
+ if( iter > 0 )
2396
+ max_center_shift = 0;
2397
+
2398
+ for( k = 0; k < K; k++ )
2399
+ {
2400
+ float* center = centers.ptr<float>(k);
2401
+ if( counters[k] != 0 )
2402
+ {
2403
+ float scale = 1.f/counters[k];
2404
+ for( j = 0; j < dims; j++ )
2405
+ center[j] *= scale;
2406
+ }
2407
+ else
2408
+ generateRandomCenter(_box, center, rng);
2409
+
2410
+ if( iter > 0 )
2411
+ {
2412
+ double dist = 0;
2413
+ const float* old_center = old_centers.ptr<float>(k);
2414
+ for( j = 0; j < dims; j++ )
2415
+ {
2416
+ double t = center[j] - old_center[j];
2417
+ dist += t*t;
2418
+ }
2419
+ max_center_shift = std::max(max_center_shift, dist);
2420
+ }
2421
+ }
2422
+ }
2423
+
2424
+ // assign labels
2425
+ compactness = 0;
2426
+ for( i = 0; i < N; i++ )
2427
+ {
2428
+ sample = data.ptr<float>(i);
2429
+ int k_best = 0;
2430
+ double min_dist = DBL_MAX;
2431
+
2432
+ for( k = 0; k < K; k++ )
2433
+ {
2434
+ const float* center = centers.ptr<float>(k);
2435
+ double dist = distance(sample, center, dims);
2436
+
2437
+ if( min_dist > dist )
2438
+ {
2439
+ min_dist = dist;
2440
+ k_best = k;
2441
+ }
2442
+ }
2443
+
2444
+ compactness += min_dist;
2445
+ labels[i] = k_best;
2446
+ }
2447
+ }
2448
+
2449
+ if( compactness < best_compactness )
2450
+ {
2451
+ best_compactness = compactness;
2452
+ if( _centers.needed() )
2453
+ centers.copyTo(_centers);
2454
+ _labels.copyTo(best_labels);
2455
+ }
2456
+ }
2457
+
2458
+ return best_compactness;
2459
+ }
2460
+
2461
+
2462
+ CV_IMPL void cvSetIdentity( CvArr* arr, CvScalar value )
2463
+ {
2464
+ cv::Mat m = cv::cvarrToMat(arr);
2465
+ cv::setIdentity(m, value);
2466
+ }
2467
+
2468
+
2469
+ CV_IMPL CvScalar cvTrace( const CvArr* arr )
2470
+ {
2471
+ return cv::trace(cv::cvarrToMat(arr));
2472
+ }
2473
+
2474
+
2475
+ CV_IMPL void cvTranspose( const CvArr* srcarr, CvArr* dstarr )
2476
+ {
2477
+ cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
2478
+
2479
+ CV_Assert( src.rows == dst.cols && src.cols == dst.rows && src.type() == dst.type() );
2480
+ transpose( src, dst );
2481
+ }
2482
+
2483
+
2484
+ CV_IMPL void cvCompleteSymm( CvMat* matrix, int LtoR )
2485
+ {
2486
+ cv::Mat m(matrix);
2487
+ cv::completeSymm( m, LtoR != 0 );
2488
+ }
2489
+
2490
+
2491
+ CV_IMPL void cvCrossProduct( const CvArr* srcAarr, const CvArr* srcBarr, CvArr* dstarr )
2492
+ {
2493
+ cv::Mat srcA = cv::cvarrToMat(srcAarr), dst = cv::cvarrToMat(dstarr);
2494
+
2495
+ CV_Assert( srcA.size() == dst.size() && srcA.type() == dst.type() );
2496
+ srcA.cross(cv::cvarrToMat(srcBarr)).copyTo(dst);
2497
+ }
2498
+
2499
+
2500
+ CV_IMPL void
2501
+ cvReduce( const CvArr* srcarr, CvArr* dstarr, int dim, int op )
2502
+ {
2503
+ cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
2504
+
2505
+ if( dim < 0 )
2506
+ dim = src.rows > dst.rows ? 0 : src.cols > dst.cols ? 1 : dst.cols == 1;
2507
+
2508
+ if( dim > 1 )
2509
+ CV_Error( CV_StsOutOfRange, "The reduced dimensionality index is out of range" );
2510
+
2511
+ if( (dim == 0 && (dst.cols != src.cols || dst.rows != 1)) ||
2512
+ (dim == 1 && (dst.rows != src.rows || dst.cols != 1)) )
2513
+ CV_Error( CV_StsBadSize, "The output array size is incorrect" );
2514
+
2515
+ if( src.channels() != dst.channels() )
2516
+ CV_Error( CV_StsUnmatchedFormats, "Input and output arrays must have the same number of channels" );
2517
+
2518
+ cv::reduce(src, dst, dim, op, dst.type());
2519
+ }
2520
+
2521
+
2522
+ CV_IMPL CvArr*
2523
+ cvRange( CvArr* arr, double start, double end )
2524
+ {
2525
+ int ok = 0;
2526
+
2527
+ CvMat stub, *mat = (CvMat*)arr;
2528
+ double delta;
2529
+ int type, step;
2530
+ double val = start;
2531
+ int i, j;
2532
+ int rows, cols;
2533
+
2534
+ if( !CV_IS_MAT(mat) )
2535
+ mat = cvGetMat( mat, &stub);
2536
+
2537
+ rows = mat->rows;
2538
+ cols = mat->cols;
2539
+ type = CV_MAT_TYPE(mat->type);
2540
+ delta = (end-start)/(rows*cols);
2541
+
2542
+ if( CV_IS_MAT_CONT(mat->type) )
2543
+ {
2544
+ cols *= rows;
2545
+ rows = 1;
2546
+ step = 1;
2547
+ }
2548
+ else
2549
+ step = mat->step / CV_ELEM_SIZE(type);
2550
+
2551
+ if( type == CV_32SC1 )
2552
+ {
2553
+ int* idata = mat->data.i;
2554
+ int ival = cvRound(val), idelta = cvRound(delta);
2555
+
2556
+ if( fabs(val - ival) < DBL_EPSILON &&
2557
+ fabs(delta - idelta) < DBL_EPSILON )
2558
+ {
2559
+ for( i = 0; i < rows; i++, idata += step )
2560
+ for( j = 0; j < cols; j++, ival += idelta )
2561
+ idata[j] = ival;
2562
+ }
2563
+ else
2564
+ {
2565
+ for( i = 0; i < rows; i++, idata += step )
2566
+ for( j = 0; j < cols; j++, val += delta )
2567
+ idata[j] = cvRound(val);
2568
+ }
2569
+ }
2570
+ else if( type == CV_32FC1 )
2571
+ {
2572
+ float* fdata = mat->data.fl;
2573
+ for( i = 0; i < rows; i++, fdata += step )
2574
+ for( j = 0; j < cols; j++, val += delta )
2575
+ fdata[j] = (float)val;
2576
+ }
2577
+ else
2578
+ CV_Error( CV_StsUnsupportedFormat, "The function only supports 32sC1 and 32fC1 datatypes" );
2579
+
2580
+ ok = 1;
2581
+ return ok ? arr : 0;
2582
+ }
2583
+
2584
+
2585
+ CV_IMPL void
2586
+ cvSort( const CvArr* _src, CvArr* _dst, CvArr* _idx, int flags )
2587
+ {
2588
+ cv::Mat src = cv::cvarrToMat(_src), dst, idx;
2589
+
2590
+ if( _idx )
2591
+ {
2592
+ cv::Mat idx0 = cv::cvarrToMat(_idx), idx = idx0;
2593
+ CV_Assert( src.size() == idx.size() && idx.type() == CV_32S && src.data != idx.data );
2594
+ cv::sortIdx( src, idx, flags );
2595
+ CV_Assert( idx0.data == idx.data );
2596
+ }
2597
+
2598
+ if( _dst )
2599
+ {
2600
+ cv::Mat dst0 = cv::cvarrToMat(_dst), dst = dst0;
2601
+ CV_Assert( src.size() == dst.size() && src.type() == dst.type() );
2602
+ cv::sort( src, dst, flags );
2603
+ CV_Assert( dst0.data == dst.data );
2604
+ }
2605
+ }
2606
+
2607
+
2608
+ CV_IMPL int
2609
+ cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels,
2610
+ CvTermCriteria termcrit, int attempts, CvRNG*,
2611
+ int flags, CvArr* _centers, double* _compactness )
2612
+ {
2613
+ cv::Mat data = cv::cvarrToMat(_samples), labels = cv::cvarrToMat(_labels), centers;
2614
+ if( _centers )
2615
+ {
2616
+ centers = cv::cvarrToMat(_centers);
2617
+ centers = centers.reshape(1);
2618
+ }
2619
+ CV_Assert( labels.isContinuous() && labels.type() == CV_32S &&
2620
+ (labels.cols == 1 || labels.rows == 1) &&
2621
+ labels.cols + labels.rows - 1 == data.rows );
2622
+
2623
+ double compactness = cv::kmeans(data, cluster_count, labels, termcrit, attempts,
2624
+ flags, _centers ? cv::_OutputArray(centers) : cv::_OutputArray() );
2625
+ if( _compactness )
2626
+ *_compactness = compactness;
2627
+ return 1;
2628
+ }
2629
+
2630
+ ///////////////////////////// n-dimensional matrices ////////////////////////////
2631
+
2632
+ namespace cv
2633
+ {
2634
+
2635
+ Mat Mat::reshape(int, int, const int*) const
2636
+ {
2637
+ CV_Error(CV_StsNotImplemented, "");
2638
+ // TBD
2639
+ return Mat();
2640
+ }
2641
+
2642
+ Mat::operator CvMatND() const
2643
+ {
2644
+ CvMatND mat;
2645
+ cvInitMatNDHeader( &mat, dims, size, type(), data );
2646
+ int i, d = dims;
2647
+ for( i = 0; i < d; i++ )
2648
+ mat.dim[i].step = (int)step[i];
2649
+ mat.type |= flags & CONTINUOUS_FLAG;
2650
+ return mat;
2651
+ }
2652
+
2653
+ NAryMatIterator::NAryMatIterator()
2654
+ : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
2655
+ {
2656
+ }
2657
+
2658
+ NAryMatIterator::NAryMatIterator(const Mat** _arrays, Mat* _planes, int _narrays)
2659
+ : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
2660
+ {
2661
+ init(_arrays, _planes, 0, _narrays);
2662
+ }
2663
+
2664
+ NAryMatIterator::NAryMatIterator(const Mat** _arrays, uchar** _ptrs, int _narrays)
2665
+ : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
2666
+ {
2667
+ init(_arrays, 0, _ptrs, _narrays);
2668
+ }
2669
+
2670
+ void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, uchar** _ptrs, int _narrays)
2671
+ {
2672
+ CV_Assert( _arrays && (_ptrs || _planes) );
2673
+ int i, j, d1=0, i0 = -1, d = -1;
2674
+
2675
+ arrays = _arrays;
2676
+ ptrs = _ptrs;
2677
+ planes = _planes;
2678
+ narrays = _narrays;
2679
+ nplanes = 0;
2680
+ size = 0;
2681
+
2682
+ if( narrays < 0 )
2683
+ {
2684
+ for( i = 0; _arrays[i] != 0; i++ )
2685
+ ;
2686
+ narrays = i;
2687
+ CV_Assert(narrays <= 1000);
2688
+ }
2689
+
2690
+ iterdepth = 0;
2691
+
2692
+ for( i = 0; i < narrays; i++ )
2693
+ {
2694
+ CV_Assert(arrays[i] != 0);
2695
+ const Mat& A = *arrays[i];
2696
+ if( ptrs )
2697
+ ptrs[i] = A.data;
2698
+
2699
+ if( !A.data )
2700
+ continue;
2701
+
2702
+ if( i0 < 0 )
2703
+ {
2704
+ i0 = i;
2705
+ d = A.dims;
2706
+
2707
+ // find the first dimensionality which is different from 1;
2708
+ // in any of the arrays the first "d1" step do not affect the continuity
2709
+ for( d1 = 0; d1 < d; d1++ )
2710
+ if( A.size[d1] > 1 )
2711
+ break;
2712
+ }
2713
+ else
2714
+ CV_Assert( A.size == arrays[i0]->size );
2715
+
2716
+ if( !A.isContinuous() )
2717
+ {
2718
+ CV_Assert( A.step[d-1] == A.elemSize() );
2719
+ for( j = d-1; j > d1; j-- )
2720
+ if( A.step[j]*A.size[j] < A.step[j-1] )
2721
+ break;
2722
+ iterdepth = std::max(iterdepth, j);
2723
+ }
2724
+ }
2725
+
2726
+ if( i0 >= 0 )
2727
+ {
2728
+ size = arrays[i0]->size[d-1];
2729
+ for( j = d-1; j > iterdepth; j-- )
2730
+ {
2731
+ int64 total1 = (int64)size*arrays[i0]->size[j-1];
2732
+ if( total1 != (int)total1 )
2733
+ break;
2734
+ size = (int)total1;
2735
+ }
2736
+
2737
+ iterdepth = j;
2738
+ if( iterdepth == d1 )
2739
+ iterdepth = 0;
2740
+
2741
+ nplanes = 1;
2742
+ for( j = iterdepth-1; j >= 0; j-- )
2743
+ nplanes *= arrays[i0]->size[j];
2744
+ }
2745
+ else
2746
+ iterdepth = 0;
2747
+
2748
+ idx = 0;
2749
+
2750
+ if( !planes )
2751
+ return;
2752
+
2753
+ for( i = 0; i < narrays; i++ )
2754
+ {
2755
+ CV_Assert(arrays[i] != 0);
2756
+ const Mat& A = *arrays[i];
2757
+
2758
+ if( !A.data )
2759
+ {
2760
+ planes[i] = Mat();
2761
+ continue;
2762
+ }
2763
+
2764
+ planes[i] = Mat(1, (int)size, A.type(), A.data);
2765
+ }
2766
+ }
2767
+
2768
+
2769
+ NAryMatIterator& NAryMatIterator::operator ++()
2770
+ {
2771
+ if( idx >= nplanes-1 )
2772
+ return *this;
2773
+ ++idx;
2774
+
2775
+ if( iterdepth == 1 )
2776
+ {
2777
+ if( ptrs )
2778
+ {
2779
+ for( int i = 0; i < narrays; i++ )
2780
+ {
2781
+ if( !ptrs[i] )
2782
+ continue;
2783
+ ptrs[i] = arrays[i]->data + arrays[i]->step[0]*idx;
2784
+ }
2785
+ }
2786
+ if( planes )
2787
+ {
2788
+ for( int i = 0; i < narrays; i++ )
2789
+ {
2790
+ if( !planes[i].data )
2791
+ continue;
2792
+ planes[i].data = arrays[i]->data + arrays[i]->step[0]*idx;
2793
+ }
2794
+ }
2795
+ }
2796
+ else
2797
+ {
2798
+ for( int i = 0; i < narrays; i++ )
2799
+ {
2800
+ const Mat& A = *arrays[i];
2801
+ if( !A.data )
2802
+ continue;
2803
+ int _idx = (int)idx;
2804
+ uchar* data = A.data;
2805
+ for( int j = iterdepth-1; j >= 0 && _idx > 0; j-- )
2806
+ {
2807
+ int szi = A.size[j], t = _idx/szi;
2808
+ data += (_idx - t * szi)*A.step[j];
2809
+ _idx = t;
2810
+ }
2811
+ if( ptrs )
2812
+ ptrs[i] = data;
2813
+ if( planes )
2814
+ planes[i].data = data;
2815
+ }
2816
+ }
2817
+
2818
+ return *this;
2819
+ }
2820
+
2821
+ NAryMatIterator NAryMatIterator::operator ++(int)
2822
+ {
2823
+ NAryMatIterator it = *this;
2824
+ ++*this;
2825
+ return it;
2826
+ }
2827
+
2828
+ ///////////////////////////////////////////////////////////////////////////
2829
+ // MatConstIterator //
2830
+ ///////////////////////////////////////////////////////////////////////////
2831
+
2832
+ Point MatConstIterator::pos() const
2833
+ {
2834
+ if( !m )
2835
+ return Point();
2836
+ CV_DbgAssert(m->dims <= 2);
2837
+
2838
+ ptrdiff_t ofs = ptr - m->data;
2839
+ int y = (int)(ofs/m->step[0]);
2840
+ return Point((int)((ofs - y*m->step[0])/elemSize), y);
2841
+ }
2842
+
2843
+ void MatConstIterator::pos(int* _idx) const
2844
+ {
2845
+ CV_Assert(m != 0 && _idx);
2846
+ ptrdiff_t ofs = ptr - m->data;
2847
+ for( int i = 0; i < m->dims; i++ )
2848
+ {
2849
+ size_t s = m->step[i], v = ofs/s;
2850
+ ofs -= v*s;
2851
+ _idx[i] = (int)v;
2852
+ }
2853
+ }
2854
+
2855
+ ptrdiff_t MatConstIterator::lpos() const
2856
+ {
2857
+ if(!m)
2858
+ return 0;
2859
+ if( m->isContinuous() )
2860
+ return (ptr - sliceStart)/elemSize;
2861
+ ptrdiff_t ofs = ptr - m->data;
2862
+ int i, d = m->dims;
2863
+ if( d == 2 )
2864
+ {
2865
+ ptrdiff_t y = ofs/m->step[0];
2866
+ return y*m->cols + (ofs - y*m->step[0])/elemSize;
2867
+ }
2868
+ ptrdiff_t result = 0;
2869
+ for( i = 0; i < d; i++ )
2870
+ {
2871
+ size_t s = m->step[i], v = ofs/s;
2872
+ ofs -= v*s;
2873
+ result = result*m->size[i] + v;
2874
+ }
2875
+ return result;
2876
+ }
2877
+
2878
+ void MatConstIterator::seek(ptrdiff_t ofs, bool relative)
2879
+ {
2880
+ if( m->isContinuous() )
2881
+ {
2882
+ ptr = (relative ? ptr : sliceStart) + ofs*elemSize;
2883
+ if( ptr < sliceStart )
2884
+ ptr = sliceStart;
2885
+ else if( ptr > sliceEnd )
2886
+ ptr = sliceEnd;
2887
+ return;
2888
+ }
2889
+
2890
+ int d = m->dims;
2891
+ if( d == 2 )
2892
+ {
2893
+ ptrdiff_t ofs0, y;
2894
+ if( relative )
2895
+ {
2896
+ ofs0 = ptr - m->data;
2897
+ y = ofs0/m->step[0];
2898
+ ofs += y*m->cols + (ofs0 - y*m->step[0])/elemSize;
2899
+ }
2900
+ y = ofs/m->cols;
2901
+ int y1 = std::min(std::max((int)y, 0), m->rows-1);
2902
+ sliceStart = m->data + y1*m->step[0];
2903
+ sliceEnd = sliceStart + m->cols*elemSize;
2904
+ ptr = y < 0 ? sliceStart : y >= m->rows ? sliceEnd :
2905
+ sliceStart + (ofs - y*m->cols)*elemSize;
2906
+ return;
2907
+ }
2908
+
2909
+ if( relative )
2910
+ ofs += lpos();
2911
+
2912
+ if( ofs < 0 )
2913
+ ofs = 0;
2914
+
2915
+ int szi = m->size[d-1];
2916
+ ptrdiff_t t = ofs/szi;
2917
+ int v = (int)(ofs - t*szi);
2918
+ ofs = t;
2919
+ ptr = m->data + v*elemSize;
2920
+ sliceStart = m->data;
2921
+
2922
+ for( int i = d-2; i >= 0; i-- )
2923
+ {
2924
+ szi = m->size[i];
2925
+ t = ofs/szi;
2926
+ v = (int)(ofs - t*szi);
2927
+ ofs = t;
2928
+ sliceStart += v*m->step[i];
2929
+ }
2930
+
2931
+ sliceEnd = sliceStart + m->size[d-1]*elemSize;
2932
+ if( ofs > 0 )
2933
+ ptr = sliceEnd;
2934
+ else
2935
+ ptr = sliceStart + (ptr - m->data);
2936
+ }
2937
+
2938
+ void MatConstIterator::seek(const int* _idx, bool relative)
2939
+ {
2940
+ int i, d = m->dims;
2941
+ ptrdiff_t ofs = 0;
2942
+ if( !_idx )
2943
+ ;
2944
+ else if( d == 2 )
2945
+ ofs = _idx[0]*m->size[1] + _idx[1];
2946
+ else
2947
+ {
2948
+ for( i = 0; i < d; i++ )
2949
+ ofs = ofs*m->size[i] + _idx[i];
2950
+ }
2951
+ seek(ofs, relative);
2952
+ }
2953
+
2954
+ ptrdiff_t operator - (const MatConstIterator& b, const MatConstIterator& a)
2955
+ {
2956
+ if( a.m != b.m )
2957
+ return INT_MAX;
2958
+ if( a.sliceEnd == b.sliceEnd )
2959
+ return (b.ptr - a.ptr)/b.elemSize;
2960
+
2961
+ return b.lpos() - a.lpos();
2962
+ }
2963
+
2964
+ //////////////////////////////// SparseMat ////////////////////////////////
2965
+
2966
+ template<typename T1, typename T2> void
2967
+ convertData_(const void* _from, void* _to, int cn)
2968
+ {
2969
+ const T1* from = (const T1*)_from;
2970
+ T2* to = (T2*)_to;
2971
+ if( cn == 1 )
2972
+ *to = saturate_cast<T2>(*from);
2973
+ else
2974
+ for( int i = 0; i < cn; i++ )
2975
+ to[i] = saturate_cast<T2>(from[i]);
2976
+ }
2977
+
2978
+ template<typename T1, typename T2> void
2979
+ convertScaleData_(const void* _from, void* _to, int cn, double alpha, double beta)
2980
+ {
2981
+ const T1* from = (const T1*)_from;
2982
+ T2* to = (T2*)_to;
2983
+ if( cn == 1 )
2984
+ *to = saturate_cast<T2>(*from*alpha + beta);
2985
+ else
2986
+ for( int i = 0; i < cn; i++ )
2987
+ to[i] = saturate_cast<T2>(from[i]*alpha + beta);
2988
+ }
2989
+
2990
+ ConvertData getConvertData(int fromType, int toType)
2991
+ {
2992
+ static ConvertData tab[][8] =
2993
+ {{ convertData_<uchar, uchar>, convertData_<uchar, schar>,
2994
+ convertData_<uchar, ushort>, convertData_<uchar, short>,
2995
+ convertData_<uchar, int>, convertData_<uchar, float>,
2996
+ convertData_<uchar, double>, 0 },
2997
+
2998
+ { convertData_<schar, uchar>, convertData_<schar, schar>,
2999
+ convertData_<schar, ushort>, convertData_<schar, short>,
3000
+ convertData_<schar, int>, convertData_<schar, float>,
3001
+ convertData_<schar, double>, 0 },
3002
+
3003
+ { convertData_<ushort, uchar>, convertData_<ushort, schar>,
3004
+ convertData_<ushort, ushort>, convertData_<ushort, short>,
3005
+ convertData_<ushort, int>, convertData_<ushort, float>,
3006
+ convertData_<ushort, double>, 0 },
3007
+
3008
+ { convertData_<short, uchar>, convertData_<short, schar>,
3009
+ convertData_<short, ushort>, convertData_<short, short>,
3010
+ convertData_<short, int>, convertData_<short, float>,
3011
+ convertData_<short, double>, 0 },
3012
+
3013
+ { convertData_<int, uchar>, convertData_<int, schar>,
3014
+ convertData_<int, ushort>, convertData_<int, short>,
3015
+ convertData_<int, int>, convertData_<int, float>,
3016
+ convertData_<int, double>, 0 },
3017
+
3018
+ { convertData_<float, uchar>, convertData_<float, schar>,
3019
+ convertData_<float, ushort>, convertData_<float, short>,
3020
+ convertData_<float, int>, convertData_<float, float>,
3021
+ convertData_<float, double>, 0 },
3022
+
3023
+ { convertData_<double, uchar>, convertData_<double, schar>,
3024
+ convertData_<double, ushort>, convertData_<double, short>,
3025
+ convertData_<double, int>, convertData_<double, float>,
3026
+ convertData_<double, double>, 0 },
3027
+
3028
+ { 0, 0, 0, 0, 0, 0, 0, 0 }};
3029
+
3030
+ ConvertData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)];
3031
+ CV_Assert( func != 0 );
3032
+ return func;
3033
+ }
3034
+
3035
+ ConvertScaleData getConvertScaleData(int fromType, int toType)
3036
+ {
3037
+ static ConvertScaleData tab[][8] =
3038
+ {{ convertScaleData_<uchar, uchar>, convertScaleData_<uchar, schar>,
3039
+ convertScaleData_<uchar, ushort>, convertScaleData_<uchar, short>,
3040
+ convertScaleData_<uchar, int>, convertScaleData_<uchar, float>,
3041
+ convertScaleData_<uchar, double>, 0 },
3042
+
3043
+ { convertScaleData_<schar, uchar>, convertScaleData_<schar, schar>,
3044
+ convertScaleData_<schar, ushort>, convertScaleData_<schar, short>,
3045
+ convertScaleData_<schar, int>, convertScaleData_<schar, float>,
3046
+ convertScaleData_<schar, double>, 0 },
3047
+
3048
+ { convertScaleData_<ushort, uchar>, convertScaleData_<ushort, schar>,
3049
+ convertScaleData_<ushort, ushort>, convertScaleData_<ushort, short>,
3050
+ convertScaleData_<ushort, int>, convertScaleData_<ushort, float>,
3051
+ convertScaleData_<ushort, double>, 0 },
3052
+
3053
+ { convertScaleData_<short, uchar>, convertScaleData_<short, schar>,
3054
+ convertScaleData_<short, ushort>, convertScaleData_<short, short>,
3055
+ convertScaleData_<short, int>, convertScaleData_<short, float>,
3056
+ convertScaleData_<short, double>, 0 },
3057
+
3058
+ { convertScaleData_<int, uchar>, convertScaleData_<int, schar>,
3059
+ convertScaleData_<int, ushort>, convertScaleData_<int, short>,
3060
+ convertScaleData_<int, int>, convertScaleData_<int, float>,
3061
+ convertScaleData_<int, double>, 0 },
3062
+
3063
+ { convertScaleData_<float, uchar>, convertScaleData_<float, schar>,
3064
+ convertScaleData_<float, ushort>, convertScaleData_<float, short>,
3065
+ convertScaleData_<float, int>, convertScaleData_<float, float>,
3066
+ convertScaleData_<float, double>, 0 },
3067
+
3068
+ { convertScaleData_<double, uchar>, convertScaleData_<double, schar>,
3069
+ convertScaleData_<double, ushort>, convertScaleData_<double, short>,
3070
+ convertScaleData_<double, int>, convertScaleData_<double, float>,
3071
+ convertScaleData_<double, double>, 0 },
3072
+
3073
+ { 0, 0, 0, 0, 0, 0, 0, 0 }};
3074
+
3075
+ ConvertScaleData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)];
3076
+ CV_Assert( func != 0 );
3077
+ return func;
3078
+ }
3079
+
3080
+ enum { HASH_SIZE0 = 8 };
3081
+
3082
+ static inline void copyElem(const uchar* from, uchar* to, size_t elemSize)
3083
+ {
3084
+ size_t i;
3085
+ for( i = 0; (int)i <= (int)(elemSize - sizeof(int)); i += sizeof(int) )
3086
+ *(int*)(to + i) = *(const int*)(from + i);
3087
+ for( ; i < elemSize; i++ )
3088
+ to[i] = from[i];
3089
+ }
3090
+
3091
+ static inline bool isZeroElem(const uchar* data, size_t elemSize)
3092
+ {
3093
+ size_t i;
3094
+ for( i = 0; i <= elemSize - sizeof(int); i += sizeof(int) )
3095
+ if( *(int*)(data + i) != 0 )
3096
+ return false;
3097
+ for( ; i < elemSize; i++ )
3098
+ if( data[i] != 0 )
3099
+ return false;
3100
+ return true;
3101
+ }
3102
+
3103
+ SparseMat::Hdr::Hdr( int _dims, const int* _sizes, int _type )
3104
+ {
3105
+ refcount = 1;
3106
+
3107
+ dims = _dims;
3108
+ valueOffset = (int)alignSize(sizeof(SparseMat::Node) +
3109
+ sizeof(int)*std::max(dims - CV_MAX_DIM, 0), CV_ELEM_SIZE1(_type));
3110
+ nodeSize = alignSize(valueOffset +
3111
+ CV_ELEM_SIZE(_type), (int)sizeof(size_t));
3112
+
3113
+ int i;
3114
+ for( i = 0; i < dims; i++ )
3115
+ size[i] = _sizes[i];
3116
+ for( ; i < CV_MAX_DIM; i++ )
3117
+ size[i] = 0;
3118
+ clear();
3119
+ }
3120
+
3121
+ void SparseMat::Hdr::clear()
3122
+ {
3123
+ hashtab.clear();
3124
+ hashtab.resize(HASH_SIZE0);
3125
+ pool.clear();
3126
+ pool.resize(nodeSize);
3127
+ nodeCount = freeList = 0;
3128
+ }
3129
+
3130
+
3131
+ SparseMat::SparseMat(const Mat& m)
3132
+ : flags(MAGIC_VAL), hdr(0)
3133
+ {
3134
+ create( m.dims, m.size, m.type() );
3135
+
3136
+ int i, idx[CV_MAX_DIM] = {0}, d = m.dims, lastSize = m.size[d - 1];
3137
+ size_t esz = m.elemSize();
3138
+ uchar* ptr = m.data;
3139
+
3140
+ for(;;)
3141
+ {
3142
+ for( i = 0; i < lastSize; i++, ptr += esz )
3143
+ {
3144
+ if( isZeroElem(ptr, esz) )
3145
+ continue;
3146
+ idx[d-1] = i;
3147
+ uchar* to = newNode(idx, hash(idx));
3148
+ copyElem( ptr, to, esz );
3149
+ }
3150
+
3151
+ for( i = d - 2; i >= 0; i-- )
3152
+ {
3153
+ ptr += m.step[i] - m.size[i+1]*m.step[i+1];
3154
+ if( ++idx[i] < m.size[i] )
3155
+ break;
3156
+ idx[i] = 0;
3157
+ }
3158
+ if( i < 0 )
3159
+ break;
3160
+ }
3161
+ }
3162
+
3163
+ SparseMat::SparseMat(const CvSparseMat* m)
3164
+ : flags(MAGIC_VAL), hdr(0)
3165
+ {
3166
+ CV_Assert(m);
3167
+ create( m->dims, &m->size[0], m->type );
3168
+
3169
+ CvSparseMatIterator it;
3170
+ CvSparseNode* n = cvInitSparseMatIterator(m, &it);
3171
+ size_t esz = elemSize();
3172
+
3173
+ for( ; n != 0; n = cvGetNextSparseNode(&it) )
3174
+ {
3175
+ const int* idx = CV_NODE_IDX(m, n);
3176
+ uchar* to = newNode(idx, hash(idx));
3177
+ copyElem((const uchar*)CV_NODE_VAL(m, n), to, esz);
3178
+ }
3179
+ }
3180
+
3181
+ void SparseMat::create(int d, const int* _sizes, int _type)
3182
+ {
3183
+ int i;
3184
+ CV_Assert( _sizes && 0 < d && d <= CV_MAX_DIM );
3185
+ for( i = 0; i < d; i++ )
3186
+ CV_Assert( _sizes[i] > 0 );
3187
+ _type = CV_MAT_TYPE(_type);
3188
+ if( hdr && _type == type() && hdr->dims == d && hdr->refcount == 1 )
3189
+ {
3190
+ for( i = 0; i < d; i++ )
3191
+ if( _sizes[i] != hdr->size[i] )
3192
+ break;
3193
+ if( i == d )
3194
+ {
3195
+ clear();
3196
+ return;
3197
+ }
3198
+ }
3199
+ release();
3200
+ flags = MAGIC_VAL | _type;
3201
+ hdr = new Hdr(d, _sizes, _type);
3202
+ }
3203
+
3204
+ void SparseMat::copyTo( SparseMat& m ) const
3205
+ {
3206
+ if( hdr == m.hdr )
3207
+ return;
3208
+ if( !hdr )
3209
+ {
3210
+ m.release();
3211
+ return;
3212
+ }
3213
+ m.create( hdr->dims, hdr->size, type() );
3214
+ SparseMatConstIterator from = begin();
3215
+ size_t i, N = nzcount(), esz = elemSize();
3216
+
3217
+ for( i = 0; i < N; i++, ++from )
3218
+ {
3219
+ const Node* n = from.node();
3220
+ uchar* to = m.newNode(n->idx, n->hashval);
3221
+ copyElem( from.ptr, to, esz );
3222
+ }
3223
+ }
3224
+
3225
+ void SparseMat::copyTo( Mat& m ) const
3226
+ {
3227
+ CV_Assert( hdr );
3228
+ m.create( dims(), hdr->size, type() );
3229
+ m = Scalar(0);
3230
+
3231
+ SparseMatConstIterator from = begin();
3232
+ size_t i, N = nzcount(), esz = elemSize();
3233
+
3234
+ for( i = 0; i < N; i++, ++from )
3235
+ {
3236
+ const Node* n = from.node();
3237
+ copyElem( from.ptr, m.ptr(n->idx), esz);
3238
+ }
3239
+ }
3240
+
3241
+
3242
+ void SparseMat::convertTo( SparseMat& m, int rtype, double alpha ) const
3243
+ {
3244
+ int cn = channels();
3245
+ if( rtype < 0 )
3246
+ rtype = type();
3247
+ rtype = CV_MAKETYPE(rtype, cn);
3248
+ if( hdr == m.hdr && rtype != type() )
3249
+ {
3250
+ SparseMat temp;
3251
+ convertTo(temp, rtype, alpha);
3252
+ m = temp;
3253
+ return;
3254
+ }
3255
+
3256
+ CV_Assert(hdr != 0);
3257
+ if( hdr != m.hdr )
3258
+ m.create( hdr->dims, hdr->size, rtype );
3259
+
3260
+ SparseMatConstIterator from = begin();
3261
+ size_t i, N = nzcount();
3262
+
3263
+ if( alpha == 1 )
3264
+ {
3265
+ ConvertData cvtfunc = getConvertData(type(), rtype);
3266
+ for( i = 0; i < N; i++, ++from )
3267
+ {
3268
+ const Node* n = from.node();
3269
+ uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval);
3270
+ cvtfunc( from.ptr, to, cn );
3271
+ }
3272
+ }
3273
+ else
3274
+ {
3275
+ ConvertScaleData cvtfunc = getConvertScaleData(type(), rtype);
3276
+ for( i = 0; i < N; i++, ++from )
3277
+ {
3278
+ const Node* n = from.node();
3279
+ uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval);
3280
+ cvtfunc( from.ptr, to, cn, alpha, 0 );
3281
+ }
3282
+ }
3283
+ }
3284
+
3285
+
3286
+ void SparseMat::convertTo( Mat& m, int rtype, double alpha, double beta ) const
3287
+ {
3288
+ int cn = channels();
3289
+ if( rtype < 0 )
3290
+ rtype = type();
3291
+ rtype = CV_MAKETYPE(rtype, cn);
3292
+
3293
+ CV_Assert( hdr );
3294
+ m.create( dims(), hdr->size, rtype );
3295
+ m = Scalar(beta);
3296
+
3297
+ SparseMatConstIterator from = begin();
3298
+ size_t i, N = nzcount();
3299
+
3300
+ if( alpha == 1 && beta == 0 )
3301
+ {
3302
+ ConvertData cvtfunc = getConvertData(type(), rtype);
3303
+ for( i = 0; i < N; i++, ++from )
3304
+ {
3305
+ const Node* n = from.node();
3306
+ uchar* to = m.ptr(n->idx);
3307
+ cvtfunc( from.ptr, to, cn );
3308
+ }
3309
+ }
3310
+ else
3311
+ {
3312
+ ConvertScaleData cvtfunc = getConvertScaleData(type(), rtype);
3313
+ for( i = 0; i < N; i++, ++from )
3314
+ {
3315
+ const Node* n = from.node();
3316
+ uchar* to = m.ptr(n->idx);
3317
+ cvtfunc( from.ptr, to, cn, alpha, beta );
3318
+ }
3319
+ }
3320
+ }
3321
+
3322
+ void SparseMat::clear()
3323
+ {
3324
+ if( hdr )
3325
+ hdr->clear();
3326
+ }
3327
+
3328
+ SparseMat::operator CvSparseMat*() const
3329
+ {
3330
+ if( !hdr )
3331
+ return 0;
3332
+ CvSparseMat* m = cvCreateSparseMat(hdr->dims, hdr->size, type());
3333
+
3334
+ SparseMatConstIterator from = begin();
3335
+ size_t i, N = nzcount(), esz = elemSize();
3336
+
3337
+ for( i = 0; i < N; i++, ++from )
3338
+ {
3339
+ const Node* n = from.node();
3340
+ uchar* to = cvPtrND(m, n->idx, 0, -2, 0);
3341
+ copyElem(from.ptr, to, esz);
3342
+ }
3343
+ return m;
3344
+ }
3345
+
3346
+ uchar* SparseMat::ptr(int i0, int i1, bool createMissing, size_t* hashval)
3347
+ {
3348
+ CV_Assert( hdr && hdr->dims == 2 );
3349
+ size_t h = hashval ? *hashval : hash(i0, i1);
3350
+ size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
3351
+ uchar* pool = &hdr->pool[0];
3352
+ while( nidx != 0 )
3353
+ {
3354
+ Node* elem = (Node*)(pool + nidx);
3355
+ if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 )
3356
+ return &value<uchar>(elem);
3357
+ nidx = elem->next;
3358
+ }
3359
+
3360
+ if( createMissing )
3361
+ {
3362
+ int idx[] = { i0, i1 };
3363
+ return newNode( idx, h );
3364
+ }
3365
+ return 0;
3366
+ }
3367
+
3368
+ uchar* SparseMat::ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval)
3369
+ {
3370
+ CV_Assert( hdr && hdr->dims == 3 );
3371
+ size_t h = hashval ? *hashval : hash(i0, i1, i2);
3372
+ size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
3373
+ uchar* pool = &hdr->pool[0];
3374
+ while( nidx != 0 )
3375
+ {
3376
+ Node* elem = (Node*)(pool + nidx);
3377
+ if( elem->hashval == h && elem->idx[0] == i0 &&
3378
+ elem->idx[1] == i1 && elem->idx[2] == i2 )
3379
+ return &value<uchar>(elem);
3380
+ nidx = elem->next;
3381
+ }
3382
+
3383
+ if( createMissing )
3384
+ {
3385
+ int idx[] = { i0, i1, i2 };
3386
+ return newNode( idx, h );
3387
+ }
3388
+ return 0;
3389
+ }
3390
+
3391
+ uchar* SparseMat::ptr(const int* idx, bool createMissing, size_t* hashval)
3392
+ {
3393
+ CV_Assert( hdr );
3394
+ int i, d = hdr->dims;
3395
+ size_t h = hashval ? *hashval : hash(idx);
3396
+ size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
3397
+ uchar* pool = &hdr->pool[0];
3398
+ while( nidx != 0 )
3399
+ {
3400
+ Node* elem = (Node*)(pool + nidx);
3401
+ if( elem->hashval == h )
3402
+ {
3403
+ for( i = 0; i < d; i++ )
3404
+ if( elem->idx[i] != idx[i] )
3405
+ break;
3406
+ if( i == d )
3407
+ return &value<uchar>(elem);
3408
+ }
3409
+ nidx = elem->next;
3410
+ }
3411
+
3412
+ return createMissing ? newNode(idx, h) : 0;
3413
+ }
3414
+
3415
+ void SparseMat::erase(int i0, int i1, size_t* hashval)
3416
+ {
3417
+ CV_Assert( hdr && hdr->dims == 2 );
3418
+ size_t h = hashval ? *hashval : hash(i0, i1);
3419
+ size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0;
3420
+ uchar* pool = &hdr->pool[0];
3421
+ while( nidx != 0 )
3422
+ {
3423
+ Node* elem = (Node*)(pool + nidx);
3424
+ if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 )
3425
+ break;
3426
+ previdx = nidx;
3427
+ nidx = elem->next;
3428
+ }
3429
+
3430
+ if( nidx )
3431
+ removeNode(hidx, nidx, previdx);
3432
+ }
3433
+
3434
+ void SparseMat::erase(int i0, int i1, int i2, size_t* hashval)
3435
+ {
3436
+ CV_Assert( hdr && hdr->dims == 3 );
3437
+ size_t h = hashval ? *hashval : hash(i0, i1, i2);
3438
+ size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0;
3439
+ uchar* pool = &hdr->pool[0];
3440
+ while( nidx != 0 )
3441
+ {
3442
+ Node* elem = (Node*)(pool + nidx);
3443
+ if( elem->hashval == h && elem->idx[0] == i0 &&
3444
+ elem->idx[1] == i1 && elem->idx[2] == i2 )
3445
+ break;
3446
+ previdx = nidx;
3447
+ nidx = elem->next;
3448
+ }
3449
+
3450
+ if( nidx )
3451
+ removeNode(hidx, nidx, previdx);
3452
+ }
3453
+
3454
+ void SparseMat::erase(const int* idx, size_t* hashval)
3455
+ {
3456
+ CV_Assert( hdr );
3457
+ int i, d = hdr->dims;
3458
+ size_t h = hashval ? *hashval : hash(idx);
3459
+ size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0;
3460
+ uchar* pool = &hdr->pool[0];
3461
+ while( nidx != 0 )
3462
+ {
3463
+ Node* elem = (Node*)(pool + nidx);
3464
+ if( elem->hashval == h )
3465
+ {
3466
+ for( i = 0; i < d; i++ )
3467
+ if( elem->idx[i] != idx[i] )
3468
+ break;
3469
+ if( i == d )
3470
+ break;
3471
+ }
3472
+ previdx = nidx;
3473
+ nidx = elem->next;
3474
+ }
3475
+
3476
+ if( nidx )
3477
+ removeNode(hidx, nidx, previdx);
3478
+ }
3479
+
3480
+ void SparseMat::resizeHashTab(size_t newsize)
3481
+ {
3482
+ newsize = std::max(newsize, (size_t)8);
3483
+ if((newsize & (newsize-1)) != 0)
3484
+ newsize = (size_t)1 << cvCeil(std::log((double)newsize)/CV_LOG2);
3485
+
3486
+ size_t i, hsize = hdr->hashtab.size();
3487
+ vector<size_t> _newh(newsize);
3488
+ size_t* newh = &_newh[0];
3489
+ for( i = 0; i < newsize; i++ )
3490
+ newh[i] = 0;
3491
+ uchar* pool = &hdr->pool[0];
3492
+ for( i = 0; i < hsize; i++ )
3493
+ {
3494
+ size_t nidx = hdr->hashtab[i];
3495
+ while( nidx )
3496
+ {
3497
+ Node* elem = (Node*)(pool + nidx);
3498
+ size_t next = elem->next;
3499
+ size_t newhidx = elem->hashval & (newsize - 1);
3500
+ elem->next = newh[newhidx];
3501
+ newh[newhidx] = nidx;
3502
+ nidx = next;
3503
+ }
3504
+ }
3505
+ hdr->hashtab = _newh;
3506
+ }
3507
+
3508
+ uchar* SparseMat::newNode(const int* idx, size_t hashval)
3509
+ {
3510
+ const int HASH_MAX_FILL_FACTOR=3;
3511
+ assert(hdr);
3512
+ size_t hsize = hdr->hashtab.size();
3513
+ if( ++hdr->nodeCount > hsize*HASH_MAX_FILL_FACTOR )
3514
+ {
3515
+ resizeHashTab(std::max(hsize*2, (size_t)8));
3516
+ hsize = hdr->hashtab.size();
3517
+ }
3518
+
3519
+ if( !hdr->freeList )
3520
+ {
3521
+ size_t i, nsz = hdr->nodeSize, psize = hdr->pool.size(),
3522
+ newpsize = std::max(psize*2, 8*nsz);
3523
+ hdr->pool.resize(newpsize);
3524
+ uchar* pool = &hdr->pool[0];
3525
+ hdr->freeList = std::max(psize, nsz);
3526
+ for( i = hdr->freeList; i < newpsize - nsz; i += nsz )
3527
+ ((Node*)(pool + i))->next = i + nsz;
3528
+ ((Node*)(pool + i))->next = 0;
3529
+ }
3530
+ size_t nidx = hdr->freeList;
3531
+ Node* elem = (Node*)&hdr->pool[nidx];
3532
+ hdr->freeList = elem->next;
3533
+ elem->hashval = hashval;
3534
+ size_t hidx = hashval & (hsize - 1);
3535
+ elem->next = hdr->hashtab[hidx];
3536
+ hdr->hashtab[hidx] = nidx;
3537
+
3538
+ int i, d = hdr->dims;
3539
+ for( i = 0; i < d; i++ )
3540
+ elem->idx[i] = idx[i];
3541
+ size_t esz = elemSize();
3542
+ uchar* p = &value<uchar>(elem);
3543
+ if( esz == sizeof(float) )
3544
+ *((float*)p) = 0.f;
3545
+ else if( esz == sizeof(double) )
3546
+ *((double*)p) = 0.;
3547
+ else
3548
+ memset(p, 0, esz);
3549
+
3550
+ return p;
3551
+ }
3552
+
3553
+
3554
+ void SparseMat::removeNode(size_t hidx, size_t nidx, size_t previdx)
3555
+ {
3556
+ Node* n = node(nidx);
3557
+ if( previdx )
3558
+ {
3559
+ Node* prev = node(previdx);
3560
+ prev->next = n->next;
3561
+ }
3562
+ else
3563
+ hdr->hashtab[hidx] = n->next;
3564
+ n->next = hdr->freeList;
3565
+ hdr->freeList = nidx;
3566
+ --hdr->nodeCount;
3567
+ }
3568
+
3569
+
3570
+ SparseMatConstIterator::SparseMatConstIterator(const SparseMat* _m)
3571
+ : m((SparseMat*)_m), hashidx(0), ptr(0)
3572
+ {
3573
+ if(!_m || !_m->hdr)
3574
+ return;
3575
+ SparseMat::Hdr& hdr = *m->hdr;
3576
+ const vector<size_t>& htab = hdr.hashtab;
3577
+ size_t i, hsize = htab.size();
3578
+ for( i = 0; i < hsize; i++ )
3579
+ {
3580
+ size_t nidx = htab[i];
3581
+ if( nidx )
3582
+ {
3583
+ hashidx = i;
3584
+ ptr = &hdr.pool[nidx] + hdr.valueOffset;
3585
+ return;
3586
+ }
3587
+ }
3588
+ }
3589
+
3590
+ SparseMatConstIterator& SparseMatConstIterator::operator ++()
3591
+ {
3592
+ if( !ptr || !m || !m->hdr )
3593
+ return *this;
3594
+ SparseMat::Hdr& hdr = *m->hdr;
3595
+ size_t next = ((const SparseMat::Node*)(ptr - hdr.valueOffset))->next;
3596
+ if( next )
3597
+ {
3598
+ ptr = &hdr.pool[next] + hdr.valueOffset;
3599
+ return *this;
3600
+ }
3601
+ size_t i = hashidx + 1, sz = hdr.hashtab.size();
3602
+ for( ; i < sz; i++ )
3603
+ {
3604
+ size_t nidx = hdr.hashtab[i];
3605
+ if( nidx )
3606
+ {
3607
+ hashidx = i;
3608
+ ptr = &hdr.pool[nidx] + hdr.valueOffset;
3609
+ return *this;
3610
+ }
3611
+ }
3612
+ hashidx = sz;
3613
+ ptr = 0;
3614
+ return *this;
3615
+ }
3616
+
3617
+
3618
+ double norm( const SparseMat& src, int normType )
3619
+ {
3620
+ SparseMatConstIterator it = src.begin();
3621
+
3622
+ size_t i, N = src.nzcount();
3623
+ normType &= NORM_TYPE_MASK;
3624
+ int type = src.type();
3625
+ double result = 0;
3626
+
3627
+ CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
3628
+
3629
+ if( type == CV_32F )
3630
+ {
3631
+ if( normType == NORM_INF )
3632
+ for( i = 0; i < N; i++, ++it )
3633
+ result = std::max(result, std::abs((double)*(const float*)it.ptr));
3634
+ else if( normType == NORM_L1 )
3635
+ for( i = 0; i < N; i++, ++it )
3636
+ result += std::abs(*(const float*)it.ptr);
3637
+ else
3638
+ for( i = 0; i < N; i++, ++it )
3639
+ {
3640
+ double v = *(const float*)it.ptr;
3641
+ result += v*v;
3642
+ }
3643
+ }
3644
+ else if( type == CV_64F )
3645
+ {
3646
+ if( normType == NORM_INF )
3647
+ for( i = 0; i < N; i++, ++it )
3648
+ result = std::max(result, std::abs(*(const double*)it.ptr));
3649
+ else if( normType == NORM_L1 )
3650
+ for( i = 0; i < N; i++, ++it )
3651
+ result += std::abs(*(const double*)it.ptr);
3652
+ else
3653
+ for( i = 0; i < N; i++, ++it )
3654
+ {
3655
+ double v = *(const double*)it.ptr;
3656
+ result += v*v;
3657
+ }
3658
+ }
3659
+ else
3660
+ CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" );
3661
+
3662
+ if( normType == NORM_L2 )
3663
+ result = std::sqrt(result);
3664
+ return result;
3665
+ }
3666
+
3667
+ void minMaxLoc( const SparseMat& src, double* _minval, double* _maxval, int* _minidx, int* _maxidx )
3668
+ {
3669
+ SparseMatConstIterator it = src.begin();
3670
+ size_t i, N = src.nzcount(), d = src.hdr ? src.hdr->dims : 0;
3671
+ int type = src.type();
3672
+ const int *minidx = 0, *maxidx = 0;
3673
+
3674
+ if( type == CV_32F )
3675
+ {
3676
+ float minval = FLT_MAX, maxval = -FLT_MAX;
3677
+ for( i = 0; i < N; i++, ++it )
3678
+ {
3679
+ float v = *(const float*)it.ptr;
3680
+ if( v < minval )
3681
+ {
3682
+ minval = v;
3683
+ minidx = it.node()->idx;
3684
+ }
3685
+ if( v > maxval )
3686
+ {
3687
+ maxval = v;
3688
+ maxidx = it.node()->idx;
3689
+ }
3690
+ }
3691
+ if( _minval )
3692
+ *_minval = minval;
3693
+ if( _maxval )
3694
+ *_maxval = maxval;
3695
+ }
3696
+ else if( type == CV_64F )
3697
+ {
3698
+ double minval = DBL_MAX, maxval = -DBL_MAX;
3699
+ for( i = 0; i < N; i++, ++it )
3700
+ {
3701
+ double v = *(const double*)it.ptr;
3702
+ if( v < minval )
3703
+ {
3704
+ minval = v;
3705
+ minidx = it.node()->idx;
3706
+ }
3707
+ if( v > maxval )
3708
+ {
3709
+ maxval = v;
3710
+ maxidx = it.node()->idx;
3711
+ }
3712
+ }
3713
+ if( _minval )
3714
+ *_minval = minval;
3715
+ if( _maxval )
3716
+ *_maxval = maxval;
3717
+ }
3718
+ else
3719
+ CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" );
3720
+
3721
+ if( _minidx )
3722
+ for( i = 0; i < d; i++ )
3723
+ _minidx[i] = minidx[i];
3724
+ if( _maxidx )
3725
+ for( i = 0; i < d; i++ )
3726
+ _maxidx[i] = maxidx[i];
3727
+ }
3728
+
3729
+
3730
+ void normalize( const SparseMat& src, SparseMat& dst, double a, int norm_type )
3731
+ {
3732
+ double scale = 1;
3733
+ if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C )
3734
+ {
3735
+ scale = norm( src, norm_type );
3736
+ scale = scale > DBL_EPSILON ? a/scale : 0.;
3737
+ }
3738
+ else
3739
+ CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" );
3740
+
3741
+ src.convertTo( dst, -1, scale );
3742
+ }
3743
+
3744
+ ////////////////////// RotatedRect //////////////////////
3745
+
3746
+ void RotatedRect::points(Point2f pt[]) const
3747
+ {
3748
+ double _angle = angle*CV_PI/180.;
3749
+ float b = (float)cos(_angle)*0.5f;
3750
+ float a = (float)sin(_angle)*0.5f;
3751
+
3752
+ pt[0].x = center.x - a*size.height - b*size.width;
3753
+ pt[0].y = center.y + b*size.height - a*size.width;
3754
+ pt[1].x = center.x + a*size.height - b*size.width;
3755
+ pt[1].y = center.y - b*size.height - a*size.width;
3756
+ pt[2].x = 2*center.x - pt[0].x;
3757
+ pt[2].y = 2*center.y - pt[0].y;
3758
+ pt[3].x = 2*center.x - pt[1].x;
3759
+ pt[3].y = 2*center.y - pt[1].y;
3760
+ }
3761
+
3762
+ Rect RotatedRect::boundingRect() const
3763
+ {
3764
+ Point2f pt[4];
3765
+ points(pt);
3766
+ Rect r(cvFloor(min(min(min(pt[0].x, pt[1].x), pt[2].x), pt[3].x)),
3767
+ cvFloor(min(min(min(pt[0].y, pt[1].y), pt[2].y), pt[3].y)),
3768
+ cvCeil(max(max(max(pt[0].x, pt[1].x), pt[2].x), pt[3].x)),
3769
+ cvCeil(max(max(max(pt[0].y, pt[1].y), pt[2].y), pt[3].y)));
3770
+ r.width -= r.x - 1;
3771
+ r.height -= r.y - 1;
3772
+ return r;
3773
+ }
3774
+
3775
+ }
3776
+
3777
+ /* End of file. */