matrix.cpp 153.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"
A
Alexander Alekhin 已提交
44
#include "opencl_kernels_core.hpp"
45

A
Alexander Alekhin 已提交
46 47
#include "bufferpool.impl.hpp"

48 49 50 51 52 53
/****************************************************************************************\
*                           [scaled] Identity matrix initialization                      *
\****************************************************************************************/

namespace cv {

54 55 56
void MatAllocator::map(UMatData*, int) const
{
}
57

58 59 60
void MatAllocator::unmap(UMatData* u) const
{
    if(u->urefcount == 0 && u->refcount == 0)
A
Alexander Alekhin 已提交
61
    {
62
        deallocate(u);
A
Alexander Alekhin 已提交
63 64
        u = NULL;
    }
65
}
66

67 68 69 70 71 72 73 74 75 76
void MatAllocator::download(UMatData* u, void* dstptr,
         int dims, const size_t sz[],
         const size_t srcofs[], const size_t srcstep[],
         const size_t dststep[]) const
{
    if(!u)
        return;
    int isz[CV_MAX_DIM];
    uchar* srcptr = u->data;
    for( int i = 0; i < dims; i++ )
77
    {
78 79
        CV_Assert( sz[i] <= (size_t)INT_MAX );
        if( sz[i] == 0 )
80
            return;
81
        if( srcofs )
82
            srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1);
83
        isz[i] = (int)sz[i];
84 85
    }

86 87
    Mat src(dims, isz, CV_8U, srcptr, srcstep);
    Mat dst(dims, isz, CV_8U, dstptr, dststep);
88

89 90 91
    const Mat* arrays[] = { &src, &dst };
    uchar* ptrs[2];
    NAryMatIterator it(arrays, ptrs, 2);
92
    size_t planesz = it.size;
93

94
    for( size_t j = 0; j < it.nplanes; j++, ++it )
95 96 97 98 99 100 101 102 103 104 105 106 107
        memcpy(ptrs[1], ptrs[0], planesz);
}


void MatAllocator::upload(UMatData* u, const void* srcptr, int dims, const size_t sz[],
                    const size_t dstofs[], const size_t dststep[],
                    const size_t srcstep[]) const
{
    if(!u)
        return;
    int isz[CV_MAX_DIM];
    uchar* dstptr = u->data;
    for( int i = 0; i < dims; i++ )
108
    {
109 110
        CV_Assert( sz[i] <= (size_t)INT_MAX );
        if( sz[i] == 0 )
111
            return;
112
        if( dstofs )
113
            dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1);
114
        isz[i] = (int)sz[i];
115 116
    }

117 118 119 120 121 122
    Mat src(dims, isz, CV_8U, (void*)srcptr, srcstep);
    Mat dst(dims, isz, CV_8U, dstptr, dststep);

    const Mat* arrays[] = { &src, &dst };
    uchar* ptrs[2];
    NAryMatIterator it(arrays, ptrs, 2);
123
    size_t planesz = it.size;
124

125
    for( size_t j = 0; j < it.nplanes; j++, ++it )
126 127 128 129
        memcpy(ptrs[1], ptrs[0], planesz);
}

void MatAllocator::copy(UMatData* usrc, UMatData* udst, int dims, const size_t sz[],
130
                  const size_t srcofs[], const size_t srcstep[],
131
                  const size_t dstofs[], const size_t dststep[], bool /*sync*/) const
132
{
133 134
    CV_INSTRUMENT_REGION()

135 136 137 138 139 140
    if(!usrc || !udst)
        return;
    int isz[CV_MAX_DIM];
    uchar* srcptr = usrc->data;
    uchar* dstptr = udst->data;
    for( int i = 0; i < dims; i++ )
141
    {
142 143
        CV_Assert( sz[i] <= (size_t)INT_MAX );
        if( sz[i] == 0 )
I
Ilya Lavrenov 已提交
144
            return;
145
        if( srcofs )
I
Ilya Lavrenov 已提交
146
            srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1);
147
        if( dstofs )
I
Ilya Lavrenov 已提交
148
            dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1);
149 150
        isz[i] = (int)sz[i];
    }
151

152 153
    Mat src(dims, isz, CV_8U, srcptr, srcstep);
    Mat dst(dims, isz, CV_8U, dstptr, dststep);
154

155 156 157
    const Mat* arrays[] = { &src, &dst };
    uchar* ptrs[2];
    NAryMatIterator it(arrays, ptrs, 2);
158
    size_t planesz = it.size;
159

160
    for( size_t j = 0; j < it.nplanes; j++, ++it )
161 162
        memcpy(ptrs[1], ptrs[0], planesz);
}
163

A
Alexander Alekhin 已提交
164
BufferPoolController* MatAllocator::getBufferPoolController(const char* id) const
A
Alexander Alekhin 已提交
165
{
A
Alexander Alekhin 已提交
166
    (void)id;
A
Alexander Alekhin 已提交
167 168 169 170
    static DummyBufferPoolController dummy;
    return &dummy;
}

171 172 173 174
class StdMatAllocator : public MatAllocator
{
public:
    UMatData* allocate(int dims, const int* sizes, int type,
175
                       void* data0, size_t* step, int /*flags*/, UMatUsageFlags /*usageFlags*/) const
176
    {
177 178
        size_t total = CV_ELEM_SIZE(type);
        for( int i = dims-1; i >= 0; i-- )
179
        {
180 181 182 183 184 185 186 187 188 189 190
            if( step )
            {
                if( data0 && step[i] != CV_AUTOSTEP )
                {
                    CV_Assert(total <= step[i]);
                    total = step[i];
                }
                else
                    step[i] = total;
            }
            total *= sizes[i];
191
        }
192 193 194 195 196 197
        uchar* data = data0 ? (uchar*)data0 : (uchar*)fastMalloc(total);
        UMatData* u = new UMatData(this);
        u->data = u->origdata = data;
        u->size = total;
        if(data0)
            u->flags |= UMatData::USER_ALLOCATED;
198

199 200
        return u;
    }
201

202
    bool allocate(UMatData* u, int /*accessFlags*/, UMatUsageFlags /*usageFlags*/) const
203 204 205
    {
        if(!u) return false;
        return true;
206 207
    }

208
    void deallocate(UMatData* u) const
209
    {
210 211 212
        if(!u)
            return;

213 214 215
        CV_Assert(u->urefcount == 0);
        CV_Assert(u->refcount == 0);
        if( !(u->flags & UMatData::USER_ALLOCATED) )
216
        {
217 218
            fastFree(u->origdata);
            u->origdata = 0;
219
        }
220
        delete u;
221 222
    }
};
223 224
namespace
{
D
Dan 已提交
225
    MatAllocator* g_matAllocator = NULL;
226
}
227

228 229 230

MatAllocator* Mat::getDefaultAllocator()
{
D
Dan 已提交
231 232 233 234 235
    if (g_matAllocator == NULL)
    {
        g_matAllocator = getStdAllocator();
    }
    return g_matAllocator;
236 237 238
}
void Mat::setDefaultAllocator(MatAllocator* allocator)
{
D
Dan 已提交
239
    g_matAllocator = allocator;
240
}
241 242
MatAllocator* Mat::getStdAllocator()
{
D
Dan 已提交
243
    CV_SINGLETON_LAZY_INIT(MatAllocator, new StdMatAllocator())
244 245
}

V
Vadim Pisarevsky 已提交
246 247
void swap( Mat& a, Mat& b )
{
248 249 250 251 252 253 254 255 256
    std::swap(a.flags, b.flags);
    std::swap(a.dims, b.dims);
    std::swap(a.rows, b.rows);
    std::swap(a.cols, b.cols);
    std::swap(a.data, b.data);
    std::swap(a.datastart, b.datastart);
    std::swap(a.dataend, b.dataend);
    std::swap(a.datalimit, b.datalimit);
    std::swap(a.allocator, b.allocator);
257
    std::swap(a.u, b.u);
258

259 260 261 262
    std::swap(a.size.p, b.size.p);
    std::swap(a.step.p, b.step.p);
    std::swap(a.step.buf[0], b.step.buf[0]);
    std::swap(a.step.buf[1], b.step.buf[1]);
263

V
Vadim Pisarevsky 已提交
264 265 266 267 268
    if( a.step.p == b.step.buf )
    {
        a.step.p = a.step.buf;
        a.size.p = &a.rows;
    }
269

V
Vadim Pisarevsky 已提交
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
    if( b.step.p == a.step.buf )
    {
        b.step.p = b.step.buf;
        b.size.p = &b.rows;
    }
}


static inline void setSize( Mat& m, int _dims, const int* _sz,
                            const size_t* _steps, bool autoSteps=false )
{
    CV_Assert( 0 <= _dims && _dims <= CV_MAX_DIM );
    if( m.dims != _dims )
    {
        if( m.step.p != m.step.buf )
        {
            fastFree(m.step.p);
            m.step.p = m.step.buf;
            m.size.p = &m.rows;
        }
        if( _dims > 2 )
        {
            m.step.p = (size_t*)fastMalloc(_dims*sizeof(m.step.p[0]) + (_dims+1)*sizeof(m.size.p[0]));
            m.size.p = (int*)(m.step.p + _dims) + 1;
            m.size.p[-1] = _dims;
295
            m.rows = m.cols = -1;
V
Vadim Pisarevsky 已提交
296 297
        }
    }
298

V
Vadim Pisarevsky 已提交
299 300 301
    m.dims = _dims;
    if( !_sz )
        return;
302

I
Ilya Lavrenov 已提交
303
    size_t esz = CV_ELEM_SIZE(m.flags), esz1 = CV_ELEM_SIZE1(m.flags), total = esz;
304
    for( int i = _dims-1; i >= 0; i-- )
V
Vadim Pisarevsky 已提交
305 306
    {
        int s = _sz[i];
307
        CV_Assert( s >= 0 );
V
Vadim Pisarevsky 已提交
308
        m.size.p[i] = s;
309

V
Vadim Pisarevsky 已提交
310
        if( _steps )
I
Ilya Lavrenov 已提交
311 312 313 314 315 316
        {
            if (_steps[i] % esz1 != 0)
            {
                CV_Error(Error::BadStep, "Step must be a multiple of esz1");
            }

V
Vadim Pisarevsky 已提交
317
            m.step.p[i] = i < _dims-1 ? _steps[i] : esz;
I
Ilya Lavrenov 已提交
318
        }
V
Vadim Pisarevsky 已提交
319 320 321 322 323 324 325 326 327
        else if( autoSteps )
        {
            m.step.p[i] = total;
            int64 total1 = (int64)total*s;
            if( (uint64)total1 != (size_t)total1 )
                CV_Error( CV_StsOutOfRange, "The total matrix size does not fit to \"size_t\" type" );
            total = (size_t)total1;
        }
    }
328

V
Vadim Pisarevsky 已提交
329 330 331 332 333 334 335
    if( _dims == 1 )
    {
        m.dims = 2;
        m.cols = 1;
        m.step[1] = esz;
    }
}
336

337
static void updateContinuityFlag(Mat& m)
V
Vadim Pisarevsky 已提交
338 339 340 341 342 343 344
{
    int i, j;
    for( i = 0; i < m.dims; i++ )
    {
        if( m.size[i] > 1 )
            break;
    }
345

V
Vadim Pisarevsky 已提交
346 347 348 349 350
    for( j = m.dims-1; j > i; j-- )
    {
        if( m.step[j]*m.size[j] < m.step[j-1] )
            break;
    }
351

352
    uint64 t = (uint64)m.step[0]*m.size[0];
353
    if( j <= i && t == (size_t)t )
V
Vadim Pisarevsky 已提交
354
        m.flags |= Mat::CONTINUOUS_FLAG;
355 356 357
    else
        m.flags &= ~Mat::CONTINUOUS_FLAG;
}
358

359 360 361
static void finalizeHdr(Mat& m)
{
    updateContinuityFlag(m);
362 363
    int d = m.dims;
    if( d > 2 )
V
Vadim Pisarevsky 已提交
364
        m.rows = m.cols = -1;
365
    if(m.u)
366
        m.datastart = m.data = m.u->data;
V
Vadim Pisarevsky 已提交
367 368
    if( m.data )
    {
369 370 371
        m.datalimit = m.datastart + m.size[0]*m.step[0];
        if( m.size[0] > 0 )
        {
372
            m.dataend = m.ptr() + m.size[d-1]*m.step[d-1];
373
            for( int i = 0; i < d-1; i++ )
374 375 376 377
                m.dataend += (m.size[i] - 1)*m.step[i];
        }
        else
            m.dataend = m.datalimit;
V
Vadim Pisarevsky 已提交
378
    }
379 380
    else
        m.dataend = m.datalimit = 0;
V
Vadim Pisarevsky 已提交
381
}
382 383


V
Vadim Pisarevsky 已提交
384 385 386
void Mat::create(int d, const int* _sizes, int _type)
{
    int i;
V
Vladislav Vinogradov 已提交
387
    CV_Assert(0 <= d && d <= CV_MAX_DIM && _sizes);
V
Vadim Pisarevsky 已提交
388
    _type = CV_MAT_TYPE(_type);
389

V
Vadim Pisarevsky 已提交
390 391 392 393 394 395 396 397 398 399
    if( data && (d == dims || (d == 1 && dims <= 2)) && _type == type() )
    {
        if( d == 2 && rows == _sizes[0] && cols == _sizes[1] )
            return;
        for( i = 0; i < d; i++ )
            if( size[i] != _sizes[i] )
                break;
        if( i == d && (d > 1 || size[1] == 1))
            return;
    }
400

401 402 403 404 405 406 407 408
    int _sizes_backup[CV_MAX_DIM]; // #5991
    if (_sizes == (this->size.p))
    {
        for(i = 0; i < d; i++ )
            _sizes_backup[i] = _sizes[i];
        _sizes = _sizes_backup;
    }

V
Vadim Pisarevsky 已提交
409 410 411 412
    release();
    if( d == 0 )
        return;
    flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL;
413
    setSize(*this, d, _sizes, 0, true);
414

415
    if( total() > 0 )
V
Vadim Pisarevsky 已提交
416
    {
417
        MatAllocator *a = allocator, *a0 = getDefaultAllocator();
A
Andrey Pavlenko 已提交
418
#ifdef HAVE_TGPU
419 420
        if( !a || a == tegra::getAllocator() )
            a = tegra::getAllocator(d, _sizes, _type);
A
Andrey Pavlenko 已提交
421
#endif
422 423 424
        if(!a)
            a = a0;
        try
425
        {
426
            u = a->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT);
427
            CV_Assert(u != 0);
428
        }
429
        catch(...)
430
        {
431
            if(a != a0)
432
                u = a0->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT);
433
            CV_Assert(u != 0);
434
        }
435
        CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
V
Vadim Pisarevsky 已提交
436
    }
437

A
Alexander Alekhin 已提交
438
    addref();
V
Vadim Pisarevsky 已提交
439 440 441 442 443 444 445 446 447 448 449 450
    finalizeHdr(*this);
}

void Mat::copySize(const Mat& m)
{
    setSize(*this, m.dims, 0, 0);
    for( int i = 0; i < dims; i++ )
    {
        size[i] = m.size[i];
        step[i] = m.step[i];
    }
}
451

V
Vadim Pisarevsky 已提交
452 453
void Mat::deallocate()
{
454
    if(u)
455
        (u->currAllocator ? u->currAllocator : allocator ? allocator : getDefaultAllocator())->unmap(u);
A
Alexander Alekhin 已提交
456
    u = NULL;
V
Vadim Pisarevsky 已提交
457 458
}

A
Andrey Kamaev 已提交
459
Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange)
460 461
    : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
      datalimit(0), allocator(0), u(0), size(&rows)
V
Vadim Pisarevsky 已提交
462 463 464 465 466
{
    CV_Assert( m.dims >= 2 );
    if( m.dims > 2 )
    {
        AutoBuffer<Range> rs(m.dims);
A
Andrey Kamaev 已提交
467 468
        rs[0] = _rowRange;
        rs[1] = _colRange;
V
Vadim Pisarevsky 已提交
469 470 471 472 473
        for( int i = 2; i < m.dims; i++ )
            rs[i] = Range::all();
        *this = m(rs);
        return;
    }
474

V
Vadim Pisarevsky 已提交
475
    *this = m;
A
Andrey Kamaev 已提交
476
    if( _rowRange != Range::all() && _rowRange != Range(0,rows) )
V
Vadim Pisarevsky 已提交
477
    {
A
Andrey Kamaev 已提交
478 479 480
        CV_Assert( 0 <= _rowRange.start && _rowRange.start <= _rowRange.end && _rowRange.end <= m.rows );
        rows = _rowRange.size();
        data += step*_rowRange.start;
481
        flags |= SUBMATRIX_FLAG;
V
Vadim Pisarevsky 已提交
482
    }
483

A
Andrey Kamaev 已提交
484
    if( _colRange != Range::all() && _colRange != Range(0,cols) )
V
Vadim Pisarevsky 已提交
485
    {
A
Andrey Kamaev 已提交
486 487 488
        CV_Assert( 0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols );
        cols = _colRange.size();
        data += _colRange.start*elemSize();
V
Vadim Pisarevsky 已提交
489
        flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1;
490
        flags |= SUBMATRIX_FLAG;
V
Vadim Pisarevsky 已提交
491
    }
492

V
Vadim Pisarevsky 已提交
493 494
    if( rows == 1 )
        flags |= CONTINUOUS_FLAG;
495

V
Vadim Pisarevsky 已提交
496 497 498 499 500 501
    if( rows <= 0 || cols <= 0 )
    {
        release();
        rows = cols = 0;
    }
}
502 503


V
Vadim Pisarevsky 已提交
504 505
Mat::Mat(const Mat& m, const Rect& roi)
    : flags(m.flags), dims(2), rows(roi.height), cols(roi.width),
506
    data(m.data + roi.y*m.step[0]),
507
    datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit),
508
    allocator(m.allocator), u(m.u), size(&rows)
V
Vadim Pisarevsky 已提交
509 510 511 512
{
    CV_Assert( m.dims <= 2 );
    flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1;
    flags |= roi.height == 1 ? CONTINUOUS_FLAG : 0;
513

514
    size_t esz = CV_ELEM_SIZE(flags);
V
Vadim Pisarevsky 已提交
515 516 517
    data += roi.x*esz;
    CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols &&
              0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows );
518 519
    if( u )
        CV_XADD(&u->refcount, 1);
520 521
    if( roi.width < m.cols || roi.height < m.rows )
        flags |= SUBMATRIX_FLAG;
522

V
Vadim Pisarevsky 已提交
523
    step[0] = m.step[0]; step[1] = esz;
524

V
Vadim Pisarevsky 已提交
525 526 527 528 529 530 531
    if( rows <= 0 || cols <= 0 )
    {
        release();
        rows = cols = 0;
    }
}

532

A
Andrey Kamaev 已提交
533
Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _steps)
534 535
    : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
      datalimit(0), allocator(0), u(0), size(&rows)
V
Vadim Pisarevsky 已提交
536
{
537
    flags |= CV_MAT_TYPE(_type);
538
    datastart = data = (uchar*)_data;
V
Vadim Pisarevsky 已提交
539 540 541
    setSize(*this, _dims, _sizes, _steps, true);
    finalizeHdr(*this);
}
542 543


A
Andrey Kamaev 已提交
544
Mat::Mat(const Mat& m, const Range* ranges)
545 546
    : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
      datalimit(0), allocator(0), u(0), size(&rows)
V
Vadim Pisarevsky 已提交
547
{
548
    int d = m.dims;
549

V
Vadim Pisarevsky 已提交
550
    CV_Assert(ranges);
551
    for( int i = 0; i < d; i++ )
V
Vadim Pisarevsky 已提交
552 553 554 555 556
    {
        Range r = ranges[i];
        CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) );
    }
    *this = m;
557
    for( int i = 0; i < d; i++ )
V
Vadim Pisarevsky 已提交
558 559
    {
        Range r = ranges[i];
560
        if( r != Range::all() && r != Range(0, size.p[i]))
V
Vadim Pisarevsky 已提交
561
        {
562 563 564
            size.p[i] = r.end - r.start;
            data += r.start*step.p[i];
            flags |= SUBMATRIX_FLAG;
V
Vadim Pisarevsky 已提交
565 566
        }
    }
567
    updateContinuityFlag(*this);
V
Vadim Pisarevsky 已提交
568
}
569 570


A
Andrey Kamaev 已提交
571
static Mat cvMatNDToMat(const CvMatND* m, bool copyData)
V
Vadim Pisarevsky 已提交
572
{
A
Andrey Kamaev 已提交
573 574
    Mat thiz;

575
    if( !m )
A
Andrey Kamaev 已提交
576
        return thiz;
577
    thiz.datastart = thiz.data = m->data.ptr;
A
Andrey Kamaev 已提交
578
    thiz.flags |= CV_MAT_TYPE(m->type);
V
Vadim Pisarevsky 已提交
579 580
    int _sizes[CV_MAX_DIM];
    size_t _steps[CV_MAX_DIM];
581

582 583
    int d = m->dims;
    for( int i = 0; i < d; i++ )
V
Vadim Pisarevsky 已提交
584 585 586 587
    {
        _sizes[i] = m->dim[i].size;
        _steps[i] = m->dim[i].step;
    }
588

A
Andrey Kamaev 已提交
589 590
    setSize(thiz, d, _sizes, _steps);
    finalizeHdr(thiz);
V
Vadim Pisarevsky 已提交
591 592 593

    if( copyData )
    {
A
Andrey Kamaev 已提交
594 595 596
        Mat temp(thiz);
        thiz.release();
        temp.copyTo(thiz);
V
Vadim Pisarevsky 已提交
597
    }
598

A
Andrey Kamaev 已提交
599
    return thiz;
V
Vadim Pisarevsky 已提交
600
}
601

A
Andrey Kamaev 已提交
602
static Mat cvMatToMat(const CvMat* m, bool copyData)
603
{
A
Andrey Kamaev 已提交
604
    Mat thiz;
605

606
    if( !m )
A
Andrey Kamaev 已提交
607
        return thiz;
608

609 610
    if( !copyData )
    {
A
Andrey Kamaev 已提交
611 612 613 614
        thiz.flags = Mat::MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG));
        thiz.dims = 2;
        thiz.rows = m->rows;
        thiz.cols = m->cols;
615
        thiz.datastart = thiz.data = m->data.ptr;
A
Andrey Kamaev 已提交
616
        size_t esz = CV_ELEM_SIZE(m->type), minstep = thiz.cols*esz, _step = m->step;
617 618
        if( _step == 0 )
            _step = minstep;
A
Andrey Kamaev 已提交
619 620 621
        thiz.datalimit = thiz.datastart + _step*thiz.rows;
        thiz.dataend = thiz.datalimit - _step + minstep;
        thiz.step[0] = _step; thiz.step[1] = esz;
622 623 624
    }
    else
    {
625
        thiz.datastart = thiz.dataend = thiz.data = 0;
A
Andrey Kamaev 已提交
626
        Mat(m->rows, m->cols, m->type, m->data.ptr, m->step).copyTo(thiz);
627
    }
A
Andrey Kamaev 已提交
628 629

    return thiz;
630 631
}

632

A
Andrey Kamaev 已提交
633
static Mat iplImageToMat(const IplImage* img, bool copyData)
634
{
A
Andrey Kamaev 已提交
635
    Mat m;
636

637
    if( !img )
A
Andrey Kamaev 已提交
638
        return m;
639

A
Andrey Kamaev 已提交
640
    m.dims = 2;
641
    CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0);
642

A
Andrey Kamaev 已提交
643
    int imgdepth = IPL2CV_DEPTH(img->depth);
644
    size_t esz;
A
Andrey Kamaev 已提交
645
    m.step[0] = img->widthStep;
646 647 648 649

    if(!img->roi)
    {
        CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL);
A
Andrey Kamaev 已提交
650 651 652 653 654
        m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, img->nChannels);
        m.rows = img->height;
        m.cols = img->width;
        m.datastart = m.data = (uchar*)img->imageData;
        esz = CV_ELEM_SIZE(m.flags);
655 656 657 658 659
    }
    else
    {
        CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL || img->roi->coi != 0);
        bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE;
A
Andrey Kamaev 已提交
660 661 662 663
        m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, selectedPlane ? 1 : img->nChannels);
        m.rows = img->roi->height;
        m.cols = img->roi->width;
        esz = CV_ELEM_SIZE(m.flags);
664
        m.datastart = m.data = (uchar*)img->imageData +
A
Andrey Kamaev 已提交
665 666 667 668 669 670 671
            (selectedPlane ? (img->roi->coi - 1)*m.step*img->height : 0) +
            img->roi->yOffset*m.step[0] + img->roi->xOffset*esz;
    }
    m.datalimit = m.datastart + m.step.p[0]*m.rows;
    m.dataend = m.datastart + m.step.p[0]*(m.rows-1) + esz*m.cols;
    m.flags |= (m.cols*esz == m.step.p[0] || m.rows == 1 ? Mat::CONTINUOUS_FLAG : 0);
    m.step[1] = esz;
672 673 674

    if( copyData )
    {
A
Andrey Kamaev 已提交
675 676
        Mat m2 = m;
        m.release();
677 678
        if( !img->roi || !img->roi->coi ||
            img->dataOrder == IPL_DATA_ORDER_PLANE)
A
Andrey Kamaev 已提交
679
            m2.copyTo(m);
680 681 682
        else
        {
            int ch[] = {img->roi->coi - 1, 0};
A
Andrey Kamaev 已提交
683 684
            m.create(m2.rows, m2.cols, m2.type());
            mixChannels(&m2, 1, &m, 1, ch, 1);
685 686 687
        }
    }

A
Andrey Kamaev 已提交
688 689
    return m;
}
690

