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.
- data/.gitignore +24 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/ext/imagecore/analyze_image.cxx +58 -0
- data/ext/imagecore/analyze_image.h +6 -0
- data/ext/imagecore/extconf.rb +9 -0
- data/ext/imagecore/imagecore.cxx +34 -0
- data/ext/opencv/core/___.c +3 -0
- data/ext/opencv/core/alloc.cpp +697 -0
- data/ext/opencv/core/array.cpp +3206 -0
- data/ext/opencv/core/datastructs.cpp +4064 -0
- data/ext/opencv/core/extconf.rb +22 -0
- data/ext/opencv/core/matrix.cpp +3777 -0
- data/ext/opencv/core/precomp.hpp +216 -0
- data/ext/opencv/core/system.cpp +832 -0
- data/ext/opencv/core/tables.cpp +3512 -0
- data/ext/opencv/highgui/___.c +3 -0
- data/ext/opencv/highgui/bitstrm.cpp +582 -0
- data/ext/opencv/highgui/bitstrm.hpp +182 -0
- data/ext/opencv/highgui/extconf.rb +28 -0
- data/ext/opencv/highgui/grfmt_base.cpp +128 -0
- data/ext/opencv/highgui/grfmt_base.hpp +113 -0
- data/ext/opencv/highgui/grfmt_bmp.cpp +564 -0
- data/ext/opencv/highgui/grfmt_bmp.hpp +99 -0
- data/ext/opencv/highgui/grfmt_exr.hpp +113 -0
- data/ext/opencv/highgui/grfmt_imageio.hpp +56 -0
- data/ext/opencv/highgui/grfmt_jpeg.cpp +622 -0
- data/ext/opencv/highgui/grfmt_jpeg.hpp +90 -0
- data/ext/opencv/highgui/grfmt_jpeg2000.cpp +529 -0
- data/ext/opencv/highgui/grfmt_jpeg2000.hpp +95 -0
- data/ext/opencv/highgui/grfmt_png.cpp +406 -0
- data/ext/opencv/highgui/grfmt_png.hpp +101 -0
- data/ext/opencv/highgui/grfmt_pxm.cpp +513 -0
- data/ext/opencv/highgui/grfmt_pxm.hpp +92 -0
- data/ext/opencv/highgui/grfmt_sunras.cpp +425 -0
- data/ext/opencv/highgui/grfmt_sunras.hpp +105 -0
- data/ext/opencv/highgui/grfmt_tiff.cpp +718 -0
- data/ext/opencv/highgui/grfmt_tiff.hpp +136 -0
- data/ext/opencv/highgui/grfmts.hpp +56 -0
- data/ext/opencv/highgui/loadsave.cpp +535 -0
- data/ext/opencv/highgui/precomp.hpp +223 -0
- data/ext/opencv/highgui/utils.cpp +689 -0
- data/ext/opencv/highgui/utils.hpp +128 -0
- data/ext/opencv/imgproc/___.c +3 -0
- data/ext/opencv/imgproc/_geom.h +72 -0
- data/ext/opencv/imgproc/color.cpp +3179 -0
- data/ext/opencv/imgproc/contours.cpp +1780 -0
- data/ext/opencv/imgproc/extconf.rb +11 -0
- data/ext/opencv/imgproc/filter.cpp +3063 -0
- data/ext/opencv/imgproc/precomp.hpp +159 -0
- data/ext/opencv/imgproc/shapedescr.cpp +1306 -0
- data/ext/opencv/imgproc/smooth.cpp +1566 -0
- data/ext/opencv/imgproc/tables.cpp +214 -0
- data/ext/opencv/imgproc/thresh.cpp +636 -0
- data/ext/opencv/imgproc/utils.cpp +242 -0
- data/ext/opencv/include/opencv2/core/core.hpp +4344 -0
- data/ext/opencv/include/opencv2/core/core_c.h +1885 -0
- data/ext/opencv/include/opencv2/core/internal.hpp +710 -0
- data/ext/opencv/include/opencv2/core/mat.hpp +2557 -0
- data/ext/opencv/include/opencv2/core/operations.hpp +3623 -0
- data/ext/opencv/include/opencv2/core/types_c.h +1875 -0
- data/ext/opencv/include/opencv2/core/version.hpp +58 -0
- data/ext/opencv/include/opencv2/highgui/highgui.hpp +198 -0
- data/ext/opencv/include/opencv2/highgui/highgui_c.h +506 -0
- data/ext/opencv/include/opencv2/imgproc/imgproc.hpp +1139 -0
- data/ext/opencv/include/opencv2/imgproc/imgproc_c.h +783 -0
- data/ext/opencv/include/opencv2/imgproc/types_c.h +538 -0
- data/imagecore.gemspec +20 -0
- data/lib/imagecore.rb +16 -0
- data/lib/imagecore/version.rb +3 -0
- 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. */
|