A
Andrey Kamaev 已提交
691
Mat Mat::diag(int d) const
692
{
V
Vadim Pisarevsky 已提交
693
    CV_Assert( dims <= 2 );
A
Andrey Kamaev 已提交
694 695 696
    Mat m = *this;
    size_t esz = elemSize();
    int len;
697

A
Andrey Kamaev 已提交
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
    if( d >= 0 )
    {
        len = std::min(cols - d, rows);
        m.data += esz*d;
    }
    else
    {
        len = std::min(rows + d, cols);
        m.data -= step[0]*d;
    }
    CV_DbgAssert( len > 0 );

    m.size[0] = m.rows = len;
    m.size[1] = m.cols = 1;
    m.step[0] += (len > 1 ? esz : 0);

    if( m.rows > 1 )
        m.flags &= ~CONTINUOUS_FLAG;
    else
        m.flags |= CONTINUOUS_FLAG;

    if( size() != Size(1,1) )
        m.flags |= SUBMATRIX_FLAG;

    return m;
}
724

725 726 727
void Mat::pop_back(size_t nelems)
{
    CV_Assert( nelems <= (size_t)size.p[0] );
728

729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
    if( isSubmatrix() )
        *this = rowRange(0, size.p[0] - (int)nelems);
    else
    {
        size.p[0] -= (int)nelems;
        dataend -= nelems*step.p[0];
        /*if( size.p[0] <= 1 )
        {
            if( dims <= 2 )
                flags |= CONTINUOUS_FLAG;
            else
                updateContinuityFlag(*this);
        }*/
    }
}
744 745


746 747 748 749 750
void Mat::push_back_(const void* elem)
{
    int r = size.p[0];
    if( isSubmatrix() || dataend + step.p[0] > datalimit )
        reserve( std::max(r + 1, (r*3+1)/2) );
751

752 753 754 755 756 757 758 759 760 761 762
    size_t esz = elemSize();
    memcpy(data + r*step.p[0], elem, esz);
    size.p[0] = r + 1;
    dataend += step.p[0];
    if( esz < step.p[0] )
        flags &= ~CONTINUOUS_FLAG;
}

void Mat::reserve(size_t nelems)
{
    const size_t MIN_SIZE = 64;
763

764 765 766
    CV_Assert( (int)nelems >= 0 );
    if( !isSubmatrix() && data + step.p[0]*nelems <= datalimit )
        return;
767

768
    int r = size.p[0];
769

770 771
    if( (size_t)r >= nelems )
        return;
772

773 774
    size.p[0] = std::max((int)nelems, 1);
    size_t newsize = total()*elemSize();
775

776 777
    if( newsize < MIN_SIZE )
        size.p[0] = (int)((MIN_SIZE + newsize - 1)*nelems/newsize);
778

779 780 781 782 783 784 785
    Mat m(dims, size.p, type());
    size.p[0] = r;
    if( r > 0 )
    {
        Mat mpart = m.rowRange(0, r);
        copyTo(mpart);
    }
786

787 788 789 790 791
    *this = m;
    size.p[0] = r;
    dataend = data + step.p[0]*r;
}

792

793 794 795
void Mat::resize(size_t nelems)
{
    int saveRows = size.p[0];
796 797
    if( saveRows == (int)nelems )
        return;
798
    CV_Assert( (int)nelems >= 0 );
799

800 801
    if( isSubmatrix() || data + step.p[0]*nelems > datalimit )
        reserve(nelems);
802

803 804
    size.p[0] = (int)nelems;
    dataend += (size.p[0] - saveRows)*step.p[0];
805

806
    //updateContinuityFlag(*this);
807 808
}

809 810 811 812 813

void Mat::resize(size_t nelems, const Scalar& s)
{
    int saveRows = size.p[0];
    resize(nelems);
814

815 816 817 818 819
    if( size.p[0] > saveRows )
    {
        Mat part = rowRange(saveRows, size.p[0]);
        part = s;
    }
820 821
}

822 823 824 825 826
void Mat::push_back(const Mat& elems)
{
    int r = size.p[0], delta = elems.size.p[0];
    if( delta == 0 )
        return;
827 828 829 830 831
    if( this == &elems )
    {
        Mat tmp = elems;
        push_back(tmp);
        return;
832
    }
833 834 835 836 837
    if( !data )
    {
        *this = elems.clone();
        return;
    }
838 839 840 841 842

    size.p[0] = elems.size.p[0];
    bool eq = size == elems.size;
    size.p[0] = r;
    if( !eq )
I
Ilya Lavrenov 已提交
843
        CV_Error(CV_StsUnmatchedSizes, "Pushed vector length is not equal to matrix row length");
844
    if( type() != elems.type() )
I
Ilya Lavrenov 已提交
845
        CV_Error(CV_StsUnmatchedFormats, "Pushed vector type is not the same as matrix type");
846

847 848
    if( isSubmatrix() || dataend + step.p[0]*delta > datalimit )
        reserve( std::max(r + delta, (r*3+1)/2) );
849

850 851
    size.p[0] += delta;
    dataend += step.p[0]*delta;
852

853
    //updateContinuityFlag(*this);
854

855 856 857 858 859 860 861 862 863
    if( isContinuous() && elems.isContinuous() )
        memcpy(data + r*step.p[0], elems.data, elems.total()*elems.elemSize());
    else
    {
        Mat part = rowRange(r, r + delta);
        elems.copyTo(part);
    }
}

864

865
Mat cvarrToMat(const CvArr* arr, bool copyData,
866
               bool /*allowND*/, int coiMode, AutoBuffer<double>* abuf )
867
{
V
Vadim Pisarevsky 已提交
868 869
    if( !arr )
        return Mat();
A
Andrey Kamaev 已提交
870 871
    if( CV_IS_MAT_HDR_Z(arr) )
        return cvMatToMat((const CvMat*)arr, copyData);
V
Vadim Pisarevsky 已提交
872
    if( CV_IS_MATND(arr) )
A
Andrey Kamaev 已提交
873
        return cvMatNDToMat((const CvMatND*)arr, copyData );
V
Vadim Pisarevsky 已提交
874
    if( CV_IS_IMAGE(arr) )
875 876 877 878
    {
        const IplImage* iplimg = (const IplImage*)arr;
        if( coiMode == 0 && iplimg->roi && iplimg->roi->coi > 0 )
            CV_Error(CV_BadCOI, "COI is not supported by the function");
A
Andrey Kamaev 已提交
879
        return iplImageToMat(iplimg, copyData);
880
    }
V
Vadim Pisarevsky 已提交
881
    if( CV_IS_SEQ(arr) )
882 883
    {
        CvSeq* seq = (CvSeq*)arr;
884 885 886 887
        int total = seq->total, type = CV_MAT_TYPE(seq->flags), esz = seq->elem_size;
        if( total == 0 )
            return Mat();
        CV_Assert(total > 0 && CV_ELEM_SIZE(seq->flags) == esz);
888
        if(!copyData && seq->first->next == seq->first)
889 890 891 892 893 894 895 896 897 898
            return Mat(total, 1, type, seq->first->data);
        if( abuf )
        {
            abuf->allocate(((size_t)total*esz + sizeof(double)-1)/sizeof(double));
            double* bufdata = *abuf;
            cvCvtSeqToArray(seq, bufdata, CV_WHOLE_SEQ);
            return Mat(total, 1, type, bufdata);
        }

        Mat buf(total, 1, type);
899
        cvCvtSeqToArray(seq, buf.ptr(), CV_WHOLE_SEQ);
900 901
        return buf;
    }
V
Vadim Pisarevsky 已提交
902 903 904 905 906 907 908 909 910
    CV_Error(CV_StsBadArg, "Unknown array type");
    return Mat();
}

void Mat::locateROI( Size& wholeSize, Point& ofs ) const
{
    CV_Assert( dims <= 2 && step[0] > 0 );
    size_t esz = elemSize(), minstep;
    ptrdiff_t delta1 = data - datastart, delta2 = dataend - datastart;
911

V
Vadim Pisarevsky 已提交
912 913
    if( delta1 == 0 )
        ofs.x = ofs.y = 0;
914 915
    else
    {
V
Vadim Pisarevsky 已提交
916 917 918
        ofs.y = (int)(delta1/step[0]);
        ofs.x = (int)((delta1 - step[0]*ofs.y)/esz);
        CV_DbgAssert( data == datastart + ofs.y*step[0] + ofs.x*esz );
919
    }
V
Vadim Pisarevsky 已提交
920 921 922 923 924
    minstep = (ofs.x + cols)*esz;
    wholeSize.height = (int)((delta2 - minstep)/step[0] + 1);
    wholeSize.height = std::max(wholeSize.height, ofs.y + rows);
    wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz);
    wholeSize.width = std::max(wholeSize.width, ofs.x + cols);
925 926
}

V
Vadim Pisarevsky 已提交
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright )
{
    CV_Assert( dims <= 2 && step[0] > 0 );
    Size wholeSize; Point ofs;
    size_t esz = elemSize();
    locateROI( wholeSize, ofs );
    int row1 = std::max(ofs.y - dtop, 0), row2 = std::min(ofs.y + rows + dbottom, wholeSize.height);
    int col1 = std::max(ofs.x - dleft, 0), col2 = std::min(ofs.x + cols + dright, wholeSize.width);
    data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
    rows = row2 - row1; cols = col2 - col1;
    size.p[0] = rows; size.p[1] = cols;
    if( esz*cols == step[0] || rows == 1 )
        flags |= CONTINUOUS_FLAG;
    else
        flags &= ~CONTINUOUS_FLAG;
    return *this;
943
}
944 945

}
946

947
void cv::extractImageCOI(const CvArr* arr, OutputArray _ch, int coi)
948 949
{
    Mat mat = cvarrToMat(arr, false, true, 1);
950 951
    _ch.create(mat.dims, mat.size, mat.depth());
    Mat ch = _ch.getMat();
V
Vadim Pisarevsky 已提交
952
    if(coi < 0)
953
    {
V
Vadim Pisarevsky 已提交
954 955 956
        CV_Assert( CV_IS_IMAGE(arr) );
        coi = cvGetImageCOI((const IplImage*)arr)-1;
    }
957 958 959 960
    CV_Assert(0 <= coi && coi < mat.channels());
    int _pairs[] = { coi, 0 };
    mixChannels( &mat, 1, &ch, 1, _pairs, 1 );
}
961

962
void cv::insertImageCOI(InputArray _ch, CvArr* arr, int coi)
963
{
964
    Mat ch = _ch.getMat(), mat = cvarrToMat(arr, false, true, 1);
V
Vadim Pisarevsky 已提交
965
    if(coi < 0)
966
    {
V
Vadim Pisarevsky 已提交
967 968 969
        CV_Assert( CV_IS_IMAGE(arr) );
        coi = cvGetImageCOI((const IplImage*)arr)-1;
    }
V
Vadim Pisarevsky 已提交
970
    CV_Assert(ch.size == mat.size && ch.depth() == mat.depth() && 0 <= coi && coi < mat.channels());
971 972 973
    int _pairs[] = { 0, coi };
    mixChannels( &ch, 1, &mat, 1, _pairs, 1 );
}
974

975 976
namespace cv
{
977 978 979 980

Mat Mat::reshape(int new_cn, int new_rows) const
{
    int cn = channels();
981
    Mat hdr = *this;
982

983 984 985 986 987 988 989
    if( dims > 2 && new_rows == 0 && new_cn != 0 && size[dims-1]*cn % new_cn == 0 )
    {
        hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
        hdr.step[dims-1] = CV_ELEM_SIZE(hdr.flags);
        hdr.size[dims-1] = hdr.size[dims-1]*cn / new_cn;
        return hdr;
    }
990

991
    CV_Assert( dims <= 2 );
992

993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
    if( new_cn == 0 )
        new_cn = cn;

    int total_width = cols * cn;

    if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 )
        new_rows = rows * total_width / new_cn;

    if( new_rows != 0 && new_rows != rows )
    {
        int total_size = total_width * rows;
        if( !isContinuous() )
            CV_Error( CV_BadStep,
            "The matrix is not continuous, thus its number of rows can not be changed" );

        if( (unsigned)new_rows > (unsigned)total_size )
            CV_Error( CV_StsOutOfRange, "Bad new number of rows" );

        total_width = total_size / new_rows;

        if( total_width * new_rows != total_size )
            CV_Error( CV_StsBadArg, "The total number of matrix elements "
                                    "is not divisible by the new number of rows" );

        hdr.rows = new_rows;
V
Vadim Pisarevsky 已提交
1018
        hdr.step[0] = total_width * elemSize1();
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
    }

    int new_width = total_width / new_cn;

    if( new_width * new_cn != total_width )
        CV_Error( CV_BadNumChannels,
        "The total width is not divisible by the new number of channels" );

    hdr.cols = new_width;
    hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
1029
    hdr.step[1] = CV_ELEM_SIZE(hdr.flags);
1030 1031 1032
    return hdr;
}

A
Andrey Kamaev 已提交
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
Mat Mat::diag(const Mat& d)
{
    CV_Assert( d.cols == 1 || d.rows == 1 );
    int len = d.rows + d.cols - 1;
    Mat m(len, len, d.type(), Scalar(0));
    Mat md = m.diag();
    if( d.cols == 1 )
        d.copyTo(md);
    else
        transpose(d, md);
    return m;
}
1045

1046 1047 1048 1049
int Mat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) const
{
    return (depth() == _depth || _depth <= 0) &&
        (isContinuous() || !_requireContinuous) &&
1050 1051
        ((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) ||
                        (cols == _elemChannels && channels() == 1))) ||
1052 1053 1054 1055
        (dims == 3 && channels() == 1 && size.p[2] == _elemChannels && (size.p[0] == 1 || size.p[1] == 1) &&
         (isContinuous() || step.p[1] == step.p[2]*size.p[2])))
    ? (int)(total()*channels()/_elemChannels) : -1;
}
1056 1057 1058 1059


void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
{
1060 1061
    CV_INSTRUMENT_REGION()

1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
    int i, depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
    CV_Assert(cn <= 4);
    switch(depth)
    {
    case CV_8U:
        {
        uchar* buf = (uchar*)_buf;
        for(i = 0; i < cn; i++)
            buf[i] = saturate_cast<uchar>(s.val[i]);
        for(; i < unroll_to; i++)
            buf[i] = buf[i-cn];
        }
        break;
    case CV_8S:
        {
        schar* buf = (schar*)_buf;
        for(i = 0; i < cn; i++)
            buf[i] = saturate_cast<schar>(s.val[i]);
        for(; i < unroll_to; i++)
            buf[i] = buf[i-cn];
        }
        break;
    case CV_16U:
        {
        ushort* buf = (ushort*)_buf;
        for(i = 0; i < cn; i++)
            buf[i] = saturate_cast<ushort>(s.val[i]);
        for(; i < unroll_to; i++)
            buf[i] = buf[i-cn];
        }
        break;
    case CV_16S:
        {
        short* buf = (short*)_buf;
        for(i = 0; i < cn; i++)
            buf[i] = saturate_cast<short>(s.val[i]);
        for(; i < unroll_to; i++)
            buf[i] = buf[i-cn];
        }
        break;
    case CV_32S:
        {
        int* buf = (int*)_buf;
        for(i = 0; i < cn; i++)
            buf[i] = saturate_cast<int>(s.val[i]);
        for(; i < unroll_to; i++)
            buf[i] = buf[i-cn];
        }
        break;
    case CV_32F:
        {
        float* buf = (float*)_buf;
        for(i = 0; i < cn; i++)
            buf[i] = saturate_cast<float>(s.val[i]);
        for(; i < unroll_to; i++)
            buf[i] = buf[i-cn];
        }
        break;
    case CV_64F:
        {
        double* buf = (double*)_buf;
        for(i = 0; i < cn; i++)
            buf[i] = saturate_cast<double>(s.val[i]);
        for(; i < unroll_to; i++)
            buf[i] = buf[i-cn];
        break;
        }
    default:
        CV_Error(CV_StsUnsupportedFormat,"");
    }
}
1133

1134

1135 1136 1137 1138
/*************************************************************************************************\
                                        Input/Output Array
\*************************************************************************************************/

1139
Mat _InputArray::getMat_(int i) const
1140 1141
{
    int k = kind();
1142
    int accessFlags = flags & ACCESS_MASK;
1143

1144 1145
    if( k == MAT )
    {
V
Vadim Pisarevsky 已提交
1146 1147 1148 1149
        const Mat* m = (const Mat*)obj;
        if( i < 0 )
            return *m;
        return m->row(i);
1150
    }
1151

1152 1153 1154 1155 1156 1157 1158 1159
    if( k == UMAT )
    {
        const UMat* m = (const UMat*)obj;
        if( i < 0 )
            return m->getMat(accessFlags);
        return m->getMat(accessFlags).row(i);
    }

1160 1161 1162 1163 1164
    if( k == EXPR )
    {
        CV_Assert( i < 0 );
        return (Mat)*((const MatExpr*)obj);
    }
1165

1166 1167 1168 1169 1170
    if( k == MATX )
    {
        CV_Assert( i < 0 );
        return Mat(sz, flags, obj);
    }
1171

1172 1173 1174 1175
    if( k == STD_VECTOR )
    {
        CV_Assert( i < 0 );
        int t = CV_MAT_TYPE(flags);
1176
        const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
1177

1178 1179
        return !v.empty() ? Mat(size(), t, (void*)&v[0]) : Mat();
    }
1180

1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
    if( k == STD_BOOL_VECTOR )
    {
        CV_Assert( i < 0 );
        int t = CV_8U;
        const std::vector<bool>& v = *(const std::vector<bool>*)obj;
        int j, n = (int)v.size();
        if( n == 0 )
            return Mat();
        Mat m(1, n, t);
        uchar* dst = m.data;
        for( j = 0; j < n; j++ )
            dst[j] = (uchar)v[j];
        return m;
    }

1196 1197
    if( k == NONE )
        return Mat();
1198

1199 1200 1201
    if( k == STD_VECTOR_VECTOR )
    {
        int t = type(i);
1202
        const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
1203
        CV_Assert( 0 <= i && i < (int)vv.size() );
1204
        const std::vector<uchar>& v = vv[i];
1205

1206 1207
        return !v.empty() ? Mat(size(i), t, (void*)&v[0]) : Mat();
    }
1208

1209
    if( k == STD_VECTOR_MAT )
1210
    {
1211
        const std::vector<Mat>& v = *(const std::vector<Mat>*)obj;
1212
        CV_Assert( 0 <= i && i < (int)v.size() );
1213

1214
        return v[i];
1215
    }
1216

1217 1218 1219 1220 1221 1222 1223 1224
    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
        CV_Assert( 0 <= i && i < (int)v.size() );

        return v[i].getMat(accessFlags);
    }

1225 1226 1227 1228 1229 1230 1231
    if( k == OPENGL_BUFFER )
    {
        CV_Assert( i < 0 );
        CV_Error(cv::Error::StsNotImplemented, "You should explicitly call mapHost/unmapHost methods for ogl::Buffer object");
        return Mat();
    }

1232
    if( k == CUDA_GPU_MAT )
1233 1234
    {
        CV_Assert( i < 0 );
1235
        CV_Error(cv::Error::StsNotImplemented, "You should explicitly call download method for cuda::GpuMat object");
1236 1237 1238
        return Mat();
    }

1239
    if( k == CUDA_HOST_MEM )
1240 1241 1242
    {
        CV_Assert( i < 0 );

1243
        const cuda::HostMem* cuda_mem = (const cuda::HostMem*)obj;
1244 1245 1246

        return cuda_mem->createMatHeader();
    }
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281

    CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
    return Mat();
}

UMat _InputArray::getUMat(int i) const
{
    int k = kind();
    int accessFlags = flags & ACCESS_MASK;

    if( k == UMAT )
    {
        const UMat* m = (const UMat*)obj;
        if( i < 0 )
            return *m;
        return m->row(i);
    }

    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
        CV_Assert( 0 <= i && i < (int)v.size() );

        return v[i];
    }

    if( k == MAT )
    {
        const Mat* m = (const Mat*)obj;
        if( i < 0 )
            return m->getUMat(accessFlags);
        return m->row(i).getUMat(accessFlags);
    }

    return getMat(i).getUMat(accessFlags);
1282
}
1283

1284
void _InputArray::getMatVector(std::vector<Mat>& mv) const
1285 1286
{
    int k = kind();
1287
    int accessFlags = flags & ACCESS_MASK;
1288

1289 1290 1291
    if( k == MAT )
    {
        const Mat& m = *(const Mat*)obj;
1292
        int n = (int)m.size[0];
1293
        mv.resize(n);
1294

1295
        for( int i = 0; i < n; i++ )
1296 1297 1298 1299
            mv[i] = m.dims == 2 ? Mat(1, m.cols, m.type(), (void*)m.ptr(i)) :
                Mat(m.dims-1, &m.size[1], m.type(), (void*)m.ptr(i), &m.step[1]);
        return;
    }
1300

1301 1302 1303
    if( k == EXPR )
    {
        Mat m = *(const MatExpr*)obj;
1304
        int n = m.size[0];
1305
        mv.resize(n);
1306

1307
        for( int i = 0; i < n; i++ )
1308 1309 1310
            mv[i] = m.row(i);
        return;
    }
1311

1312 1313
    if( k == MATX )
    {
1314
        size_t n = sz.height, esz = CV_ELEM_SIZE(flags);
1315
        mv.resize(n);
1316

1317
        for( size_t i = 0; i < n; i++ )
1318 1319 1320
            mv[i] = Mat(1, sz.width, CV_MAT_TYPE(flags), (uchar*)obj + esz*sz.width*i);
        return;
    }
1321

1322 1323
    if( k == STD_VECTOR )
    {
1324
        const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
1325

1326
        size_t n = v.size(), esz = CV_ELEM_SIZE(flags);
1327 1328
        int t = CV_MAT_DEPTH(flags), cn = CV_MAT_CN(flags);
        mv.resize(n);
1329

1330
        for( size_t i = 0; i < n; i++ )
1331 1332 1333
            mv[i] = Mat(1, cn, t, (void*)(&v[0] + esz*i));
        return;
    }
1334

1335 1336 1337 1338 1339
    if( k == NONE )
    {
        mv.clear();
        return;
    }
1340

1341 1342
    if( k == STD_VECTOR_VECTOR )
    {
1343
        const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
1344
        int n = (int)vv.size();
1345 1346
        int t = CV_MAT_TYPE(flags);
        mv.resize(n);
1347

1348
        for( int i = 0; i < n; i++ )
1349
        {
1350
            const std::vector<uchar>& v = vv[i];
1351 1352 1353 1354
            mv[i] = Mat(size(i), t, (void*)&v[0]);
        }
        return;
    }
1355

1356 1357 1358
    if( k == STD_VECTOR_MAT )
    {
        const std::vector<Mat>& v = *(const std::vector<Mat>*)obj;
1359
        size_t n = v.size();
1360 1361
        mv.resize(n);

1362
        for( size_t i = 0; i < n; i++ )
1363 1364 1365 1366
            mv[i] = v[i];
        return;
    }

1367
    if( k == STD_VECTOR_UMAT )
1368
    {
1369
        const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
1370
        size_t n = v.size();
1371
        mv.resize(n);
1372

1373
        for( size_t i = 0; i < n; i++ )
1374
            mv[i] = v[i].getMat(accessFlags);
1375 1376
        return;
    }
1377 1378

    CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
1379
}
1380

K
Konstantin Matskevich 已提交
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
void _InputArray::getUMatVector(std::vector<UMat>& umv) const
{
    int k = kind();
    int accessFlags = flags & ACCESS_MASK;

    if( k == NONE )
    {
        umv.clear();
        return;
    }

    if( k == STD_VECTOR_MAT )
    {
        const std::vector<Mat>& v = *(const std::vector<Mat>*)obj;
1395
        size_t n = v.size();
K
Konstantin Matskevich 已提交
1396 1397
        umv.resize(n);

1398
        for( size_t i = 0; i < n; i++ )
K
Konstantin Matskevich 已提交
1399 1400 1401 1402 1403 1404 1405
            umv[i] = v[i].getUMat(accessFlags);
        return;
    }

    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
1406
        size_t n = v.size();
K
Konstantin Matskevich 已提交
1407 1408
        umv.resize(n);

1409
        for( size_t i = 0; i < n; i++ )
K
Konstantin Matskevich 已提交
1410 1411 1412 1413
            umv[i] = v[i];
        return;
    }

1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428
    if( k == UMAT )
    {
        UMat& v = *(UMat*)obj;
        umv.resize(1);
        umv[0] = v;
        return;
    }
    if( k == MAT )
    {
        Mat& v = *(Mat*)obj;
        umv.resize(1);
        umv[0] = v.getUMat(accessFlags);
        return;
    }

K
Konstantin Matskevich 已提交
1429 1430 1431
    CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
}

1432
cuda::GpuMat _InputArray::getGpuMat() const
1433 1434 1435
{
    int k = kind();

1436
    if (k == CUDA_GPU_MAT)
1437
    {
1438
        const cuda::GpuMat* d_mat = (const cuda::GpuMat*)obj;
1439 1440
        return *d_mat;
    }
1441

1442
    if (k == CUDA_HOST_MEM)
1443
    {
1444
        const cuda::HostMem* cuda_mem = (const cuda::HostMem*)obj;
1445 1446 1447 1448 1449 1450
        return cuda_mem->createGpuMatHeader();
    }

    if (k == OPENGL_BUFFER)
    {
        CV_Error(cv::Error::StsNotImplemented, "You should explicitly call mapDevice/unmapDevice methods for ogl::Buffer object");
1451
        return cuda::GpuMat();
1452 1453
    }

V
Vladislav Vinogradov 已提交
1454
    if (k == NONE)
1455
        return cuda::GpuMat();
V
Vladislav Vinogradov 已提交
1456

1457
    CV_Error(cv::Error::StsNotImplemented, "getGpuMat is available only for cuda::GpuMat and cuda::HostMem");
1458
    return cuda::GpuMat();
1459
}
D
Dan 已提交
1460
void _InputArray::getGpuMatVector(std::vector<cuda::GpuMat>& gpumv) const
1461 1462 1463 1464
{
    int k = kind();
    if (k == STD_VECTOR_CUDA_GPU_MAT)
    {
D
Dan 已提交
1465
        gpumv = *(std::vector<cuda::GpuMat>*)obj;
1466 1467
    }
}
1468
ogl::Buffer _InputArray::getOGlBuffer() const
1469 1470 1471
{
    int k = kind();

1472 1473 1474 1475
    CV_Assert(k == OPENGL_BUFFER);

    const ogl::Buffer* gl_buf = (const ogl::Buffer*)obj;
    return *gl_buf;
1476 1477
}

1478
int _InputArray::kind() const
1479
{
1480
    return flags & KIND_MASK;
1481
}
1482

1483 1484 1485 1486 1487 1488 1489 1490 1491 1492
int _InputArray::rows(int i) const
{
    return size(i).height;
}

int _InputArray::cols(int i) const
{
    return size(i).width;
}

1493
Size _InputArray::size(int i) const
1494 1495
{
    int k = kind();
1496

1497 1498 1499 1500 1501
    if( k == MAT )
    {
        CV_Assert( i < 0 );
        return ((const Mat*)obj)->size();
    }
1502

1503 1504 1505 1506 1507
    if( k == EXPR )
    {
        CV_Assert( i < 0 );
        return ((const MatExpr*)obj)->size();
    }
1508

1509 1510 1511 1512 1513 1514
    if( k == UMAT )
    {
        CV_Assert( i < 0 );
        return ((const UMat*)obj)->size();
    }

1515 1516 1517 1518 1519
    if( k == MATX )
    {
        CV_Assert( i < 0 );
        return sz;
    }
1520

1521 1522 1523
    if( k == STD_VECTOR )
    {
        CV_Assert( i < 0 );
1524 1525
        const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
        const std::vector<int>& iv = *(const std::vector<int>*)obj;
1526 1527 1528
        size_t szb = v.size(), szi = iv.size();
        return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1);
    }
1529

1530 1531 1532 1533 1534 1535 1536
    if( k == STD_BOOL_VECTOR )
    {
        CV_Assert( i < 0 );
        const std::vector<bool>& v = *(const std::vector<bool>*)obj;
        return Size((int)v.size(), 1);
    }

1537 1538
    if( k == NONE )
        return Size();
1539

1540 1541
    if( k == STD_VECTOR_VECTOR )
    {
1542
        const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
1543 1544 1545
        if( i < 0 )
            return vv.empty() ? Size() : Size((int)vv.size(), 1);
        CV_Assert( i < (int)vv.size() );
1546
        const std::vector<std::vector<int> >& ivv = *(const std::vector<std::vector<int> >*)obj;
1547

1548 1549 1550
        size_t szb = vv[i].size(), szi = ivv[i].size();
        return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1);
    }
1551

1552
    if( k == STD_VECTOR_MAT )
1553
    {
1554
        const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1555 1556 1557
        if( i < 0 )
            return vv.empty() ? Size() : Size((int)vv.size(), 1);
        CV_Assert( i < (int)vv.size() );
1558

1559 1560
        return vv[i].size();
    }
1561

1562 1563 1564 1565 1566 1567 1568 1569 1570
    if (k == STD_VECTOR_CUDA_GPU_MAT)
    {
        const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
        if (i < 0)
            return vv.empty() ? Size() : Size((int)vv.size(), 1);
        CV_Assert(i < (int)vv.size());
        return vv[i].size();
    }

1571 1572 1573 1574 1575 1576 1577 1578 1579 1580
    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
        if( i < 0 )
            return vv.empty() ? Size() : Size((int)vv.size(), 1);
        CV_Assert( i < (int)vv.size() );

        return vv[i].size();
    }

1581 1582 1583
    if( k == OPENGL_BUFFER )
    {
        CV_Assert( i < 0 );
1584
        const ogl::Buffer* buf = (const ogl::Buffer*)obj;
1585 1586 1587
        return buf->size();
    }

1588
    if( k == CUDA_GPU_MAT )
1589 1590
    {
        CV_Assert( i < 0 );
1591
        const cuda::GpuMat* d_mat = (const cuda::GpuMat*)obj;
1592 1593
        return d_mat->size();
    }
1594

1595
    if( k == CUDA_HOST_MEM )
1596 1597
    {
        CV_Assert( i < 0 );
1598
        const cuda::HostMem* cuda_mem = (const cuda::HostMem*)obj;
1599 1600
        return cuda_mem->size();
    }
1601 1602 1603

    CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
    return Size();
1604 1605
}

1606
int _InputArray::sizend(int* arrsz, int i) const
1607 1608 1609 1610 1611 1612 1613 1614 1615 1616
{
    int j, d=0, k = kind();

    if( k == NONE )
        ;
    else if( k == MAT )
    {
        CV_Assert( i < 0 );
        const Mat& m = *(const Mat*)obj;
        d = m.dims;
1617
        if(arrsz)
1618
            for(j = 0; j < d; j++)
1619
                arrsz[j] = m.size.p[j];
1620 1621 1622 1623 1624 1625
    }
    else if( k == UMAT )
    {
        CV_Assert( i < 0 );
        const UMat& m = *(const UMat*)obj;
        d = m.dims;
1626
        if(arrsz)
1627
            for(j = 0; j < d; j++)
1628
                arrsz[j] = m.size.p[j];
1629 1630 1631 1632 1633 1634 1635
    }
    else if( k == STD_VECTOR_MAT && i >= 0 )
    {
        const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
        CV_Assert( i < (int)vv.size() );
        const Mat& m = vv[i];
        d = m.dims;
1636
        if(arrsz)
1637
            for(j = 0; j < d; j++)
1638
                arrsz[j] = m.size.p[j];
1639 1640 1641 1642 1643 1644 1645
    }
    else if( k == STD_VECTOR_UMAT && i >= 0 )
    {
        const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
        CV_Assert( i < (int)vv.size() );
        const UMat& m = vv[i];
        d = m.dims;
1646
        if(arrsz)
1647
            for(j = 0; j < d; j++)
1648
                arrsz[j] = m.size.p[j];
1649 1650 1651 1652 1653
    }
    else
    {
        Size sz2d = size(i);
        d = 2;
1654
        if(arrsz)
1655
        {
1656 1657
            arrsz[0] = sz2d.height;
            arrsz[1] = sz2d.width;
1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725
        }
    }

    return d;
}

bool _InputArray::sameSize(const _InputArray& arr) const
{
    int k1 = kind(), k2 = arr.kind();
    Size sz1;

    if( k1 == MAT )
    {
        const Mat* m = ((const Mat*)obj);
        if( k2 == MAT )
            return m->size == ((const Mat*)arr.obj)->size;
        if( k2 == UMAT )
            return m->size == ((const UMat*)arr.obj)->size;
        if( m->dims > 2 )
            return false;
        sz1 = m->size();
    }
    else if( k1 == UMAT )
    {
        const UMat* m = ((const UMat*)obj);
        if( k2 == MAT )
            return m->size == ((const Mat*)arr.obj)->size;
        if( k2 == UMAT )
            return m->size == ((const UMat*)arr.obj)->size;
        if( m->dims > 2 )
            return false;
        sz1 = m->size();
    }
    else
        sz1 = size();
    if( arr.dims() > 2 )
        return false;
    return sz1 == arr.size();
}

int _InputArray::dims(int i) const
{
    int k = kind();

    if( k == MAT )
    {
        CV_Assert( i < 0 );
        return ((const Mat*)obj)->dims;
    }

    if( k == EXPR )
    {
        CV_Assert( i < 0 );
        return ((const MatExpr*)obj)->a.dims;
    }

    if( k == UMAT )
    {
        CV_Assert( i < 0 );
        return ((const UMat*)obj)->dims;
    }

    if( k == MATX )
    {
        CV_Assert( i < 0 );
        return 2;
    }

1726
    if( k == STD_VECTOR || k == STD_BOOL_VECTOR )
1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753
    {
        CV_Assert( i < 0 );
        return 2;
    }

    if( k == NONE )
        return 0;

    if( k == STD_VECTOR_VECTOR )
    {
        const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
        if( i < 0 )
            return 1;
        CV_Assert( i < (int)vv.size() );
        return 2;
    }

    if( k == STD_VECTOR_MAT )
    {
        const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
        if( i < 0 )
            return 1;
        CV_Assert( i < (int)vv.size() );

        return vv[i].dims;
    }

1754 1755 1756 1757 1758 1759 1760 1761 1762 1763
    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
        if( i < 0 )
            return 1;
        CV_Assert( i < (int)vv.size() );

        return vv[i].dims;
    }

1764 1765 1766 1767 1768 1769
    if( k == OPENGL_BUFFER )
    {
        CV_Assert( i < 0 );
        return 2;
    }

1770
    if( k == CUDA_GPU_MAT )
1771 1772 1773 1774
    {
        CV_Assert( i < 0 );
        return 2;
    }
1775

1776
    if( k == CUDA_HOST_MEM )
1777 1778 1779 1780
    {
        CV_Assert( i < 0 );
        return 2;
    }
1781 1782 1783

    CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
    return 0;
1784 1785
}

1786
size_t _InputArray::total(int i) const
1787
{
1788 1789 1790 1791 1792 1793 1794 1795
    int k = kind();

    if( k == MAT )
    {
        CV_Assert( i < 0 );
        return ((const Mat*)obj)->total();
    }

1796 1797 1798 1799 1800 1801
    if( k == UMAT )
    {
        CV_Assert( i < 0 );
        return ((const UMat*)obj)->total();
    }

1802 1803
    if( k == STD_VECTOR_MAT )
    {
1804
        const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1805 1806 1807 1808 1809 1810 1811
        if( i < 0 )
            return vv.size();

        CV_Assert( i < (int)vv.size() );
        return vv[i].total();
    }

1812

1813 1814 1815 1816 1817 1818 1819 1820 1821 1822
    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
        if( i < 0 )
            return vv.size();

        CV_Assert( i < (int)vv.size() );
        return vv[i].total();
    }

1823 1824
    return size(i).area();
}
1825

1826
int _InputArray::type(int i) const
1827 1828
{
    int k = kind();
1829

1830 1831
    if( k == MAT )
        return ((const Mat*)obj)->type();
1832

1833 1834 1835
    if( k == UMAT )
        return ((const UMat*)obj)->type();

1836 1837
    if( k == EXPR )
        return ((const MatExpr*)obj)->type();
1838

1839
    if( k == MATX || k == STD_VECTOR || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
V
Vadim Pisarevsky 已提交
1840 1841
        return CV_MAT_TYPE(flags);

1842 1843
    if( k == NONE )
        return -1;
1844

1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856
    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
        if( vv.empty() )
        {
            CV_Assert((flags & FIXED_TYPE) != 0);
            return CV_MAT_TYPE(flags);
        }
        CV_Assert( i < (int)vv.size() );
        return vv[i >= 0 ? i : 0].type();
    }

1857
    if( k == STD_VECTOR_MAT )
1858
    {
1859
        const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
V
Vadim Pisarevsky 已提交
1860 1861 1862 1863 1864
        if( vv.empty() )
        {
            CV_Assert((flags & FIXED_TYPE) != 0);
            return CV_MAT_TYPE(flags);
        }
1865 1866 1867
        CV_Assert( i < (int)vv.size() );
        return vv[i >= 0 ? i : 0].type();
    }
1868

1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880
    if (k == STD_VECTOR_CUDA_GPU_MAT)
    {
        const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
        if (vv.empty())
        {
            CV_Assert((flags & FIXED_TYPE) != 0);
            return CV_MAT_TYPE(flags);
        }
        CV_Assert(i < (int)vv.size());
        return vv[i >= 0 ? i : 0].type();
    }

1881
    if( k == OPENGL_BUFFER )
1882
        return ((const ogl::Buffer*)obj)->type();
1883

1884
    if( k == CUDA_GPU_MAT )
1885
        return ((const cuda::GpuMat*)obj)->type();
1886

1887
    if( k == CUDA_HOST_MEM )
1888
        return ((const cuda::HostMem*)obj)->type();
1889 1890 1891

    CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
    return 0;
1892
}
1893

1894
int _InputArray::depth(int i) const
1895 1896 1897
{
    return CV_MAT_DEPTH(type(i));
}
1898

1899
int _InputArray::channels(int i) const
1900 1901 1902
{
    return CV_MAT_CN(type(i));
}
1903

1904
bool _InputArray::empty() const
1905 1906
{
    int k = kind();
1907

1908 1909
    if( k == MAT )
        return ((const Mat*)obj)->empty();
1910

1911 1912 1913
    if( k == UMAT )
        return ((const UMat*)obj)->empty();

1914 1915
    if( k == EXPR )
        return false;
1916

1917 1918
    if( k == MATX )
        return false;
1919

1920 1921
    if( k == STD_VECTOR )
    {
1922
        const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
1923 1924
        return v.empty();
    }
1925

1926 1927 1928 1929 1930 1931
    if( k == STD_BOOL_VECTOR )
    {
        const std::vector<bool>& v = *(const std::vector<bool>*)obj;
        return v.empty();
    }

1932 1933
    if( k == NONE )
        return true;
1934

1935 1936
    if( k == STD_VECTOR_VECTOR )
    {
1937
        const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
1938 1939
        return vv.empty();
    }
1940

1941
    if( k == STD_VECTOR_MAT )
1942
    {
1943
        const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1944 1945
        return vv.empty();
    }
1946

1947 1948 1949 1950 1951 1952
    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
        return vv.empty();
    }

1953
    if( k == OPENGL_BUFFER )
1954
        return ((const ogl::Buffer*)obj)->empty();
1955

1956
    if( k == CUDA_GPU_MAT )
1957
        return ((const cuda::GpuMat*)obj)->empty();
1958

1959 1960 1961 1962 1963 1964
    if (k == STD_VECTOR_CUDA_GPU_MAT)
    {
        const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
        return vv.empty();
    }

1965
    if( k == CUDA_HOST_MEM )
1966
        return ((const cuda::HostMem*)obj)->empty();
1967 1968 1969

    CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
    return true;
1970
}
1971

1972 1973 1974 1975 1976 1977 1978 1979 1980 1981
bool _InputArray::isContinuous(int i) const
{
    int k = kind();

    if( k == MAT )
        return i < 0 ? ((const Mat*)obj)->isContinuous() : true;

    if( k == UMAT )
        return i < 0 ? ((const UMat*)obj)->isContinuous() : true;

1982 1983
    if( k == EXPR || k == MATX || k == STD_VECTOR ||
        k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999
        return true;

    if( k == STD_VECTOR_MAT )
    {
        const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
        CV_Assert((size_t)i < vv.size());
        return vv[i].isContinuous();
    }

    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
        CV_Assert((size_t)i < vv.size());
        return vv[i].isContinuous();
    }

2000 2001 2002
    if( k == CUDA_GPU_MAT )
      return i < 0 ? ((const cuda::GpuMat*)obj)->isContinuous() : true;

2003
    CV_Error(CV_StsNotImplemented, "Unknown/unsupported array type");
2004 2005 2006
    return false;
}

I
Ilya Lavrenov 已提交
2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
bool _InputArray::isSubmatrix(int i) const
{
    int k = kind();

    if( k == MAT )
        return i < 0 ? ((const Mat*)obj)->isSubmatrix() : false;

    if( k == UMAT )
        return i < 0 ? ((const UMat*)obj)->isSubmatrix() : false;

2017 2018
    if( k == EXPR || k == MATX || k == STD_VECTOR ||
        k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
I
Ilya Lavrenov 已提交
2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038
        return false;

    if( k == STD_VECTOR_MAT )
    {
        const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
        CV_Assert((size_t)i < vv.size());
        return vv[i].isSubmatrix();
    }

    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
        CV_Assert((size_t)i < vv.size());
        return vv[i].isSubmatrix();
    }

    CV_Error(CV_StsNotImplemented, "");
    return false;
}

I
Ilya Lavrenov 已提交
2039 2040 2041 2042 2043 2044 2045 2046
size_t _InputArray::offset(int i) const
{
    int k = kind();

    if( k == MAT )
    {
        CV_Assert( i < 0 );
        const Mat * const m = ((const Mat*)obj);
2047
        return (size_t)(m->ptr() - m->datastart);
I
Ilya Lavrenov 已提交
2048 2049 2050 2051 2052 2053 2054 2055
    }

    if( k == UMAT )
    {
        CV_Assert( i < 0 );
        return ((const UMat*)obj)->offset;
    }

2056 2057
    if( k == EXPR || k == MATX || k == STD_VECTOR ||
        k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
I
Ilya Lavrenov 已提交
2058 2059 2060 2061 2062 2063 2064 2065 2066
        return 0;

    if( k == STD_VECTOR_MAT )
    {
        const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
        if( i < 0 )
            return 1;
        CV_Assert( i < (int)vv.size() );

2067
        return (size_t)(vv[i].ptr() - vv[i].datastart);
I
Ilya Lavrenov 已提交
2068 2069
    }

I
Ilya Lavrenov 已提交
2070 2071 2072 2073 2074 2075 2076
    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
        CV_Assert((size_t)i < vv.size());
        return vv[i].offset;
    }

2077
    if( k == CUDA_GPU_MAT )
I
Ilya Lavrenov 已提交
2078 2079 2080 2081 2082 2083
    {
        CV_Assert( i < 0 );
        const cuda::GpuMat * const m = ((const cuda::GpuMat*)obj);
        return (size_t)(m->data - m->datastart);
    }

2084 2085 2086 2087 2088 2089 2090
    if (k == STD_VECTOR_CUDA_GPU_MAT)
    {
        const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
        CV_Assert((size_t)i < vv.size());
        return (size_t)(vv[i].data - vv[i].datastart);
    }

I
Ilya Lavrenov 已提交
2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110
    CV_Error(Error::StsNotImplemented, "");
    return 0;
}

size_t _InputArray::step(int i) const
{
    int k = kind();

    if( k == MAT )
    {
        CV_Assert( i < 0 );
        return ((const Mat*)obj)->step;
    }

    if( k == UMAT )
    {
        CV_Assert( i < 0 );
        return ((const UMat*)obj)->step;
    }

2111 2112
    if( k == EXPR || k == MATX || k == STD_VECTOR ||
        k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
I
Ilya Lavrenov 已提交
2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123
        return 0;

    if( k == STD_VECTOR_MAT )
    {
        const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
        if( i < 0 )
            return 1;
        CV_Assert( i < (int)vv.size() );
        return vv[i].step;
    }

I
Ilya Lavrenov 已提交
2124 2125 2126 2127 2128 2129 2130
    if( k == STD_VECTOR_UMAT )
    {
        const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
        CV_Assert((size_t)i < vv.size());
        return vv[i].step;
    }

2131
    if( k == CUDA_GPU_MAT )
I
Ilya Lavrenov 已提交
2132 2133 2134 2135
    {
        CV_Assert( i < 0 );
        return ((const cuda::GpuMat*)obj)->step;
    }
2136 2137 2138 2139 2140 2141
    if (k == STD_VECTOR_CUDA_GPU_MAT)
    {
        const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
        CV_Assert((size_t)i < vv.size());
        return vv[i].step;
    }
I
Ilya Lavrenov 已提交
2142 2143 2144 2145 2146

    CV_Error(Error::StsNotImplemented, "");
    return 0;
}

2147 2148 2149 2150 2151 2152
void _InputArray::copyTo(const _OutputArray& arr) const
{
    int k = kind();

    if( k == NONE )
        arr.release();
2153
    else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_BOOL_VECTOR )
2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170
    {
        Mat m = getMat();
        m.copyTo(arr);
    }
    else if( k == EXPR )
    {
        const MatExpr& e = *((MatExpr*)obj);
        if( arr.kind() == MAT )
            arr.getMatRef() = e;
        else
            Mat(e).copyTo(arr);
    }
    else if( k == UMAT )
        ((UMat*)obj)->copyTo(arr);
    else
        CV_Error(Error::StsNotImplemented, "");
}
2171

2172 2173 2174 2175 2176 2177
void _InputArray::copyTo(const _OutputArray& arr, const _InputArray & mask) const
{
    int k = kind();

    if( k == NONE )
        arr.release();
2178
    else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_BOOL_VECTOR )
2179 2180 2181 2182 2183 2184 2185 2186 2187 2188
    {
        Mat m = getMat();
        m.copyTo(arr, mask);
    }
    else if( k == UMAT )
        ((UMat*)obj)->copyTo(arr, mask);
    else
        CV_Error(Error::StsNotImplemented, "");
}

2189
bool _OutputArray::fixedSize() const
2190
{
2191
    return (flags & FIXED_SIZE) == FIXED_SIZE;
2192 2193
}

2194
bool _OutputArray::fixedType() const
2195
{
2196
    return (flags & FIXED_TYPE) == FIXED_TYPE;
2197
}
2198

A
Andrey Kamaev 已提交
2199
void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, int fixedDepthMask) const
2200 2201 2202 2203
{
    int k = kind();
    if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
    {
2204
        CV_Assert(!fixedSize() || ((Mat*)obj)->size.operator()() == _sz);
A
Andrey Kamaev 已提交
2205 2206
        CV_Assert(!fixedType() || ((Mat*)obj)->type() == mtype);
        ((Mat*)obj)->create(_sz, mtype);
2207 2208
        return;
    }
2209 2210 2211 2212 2213 2214 2215
    if( k == UMAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
    {
        CV_Assert(!fixedSize() || ((UMat*)obj)->size.operator()() == _sz);
        CV_Assert(!fixedType() || ((UMat*)obj)->type() == mtype);
        ((UMat*)obj)->create(_sz, mtype);
        return;
    }
2216
    if( k == CUDA_GPU_MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2217
    {
2218 2219 2220
        CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == _sz);
        CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype);
        ((cuda::GpuMat*)obj)->create(_sz, mtype);
2221 2222
        return;
    }
2223 2224
    if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
    {
2225 2226 2227
        CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == _sz);
        CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype);
        ((ogl::Buffer*)obj)->create(_sz, mtype);
2228 2229
        return;
    }
2230
    if( k == CUDA_HOST_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2231
    {
2232 2233 2234
        CV_Assert(!fixedSize() || ((cuda::HostMem*)obj)->size() == _sz);
        CV_Assert(!fixedType() || ((cuda::HostMem*)obj)->type() == mtype);
        ((cuda::HostMem*)obj)->create(_sz, mtype);
2235 2236
        return;
    }
A
Andrey Kamaev 已提交
2237 2238
    int sizes[] = {_sz.height, _sz.width};
    create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
2239 2240
}

2241
void _OutputArray::create(int _rows, int _cols, int mtype, int i, bool allowTransposed, int fixedDepthMask) const
2242 2243 2244 2245
{
    int k = kind();
    if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
    {
2246
        CV_Assert(!fixedSize() || ((Mat*)obj)->size.operator()() == Size(_cols, _rows));
A
Andrey Kamaev 已提交
2247
        CV_Assert(!fixedType() || ((Mat*)obj)->type() == mtype);
2248
        ((Mat*)obj)->create(_rows, _cols, mtype);
2249 2250
        return;
    }
2251 2252
    if( k == UMAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
    {
2253
        CV_Assert(!fixedSize() || ((UMat*)obj)->size.operator()() == Size(_cols, _rows));
2254
        CV_Assert(!fixedType() || ((UMat*)obj)->type() == mtype);
2255
        ((UMat*)obj)->create(_rows, _cols, mtype);
2256 2257
        return;
    }
2258
    if( k == CUDA_GPU_MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2259
    {
2260
        CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == Size(_cols, _rows));
2261
        CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype);
2262
        ((cuda::GpuMat*)obj)->create(_rows, _cols, mtype);
2263 2264
        return;
    }
2265 2266
    if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
    {
2267
        CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == Size(_cols, _rows));
2268
        CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype);
2269
        ((ogl::Buffer*)obj)->create(_rows, _cols, mtype);
2270 2271
        return;
    }
2272
    if( k == CUDA_HOST_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2273
    {
2274 2275 2276
        CV_Assert(!fixedSize() || ((cuda::HostMem*)obj)->size() == Size(_cols, _rows));
        CV_Assert(!fixedType() || ((cuda::HostMem*)obj)->type() == mtype);
        ((cuda::HostMem*)obj)->create(_rows, _cols, mtype);
2277 2278
        return;
    }
2279
    int sizes[] = {_rows, _cols};
A
Andrey Kamaev 已提交
2280
    create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
2281
}
2282

2283
void _OutputArray::create(int d, const int* sizes, int mtype, int i,
2284
                          bool allowTransposed, int fixedDepthMask) const
2285 2286
{
    int k = kind();
A
Andrey Kamaev 已提交
2287
    mtype = CV_MAT_TYPE(mtype);
2288

2289 2290 2291 2292
    if( k == MAT )
    {
        CV_Assert( i < 0 );
        Mat& m = *(Mat*)obj;
2293
        if( allowTransposed )
2294 2295
        {
            if( !m.isContinuous() )
2296 2297
            {
                CV_Assert(!fixedType() && !fixedSize());
2298
                m.release();
2299
            }
2300

2301
            if( d == 2 && m.dims == 2 && m.data &&
A
Andrey Kamaev 已提交
2302
                m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
2303 2304
                return;
        }
2305 2306 2307

        if(fixedType())
        {
A
Andrey Kamaev 已提交
2308 2309
            if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
                mtype = m.type();
2310
            else
A
Andrey Kamaev 已提交
2311
                CV_Assert(CV_MAT_TYPE(mtype) == m.type());
2312 2313 2314
        }
        if(fixedSize())
        {
2315 2316
            CV_Assert(m.dims == d);
            for(int j = 0; j < d; ++j)
A
Andrey Kamaev 已提交
2317
                CV_Assert(m.size[j] == sizes[j]);
2318
        }
2319
        m.create(d, sizes, mtype);
2320 2321
        return;
    }
2322

2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334
    if( k == UMAT )
    {
        CV_Assert( i < 0 );
        UMat& m = *(UMat*)obj;
        if( allowTransposed )
        {
            if( !m.isContinuous() )
            {
                CV_Assert(!fixedType() && !fixedSize());
                m.release();
            }

2335
            if( d == 2 && m.dims == 2 && !m.empty() &&
2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348
                m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
                return;
        }

        if(fixedType())
        {
            if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
                mtype = m.type();
            else
                CV_Assert(CV_MAT_TYPE(mtype) == m.type());
        }
        if(fixedSize())
        {
2349 2350
            CV_Assert(m.dims == d);
            for(int j = 0; j < d; ++j)
2351 2352
                CV_Assert(m.size[j] == sizes[j]);
        }
2353
        m.create(d, sizes, mtype);
2354 2355 2356
        return;
    }

2357 2358 2359 2360
    if( k == MATX )
    {
        CV_Assert( i < 0 );
        int type0 = CV_MAT_TYPE(flags);
A
Andrey Kamaev 已提交
2361
        CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == 1 && ((1 << type0) & fixedDepthMask) != 0) );
2362
        CV_Assert( d == 2 && ((sizes[0] == sz.height && sizes[1] == sz.width) ||
A
Andrey Kamaev 已提交
2363
                                 (allowTransposed && sizes[0] == sz.width && sizes[1] == sz.height)));
2364 2365
        return;
    }
2366

2367 2368
    if( k == STD_VECTOR || k == STD_VECTOR_VECTOR )
    {
2369
        CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) );
A
Andrey Kamaev 已提交
2370
        size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0;
2371
        std::vector<uchar>* v = (std::vector<uchar>*)obj;
2372

2373 2374
        if( k == STD_VECTOR_VECTOR )
        {
2375
            std::vector<std::vector<uchar> >& vv = *(std::vector<std::vector<uchar> >*)obj;
2376 2377
            if( i < 0 )
            {
2378
                CV_Assert(!fixedSize() || len == vv.size());
2379 2380 2381 2382 2383 2384 2385 2386
                vv.resize(len);
                return;
            }
            CV_Assert( i < (int)vv.size() );
            v = &vv[i];
        }
        else
            CV_Assert( i < 0 );
2387

2388
        int type0 = CV_MAT_TYPE(flags);
A
Andrey Kamaev 已提交
2389
        CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) );
2390

2391
        int esz = CV_ELEM_SIZE(type0);
2392
        CV_Assert(!fixedSize() || len == ((std::vector<uchar>*)v)->size() / esz);
2393 2394 2395
        switch( esz )
        {
        case 1:
2396
            ((std::vector<uchar>*)v)->resize(len);
2397 2398
            break;
        case 2:
2399
            ((std::vector<Vec2b>*)v)->resize(len);
2400 2401
            break;
        case 3:
2402
            ((std::vector<Vec3b>*)v)->resize(len);
2403 2404
            break;
        case 4:
2405
            ((std::vector<int>*)v)->resize(len);
2406 2407
            break;
        case 6:
2408
            ((std::vector<Vec3s>*)v)->resize(len);
2409 2410
            break;
        case 8:
2411
            ((std::vector<Vec2i>*)v)->resize(len);
2412 2413
            break;
        case 12:
2414
            ((std::vector<Vec3i>*)v)->resize(len);
2415 2416
            break;
        case 16:
2417
            ((std::vector<Vec4i>*)v)->resize(len);
2418 2419
            break;
        case 24:
2420
            ((std::vector<Vec6i>*)v)->resize(len);
2421 2422
            break;
        case 32:
2423
            ((std::vector<Vec8i>*)v)->resize(len);
2424 2425
            break;
        case 36:
2426
            ((std::vector<Vec<int, 9> >*)v)->resize(len);
2427 2428
            break;
        case 48:
2429
            ((std::vector<Vec<int, 12> >*)v)->resize(len);
2430 2431
            break;
        case 64:
2432
            ((std::vector<Vec<int, 16> >*)v)->resize(len);
2433 2434
            break;
        case 128:
2435
            ((std::vector<Vec<int, 32> >*)v)->resize(len);
2436 2437
            break;
        case 256:
2438
            ((std::vector<Vec<int, 64> >*)v)->resize(len);
2439 2440
            break;
        case 512:
2441
            ((std::vector<Vec<int, 128> >*)v)->resize(len);
2442 2443 2444 2445 2446 2447
            break;
        default:
            CV_Error_(CV_StsBadArg, ("Vectors with element size %d are not supported. Please, modify OutputArray::create()\n", esz));
        }
        return;
    }
2448

2449 2450
    if( k == NONE )
    {
2451
        CV_Error(CV_StsNullPtr, "create() called for the missing output array" );
2452 2453
        return;
    }
2454

2455
    if( k == STD_VECTOR_MAT )
2456
    {
2457
        std::vector<Mat>& v = *(std::vector<Mat>*)obj;
2458

2459 2460
        if( i < 0 )
        {
2461
            CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) );
A
Andrey Kamaev 已提交
2462
            size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0, len0 = v.size();
2463

2464
            CV_Assert(!fixedSize() || len == len0);
2465
            v.resize(len);
2466 2467
            if( fixedType() )
            {
A
Andrey Kamaev 已提交
2468
                int _type = CV_MAT_TYPE(flags);
2469 2470
                for( size_t j = len0; j < len; j++ )
                {
2471
                    if( v[j].type() == _type )
2472
                        continue;
2473 2474
                    CV_Assert( v[j].empty() );
                    v[j].flags = (v[j].flags & ~CV_MAT_TYPE_MASK) | _type;
2475 2476
                }
            }
2477 2478
            return;
        }
2479

2480 2481
        CV_Assert( i < (int)v.size() );
        Mat& m = v[i];
2482

2483
        if( allowTransposed )
2484 2485
        {
            if( !m.isContinuous() )
2486 2487
            {
                CV_Assert(!fixedType() && !fixedSize());
2488
                m.release();
2489
            }
2490

2491
            if( d == 2 && m.dims == 2 && m.data &&
A
Andrey Kamaev 已提交
2492
                m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
2493 2494
                return;
        }
2495 2496 2497

        if(fixedType())
        {
A
Andrey Kamaev 已提交
2498 2499
            if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
                mtype = m.type();
2500
            else
I
Ilya Lavrenov 已提交
2501
                CV_Assert(CV_MAT_TYPE(mtype) == m.type());
2502 2503 2504
        }
        if(fixedSize())
        {
2505 2506
            CV_Assert(m.dims == d);
            for(int j = 0; j < d; ++j)
A
Andrey Kamaev 已提交
2507
                CV_Assert(m.size[j] == sizes[j]);
2508 2509
        }

2510
        m.create(d, sizes, mtype);
2511
        return;
2512
    }
2513

2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559
    if( k == STD_VECTOR_UMAT )
    {
        std::vector<UMat>& v = *(std::vector<UMat>*)obj;

        if( i < 0 )
        {
            CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) );
            size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0, len0 = v.size();

            CV_Assert(!fixedSize() || len == len0);
            v.resize(len);
            if( fixedType() )
            {
                int _type = CV_MAT_TYPE(flags);
                for( size_t j = len0; j < len; j++ )
                {
                    if( v[j].type() == _type )
                        continue;
                    CV_Assert( v[j].empty() );
                    v[j].flags = (v[j].flags & ~CV_MAT_TYPE_MASK) | _type;
                }
            }
            return;
        }

        CV_Assert( i < (int)v.size() );
        UMat& m = v[i];

        if( allowTransposed )
        {
            if( !m.isContinuous() )
            {
                CV_Assert(!fixedType() && !fixedSize());
                m.release();
            }

            if( d == 2 && m.dims == 2 && m.u &&
                m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
                return;
        }

        if(fixedType())
        {
            if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
                mtype = m.type();
            else
I
Ilya Lavrenov 已提交
2560
                CV_Assert(CV_MAT_TYPE(mtype) == m.type());
2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572
        }
        if(fixedSize())
        {
            CV_Assert(m.dims == d);
            for(int j = 0; j < d; ++j)
                CV_Assert(m.size[j] == sizes[j]);
        }

        m.create(d, sizes, mtype);
        return;
    }

2573
    CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
2574
}
2575

2576 2577
void _OutputArray::createSameSize(const _InputArray& arr, int mtype) const
{
2578 2579
    int arrsz[CV_MAX_DIM], d = arr.sizend(arrsz);
    create(d, arrsz, mtype);
2580 2581
}

2582
void _OutputArray::release() const
2583
{
2584 2585
    CV_Assert(!fixedSize());

2586
    int k = kind();
2587

2588 2589 2590 2591 2592
    if( k == MAT )
    {
        ((Mat*)obj)->release();
        return;
    }
2593

2594 2595 2596 2597 2598 2599
    if( k == UMAT )
    {
        ((UMat*)obj)->release();
        return;
    }

2600
    if( k == CUDA_GPU_MAT )
2601
    {
2602
        ((cuda::GpuMat*)obj)->release();
2603 2604 2605
        return;
    }

2606
    if( k == CUDA_HOST_MEM )
2607
    {
2608
        ((cuda::HostMem*)obj)->release();
2609 2610 2611
        return;
    }

2612 2613
    if( k == OPENGL_BUFFER )
    {
2614
        ((ogl::Buffer*)obj)->release();
2615 2616 2617
        return;
    }

2618 2619
    if( k == NONE )
        return;
2620

2621 2622 2623 2624 2625
    if( k == STD_VECTOR )
    {
        create(Size(), CV_MAT_TYPE(flags));
        return;
    }
2626

2627 2628
    if( k == STD_VECTOR_VECTOR )
    {
2629
        ((std::vector<std::vector<uchar> >*)obj)->clear();
2630 2631
        return;
    }
2632

2633
    if( k == STD_VECTOR_MAT )
2634
    {
2635
        ((std::vector<Mat>*)obj)->clear();
2636
        return;
2637
    }
2638

2639 2640 2641 2642 2643
    if( k == STD_VECTOR_UMAT )
    {
        ((std::vector<UMat>*)obj)->clear();
        return;
    }
2644 2645 2646 2647 2648
    if (k == STD_VECTOR_CUDA_GPU_MAT)
    {
        ((std::vector<cuda::GpuMat>*)obj)->clear();
        return;
    }
2649
    CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
2650 2651
}

2652
void _OutputArray::clear() const
2653 2654
{
    int k = kind();
2655

2656 2657
    if( k == MAT )
    {
2658
        CV_Assert(!fixedSize());
2659 2660 2661
        ((Mat*)obj)->resize(0);
        return;
    }
2662

2663 2664
    release();
}
2665

2666
bool _OutputArray::needed() const
2667 2668 2669 2670
{
    return kind() != NONE;
}

2671
Mat& _OutputArray::getMatRef(int i) const
2672 2673 2674 2675 2676 2677 2678 2679 2680 2681
{
    int k = kind();
    if( i < 0 )
    {
        CV_Assert( k == MAT );
        return *(Mat*)obj;
    }
    else
    {
        CV_Assert( k == STD_VECTOR_MAT );
2682
        std::vector<Mat>& v = *(std::vector<Mat>*)obj;
2683 2684 2685 2686
        CV_Assert( i < (int)v.size() );
        return v[i];
    }
}
2687

2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704
UMat& _OutputArray::getUMatRef(int i) const
{
    int k = kind();
    if( i < 0 )
    {
        CV_Assert( k == UMAT );
        return *(UMat*)obj;
    }
    else
    {
        CV_Assert( k == STD_VECTOR_UMAT );
        std::vector<UMat>& v = *(std::vector<UMat>*)obj;
        CV_Assert( i < (int)v.size() );
        return v[i];
    }
}

2705
cuda::GpuMat& _OutputArray::getGpuMatRef() const
2706 2707
{
    int k = kind();
2708
    CV_Assert( k == CUDA_GPU_MAT );
2709
    return *(cuda::GpuMat*)obj;
2710
}
2711 2712 2713 2714 2715 2716
std::vector<cuda::GpuMat>& _OutputArray::getGpuMatVecRef() const
{
    int k = kind();
    CV_Assert(k == STD_VECTOR_CUDA_GPU_MAT);
    return *(std::vector<cuda::GpuMat>*)obj;
}
2717

2718
ogl::Buffer& _OutputArray::getOGlBufferRef() const
2719 2720 2721
{
    int k = kind();
    CV_Assert( k == OPENGL_BUFFER );
2722
    return *(ogl::Buffer*)obj;
2723 2724
}

2725
cuda::HostMem& _OutputArray::getHostMemRef() const
2726 2727
{
    int k = kind();
2728 2729
    CV_Assert( k == CUDA_HOST_MEM );
    return *(cuda::HostMem*)obj;
2730 2731
}

I
Ilya Lavrenov 已提交
2732
void _OutputArray::setTo(const _InputArray& arr, const _InputArray & mask) const
2733 2734 2735 2736 2737 2738 2739 2740
{
    int k = kind();

    if( k == NONE )
        ;
    else if( k == MAT || k == MATX || k == STD_VECTOR )
    {
        Mat m = getMat();
I
Ilya Lavrenov 已提交
2741
        m.setTo(arr, mask);
2742 2743
    }
    else if( k == UMAT )
I
Ilya Lavrenov 已提交
2744
        ((UMat*)obj)->setTo(arr, mask);
2745
    else if( k == CUDA_GPU_MAT )
I
Ilya Lavrenov 已提交
2746 2747
    {
        Mat value = arr.getMat();
2748
        CV_Assert( checkScalar(value, type(), arr.kind(), _InputArray::CUDA_GPU_MAT) );
2749
        ((cuda::GpuMat*)obj)->setTo(Scalar(Vec<double, 4>(value.ptr<double>())), mask);
I
Ilya Lavrenov 已提交
2750
    }
2751 2752 2753 2754
    else
        CV_Error(Error::StsNotImplemented, "");
}

2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766

void _OutputArray::assign(const UMat& u) const
{
    int k = kind();
    if (k == UMAT)
    {
        *(UMat*)obj = u;
    }
    else if (k == MAT)
    {
        u.copyTo(*(Mat*)obj); // TODO check u.getMat()
    }
2767 2768 2769 2770
    else if (k == MATX)
    {
        u.copyTo(getMat()); // TODO check u.getMat()
    }
2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788
    else
    {
        CV_Error(Error::StsNotImplemented, "");
    }
}


void _OutputArray::assign(const Mat& m) const
{
    int k = kind();
    if (k == UMAT)
    {
        m.copyTo(*(UMat*)obj); // TODO check m.getUMat()
    }
    else if (k == MAT)
    {
        *(Mat*)obj = m;
    }
2789 2790
    else if (k == MATX)
    {
2791
        m.copyTo(getMat());
2792
    }
2793 2794 2795 2796 2797 2798 2799
    else
    {
        CV_Error(Error::StsNotImplemented, "");
    }
}


2800 2801
static _InputOutputArray _none;
InputOutputArray noArray() { return _none; }
2802

2803 2804
}

2805 2806 2807
/*************************************************************************************************\
                                        Matrix Operations
\*************************************************************************************************/
2808

2809
void cv::hconcat(const Mat* src, size_t nsrc, OutputArray _dst)
2810
{
2811 2812
    CV_INSTRUMENT_REGION()

2813 2814
    if( nsrc == 0 || !src )
    {
2815
        _dst.release();
2816 2817
        return;
    }
2818

2819
    int totalCols = 0, cols = 0;
2820
    for( size_t i = 0; i < nsrc; i++ )
2821
    {
2822
        CV_Assert( src[i].dims <= 2 &&
2823 2824 2825 2826
                   src[i].rows == src[0].rows &&
                   src[i].type() == src[0].type());
        totalCols += src[i].cols;
    }
2827 2828
    _dst.create( src[0].rows, totalCols, src[0].type());
    Mat dst = _dst.getMat();
2829
    for( size_t i = 0; i < nsrc; i++ )
2830
    {
2831
        Mat dpart = dst(Rect(cols, 0, src[i].cols, src[i].rows));
2832 2833 2834 2835
        src[i].copyTo(dpart);
        cols += src[i].cols;
    }
}
2836

2837
void cv::hconcat(InputArray src1, InputArray src2, OutputArray dst)
2838
{
2839 2840
    CV_INSTRUMENT_REGION()

2841
    Mat src[] = {src1.getMat(), src2.getMat()};
2842 2843
    hconcat(src, 2, dst);
}
2844

2845
void cv::hconcat(InputArray _src, OutputArray dst)
2846
{
2847 2848
    CV_INSTRUMENT_REGION()

2849
    std::vector<Mat> src;
2850
    _src.getMatVector(src);
2851 2852 2853
    hconcat(!src.empty() ? &src[0] : 0, src.size(), dst);
}

2854
void cv::vconcat(const Mat* src, size_t nsrc, OutputArray _dst)
2855
{
2856 2857
    CV_INSTRUMENT_REGION()

2858 2859
    if( nsrc == 0 || !src )
    {
2860
        _dst.release();
2861 2862
        return;
    }
2863

2864
    int totalRows = 0, rows = 0;
2865
    for( size_t i = 0; i < nsrc; i++ )
2866
    {
2867
        CV_Assert(src[i].dims <= 2 &&
2868 2869 2870 2871
                  src[i].cols == src[0].cols &&
                  src[i].type() == src[0].type());
        totalRows += src[i].rows;
    }
2872 2873
    _dst.create( totalRows, src[0].cols, src[0].type());
    Mat dst = _dst.getMat();
2874
    for( size_t i = 0; i < nsrc; i++ )
2875 2876 2877 2878 2879 2880
    {
        Mat dpart(dst, Rect(0, rows, src[i].cols, src[i].rows));
        src[i].copyTo(dpart);
        rows += src[i].rows;
    }
}
2881

2882
void cv::vconcat(InputArray src1, InputArray src2, OutputArray dst)
2883
{
2884 2885
    CV_INSTRUMENT_REGION()

2886
    Mat src[] = {src1.getMat(), src2.getMat()};
2887
    vconcat(src, 2, dst);
2888
}
2889

2890
void cv::vconcat(InputArray _src, OutputArray dst)
2891
{
2892 2893
    CV_INSTRUMENT_REGION()

2894
    std::vector<Mat> src;
2895
    _src.getMatVector(src);
2896 2897
    vconcat(!src.empty() ? &src[0] : 0, src.size(), dst);
}
2898

2899
//////////////////////////////////////// set identity ////////////////////////////////////////////
I
Ilya Lavrenov 已提交
2900

I
Ilya Lavrenov 已提交
2901 2902
#ifdef HAVE_OPENCL

I
Ilya Lavrenov 已提交
2903 2904 2905 2906
namespace cv {

static bool ocl_setIdentity( InputOutputArray _m, const Scalar& s )
{
2907 2908 2909
    int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), kercn = cn, rowsPerWI = 1;
    int sctype = CV_MAKE_TYPE(depth, cn == 3 ? 4 : cn);
    if (ocl::Device::getDefault().isIntel())
I
Ilya Lavrenov 已提交
2910
    {
2911 2912 2913 2914 2915 2916 2917
        rowsPerWI = 4;
        if (cn == 1)
        {
            kercn = std::min(ocl::predictOptimalVectorWidth(_m), 4);
            if (kercn != 4)
                kercn = 1;
        }
I
Ilya Lavrenov 已提交
2918
    }
I
Ilya Lavrenov 已提交
2919 2920

    ocl::Kernel k("setIdentity", ocl::core::set_identity_oclsrc,
I
Ilya Lavrenov 已提交
2921 2922 2923 2924 2925
                  format("-D T=%s -D T1=%s -D cn=%d -D ST=%s -D kercn=%d -D rowsPerWI=%d",
                         ocl::memopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
                         ocl::memopTypeToStr(depth), cn,
                         ocl::memopTypeToStr(sctype),
                         kercn, rowsPerWI));
I
Ilya Lavrenov 已提交
2926 2927 2928 2929
    if (k.empty())
        return false;

    UMat m = _m.getUMat();
I
Ilya Lavrenov 已提交
2930 2931
    k.args(ocl::KernelArg::WriteOnly(m, cn, kercn),
           ocl::KernelArg::Constant(Mat(1, 1, sctype, s)));
I
Ilya Lavrenov 已提交
2932

2933
    size_t globalsize[2] = { (size_t)m.cols * cn / kercn, ((size_t)m.rows + rowsPerWI - 1) / rowsPerWI };
I
Ilya Lavrenov 已提交
2934 2935 2936 2937 2938
    return k.run(2, globalsize, NULL, false);
}

}

I
Ilya Lavrenov 已提交
2939 2940
#endif

2941
void cv::setIdentity( InputOutputArray _m, const Scalar& s )
2942
{
2943 2944
    CV_INSTRUMENT_REGION()

I
Ilya Lavrenov 已提交
2945 2946
    CV_Assert( _m.dims() <= 2 );

I
Ilya Lavrenov 已提交
2947 2948
    CV_OCL_RUN(_m.isUMat(),
               ocl_setIdentity(_m, s))
I
Ilya Lavrenov 已提交
2949

2950
    Mat m = _m.getMat();
2951
    int rows = m.rows, cols = m.cols, type = m.type();
2952

2953 2954
    if( type == CV_32FC1 )
    {
2955
        float* data = m.ptr<float>();
2956 2957 2958
        float val = (float)s[0];
        size_t step = m.step/sizeof(data[0]);

2959
        for( int i = 0; i < rows; i++, data += step )
2960
        {
2961
            for( int j = 0; j < cols; j++ )
2962 2963 2964 2965 2966 2967 2968
                data[j] = 0;
            if( i < cols )
                data[i] = val;
        }
    }
    else if( type == CV_64FC1 )
    {
2969
        double* data = m.ptr<double>();
2970 2971 2972
        double val = s[0];
        size_t step = m.step/sizeof(data[0]);

2973
        for( int i = 0; i < rows; i++, data += step )
2974
        {
2975
            for( int j = 0; j < cols; j++ )
2976 2977 2978 2979 2980 2981 2982 2983 2984 2985
                data[j] = j == i ? val : 0;
        }
    }
    else
    {
        m = Scalar(0);
        m.diag() = s;
    }
}

2986 2987
//////////////////////////////////////////// trace ///////////////////////////////////////////

2988
cv::Scalar cv::trace( InputArray _m )
2989
{
2990 2991
    CV_INSTRUMENT_REGION()

2992
    Mat m = _m.getMat();
V
Vadim Pisarevsky 已提交
2993
    CV_Assert( m.dims <= 2 );
2994
    int type = m.type();
2995
    int nm = std::min(m.rows, m.cols);
2996

2997 2998
    if( type == CV_32FC1 )
    {
2999
        const float* ptr = m.ptr<float>();
3000 3001
        size_t step = m.step/sizeof(ptr[0]) + 1;
        double _s = 0;
3002
        for( int i = 0; i < nm; i++ )
3003 3004 3005
            _s += ptr[i*step];
        return _s;
    }
3006

3007 3008
    if( type == CV_64FC1 )
    {
3009
        const double* ptr = m.ptr<double>();
3010 3011
        size_t step = m.step/sizeof(ptr[0]) + 1;
        double _s = 0;
3012
        for( int i = 0; i < nm; i++ )
3013 3014 3015
            _s += ptr[i*step];
        return _s;
    }
3016

3017 3018 3019
    return cv::sum(m.diag());
}

3020
////////////////////////////////////// transpose /////////////////////////////////////////
3021 3022 3023 3024

namespace cv
{

3025
template<typename T> static void
3026
transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz )
3027
{
V
Victoria Zhislina 已提交
3028 3029
    int i=0, j, m = sz.width, n = sz.height;

3030
    #if CV_ENABLE_UNROLLED
V
Victoria Zhislina 已提交
3031
    for(; i <= m - 4; i += 4 )
3032 3033 3034 3035 3036
    {
        T* d0 = (T*)(dst + dstep*i);
        T* d1 = (T*)(dst + dstep*(i+1));
        T* d2 = (T*)(dst + dstep*(i+2));
        T* d3 = (T*)(dst + dstep*(i+3));
3037

3038 3039 3040 3041 3042 3043
        for( j = 0; j <= n - 4; j += 4 )
        {
            const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
            const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
            const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
            const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
3044

3045 3046 3047 3048 3049
            d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
            d1[j] = s0[1]; d1[j+1] = s1[1]; d1[j+2] = s2[1]; d1[j+3] = s3[1];
            d2[j] = s0[2]; d2[j+1] = s1[2]; d2[j+2] = s2[2]; d2[j+3] = s3[2];
            d3[j] = s0[3]; d3[j+1] = s1[3]; d3[j+2] = s2[3]; d3[j+3] = s3[3];
        }
3050

3051 3052 3053 3054 3055 3056
        for( ; j < n; j++ )
        {
            const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
            d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3];
        }
    }
V
Victoria Zhislina 已提交
3057
    #endif
3058 3059 3060
    for( ; i < m; i++ )
    {
        T* d0 = (T*)(dst + dstep*i);
V
Victoria Zhislina 已提交
3061
        j = 0;
3062
        #if CV_ENABLE_UNROLLED
V
Victoria Zhislina 已提交
3063
        for(; j <= n - 4; j += 4 )
3064 3065 3066 3067 3068
        {
            const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
            const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
            const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
            const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
3069

3070 3071
            d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
        }
V
Victoria Zhislina 已提交
3072
        #endif
3073 3074 3075 3076 3077 3078 3079
        for( ; j < n; j++ )
        {
            const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
            d0[j] = s0[0];
        }
    }
}
3080

3081 3082 3083
template<typename T> static void
transposeI_( uchar* data, size_t step, int n )
{
3084
    for( int i = 0; i < n; i++ )
3085 3086 3087
    {
        T* row = (T*)(data + step*i);
        uchar* data1 = data + i*sizeof(T);
3088
        for( int j = i+1; j < n; j++ )
3089 3090 3091
            std::swap( row[j], *(T*)(data1 + step*j) );
    }
}
3092

3093 3094
typedef void (*TransposeFunc)( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz );
typedef void (*TransposeInplaceFunc)( uchar* data, size_t step, int n );
3095

3096 3097 3098 3099 3100 3101
#define DEF_TRANSPOSE_FUNC(suffix, type) \
static void transpose_##suffix( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) \
{ transpose_<type>(src, sstep, dst, dstep, sz); } \
\
static void transposeI_##suffix( uchar* data, size_t step, int n ) \
{ transposeI_<type>(data, step, n); }
3102

3103 3104 3105 3106 3107 3108 3109 3110 3111 3112
DEF_TRANSPOSE_FUNC(8u, uchar)
DEF_TRANSPOSE_FUNC(16u, ushort)
DEF_TRANSPOSE_FUNC(8uC3, Vec3b)
DEF_TRANSPOSE_FUNC(32s, int)
DEF_TRANSPOSE_FUNC(16uC3, Vec3s)
DEF_TRANSPOSE_FUNC(32sC2, Vec2i)
DEF_TRANSPOSE_FUNC(32sC3, Vec3i)
DEF_TRANSPOSE_FUNC(32sC4, Vec4i)
DEF_TRANSPOSE_FUNC(32sC6, Vec6i)
DEF_TRANSPOSE_FUNC(32sC8, Vec8i)
3113

3114 3115 3116 3117 3118 3119
static TransposeFunc transposeTab[] =
{
    0, transpose_8u, transpose_16u, transpose_8uC3, transpose_32s, 0, transpose_16uC3, 0,
    transpose_32sC2, 0, 0, 0, transpose_32sC3, 0, 0, 0, transpose_32sC4,
    0, 0, 0, 0, 0, 0, 0, transpose_32sC6, 0, 0, 0, 0, 0, 0, 0, transpose_32sC8
};
3120

3121 3122 3123 3124 3125 3126
static TransposeInplaceFunc transposeInplaceTab[] =
{
    0, transposeI_8u, transposeI_16u, transposeI_8uC3, transposeI_32s, 0, transposeI_16uC3, 0,
    transposeI_32sC2, 0, 0, 0, transposeI_32sC3, 0, 0, 0, transposeI_32sC4,
    0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8
};
3127

I
Ilya Lavrenov 已提交
3128 3129
#ifdef HAVE_OPENCL

I
Ilya Lavrenov 已提交
3130 3131 3132 3133 3134 3135 3136
static inline int divUp(int a, int b)
{
    return (a + b - 1) / b;
}

static bool ocl_transpose( InputArray _src, OutputArray _dst )
{
I
Ilya Lavrenov 已提交
3137
    const ocl::Device & dev = ocl::Device::getDefault();
I
Ilya Lavrenov 已提交
3138
    const int TILE_DIM = 32, BLOCK_ROWS = 8;
I
Ilya Lavrenov 已提交
3139 3140
    int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
        rowsPerWI = dev.isIntel() ? 4 : 1;
I
Ilya Lavrenov 已提交
3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153

    UMat src = _src.getUMat();
    _dst.create(src.cols, src.rows, type);
    UMat dst = _dst.getUMat();

    String kernelName("transpose");
    bool inplace = dst.u == src.u;

    if (inplace)
    {
        CV_Assert(dst.cols == dst.rows);
        kernelName += "_inplace";
    }
3154 3155 3156 3157 3158 3159 3160
    else
    {
        // check required local memory size
        size_t required_local_memory = (size_t) TILE_DIM*(TILE_DIM+1)*CV_ELEM_SIZE(type);
        if (required_local_memory > ocl::Device::getDefault().localMemSize())
            return false;
    }
I
Ilya Lavrenov 已提交
3161 3162

    ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc,
3163
                  format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d%s",
3164
                         ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth),
3165
                         cn, TILE_DIM, BLOCK_ROWS, rowsPerWI, inplace ? " -D INPLACE" : ""));
I
Ilya Lavrenov 已提交
3166 3167 3168
    if (k.empty())
        return false;

I
Ilya Lavrenov 已提交
3169 3170 3171 3172 3173 3174
    if (inplace)
        k.args(ocl::KernelArg::ReadWriteNoSize(dst), dst.rows);
    else
        k.args(ocl::KernelArg::ReadOnly(src),
               ocl::KernelArg::WriteOnlyNoSize(dst));

I
Ilya Lavrenov 已提交
3175
    size_t localsize[2]  = { TILE_DIM, BLOCK_ROWS };
3176
    size_t globalsize[2] = { (size_t)src.cols, inplace ? ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI : (divUp((size_t)src.rows, TILE_DIM) * BLOCK_ROWS) };
I
Ilya Lavrenov 已提交
3177 3178 3179 3180 3181 3182

    if (inplace && dev.isIntel())
    {
        localsize[0] = 16;
        localsize[1] = dev.maxWorkGroupSize() / localsize[0];
    }
I
Ilya Lavrenov 已提交
3183 3184 3185 3186

    return k.run(2, globalsize, localsize, false);
}

I
Ilya Lavrenov 已提交
3187 3188
#endif

D
Dmitry Budnikov 已提交
3189
#ifdef HAVE_IPP
3190
static bool ipp_transpose( Mat &src, Mat &dst )
D
Dmitry Budnikov 已提交
3191
{
3192 3193
    CV_INSTRUMENT_REGION_IPP()

3194
    int type = src.type();
3195 3196 3197 3198
    typedef IppStatus (CV_STDCALL * IppiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize);
    typedef IppStatus (CV_STDCALL * IppiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize);
    IppiTranspose ippiTranspose = 0;
    IppiTransposeI ippiTranspose_I = 0;
D
Dmitry Budnikov 已提交
3199 3200 3201 3202

    if (dst.data == src.data && dst.cols == dst.rows)
    {
        CV_SUPPRESS_DEPRECATED_START
3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218
        ippiTranspose_I =
            type == CV_8UC1 ? (IppiTransposeI)ippiTranspose_8u_C1IR :
            type == CV_8UC3 ? (IppiTransposeI)ippiTranspose_8u_C3IR :
            type == CV_8UC4 ? (IppiTransposeI)ippiTranspose_8u_C4IR :
            type == CV_16UC1 ? (IppiTransposeI)ippiTranspose_16u_C1IR :
            type == CV_16UC3 ? (IppiTransposeI)ippiTranspose_16u_C3IR :
            type == CV_16UC4 ? (IppiTransposeI)ippiTranspose_16u_C4IR :
            type == CV_16SC1 ? (IppiTransposeI)ippiTranspose_16s_C1IR :
            type == CV_16SC3 ? (IppiTransposeI)ippiTranspose_16s_C3IR :
            type == CV_16SC4 ? (IppiTransposeI)ippiTranspose_16s_C4IR :
            type == CV_32SC1 ? (IppiTransposeI)ippiTranspose_32s_C1IR :
            type == CV_32SC3 ? (IppiTransposeI)ippiTranspose_32s_C3IR :
            type == CV_32SC4 ? (IppiTransposeI)ippiTranspose_32s_C4IR :
            type == CV_32FC1 ? (IppiTransposeI)ippiTranspose_32f_C1IR :
            type == CV_32FC3 ? (IppiTransposeI)ippiTranspose_32f_C3IR :
            type == CV_32FC4 ? (IppiTransposeI)ippiTranspose_32f_C4IR : 0;
D
Dmitry Budnikov 已提交
3219 3220 3221 3222
        CV_SUPPRESS_DEPRECATED_END
    }
    else
    {
3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238
        ippiTranspose =
            type == CV_8UC1 ? (IppiTranspose)ippiTranspose_8u_C1R :
            type == CV_8UC3 ? (IppiTranspose)ippiTranspose_8u_C3R :
            type == CV_8UC4 ? (IppiTranspose)ippiTranspose_8u_C4R :
            type == CV_16UC1 ? (IppiTranspose)ippiTranspose_16u_C1R :
            type == CV_16UC3 ? (IppiTranspose)ippiTranspose_16u_C3R :
            type == CV_16UC4 ? (IppiTranspose)ippiTranspose_16u_C4R :
            type == CV_16SC1 ? (IppiTranspose)ippiTranspose_16s_C1R :
            type == CV_16SC3 ? (IppiTranspose)ippiTranspose_16s_C3R :
            type == CV_16SC4 ? (IppiTranspose)ippiTranspose_16s_C4R :
            type == CV_32SC1 ? (IppiTranspose)ippiTranspose_32s_C1R :
            type == CV_32SC3 ? (IppiTranspose)ippiTranspose_32s_C3R :
            type == CV_32SC4 ? (IppiTranspose)ippiTranspose_32s_C4R :
            type == CV_32FC1 ? (IppiTranspose)ippiTranspose_32f_C1R :
            type == CV_32FC3 ? (IppiTranspose)ippiTranspose_32f_C3R :
            type == CV_32FC4 ? (IppiTranspose)ippiTranspose_32f_C4R : 0;
D
Dmitry Budnikov 已提交
3239 3240 3241
    }

    IppiSize roiSize = { src.cols, src.rows };
3242
    if (ippiTranspose != 0)
D
Dmitry Budnikov 已提交
3243
    {
3244
        if (CV_INSTRUMENT_FUN_IPP(ippiTranspose, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize) >= 0)
D
Dmitry Budnikov 已提交
3245 3246
            return true;
    }
3247
    else if (ippiTranspose_I != 0)
D
Dmitry Budnikov 已提交
3248
    {
3249
        if (CV_INSTRUMENT_FUN_IPP(ippiTranspose_I, dst.ptr(), (int)dst.step, roiSize) >= 0)
D
Dmitry Budnikov 已提交
3250 3251 3252
            return true;
    }
    return false;
3253
}
D
Dmitry Budnikov 已提交
3254 3255
#endif

3256
}
3257 3258


3259
void cv::transpose( InputArray _src, OutputArray _dst )
3260
{
3261 3262
    CV_INSTRUMENT_REGION()

I
Ilya Lavrenov 已提交
3263 3264 3265
    int type = _src.type(), esz = CV_ELEM_SIZE(type);
    CV_Assert( _src.dims() <= 2 && esz <= 32 );

I
Ilya Lavrenov 已提交
3266 3267
    CV_OCL_RUN(_dst.isUMat(),
               ocl_transpose(_src, _dst))
I
Ilya Lavrenov 已提交
3268

3269
    Mat src = _src.getMat();
3270 3271 3272 3273 3274
    if( src.empty() )
    {
        _dst.release();
        return;
    }
3275

3276 3277
    _dst.create(src.cols, src.rows, src.type());
    Mat dst = _dst.getMat();
3278

3279 3280 3281
    // handle the case of single-column/single-row matrices, stored in STL vectors.
    if( src.rows != dst.cols || src.cols != dst.rows )
    {
3282
        CV_Assert( src.size() == dst.size() && (src.cols == 1 || src.rows == 1) );
3283 3284 3285 3286
        src.copyTo(dst);
        return;
    }

3287
    CV_IPP_RUN_FAST(ipp_transpose(src, dst))
I
Ilya Lavrenov 已提交
3288

3289
    if( dst.data == src.data )
3290
    {
3291
        TransposeInplaceFunc func = transposeInplaceTab[esz];
3292
        CV_Assert( func != 0 );
I
Ilya Lavrenov 已提交
3293
        CV_Assert( dst.cols == dst.rows );
3294
        func( dst.ptr(), dst.step, dst.rows );
3295 3296 3297
    }
    else
    {
3298
        TransposeFunc func = transposeTab[esz];
3299
        CV_Assert( func != 0 );
3300
        func( src.ptr(), src.step, dst.ptr(), dst.step, src.size() );
3301 3302 3303 3304
    }
}


3305 3306
////////////////////////////////////// completeSymm /////////////////////////////////////////

3307
void cv::completeSymm( InputOutputArray _m, bool LtoR )
3308
{
3309 3310
    CV_INSTRUMENT_REGION()

3311
    Mat m = _m.getMat();
3312 3313
    size_t step = m.step, esz = m.elemSize();
    CV_Assert( m.dims <= 2 && m.rows == m.cols );
3314

3315 3316
    int rows = m.rows;
    int j0 = 0, j1 = rows;
3317

3318
    uchar* data = m.ptr();
3319
    for( int i = 0; i < rows; i++ )
3320
    {
3321 3322 3323
        if( !LtoR ) j1 = i; else j0 = i+1;
        for( int j = j0; j < j1; j++ )
            memcpy(data + (i*step + j*esz), data + (j*step + i*esz), esz);
3324 3325 3326
    }
}

3327

3328
cv::Mat cv::Mat::cross(InputArray _m) const
3329
{
3330
    Mat m = _m.getMat();
A
Andrey Kamaev 已提交
3331 3332
    int tp = type(), d = CV_MAT_DEPTH(tp);
    CV_Assert( dims <= 2 && m.dims <= 2 && size() == m.size() && tp == m.type() &&
3333
        ((rows == 3 && cols == 1) || (cols*channels() == 3 && rows == 1)));
A
Andrey Kamaev 已提交
3334
    Mat result(rows, cols, tp);
3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362

    if( d == CV_32F )
    {
        const float *a = (const float*)data, *b = (const float*)m.data;
        float* c = (float*)result.data;
        size_t lda = rows > 1 ? step/sizeof(a[0]) : 1;
        size_t ldb = rows > 1 ? m.step/sizeof(b[0]) : 1;

        c[0] = a[lda] * b[ldb*2] - a[lda*2] * b[ldb];
        c[1] = a[lda*2] * b[0] - a[0] * b[ldb*2];
        c[2] = a[0] * b[ldb] - a[lda] * b[0];
    }
    else if( d == CV_64F )
    {
        const double *a = (const double*)data, *b = (const double*)m.data;
        double* c = (double*)result.data;
        size_t lda = rows > 1 ? step/sizeof(a[0]) : 1;
        size_t ldb = rows > 1 ? m.step/sizeof(b[0]) : 1;

        c[0] = a[lda] * b[ldb*2] - a[lda*2] * b[ldb];
        c[1] = a[lda*2] * b[0] - a[0] * b[ldb*2];
        c[2] = a[0] * b[ldb] - a[lda] * b[0];
    }

    return result;
}


3363
////////////////////////////////////////// reduce ////////////////////////////////////////////
3364

3365 3366 3367
namespace cv
{

3368 3369 3370 3371 3372 3373 3374 3375
template<typename T, typename ST, class Op> static void
reduceR_( const Mat& srcmat, Mat& dstmat )
{
    typedef typename Op::rtype WT;
    Size size = srcmat.size();
    size.width *= srcmat.channels();
    AutoBuffer<WT> buffer(size.width);
    WT* buf = buffer;
3376 3377
    ST* dst = dstmat.ptr<ST>();
    const T* src = srcmat.ptr<T>();
3378 3379 3380 3381 3382 3383 3384 3385 3386 3387
    size_t srcstep = srcmat.step/sizeof(src[0]);
    int i;
    Op op;

    for( i = 0; i < size.width; i++ )
        buf[i] = src[i];

    for( ; --size.height; )
    {
        src += srcstep;
V
Victoria Zhislina 已提交
3388
        i = 0;
3389
        #if CV_ENABLE_UNROLLED
V
Victoria Zhislina 已提交
3390
        for(; i <= size.width - 4; i += 4 )
3391 3392 3393 3394 3395 3396 3397 3398 3399 3400
        {
            WT s0, s1;
            s0 = op(buf[i], (WT)src[i]);
            s1 = op(buf[i+1], (WT)src[i+1]);
            buf[i] = s0; buf[i+1] = s1;

            s0 = op(buf[i+2], (WT)src[i+2]);
            s1 = op(buf[i+3], (WT)src[i+3]);
            buf[i+2] = s0; buf[i+3] = s1;
        }
V
Victoria Zhislina 已提交
3401
        #endif
3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415
        for( ; i < size.width; i++ )
            buf[i] = op(buf[i], (WT)src[i]);
    }

    for( i = 0; i < size.width; i++ )
        dst[i] = (ST)buf[i];
}


template<typename T, typename ST, class Op> static void
reduceC_( const Mat& srcmat, Mat& dstmat )
{
    typedef typename Op::rtype WT;
    Size size = srcmat.size();
3416
    int cn = srcmat.channels();
3417 3418 3419 3420 3421
    size.width *= cn;
    Op op;

    for( int y = 0; y < size.height; y++ )
    {
3422 3423
        const T* src = srcmat.ptr<T>(y);
        ST* dst = dstmat.ptr<ST>(y);
3424
        if( size.width == cn )
3425
            for( int k = 0; k < cn; k++ )
3426 3427 3428
                dst[k] = src[k];
        else
        {
3429
            for( int k = 0; k < cn; k++ )
3430 3431
            {
                WT a0 = src[k], a1 = src[k+cn];
3432
                int i;
3433 3434 3435 3436 3437 3438 3439 3440 3441 3442
                for( i = 2*cn; i <= size.width - 4*cn; i += 4*cn )
                {
                    a0 = op(a0, (WT)src[i+k]);
                    a1 = op(a1, (WT)src[i+k+cn]);
                    a0 = op(a0, (WT)src[i+k+cn*2]);
                    a1 = op(a1, (WT)src[i+k+cn*3]);
                }

                for( ; i < size.width; i += cn )
                {
3443
                    a0 = op(a0, (WT)src[i+k]);
3444 3445
                }
                a0 = op(a0, a1);
3446
                dst[k] = (ST)a0;
3447 3448
            }
        }
3449
    }
3450 3451 3452 3453
}

typedef void (*ReduceFunc)( const Mat& src, Mat& dst );

3454
}
3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478

#define reduceSumR8u32s  reduceR_<uchar, int,   OpAdd<int> >
#define reduceSumR8u32f  reduceR_<uchar, float, OpAdd<int> >
#define reduceSumR8u64f  reduceR_<uchar, double,OpAdd<int> >
#define reduceSumR16u32f reduceR_<ushort,float, OpAdd<float> >
#define reduceSumR16u64f reduceR_<ushort,double,OpAdd<double> >
#define reduceSumR16s32f reduceR_<short, float, OpAdd<float> >
#define reduceSumR16s64f reduceR_<short, double,OpAdd<double> >
#define reduceSumR32f32f reduceR_<float, float, OpAdd<float> >
#define reduceSumR32f64f reduceR_<float, double,OpAdd<double> >
#define reduceSumR64f64f reduceR_<double,double,OpAdd<double> >

#define reduceMaxR8u  reduceR_<uchar, uchar, OpMax<uchar> >
#define reduceMaxR16u reduceR_<ushort,ushort,OpMax<ushort> >
#define reduceMaxR16s reduceR_<short, short, OpMax<short> >
#define reduceMaxR32f reduceR_<float, float, OpMax<float> >
#define reduceMaxR64f reduceR_<double,double,OpMax<double> >

#define reduceMinR8u  reduceR_<uchar, uchar, OpMin<uchar> >
#define reduceMinR16u reduceR_<ushort,ushort,OpMin<ushort> >
#define reduceMinR16s reduceR_<short, short, OpMin<short> >
#define reduceMinR32f reduceR_<float, float, OpMin<float> >
#define reduceMinR64f reduceR_<double,double,OpMin<double> >

3479 3480
#ifdef HAVE_IPP
static inline bool ipp_reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat)
I
Ilya Lavrenov 已提交
3481 3482
{
    int sstep = (int)srcmat.step, stype = srcmat.type(),
3483 3484 3485
            ddepth = dstmat.depth();

    IppiSize roisize = { srcmat.size().width, 1 };
I
Ilya Lavrenov 已提交
3486

3487 3488 3489 3490
    typedef IppStatus (CV_STDCALL * IppiSum)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum);
    typedef IppStatus (CV_STDCALL * IppiSumHint)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum, IppHintAlgorithm hint);
    IppiSum ippiSum = 0;
    IppiSumHint ippiSumHint = 0;
I
Ilya Lavrenov 已提交
3491

3492
    if(ddepth == CV_64F)
I
Ilya Lavrenov 已提交
3493
    {
3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507
        ippiSum =
            stype == CV_8UC1 ? (IppiSum)ippiSum_8u_C1R :
            stype == CV_8UC3 ? (IppiSum)ippiSum_8u_C3R :
            stype == CV_8UC4 ? (IppiSum)ippiSum_8u_C4R :
            stype == CV_16UC1 ? (IppiSum)ippiSum_16u_C1R :
            stype == CV_16UC3 ? (IppiSum)ippiSum_16u_C3R :
            stype == CV_16UC4 ? (IppiSum)ippiSum_16u_C4R :
            stype == CV_16SC1 ? (IppiSum)ippiSum_16s_C1R :
            stype == CV_16SC3 ? (IppiSum)ippiSum_16s_C3R :
            stype == CV_16SC4 ? (IppiSum)ippiSum_16s_C4R : 0;
        ippiSumHint =
            stype == CV_32FC1 ? (IppiSumHint)ippiSum_32f_C1R :
            stype == CV_32FC3 ? (IppiSumHint)ippiSum_32f_C3R :
            stype == CV_32FC4 ? (IppiSumHint)ippiSum_32f_C4R : 0;
I
Ilya Lavrenov 已提交
3508 3509
    }

3510
    if(ippiSum)
I
Ilya Lavrenov 已提交
3511
    {
3512
        for(int y = 0; y < srcmat.size().height; y++)
3513
        {
3514
            if(CV_INSTRUMENT_FUN_IPP(ippiSum, srcmat.ptr(y), sstep, roisize, dstmat.ptr<Ipp64f>(y)) < 0)
3515
                return false;
3516
        }
3517 3518
        return true;
    }
3519
    else if(ippiSumHint)
3520 3521
    {
        for(int y = 0; y < srcmat.size().height; y++)
3522
        {
3523
            if(CV_INSTRUMENT_FUN_IPP(ippiSumHint, srcmat.ptr(y), sstep, roisize, dstmat.ptr<Ipp64f>(y), ippAlgHintAccurate) < 0)
3524
                return false;
3525
        }
3526 3527 3528 3529 3530 3531 3532 3533
        return true;
    }

    return false;
}

static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat)
{
3534
    CV_IPP_RUN_FAST(ipp_reduceSumC_8u16u16s32f_64f(srcmat, dstmat));
3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545

    cv::ReduceFunc func = 0;

    if(dstmat.depth() == CV_64F)
    {
        int sdepth = CV_MAT_DEPTH(srcmat.type());
        func =
            sdepth == CV_8U ? (cv::ReduceFunc)cv::reduceC_<uchar, double,   cv::OpAdd<double> > :
            sdepth == CV_16U ? (cv::ReduceFunc)cv::reduceC_<ushort, double,   cv::OpAdd<double> > :
            sdepth == CV_16S ? (cv::ReduceFunc)cv::reduceC_<short, double,   cv::OpAdd<double> > :
            sdepth == CV_32F ? (cv::ReduceFunc)cv::reduceC_<float, double,   cv::OpAdd<double> > : 0;
I
Ilya Lavrenov 已提交
3546
    }
3547
    CV_Assert(func);
I
Ilya Lavrenov 已提交
3548 3549 3550 3551 3552 3553

    func(srcmat, dstmat);
}

#endif

3554 3555 3556 3557 3558 3559 3560
#define reduceSumC8u32s  reduceC_<uchar, int,   OpAdd<int> >
#define reduceSumC8u32f  reduceC_<uchar, float, OpAdd<int> >
#define reduceSumC16u32f reduceC_<ushort,float, OpAdd<float> >
#define reduceSumC16s32f reduceC_<short, float, OpAdd<float> >
#define reduceSumC32f32f reduceC_<float, float, OpAdd<float> >
#define reduceSumC64f64f reduceC_<double,double,OpAdd<double> >

3561
#ifdef HAVE_IPP
I
Ilya Lavrenov 已提交
3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572
#define reduceSumC8u64f  reduceSumC_8u16u16s32f_64f
#define reduceSumC16u64f reduceSumC_8u16u16s32f_64f
#define reduceSumC16s64f reduceSumC_8u16u16s32f_64f
#define reduceSumC32f64f reduceSumC_8u16u16s32f_64f
#else
#define reduceSumC8u64f  reduceC_<uchar, double,OpAdd<int> >
#define reduceSumC16u64f reduceC_<ushort,double,OpAdd<double> >
#define reduceSumC16s64f reduceC_<short, double,OpAdd<double> >
#define reduceSumC32f64f reduceC_<float, double,OpAdd<double> >
#endif

3573
#ifdef HAVE_IPP
3574
#define REDUCE_OP(favor, optype, type1, type2) \
3575
static inline bool ipp_reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \
3576
{ \
3577
    if((srcmat.channels() == 1)) \
3578
    { \
3579 3580 3581 3582 3583
        int sstep = (int)srcmat.step; \
        typedef Ipp##favor IppType; \
        IppiSize roisize = ippiSize(srcmat.size().width, 1);\
        for(int y = 0; y < srcmat.size().height; y++)\
        {\
3584
            if(CV_INSTRUMENT_FUN_IPP(ippi##optype##_##favor##_C1R, srcmat.ptr<IppType>(y), sstep, roisize, dstmat.ptr<IppType>(y)) < 0)\
3585 3586 3587 3588 3589 3590 3591 3592
                return false;\
        }\
        return true;\
    }\
    return false; \
} \
static inline void reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \
{ \
3593
    CV_IPP_RUN_FAST(ipp_reduce##optype##C##favor(srcmat, dstmat)); \
3594 3595 3596 3597
    cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat, dstmat); \
}
#endif

3598
#ifdef HAVE_IPP
3599 3600 3601 3602 3603
REDUCE_OP(8u, Max, uchar, uchar)
REDUCE_OP(16u, Max, ushort, ushort)
REDUCE_OP(16s, Max, short, short)
REDUCE_OP(32f, Max, float, float)
#else
3604 3605 3606 3607
#define reduceMaxC8u  reduceC_<uchar, uchar, OpMax<uchar> >
#define reduceMaxC16u reduceC_<ushort,ushort,OpMax<ushort> >
#define reduceMaxC16s reduceC_<short, short, OpMax<short> >
#define reduceMaxC32f reduceC_<float, float, OpMax<float> >
3608
#endif
3609 3610
#define reduceMaxC64f reduceC_<double,double,OpMax<double> >

3611
#ifdef HAVE_IPP
3612 3613 3614 3615 3616
REDUCE_OP(8u, Min, uchar, uchar)
REDUCE_OP(16u, Min, ushort, ushort)
REDUCE_OP(16s, Min, short, short)
REDUCE_OP(32f, Min, float, float)
#else
3617 3618 3619 3620
#define reduceMinC8u  reduceC_<uchar, uchar, OpMin<uchar> >
#define reduceMinC16u reduceC_<ushort,ushort,OpMin<ushort> >
#define reduceMinC16s reduceC_<short, short, OpMin<short> >
#define reduceMinC32f reduceC_<float, float, OpMin<float> >
3621
#endif
3622 3623
#define reduceMinC64f reduceC_<double,double,OpMin<double> >

I
Ilya Lavrenov 已提交
3624 3625
#ifdef HAVE_OPENCL

I
Ilya Lavrenov 已提交
3626 3627 3628 3629 3630
namespace cv {

static bool ocl_reduce(InputArray _src, OutputArray _dst,
                       int dim, int op, int op0, int stype, int dtype)
{
I
Ilya Lavrenov 已提交
3631
    const int min_opt_cols = 128, buf_cols = 32;
I
Ilya Lavrenov 已提交
3632 3633
    int sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype),
            ddepth = CV_MAT_DEPTH(dtype), ddepth0 = ddepth;
V
vbystricky 已提交
3634 3635 3636 3637 3638
    const ocl::Device &defDev = ocl::Device::getDefault();
    bool doubleSupport = defDev.doubleFPConfig() > 0;

    size_t wgs = defDev.maxWorkGroupSize();
    bool useOptimized = 1 == dim && _src.cols() > min_opt_cols && (wgs >= buf_cols);
I
Ilya Lavrenov 已提交
3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650

    if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F))
        return false;

    if (op == CV_REDUCE_AVG)
    {
        if (sdepth < CV_32S && ddepth < CV_32S)
            ddepth = CV_32S;
    }

    const char * const ops[4] = { "OCL_CV_REDUCE_SUM", "OCL_CV_REDUCE_AVG",
                                  "OCL_CV_REDUCE_MAX", "OCL_CV_REDUCE_MIN" };
I
Ilya Lavrenov 已提交
3651 3652 3653
    int wdepth = std::max(ddepth, CV_32F);
    if (useOptimized)
    {
V
vbystricky 已提交
3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674
        size_t tileHeight = (size_t)(wgs / buf_cols);
        if (defDev.isIntel())
        {
            static const size_t maxItemInGroupCount = 16;
            tileHeight = min(tileHeight, defDev.localMemSize() / buf_cols / CV_ELEM_SIZE(CV_MAKETYPE(wdepth, cn)) / maxItemInGroupCount);
        }
        char cvt[3][40];
        cv::String build_opt = format("-D OP_REDUCE_PRE -D BUF_COLS=%d -D TILE_HEIGHT=%d -D %s -D dim=1"
                                            " -D cn=%d -D ddepth=%d"
                                            " -D srcT=%s -D bufT=%s -D dstT=%s"
                                            " -D convertToWT=%s -D convertToBufT=%s -D convertToDT=%s%s",
                                            buf_cols, tileHeight, ops[op], cn, ddepth,
                                            ocl::typeToStr(sdepth),
                                            ocl::typeToStr(ddepth),
                                            ocl::typeToStr(ddepth0),
                                            ocl::convertTypeStr(ddepth, wdepth, 1, cvt[0]),
                                            ocl::convertTypeStr(sdepth, ddepth, 1, cvt[1]),
                                            ocl::convertTypeStr(wdepth, ddepth0, 1, cvt[2]),
                                            doubleSupport ? " -D DOUBLE_SUPPORT" : "");
        ocl::Kernel k("reduce_horz_opt", ocl::core::reduce2_oclsrc, build_opt);
        if (k.empty())
3675 3676 3677 3678
            return false;
        UMat src = _src.getUMat();
        Size dsize(1, src.rows);
        _dst.create(dsize, dtype);
I
Ilya Lavrenov 已提交
3679
        UMat dst = _dst.getUMat();
3680 3681

        if (op0 == CV_REDUCE_AVG)
V
vbystricky 已提交
3682 3683
            k.args(ocl::KernelArg::ReadOnly(src),
                      ocl::KernelArg::WriteOnlyNoSize(dst), 1.0f / src.cols);
I
Ilya Lavrenov 已提交
3684
        else
V
vbystricky 已提交
3685 3686
            k.args(ocl::KernelArg::ReadOnly(src),
                      ocl::KernelArg::WriteOnlyNoSize(dst));
3687

3688 3689
        size_t localSize[2] = { (size_t)buf_cols, (size_t)tileHeight};
        size_t globalSize[2] = { (size_t)buf_cols, (size_t)src.rows };
V
vbystricky 已提交
3690
        return k.run(2, globalSize, localSize, false);
3691
    }
V
vbystricky 已提交
3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707
    else
    {
        char cvt[2][40];
        cv::String build_opt = format("-D %s -D dim=%d -D cn=%d -D ddepth=%d"
                                      " -D srcT=%s -D dstT=%s -D dstT0=%s -D convertToWT=%s"
                                      " -D convertToDT=%s -D convertToDT0=%s%s",
                                      ops[op], dim, cn, ddepth, ocl::typeToStr(useOptimized ? ddepth : sdepth),
                                      ocl::typeToStr(ddepth), ocl::typeToStr(ddepth0),
                                      ocl::convertTypeStr(ddepth, wdepth, 1, cvt[0]),
                                      ocl::convertTypeStr(sdepth, ddepth, 1, cvt[0]),
                                      ocl::convertTypeStr(wdepth, ddepth0, 1, cvt[1]),
                                      doubleSupport ? " -D DOUBLE_SUPPORT" : "");

        ocl::Kernel k("reduce", ocl::core::reduce2_oclsrc, build_opt);
        if (k.empty())
            return false;
3708

V
vbystricky 已提交
3709 3710 3711 3712
        UMat src = _src.getUMat();
        Size dsize(dim == 0 ? src.cols : 1, dim == 0 ? 1 : src.rows);
        _dst.create(dsize, dtype);
        UMat dst = _dst.getUMat();
I
Ilya Lavrenov 已提交
3713

V
vbystricky 已提交
3714 3715
        ocl::KernelArg srcarg = ocl::KernelArg::ReadOnly(src),
                temparg = ocl::KernelArg::WriteOnlyNoSize(dst);
I
Ilya Lavrenov 已提交
3716

V
vbystricky 已提交
3717 3718 3719 3720
        if (op0 == CV_REDUCE_AVG)
            k.args(srcarg, temparg, 1.0f / (dim == 0 ? src.rows : src.cols));
        else
            k.args(srcarg, temparg);
I
Ilya Lavrenov 已提交
3721

V
vbystricky 已提交
3722 3723 3724
        size_t globalsize = std::max(dsize.width, dsize.height);
        return k.run(1, &globalsize, NULL, false);
    }
I
Ilya Lavrenov 已提交
3725 3726 3727 3728
}

}

I
Ilya Lavrenov 已提交
3729 3730
#endif

3731
void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype)
3732
{
3733 3734
    CV_INSTRUMENT_REGION()

I
Ilya Lavrenov 已提交
3735
    CV_Assert( _src.dims() <= 2 );
3736
    int op0 = op;
I
Ilya Lavrenov 已提交
3737
    int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
3738
    if( dtype < 0 )
3739
        dtype = _dst.fixedType() ? _dst.type() : stype;
I
Ilya Lavrenov 已提交
3740
    dtype = CV_MAKETYPE(dtype >= 0 ? dtype : stype, cn);
3741 3742
    int ddepth = CV_MAT_DEPTH(dtype);

I
Ilya Lavrenov 已提交
3743
    CV_Assert( cn == CV_MAT_CN(dtype) );
3744
    CV_Assert( op == CV_REDUCE_SUM || op == CV_REDUCE_MAX ||
3745
               op == CV_REDUCE_MIN || op == CV_REDUCE_AVG );
I
Ilya Lavrenov 已提交
3746

I
Ilya Lavrenov 已提交
3747 3748
    CV_OCL_RUN(_dst.isUMat(),
               ocl_reduce(_src, _dst, dim, op, op0, stype, dtype))
I
Ilya Lavrenov 已提交
3749 3750 3751 3752

    Mat src = _src.getMat();
    _dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1, dtype);
    Mat dst = _dst.getMat(), temp = dst;
3753 3754 3755 3756 3757

    if( op == CV_REDUCE_AVG )
    {
        op = CV_REDUCE_SUM;
        if( sdepth < CV_32S && ddepth < CV_32S )
3758
        {
3759
            temp.create(dst.rows, dst.cols, CV_32SC(cn));
3760 3761
            ddepth = CV_32S;
        }
3762 3763 3764 3765 3766 3767 3768
    }

    ReduceFunc func = 0;
    if( dim == 0 )
    {
        if( op == CV_REDUCE_SUM )
        {
3769
            if(sdepth == CV_8U && ddepth == CV_32S)
3770
                func = GET_OPTIMIZED(reduceSumR8u32s);
3771
            else if(sdepth == CV_8U && ddepth == CV_32F)
3772
                func = reduceSumR8u32f;
3773
            else if(sdepth == CV_8U && ddepth == CV_64F)
3774
                func = reduceSumR8u64f;
3775
            else if(sdepth == CV_16U && ddepth == CV_32F)
3776
                func = reduceSumR16u32f;
3777
            else if(sdepth == CV_16U && ddepth == CV_64F)
3778
                func = reduceSumR16u64f;
3779
            else if(sdepth == CV_16S && ddepth == CV_32F)
3780
                func = reduceSumR16s32f;
3781
            else if(sdepth == CV_16S && ddepth == CV_64F)
3782 3783 3784
                func = reduceSumR16s64f;
            else if(sdepth == CV_32F && ddepth == CV_32F)
                func = GET_OPTIMIZED(reduceSumR32f32f);
3785
            else if(sdepth == CV_32F && ddepth == CV_64F)
3786
                func = reduceSumR32f64f;
3787
            else if(sdepth == CV_64F && ddepth == CV_64F)
3788
                func = reduceSumR64f64f;
3789 3790 3791
        }
        else if(op == CV_REDUCE_MAX)
        {
3792
            if(sdepth == CV_8U && ddepth == CV_8U)
3793 3794 3795
                func = GET_OPTIMIZED(reduceMaxR8u);
            else if(sdepth == CV_16U && ddepth == CV_16U)
                func = reduceMaxR16u;
3796
            else if(sdepth == CV_16S && ddepth == CV_16S)
3797
                func = reduceMaxR16s;
3798
            else if(sdepth == CV_32F && ddepth == CV_32F)
3799 3800 3801
                func = GET_OPTIMIZED(reduceMaxR32f);
            else if(sdepth == CV_64F && ddepth == CV_64F)
                func = reduceMaxR64f;
3802 3803 3804
        }
        else if(op == CV_REDUCE_MIN)
        {
3805
            if(sdepth == CV_8U && ddepth == CV_8U)
3806
                func = GET_OPTIMIZED(reduceMinR8u);
3807
            else if(sdepth == CV_16U && ddepth == CV_16U)
3808
                func = reduceMinR16u;
3809
            else if(sdepth == CV_16S && ddepth == CV_16S)
3810
                func = reduceMinR16s;
3811
            else if(sdepth == CV_32F && ddepth == CV_32F)
3812
                func = GET_OPTIMIZED(reduceMinR32f);
3813
            else if(sdepth == CV_64F && ddepth == CV_64F)
3814
                func = reduceMinR64f;
3815 3816 3817 3818 3819 3820
        }
    }
    else
    {
        if(op == CV_REDUCE_SUM)
        {
3821
            if(sdepth == CV_8U && ddepth == CV_32S)
3822
                func = GET_OPTIMIZED(reduceSumC8u32s);
3823
            else if(sdepth == CV_8U && ddepth == CV_32F)
3824
                func = reduceSumC8u32f;
3825
            else if(sdepth == CV_8U && ddepth == CV_64F)
3826
                func = reduceSumC8u64f;
3827
            else if(sdepth == CV_16U && ddepth == CV_32F)
3828
                func = reduceSumC16u32f;
3829
            else if(sdepth == CV_16U && ddepth == CV_64F)
3830
                func = reduceSumC16u64f;
3831
            else if(sdepth == CV_16S && ddepth == CV_32F)
3832
                func = reduceSumC16s32f;
3833
            else if(sdepth == CV_16S && ddepth == CV_64F)
3834 3835 3836
                func = reduceSumC16s64f;
            else if(sdepth == CV_32F && ddepth == CV_32F)
                func = GET_OPTIMIZED(reduceSumC32f32f);
3837
            else if(sdepth == CV_32F && ddepth == CV_64F)
3838
                func = reduceSumC32f64f;
3839
            else if(sdepth == CV_64F && ddepth == CV_64F)
3840
                func = reduceSumC64f64f;
3841 3842 3843
        }
        else if(op == CV_REDUCE_MAX)
        {
3844
            if(sdepth == CV_8U && ddepth == CV_8U)
3845 3846 3847
                func = GET_OPTIMIZED(reduceMaxC8u);
            else if(sdepth == CV_16U && ddepth == CV_16U)
                func = reduceMaxC16u;
3848
            else if(sdepth == CV_16S && ddepth == CV_16S)
3849
                func = reduceMaxC16s;
3850
            else if(sdepth == CV_32F && ddepth == CV_32F)
3851
                func = GET_OPTIMIZED(reduceMaxC32f);
3852
            else if(sdepth == CV_64F && ddepth == CV_64F)
3853
                func = reduceMaxC64f;
3854 3855 3856
        }
        else if(op == CV_REDUCE_MIN)
        {
3857
            if(sdepth == CV_8U && ddepth == CV_8U)
3858
                func = GET_OPTIMIZED(reduceMinC8u);
3859
            else if(sdepth == CV_16U && ddepth == CV_16U)
3860
                func = reduceMinC16u;
3861
            else if(sdepth == CV_16S && ddepth == CV_16S)
3862
                func = reduceMinC16s;
3863
            else if(sdepth == CV_32F && ddepth == CV_32F)
3864
                func = GET_OPTIMIZED(reduceMinC32f);
3865
            else if(sdepth == CV_64F && ddepth == CV_64F)
3866
                func = reduceMinC64f;
3867 3868 3869 3870 3871
        }
    }

    if( !func )
        CV_Error( CV_StsUnsupportedFormat,
3872
                  "Unsupported combination of input and output array formats" );
3873 3874 3875

    func( src, temp );

3876
    if( op0 == CV_REDUCE_AVG )
3877
        temp.convertTo(dst, dst.type(), 1./(dim == 0 ? src.rows : src.cols));
3878
}
3879 3880


3881
//////////////////////////////////////// sort ///////////////////////////////////////////
3882

3883 3884 3885
namespace cv
{

3886
#ifdef HAVE_IPP
I
Ilya Lavrenov 已提交
3887
#define USE_IPP_SORT
I
Ilya Lavrenov 已提交
3888

3889
typedef IppStatus (CV_STDCALL * IppSortFunc)(void *, int);
I
Ilya Lavrenov 已提交
3890
typedef IppSortFunc IppFlipFunc;
I
Ilya Lavrenov 已提交
3891 3892 3893 3894 3895

static IppSortFunc getSortFunc(int depth, bool sortDescending)
{
    if (!sortDescending)
        return depth == CV_8U ? (IppSortFunc)ippsSortAscend_8u_I :
P
Pavel Vlasov 已提交
3896 3897
#if IPP_DISABLE_BLOCK
            depth == CV_16U ? (IppSortFunc)ippsSortAscend_16u_I :
I
Ilya Lavrenov 已提交
3898 3899 3900
            depth == CV_16S ? (IppSortFunc)ippsSortAscend_16s_I :
            depth == CV_32S ? (IppSortFunc)ippsSortAscend_32s_I :
            depth == CV_32F ? (IppSortFunc)ippsSortAscend_32f_I :
P
Pavel Vlasov 已提交
3901 3902 3903
            depth == CV_64F ? (IppSortFunc)ippsSortAscend_64f_I :
#endif
            0;
I
Ilya Lavrenov 已提交
3904 3905
    else
        return depth == CV_8U ? (IppSortFunc)ippsSortDescend_8u_I :
P
Pavel Vlasov 已提交
3906 3907
#if IPP_DISABLE_BLOCK
            depth == CV_16U ? (IppSortFunc)ippsSortDescend_16u_I :
I
Ilya Lavrenov 已提交
3908 3909 3910
            depth == CV_16S ? (IppSortFunc)ippsSortDescend_16s_I :
            depth == CV_32S ? (IppSortFunc)ippsSortDescend_32s_I :
            depth == CV_32F ? (IppSortFunc)ippsSortDescend_32f_I :
P
Pavel Vlasov 已提交
3911 3912 3913
            depth == CV_64F ? (IppSortFunc)ippsSortDescend_64f_I :
#endif
            0;
I
Ilya Lavrenov 已提交
3914 3915
}

I
Ilya Lavrenov 已提交
3916 3917 3918 3919 3920
static IppFlipFunc getFlipFunc(int depth)
{
    CV_SUPPRESS_DEPRECATED_START
    return
            depth == CV_8U || depth == CV_8S ? (IppFlipFunc)ippsFlip_8u_I :
I
Ilya Lavrenov 已提交
3921
            depth == CV_16U || depth == CV_16S ? (IppFlipFunc)ippsFlip_16u_I :
I
Ilya Lavrenov 已提交
3922
            depth == CV_32S || depth == CV_32F ? (IppFlipFunc)ippsFlip_32f_I :
I
Ilya Lavrenov 已提交
3923
            depth == CV_64F ? (IppFlipFunc)ippsFlip_64f_I : 0;
I
Ilya Lavrenov 已提交
3924 3925 3926 3927
    CV_SUPPRESS_DEPRECATED_END
}


I
Ilya Lavrenov 已提交
3928 3929
#endif

3930 3931 3932 3933
template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
{
    AutoBuffer<T> buf;
    T* bptr;
3934
    int n, len;
3935 3936 3937
    bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
    bool inplace = src.data == dst.data;
    bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;
3938

3939 3940 3941 3942 3943 3944 3945 3946 3947
    if( sortRows )
        n = src.rows, len = src.cols;
    else
    {
        n = src.cols, len = src.rows;
        buf.allocate(len);
    }
    bptr = (T*)buf;

I
Ilya Lavrenov 已提交
3948 3949
#ifdef USE_IPP_SORT
    int depth = src.depth();
3950 3951 3952 3953 3954 3955 3956
    IppSortFunc ippSortFunc = 0;
    IppFlipFunc ippFlipFunc = 0;
    CV_IPP_CHECK()
    {
        ippSortFunc = getSortFunc(depth, sortDescending);
        ippFlipFunc = getFlipFunc(depth);
    }
I
Ilya Lavrenov 已提交
3957 3958
#endif

3959
    for( int i = 0; i < n; i++ )
3960 3961 3962 3963
    {
        T* ptr = bptr;
        if( sortRows )
        {
3964
            T* dptr = dst.ptr<T>(i);
3965 3966
            if( !inplace )
            {
3967
                const T* sptr = src.ptr<T>(i);
I
Ilya Lavrenov 已提交
3968
                memcpy(dptr, sptr, sizeof(T) * len);
3969 3970 3971 3972 3973
            }
            ptr = dptr;
        }
        else
        {
3974
            for( int j = 0; j < len; j++ )
3975
                ptr[j] = src.ptr<T>(j)[i];
3976
        }
I
Ilya Lavrenov 已提交
3977

I
Ilya Lavrenov 已提交
3978
#ifdef USE_IPP_SORT
3979
        if (!ippSortFunc || CV_INSTRUMENT_FUN_IPP(ippSortFunc, ptr, len) < 0)
I
Ilya Lavrenov 已提交
3980 3981
#endif
        {
I
Ilya Lavrenov 已提交
3982
#ifdef USE_IPP_SORT
I
Ilya Lavrenov 已提交
3983
            if (depth == CV_8U)
3984
                setIppErrorStatus();
I
Ilya Lavrenov 已提交
3985
#endif
I
Ilya Lavrenov 已提交
3986 3987
            std::sort( ptr, ptr + len );
            if( sortDescending )
I
Ilya Lavrenov 已提交
3988 3989
            {
#ifdef USE_IPP_SORT
3990
                if (!ippFlipFunc || CV_INSTRUMENT_FUN_IPP(ippFlipFunc, ptr, len) < 0)
I
Ilya Lavrenov 已提交
3991 3992 3993 3994 3995
#endif
                {
#ifdef USE_IPP_SORT
                    setIppErrorStatus();
#endif
3996
                    for( int j = 0; j < len/2; j++ )
I
Ilya Lavrenov 已提交
3997 3998
                        std::swap(ptr[j], ptr[len-1-j]);
                }
3999 4000 4001 4002 4003 4004
#ifdef USE_IPP_SORT
                else
                {
                    CV_IMPL_ADD(CV_IMPL_IPP);
                }
#endif
I
Ilya Lavrenov 已提交
4005
            }
I
Ilya Lavrenov 已提交
4006
        }
4007 4008 4009 4010 4011 4012
#ifdef USE_IPP_SORT
        else
        {
            CV_IMPL_ADD(CV_IMPL_IPP);
        }
#endif
I
Ilya Lavrenov 已提交
4013

4014
        if( !sortRows )
4015
            for( int j = 0; j < len; j++ )
4016
                dst.ptr<T>(j)[i] = ptr[j];
4017 4018 4019
    }
}

4020 4021 4022 4023 4024 4025 4026 4027
template<typename _Tp> class LessThanIdx
{
public:
    LessThanIdx( const _Tp* _arr ) : arr(_arr) {}
    bool operator()(int a, int b) const { return arr[a] < arr[b]; }
    const _Tp* arr;
};

P
Pavel Vlasov 已提交
4028
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
I
Ilya Lavrenov 已提交
4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048

typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(void *, int *, int);

static IppSortIndexFunc getSortIndexFunc(int depth, bool sortDescending)
{
    if (!sortDescending)
        return depth == CV_8U ? (IppSortIndexFunc)ippsSortIndexAscend_8u_I :
            depth == CV_16U ? (IppSortIndexFunc)ippsSortIndexAscend_16u_I :
            depth == CV_16S ? (IppSortIndexFunc)ippsSortIndexAscend_16s_I :
            depth == CV_32S ? (IppSortIndexFunc)ippsSortIndexAscend_32s_I :
            depth == CV_32F ? (IppSortIndexFunc)ippsSortIndexAscend_32f_I :
            depth == CV_64F ? (IppSortIndexFunc)ippsSortIndexAscend_64f_I : 0;
    else
        return depth == CV_8U ? (IppSortIndexFunc)ippsSortIndexDescend_8u_I :
            depth == CV_16U ? (IppSortIndexFunc)ippsSortIndexDescend_16u_I :
            depth == CV_16S ? (IppSortIndexFunc)ippsSortIndexDescend_16s_I :
            depth == CV_32S ? (IppSortIndexFunc)ippsSortIndexDescend_32s_I :
            depth == CV_32F ? (IppSortIndexFunc)ippsSortIndexDescend_32f_I :
            depth == CV_64F ? (IppSortIndexFunc)ippsSortIndexDescend_64f_I : 0;
}
4049

I
Ilya Lavrenov 已提交
4050
#endif
4051 4052 4053 4054 4055 4056 4057 4058 4059

template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
{
    AutoBuffer<T> buf;
    AutoBuffer<int> ibuf;
    bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
    bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;

    CV_Assert( src.data != dst.data );
4060

4061
    int n, len;
4062 4063 4064 4065 4066 4067 4068 4069
    if( sortRows )
        n = src.rows, len = src.cols;
    else
    {
        n = src.cols, len = src.rows;
        buf.allocate(len);
        ibuf.allocate(len);
    }
4070 4071
    T* bptr = (T*)buf;
    int* _iptr = (int*)ibuf;
4072

P
Pavel Vlasov 已提交
4073
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
I
Ilya Lavrenov 已提交
4074
    int depth = src.depth();
4075 4076 4077 4078 4079 4080 4081
    IppSortIndexFunc ippFunc = 0;
    IppFlipFunc ippFlipFunc = 0;
    CV_IPP_CHECK()
    {
        ippFunc = getSortIndexFunc(depth, sortDescending);
        ippFlipFunc = getFlipFunc(depth);
    }
I
Ilya Lavrenov 已提交
4082 4083
#endif

4084
    for( int i = 0; i < n; i++ )
4085 4086 4087 4088 4089 4090 4091
    {
        T* ptr = bptr;
        int* iptr = _iptr;

        if( sortRows )
        {
            ptr = (T*)(src.data + src.step*i);
4092
            iptr = dst.ptr<int>(i);
4093 4094 4095
        }
        else
        {
4096
            for( int j = 0; j < len; j++ )
4097
                ptr[j] = src.ptr<T>(j)[i];
4098
        }
4099
        for( int j = 0; j < len; j++ )
4100
            iptr[j] = j;
I
Ilya Lavrenov 已提交
4101

P
Pavel Vlasov 已提交
4102
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
I
Ilya Lavrenov 已提交
4103 4104 4105
        if (sortRows || !ippFunc || ippFunc(ptr, iptr, len) < 0)
#endif
        {
P
Pavel Vlasov 已提交
4106
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
I
Ilya Lavrenov 已提交
4107 4108
            setIppErrorStatus();
#endif
I
Ilya Lavrenov 已提交
4109 4110
            std::sort( iptr, iptr + len, LessThanIdx<T>(ptr) );
            if( sortDescending )
I
Ilya Lavrenov 已提交
4111
            {
P
Pavel Vlasov 已提交
4112
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
I
Ilya Lavrenov 已提交
4113 4114 4115
                if (!ippFlipFunc || ippFlipFunc(iptr, len) < 0)
#endif
                {
P
Pavel Vlasov 已提交
4116
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
I
Ilya Lavrenov 已提交
4117 4118
                    setIppErrorStatus();
#endif
4119
                    for( int j = 0; j < len/2; j++ )
I
Ilya Lavrenov 已提交
4120 4121
                        std::swap(iptr[j], iptr[len-1-j]);
                }
P
Pavel Vlasov 已提交
4122
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
4123 4124 4125 4126 4127
                else
                {
                    CV_IMPL_ADD(CV_IMPL_IPP);
                }
#endif
I
Ilya Lavrenov 已提交
4128
            }
I
Ilya Lavrenov 已提交
4129
        }
P
Pavel Vlasov 已提交
4130
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
4131 4132 4133 4134 4135
        else
        {
            CV_IMPL_ADD(CV_IMPL_IPP);
        }
#endif
I
Ilya Lavrenov 已提交
4136

4137
        if( !sortRows )
4138
            for( int j = 0; j < len; j++ )
4139
                dst.ptr<int>(j)[i] = iptr[j];
4140 4141 4142 4143 4144
    }
}

typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags);

4145
}
4146

4147
void cv::sort( InputArray _src, OutputArray _dst, int flags )
4148
{
4149 4150
    CV_INSTRUMENT_REGION()

4151 4152 4153 4154 4155
    static SortFunc tab[] =
    {
        sort_<uchar>, sort_<schar>, sort_<ushort>, sort_<short>,
        sort_<int>, sort_<float>, sort_<double>, 0
    };
4156
    Mat src = _src.getMat();
4157
    SortFunc func = tab[src.depth()];
V
Vadim Pisarevsky 已提交
4158
    CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 );
4159 4160
    _dst.create( src.size(), src.type() );
    Mat dst = _dst.getMat();
4161 4162 4163
    func( src, dst, flags );
}

4164
void cv::sortIdx( InputArray _src, OutputArray _dst, int flags )
4165
{
4166 4167
    CV_INSTRUMENT_REGION()

4168 4169 4170 4171 4172
    static SortFunc tab[] =
    {
        sortIdx_<uchar>, sortIdx_<schar>, sortIdx_<ushort>, sortIdx_<short>,
        sortIdx_<int>, sortIdx_<float>, sortIdx_<double>, 0
    };
4173
    Mat src = _src.getMat();
4174
    SortFunc func = tab[src.depth()];
V
Vadim Pisarevsky 已提交
4175
    CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 );
4176

4177
    Mat dst = _dst.getMat();
4178
    if( dst.data == src.data )
4179 4180 4181
        _dst.release();
    _dst.create( src.size(), CV_32S );
    dst = _dst.getMat();
4182 4183
    func( src, dst, flags );
}
4184 4185


4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209
CV_IMPL void cvSetIdentity( CvArr* arr, CvScalar value )
{
    cv::Mat m = cv::cvarrToMat(arr);
    cv::setIdentity(m, value);
}


CV_IMPL CvScalar cvTrace( const CvArr* arr )
{
    return cv::trace(cv::cvarrToMat(arr));
}


CV_IMPL void cvTranspose( const CvArr* srcarr, CvArr* dstarr )
{
    cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);

    CV_Assert( src.rows == dst.cols && src.cols == dst.rows && src.type() == dst.type() );
    transpose( src, dst );
}


CV_IMPL void cvCompleteSymm( CvMat* matrix, int LtoR )
{
A
Andrey Kamaev 已提交
4210
    cv::Mat m = cv::cvarrToMat(matrix);
4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227
    cv::completeSymm( m, LtoR != 0 );
}


CV_IMPL void cvCrossProduct( const CvArr* srcAarr, const CvArr* srcBarr, CvArr* dstarr )
{
    cv::Mat srcA = cv::cvarrToMat(srcAarr), dst = cv::cvarrToMat(dstarr);

    CV_Assert( srcA.size() == dst.size() && srcA.type() == dst.type() );
    srcA.cross(cv::cvarrToMat(srcBarr)).copyTo(dst);
}


CV_IMPL void
cvReduce( const CvArr* srcarr, CvArr* dstarr, int dim, int op )
{
    cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
4228

4229 4230 4231 4232 4233 4234 4235 4236 4237
    if( dim < 0 )
        dim = src.rows > dst.rows ? 0 : src.cols > dst.cols ? 1 : dst.cols == 1;

    if( dim > 1 )
        CV_Error( CV_StsOutOfRange, "The reduced dimensionality index is out of range" );

    if( (dim == 0 && (dst.cols != src.cols || dst.rows != 1)) ||
        (dim == 1 && (dst.rows != src.rows || dst.cols != 1)) )
        CV_Error( CV_StsBadSize, "The output array size is incorrect" );
4238

4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249
    if( src.channels() != dst.channels() )
        CV_Error( CV_StsUnmatchedFormats, "Input and output arrays must have the same number of channels" );

    cv::reduce(src, dst, dim, op, dst.type());
}


CV_IMPL CvArr*
cvRange( CvArr* arr, double start, double end )
{
    CvMat stub, *mat = (CvMat*)arr;
4250
    int step;
4251
    double val = start;
4252

4253 4254 4255
    if( !CV_IS_MAT(mat) )
        mat = cvGetMat( mat, &stub);

4256 4257 4258 4259
    int rows = mat->rows;
    int cols = mat->cols;
    int type = CV_MAT_TYPE(mat->type);
    double delta = (end-start)/(rows*cols);
4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277

    if( CV_IS_MAT_CONT(mat->type) )
    {
        cols *= rows;
        rows = 1;
        step = 1;
    }
    else
        step = mat->step / CV_ELEM_SIZE(type);

    if( type == CV_32SC1 )
    {
        int* idata = mat->data.i;
        int ival = cvRound(val), idelta = cvRound(delta);

        if( fabs(val - ival) < DBL_EPSILON &&
            fabs(delta - idelta) < DBL_EPSILON )
        {
4278 4279
            for( int i = 0; i < rows; i++, idata += step )
                for( int j = 0; j < cols; j++, ival += idelta )
4280 4281 4282 4283
                    idata[j] = ival;
        }
        else
        {
4284 4285
            for( int i = 0; i < rows; i++, idata += step )
                for( int j = 0; j < cols; j++, val += delta )
4286 4287 4288 4289 4290 4291
                    idata[j] = cvRound(val);
        }
    }
    else if( type == CV_32FC1 )
    {
        float* fdata = mat->data.fl;
4292 4293
        for( int i = 0; i < rows; i++, fdata += step )
            for( int j = 0; j < cols; j++, val += delta )
4294 4295 4296 4297 4298
                fdata[j] = (float)val;
    }
    else
        CV_Error( CV_StsUnsupportedFormat, "The function only supports 32sC1 and 32fC1 datatypes" );

4299
    return arr;
4300 4301 4302 4303 4304 4305
}


CV_IMPL void
cvSort( const CvArr* _src, CvArr* _dst, CvArr* _idx, int flags )
{
A
Andrey Kamaev 已提交
4306
    cv::Mat src = cv::cvarrToMat(_src);
4307

4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332
    if( _idx )
    {
        cv::Mat idx0 = cv::cvarrToMat(_idx), idx = idx0;
        CV_Assert( src.size() == idx.size() && idx.type() == CV_32S && src.data != idx.data );
        cv::sortIdx( src, idx, flags );
        CV_Assert( idx0.data == idx.data );
    }

    if( _dst )
    {
        cv::Mat dst0 = cv::cvarrToMat(_dst), dst = dst0;
        CV_Assert( src.size() == dst.size() && src.type() == dst.type() );
        cv::sort( src, dst, flags );
        CV_Assert( dst0.data == dst.data );
    }
}


CV_IMPL int
cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels,
           CvTermCriteria termcrit, int attempts, CvRNG*,
           int flags, CvArr* _centers, double* _compactness )
{
    cv::Mat data = cv::cvarrToMat(_samples), labels = cv::cvarrToMat(_labels), centers;
    if( _centers )
4333
    {
4334
        centers = cv::cvarrToMat(_centers);
M
Maria Dimashova 已提交
4335

4336
        centers = centers.reshape(1);
M
Maria Dimashova 已提交
4337 4338 4339 4340 4341 4342
        data = data.reshape(1);

        CV_Assert( !centers.empty() );
        CV_Assert( centers.rows == cluster_count );
        CV_Assert( centers.cols == data.cols );
        CV_Assert( centers.depth() == data.depth() );
4343
    }
4344 4345 4346
    CV_Assert( labels.isContinuous() && labels.type() == CV_32S &&
        (labels.cols == 1 || labels.rows == 1) &&
        labels.cols + labels.rows - 1 == data.rows );
4347

4348
    double compactness = cv::kmeans(data, cluster_count, labels, termcrit, attempts,
4349
                                    flags, _centers ? cv::_OutputArray(centers) : cv::_OutputArray() );
4350 4351 4352 4353 4354 4355 4356 4357 4358 4359
    if( _compactness )
        *_compactness = compactness;
    return 1;
}

///////////////////////////// n-dimensional matrices ////////////////////////////

namespace cv
{

4360
Mat Mat::reshape(int _cn, int _newndims, const int* _newsz) const
4361
{
4362 4363 4364 4365 4366 4367 4368 4369
    if(_newndims == dims)
    {
        if(_newsz == 0)
            return reshape(_cn);
        if(_newndims == 2)
            return reshape(_cn, _newsz[0]);
    }

4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408
    if (isContinuous())
    {
        CV_Assert(_cn >= 0 && _newndims > 0 && _newndims <= CV_MAX_DIM && _newsz);

        if (_cn == 0)
            _cn = this->channels();
        else
            CV_Assert(_cn <= CV_CN_MAX);

        size_t total_elem1_ref = this->total() * this->channels();
        size_t total_elem1 = _cn;

        AutoBuffer<int, 4> newsz_buf( (size_t)_newndims );

        for (int i = 0; i < _newndims; i++)
        {
            CV_Assert(_newsz[i] >= 0);

            if (_newsz[i] > 0)
                newsz_buf[i] = _newsz[i];
            else if (i < dims)
                newsz_buf[i] = this->size[i];
            else
                CV_Error(CV_StsOutOfRange, "Copy dimension (which has zero size) is not present in source matrix");

            total_elem1 *= (size_t)newsz_buf[i];
        }

        if (total_elem1 != total_elem1_ref)
            CV_Error(CV_StsUnmatchedSizes, "Requested and source matrices have different count of elements");

        Mat hdr = *this;
        hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((_cn-1) << CV_CN_SHIFT);
        setSize(hdr, _newndims, (int*)newsz_buf, NULL, true);

        return hdr;
    }

    CV_Error(CV_StsNotImplemented, "Reshaping of n-dimensional non-continuous matrices is not supported yet");
V
Vadim Pisarevsky 已提交
4409 4410 4411
    // TBD
    return Mat();
}
4412

V
Vadim Pisarevsky 已提交
4413
NAryMatIterator::NAryMatIterator()
4414
    : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
V
Vadim Pisarevsky 已提交
4415 4416
{
}
4417

V
Vadim Pisarevsky 已提交
4418
NAryMatIterator::NAryMatIterator(const Mat** _arrays, Mat* _planes, int _narrays)
4419 4420 4421
: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
{
    init(_arrays, _planes, 0, _narrays);
4422 4423
}

4424 4425
NAryMatIterator::NAryMatIterator(const Mat** _arrays, uchar** _ptrs, int _narrays)
    : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
V
Vadim Pisarevsky 已提交
4426
{
4427
    init(_arrays, 0, _ptrs, _narrays);
V
Vadim Pisarevsky 已提交
4428
}
4429

4430
void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, uchar** _ptrs, int _narrays)
V
Vadim Pisarevsky 已提交
4431
{
4432 4433
    CV_Assert( _arrays && (_ptrs || _planes) );
    int i, j, d1=0, i0 = -1, d = -1;
4434

V
Vadim Pisarevsky 已提交
4435
    arrays = _arrays;
4436
    ptrs = _ptrs;
V
Vadim Pisarevsky 已提交
4437 4438 4439
    planes = _planes;
    narrays = _narrays;
    nplanes = 0;
4440
    size = 0;
4441

V
Vadim Pisarevsky 已提交
4442
    if( narrays < 0 )
4443
    {
V
Vadim Pisarevsky 已提交
4444 4445 4446 4447
        for( i = 0; _arrays[i] != 0; i++ )
            ;
        narrays = i;
        CV_Assert(narrays <= 1000);
4448
    }
V
Vadim Pisarevsky 已提交
4449 4450 4451 4452

    iterdepth = 0;

    for( i = 0; i < narrays; i++ )
4453
    {
V
Vadim Pisarevsky 已提交
4454 4455
        CV_Assert(arrays[i] != 0);
        const Mat& A = *arrays[i];
4456 4457
        if( ptrs )
            ptrs[i] = A.data;
4458

4459 4460
        if( !A.data )
            continue;
4461

V
Vadim Pisarevsky 已提交
4462
        if( i0 < 0 )
4463
        {
V
Vadim Pisarevsky 已提交
4464 4465
            i0 = i;
            d = A.dims;
4466

V
Vadim Pisarevsky 已提交
4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482
            // find the first dimensionality which is different from 1;
            // in any of the arrays the first "d1" step do not affect the continuity
            for( d1 = 0; d1 < d; d1++ )
                if( A.size[d1] > 1 )
                    break;
        }
        else
            CV_Assert( A.size == arrays[i0]->size );

        if( !A.isContinuous() )
        {
            CV_Assert( A.step[d-1] == A.elemSize() );
            for( j = d-1; j > d1; j-- )
                if( A.step[j]*A.size[j] < A.step[j-1] )
                    break;
            iterdepth = std::max(iterdepth, j);
4483 4484
        }
    }
V
Vadim Pisarevsky 已提交
4485 4486

    if( i0 >= 0 )
4487
    {
4488
        size = arrays[i0]->size[d-1];
V
Vadim Pisarevsky 已提交
4489 4490
        for( j = d-1; j > iterdepth; j-- )
        {
4491
            int64 total1 = (int64)size*arrays[i0]->size[j-1];
V
Vadim Pisarevsky 已提交
4492 4493
            if( total1 != (int)total1 )
                break;
4494
            size = (int)total1;
V
Vadim Pisarevsky 已提交
4495 4496 4497 4498 4499
        }

        iterdepth = j;
        if( iterdepth == d1 )
            iterdepth = 0;
4500

V
Vadim Pisarevsky 已提交
4501 4502 4503
        nplanes = 1;
        for( j = iterdepth-1; j >= 0; j-- )
            nplanes *= arrays[i0]->size[j];
4504
    }
V
Vadim Pisarevsky 已提交
4505
    else
4506
        iterdepth = 0;
4507

4508
    idx = 0;
4509

4510 4511
    if( !planes )
        return;
4512

V
Vadim Pisarevsky 已提交
4513
    for( i = 0; i < narrays; i++ )
4514
    {
4515 4516
        CV_Assert(arrays[i] != 0);
        const Mat& A = *arrays[i];
4517

4518
        if( !A.data )
V
Vadim Pisarevsky 已提交
4519 4520 4521 4522
        {
            planes[i] = Mat();
            continue;
        }
4523 4524

        planes[i] = Mat(1, (int)size, A.type(), A.data);
4525 4526 4527
    }
}

V
Vadim Pisarevsky 已提交
4528 4529

NAryMatIterator& NAryMatIterator::operator ++()
4530 4531 4532 4533
{
    if( idx >= nplanes-1 )
        return *this;
    ++idx;
4534

4535
    if( iterdepth == 1 )
4536
    {
4537 4538 4539 4540 4541 4542 4543 4544 4545 4546
        if( ptrs )
        {
            for( int i = 0; i < narrays; i++ )
            {
                if( !ptrs[i] )
                    continue;
                ptrs[i] = arrays[i]->data + arrays[i]->step[0]*idx;
            }
        }
        if( planes )
4547
        {
4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562
            for( int i = 0; i < narrays; i++ )
            {
                if( !planes[i].data )
                    continue;
                planes[i].data = arrays[i]->data + arrays[i]->step[0]*idx;
            }
        }
    }
    else
    {
        for( int i = 0; i < narrays; i++ )
        {
            const Mat& A = *arrays[i];
            if( !A.data )
                continue;
4563
            int _idx = (int)idx;
4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574
            uchar* data = A.data;
            for( int j = iterdepth-1; j >= 0 && _idx > 0; j-- )
            {
                int szi = A.size[j], t = _idx/szi;
                data += (_idx - t * szi)*A.step[j];
                _idx = t;
            }
            if( ptrs )
                ptrs[i] = data;
            if( planes )
                planes[i].data = data;
4575 4576
        }
    }
4577

4578 4579 4580
    return *this;
}

V
Vadim Pisarevsky 已提交
4581
NAryMatIterator NAryMatIterator::operator ++(int)
4582
{
V
Vadim Pisarevsky 已提交
4583
    NAryMatIterator it = *this;
4584 4585 4586 4587
    ++*this;
    return it;
}

V
Vadim Pisarevsky 已提交
4588 4589 4590
///////////////////////////////////////////////////////////////////////////
//                              MatConstIterator                         //
///////////////////////////////////////////////////////////////////////////
4591

V
Vadim Pisarevsky 已提交
4592
Point MatConstIterator::pos() const
4593
{
V
Vadim Pisarevsky 已提交
4594 4595 4596
    if( !m )
        return Point();
    CV_DbgAssert(m->dims <= 2);
4597

4598
    ptrdiff_t ofs = ptr - m->ptr();
V
Vadim Pisarevsky 已提交
4599 4600
    int y = (int)(ofs/m->step[0]);
    return Point((int)((ofs - y*m->step[0])/elemSize), y);
4601 4602
}

V
Vadim Pisarevsky 已提交
4603
void MatConstIterator::pos(int* _idx) const
4604
{
V
Vadim Pisarevsky 已提交
4605
    CV_Assert(m != 0 && _idx);
4606
    ptrdiff_t ofs = ptr - m->ptr();
V
Vadim Pisarevsky 已提交
4607
    for( int i = 0; i < m->dims; i++ )
4608
    {
V
Vadim Pisarevsky 已提交
4609 4610 4611
        size_t s = m->step[i], v = ofs/s;
        ofs -= v*s;
        _idx[i] = (int)v;
4612 4613 4614
    }
}

V
Vadim Pisarevsky 已提交
4615
ptrdiff_t MatConstIterator::lpos() const
4616
{
V
Vadim Pisarevsky 已提交
4617 4618 4619 4620
    if(!m)
        return 0;
    if( m->isContinuous() )
        return (ptr - sliceStart)/elemSize;
4621
    ptrdiff_t ofs = ptr - m->ptr();
V
Vadim Pisarevsky 已提交
4622 4623
    int i, d = m->dims;
    if( d == 2 )
4624
    {
V
Vadim Pisarevsky 已提交
4625 4626
        ptrdiff_t y = ofs/m->step[0];
        return y*m->cols + (ofs - y*m->step[0])/elemSize;
4627
    }
V
Vadim Pisarevsky 已提交
4628 4629
    ptrdiff_t result = 0;
    for( i = 0; i < d; i++ )
4630
    {
V
Vadim Pisarevsky 已提交
4631 4632 4633
        size_t s = m->step[i], v = ofs/s;
        ofs -= v*s;
        result = result*m->size[i] + v;
4634
    }
V
Vadim Pisarevsky 已提交
4635
    return result;
4636
}
4637

V
Vadim Pisarevsky 已提交
4638
void MatConstIterator::seek(ptrdiff_t ofs, bool relative)
4639
{
V
Vadim Pisarevsky 已提交
4640
    if( m->isContinuous() )
4641
    {
V
Vadim Pisarevsky 已提交
4642 4643 4644 4645 4646 4647
        ptr = (relative ? ptr : sliceStart) + ofs*elemSize;
        if( ptr < sliceStart )
            ptr = sliceStart;
        else if( ptr > sliceEnd )
            ptr = sliceEnd;
        return;
4648
    }
4649

V
Vadim Pisarevsky 已提交
4650 4651
    int d = m->dims;
    if( d == 2 )
4652
    {
V
Vadim Pisarevsky 已提交
4653 4654
        ptrdiff_t ofs0, y;
        if( relative )
4655
        {
4656
            ofs0 = ptr - m->ptr();
V
Vadim Pisarevsky 已提交
4657 4658
            y = ofs0/m->step[0];
            ofs += y*m->cols + (ofs0 - y*m->step[0])/elemSize;
4659
        }
V
Vadim Pisarevsky 已提交
4660 4661
        y = ofs/m->cols;
        int y1 = std::min(std::max((int)y, 0), m->rows-1);
4662
        sliceStart = m->ptr(y1);
4663
        sliceEnd = sliceStart + m->cols*elemSize;
V
Vadim Pisarevsky 已提交
4664 4665 4666
        ptr = y < 0 ? sliceStart : y >= m->rows ? sliceEnd :
            sliceStart + (ofs - y*m->cols)*elemSize;
        return;
4667
    }
4668

V
Vadim Pisarevsky 已提交
4669 4670
    if( relative )
        ofs += lpos();
4671

V
Vadim Pisarevsky 已提交
4672 4673
    if( ofs < 0 )
        ofs = 0;
4674

V
Vadim Pisarevsky 已提交
4675 4676 4677 4678
    int szi = m->size[d-1];
    ptrdiff_t t = ofs/szi;
    int v = (int)(ofs - t*szi);
    ofs = t;
4679 4680
    ptr = m->ptr() + v*elemSize;
    sliceStart = m->ptr();
4681

V
Vadim Pisarevsky 已提交
4682
    for( int i = d-2; i >= 0; i-- )
4683
    {
V
Vadim Pisarevsky 已提交
4684 4685 4686 4687 4688
        szi = m->size[i];
        t = ofs/szi;
        v = (int)(ofs - t*szi);
        ofs = t;
        sliceStart += v*m->step[i];
4689
    }
4690

V
Vadim Pisarevsky 已提交
4691 4692 4693 4694
    sliceEnd = sliceStart + m->size[d-1]*elemSize;
    if( ofs > 0 )
        ptr = sliceEnd;
    else
4695
        ptr = sliceStart + (ptr - m->ptr());
4696
}
4697

V
Vadim Pisarevsky 已提交
4698 4699
void MatConstIterator::seek(const int* _idx, bool relative)
{
4700
    int d = m->dims;
V
Vadim Pisarevsky 已提交
4701 4702 4703 4704 4705 4706
    ptrdiff_t ofs = 0;
    if( !_idx )
        ;
    else if( d == 2 )
        ofs = _idx[0]*m->size[1] + _idx[1];
    else
4707
    {
4708
        for( int i = 0; i < d; i++ )
V
Vadim Pisarevsky 已提交
4709
            ofs = ofs*m->size[i] + _idx[i];
4710
    }
V
Vadim Pisarevsky 已提交
4711
    seek(ofs, relative);
4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739
}

//////////////////////////////// SparseMat ////////////////////////////////

template<typename T1, typename T2> void
convertData_(const void* _from, void* _to, int cn)
{
    const T1* from = (const T1*)_from;
    T2* to = (T2*)_to;
    if( cn == 1 )
        *to = saturate_cast<T2>(*from);
    else
        for( int i = 0; i < cn; i++ )
            to[i] = saturate_cast<T2>(from[i]);
}

template<typename T1, typename T2> void
convertScaleData_(const void* _from, void* _to, int cn, double alpha, double beta)
{
    const T1* from = (const T1*)_from;
    T2* to = (T2*)_to;
    if( cn == 1 )
        *to = saturate_cast<T2>(*from*alpha + beta);
    else
        for( int i = 0; i < cn; i++ )
            to[i] = saturate_cast<T2>(from[i]*alpha + beta);
}

A
Andrey Kamaev 已提交
4740 4741 4742 4743
typedef void (*ConvertData)(const void* from, void* to, int cn);
typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alpha, double beta);

static ConvertData getConvertElem(int fromType, int toType)
4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787
{
    static ConvertData tab[][8] =
    {{ convertData_<uchar, uchar>, convertData_<uchar, schar>,
      convertData_<uchar, ushort>, convertData_<uchar, short>,
      convertData_<uchar, int>, convertData_<uchar, float>,
      convertData_<uchar, double>, 0 },

    { convertData_<schar, uchar>, convertData_<schar, schar>,
      convertData_<schar, ushort>, convertData_<schar, short>,
      convertData_<schar, int>, convertData_<schar, float>,
      convertData_<schar, double>, 0 },

    { convertData_<ushort, uchar>, convertData_<ushort, schar>,
      convertData_<ushort, ushort>, convertData_<ushort, short>,
      convertData_<ushort, int>, convertData_<ushort, float>,
      convertData_<ushort, double>, 0 },

    { convertData_<short, uchar>, convertData_<short, schar>,
      convertData_<short, ushort>, convertData_<short, short>,
      convertData_<short, int>, convertData_<short, float>,
      convertData_<short, double>, 0 },

    { convertData_<int, uchar>, convertData_<int, schar>,
      convertData_<int, ushort>, convertData_<int, short>,
      convertData_<int, int>, convertData_<int, float>,
      convertData_<int, double>, 0 },

    { convertData_<float, uchar>, convertData_<float, schar>,
      convertData_<float, ushort>, convertData_<float, short>,
      convertData_<float, int>, convertData_<float, float>,
      convertData_<float, double>, 0 },

    { convertData_<double, uchar>, convertData_<double, schar>,
      convertData_<double, ushort>, convertData_<double, short>,
      convertData_<double, int>, convertData_<double, float>,
      convertData_<double, double>, 0 },

    { 0, 0, 0, 0, 0, 0, 0, 0 }};

    ConvertData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)];
    CV_Assert( func != 0 );
    return func;
}

A
Andrey Kamaev 已提交
4788
static ConvertScaleData getConvertScaleElem(int fromType, int toType)
4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837
{
    static ConvertScaleData tab[][8] =
    {{ convertScaleData_<uchar, uchar>, convertScaleData_<uchar, schar>,
      convertScaleData_<uchar, ushort>, convertScaleData_<uchar, short>,
      convertScaleData_<uchar, int>, convertScaleData_<uchar, float>,
      convertScaleData_<uchar, double>, 0 },

    { convertScaleData_<schar, uchar>, convertScaleData_<schar, schar>,
      convertScaleData_<schar, ushort>, convertScaleData_<schar, short>,
      convertScaleData_<schar, int>, convertScaleData_<schar, float>,
      convertScaleData_<schar, double>, 0 },

    { convertScaleData_<ushort, uchar>, convertScaleData_<ushort, schar>,
      convertScaleData_<ushort, ushort>, convertScaleData_<ushort, short>,
      convertScaleData_<ushort, int>, convertScaleData_<ushort, float>,
      convertScaleData_<ushort, double>, 0 },

    { convertScaleData_<short, uchar>, convertScaleData_<short, schar>,
      convertScaleData_<short, ushort>, convertScaleData_<short, short>,
      convertScaleData_<short, int>, convertScaleData_<short, float>,
      convertScaleData_<short, double>, 0 },

    { convertScaleData_<int, uchar>, convertScaleData_<int, schar>,
      convertScaleData_<int, ushort>, convertScaleData_<int, short>,
      convertScaleData_<int, int>, convertScaleData_<int, float>,
      convertScaleData_<int, double>, 0 },

    { convertScaleData_<float, uchar>, convertScaleData_<float, schar>,
      convertScaleData_<float, ushort>, convertScaleData_<float, short>,
      convertScaleData_<float, int>, convertScaleData_<float, float>,
      convertScaleData_<float, double>, 0 },

    { convertScaleData_<double, uchar>, convertScaleData_<double, schar>,
      convertScaleData_<double, ushort>, convertScaleData_<double, short>,
      convertScaleData_<double, int>, convertScaleData_<double, float>,
      convertScaleData_<double, double>, 0 },

    { 0, 0, 0, 0, 0, 0, 0, 0 }};

    ConvertScaleData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)];
    CV_Assert( func != 0 );
    return func;
}

enum { HASH_SIZE0 = 8 };

static inline void copyElem(const uchar* from, uchar* to, size_t elemSize)
{
    size_t i;
4838
    for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) )
4839 4840 4841 4842 4843 4844 4845 4846
        *(int*)(to + i) = *(const int*)(from + i);
    for( ; i < elemSize; i++ )
        to[i] = from[i];
}

static inline bool isZeroElem(const uchar* data, size_t elemSize)
{
    size_t i;
4847
    for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) )
4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860
        if( *(int*)(data + i) != 0 )
            return false;
    for( ; i < elemSize; i++ )
        if( data[i] != 0 )
            return false;
    return true;
}

SparseMat::Hdr::Hdr( int _dims, const int* _sizes, int _type )
{
    refcount = 1;

    dims = _dims;
4861 4862
    valueOffset = (int)alignSize(sizeof(SparseMat::Node) - MAX_DIM*sizeof(int) +
                                 dims*sizeof(int), CV_ELEM_SIZE1(_type));
4863 4864
    nodeSize = alignSize(valueOffset +
        CV_ELEM_SIZE(_type), (int)sizeof(size_t));
4865

4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883
    int i;
    for( i = 0; i < dims; i++ )
        size[i] = _sizes[i];
    for( ; i < CV_MAX_DIM; i++ )
        size[i] = 0;
    clear();
}

void SparseMat::Hdr::clear()
{
    hashtab.clear();
    hashtab.resize(HASH_SIZE0);
    pool.clear();
    pool.resize(nodeSize);
    nodeCount = freeList = 0;
}


V
Vadim Pisarevsky 已提交
4884
SparseMat::SparseMat(const Mat& m)
4885 4886 4887 4888 4889 4890
: flags(MAGIC_VAL), hdr(0)
{
    create( m.dims, m.size, m.type() );

    int i, idx[CV_MAX_DIM] = {0}, d = m.dims, lastSize = m.size[d - 1];
    size_t esz = m.elemSize();
4891
    const uchar* dptr = m.ptr();
4892 4893 4894

    for(;;)
    {
A
Andrey Kamaev 已提交
4895
        for( i = 0; i < lastSize; i++, dptr += esz )
4896
        {
A
Andrey Kamaev 已提交
4897
            if( isZeroElem(dptr, esz) )
4898 4899 4900
                continue;
            idx[d-1] = i;
            uchar* to = newNode(idx, hash(idx));
A
Andrey Kamaev 已提交
4901
            copyElem( dptr, to, esz );
4902
        }
4903

4904 4905
        for( i = d - 2; i >= 0; i-- )
        {
A
Andrey Kamaev 已提交
4906
            dptr += m.step[i] - m.size[i+1]*m.step[i+1];
4907 4908 4909 4910 4911 4912 4913 4914
            if( ++idx[i] < m.size[i] )
                break;
            idx[i] = 0;
        }
        if( i < 0 )
            break;
    }
}
4915

4916 4917 4918
void SparseMat::create(int d, const int* _sizes, int _type)
{
    CV_Assert( _sizes && 0 < d && d <= CV_MAX_DIM );
4919
    for( int i = 0; i < d; i++ )
4920 4921 4922 4923
        CV_Assert( _sizes[i] > 0 );
    _type = CV_MAT_TYPE(_type);
    if( hdr && _type == type() && hdr->dims == d && hdr->refcount == 1 )
    {
4924
        int i;
4925 4926 4927 4928 4929 4930 4931 4932 4933
        for( i = 0; i < d; i++ )
            if( _sizes[i] != hdr->size[i] )
                break;
        if( i == d )
        {
            clear();
            return;
        }
    }
4934 4935 4936
    int _sizes_backup[CV_MAX_DIM]; // #5991
    if (_sizes == hdr->size)
    {
4937
        for(int i = 0; i < d; i++ )
4938 4939 4940
            _sizes_backup[i] = _sizes[i];
        _sizes = _sizes_backup;
    }
4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956
    release();
    flags = MAGIC_VAL | _type;
    hdr = new Hdr(d, _sizes, _type);
}

void SparseMat::copyTo( SparseMat& m ) const
{
    if( hdr == m.hdr )
        return;
    if( !hdr )
    {
        m.release();
        return;
    }
    m.create( hdr->dims, hdr->size, type() );
    SparseMatConstIterator from = begin();
4957
    size_t N = nzcount(), esz = elemSize();
4958

4959
    for( size_t i = 0; i < N; i++, ++from )
4960 4961 4962 4963 4964 4965 4966 4967 4968 4969
    {
        const Node* n = from.node();
        uchar* to = m.newNode(n->idx, n->hashval);
        copyElem( from.ptr, to, esz );
    }
}

void SparseMat::copyTo( Mat& m ) const
{
    CV_Assert( hdr );
4970 4971
    int ndims = dims();
    m.create( ndims, hdr->size, type() );
4972 4973 4974
    m = Scalar(0);

    SparseMatConstIterator from = begin();
4975
    size_t N = nzcount(), esz = elemSize();
4976

4977
    for( size_t i = 0; i < N; i++, ++from )
4978 4979
    {
        const Node* n = from.node();
4980
        copyElem( from.ptr, (ndims > 1 ? m.ptr(n->idx) : m.ptr(n->idx[0])), esz);
4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997
    }
}


void SparseMat::convertTo( SparseMat& m, int rtype, double alpha ) const
{
    int cn = channels();
    if( rtype < 0 )
        rtype = type();
    rtype = CV_MAKETYPE(rtype, cn);
    if( hdr == m.hdr && rtype != type()  )
    {
        SparseMat temp;
        convertTo(temp, rtype, alpha);
        m = temp;
        return;
    }
4998

4999 5000 5001
    CV_Assert(hdr != 0);
    if( hdr != m.hdr )
        m.create( hdr->dims, hdr->size, rtype );
5002

5003
    SparseMatConstIterator from = begin();
5004
    size_t N = nzcount();
5005 5006 5007

    if( alpha == 1 )
    {
5008
        ConvertData cvtfunc = getConvertElem(type(), rtype);
5009
        for( size_t i = 0; i < N; i++, ++from )
5010 5011 5012
        {
            const Node* n = from.node();
            uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval);
5013
            cvtfunc( from.ptr, to, cn );
5014 5015 5016 5017
        }
    }
    else
    {
5018
        ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype);
5019
        for( size_t i = 0; i < N; i++, ++from )
5020 5021 5022
        {
            const Node* n = from.node();
            uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval);
5023
            cvtfunc( from.ptr, to, cn, alpha, 0 );
5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034
        }
    }
}


void SparseMat::convertTo( Mat& m, int rtype, double alpha, double beta ) const
{
    int cn = channels();
    if( rtype < 0 )
        rtype = type();
    rtype = CV_MAKETYPE(rtype, cn);
5035

5036 5037 5038 5039 5040
    CV_Assert( hdr );
    m.create( dims(), hdr->size, rtype );
    m = Scalar(beta);

    SparseMatConstIterator from = begin();
5041
    size_t N = nzcount();
5042 5043 5044

    if( alpha == 1 && beta == 0 )
    {
5045
        ConvertData cvtfunc = getConvertElem(type(), rtype);
5046
        for( size_t i = 0; i < N; i++, ++from )
5047 5048 5049 5050 5051 5052 5053 5054
        {
            const Node* n = from.node();
            uchar* to = m.ptr(n->idx);
            cvtfunc( from.ptr, to, cn );
        }
    }
    else
    {
5055
        ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype);
5056
        for( size_t i = 0; i < N; i++, ++from )
5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070
        {
            const Node* n = from.node();
            uchar* to = m.ptr(n->idx);
            cvtfunc( from.ptr, to, cn, alpha, beta );
        }
    }
}

void SparseMat::clear()
{
    if( hdr )
        hdr->clear();
}

5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083
uchar* SparseMat::ptr(int i0, bool createMissing, size_t* hashval)
{
    CV_Assert( hdr && hdr->dims == 1 );
    size_t h = hashval ? *hashval : hash(i0);
    size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
    uchar* pool = &hdr->pool[0];
    while( nidx != 0 )
    {
        Node* elem = (Node*)(pool + nidx);
        if( elem->hashval == h && elem->idx[0] == i0 )
            return &value<uchar>(elem);
        nidx = elem->next;
    }
5084

5085 5086 5087 5088 5089
    if( createMissing )
    {
        int idx[] = { i0 };
        return newNode( idx, h );
    }
5090
    return NULL;
5091
}
5092

5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111
uchar* SparseMat::ptr(int i0, int i1, bool createMissing, size_t* hashval)
{
    CV_Assert( hdr && hdr->dims == 2 );
    size_t h = hashval ? *hashval : hash(i0, i1);
    size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
    uchar* pool = &hdr->pool[0];
    while( nidx != 0 )
    {
        Node* elem = (Node*)(pool + nidx);
        if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 )
            return &value<uchar>(elem);
        nidx = elem->next;
    }

    if( createMissing )
    {
        int idx[] = { i0, i1 };
        return newNode( idx, h );
    }
5112
    return NULL;
5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134
}

uchar* SparseMat::ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval)
{
    CV_Assert( hdr && hdr->dims == 3 );
    size_t h = hashval ? *hashval : hash(i0, i1, i2);
    size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
    uchar* pool = &hdr->pool[0];
    while( nidx != 0 )
    {
        Node* elem = (Node*)(pool + nidx);
        if( elem->hashval == h && elem->idx[0] == i0 &&
            elem->idx[1] == i1 && elem->idx[2] == i2 )
            return &value<uchar>(elem);
        nidx = elem->next;
    }

    if( createMissing )
    {
        int idx[] = { i0, i1, i2 };
        return newNode( idx, h );
    }
5135
    return NULL;
5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158
}

uchar* SparseMat::ptr(const int* idx, bool createMissing, size_t* hashval)
{
    CV_Assert( hdr );
    int i, d = hdr->dims;
    size_t h = hashval ? *hashval : hash(idx);
    size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
    uchar* pool = &hdr->pool[0];
    while( nidx != 0 )
    {
        Node* elem = (Node*)(pool + nidx);
        if( elem->hashval == h )
        {
            for( i = 0; i < d; i++ )
                if( elem->idx[i] != idx[i] )
                    break;
            if( i == d )
                return &value<uchar>(elem);
        }
        nidx = elem->next;
    }

5159
    return createMissing ? newNode(idx, h) : NULL;
5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230
}

void SparseMat::erase(int i0, int i1, size_t* hashval)
{
    CV_Assert( hdr && hdr->dims == 2 );
    size_t h = hashval ? *hashval : hash(i0, i1);
    size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0;
    uchar* pool = &hdr->pool[0];
    while( nidx != 0 )
    {
        Node* elem = (Node*)(pool + nidx);
        if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 )
            break;
        previdx = nidx;
        nidx = elem->next;
    }

    if( nidx )
        removeNode(hidx, nidx, previdx);
}

void SparseMat::erase(int i0, int i1, int i2, size_t* hashval)
{
    CV_Assert( hdr && hdr->dims == 3 );
    size_t h = hashval ? *hashval : hash(i0, i1, i2);
    size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0;
    uchar* pool = &hdr->pool[0];
    while( nidx != 0 )
    {
        Node* elem = (Node*)(pool + nidx);
        if( elem->hashval == h && elem->idx[0] == i0 &&
            elem->idx[1] == i1 && elem->idx[2] == i2 )
            break;
        previdx = nidx;
        nidx = elem->next;
    }

    if( nidx )
        removeNode(hidx, nidx, previdx);
}

void SparseMat::erase(const int* idx, size_t* hashval)
{
    CV_Assert( hdr );
    int i, d = hdr->dims;
    size_t h = hashval ? *hashval : hash(idx);
    size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0;
    uchar* pool = &hdr->pool[0];
    while( nidx != 0 )
    {
        Node* elem = (Node*)(pool + nidx);
        if( elem->hashval == h )
        {
            for( i = 0; i < d; i++ )
                if( elem->idx[i] != idx[i] )
                    break;
            if( i == d )
                break;
        }
        previdx = nidx;
        nidx = elem->next;
    }

    if( nidx )
        removeNode(hidx, nidx, previdx);
}

void SparseMat::resizeHashTab(size_t newsize)
{
    newsize = std::max(newsize, (size_t)8);
    if((newsize & (newsize-1)) != 0)
5231
        newsize = (size_t)1 << cvCeil(std::log((double)newsize)/CV_LOG2);
5232

5233
    size_t hsize = hdr->hashtab.size();
5234
    std::vector<size_t> _newh(newsize);
5235
    size_t* newh = &_newh[0];
5236
    for( size_t i = 0; i < newsize; i++ )
5237 5238
        newh[i] = 0;
    uchar* pool = &hdr->pool[0];
5239
    for( size_t i = 0; i < hsize; i++ )
5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264
    {
        size_t nidx = hdr->hashtab[i];
        while( nidx )
        {
            Node* elem = (Node*)(pool + nidx);
            size_t next = elem->next;
            size_t newhidx = elem->hashval & (newsize - 1);
            elem->next = newh[newhidx];
            newh[newhidx] = nidx;
            nidx = next;
        }
    }
    hdr->hashtab = _newh;
}

uchar* SparseMat::newNode(const int* idx, size_t hashval)
{
    const int HASH_MAX_FILL_FACTOR=3;
    assert(hdr);
    size_t hsize = hdr->hashtab.size();
    if( ++hdr->nodeCount > hsize*HASH_MAX_FILL_FACTOR )
    {
        resizeHashTab(std::max(hsize*2, (size_t)8));
        hsize = hdr->hashtab.size();
    }
5265

5266 5267 5268
    if( !hdr->freeList )
    {
        size_t i, nsz = hdr->nodeSize, psize = hdr->pool.size(),
5269 5270
            newpsize = std::max(psize*3/2, 8*nsz);
        newpsize = (newpsize/nsz)*nsz;
5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288
        hdr->pool.resize(newpsize);
        uchar* pool = &hdr->pool[0];
        hdr->freeList = std::max(psize, nsz);
        for( i = hdr->freeList; i < newpsize - nsz; i += nsz )
            ((Node*)(pool + i))->next = i + nsz;
        ((Node*)(pool + i))->next = 0;
    }
    size_t nidx = hdr->freeList;
    Node* elem = (Node*)&hdr->pool[nidx];
    hdr->freeList = elem->next;
    elem->hashval = hashval;
    size_t hidx = hashval & (hsize - 1);
    elem->next = hdr->hashtab[hidx];
    hdr->hashtab[hidx] = nidx;

    int i, d = hdr->dims;
    for( i = 0; i < d; i++ )
        elem->idx[i] = idx[i];
5289
    size_t esz = elemSize();
5290
    uchar* p = &value<uchar>(elem);
5291
    if( esz == sizeof(float) )
5292
        *((float*)p) = 0.f;
5293
    else if( esz == sizeof(double) )
5294 5295
        *((double*)p) = 0.;
    else
5296
        memset(p, 0, esz);
5297

5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323
    return p;
}


void SparseMat::removeNode(size_t hidx, size_t nidx, size_t previdx)
{
    Node* n = node(nidx);
    if( previdx )
    {
        Node* prev = node(previdx);
        prev->next = n->next;
    }
    else
        hdr->hashtab[hidx] = n->next;
    n->next = hdr->freeList;
    hdr->freeList = nidx;
    --hdr->nodeCount;
}


SparseMatConstIterator::SparseMatConstIterator(const SparseMat* _m)
: m((SparseMat*)_m), hashidx(0), ptr(0)
{
    if(!_m || !_m->hdr)
        return;
    SparseMat::Hdr& hdr = *m->hdr;
5324
    const std::vector<size_t>& htab = hdr.hashtab;
5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367
    size_t i, hsize = htab.size();
    for( i = 0; i < hsize; i++ )
    {
        size_t nidx = htab[i];
        if( nidx )
        {
            hashidx = i;
            ptr = &hdr.pool[nidx] + hdr.valueOffset;
            return;
        }
    }
}

SparseMatConstIterator& SparseMatConstIterator::operator ++()
{
    if( !ptr || !m || !m->hdr )
        return *this;
    SparseMat::Hdr& hdr = *m->hdr;
    size_t next = ((const SparseMat::Node*)(ptr - hdr.valueOffset))->next;
    if( next )
    {
        ptr = &hdr.pool[next] + hdr.valueOffset;
        return *this;
    }
    size_t i = hashidx + 1, sz = hdr.hashtab.size();
    for( ; i < sz; i++ )
    {
        size_t nidx = hdr.hashtab[i];
        if( nidx )
        {
            hashidx = i;
            ptr = &hdr.pool[nidx] + hdr.valueOffset;
            return *this;
        }
    }
    hashidx = sz;
    ptr = 0;
    return *this;
}


double norm( const SparseMat& src, int normType )
{
5368 5369
    CV_INSTRUMENT_REGION()

5370
    SparseMatConstIterator it = src.begin();
5371

5372 5373 5374 5375
    size_t i, N = src.nzcount();
    normType &= NORM_TYPE_MASK;
    int type = src.type();
    double result = 0;
5376

5377
    CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
5378

5379 5380 5381 5382
    if( type == CV_32F )
    {
        if( normType == NORM_INF )
            for( i = 0; i < N; i++, ++it )
5383
                result = std::max(result, std::abs((double)it.value<float>()));
5384 5385
        else if( normType == NORM_L1 )
            for( i = 0; i < N; i++, ++it )
5386
                result += std::abs(it.value<float>());
5387 5388 5389
        else
            for( i = 0; i < N; i++, ++it )
            {
5390
                double v = it.value<float>();
5391 5392 5393 5394 5395 5396 5397
                result += v*v;
            }
    }
    else if( type == CV_64F )
    {
        if( normType == NORM_INF )
            for( i = 0; i < N; i++, ++it )
5398
                result = std::max(result, std::abs(it.value<double>()));
5399 5400
        else if( normType == NORM_L1 )
            for( i = 0; i < N; i++, ++it )
5401
                result += std::abs(it.value<double>());
5402 5403 5404
        else
            for( i = 0; i < N; i++, ++it )
            {
5405
                double v = it.value<double>();
5406 5407 5408 5409 5410
                result += v*v;
            }
    }
    else
        CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" );
5411

5412 5413 5414 5415
    if( normType == NORM_L2 )
        result = std::sqrt(result);
    return result;
}
5416

5417 5418
void minMaxLoc( const SparseMat& src, double* _minval, double* _maxval, int* _minidx, int* _maxidx )
{
5419 5420
    CV_INSTRUMENT_REGION()

5421 5422 5423 5424
    SparseMatConstIterator it = src.begin();
    size_t i, N = src.nzcount(), d = src.hdr ? src.hdr->dims : 0;
    int type = src.type();
    const int *minidx = 0, *maxidx = 0;
5425

5426 5427 5428 5429 5430
    if( type == CV_32F )
    {
        float minval = FLT_MAX, maxval = -FLT_MAX;
        for( i = 0; i < N; i++, ++it )
        {
5431
            float v = it.value<float>();
5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452
            if( v < minval )
            {
                minval = v;
                minidx = it.node()->idx;
            }
            if( v > maxval )
            {
                maxval = v;
                maxidx = it.node()->idx;
            }
        }
        if( _minval )
            *_minval = minval;
        if( _maxval )
            *_maxval = maxval;
    }
    else if( type == CV_64F )
    {
        double minval = DBL_MAX, maxval = -DBL_MAX;
        for( i = 0; i < N; i++, ++it )
        {
5453
            double v = it.value<double>();
5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471
            if( v < minval )
            {
                minval = v;
                minidx = it.node()->idx;
            }
            if( v > maxval )
            {
                maxval = v;
                maxidx = it.node()->idx;
            }
        }
        if( _minval )
            *_minval = minval;
        if( _maxval )
            *_maxval = maxval;
    }
    else
        CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" );
5472

5473 5474 5475 5476 5477 5478 5479 5480
    if( _minidx )
        for( i = 0; i < d; i++ )
            _minidx[i] = minidx[i];
    if( _maxidx )
        for( i = 0; i < d; i++ )
            _maxidx[i] = maxidx[i];
}

5481

5482 5483
void normalize( const SparseMat& src, SparseMat& dst, double a, int norm_type )
{
5484 5485
    CV_INSTRUMENT_REGION()

5486 5487 5488 5489 5490 5491 5492 5493
    double scale = 1;
    if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C )
    {
        scale = norm( src, norm_type );
        scale = scale > DBL_EPSILON ? a/scale : 0.;
    }
    else
        CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" );
5494

5495 5496
    src.convertTo( dst, -1, scale );
}
5497 5498

////////////////////// RotatedRect //////////////////////
5499

5500 5501 5502 5503 5504 5505 5506
RotatedRect::RotatedRect(const Point2f& _point1, const Point2f& _point2, const Point2f& _point3)
{
    Point2f _center = 0.5f * (_point1 + _point3);
    Vec2f vecs[2];
    vecs[0] = Vec2f(_point1 - _point2);
    vecs[1] = Vec2f(_point2 - _point3);
    // check that given sides are perpendicular
R
Rohit Girdhar 已提交
5507
    CV_Assert( abs(vecs[0].dot(vecs[1])) / (norm(vecs[0]) * norm(vecs[1])) <= FLT_EPSILON );
5508 5509 5510 5511

    // wd_i stores which vector (0,1) or (1,2) will make the width
    // One of them will definitely have slope within -1 to 1
    int wd_i = 0;
R
Rohit Girdhar 已提交
5512
    if( abs(vecs[1][1]) < abs(vecs[1][0]) ) wd_i = 1;
5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523
    int ht_i = (wd_i + 1) % 2;

    float _angle = atan(vecs[wd_i][1] / vecs[wd_i][0]) * 180.0f / (float) CV_PI;
    float _width = (float) norm(vecs[wd_i]);
    float _height = (float) norm(vecs[ht_i]);

    center = _center;
    size = Size2f(_width, _height);
    angle = _angle;
}

5524 5525 5526 5527 5528
void RotatedRect::points(Point2f pt[]) const
{
    double _angle = angle*CV_PI/180.;
    float b = (float)cos(_angle)*0.5f;
    float a = (float)sin(_angle)*0.5f;
5529

5530 5531 5532 5533 5534 5535 5536 5537 5538 5539
    pt[0].x = center.x - a*size.height - b*size.width;
    pt[0].y = center.y + b*size.height - a*size.width;
    pt[1].x = center.x + a*size.height - b*size.width;
    pt[1].y = center.y - b*size.height - a*size.width;
    pt[2].x = 2*center.x - pt[0].x;
    pt[2].y = 2*center.y - pt[0].y;
    pt[3].x = 2*center.x - pt[1].x;
    pt[3].y = 2*center.y - pt[1].y;
}

5540
Rect RotatedRect::boundingRect() const
5541 5542 5543
{
    Point2f pt[4];
    points(pt);
5544 5545 5546 5547
    Rect r(cvFloor(std::min(std::min(std::min(pt[0].x, pt[1].x), pt[2].x), pt[3].x)),
           cvFloor(std::min(std::min(std::min(pt[0].y, pt[1].y), pt[2].y), pt[3].y)),
           cvCeil(std::max(std::max(std::max(pt[0].x, pt[1].x), pt[2].x), pt[3].x)),
           cvCeil(std::max(std::max(std::max(pt[0].y, pt[1].y), pt[2].y), pt[3].y)));
5548 5549 5550
    r.width -= r.x - 1;
    r.height -= r.y - 1;
    return r;
5551
}
5552 5553 5554

}

A
Andrey Kamaev 已提交
5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608
// glue

CvMatND::CvMatND(const cv::Mat& m)
{
    cvInitMatNDHeader(this, m.dims, m.size, m.type(), m.data );
    int i, d = m.dims;
    for( i = 0; i < d; i++ )
        dim[i].step = (int)m.step[i];
    type |= m.flags & cv::Mat::CONTINUOUS_FLAG;
}

_IplImage::_IplImage(const cv::Mat& m)
{
    CV_Assert( m.dims <= 2 );
    cvInitImageHeader(this, m.size(), cvIplDepth(m.flags), m.channels());
    cvSetData(this, m.data, (int)m.step[0]);
}

CvSparseMat* cvCreateSparseMat(const cv::SparseMat& sm)
{
    if( !sm.hdr )
        return 0;

    CvSparseMat* m = cvCreateSparseMat(sm.hdr->dims, sm.hdr->size, sm.type());

    cv::SparseMatConstIterator from = sm.begin();
    size_t i, N = sm.nzcount(), esz = sm.elemSize();

    for( i = 0; i < N; i++, ++from )
    {
        const cv::SparseMat::Node* n = from.node();
        uchar* to = cvPtrND(m, n->idx, 0, -2, 0);
        cv::copyElem(from.ptr, to, esz);
    }
    return m;
}

void CvSparseMat::copyToSparseMat(cv::SparseMat& m) const
{
    m.create( dims, &size[0], type );

    CvSparseMatIterator it;
    CvSparseNode* n = cvInitSparseMatIterator(this, &it);
    size_t esz = m.elemSize();

    for( ; n != 0; n = cvGetNextSparseNode(&it) )
    {
        const int* idx = CV_NODE_IDX(this, n);
        uchar* to = m.newNode(idx, m.hash(idx));
        cv::copyElem((const uchar*)CV_NODE_VAL(this, n), to, esz);
    }
}


5609
/* End of file. */