2010-05-12 01:44:00 +08:00
|
|
|
/*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"
|
2013-11-30 21:40:03 +08:00
|
|
|
#include "opencl_kernels.hpp"
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2014-01-16 22:30:39 +08:00
|
|
|
#include "bufferpool.impl.hpp"
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
/****************************************************************************************\
|
|
|
|
* [scaled] Identity matrix initialization *
|
|
|
|
\****************************************************************************************/
|
|
|
|
|
|
|
|
namespace cv {
|
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
void MatAllocator::map(UMatData*, int) const
|
|
|
|
{
|
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
void MatAllocator::unmap(UMatData* u) const
|
|
|
|
{
|
|
|
|
if(u->urefcount == 0 && u->refcount == 0)
|
2013-12-16 20:46:36 +08:00
|
|
|
{
|
2013-12-01 07:12:19 +08:00
|
|
|
deallocate(u);
|
2013-12-16 20:46:36 +08:00
|
|
|
u = NULL;
|
|
|
|
}
|
2013-12-01 07:12:19 +08:00
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
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++ )
|
2013-10-22 18:05:15 +08:00
|
|
|
{
|
2013-12-01 07:12:19 +08:00
|
|
|
CV_Assert( sz[i] <= (size_t)INT_MAX );
|
|
|
|
if( sz[i] == 0 )
|
|
|
|
return;
|
|
|
|
if( srcofs )
|
|
|
|
srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1);
|
|
|
|
isz[i] = (int)sz[i];
|
2013-10-22 18:05:15 +08:00
|
|
|
}
|
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
Mat src(dims, isz, CV_8U, srcptr, srcstep);
|
|
|
|
Mat dst(dims, isz, CV_8U, dstptr, dststep);
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
const Mat* arrays[] = { &src, &dst };
|
|
|
|
uchar* ptrs[2];
|
|
|
|
NAryMatIterator it(arrays, ptrs, 2);
|
|
|
|
size_t j, planesz = it.size;
|
|
|
|
|
|
|
|
for( j = 0; j < it.nplanes; j++, ++it )
|
|
|
|
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++ )
|
2013-10-22 18:05:15 +08:00
|
|
|
{
|
2013-12-01 07:12:19 +08:00
|
|
|
CV_Assert( sz[i] <= (size_t)INT_MAX );
|
|
|
|
if( sz[i] == 0 )
|
|
|
|
return;
|
|
|
|
if( dstofs )
|
|
|
|
dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1);
|
|
|
|
isz[i] = (int)sz[i];
|
2013-10-22 18:05:15 +08:00
|
|
|
}
|
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
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);
|
|
|
|
size_t j, planesz = it.size;
|
|
|
|
|
|
|
|
for( j = 0; j < it.nplanes; j++, ++it )
|
|
|
|
memcpy(ptrs[1], ptrs[0], planesz);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MatAllocator::copy(UMatData* usrc, UMatData* udst, int dims, const size_t sz[],
|
2013-10-22 18:05:15 +08:00
|
|
|
const size_t srcofs[], const size_t srcstep[],
|
2013-12-02 00:58:30 +08:00
|
|
|
const size_t dstofs[], const size_t dststep[], bool /*sync*/) const
|
2013-12-01 07:12:19 +08:00
|
|
|
{
|
|
|
|
if(!usrc || !udst)
|
|
|
|
return;
|
|
|
|
int isz[CV_MAX_DIM];
|
|
|
|
uchar* srcptr = usrc->data;
|
|
|
|
uchar* dstptr = udst->data;
|
|
|
|
for( int i = 0; i < dims; i++ )
|
2013-10-22 18:05:15 +08:00
|
|
|
{
|
2013-12-01 07:12:19 +08:00
|
|
|
CV_Assert( sz[i] <= (size_t)INT_MAX );
|
|
|
|
if( sz[i] == 0 )
|
2013-12-17 18:14:04 +08:00
|
|
|
return;
|
2013-12-01 07:12:19 +08:00
|
|
|
if( srcofs )
|
2013-12-17 18:14:04 +08:00
|
|
|
srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1);
|
2013-12-01 07:12:19 +08:00
|
|
|
if( dstofs )
|
2013-12-17 18:14:04 +08:00
|
|
|
dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1);
|
2013-12-01 07:12:19 +08:00
|
|
|
isz[i] = (int)sz[i];
|
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
Mat src(dims, isz, CV_8U, srcptr, srcstep);
|
|
|
|
Mat dst(dims, isz, CV_8U, dstptr, dststep);
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
const Mat* arrays[] = { &src, &dst };
|
|
|
|
uchar* ptrs[2];
|
|
|
|
NAryMatIterator it(arrays, ptrs, 2);
|
|
|
|
size_t j, planesz = it.size;
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
for( j = 0; j < it.nplanes; j++, ++it )
|
|
|
|
memcpy(ptrs[1], ptrs[0], planesz);
|
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2014-01-16 22:30:39 +08:00
|
|
|
BufferPoolController* MatAllocator::getBufferPoolController() const
|
|
|
|
{
|
|
|
|
static DummyBufferPoolController dummy;
|
|
|
|
return &dummy;
|
|
|
|
}
|
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
class StdMatAllocator : public MatAllocator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
UMatData* allocate(int dims, const int* sizes, int type,
|
2014-02-10 20:34:45 +08:00
|
|
|
void* data0, size_t* step, int /*flags*/, UMatUsageFlags /*usageFlags*/) const
|
2013-10-22 18:05:15 +08:00
|
|
|
{
|
2013-12-01 07:12:19 +08:00
|
|
|
size_t total = CV_ELEM_SIZE(type);
|
|
|
|
for( int i = dims-1; i >= 0; i-- )
|
2013-10-22 18:05:15 +08:00
|
|
|
{
|
2013-12-01 07:12:19 +08:00
|
|
|
if( step )
|
|
|
|
{
|
|
|
|
if( data0 && step[i] != CV_AUTOSTEP )
|
|
|
|
{
|
|
|
|
CV_Assert(total <= step[i]);
|
|
|
|
total = step[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
step[i] = total;
|
|
|
|
}
|
|
|
|
total *= sizes[i];
|
2013-10-22 18:05:15 +08:00
|
|
|
}
|
2013-12-01 07:12:19 +08:00
|
|
|
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;
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
return u;
|
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2014-02-10 20:34:45 +08:00
|
|
|
bool allocate(UMatData* u, int /*accessFlags*/, UMatUsageFlags /*usageFlags*/) const
|
2013-12-01 07:12:19 +08:00
|
|
|
{
|
|
|
|
if(!u) return false;
|
|
|
|
return true;
|
2013-10-22 18:05:15 +08:00
|
|
|
}
|
|
|
|
|
2013-12-01 07:12:19 +08:00
|
|
|
void deallocate(UMatData* u) const
|
2013-10-22 18:05:15 +08:00
|
|
|
{
|
2013-12-16 20:46:36 +08:00
|
|
|
CV_Assert(u->urefcount >= 0);
|
|
|
|
CV_Assert(u->refcount >= 0);
|
2013-12-01 07:12:19 +08:00
|
|
|
if(u && u->refcount == 0)
|
2013-10-22 18:05:15 +08:00
|
|
|
{
|
2013-12-01 07:12:19 +08:00
|
|
|
if( !(u->flags & UMatData::USER_ALLOCATED) )
|
|
|
|
{
|
|
|
|
fastFree(u->origdata);
|
|
|
|
u->origdata = 0;
|
|
|
|
}
|
|
|
|
delete u;
|
2013-10-22 18:05:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
MatAllocator* Mat::getStdAllocator()
|
|
|
|
{
|
2014-02-04 23:47:58 +08:00
|
|
|
static MatAllocator * allocator = new StdMatAllocator();
|
|
|
|
return allocator;
|
2013-10-22 18:05:15 +08:00
|
|
|
}
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
void swap( Mat& a, Mat& b )
|
|
|
|
{
|
2010-11-04 23:59:10 +08:00
|
|
|
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);
|
2013-10-22 18:05:15 +08:00
|
|
|
std::swap(a.u, b.u);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-11-04 23:59:10 +08:00
|
|
|
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]);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( a.step.p == b.step.buf )
|
|
|
|
{
|
|
|
|
a.step.p = a.step.buf;
|
|
|
|
a.size.p = &a.rows;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
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;
|
2011-02-10 04:55:11 +08:00
|
|
|
m.rows = m.cols = -1;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
m.dims = _dims;
|
|
|
|
if( !_sz )
|
|
|
|
return;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2014-02-05 20:01:15 +08:00
|
|
|
size_t esz = CV_ELEM_SIZE(m.flags), esz1 = CV_ELEM_SIZE1(m.flags), total = esz;
|
2010-10-12 20:31:40 +08:00
|
|
|
int i;
|
|
|
|
for( i = _dims-1; i >= 0; i-- )
|
|
|
|
{
|
|
|
|
int s = _sz[i];
|
2010-10-21 21:19:15 +08:00
|
|
|
CV_Assert( s >= 0 );
|
2010-10-12 20:31:40 +08:00
|
|
|
m.size.p[i] = s;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( _steps )
|
2014-02-05 20:01:15 +08:00
|
|
|
{
|
|
|
|
if (_steps[i] % esz1 != 0)
|
|
|
|
{
|
|
|
|
CV_Error(Error::BadStep, "Step must be a multiple of esz1");
|
|
|
|
}
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
m.step.p[i] = i < _dims-1 ? _steps[i] : esz;
|
2014-02-05 20:01:15 +08:00
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( _dims == 1 )
|
|
|
|
{
|
|
|
|
m.dims = 2;
|
|
|
|
m.cols = 1;
|
|
|
|
m.step[1] = esz;
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
static void updateContinuityFlag(Mat& m)
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
for( i = 0; i < m.dims; i++ )
|
|
|
|
{
|
|
|
|
if( m.size[i] > 1 )
|
|
|
|
break;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
for( j = m.dims-1; j > i; j-- )
|
|
|
|
{
|
|
|
|
if( m.step[j]*m.size[j] < m.step[j-1] )
|
|
|
|
break;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-06-28 19:08:11 +08:00
|
|
|
uint64 t = (uint64)m.step[0]*m.size[0];
|
2012-06-27 22:19:35 +08:00
|
|
|
if( j <= i && t == (size_t)t )
|
2010-10-12 20:31:40 +08:00
|
|
|
m.flags |= Mat::CONTINUOUS_FLAG;
|
2010-10-18 16:51:46 +08:00
|
|
|
else
|
|
|
|
m.flags &= ~Mat::CONTINUOUS_FLAG;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
static void finalizeHdr(Mat& m)
|
|
|
|
{
|
|
|
|
updateContinuityFlag(m);
|
2010-10-22 05:07:11 +08:00
|
|
|
int d = m.dims;
|
|
|
|
if( d > 2 )
|
2010-10-12 20:31:40 +08:00
|
|
|
m.rows = m.cols = -1;
|
2013-10-22 18:05:15 +08:00
|
|
|
if(m.u)
|
|
|
|
m.data = m.datastart = m.u->data;
|
2010-10-12 20:31:40 +08:00
|
|
|
if( m.data )
|
|
|
|
{
|
2010-10-18 16:51:46 +08:00
|
|
|
m.datalimit = m.datastart + m.size[0]*m.step[0];
|
|
|
|
if( m.size[0] > 0 )
|
|
|
|
{
|
2010-10-22 05:07:11 +08:00
|
|
|
m.dataend = m.data + m.size[d-1]*m.step[d-1];
|
|
|
|
for( int i = 0; i < d-1; i++ )
|
2010-10-18 16:51:46 +08:00
|
|
|
m.dataend += (m.size[i] - 1)*m.step[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m.dataend = m.datalimit;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2010-10-18 16:51:46 +08:00
|
|
|
else
|
|
|
|
m.dataend = m.datalimit = 0;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
void Mat::create(int d, const int* _sizes, int _type)
|
|
|
|
{
|
|
|
|
int i;
|
2013-04-01 15:29:13 +08:00
|
|
|
CV_Assert(0 <= d && d <= CV_MAX_DIM && _sizes);
|
2010-10-12 20:31:40 +08:00
|
|
|
_type = CV_MAT_TYPE(_type);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
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;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
release();
|
|
|
|
if( d == 0 )
|
|
|
|
return;
|
|
|
|
flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL;
|
2011-12-28 22:47:21 +08:00
|
|
|
setSize(*this, d, _sizes, 0, true);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-11-20 21:16:16 +08:00
|
|
|
if( total() > 0 )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2013-10-22 18:05:15 +08:00
|
|
|
MatAllocator *a = allocator, *a0 = getStdAllocator();
|
2011-11-25 23:39:24 +08:00
|
|
|
#ifdef HAVE_TGPU
|
2013-10-22 18:05:15 +08:00
|
|
|
if( !a || a == tegra::getAllocator() )
|
|
|
|
a = tegra::getAllocator(d, _sizes, _type);
|
2011-11-25 23:39:24 +08:00
|
|
|
#endif
|
2013-10-22 18:05:15 +08:00
|
|
|
if(!a)
|
|
|
|
a = a0;
|
|
|
|
try
|
2010-10-18 16:51:46 +08:00
|
|
|
{
|
2014-02-10 20:34:45 +08:00
|
|
|
u = a->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT);
|
2013-10-22 18:05:15 +08:00
|
|
|
CV_Assert(u != 0);
|
2010-10-18 16:51:46 +08:00
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
catch(...)
|
2010-10-18 16:51:46 +08:00
|
|
|
{
|
2013-10-22 18:05:15 +08:00
|
|
|
if(a != a0)
|
2014-02-10 20:34:45 +08:00
|
|
|
u = a0->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT);
|
2013-10-22 18:05:15 +08:00
|
|
|
CV_Assert(u != 0);
|
2010-10-18 16:51:46 +08:00
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-12-16 20:46:36 +08:00
|
|
|
addref();
|
2010-10-12 20:31:40 +08:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
void Mat::deallocate()
|
|
|
|
{
|
2013-10-22 18:05:15 +08:00
|
|
|
if(u)
|
|
|
|
(u->currAllocator ? u->currAllocator : allocator ? allocator : getStdAllocator())->unmap(u);
|
2013-12-16 20:46:36 +08:00
|
|
|
u = NULL;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
|
|
|
|
2013-03-30 23:03:55 +08:00
|
|
|
Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange)
|
2013-10-24 20:08:15 +08:00
|
|
|
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
|
|
|
datalimit(0), allocator(0), u(0), size(&rows)
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
|
|
|
CV_Assert( m.dims >= 2 );
|
|
|
|
if( m.dims > 2 )
|
|
|
|
{
|
|
|
|
AutoBuffer<Range> rs(m.dims);
|
2012-06-09 23:00:04 +08:00
|
|
|
rs[0] = _rowRange;
|
|
|
|
rs[1] = _colRange;
|
2010-10-12 20:31:40 +08:00
|
|
|
for( int i = 2; i < m.dims; i++ )
|
|
|
|
rs[i] = Range::all();
|
|
|
|
*this = m(rs);
|
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
*this = m;
|
2012-06-09 23:00:04 +08:00
|
|
|
if( _rowRange != Range::all() && _rowRange != Range(0,rows) )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2012-06-09 23:00:04 +08:00
|
|
|
CV_Assert( 0 <= _rowRange.start && _rowRange.start <= _rowRange.end && _rowRange.end <= m.rows );
|
|
|
|
rows = _rowRange.size();
|
|
|
|
data += step*_rowRange.start;
|
2010-10-18 16:51:46 +08:00
|
|
|
flags |= SUBMATRIX_FLAG;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-06-09 23:00:04 +08:00
|
|
|
if( _colRange != Range::all() && _colRange != Range(0,cols) )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2012-06-09 23:00:04 +08:00
|
|
|
CV_Assert( 0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols );
|
|
|
|
cols = _colRange.size();
|
|
|
|
data += _colRange.start*elemSize();
|
2010-10-12 20:31:40 +08:00
|
|
|
flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1;
|
2010-10-18 16:51:46 +08:00
|
|
|
flags |= SUBMATRIX_FLAG;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( rows == 1 )
|
|
|
|
flags |= CONTINUOUS_FLAG;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( rows <= 0 || cols <= 0 )
|
|
|
|
{
|
|
|
|
release();
|
|
|
|
rows = cols = 0;
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
Mat::Mat(const Mat& m, const Rect& roi)
|
|
|
|
: flags(m.flags), dims(2), rows(roi.height), cols(roi.width),
|
2013-10-24 20:08:15 +08:00
|
|
|
data(m.data + roi.y*m.step[0]),
|
2010-10-18 16:51:46 +08:00
|
|
|
datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit),
|
2013-10-24 20:08:15 +08:00
|
|
|
allocator(m.allocator), u(m.u), size(&rows)
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
|
|
|
CV_Assert( m.dims <= 2 );
|
|
|
|
flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1;
|
|
|
|
flags |= roi.height == 1 ? CONTINUOUS_FLAG : 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
size_t esz = CV_ELEM_SIZE(flags);
|
2010-10-12 20:31:40 +08:00
|
|
|
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 );
|
2013-10-24 20:08:15 +08:00
|
|
|
if( u )
|
|
|
|
CV_XADD(&u->refcount, 1);
|
2010-10-18 16:51:46 +08:00
|
|
|
if( roi.width < m.cols || roi.height < m.rows )
|
|
|
|
flags |= SUBMATRIX_FLAG;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
step[0] = m.step[0]; step[1] = esz;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( rows <= 0 || cols <= 0 )
|
|
|
|
{
|
|
|
|
release();
|
|
|
|
rows = cols = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-03-30 23:03:55 +08:00
|
|
|
Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _steps)
|
2013-10-24 20:08:15 +08:00
|
|
|
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
|
|
|
datalimit(0), allocator(0), u(0), size(&rows)
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2012-04-14 05:50:59 +08:00
|
|
|
flags |= CV_MAT_TYPE(_type);
|
|
|
|
data = datastart = (uchar*)_data;
|
2010-10-12 20:31:40 +08:00
|
|
|
setSize(*this, _dims, _sizes, _steps, true);
|
|
|
|
finalizeHdr(*this);
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
|
|
|
|
2013-03-30 23:03:55 +08:00
|
|
|
Mat::Mat(const Mat& m, const Range* ranges)
|
2013-10-24 20:08:15 +08:00
|
|
|
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
|
|
|
datalimit(0), allocator(0), u(0), size(&rows)
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
|
|
|
int i, d = m.dims;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
CV_Assert(ranges);
|
|
|
|
for( i = 0; i < d; i++ )
|
|
|
|
{
|
|
|
|
Range r = ranges[i];
|
|
|
|
CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) );
|
|
|
|
}
|
|
|
|
*this = m;
|
|
|
|
for( i = 0; i < d; i++ )
|
|
|
|
{
|
|
|
|
Range r = ranges[i];
|
2010-10-18 16:51:46 +08:00
|
|
|
if( r != Range::all() && r != Range(0, size.p[i]))
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2010-10-18 16:51:46 +08:00
|
|
|
size.p[i] = r.end - r.start;
|
|
|
|
data += r.start*step.p[i];
|
|
|
|
flags |= SUBMATRIX_FLAG;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
|
|
|
}
|
2010-10-18 16:51:46 +08:00
|
|
|
updateContinuityFlag(*this);
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
|
|
|
|
2013-03-29 01:01:12 +08:00
|
|
|
static Mat cvMatNDToMat(const CvMatND* m, bool copyData)
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2013-03-29 01:01:12 +08:00
|
|
|
Mat thiz;
|
|
|
|
|
2012-04-14 05:50:59 +08:00
|
|
|
if( !m )
|
2013-03-29 01:01:12 +08:00
|
|
|
return thiz;
|
|
|
|
thiz.data = thiz.datastart = m->data.ptr;
|
|
|
|
thiz.flags |= CV_MAT_TYPE(m->type);
|
2010-10-12 20:31:40 +08:00
|
|
|
int _sizes[CV_MAX_DIM];
|
|
|
|
size_t _steps[CV_MAX_DIM];
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
int i, d = m->dims;
|
|
|
|
for( i = 0; i < d; i++ )
|
|
|
|
{
|
|
|
|
_sizes[i] = m->dim[i].size;
|
|
|
|
_steps[i] = m->dim[i].step;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-03-29 01:01:12 +08:00
|
|
|
setSize(thiz, d, _sizes, _steps);
|
|
|
|
finalizeHdr(thiz);
|
2010-10-12 20:31:40 +08:00
|
|
|
|
|
|
|
if( copyData )
|
|
|
|
{
|
2013-03-29 01:01:12 +08:00
|
|
|
Mat temp(thiz);
|
|
|
|
thiz.release();
|
|
|
|
temp.copyTo(thiz);
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-03-29 01:01:12 +08:00
|
|
|
return thiz;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2012-04-14 05:50:59 +08:00
|
|
|
|
2013-03-29 01:01:12 +08:00
|
|
|
static Mat cvMatToMat(const CvMat* m, bool copyData)
|
2012-04-14 05:50:59 +08:00
|
|
|
{
|
2013-03-29 01:01:12 +08:00
|
|
|
Mat thiz;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-04-14 05:50:59 +08:00
|
|
|
if( !m )
|
2013-03-29 01:01:12 +08:00
|
|
|
return thiz;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-04-14 05:50:59 +08:00
|
|
|
if( !copyData )
|
|
|
|
{
|
2013-03-29 01:01:12 +08:00
|
|
|
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;
|
|
|
|
thiz.data = thiz.datastart = m->data.ptr;
|
|
|
|
size_t esz = CV_ELEM_SIZE(m->type), minstep = thiz.cols*esz, _step = m->step;
|
2012-04-14 05:50:59 +08:00
|
|
|
if( _step == 0 )
|
|
|
|
_step = minstep;
|
2013-03-29 01:01:12 +08:00
|
|
|
thiz.datalimit = thiz.datastart + _step*thiz.rows;
|
|
|
|
thiz.dataend = thiz.datalimit - _step + minstep;
|
|
|
|
thiz.step[0] = _step; thiz.step[1] = esz;
|
2012-04-14 05:50:59 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-03-29 01:01:12 +08:00
|
|
|
thiz.data = thiz.datastart = thiz.dataend = 0;
|
|
|
|
Mat(m->rows, m->cols, m->type, m->data.ptr, m->step).copyTo(thiz);
|
2012-04-14 05:50:59 +08:00
|
|
|
}
|
2013-03-29 01:01:12 +08:00
|
|
|
|
|
|
|
return thiz;
|
2012-04-14 05:50:59 +08:00
|
|
|
}
|
|
|
|
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-03-29 01:01:12 +08:00
|
|
|
static Mat iplImageToMat(const IplImage* img, bool copyData)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2013-03-29 01:01:12 +08:00
|
|
|
Mat m;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-04-14 05:50:59 +08:00
|
|
|
if( !img )
|
2013-03-29 01:01:12 +08:00
|
|
|
return m;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-03-29 01:01:12 +08:00
|
|
|
m.dims = 2;
|
2010-05-12 01:44:00 +08:00
|
|
|
CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-06-09 23:00:04 +08:00
|
|
|
int imgdepth = IPL2CV_DEPTH(img->depth);
|
2010-05-12 01:44:00 +08:00
|
|
|
size_t esz;
|
2013-03-29 01:01:12 +08:00
|
|
|
m.step[0] = img->widthStep;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
if(!img->roi)
|
|
|
|
{
|
|
|
|
CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL);
|
2013-03-29 01:01:12 +08:00
|
|
|
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);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL || img->roi->coi != 0);
|
|
|
|
bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE;
|
2013-03-29 01:01:12 +08:00
|
|
|
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);
|
|
|
|
m.data = m.datastart = (uchar*)img->imageData +
|
|
|
|
(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;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
if( copyData )
|
|
|
|
{
|
2013-03-29 01:01:12 +08:00
|
|
|
Mat m2 = m;
|
|
|
|
m.release();
|
2010-05-12 01:44:00 +08:00
|
|
|
if( !img->roi || !img->roi->coi ||
|
|
|
|
img->dataOrder == IPL_DATA_ORDER_PLANE)
|
2013-03-29 01:01:12 +08:00
|
|
|
m2.copyTo(m);
|
2010-05-12 01:44:00 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
int ch[] = {img->roi->coi - 1, 0};
|
2013-03-29 01:01:12 +08:00
|
|
|
m.create(m2.rows, m2.cols, m2.type());
|
|
|
|
mixChannels(&m2, 1, &m, 1, ch, 1);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-29 01:01:12 +08:00
|
|
|
return m;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-03-29 01:01:12 +08:00
|
|
|
Mat Mat::diag(int d) const
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
CV_Assert( dims <= 2 );
|
2013-03-29 01:01:12 +08:00
|
|
|
Mat m = *this;
|
|
|
|
size_t esz = elemSize();
|
|
|
|
int len;
|
2010-10-18 16:51:46 +08:00
|
|
|
|
2013-03-29 01:01:12 +08:00
|
|
|
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;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
void Mat::pop_back(size_t nelems)
|
|
|
|
{
|
|
|
|
CV_Assert( nelems <= (size_t)size.p[0] );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
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);
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
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) );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
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;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
CV_Assert( (int)nelems >= 0 );
|
|
|
|
if( !isSubmatrix() && data + step.p[0]*nelems <= datalimit )
|
|
|
|
return;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
int r = size.p[0];
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-19 19:57:37 +08:00
|
|
|
if( (size_t)r >= nelems )
|
|
|
|
return;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
size.p[0] = std::max((int)nelems, 1);
|
|
|
|
size_t newsize = total()*elemSize();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
if( newsize < MIN_SIZE )
|
|
|
|
size.p[0] = (int)((MIN_SIZE + newsize - 1)*nelems/newsize);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
Mat m(dims, size.p, type());
|
|
|
|
size.p[0] = r;
|
|
|
|
if( r > 0 )
|
|
|
|
{
|
|
|
|
Mat mpart = m.rowRange(0, r);
|
|
|
|
copyTo(mpart);
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
*this = m;
|
|
|
|
size.p[0] = r;
|
|
|
|
dataend = data + step.p[0]*r;
|
|
|
|
}
|
|
|
|
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
void Mat::resize(size_t nelems)
|
|
|
|
{
|
|
|
|
int saveRows = size.p[0];
|
2010-10-19 19:57:37 +08:00
|
|
|
if( saveRows == (int)nelems )
|
|
|
|
return;
|
2010-10-18 16:51:46 +08:00
|
|
|
CV_Assert( (int)nelems >= 0 );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
if( isSubmatrix() || data + step.p[0]*nelems > datalimit )
|
|
|
|
reserve(nelems);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
size.p[0] = (int)nelems;
|
|
|
|
dataend += (size.p[0] - saveRows)*step.p[0];
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
//updateContinuityFlag(*this);
|
2012-06-08 01:21:29 +08:00
|
|
|
}
|
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
|
|
|
|
void Mat::resize(size_t nelems, const Scalar& s)
|
|
|
|
{
|
|
|
|
int saveRows = size.p[0];
|
|
|
|
resize(nelems);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
if( size.p[0] > saveRows )
|
|
|
|
{
|
|
|
|
Mat part = rowRange(saveRows, size.p[0]);
|
|
|
|
part = s;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
}
|
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
void Mat::push_back(const Mat& elems)
|
|
|
|
{
|
|
|
|
int r = size.p[0], delta = elems.size.p[0];
|
|
|
|
if( delta == 0 )
|
|
|
|
return;
|
2011-05-28 04:32:48 +08:00
|
|
|
if( this == &elems )
|
|
|
|
{
|
|
|
|
Mat tmp = elems;
|
|
|
|
push_back(tmp);
|
|
|
|
return;
|
2010-10-18 16:51:46 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
if( !data )
|
|
|
|
{
|
|
|
|
*this = elems.clone();
|
|
|
|
return;
|
|
|
|
}
|
2011-05-28 04:32:48 +08:00
|
|
|
|
|
|
|
size.p[0] = elems.size.p[0];
|
|
|
|
bool eq = size == elems.size;
|
|
|
|
size.p[0] = r;
|
|
|
|
if( !eq )
|
|
|
|
CV_Error(CV_StsUnmatchedSizes, "");
|
|
|
|
if( type() != elems.type() )
|
|
|
|
CV_Error(CV_StsUnmatchedFormats, "");
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
if( isSubmatrix() || dataend + step.p[0]*delta > datalimit )
|
|
|
|
reserve( std::max(r + delta, (r*3+1)/2) );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
size.p[0] += delta;
|
|
|
|
dataend += step.p[0]*delta;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
//updateContinuityFlag(*this);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-18 16:51:46 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
Mat cvarrToMat(const CvArr* arr, bool copyData,
|
2013-01-20 04:58:51 +08:00
|
|
|
bool /*allowND*/, int coiMode, AutoBuffer<double>* abuf )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
if( !arr )
|
|
|
|
return Mat();
|
2013-03-29 01:01:12 +08:00
|
|
|
if( CV_IS_MAT_HDR_Z(arr) )
|
|
|
|
return cvMatToMat((const CvMat*)arr, copyData);
|
2010-10-12 20:31:40 +08:00
|
|
|
if( CV_IS_MATND(arr) )
|
2013-03-29 01:01:12 +08:00
|
|
|
return cvMatNDToMat((const CvMatND*)arr, copyData );
|
2010-10-12 20:31:40 +08:00
|
|
|
if( CV_IS_IMAGE(arr) )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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");
|
2013-03-29 01:01:12 +08:00
|
|
|
return iplImageToMat(iplimg, copyData);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
if( CV_IS_SEQ(arr) )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
CvSeq* seq = (CvSeq*)arr;
|
2013-01-20 04:58:51 +08:00
|
|
|
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);
|
2010-05-12 01:44:00 +08:00
|
|
|
if(!copyData && seq->first->next == seq->first)
|
2013-01-20 04:58:51 +08:00
|
|
|
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);
|
2010-05-12 01:44:00 +08:00
|
|
|
cvCvtSeqToArray(seq, buf.data, CV_WHOLE_SEQ);
|
|
|
|
return buf;
|
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
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;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( delta1 == 0 )
|
|
|
|
ofs.x = ofs.y = 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
else
|
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
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 );
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
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);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
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;
|
2012-06-08 01:21:29 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
void cv::extractImageCOI(const CvArr* arr, OutputArray _ch, int coi)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
Mat mat = cvarrToMat(arr, false, true, 1);
|
2011-04-17 21:14:45 +08:00
|
|
|
_ch.create(mat.dims, mat.size, mat.depth());
|
|
|
|
Mat ch = _ch.getMat();
|
2010-11-20 20:05:28 +08:00
|
|
|
if(coi < 0)
|
2012-06-08 01:21:29 +08:00
|
|
|
{
|
2010-11-20 20:05:28 +08:00
|
|
|
CV_Assert( CV_IS_IMAGE(arr) );
|
|
|
|
coi = cvGetImageCOI((const IplImage*)arr)-1;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
CV_Assert(0 <= coi && coi < mat.channels());
|
|
|
|
int _pairs[] = { coi, 0 };
|
|
|
|
mixChannels( &mat, 1, &ch, 1, _pairs, 1 );
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::insertImageCOI(InputArray _ch, CvArr* arr, int coi)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat ch = _ch.getMat(), mat = cvarrToMat(arr, false, true, 1);
|
2010-11-20 20:05:28 +08:00
|
|
|
if(coi < 0)
|
2012-06-08 01:21:29 +08:00
|
|
|
{
|
2010-11-20 20:05:28 +08:00
|
|
|
CV_Assert( CV_IS_IMAGE(arr) );
|
|
|
|
coi = cvGetImageCOI((const IplImage*)arr)-1;
|
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
CV_Assert(ch.size == mat.size && ch.depth() == mat.depth() && 0 <= coi && coi < mat.channels());
|
2010-05-12 01:44:00 +08:00
|
|
|
int _pairs[] = { 0, coi };
|
|
|
|
mixChannels( &ch, 1, &mat, 1, _pairs, 1 );
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
namespace cv
|
|
|
|
{
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
Mat Mat::reshape(int new_cn, int new_rows) const
|
|
|
|
{
|
|
|
|
int cn = channels();
|
2011-02-10 04:55:11 +08:00
|
|
|
Mat hdr = *this;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-02-10 04:55:11 +08:00
|
|
|
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;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-02-10 04:55:11 +08:00
|
|
|
CV_Assert( dims <= 2 );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
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;
|
2010-10-12 20:31:40 +08:00
|
|
|
hdr.step[0] = total_width * elemSize1();
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2010-10-19 19:57:37 +08:00
|
|
|
hdr.step[1] = CV_ELEM_SIZE(hdr.flags);
|
2010-05-12 01:44:00 +08:00
|
|
|
return hdr;
|
|
|
|
}
|
|
|
|
|
2013-03-30 23:03:55 +08:00
|
|
|
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;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-28 02:26:39 +08:00
|
|
|
int Mat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) const
|
|
|
|
{
|
|
|
|
return (depth() == _depth || _depth <= 0) &&
|
|
|
|
(isContinuous() || !_requireContinuous) &&
|
2013-01-26 03:45:41 +08:00
|
|
|
((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) ||
|
|
|
|
(cols == _elemChannels && channels() == 1))) ||
|
2010-10-28 02:26:39 +08:00
|
|
|
(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;
|
|
|
|
}
|
2010-11-07 05:51:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
|
|
|
|
{
|
|
|
|
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,"");
|
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
/*************************************************************************************************\
|
|
|
|
Input/Output Array
|
|
|
|
\*************************************************************************************************/
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
Mat _InputArray::getMat(int i) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
2013-10-22 18:05:15 +08:00
|
|
|
int accessFlags = flags & ACCESS_MASK;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MAT )
|
|
|
|
{
|
2011-09-22 17:58:58 +08:00
|
|
|
const Mat* m = (const Mat*)obj;
|
|
|
|
if( i < 0 )
|
|
|
|
return *m;
|
|
|
|
return m->row(i);
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == UMAT )
|
|
|
|
{
|
|
|
|
const UMat* m = (const UMat*)obj;
|
|
|
|
if( i < 0 )
|
|
|
|
return m->getMat(accessFlags);
|
|
|
|
return m->getMat(accessFlags).row(i);
|
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == EXPR )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return (Mat)*((const MatExpr*)obj);
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MATX )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return Mat(sz, flags, obj);
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
int t = CV_MAT_TYPE(flags);
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
return !v.empty() ? Mat(size(), t, (void*)&v[0]) : Mat();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == NONE )
|
|
|
|
return Mat();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR_VECTOR )
|
|
|
|
{
|
|
|
|
int t = type(i);
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
|
2011-04-17 21:14:45 +08:00
|
|
|
CV_Assert( 0 <= i && i < (int)vv.size() );
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<uchar>& v = vv[i];
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
return !v.empty() ? Mat(size(i), t, (void*)&v[0]) : Mat();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-04-26 14:49:51 +08:00
|
|
|
if( k == STD_VECTOR_MAT )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<Mat>& v = *(const std::vector<Mat>*)obj;
|
2011-04-17 21:14:45 +08:00
|
|
|
CV_Assert( 0 <= i && i < (int)v.size() );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
return v[i];
|
2012-06-08 01:21:29 +08:00
|
|
|
}
|
2013-04-26 14:49:51 +08:00
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-04-26 14:49:51 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( k == GPU_MAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
2013-08-28 19:45:13 +08:00
|
|
|
CV_Error(cv::Error::StsNotImplemented, "You should explicitly call download method for cuda::GpuMat object");
|
2013-04-26 14:49:51 +08:00
|
|
|
return Mat();
|
|
|
|
}
|
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == CUDA_MEM )
|
2013-04-26 14:49:51 +08:00
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
|
2013-08-28 19:45:13 +08:00
|
|
|
const cuda::CudaMem* cuda_mem = (const cuda::CudaMem*)obj;
|
2013-04-26 14:49:51 +08:00
|
|
|
|
|
|
|
return cuda_mem->createMatHeader();
|
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
|
|
|
|
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);
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-02-25 00:14:01 +08:00
|
|
|
void _InputArray::getMatVector(std::vector<Mat>& mv) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
2013-10-22 18:05:15 +08:00
|
|
|
int accessFlags = flags & ACCESS_MASK;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MAT )
|
|
|
|
{
|
|
|
|
const Mat& m = *(const Mat*)obj;
|
2011-07-19 20:27:07 +08:00
|
|
|
int i, n = (int)m.size[0];
|
2011-04-17 21:14:45 +08:00
|
|
|
mv.resize(n);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
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;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == EXPR )
|
|
|
|
{
|
|
|
|
Mat m = *(const MatExpr*)obj;
|
2011-07-19 20:27:07 +08:00
|
|
|
int i, n = m.size[0];
|
2011-04-17 21:14:45 +08:00
|
|
|
mv.resize(n);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
mv[i] = m.row(i);
|
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MATX )
|
|
|
|
{
|
|
|
|
size_t i, n = sz.height, esz = CV_ELEM_SIZE(flags);
|
|
|
|
mv.resize(n);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
mv[i] = Mat(1, sz.width, CV_MAT_TYPE(flags), (uchar*)obj + esz*sz.width*i);
|
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR )
|
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
size_t i, n = v.size(), esz = CV_ELEM_SIZE(flags);
|
|
|
|
int t = CV_MAT_DEPTH(flags), cn = CV_MAT_CN(flags);
|
|
|
|
mv.resize(n);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
mv[i] = Mat(1, cn, t, (void*)(&v[0] + esz*i));
|
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == NONE )
|
|
|
|
{
|
|
|
|
mv.clear();
|
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR_VECTOR )
|
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
|
2011-07-19 20:27:07 +08:00
|
|
|
int i, n = (int)vv.size();
|
2011-04-17 21:14:45 +08:00
|
|
|
int t = CV_MAT_TYPE(flags);
|
|
|
|
mv.resize(n);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<uchar>& v = vv[i];
|
2011-04-17 21:14:45 +08:00
|
|
|
mv[i] = Mat(size(i), t, (void*)&v[0]);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-10-22 21:41:28 +08:00
|
|
|
if( k == STD_VECTOR_MAT )
|
|
|
|
{
|
|
|
|
const std::vector<Mat>& v = *(const std::vector<Mat>*)obj;
|
|
|
|
size_t i, n = v.size();
|
|
|
|
mv.resize(n);
|
|
|
|
|
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
mv[i] = v[i];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == STD_VECTOR_UMAT )
|
2013-06-21 14:05:29 +08:00
|
|
|
{
|
2013-10-22 18:05:15 +08:00
|
|
|
const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
|
|
|
|
size_t i, n = v.size();
|
|
|
|
mv.resize(n);
|
2013-06-21 14:05:29 +08:00
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
mv[i] = v[i].getMat(accessFlags);
|
2011-04-17 21:14:45 +08:00
|
|
|
return;
|
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
|
|
|
|
CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2011-11-30 14:20:29 +08:00
|
|
|
|
2013-12-27 17:04:02 +08:00
|
|
|
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;
|
|
|
|
size_t i, n = v.size();
|
|
|
|
umv.resize(n);
|
|
|
|
|
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
umv[i] = v[i].getUMat(accessFlags);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( k == STD_VECTOR_UMAT )
|
|
|
|
{
|
|
|
|
const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
|
|
|
|
size_t i, n = v.size();
|
|
|
|
umv.resize(n);
|
|
|
|
|
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
umv[i] = v[i];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-21 21:58:33 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-12-27 17:04:02 +08:00
|
|
|
CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
|
|
|
|
}
|
|
|
|
|
2013-08-28 19:45:13 +08:00
|
|
|
cuda::GpuMat _InputArray::getGpuMat() const
|
2011-11-30 14:20:29 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
|
2013-04-26 14:49:51 +08:00
|
|
|
if (k == GPU_MAT)
|
|
|
|
{
|
2013-08-28 19:45:13 +08:00
|
|
|
const cuda::GpuMat* d_mat = (const cuda::GpuMat*)obj;
|
2013-04-26 14:49:51 +08:00
|
|
|
return *d_mat;
|
|
|
|
}
|
2013-03-06 19:18:44 +08:00
|
|
|
|
2013-04-26 14:49:51 +08:00
|
|
|
if (k == CUDA_MEM)
|
|
|
|
{
|
2013-08-28 19:45:13 +08:00
|
|
|
const cuda::CudaMem* cuda_mem = (const cuda::CudaMem*)obj;
|
2013-04-26 14:49:51 +08:00
|
|
|
return cuda_mem->createGpuMatHeader();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (k == OPENGL_BUFFER)
|
|
|
|
{
|
|
|
|
CV_Error(cv::Error::StsNotImplemented, "You should explicitly call mapDevice/unmapDevice methods for ogl::Buffer object");
|
2013-08-28 19:45:13 +08:00
|
|
|
return cuda::GpuMat();
|
2013-04-26 14:49:51 +08:00
|
|
|
}
|
|
|
|
|
2013-04-16 17:03:34 +08:00
|
|
|
if (k == NONE)
|
2013-08-28 19:45:13 +08:00
|
|
|
return cuda::GpuMat();
|
2013-04-16 17:03:34 +08:00
|
|
|
|
2013-08-28 19:45:13 +08:00
|
|
|
CV_Error(cv::Error::StsNotImplemented, "getGpuMat is available only for cuda::GpuMat and cuda::CudaMem");
|
|
|
|
return cuda::GpuMat();
|
2011-11-30 14:20:29 +08:00
|
|
|
}
|
|
|
|
|
2013-03-06 19:18:44 +08:00
|
|
|
ogl::Buffer _InputArray::getOGlBuffer() const
|
2011-11-30 14:20:29 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
|
2013-03-06 19:18:44 +08:00
|
|
|
CV_Assert(k == OPENGL_BUFFER);
|
|
|
|
|
|
|
|
const ogl::Buffer* gl_buf = (const ogl::Buffer*)obj;
|
|
|
|
return *gl_buf;
|
2011-11-30 14:20:29 +08:00
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
int _InputArray::kind() const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2012-03-26 16:18:53 +08:00
|
|
|
return flags & KIND_MASK;
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2014-03-20 22:38:31 +08:00
|
|
|
int _InputArray::rows(int i) const
|
|
|
|
{
|
|
|
|
return size(i).height;
|
|
|
|
}
|
|
|
|
|
|
|
|
int _InputArray::cols(int i) const
|
|
|
|
{
|
|
|
|
return size(i).width;
|
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
Size _InputArray::size(int i) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return ((const Mat*)obj)->size();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == EXPR )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return ((const MatExpr*)obj)->size();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == UMAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return ((const UMat*)obj)->size();
|
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MATX )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return sz;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
|
|
|
|
const std::vector<int>& iv = *(const std::vector<int>*)obj;
|
2011-04-17 21:14:45 +08:00
|
|
|
size_t szb = v.size(), szi = iv.size();
|
|
|
|
return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1);
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == NONE )
|
|
|
|
return Size();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR_VECTOR )
|
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
|
2011-04-17 21:14:45 +08:00
|
|
|
if( i < 0 )
|
|
|
|
return vv.empty() ? Size() : Size((int)vv.size(), 1);
|
|
|
|
CV_Assert( i < (int)vv.size() );
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<std::vector<int> >& ivv = *(const std::vector<std::vector<int> >*)obj;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
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);
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-11-30 14:20:29 +08:00
|
|
|
if( k == STD_VECTOR_MAT )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
|
2011-04-17 21:14:45 +08:00
|
|
|
if( i < 0 )
|
|
|
|
return vv.empty() ? Size() : Size((int)vv.size(), 1);
|
|
|
|
CV_Assert( i < (int)vv.size() );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
return vv[i].size();
|
|
|
|
}
|
2011-11-30 14:20:29 +08:00
|
|
|
|
2013-12-23 21:37:41 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2011-11-30 14:20:29 +08:00
|
|
|
if( k == OPENGL_BUFFER )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
2013-03-06 19:18:44 +08:00
|
|
|
const ogl::Buffer* buf = (const ogl::Buffer*)obj;
|
2011-11-30 14:20:29 +08:00
|
|
|
return buf->size();
|
|
|
|
}
|
|
|
|
|
2013-04-26 14:49:51 +08:00
|
|
|
if( k == GPU_MAT )
|
2011-11-30 14:20:29 +08:00
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
2013-08-28 19:45:13 +08:00
|
|
|
const cuda::GpuMat* d_mat = (const cuda::GpuMat*)obj;
|
2011-11-30 14:20:29 +08:00
|
|
|
return d_mat->size();
|
|
|
|
}
|
2013-04-26 14:49:51 +08:00
|
|
|
|
|
|
|
CV_Assert( k == CUDA_MEM );
|
|
|
|
//if( k == CUDA_MEM )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
2013-08-28 19:45:13 +08:00
|
|
|
const cuda::CudaMem* cuda_mem = (const cuda::CudaMem*)obj;
|
2013-04-26 14:49:51 +08:00
|
|
|
return cuda_mem->size();
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
|
|
|
|
2013-11-19 02:48:04 +08:00
|
|
|
int _InputArray::sizend(int* arrsz, int i) const
|
2013-11-19 00:48:00 +08:00
|
|
|
{
|
|
|
|
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;
|
2013-11-19 02:48:04 +08:00
|
|
|
if(arrsz)
|
2013-11-19 00:48:00 +08:00
|
|
|
for(j = 0; j < d; j++)
|
2013-11-19 02:48:04 +08:00
|
|
|
arrsz[j] = m.size.p[j];
|
2013-11-19 00:48:00 +08:00
|
|
|
}
|
|
|
|
else if( k == UMAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
const UMat& m = *(const UMat*)obj;
|
|
|
|
d = m.dims;
|
2013-11-19 02:48:04 +08:00
|
|
|
if(arrsz)
|
2013-11-19 00:48:00 +08:00
|
|
|
for(j = 0; j < d; j++)
|
2013-11-19 02:48:04 +08:00
|
|
|
arrsz[j] = m.size.p[j];
|
2013-11-19 00:48:00 +08:00
|
|
|
}
|
|
|
|
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;
|
2013-11-19 02:48:04 +08:00
|
|
|
if(arrsz)
|
2013-11-19 00:48:00 +08:00
|
|
|
for(j = 0; j < d; j++)
|
2013-11-19 02:48:04 +08:00
|
|
|
arrsz[j] = m.size.p[j];
|
2013-11-19 00:48:00 +08:00
|
|
|
}
|
|
|
|
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;
|
2013-11-19 02:48:04 +08:00
|
|
|
if(arrsz)
|
2013-11-19 00:48:00 +08:00
|
|
|
for(j = 0; j < d; j++)
|
2013-11-19 02:48:04 +08:00
|
|
|
arrsz[j] = m.size.p[j];
|
2013-11-19 00:48:00 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Size sz2d = size(i);
|
|
|
|
d = 2;
|
2013-11-19 02:48:04 +08:00
|
|
|
if(arrsz)
|
2013-11-19 00:48:00 +08:00
|
|
|
{
|
2013-11-19 02:48:04 +08:00
|
|
|
arrsz[0] = sz2d.height;
|
|
|
|
arrsz[1] = sz2d.width;
|
2013-11-19 00:48:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( k == STD_VECTOR )
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-01-30 00:19:15 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-11-19 00:48:00 +08:00
|
|
|
if( k == OPENGL_BUFFER )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( k == GPU_MAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return 2;
|
|
|
|
}
|
2013-11-19 02:48:04 +08:00
|
|
|
|
2013-11-19 00:48:00 +08:00
|
|
|
CV_Assert( k == CUDA_MEM );
|
|
|
|
//if( k == CUDA_MEM )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
size_t _InputArray::total(int i) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2012-12-22 21:56:02 +08:00
|
|
|
int k = kind();
|
|
|
|
|
|
|
|
if( k == MAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return ((const Mat*)obj)->total();
|
|
|
|
}
|
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == UMAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return ((const UMat*)obj)->total();
|
|
|
|
}
|
|
|
|
|
2012-12-22 21:56:02 +08:00
|
|
|
if( k == STD_VECTOR_MAT )
|
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
|
2012-12-22 21:56:02 +08:00
|
|
|
if( i < 0 )
|
|
|
|
return vv.size();
|
|
|
|
|
|
|
|
CV_Assert( i < (int)vv.size() );
|
|
|
|
return vv[i].total();
|
|
|
|
}
|
|
|
|
|
2014-01-30 00:19:15 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
return size(i).area();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
int _InputArray::type(int i) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MAT )
|
|
|
|
return ((const Mat*)obj)->type();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == UMAT )
|
|
|
|
return ((const UMat*)obj)->type();
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == EXPR )
|
|
|
|
return ((const MatExpr*)obj)->type();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-10-24 21:23:48 +08:00
|
|
|
if( k == MATX || k == STD_VECTOR || k == STD_VECTOR_VECTOR )
|
|
|
|
return CV_MAT_TYPE(flags);
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == NONE )
|
|
|
|
return -1;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2014-01-30 00:19:15 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2011-11-30 14:20:29 +08:00
|
|
|
if( k == STD_VECTOR_MAT )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
|
2013-10-24 21:23:48 +08:00
|
|
|
if( vv.empty() )
|
|
|
|
{
|
|
|
|
CV_Assert((flags & FIXED_TYPE) != 0);
|
|
|
|
return CV_MAT_TYPE(flags);
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
CV_Assert( i < (int)vv.size() );
|
|
|
|
return vv[i >= 0 ? i : 0].type();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-11-30 14:20:29 +08:00
|
|
|
if( k == OPENGL_BUFFER )
|
2013-03-06 19:18:44 +08:00
|
|
|
return ((const ogl::Buffer*)obj)->type();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-04-26 14:49:51 +08:00
|
|
|
if( k == GPU_MAT )
|
2013-08-28 19:45:13 +08:00
|
|
|
return ((const cuda::GpuMat*)obj)->type();
|
2013-04-26 14:49:51 +08:00
|
|
|
|
|
|
|
CV_Assert( k == CUDA_MEM );
|
|
|
|
//if( k == CUDA_MEM )
|
2013-08-28 19:45:13 +08:00
|
|
|
return ((const cuda::CudaMem*)obj)->type();
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
int _InputArray::depth(int i) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
return CV_MAT_DEPTH(type(i));
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
int _InputArray::channels(int i) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
return CV_MAT_CN(type(i));
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
bool _InputArray::empty() const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MAT )
|
|
|
|
return ((const Mat*)obj)->empty();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == UMAT )
|
|
|
|
return ((const UMat*)obj)->empty();
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == EXPR )
|
|
|
|
return false;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MATX )
|
|
|
|
return false;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR )
|
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
|
2011-04-17 21:14:45 +08:00
|
|
|
return v.empty();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == NONE )
|
|
|
|
return true;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR_VECTOR )
|
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
|
2011-04-17 21:14:45 +08:00
|
|
|
return vv.empty();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-11-30 14:20:29 +08:00
|
|
|
if( k == STD_VECTOR_MAT )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
|
2011-04-17 21:14:45 +08:00
|
|
|
return vv.empty();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2014-01-30 00:19:15 +08:00
|
|
|
if( k == STD_VECTOR_UMAT )
|
|
|
|
{
|
|
|
|
const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
|
|
|
|
return vv.empty();
|
|
|
|
}
|
|
|
|
|
2011-11-30 14:20:29 +08:00
|
|
|
if( k == OPENGL_BUFFER )
|
2013-03-06 19:18:44 +08:00
|
|
|
return ((const ogl::Buffer*)obj)->empty();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-04-26 14:49:51 +08:00
|
|
|
if( k == GPU_MAT )
|
2013-08-28 19:45:13 +08:00
|
|
|
return ((const cuda::GpuMat*)obj)->empty();
|
2013-04-26 14:49:51 +08:00
|
|
|
|
|
|
|
CV_Assert( k == CUDA_MEM );
|
|
|
|
//if( k == CUDA_MEM )
|
2013-08-28 19:45:13 +08:00
|
|
|
return ((const cuda::CudaMem*)obj)->empty();
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-11-19 00:48:00 +08:00
|
|
|
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;
|
|
|
|
|
|
|
|
if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR)
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2014-02-01 01:00:16 +08:00
|
|
|
CV_Error(CV_StsNotImplemented, "Unknown/unsupported array type");
|
2013-11-19 00:48:00 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-01-14 18:10:24 +08:00
|
|
|
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;
|
|
|
|
|
|
|
|
if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR)
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-12-05 23:43:50 +08:00
|
|
|
size_t _InputArray::offset(int i) const
|
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
|
|
|
|
if( k == MAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
const Mat * const m = ((const Mat*)obj);
|
|
|
|
return (size_t)(m->data - m->datastart);
|
|
|
|
}
|
|
|
|
|
|
|
|
if( k == UMAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return ((const UMat*)obj)->offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR)
|
|
|
|
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 (size_t)(vv[i].data - vv[i].datastart);
|
|
|
|
}
|
|
|
|
|
2013-12-08 05:32:17 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-12-05 23:43:50 +08:00
|
|
|
if( k == GPU_MAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
const cuda::GpuMat * const m = ((const cuda::GpuMat*)obj);
|
|
|
|
return (size_t)(m->data - m->datastart);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR)
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-12-08 05:32:17 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-12-05 23:43:50 +08:00
|
|
|
if( k == GPU_MAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
return ((const cuda::GpuMat*)obj)->step;
|
|
|
|
}
|
|
|
|
|
|
|
|
CV_Error(Error::StsNotImplemented, "");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-19 00:48:00 +08:00
|
|
|
void _InputArray::copyTo(const _OutputArray& arr) const
|
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
|
|
|
|
if( k == NONE )
|
|
|
|
arr.release();
|
|
|
|
else if( k == MAT || k == MATX || k == STD_VECTOR )
|
|
|
|
{
|
|
|
|
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, "");
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
bool _OutputArray::fixedSize() const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2012-03-26 16:18:53 +08:00
|
|
|
return (flags & FIXED_SIZE) == FIXED_SIZE;
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
bool _OutputArray::fixedType() const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2012-03-26 16:18:53 +08:00
|
|
|
return (flags & FIXED_TYPE) == FIXED_TYPE;
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-06-09 23:00:04 +08:00
|
|
|
void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, int fixedDepthMask) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
|
|
|
{
|
2012-03-26 16:18:53 +08:00
|
|
|
CV_Assert(!fixedSize() || ((Mat*)obj)->size.operator()() == _sz);
|
2012-06-09 23:00:04 +08:00
|
|
|
CV_Assert(!fixedType() || ((Mat*)obj)->type() == mtype);
|
|
|
|
((Mat*)obj)->create(_sz, mtype);
|
2011-04-17 21:14:45 +08:00
|
|
|
return;
|
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
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;
|
|
|
|
}
|
2012-10-02 18:34:17 +08:00
|
|
|
if( k == GPU_MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
|
|
|
{
|
2013-08-28 19:45:13 +08:00
|
|
|
CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == _sz);
|
|
|
|
CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype);
|
|
|
|
((cuda::GpuMat*)obj)->create(_sz, mtype);
|
2012-10-02 18:34:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
|
|
|
{
|
2013-03-06 19:18:44 +08:00
|
|
|
CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == _sz);
|
|
|
|
CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype);
|
|
|
|
((ogl::Buffer*)obj)->create(_sz, mtype);
|
2012-11-30 21:35:28 +08:00
|
|
|
return;
|
|
|
|
}
|
2013-04-26 14:49:51 +08:00
|
|
|
if( k == CUDA_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
|
|
|
{
|
2013-08-28 19:45:13 +08:00
|
|
|
CV_Assert(!fixedSize() || ((cuda::CudaMem*)obj)->size() == _sz);
|
|
|
|
CV_Assert(!fixedType() || ((cuda::CudaMem*)obj)->type() == mtype);
|
|
|
|
((cuda::CudaMem*)obj)->create(_sz, mtype);
|
2013-04-26 14:49:51 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-06-09 23:00:04 +08:00
|
|
|
int sizes[] = {_sz.height, _sz.width};
|
|
|
|
create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
|
|
|
|
2014-03-20 22:38:31 +08:00
|
|
|
void _OutputArray::create(int _rows, int _cols, int mtype, int i, bool allowTransposed, int fixedDepthMask) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
|
|
|
{
|
2014-03-20 22:38:31 +08:00
|
|
|
CV_Assert(!fixedSize() || ((Mat*)obj)->size.operator()() == Size(_cols, _rows));
|
2012-06-09 23:00:04 +08:00
|
|
|
CV_Assert(!fixedType() || ((Mat*)obj)->type() == mtype);
|
2014-03-20 22:38:31 +08:00
|
|
|
((Mat*)obj)->create(_rows, _cols, mtype);
|
2011-04-17 21:14:45 +08:00
|
|
|
return;
|
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == UMAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
|
|
|
{
|
2014-03-20 22:38:31 +08:00
|
|
|
CV_Assert(!fixedSize() || ((UMat*)obj)->size.operator()() == Size(_cols, _rows));
|
2013-10-22 18:05:15 +08:00
|
|
|
CV_Assert(!fixedType() || ((UMat*)obj)->type() == mtype);
|
2014-03-20 22:38:31 +08:00
|
|
|
((UMat*)obj)->create(_rows, _cols, mtype);
|
2013-10-22 18:05:15 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-10-02 18:34:17 +08:00
|
|
|
if( k == GPU_MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
|
|
|
{
|
2014-03-20 22:38:31 +08:00
|
|
|
CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == Size(_cols, _rows));
|
2013-08-28 19:45:13 +08:00
|
|
|
CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype);
|
2014-03-20 22:38:31 +08:00
|
|
|
((cuda::GpuMat*)obj)->create(_rows, _cols, mtype);
|
2012-10-02 18:34:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-11-30 21:35:28 +08:00
|
|
|
if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
|
|
|
{
|
2014-03-20 22:38:31 +08:00
|
|
|
CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == Size(_cols, _rows));
|
2013-03-06 19:18:44 +08:00
|
|
|
CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype);
|
2014-03-20 22:38:31 +08:00
|
|
|
((ogl::Buffer*)obj)->create(_rows, _cols, mtype);
|
2012-11-30 21:35:28 +08:00
|
|
|
return;
|
|
|
|
}
|
2013-04-26 14:49:51 +08:00
|
|
|
if( k == CUDA_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
|
|
|
{
|
2014-03-20 22:38:31 +08:00
|
|
|
CV_Assert(!fixedSize() || ((cuda::CudaMem*)obj)->size() == Size(_cols, _rows));
|
2013-08-28 19:45:13 +08:00
|
|
|
CV_Assert(!fixedType() || ((cuda::CudaMem*)obj)->type() == mtype);
|
2014-03-20 22:38:31 +08:00
|
|
|
((cuda::CudaMem*)obj)->create(_rows, _cols, mtype);
|
2013-04-26 14:49:51 +08:00
|
|
|
return;
|
|
|
|
}
|
2014-03-20 22:38:31 +08:00
|
|
|
int sizes[] = {_rows, _cols};
|
2012-06-09 23:00:04 +08:00
|
|
|
create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-11-19 02:48:04 +08:00
|
|
|
void _OutputArray::create(int d, const int* sizes, int mtype, int i,
|
2013-10-22 18:05:15 +08:00
|
|
|
bool allowTransposed, int fixedDepthMask) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
2012-06-09 23:00:04 +08:00
|
|
|
mtype = CV_MAT_TYPE(mtype);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
Mat& m = *(Mat*)obj;
|
2012-03-26 16:18:53 +08:00
|
|
|
if( allowTransposed )
|
2011-04-19 00:32:43 +08:00
|
|
|
{
|
|
|
|
if( !m.isContinuous() )
|
2012-03-26 16:18:53 +08:00
|
|
|
{
|
|
|
|
CV_Assert(!fixedType() && !fixedSize());
|
2011-04-19 00:32:43 +08:00
|
|
|
m.release();
|
2012-03-26 16:18:53 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-11-19 02:48:04 +08:00
|
|
|
if( d == 2 && m.dims == 2 && m.data &&
|
2012-06-09 23:00:04 +08:00
|
|
|
m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
|
2011-04-19 00:32:43 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-03-26 16:18:53 +08:00
|
|
|
|
|
|
|
if(fixedType())
|
|
|
|
{
|
2012-06-09 23:00:04 +08:00
|
|
|
if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
|
|
|
|
mtype = m.type();
|
2012-03-26 16:18:53 +08:00
|
|
|
else
|
2012-06-09 23:00:04 +08:00
|
|
|
CV_Assert(CV_MAT_TYPE(mtype) == m.type());
|
2012-03-26 16:18:53 +08:00
|
|
|
}
|
|
|
|
if(fixedSize())
|
|
|
|
{
|
2013-11-19 02:48:04 +08:00
|
|
|
CV_Assert(m.dims == d);
|
|
|
|
for(int j = 0; j < d; ++j)
|
2012-06-09 23:00:04 +08:00
|
|
|
CV_Assert(m.size[j] == sizes[j]);
|
2012-03-26 16:18:53 +08:00
|
|
|
}
|
2013-11-19 02:48:04 +08:00
|
|
|
m.create(d, sizes, mtype);
|
2011-04-17 21:14:45 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == UMAT )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
UMat& m = *(UMat*)obj;
|
|
|
|
if( allowTransposed )
|
|
|
|
{
|
|
|
|
if( !m.isContinuous() )
|
|
|
|
{
|
|
|
|
CV_Assert(!fixedType() && !fixedSize());
|
|
|
|
m.release();
|
|
|
|
}
|
|
|
|
|
2013-11-19 02:48:04 +08:00
|
|
|
if( d == 2 && m.dims == 2 && !m.empty() &&
|
2013-10-22 18:05:15 +08:00
|
|
|
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())
|
|
|
|
{
|
2013-11-19 02:48:04 +08:00
|
|
|
CV_Assert(m.dims == d);
|
|
|
|
for(int j = 0; j < d; ++j)
|
2013-10-22 18:05:15 +08:00
|
|
|
CV_Assert(m.size[j] == sizes[j]);
|
|
|
|
}
|
2013-11-19 02:48:04 +08:00
|
|
|
m.create(d, sizes, mtype);
|
2013-10-22 18:05:15 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MATX )
|
|
|
|
{
|
|
|
|
CV_Assert( i < 0 );
|
|
|
|
int type0 = CV_MAT_TYPE(flags);
|
2012-06-09 23:00:04 +08:00
|
|
|
CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == 1 && ((1 << type0) & fixedDepthMask) != 0) );
|
2013-11-19 02:48:04 +08:00
|
|
|
CV_Assert( d == 2 && ((sizes[0] == sz.height && sizes[1] == sz.width) ||
|
2012-06-09 23:00:04 +08:00
|
|
|
(allowTransposed && sizes[0] == sz.width && sizes[1] == sz.height)));
|
2011-04-17 21:14:45 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR || k == STD_VECTOR_VECTOR )
|
|
|
|
{
|
2013-11-19 02:48:04 +08:00
|
|
|
CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) );
|
2012-06-09 23:00:04 +08:00
|
|
|
size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0;
|
2013-02-25 00:14:01 +08:00
|
|
|
std::vector<uchar>* v = (std::vector<uchar>*)obj;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR_VECTOR )
|
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
std::vector<std::vector<uchar> >& vv = *(std::vector<std::vector<uchar> >*)obj;
|
2011-04-17 21:14:45 +08:00
|
|
|
if( i < 0 )
|
|
|
|
{
|
2012-03-26 16:18:53 +08:00
|
|
|
CV_Assert(!fixedSize() || len == vv.size());
|
2011-04-17 21:14:45 +08:00
|
|
|
vv.resize(len);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
CV_Assert( i < (int)vv.size() );
|
|
|
|
v = &vv[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
CV_Assert( i < 0 );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
int type0 = CV_MAT_TYPE(flags);
|
2012-06-09 23:00:04 +08:00
|
|
|
CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
int esz = CV_ELEM_SIZE(type0);
|
2013-02-25 00:14:01 +08:00
|
|
|
CV_Assert(!fixedSize() || len == ((std::vector<uchar>*)v)->size() / esz);
|
2011-04-17 21:14:45 +08:00
|
|
|
switch( esz )
|
|
|
|
{
|
|
|
|
case 1:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<uchar>*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec2b>*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 3:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec3b>*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 4:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<int>*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 6:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec3s>*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 8:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec2i>*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 12:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec3i>*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 16:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec4i>*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 24:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec6i>*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 32:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec8i>*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 36:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec<int, 9> >*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 48:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec<int, 12> >*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 64:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec<int, 16> >*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 128:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec<int, 32> >*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 256:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec<int, 64> >*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
case 512:
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Vec<int, 128> >*)v)->resize(len);
|
2011-04-17 21:14:45 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CV_Error_(CV_StsBadArg, ("Vectors with element size %d are not supported. Please, modify OutputArray::create()\n", esz));
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == NONE )
|
|
|
|
{
|
2012-06-08 01:21:29 +08:00
|
|
|
CV_Error(CV_StsNullPtr, "create() called for the missing output array" );
|
2011-04-17 21:14:45 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == STD_VECTOR_MAT )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
std::vector<Mat>& v = *(std::vector<Mat>*)obj;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( i < 0 )
|
|
|
|
{
|
2013-11-19 02:48:04 +08:00
|
|
|
CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) );
|
2012-06-09 23:00:04 +08:00
|
|
|
size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0, len0 = v.size();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-05-11 21:36:48 +08:00
|
|
|
CV_Assert(!fixedSize() || len == len0);
|
2011-04-17 21:14:45 +08:00
|
|
|
v.resize(len);
|
2012-05-11 21:36:48 +08:00
|
|
|
if( fixedType() )
|
|
|
|
{
|
2012-06-09 23:00:04 +08:00
|
|
|
int _type = CV_MAT_TYPE(flags);
|
2012-05-11 21:36:48 +08:00
|
|
|
for( size_t j = len0; j < len; j++ )
|
|
|
|
{
|
2013-03-31 17:24:36 +08:00
|
|
|
if( v[j].type() == _type )
|
2012-05-11 21:36:48 +08:00
|
|
|
continue;
|
2013-03-31 17:24:36 +08:00
|
|
|
CV_Assert( v[j].empty() );
|
|
|
|
v[j].flags = (v[j].flags & ~CV_MAT_TYPE_MASK) | _type;
|
2012-05-11 21:36:48 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
CV_Assert( i < (int)v.size() );
|
|
|
|
Mat& m = v[i];
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-03-26 16:18:53 +08:00
|
|
|
if( allowTransposed )
|
2011-04-19 00:32:43 +08:00
|
|
|
{
|
|
|
|
if( !m.isContinuous() )
|
2012-03-26 16:18:53 +08:00
|
|
|
{
|
|
|
|
CV_Assert(!fixedType() && !fixedSize());
|
2011-04-19 00:32:43 +08:00
|
|
|
m.release();
|
2012-03-26 16:18:53 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-11-19 02:48:04 +08:00
|
|
|
if( d == 2 && m.dims == 2 && m.data &&
|
2012-06-09 23:00:04 +08:00
|
|
|
m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
|
2011-04-19 00:32:43 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-03-26 16:18:53 +08:00
|
|
|
|
|
|
|
if(fixedType())
|
|
|
|
{
|
2012-06-09 23:00:04 +08:00
|
|
|
if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
|
|
|
|
mtype = m.type();
|
2012-03-26 16:18:53 +08:00
|
|
|
else
|
2014-01-25 05:58:55 +08:00
|
|
|
CV_Assert(CV_MAT_TYPE(mtype) == m.type());
|
2012-03-26 16:18:53 +08:00
|
|
|
}
|
|
|
|
if(fixedSize())
|
|
|
|
{
|
2013-11-19 02:48:04 +08:00
|
|
|
CV_Assert(m.dims == d);
|
|
|
|
for(int j = 0; j < d; ++j)
|
2012-06-09 23:00:04 +08:00
|
|
|
CV_Assert(m.size[j] == sizes[j]);
|
2012-03-26 16:18:53 +08:00
|
|
|
}
|
|
|
|
|
2013-11-19 02:48:04 +08:00
|
|
|
m.create(d, sizes, mtype);
|
2013-10-24 22:00:15 +08:00
|
|
|
return;
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2014-01-25 04:27:33 +08:00
|
|
|
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
|
2014-01-25 05:58:55 +08:00
|
|
|
CV_Assert(CV_MAT_TYPE(mtype) == m.type());
|
2014-01-25 04:27:33 +08:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-11-19 00:48:00 +08:00
|
|
|
void _OutputArray::createSameSize(const _InputArray& arr, int mtype) const
|
|
|
|
{
|
2013-11-19 02:48:04 +08:00
|
|
|
int arrsz[CV_MAX_DIM], d = arr.sizend(arrsz);
|
|
|
|
create(d, arrsz, mtype);
|
2013-11-19 00:48:00 +08:00
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void _OutputArray::release() const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2012-03-26 16:18:53 +08:00
|
|
|
CV_Assert(!fixedSize());
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
int k = kind();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MAT )
|
|
|
|
{
|
|
|
|
((Mat*)obj)->release();
|
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-12-23 21:37:41 +08:00
|
|
|
if( k == UMAT )
|
|
|
|
{
|
|
|
|
((UMat*)obj)->release();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-02 18:34:17 +08:00
|
|
|
if( k == GPU_MAT )
|
|
|
|
{
|
2013-08-28 19:45:13 +08:00
|
|
|
((cuda::GpuMat*)obj)->release();
|
2012-10-02 18:34:17 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-04-26 14:49:51 +08:00
|
|
|
if( k == CUDA_MEM )
|
|
|
|
{
|
2013-08-28 19:45:13 +08:00
|
|
|
((cuda::CudaMem*)obj)->release();
|
2013-04-26 14:49:51 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-11-30 21:35:28 +08:00
|
|
|
if( k == OPENGL_BUFFER )
|
|
|
|
{
|
2013-03-06 19:18:44 +08:00
|
|
|
((ogl::Buffer*)obj)->release();
|
2012-11-30 21:35:28 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == NONE )
|
|
|
|
return;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR )
|
|
|
|
{
|
|
|
|
create(Size(), CV_MAT_TYPE(flags));
|
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == STD_VECTOR_VECTOR )
|
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<std::vector<uchar> >*)obj)->clear();
|
2011-04-17 21:14:45 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
if( k == STD_VECTOR_MAT )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
((std::vector<Mat>*)obj)->clear();
|
2013-10-24 22:00:15 +08:00
|
|
|
return;
|
2012-06-08 01:21:29 +08:00
|
|
|
}
|
2013-10-22 18:05:15 +08:00
|
|
|
|
2013-12-23 21:37:41 +08:00
|
|
|
if( k == STD_VECTOR_UMAT )
|
|
|
|
{
|
|
|
|
((std::vector<UMat>*)obj)->clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void _OutputArray::clear() const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( k == MAT )
|
|
|
|
{
|
2012-03-26 16:18:53 +08:00
|
|
|
CV_Assert(!fixedSize());
|
2011-04-17 21:14:45 +08:00
|
|
|
((Mat*)obj)->resize(0);
|
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
release();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
bool _OutputArray::needed() const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
return kind() != NONE;
|
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
Mat& _OutputArray::getMatRef(int i) const
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
if( i < 0 )
|
|
|
|
{
|
|
|
|
CV_Assert( k == MAT );
|
|
|
|
return *(Mat*)obj;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CV_Assert( k == STD_VECTOR_MAT );
|
2013-02-25 00:14:01 +08:00
|
|
|
std::vector<Mat>& v = *(std::vector<Mat>*)obj;
|
2011-04-17 21:14:45 +08:00
|
|
|
CV_Assert( i < (int)v.size() );
|
|
|
|
return v[i];
|
|
|
|
}
|
|
|
|
}
|
2011-06-06 22:51:27 +08:00
|
|
|
|
2014-01-27 22:34:19 +08:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-28 19:45:13 +08:00
|
|
|
cuda::GpuMat& _OutputArray::getGpuMatRef() const
|
2012-10-02 18:34:17 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
CV_Assert( k == GPU_MAT );
|
2013-08-28 19:45:13 +08:00
|
|
|
return *(cuda::GpuMat*)obj;
|
2012-10-02 18:34:17 +08:00
|
|
|
}
|
|
|
|
|
2013-03-06 19:18:44 +08:00
|
|
|
ogl::Buffer& _OutputArray::getOGlBufferRef() const
|
2012-11-30 21:35:28 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
CV_Assert( k == OPENGL_BUFFER );
|
2013-03-06 19:18:44 +08:00
|
|
|
return *(ogl::Buffer*)obj;
|
2012-11-30 21:35:28 +08:00
|
|
|
}
|
|
|
|
|
2013-08-28 19:45:13 +08:00
|
|
|
cuda::CudaMem& _OutputArray::getCudaMemRef() const
|
2013-04-26 14:49:51 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
CV_Assert( k == CUDA_MEM );
|
2013-08-28 19:45:13 +08:00
|
|
|
return *(cuda::CudaMem*)obj;
|
2013-04-26 14:49:51 +08:00
|
|
|
}
|
|
|
|
|
2014-01-22 23:13:29 +08:00
|
|
|
void _OutputArray::setTo(const _InputArray& arr, const _InputArray & mask) const
|
2013-11-19 00:48:00 +08:00
|
|
|
{
|
|
|
|
int k = kind();
|
|
|
|
|
|
|
|
if( k == NONE )
|
|
|
|
;
|
|
|
|
else if( k == MAT || k == MATX || k == STD_VECTOR )
|
|
|
|
{
|
|
|
|
Mat m = getMat();
|
2014-01-22 23:13:29 +08:00
|
|
|
m.setTo(arr, mask);
|
2013-11-19 00:48:00 +08:00
|
|
|
}
|
|
|
|
else if( k == UMAT )
|
2014-01-22 23:13:29 +08:00
|
|
|
((UMat*)obj)->setTo(arr, mask);
|
|
|
|
else if( k == GPU_MAT )
|
|
|
|
{
|
|
|
|
Mat value = arr.getMat();
|
|
|
|
CV_Assert( checkScalar(value, type(), arr.kind(), _InputArray::GPU_MAT) );
|
|
|
|
((cuda::GpuMat*)obj)->setTo(Scalar(Vec<double, 4>((double *)value.data)), mask);
|
|
|
|
}
|
2013-11-19 00:48:00 +08:00
|
|
|
else
|
|
|
|
CV_Error(Error::StsNotImplemented, "");
|
|
|
|
}
|
|
|
|
|
2014-02-14 19:36:04 +08:00
|
|
|
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CV_Error(Error::StsNotImplemented, "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-22 18:05:15 +08:00
|
|
|
static _InputOutputArray _none;
|
|
|
|
InputOutputArray noArray() { return _none; }
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
|
|
|
|
2010-10-19 19:57:37 +08:00
|
|
|
/*************************************************************************************************\
|
|
|
|
Matrix Operations
|
|
|
|
\*************************************************************************************************/
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
void cv::hconcat(const Mat* src, size_t nsrc, OutputArray _dst)
|
2010-11-24 00:39:20 +08:00
|
|
|
{
|
|
|
|
if( nsrc == 0 || !src )
|
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
_dst.release();
|
2010-11-24 00:39:20 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-11-24 00:39:20 +08:00
|
|
|
int totalCols = 0, cols = 0;
|
|
|
|
size_t i;
|
|
|
|
for( i = 0; i < nsrc; i++ )
|
|
|
|
{
|
|
|
|
CV_Assert( !src[i].empty() && src[i].dims <= 2 &&
|
|
|
|
src[i].rows == src[0].rows &&
|
|
|
|
src[i].type() == src[0].type());
|
|
|
|
totalCols += src[i].cols;
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
_dst.create( src[0].rows, totalCols, src[0].type());
|
|
|
|
Mat dst = _dst.getMat();
|
2010-11-24 00:39:20 +08:00
|
|
|
for( i = 0; i < nsrc; i++ )
|
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat dpart = dst(Rect(cols, 0, src[i].cols, src[i].rows));
|
2010-11-24 00:39:20 +08:00
|
|
|
src[i].copyTo(dpart);
|
|
|
|
cols += src[i].cols;
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::hconcat(InputArray src1, InputArray src2, OutputArray dst)
|
2010-11-24 00:39:20 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat src[] = {src1.getMat(), src2.getMat()};
|
2010-11-24 00:39:20 +08:00
|
|
|
hconcat(src, 2, dst);
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::hconcat(InputArray _src, OutputArray dst)
|
2010-11-24 00:39:20 +08:00
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
std::vector<Mat> src;
|
2011-04-17 21:14:45 +08:00
|
|
|
_src.getMatVector(src);
|
2010-11-24 00:39:20 +08:00
|
|
|
hconcat(!src.empty() ? &src[0] : 0, src.size(), dst);
|
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
void cv::vconcat(const Mat* src, size_t nsrc, OutputArray _dst)
|
2010-11-24 00:39:20 +08:00
|
|
|
{
|
|
|
|
if( nsrc == 0 || !src )
|
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
_dst.release();
|
2010-11-24 00:39:20 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-11-24 00:39:20 +08:00
|
|
|
int totalRows = 0, rows = 0;
|
|
|
|
size_t i;
|
|
|
|
for( i = 0; i < nsrc; i++ )
|
|
|
|
{
|
|
|
|
CV_Assert( !src[i].empty() && src[i].dims <= 2 &&
|
|
|
|
src[i].cols == src[0].cols &&
|
|
|
|
src[i].type() == src[0].type());
|
|
|
|
totalRows += src[i].rows;
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
_dst.create( totalRows, src[0].cols, src[0].type());
|
|
|
|
Mat dst = _dst.getMat();
|
2010-11-24 00:39:20 +08:00
|
|
|
for( i = 0; i < nsrc; i++ )
|
|
|
|
{
|
|
|
|
Mat dpart(dst, Rect(0, rows, src[i].cols, src[i].rows));
|
|
|
|
src[i].copyTo(dpart);
|
|
|
|
rows += src[i].rows;
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::vconcat(InputArray src1, InputArray src2, OutputArray dst)
|
2010-11-24 00:39:20 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat src[] = {src1.getMat(), src2.getMat()};
|
2010-11-24 00:39:20 +08:00
|
|
|
vconcat(src, 2, dst);
|
2012-06-08 01:21:29 +08:00
|
|
|
}
|
2010-11-24 00:39:20 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::vconcat(InputArray _src, OutputArray dst)
|
2010-11-24 00:39:20 +08:00
|
|
|
{
|
2013-02-25 00:14:01 +08:00
|
|
|
std::vector<Mat> src;
|
2011-04-17 21:14:45 +08:00
|
|
|
_src.getMatVector(src);
|
2010-11-24 00:39:20 +08:00
|
|
|
vconcat(!src.empty() ? &src[0] : 0, src.size(), dst);
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-19 19:57:37 +08:00
|
|
|
//////////////////////////////////////// set identity ////////////////////////////////////////////
|
2013-11-30 21:40:03 +08:00
|
|
|
|
2014-01-25 01:03:31 +08:00
|
|
|
#ifdef HAVE_OPENCL
|
|
|
|
|
2013-11-30 21:40:03 +08:00
|
|
|
namespace cv {
|
|
|
|
|
|
|
|
static bool ocl_setIdentity( InputOutputArray _m, const Scalar& s )
|
|
|
|
{
|
2014-03-18 23:42:04 +08:00
|
|
|
int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
|
|
|
|
sctype = CV_MAKE_TYPE(depth, cn == 3 ? 4 : cn);
|
2013-11-30 21:40:03 +08:00
|
|
|
|
|
|
|
ocl::Kernel k("setIdentity", ocl::core::set_identity_oclsrc,
|
2014-03-18 23:42:04 +08:00
|
|
|
format("-D T=%s -D T1=%s -D cn=%d -D ST=%s", ocl::memopTypeToStr(type),
|
|
|
|
ocl::memopTypeToStr(depth), cn, ocl::memopTypeToStr(sctype)));
|
2013-12-03 04:41:07 +08:00
|
|
|
if (k.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
UMat m = _m.getUMat();
|
2014-03-18 23:42:04 +08:00
|
|
|
k.args(ocl::KernelArg::WriteOnly(m), ocl::KernelArg::Constant(Mat(1, 1, sctype, s)));
|
2013-11-30 21:40:03 +08:00
|
|
|
|
|
|
|
size_t globalsize[2] = { m.cols, m.rows };
|
|
|
|
return k.run(2, globalsize, NULL, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-01-25 01:03:31 +08:00
|
|
|
#endif
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
void cv::setIdentity( InputOutputArray _m, const Scalar& s )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2013-11-30 21:40:03 +08:00
|
|
|
CV_Assert( _m.dims() <= 2 );
|
|
|
|
|
2014-01-25 01:03:31 +08:00
|
|
|
CV_OCL_RUN(_m.isUMat(),
|
|
|
|
ocl_setIdentity(_m, s))
|
2013-11-30 21:40:03 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat m = _m.getMat();
|
2010-05-12 01:44:00 +08:00
|
|
|
int i, j, rows = m.rows, cols = m.cols, type = m.type();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( type == CV_32FC1 )
|
|
|
|
{
|
|
|
|
float* data = (float*)m.data;
|
|
|
|
float val = (float)s[0];
|
|
|
|
size_t step = m.step/sizeof(data[0]);
|
|
|
|
|
|
|
|
for( i = 0; i < rows; i++, data += step )
|
|
|
|
{
|
|
|
|
for( j = 0; j < cols; j++ )
|
|
|
|
data[j] = 0;
|
|
|
|
if( i < cols )
|
|
|
|
data[i] = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( type == CV_64FC1 )
|
|
|
|
{
|
|
|
|
double* data = (double*)m.data;
|
|
|
|
double val = s[0];
|
|
|
|
size_t step = m.step/sizeof(data[0]);
|
|
|
|
|
|
|
|
for( i = 0; i < rows; i++, data += step )
|
|
|
|
{
|
|
|
|
for( j = 0; j < cols; j++ )
|
|
|
|
data[j] = j == i ? val : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m = Scalar(0);
|
|
|
|
m.diag() = s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-08 01:21:29 +08:00
|
|
|
//////////////////////////////////////////// trace ///////////////////////////////////////////
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
cv::Scalar cv::trace( InputArray _m )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat m = _m.getMat();
|
2010-10-12 20:31:40 +08:00
|
|
|
CV_Assert( m.dims <= 2 );
|
2010-05-12 01:44:00 +08:00
|
|
|
int i, type = m.type();
|
|
|
|
int nm = std::min(m.rows, m.cols);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( type == CV_32FC1 )
|
|
|
|
{
|
|
|
|
const float* ptr = (const float*)m.data;
|
|
|
|
size_t step = m.step/sizeof(ptr[0]) + 1;
|
|
|
|
double _s = 0;
|
|
|
|
for( i = 0; i < nm; i++ )
|
|
|
|
_s += ptr[i*step];
|
|
|
|
return _s;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( type == CV_64FC1 )
|
|
|
|
{
|
|
|
|
const double* ptr = (const double*)m.data;
|
|
|
|
size_t step = m.step/sizeof(ptr[0]) + 1;
|
|
|
|
double _s = 0;
|
|
|
|
for( i = 0; i < nm; i++ )
|
|
|
|
_s += ptr[i*step];
|
|
|
|
return _s;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
return cv::sum(m.diag());
|
|
|
|
}
|
|
|
|
|
2010-10-19 19:57:37 +08:00
|
|
|
////////////////////////////////////// transpose /////////////////////////////////////////
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
namespace cv
|
|
|
|
{
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
template<typename T> static void
|
2011-04-17 21:14:45 +08:00
|
|
|
transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2012-02-10 14:05:04 +08:00
|
|
|
int i=0, j, m = sz.width, n = sz.height;
|
|
|
|
|
2012-06-08 01:21:29 +08:00
|
|
|
#if CV_ENABLE_UNROLLED
|
2012-02-10 14:05:04 +08:00
|
|
|
for(; i <= m - 4; i += 4 )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
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));
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
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));
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
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];
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
}
|
2012-02-10 14:05:04 +08:00
|
|
|
#endif
|
2011-04-17 21:14:45 +08:00
|
|
|
for( ; i < m; i++ )
|
|
|
|
{
|
|
|
|
T* d0 = (T*)(dst + dstep*i);
|
2012-02-10 14:05:04 +08:00
|
|
|
j = 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
#if CV_ENABLE_UNROLLED
|
2012-02-10 14:05:04 +08:00
|
|
|
for(; j <= n - 4; j += 4 )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
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));
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
|
|
|
|
}
|
2012-02-10 14:05:04 +08:00
|
|
|
#endif
|
2011-04-17 21:14:45 +08:00
|
|
|
for( ; j < n; j++ )
|
|
|
|
{
|
|
|
|
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
|
|
|
|
d0[j] = s0[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
template<typename T> static void
|
|
|
|
transposeI_( uchar* data, size_t step, int n )
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
for( i = 0; i < n; i++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
T* row = (T*)(data + step*i);
|
|
|
|
uchar* data1 = data + i*sizeof(T);
|
2011-04-17 21:14:45 +08:00
|
|
|
for( j = i+1; j < n; j++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
std::swap( row[j], *(T*)(data1 + step*j) );
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
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 );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
#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); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
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)
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
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
|
|
|
|
};
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
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
|
|
|
|
};
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2014-01-25 01:03:31 +08:00
|
|
|
#ifdef HAVE_OPENCL
|
|
|
|
|
2013-11-30 22:42:09 +08:00
|
|
|
static inline int divUp(int a, int b)
|
|
|
|
{
|
|
|
|
return (a + b - 1) / b;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool ocl_transpose( InputArray _src, OutputArray _dst )
|
|
|
|
{
|
|
|
|
const int TILE_DIM = 32, BLOCK_ROWS = 8;
|
2014-03-12 04:08:55 +08:00
|
|
|
int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type);
|
2013-11-30 22:42:09 +08:00
|
|
|
|
|
|
|
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";
|
|
|
|
}
|
|
|
|
|
|
|
|
ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc,
|
2014-03-12 04:08:55 +08:00
|
|
|
format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d",
|
|
|
|
ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth),
|
|
|
|
cn, TILE_DIM, BLOCK_ROWS));
|
2014-02-01 19:07:03 +08:00
|
|
|
if (k.empty())
|
|
|
|
return false;
|
|
|
|
|
2013-11-30 22:42:09 +08:00
|
|
|
if (inplace)
|
|
|
|
k.args(ocl::KernelArg::ReadWriteNoSize(dst), dst.rows);
|
|
|
|
else
|
|
|
|
k.args(ocl::KernelArg::ReadOnly(src),
|
|
|
|
ocl::KernelArg::WriteOnlyNoSize(dst));
|
|
|
|
|
|
|
|
size_t localsize[3] = { TILE_DIM, BLOCK_ROWS, 1 };
|
|
|
|
size_t globalsize[3] = { src.cols, inplace ? src.rows : divUp(src.rows, TILE_DIM) * BLOCK_ROWS, 1 };
|
|
|
|
|
|
|
|
return k.run(2, globalsize, localsize, false);
|
|
|
|
}
|
|
|
|
|
2014-01-25 01:03:31 +08:00
|
|
|
#endif
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::transpose( InputArray _src, OutputArray _dst )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
2013-11-30 22:42:09 +08:00
|
|
|
int type = _src.type(), esz = CV_ELEM_SIZE(type);
|
|
|
|
CV_Assert( _src.dims() <= 2 && esz <= 32 );
|
|
|
|
|
2014-01-25 01:03:31 +08:00
|
|
|
CV_OCL_RUN(_dst.isUMat(),
|
|
|
|
ocl_transpose(_src, _dst))
|
2013-11-30 22:42:09 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat src = _src.getMat();
|
2013-02-14 19:36:20 +08:00
|
|
|
if( src.empty() )
|
|
|
|
{
|
|
|
|
_dst.release();
|
|
|
|
return;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
_dst.create(src.cols, src.rows, src.type());
|
|
|
|
Mat dst = _dst.getMat();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-01-31 23:44:16 +08:00
|
|
|
// handle the case of single-column/single-row matrices, stored in STL vectors.
|
|
|
|
if( src.rows != dst.cols || src.cols != dst.rows )
|
|
|
|
{
|
2013-02-01 00:26:16 +08:00
|
|
|
CV_Assert( src.size() == dst.size() && (src.cols == 1 || src.rows == 1) );
|
2013-01-31 23:44:16 +08:00
|
|
|
src.copyTo(dst);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-04-09 20:01:51 +08:00
|
|
|
#if defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY)
|
2014-04-04 03:41:13 +08:00
|
|
|
typedef IppStatus (CV_STDCALL * ippiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize);
|
|
|
|
ippiTranspose ippFunc =
|
|
|
|
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;
|
|
|
|
|
|
|
|
IppiSize roiSize = { src.cols, src.rows };
|
2014-04-16 23:23:44 +08:00
|
|
|
if (ippFunc != 0)
|
|
|
|
{
|
|
|
|
if (ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, roiSize) >= 0)
|
|
|
|
return;
|
|
|
|
setIppErrorStatus();
|
|
|
|
}
|
2014-04-04 03:41:13 +08:00
|
|
|
#endif
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( dst.data == src.data )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
TransposeInplaceFunc func = transposeInplaceTab[esz];
|
2010-05-12 01:44:00 +08:00
|
|
|
CV_Assert( func != 0 );
|
2013-12-01 00:05:54 +08:00
|
|
|
CV_Assert( dst.cols == dst.rows );
|
2011-04-17 21:14:45 +08:00
|
|
|
func( dst.data, dst.step, dst.rows );
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
TransposeFunc func = transposeTab[esz];
|
2010-05-12 01:44:00 +08:00
|
|
|
CV_Assert( func != 0 );
|
2011-04-17 21:14:45 +08:00
|
|
|
func( src.data, src.step, dst.data, dst.step, src.size() );
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-15 08:48:01 +08:00
|
|
|
////////////////////////////////////// completeSymm /////////////////////////////////////////
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
void cv::completeSymm( InputOutputArray _m, bool LtoR )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat m = _m.getMat();
|
2013-12-15 08:48:01 +08:00
|
|
|
size_t step = m.step, esz = m.elemSize();
|
|
|
|
CV_Assert( m.dims <= 2 && m.rows == m.cols );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2013-12-15 08:48:01 +08:00
|
|
|
int rows = m.rows;
|
|
|
|
int j0 = 0, j1 = rows;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2013-12-15 08:48:01 +08:00
|
|
|
uchar* data = m.data;
|
|
|
|
for( int i = 0; i < rows; i++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2013-12-15 08:48:01 +08:00
|
|
|
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);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
cv::Mat cv::Mat::cross(InputArray _m) const
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat m = _m.getMat();
|
2012-06-09 23:00:04 +08:00
|
|
|
int tp = type(), d = CV_MAT_DEPTH(tp);
|
|
|
|
CV_Assert( dims <= 2 && m.dims <= 2 && size() == m.size() && tp == m.type() &&
|
2010-05-12 01:44:00 +08:00
|
|
|
((rows == 3 && cols == 1) || (cols*channels() == 3 && rows == 1)));
|
2012-06-09 23:00:04 +08:00
|
|
|
Mat result(rows, cols, tp);
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-19 19:57:37 +08:00
|
|
|
////////////////////////////////////////// reduce ////////////////////////////////////////////
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
namespace cv
|
|
|
|
{
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
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;
|
|
|
|
ST* dst = (ST*)dstmat.data;
|
|
|
|
const T* src = (const T*)srcmat.data;
|
|
|
|
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;
|
2012-02-10 14:05:04 +08:00
|
|
|
i = 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
#if CV_ENABLE_UNROLLED
|
2012-02-10 14:05:04 +08:00
|
|
|
for(; i <= size.width - 4; i += 4 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2012-02-10 14:05:04 +08:00
|
|
|
#endif
|
2010-05-12 01:44:00 +08:00
|
|
|
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();
|
|
|
|
int i, k, cn = srcmat.channels();
|
|
|
|
size.width *= cn;
|
|
|
|
Op op;
|
|
|
|
|
|
|
|
for( int y = 0; y < size.height; y++ )
|
|
|
|
{
|
|
|
|
const T* src = (const T*)(srcmat.data + srcmat.step*y);
|
|
|
|
ST* dst = (ST*)(dstmat.data + dstmat.step*y);
|
|
|
|
if( size.width == cn )
|
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
dst[k] = src[k];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
{
|
|
|
|
WT a0 = src[k], a1 = src[k+cn];
|
|
|
|
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 )
|
|
|
|
{
|
2011-09-22 14:43:52 +08:00
|
|
|
a0 = op(a0, (WT)src[i+k]);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
a0 = op(a0, a1);
|
2011-12-22 14:22:16 +08:00
|
|
|
dst[k] = (ST)a0;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef void (*ReduceFunc)( const Mat& src, Mat& dst );
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2011-12-22 20:51:01 +08:00
|
|
|
|
|
|
|
#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> >
|
|
|
|
|
2014-04-15 22:29:53 +08:00
|
|
|
#if IPP_VERSION_X100 > 0 && !defined HAVE_IPP_ICV_ONLY
|
|
|
|
|
|
|
|
static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat)
|
|
|
|
{
|
|
|
|
cv::Size size = srcmat.size();
|
|
|
|
IppiSize roisize = { size.width, 1 };
|
|
|
|
int sstep = (int)srcmat.step, stype = srcmat.type(),
|
|
|
|
sdepth = CV_MAT_DEPTH(stype), ddepth = dstmat.depth();
|
|
|
|
|
|
|
|
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 ippFunc = 0;
|
|
|
|
ippiSumHint ippFuncHint = 0;
|
|
|
|
cv::ReduceFunc func = 0;
|
|
|
|
|
|
|
|
if (ddepth == CV_64F)
|
|
|
|
{
|
|
|
|
ippFunc =
|
|
|
|
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;
|
|
|
|
ippFuncHint =
|
|
|
|
stype == CV_32FC1 ? (ippiSumHint)ippiSum_32f_C1R :
|
|
|
|
stype == CV_32FC3 ? (ippiSumHint)ippiSum_32f_C3R :
|
|
|
|
stype == CV_32FC4 ? (ippiSumHint)ippiSum_32f_C4R : 0;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
CV_Assert(!(ippFunc && ippFuncHint) && func);
|
|
|
|
|
|
|
|
if (ippFunc)
|
|
|
|
{
|
|
|
|
for (int y = 0; y < size.height; ++y)
|
|
|
|
if (ippFunc(srcmat.data + sstep * y, sstep, roisize, dstmat.ptr<Ipp64f>(y)) < 0)
|
|
|
|
{
|
|
|
|
setIppErrorStatus();
|
|
|
|
cv::Mat dstroi = dstmat.rowRange(y, y + 1);
|
|
|
|
func(srcmat.rowRange(y, y + 1), dstroi);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (ippFuncHint)
|
|
|
|
{
|
|
|
|
for (int y = 0; y < size.height; ++y)
|
|
|
|
if (ippFuncHint(srcmat.data + sstep * y, sstep, roisize, dstmat.ptr<Ipp64f>(y), ippAlgHintAccurate) < 0)
|
|
|
|
{
|
|
|
|
setIppErrorStatus();
|
|
|
|
cv::Mat dstroi = dstmat.rowRange(y, y + 1);
|
|
|
|
func(srcmat.rowRange(y, y + 1), dstroi);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
func(srcmat, dstmat);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2011-12-22 20:51:01 +08:00
|
|
|
#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> >
|
|
|
|
|
2014-04-15 22:29:53 +08:00
|
|
|
#if IPP_VERSION_X100 > 0 && !defined HAVE_IPP_ICV_ONLY
|
|
|
|
#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
|
|
|
|
|
2014-04-15 21:43:06 +08:00
|
|
|
#if IPP_VERSION_X100 > 0 && !defined HAVE_IPP_ICV_ONLY
|
|
|
|
#define REDUCE_OP(favor, optype, type1, type2) \
|
|
|
|
static inline void reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \
|
|
|
|
{ \
|
|
|
|
typedef Ipp##favor IppType; \
|
|
|
|
cv::Size size = srcmat.size(); \
|
2014-04-15 22:29:53 +08:00
|
|
|
IppiSize roisize = ippiSize(size.width, 1);\
|
|
|
|
int sstep = (int)srcmat.step; \
|
|
|
|
\
|
2014-04-15 21:43:06 +08:00
|
|
|
if (srcmat.channels() == 1) \
|
|
|
|
{ \
|
|
|
|
for (int y = 0; y < size.height; ++y) \
|
2014-04-15 22:29:53 +08:00
|
|
|
if (ippi##optype##_##favor##_C1R(srcmat.ptr<IppType>(y), sstep, roisize, dstmat.ptr<IppType>(y)) < 0) \
|
2014-04-15 21:43:06 +08:00
|
|
|
{ \
|
2014-04-15 22:29:53 +08:00
|
|
|
setIppErrorStatus(); \
|
2014-04-15 21:43:06 +08:00
|
|
|
cv::Mat dstroi = dstmat.rowRange(y, y + 1); \
|
|
|
|
cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat.rowRange(y, y + 1), dstroi); \
|
|
|
|
} \
|
|
|
|
return; \
|
|
|
|
} \
|
|
|
|
cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat, dstmat); \
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IPP_VERSION_X100 > 0 && !defined HAVE_IPP_ICV_ONLY
|
|
|
|
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
|
2011-12-22 20:51:01 +08:00
|
|
|
#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> >
|
2014-04-15 21:43:06 +08:00
|
|
|
#endif
|
2011-12-22 20:51:01 +08:00
|
|
|
#define reduceMaxC64f reduceC_<double,double,OpMax<double> >
|
|
|
|
|
2014-04-15 21:43:06 +08:00
|
|
|
#if IPP_VERSION_X100 > 0 && !defined HAVE_IPP_ICV_ONLY
|
|
|
|
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
|
2011-12-22 20:51:01 +08:00
|
|
|
#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> >
|
2014-04-15 21:43:06 +08:00
|
|
|
#endif
|
2011-12-22 20:51:01 +08:00
|
|
|
#define reduceMinC64f reduceC_<double,double,OpMin<double> >
|
|
|
|
|
2014-01-25 01:03:31 +08:00
|
|
|
#ifdef HAVE_OPENCL
|
|
|
|
|
2014-01-17 00:52:45 +08:00
|
|
|
namespace cv {
|
|
|
|
|
|
|
|
static bool ocl_reduce(InputArray _src, OutputArray _dst,
|
|
|
|
int dim, int op, int op0, int stype, int dtype)
|
|
|
|
{
|
|
|
|
int sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype),
|
|
|
|
ddepth = CV_MAT_DEPTH(dtype), ddepth0 = ddepth;
|
|
|
|
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
|
|
|
|
|
|
|
if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (op == CV_REDUCE_AVG)
|
|
|
|
{
|
|
|
|
op = CV_REDUCE_SUM;
|
|
|
|
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" };
|
|
|
|
char cvt[40];
|
|
|
|
ocl::Kernel k("reduce", ocl::core::reduce2_oclsrc,
|
|
|
|
format("-D %s -D dim=%d -D cn=%d -D ddepth=%d -D srcT=%s -D dstT=%s -D convertToDT=%s%s",
|
|
|
|
ops[op], dim, cn, ddepth, ocl::typeToStr(sdepth), ocl::typeToStr(ddepth),
|
|
|
|
ocl::convertTypeStr(sdepth, ddepth, 1, cvt),
|
|
|
|
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
|
|
|
if (k.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
UMat src = _src.getUMat();
|
|
|
|
Size dsize(dim == 0 ? src.cols : 1, dim == 0 ? 1 : src.rows);
|
|
|
|
_dst.create(dsize, dtype);
|
|
|
|
UMat dst = _dst.getUMat(), temp = dst;
|
|
|
|
|
|
|
|
if (op0 == CV_REDUCE_AVG && sdepth < CV_32S && ddepth0 < CV_32S)
|
|
|
|
temp.create(dsize, CV_32SC(cn));
|
|
|
|
|
|
|
|
size_t globalsize = std::max(dsize.width, dsize.height);
|
|
|
|
|
|
|
|
k.args(ocl::KernelArg::ReadOnly(src),
|
|
|
|
ocl::KernelArg::WriteOnlyNoSize(temp));
|
|
|
|
if (!k.run(1, &globalsize, NULL, false))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (op0 == CV_REDUCE_AVG)
|
|
|
|
temp.convertTo(dst, ddepth0, 1. / (dim == 0 ? src.rows : src.cols));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-01-25 01:03:31 +08:00
|
|
|
#endif
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2014-01-17 00:52:45 +08:00
|
|
|
CV_Assert( _src.dims() <= 2 );
|
2010-05-12 01:44:00 +08:00
|
|
|
int op0 = op;
|
2014-01-17 00:52:45 +08:00
|
|
|
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
|
2010-05-12 01:44:00 +08:00
|
|
|
if( dtype < 0 )
|
2011-04-17 21:14:45 +08:00
|
|
|
dtype = _dst.fixedType() ? _dst.type() : stype;
|
2014-01-17 05:05:59 +08:00
|
|
|
dtype = CV_MAKETYPE(dtype >= 0 ? dtype : stype, cn);
|
2010-05-12 01:44:00 +08:00
|
|
|
int ddepth = CV_MAT_DEPTH(dtype);
|
|
|
|
|
2014-01-17 00:52:45 +08:00
|
|
|
CV_Assert( cn == CV_MAT_CN(dtype) );
|
2010-05-12 01:44:00 +08:00
|
|
|
CV_Assert( op == CV_REDUCE_SUM || op == CV_REDUCE_MAX ||
|
2011-12-22 20:51:01 +08:00
|
|
|
op == CV_REDUCE_MIN || op == CV_REDUCE_AVG );
|
2014-01-17 00:52:45 +08:00
|
|
|
|
2014-01-25 01:03:31 +08:00
|
|
|
CV_OCL_RUN(_dst.isUMat(),
|
|
|
|
ocl_reduce(_src, _dst, dim, op, op0, stype, dtype))
|
2014-01-17 00:52:45 +08:00
|
|
|
|
|
|
|
Mat src = _src.getMat();
|
|
|
|
_dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1, dtype);
|
|
|
|
Mat dst = _dst.getMat(), temp = dst;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
if( op == CV_REDUCE_AVG )
|
|
|
|
{
|
|
|
|
op = CV_REDUCE_SUM;
|
|
|
|
if( sdepth < CV_32S && ddepth < CV_32S )
|
2011-06-01 21:44:09 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
temp.create(dst.rows, dst.cols, CV_32SC(cn));
|
2011-06-01 21:44:09 +08:00
|
|
|
ddepth = CV_32S;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ReduceFunc func = 0;
|
|
|
|
if( dim == 0 )
|
|
|
|
{
|
|
|
|
if( op == CV_REDUCE_SUM )
|
|
|
|
{
|
2011-12-01 20:56:29 +08:00
|
|
|
if(sdepth == CV_8U && ddepth == CV_32S)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = GET_OPTIMIZED(reduceSumR8u32s);
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_8U && ddepth == CV_32F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumR8u32f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_8U && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumR8u64f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16U && ddepth == CV_32F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumR16u32f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16U && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumR16u64f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16S && ddepth == CV_32F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumR16s32f;
|
2011-12-01 20:56:29 +08:00
|
|
|
else if(sdepth == CV_16S && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumR16s64f;
|
|
|
|
else if(sdepth == CV_32F && ddepth == CV_32F)
|
|
|
|
func = GET_OPTIMIZED(reduceSumR32f32f);
|
2011-12-01 20:56:29 +08:00
|
|
|
else if(sdepth == CV_32F && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumR32f64f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_64F && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumR64f64f;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
else if(op == CV_REDUCE_MAX)
|
|
|
|
{
|
2011-12-01 20:56:29 +08:00
|
|
|
if(sdepth == CV_8U && ddepth == CV_8U)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = GET_OPTIMIZED(reduceMaxR8u);
|
|
|
|
else if(sdepth == CV_16U && ddepth == CV_16U)
|
|
|
|
func = reduceMaxR16u;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16S && ddepth == CV_16S)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceMaxR16s;
|
2011-12-01 20:56:29 +08:00
|
|
|
else if(sdepth == CV_32F && ddepth == CV_32F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = GET_OPTIMIZED(reduceMaxR32f);
|
|
|
|
else if(sdepth == CV_64F && ddepth == CV_64F)
|
|
|
|
func = reduceMaxR64f;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
else if(op == CV_REDUCE_MIN)
|
|
|
|
{
|
2011-12-01 20:56:29 +08:00
|
|
|
if(sdepth == CV_8U && ddepth == CV_8U)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = GET_OPTIMIZED(reduceMinR8u);
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16U && ddepth == CV_16U)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceMinR16u;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16S && ddepth == CV_16S)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceMinR16s;
|
2011-12-01 20:56:29 +08:00
|
|
|
else if(sdepth == CV_32F && ddepth == CV_32F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = GET_OPTIMIZED(reduceMinR32f);
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_64F && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceMinR64f;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(op == CV_REDUCE_SUM)
|
|
|
|
{
|
2011-12-01 20:56:29 +08:00
|
|
|
if(sdepth == CV_8U && ddepth == CV_32S)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = GET_OPTIMIZED(reduceSumC8u32s);
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_8U && ddepth == CV_32F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumC8u32f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_8U && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumC8u64f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16U && ddepth == CV_32F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumC16u32f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16U && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumC16u64f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16S && ddepth == CV_32F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumC16s32f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16S && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumC16s64f;
|
|
|
|
else if(sdepth == CV_32F && ddepth == CV_32F)
|
|
|
|
func = GET_OPTIMIZED(reduceSumC32f32f);
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_32F && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumC32f64f;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_64F && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceSumC64f64f;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
else if(op == CV_REDUCE_MAX)
|
|
|
|
{
|
2011-12-01 20:56:29 +08:00
|
|
|
if(sdepth == CV_8U && ddepth == CV_8U)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = GET_OPTIMIZED(reduceMaxC8u);
|
|
|
|
else if(sdepth == CV_16U && ddepth == CV_16U)
|
|
|
|
func = reduceMaxC16u;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16S && ddepth == CV_16S)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceMaxC16s;
|
2011-12-01 20:56:29 +08:00
|
|
|
else if(sdepth == CV_32F && ddepth == CV_32F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = GET_OPTIMIZED(reduceMaxC32f);
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_64F && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceMaxC64f;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
else if(op == CV_REDUCE_MIN)
|
|
|
|
{
|
2011-12-01 20:56:29 +08:00
|
|
|
if(sdepth == CV_8U && ddepth == CV_8U)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = GET_OPTIMIZED(reduceMinC8u);
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16U && ddepth == CV_16U)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceMinC16u;
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_16S && ddepth == CV_16S)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceMinC16s;
|
2011-12-01 20:56:29 +08:00
|
|
|
else if(sdepth == CV_32F && ddepth == CV_32F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = GET_OPTIMIZED(reduceMinC32f);
|
2011-06-18 03:03:26 +08:00
|
|
|
else if(sdepth == CV_64F && ddepth == CV_64F)
|
2011-12-22 20:51:01 +08:00
|
|
|
func = reduceMinC64f;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !func )
|
|
|
|
CV_Error( CV_StsUnsupportedFormat,
|
2011-12-22 20:51:01 +08:00
|
|
|
"Unsupported combination of input and output array formats" );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
func( src, temp );
|
|
|
|
|
2011-12-22 20:51:01 +08:00
|
|
|
if( op0 == CV_REDUCE_AVG )
|
2010-05-12 01:44:00 +08:00
|
|
|
temp.convertTo(dst, dst.type(), 1./(dim == 0 ? src.rows : src.cols));
|
2011-12-22 20:51:01 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
|
|
|
|
2010-10-19 19:57:37 +08:00
|
|
|
//////////////////////////////////////// sort ///////////////////////////////////////////
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
namespace cv
|
|
|
|
{
|
|
|
|
|
2014-04-15 04:11:16 +08:00
|
|
|
#if IPP_VERSION_X100 > 0 && !defined HAVE_IPP_ICV_ONLY
|
2014-04-15 18:58:11 +08:00
|
|
|
#define USE_IPP_SORT
|
2014-04-15 04:11:16 +08:00
|
|
|
|
|
|
|
typedef IppStatus (CV_STDCALL *IppSortFunc)(void *, int);
|
2014-04-15 18:58:11 +08:00
|
|
|
typedef IppSortFunc IppFlipFunc;
|
2014-04-15 04:11:16 +08:00
|
|
|
|
|
|
|
static IppSortFunc getSortFunc(int depth, bool sortDescending)
|
|
|
|
{
|
|
|
|
if (!sortDescending)
|
|
|
|
return depth == CV_8U ? (IppSortFunc)ippsSortAscend_8u_I :
|
|
|
|
depth == CV_16U ? (IppSortFunc)ippsSortAscend_16u_I :
|
|
|
|
depth == CV_16S ? (IppSortFunc)ippsSortAscend_16s_I :
|
|
|
|
depth == CV_32S ? (IppSortFunc)ippsSortAscend_32s_I :
|
|
|
|
depth == CV_32F ? (IppSortFunc)ippsSortAscend_32f_I :
|
|
|
|
depth == CV_64F ? (IppSortFunc)ippsSortAscend_64f_I : 0;
|
|
|
|
else
|
|
|
|
return depth == CV_8U ? (IppSortFunc)ippsSortDescend_8u_I :
|
|
|
|
depth == CV_16U ? (IppSortFunc)ippsSortDescend_16u_I :
|
|
|
|
depth == CV_16S ? (IppSortFunc)ippsSortDescend_16s_I :
|
|
|
|
depth == CV_32S ? (IppSortFunc)ippsSortDescend_32s_I :
|
|
|
|
depth == CV_32F ? (IppSortFunc)ippsSortDescend_32f_I :
|
|
|
|
depth == CV_64F ? (IppSortFunc)ippsSortDescend_64f_I : 0;
|
|
|
|
}
|
|
|
|
|
2014-04-15 18:58:11 +08:00
|
|
|
static IppFlipFunc getFlipFunc(int depth)
|
|
|
|
{
|
|
|
|
CV_SUPPRESS_DEPRECATED_START
|
|
|
|
return
|
|
|
|
depth == CV_8U || depth == CV_8S ? (IppFlipFunc)ippsFlip_8u_I :
|
|
|
|
depth == CV_16U || depth == CV_16S ? (IppFlipFunc)ippsFlip_16u_I :
|
|
|
|
depth == CV_32S || depth == CV_32F ? (IppFlipFunc)ippsFlip_32f_I :
|
|
|
|
depth == CV_64F ? (IppFlipFunc)ippsFlip_64f_I : 0;
|
|
|
|
CV_SUPPRESS_DEPRECATED_END
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-15 04:11:16 +08:00
|
|
|
#endif
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
|
|
|
|
{
|
|
|
|
AutoBuffer<T> buf;
|
|
|
|
T* bptr;
|
|
|
|
int i, j, n, len;
|
|
|
|
bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
|
|
|
|
bool inplace = src.data == dst.data;
|
|
|
|
bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( sortRows )
|
|
|
|
n = src.rows, len = src.cols;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
n = src.cols, len = src.rows;
|
|
|
|
buf.allocate(len);
|
|
|
|
}
|
|
|
|
bptr = (T*)buf;
|
|
|
|
|
2014-04-15 18:58:11 +08:00
|
|
|
#ifdef USE_IPP_SORT
|
|
|
|
int depth = src.depth();
|
|
|
|
IppSortFunc ippSortFunc = getSortFunc(depth, sortDescending);
|
|
|
|
IppFlipFunc ippFlipFunc = getFlipFunc(depth);
|
2014-04-15 04:11:16 +08:00
|
|
|
#endif
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
{
|
|
|
|
T* ptr = bptr;
|
|
|
|
if( sortRows )
|
|
|
|
{
|
|
|
|
T* dptr = (T*)(dst.data + dst.step*i);
|
|
|
|
if( !inplace )
|
|
|
|
{
|
|
|
|
const T* sptr = (const T*)(src.data + src.step*i);
|
2014-04-15 04:11:16 +08:00
|
|
|
memcpy(dptr, sptr, sizeof(T) * len);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
ptr = dptr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( j = 0; j < len; j++ )
|
|
|
|
ptr[j] = ((const T*)(src.data + src.step*j))[i];
|
|
|
|
}
|
2014-04-15 04:11:16 +08:00
|
|
|
|
2014-04-15 18:58:11 +08:00
|
|
|
#ifdef USE_IPP_SORT
|
|
|
|
if (!ippSortFunc || ippSortFunc(ptr, len) < 0)
|
2014-04-15 04:11:16 +08:00
|
|
|
#endif
|
|
|
|
{
|
2014-04-15 18:58:11 +08:00
|
|
|
#ifdef USE_IPP_SORT
|
|
|
|
setIppErrorStatus();
|
|
|
|
#endif
|
2014-04-15 04:11:16 +08:00
|
|
|
std::sort( ptr, ptr + len );
|
|
|
|
if( sortDescending )
|
2014-04-15 18:58:11 +08:00
|
|
|
{
|
|
|
|
#ifdef USE_IPP_SORT
|
|
|
|
if (!ippFlipFunc || ippFlipFunc(ptr, len) < 0)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
#ifdef USE_IPP_SORT
|
|
|
|
setIppErrorStatus();
|
|
|
|
#endif
|
|
|
|
for( j = 0; j < len/2; j++ )
|
|
|
|
std::swap(ptr[j], ptr[len-1-j]);
|
|
|
|
}
|
|
|
|
}
|
2014-04-15 04:11:16 +08:00
|
|
|
}
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( !sortRows )
|
|
|
|
for( j = 0; j < len; j++ )
|
|
|
|
((T*)(dst.data + dst.step*j))[i] = ptr[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 20:12:13 +08:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2014-04-15 18:58:11 +08:00
|
|
|
#ifdef USE_IPP_SORT
|
2014-04-15 18:43:44 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2013-03-28 20:12:13 +08:00
|
|
|
|
2014-04-15 18:43:44 +08:00
|
|
|
#endif
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
|
|
|
|
{
|
|
|
|
AutoBuffer<T> buf;
|
|
|
|
AutoBuffer<int> ibuf;
|
|
|
|
T* bptr;
|
|
|
|
int* _iptr;
|
|
|
|
int i, j, n, len;
|
|
|
|
bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
|
|
|
|
bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;
|
|
|
|
|
|
|
|
CV_Assert( src.data != dst.data );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( sortRows )
|
|
|
|
n = src.rows, len = src.cols;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
n = src.cols, len = src.rows;
|
|
|
|
buf.allocate(len);
|
|
|
|
ibuf.allocate(len);
|
|
|
|
}
|
|
|
|
bptr = (T*)buf;
|
|
|
|
_iptr = (int*)ibuf;
|
|
|
|
|
2014-04-15 18:58:11 +08:00
|
|
|
#ifdef USE_IPP_SORT
|
|
|
|
int depth = src.depth();
|
|
|
|
IppSortIndexFunc ippFunc = getSortIndexFunc(depth, sortDescending);
|
|
|
|
IppFlipFunc ippFlipFunc = getFlipFunc(depth);
|
2014-04-15 18:43:44 +08:00
|
|
|
#endif
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
{
|
|
|
|
T* ptr = bptr;
|
|
|
|
int* iptr = _iptr;
|
|
|
|
|
|
|
|
if( sortRows )
|
|
|
|
{
|
|
|
|
ptr = (T*)(src.data + src.step*i);
|
|
|
|
iptr = (int*)(dst.data + dst.step*i);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( j = 0; j < len; j++ )
|
|
|
|
ptr[j] = ((const T*)(src.data + src.step*j))[i];
|
|
|
|
}
|
|
|
|
for( j = 0; j < len; j++ )
|
|
|
|
iptr[j] = j;
|
2014-04-15 18:43:44 +08:00
|
|
|
|
2014-04-15 18:58:11 +08:00
|
|
|
#ifdef USE_IPP_SORT
|
2014-04-15 18:43:44 +08:00
|
|
|
if (sortRows || !ippFunc || ippFunc(ptr, iptr, len) < 0)
|
|
|
|
#endif
|
|
|
|
{
|
2014-04-15 18:58:11 +08:00
|
|
|
#ifdef USE_IPP_SORT
|
|
|
|
setIppErrorStatus();
|
|
|
|
#endif
|
2014-04-15 18:43:44 +08:00
|
|
|
std::sort( iptr, iptr + len, LessThanIdx<T>(ptr) );
|
|
|
|
if( sortDescending )
|
2014-04-15 18:58:11 +08:00
|
|
|
{
|
|
|
|
#ifdef USE_IPP_SORT
|
|
|
|
if (!ippFlipFunc || ippFlipFunc(iptr, len) < 0)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
#ifdef USE_IPP_SORT
|
|
|
|
setIppErrorStatus();
|
|
|
|
#endif
|
|
|
|
for( j = 0; j < len/2; j++ )
|
|
|
|
std::swap(iptr[j], iptr[len-1-j]);
|
|
|
|
}
|
|
|
|
}
|
2014-04-15 18:43:44 +08:00
|
|
|
}
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( !sortRows )
|
|
|
|
for( j = 0; j < len; j++ )
|
|
|
|
((int*)(dst.data + dst.step*j))[i] = iptr[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags);
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::sort( InputArray _src, OutputArray _dst, int flags )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
static SortFunc tab[] =
|
|
|
|
{
|
|
|
|
sort_<uchar>, sort_<schar>, sort_<ushort>, sort_<short>,
|
|
|
|
sort_<int>, sort_<float>, sort_<double>, 0
|
|
|
|
};
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat src = _src.getMat();
|
2010-05-12 01:44:00 +08:00
|
|
|
SortFunc func = tab[src.depth()];
|
2010-10-12 20:31:40 +08:00
|
|
|
CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 );
|
2011-04-17 21:14:45 +08:00
|
|
|
_dst.create( src.size(), src.type() );
|
|
|
|
Mat dst = _dst.getMat();
|
2010-05-12 01:44:00 +08:00
|
|
|
func( src, dst, flags );
|
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::sortIdx( InputArray _src, OutputArray _dst, int flags )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
static SortFunc tab[] =
|
|
|
|
{
|
|
|
|
sortIdx_<uchar>, sortIdx_<schar>, sortIdx_<ushort>, sortIdx_<short>,
|
|
|
|
sortIdx_<int>, sortIdx_<float>, sortIdx_<double>, 0
|
|
|
|
};
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat src = _src.getMat();
|
2010-05-12 01:44:00 +08:00
|
|
|
SortFunc func = tab[src.depth()];
|
2010-10-12 20:31:40 +08:00
|
|
|
CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat dst = _dst.getMat();
|
2010-05-12 01:44:00 +08:00
|
|
|
if( dst.data == src.data )
|
2011-04-17 21:14:45 +08:00
|
|
|
_dst.release();
|
|
|
|
_dst.create( src.size(), CV_32S );
|
|
|
|
dst = _dst.getMat();
|
2010-05-12 01:44:00 +08:00
|
|
|
func( src, dst, flags );
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
|
|
|
|
2010-10-19 19:57:37 +08:00
|
|
|
////////////////////////////////////////// kmeans ////////////////////////////////////////////
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
namespace cv
|
|
|
|
{
|
|
|
|
|
2013-02-25 00:14:01 +08:00
|
|
|
static void generateRandomCenter(const std::vector<Vec2f>& box, float* center, RNG& rng)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
size_t j, dims = box.size();
|
|
|
|
float margin = 1.f/dims;
|
|
|
|
for( j = 0; j < dims; j++ )
|
|
|
|
center[j] = ((float)rng*(1.f+margin*2.f)-margin)*(box[j][1] - box[j][0]) + box[j][0];
|
|
|
|
}
|
|
|
|
|
2013-02-01 18:01:44 +08:00
|
|
|
class KMeansPPDistanceComputer : public ParallelLoopBody
|
2012-10-10 16:40:03 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
KMeansPPDistanceComputer( float *_tdist2,
|
|
|
|
const float *_data,
|
|
|
|
const float *_dist,
|
|
|
|
int _dims,
|
|
|
|
size_t _step,
|
|
|
|
size_t _stepci )
|
|
|
|
: tdist2(_tdist2),
|
|
|
|
data(_data),
|
|
|
|
dist(_dist),
|
|
|
|
dims(_dims),
|
|
|
|
step(_step),
|
|
|
|
stepci(_stepci) { }
|
|
|
|
|
2013-02-01 18:01:44 +08:00
|
|
|
void operator()( const cv::Range& range ) const
|
2012-10-10 16:40:03 +08:00
|
|
|
{
|
2013-02-01 18:01:44 +08:00
|
|
|
const int begin = range.start;
|
|
|
|
const int end = range.end;
|
2012-10-10 16:40:03 +08:00
|
|
|
|
|
|
|
for ( int i = begin; i<end; i++ )
|
|
|
|
{
|
|
|
|
tdist2[i] = std::min(normL2Sqr_(data + step*i, data + stepci, dims), dist[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2012-10-10 18:35:20 +08:00
|
|
|
KMeansPPDistanceComputer& operator=(const KMeansPPDistanceComputer&); // to quiet MSVC
|
|
|
|
|
2012-10-10 16:40:03 +08:00
|
|
|
float *tdist2;
|
|
|
|
const float *data;
|
|
|
|
const float *dist;
|
|
|
|
const int dims;
|
|
|
|
const size_t step;
|
|
|
|
const size_t stepci;
|
|
|
|
};
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
k-means center initialization using the following algorithm:
|
|
|
|
Arthur & Vassilvitskii (2007) k-means++: The Advantages of Careful Seeding
|
|
|
|
*/
|
|
|
|
static void generateCentersPP(const Mat& _data, Mat& _out_centers,
|
|
|
|
int K, RNG& rng, int trials)
|
|
|
|
{
|
|
|
|
int i, j, k, dims = _data.cols, N = _data.rows;
|
|
|
|
const float* data = _data.ptr<float>(0);
|
2011-08-12 06:27:18 +08:00
|
|
|
size_t step = _data.step/sizeof(data[0]);
|
2013-02-25 00:14:01 +08:00
|
|
|
std::vector<int> _centers(K);
|
2010-05-12 01:44:00 +08:00
|
|
|
int* centers = &_centers[0];
|
2013-02-25 00:14:01 +08:00
|
|
|
std::vector<float> _dist(N*3);
|
2010-05-12 01:44:00 +08:00
|
|
|
float* dist = &_dist[0], *tdist = dist + N, *tdist2 = tdist + N;
|
|
|
|
double sum0 = 0;
|
|
|
|
|
|
|
|
centers[0] = (unsigned)rng % N;
|
|
|
|
|
|
|
|
for( i = 0; i < N; i++ )
|
|
|
|
{
|
2011-10-11 23:13:53 +08:00
|
|
|
dist[i] = normL2Sqr_(data + step*i, data + step*centers[0], dims);
|
2010-05-12 01:44:00 +08:00
|
|
|
sum0 += dist[i];
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
for( k = 1; k < K; k++ )
|
|
|
|
{
|
|
|
|
double bestSum = DBL_MAX;
|
|
|
|
int bestCenter = -1;
|
|
|
|
|
|
|
|
for( j = 0; j < trials; j++ )
|
|
|
|
{
|
|
|
|
double p = (double)rng*sum0, s = 0;
|
|
|
|
for( i = 0; i < N-1; i++ )
|
|
|
|
if( (p -= dist[i]) <= 0 )
|
|
|
|
break;
|
|
|
|
int ci = i;
|
2012-10-10 16:40:03 +08:00
|
|
|
|
2013-02-01 18:01:44 +08:00
|
|
|
parallel_for_(Range(0, N),
|
2012-10-10 16:40:03 +08:00
|
|
|
KMeansPPDistanceComputer(tdist2, data, dist, dims, step, step*ci));
|
2010-05-12 01:44:00 +08:00
|
|
|
for( i = 0; i < N; i++ )
|
|
|
|
{
|
|
|
|
s += tdist2[i];
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( s < bestSum )
|
|
|
|
{
|
|
|
|
bestSum = s;
|
|
|
|
bestCenter = ci;
|
|
|
|
std::swap(tdist, tdist2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
centers[k] = bestCenter;
|
|
|
|
sum0 = bestSum;
|
|
|
|
std::swap(dist, tdist);
|
|
|
|
}
|
|
|
|
|
|
|
|
for( k = 0; k < K; k++ )
|
|
|
|
{
|
|
|
|
const float* src = data + step*centers[k];
|
|
|
|
float* dst = _out_centers.ptr<float>(k);
|
|
|
|
for( j = 0; j < dims; j++ )
|
|
|
|
dst[j] = src[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-01 18:01:44 +08:00
|
|
|
class KMeansDistanceComputer : public ParallelLoopBody
|
2012-10-10 16:40:03 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
KMeansDistanceComputer( double *_distances,
|
|
|
|
int *_labels,
|
|
|
|
const Mat& _data,
|
|
|
|
const Mat& _centers )
|
|
|
|
: distances(_distances),
|
|
|
|
labels(_labels),
|
|
|
|
data(_data),
|
|
|
|
centers(_centers)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-02-01 18:01:44 +08:00
|
|
|
void operator()( const Range& range ) const
|
2012-10-10 16:40:03 +08:00
|
|
|
{
|
2013-02-01 18:01:44 +08:00
|
|
|
const int begin = range.start;
|
|
|
|
const int end = range.end;
|
2012-10-10 16:40:03 +08:00
|
|
|
const int K = centers.rows;
|
|
|
|
const int dims = centers.cols;
|
|
|
|
|
|
|
|
const float *sample;
|
|
|
|
for( int i = begin; i<end; ++i)
|
|
|
|
{
|
|
|
|
sample = data.ptr<float>(i);
|
|
|
|
int k_best = 0;
|
|
|
|
double min_dist = DBL_MAX;
|
|
|
|
|
|
|
|
for( int k = 0; k < K; k++ )
|
|
|
|
{
|
|
|
|
const float* center = centers.ptr<float>(k);
|
|
|
|
const double dist = normL2Sqr_(sample, center, dims);
|
|
|
|
|
|
|
|
if( min_dist > dist )
|
|
|
|
{
|
|
|
|
min_dist = dist;
|
|
|
|
k_best = k;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
distances[i] = min_dist;
|
|
|
|
labels[i] = k_best;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2012-10-10 18:51:46 +08:00
|
|
|
KMeansDistanceComputer& operator=(const KMeansDistanceComputer&); // to quiet MSVC
|
|
|
|
|
2012-10-10 16:40:03 +08:00
|
|
|
double *distances;
|
|
|
|
int *labels;
|
|
|
|
const Mat& data;
|
|
|
|
const Mat& centers;
|
|
|
|
};
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
double cv::kmeans( InputArray _data, int K,
|
2011-04-17 21:14:45 +08:00
|
|
|
InputOutputArray _bestLabels,
|
|
|
|
TermCriteria criteria, int attempts,
|
|
|
|
int flags, OutputArray _centers )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
const int SPP_TRIALS = 3;
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat data = _data.getMat();
|
2012-04-14 05:50:59 +08:00
|
|
|
bool isrow = data.rows == 1 && data.channels() > 1;
|
|
|
|
int N = !isrow ? data.rows : data.cols;
|
|
|
|
int dims = (!isrow ? data.cols : 1)*data.channels();
|
2010-05-12 01:44:00 +08:00
|
|
|
int type = data.depth();
|
|
|
|
|
|
|
|
attempts = std::max(attempts, 1);
|
2010-10-12 20:31:40 +08:00
|
|
|
CV_Assert( data.dims <= 2 && type == CV_32F && K > 0 );
|
2012-03-28 22:32:23 +08:00
|
|
|
CV_Assert( N >= K );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
_bestLabels.create(N, 1, CV_32S, -1, true);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat _labels, best_labels = _bestLabels.getMat();
|
2010-05-12 01:44:00 +08:00
|
|
|
if( flags & CV_KMEANS_USE_INITIAL_LABELS )
|
|
|
|
{
|
|
|
|
CV_Assert( (best_labels.cols == 1 || best_labels.rows == 1) &&
|
|
|
|
best_labels.cols*best_labels.rows == N &&
|
|
|
|
best_labels.type() == CV_32S &&
|
|
|
|
best_labels.isContinuous());
|
|
|
|
best_labels.copyTo(_labels);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( !((best_labels.cols == 1 || best_labels.rows == 1) &&
|
|
|
|
best_labels.cols*best_labels.rows == N &&
|
|
|
|
best_labels.type() == CV_32S &&
|
|
|
|
best_labels.isContinuous()))
|
|
|
|
best_labels.create(N, 1, CV_32S);
|
|
|
|
_labels.create(best_labels.size(), best_labels.type());
|
|
|
|
}
|
|
|
|
int* labels = _labels.ptr<int>();
|
|
|
|
|
2012-04-14 05:50:59 +08:00
|
|
|
Mat centers(K, dims, type), old_centers(K, dims, type), temp(1, dims, type);
|
2013-02-25 00:14:01 +08:00
|
|
|
std::vector<int> counters(K);
|
|
|
|
std::vector<Vec2f> _box(dims);
|
2010-05-12 01:44:00 +08:00
|
|
|
Vec2f* box = &_box[0];
|
|
|
|
double best_compactness = DBL_MAX, compactness = 0;
|
|
|
|
RNG& rng = theRNG();
|
|
|
|
int a, iter, i, j, k;
|
|
|
|
|
|
|
|
if( criteria.type & TermCriteria::EPS )
|
|
|
|
criteria.epsilon = std::max(criteria.epsilon, 0.);
|
|
|
|
else
|
|
|
|
criteria.epsilon = FLT_EPSILON;
|
|
|
|
criteria.epsilon *= criteria.epsilon;
|
|
|
|
|
|
|
|
if( criteria.type & TermCriteria::COUNT )
|
|
|
|
criteria.maxCount = std::min(std::max(criteria.maxCount, 2), 100);
|
|
|
|
else
|
|
|
|
criteria.maxCount = 100;
|
|
|
|
|
|
|
|
if( K == 1 )
|
|
|
|
{
|
|
|
|
attempts = 1;
|
|
|
|
criteria.maxCount = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
const float* sample = data.ptr<float>(0);
|
|
|
|
for( j = 0; j < dims; j++ )
|
|
|
|
box[j] = Vec2f(sample[j], sample[j]);
|
|
|
|
|
|
|
|
for( i = 1; i < N; i++ )
|
|
|
|
{
|
|
|
|
sample = data.ptr<float>(i);
|
|
|
|
for( j = 0; j < dims; j++ )
|
|
|
|
{
|
|
|
|
float v = sample[j];
|
|
|
|
box[j][0] = std::min(box[j][0], v);
|
|
|
|
box[j][1] = std::max(box[j][1], v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for( a = 0; a < attempts; a++ )
|
|
|
|
{
|
|
|
|
double max_center_shift = DBL_MAX;
|
2012-04-14 05:50:59 +08:00
|
|
|
for( iter = 0;; )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
swap(centers, old_centers);
|
|
|
|
|
|
|
|
if( iter == 0 && (a > 0 || !(flags & KMEANS_USE_INITIAL_LABELS)) )
|
|
|
|
{
|
|
|
|
if( flags & KMEANS_PP_CENTERS )
|
|
|
|
generateCentersPP(data, centers, K, rng, SPP_TRIALS);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( k = 0; k < K; k++ )
|
|
|
|
generateRandomCenter(_box, centers.ptr<float>(k), rng);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( iter == 0 && a == 0 && (flags & KMEANS_USE_INITIAL_LABELS) )
|
|
|
|
{
|
|
|
|
for( i = 0; i < N; i++ )
|
|
|
|
CV_Assert( (unsigned)labels[i] < (unsigned)K );
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// compute centers
|
|
|
|
centers = Scalar(0);
|
|
|
|
for( k = 0; k < K; k++ )
|
|
|
|
counters[k] = 0;
|
|
|
|
|
|
|
|
for( i = 0; i < N; i++ )
|
|
|
|
{
|
|
|
|
sample = data.ptr<float>(i);
|
|
|
|
k = labels[i];
|
|
|
|
float* center = centers.ptr<float>(k);
|
2012-06-08 01:21:29 +08:00
|
|
|
j=0;
|
|
|
|
#if CV_ENABLE_UNROLLED
|
2012-02-10 14:05:04 +08:00
|
|
|
for(; j <= dims - 4; j += 4 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
float t0 = center[j] + sample[j];
|
|
|
|
float t1 = center[j+1] + sample[j+1];
|
|
|
|
|
|
|
|
center[j] = t0;
|
|
|
|
center[j+1] = t1;
|
|
|
|
|
|
|
|
t0 = center[j+2] + sample[j+2];
|
|
|
|
t1 = center[j+3] + sample[j+3];
|
|
|
|
|
|
|
|
center[j+2] = t0;
|
|
|
|
center[j+3] = t1;
|
|
|
|
}
|
2012-02-10 14:05:04 +08:00
|
|
|
#endif
|
2010-05-12 01:44:00 +08:00
|
|
|
for( ; j < dims; j++ )
|
|
|
|
center[j] += sample[j];
|
|
|
|
counters[k]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( iter > 0 )
|
|
|
|
max_center_shift = 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
for( k = 0; k < K; k++ )
|
|
|
|
{
|
|
|
|
if( counters[k] != 0 )
|
2012-03-28 22:32:23 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// if some cluster appeared to be empty then:
|
|
|
|
// 1. find the biggest cluster
|
|
|
|
// 2. find the farthest from the center point in the biggest cluster
|
|
|
|
// 3. exclude the farthest point from the biggest cluster and form a new 1-point cluster.
|
|
|
|
int max_k = 0;
|
2012-03-28 22:56:18 +08:00
|
|
|
for( int k1 = 1; k1 < K; k1++ )
|
2012-03-28 22:32:23 +08:00
|
|
|
{
|
|
|
|
if( counters[max_k] < counters[k1] )
|
|
|
|
max_k = k1;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
|
|
|
double max_dist = 0;
|
2012-03-28 22:32:23 +08:00
|
|
|
int farthest_i = -1;
|
|
|
|
float* new_center = centers.ptr<float>(k);
|
|
|
|
float* old_center = centers.ptr<float>(max_k);
|
2012-04-14 05:50:59 +08:00
|
|
|
float* _old_center = temp.ptr<float>(); // normalized
|
|
|
|
float scale = 1.f/counters[max_k];
|
|
|
|
for( j = 0; j < dims; j++ )
|
|
|
|
_old_center[j] = old_center[j]*scale;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-03-28 22:32:23 +08:00
|
|
|
for( i = 0; i < N; i++ )
|
|
|
|
{
|
|
|
|
if( labels[i] != max_k )
|
|
|
|
continue;
|
|
|
|
sample = data.ptr<float>(i);
|
2012-04-14 05:50:59 +08:00
|
|
|
double dist = normL2Sqr_(sample, _old_center, dims);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-03-28 22:32:23 +08:00
|
|
|
if( max_dist <= dist )
|
|
|
|
{
|
|
|
|
max_dist = dist;
|
|
|
|
farthest_i = i;
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-03-28 22:32:23 +08:00
|
|
|
counters[max_k]--;
|
|
|
|
counters[k]++;
|
2012-04-14 05:50:59 +08:00
|
|
|
labels[farthest_i] = k;
|
2012-03-28 22:32:23 +08:00
|
|
|
sample = data.ptr<float>(farthest_i);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-03-28 22:32:23 +08:00
|
|
|
for( j = 0; j < dims; j++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2012-03-28 22:32:23 +08:00
|
|
|
old_center[j] -= sample[j];
|
|
|
|
new_center[j] += sample[j];
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2012-03-28 22:32:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for( k = 0; k < K; k++ )
|
|
|
|
{
|
|
|
|
float* center = centers.ptr<float>(k);
|
|
|
|
CV_Assert( counters[k] != 0 );
|
|
|
|
|
|
|
|
float scale = 1.f/counters[k];
|
|
|
|
for( j = 0; j < dims; j++ )
|
|
|
|
center[j] *= scale;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( iter > 0 )
|
|
|
|
{
|
|
|
|
double dist = 0;
|
|
|
|
const float* old_center = old_centers.ptr<float>(k);
|
|
|
|
for( j = 0; j < dims; j++ )
|
|
|
|
{
|
|
|
|
double t = center[j] - old_center[j];
|
|
|
|
dist += t*t;
|
|
|
|
}
|
|
|
|
max_center_shift = std::max(max_center_shift, dist);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-04-14 05:50:59 +08:00
|
|
|
if( ++iter == MAX(criteria.maxCount, 2) || max_center_shift <= criteria.epsilon )
|
|
|
|
break;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
// assign labels
|
2012-10-10 16:40:03 +08:00
|
|
|
Mat dists(1, N, CV_64F);
|
|
|
|
double* dist = dists.ptr<double>(0);
|
2013-02-01 18:01:44 +08:00
|
|
|
parallel_for_(Range(0, N),
|
2012-10-10 16:40:03 +08:00
|
|
|
KMeansDistanceComputer(dist, labels, data, centers));
|
2010-05-12 01:44:00 +08:00
|
|
|
compactness = 0;
|
|
|
|
for( i = 0; i < N; i++ )
|
|
|
|
{
|
2012-10-10 16:40:03 +08:00
|
|
|
compactness += dist[i];
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( compactness < best_compactness )
|
|
|
|
{
|
|
|
|
best_compactness = compactness;
|
2011-04-17 21:14:45 +08:00
|
|
|
if( _centers.needed() )
|
|
|
|
centers.copyTo(_centers);
|
2010-05-12 01:44:00 +08:00
|
|
|
_labels.copyTo(best_labels);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return best_compactness;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
2013-03-29 01:01:12 +08:00
|
|
|
cv::Mat m = cv::cvarrToMat(matrix);
|
2010-05-12 01:44:00 +08:00
|
|
|
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);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
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" );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
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 )
|
|
|
|
{
|
|
|
|
int ok = 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
CvMat stub, *mat = (CvMat*)arr;
|
|
|
|
double delta;
|
|
|
|
int type, step;
|
|
|
|
double val = start;
|
|
|
|
int i, j;
|
|
|
|
int rows, cols;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( !CV_IS_MAT(mat) )
|
|
|
|
mat = cvGetMat( mat, &stub);
|
|
|
|
|
|
|
|
rows = mat->rows;
|
|
|
|
cols = mat->cols;
|
|
|
|
type = CV_MAT_TYPE(mat->type);
|
|
|
|
delta = (end-start)/(rows*cols);
|
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
for( i = 0; i < rows; i++, idata += step )
|
|
|
|
for( j = 0; j < cols; j++, ival += idelta )
|
|
|
|
idata[j] = ival;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( i = 0; i < rows; i++, idata += step )
|
|
|
|
for( j = 0; j < cols; j++, val += delta )
|
|
|
|
idata[j] = cvRound(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( type == CV_32FC1 )
|
|
|
|
{
|
|
|
|
float* fdata = mat->data.fl;
|
|
|
|
for( i = 0; i < rows; i++, fdata += step )
|
|
|
|
for( j = 0; j < cols; j++, val += delta )
|
|
|
|
fdata[j] = (float)val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
CV_Error( CV_StsUnsupportedFormat, "The function only supports 32sC1 and 32fC1 datatypes" );
|
|
|
|
|
|
|
|
ok = 1;
|
|
|
|
return ok ? arr : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CV_IMPL void
|
|
|
|
cvSort( const CvArr* _src, CvArr* _dst, CvArr* _idx, int flags )
|
|
|
|
{
|
2012-06-09 23:00:04 +08:00
|
|
|
cv::Mat src = cv::cvarrToMat(_src);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
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 )
|
2011-06-01 20:06:39 +08:00
|
|
|
{
|
2010-05-12 01:44:00 +08:00
|
|
|
centers = cv::cvarrToMat(_centers);
|
2012-03-28 23:45:14 +08:00
|
|
|
|
2011-06-01 20:06:39 +08:00
|
|
|
centers = centers.reshape(1);
|
2012-03-28 23:45:14 +08:00
|
|
|
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() );
|
2011-06-01 20:06:39 +08:00
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
CV_Assert( labels.isContinuous() && labels.type() == CV_32S &&
|
|
|
|
(labels.cols == 1 || labels.rows == 1) &&
|
|
|
|
labels.cols + labels.rows - 1 == data.rows );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
double compactness = cv::kmeans(data, cluster_count, labels, termcrit, attempts,
|
2011-06-06 22:51:27 +08:00
|
|
|
flags, _centers ? cv::_OutputArray(centers) : cv::_OutputArray() );
|
2010-05-12 01:44:00 +08:00
|
|
|
if( _compactness )
|
|
|
|
*_compactness = compactness;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////// n-dimensional matrices ////////////////////////////
|
|
|
|
|
|
|
|
namespace cv
|
|
|
|
{
|
|
|
|
|
2012-05-16 23:11:17 +08:00
|
|
|
Mat Mat::reshape(int _cn, int _newndims, const int* _newsz) const
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2012-05-16 23:11:17 +08:00
|
|
|
if(_newndims == dims)
|
|
|
|
{
|
|
|
|
if(_newsz == 0)
|
|
|
|
return reshape(_cn);
|
|
|
|
if(_newndims == 2)
|
|
|
|
return reshape(_cn, _newsz[0]);
|
|
|
|
}
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
CV_Error(CV_StsNotImplemented, "");
|
|
|
|
// TBD
|
|
|
|
return Mat();
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
NAryMatIterator::NAryMatIterator()
|
2011-04-17 21:14:45 +08:00
|
|
|
: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
NAryMatIterator::NAryMatIterator(const Mat** _arrays, Mat* _planes, int _narrays)
|
2011-04-17 21:14:45 +08:00
|
|
|
: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
|
|
|
|
{
|
|
|
|
init(_arrays, _planes, 0, _narrays);
|
2012-06-08 01:21:29 +08:00
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
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)
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
init(_arrays, 0, _ptrs, _narrays);
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, uchar** _ptrs, int _narrays)
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
CV_Assert( _arrays && (_ptrs || _planes) );
|
|
|
|
int i, j, d1=0, i0 = -1, d = -1;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
arrays = _arrays;
|
2011-04-17 21:14:45 +08:00
|
|
|
ptrs = _ptrs;
|
2010-10-12 20:31:40 +08:00
|
|
|
planes = _planes;
|
|
|
|
narrays = _narrays;
|
|
|
|
nplanes = 0;
|
2011-04-17 21:14:45 +08:00
|
|
|
size = 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( narrays < 0 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
for( i = 0; _arrays[i] != 0; i++ )
|
|
|
|
;
|
|
|
|
narrays = i;
|
|
|
|
CV_Assert(narrays <= 1000);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
|
|
|
|
iterdepth = 0;
|
|
|
|
|
|
|
|
for( i = 0; i < narrays; i++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
CV_Assert(arrays[i] != 0);
|
|
|
|
const Mat& A = *arrays[i];
|
2011-04-17 21:14:45 +08:00
|
|
|
if( ptrs )
|
|
|
|
ptrs[i] = A.data;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( !A.data )
|
|
|
|
continue;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( i0 < 0 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
i0 = i;
|
|
|
|
d = A.dims;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
// 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);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
|
|
|
|
if( i0 >= 0 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
size = arrays[i0]->size[d-1];
|
2010-10-12 20:31:40 +08:00
|
|
|
for( j = d-1; j > iterdepth; j-- )
|
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
int64 total1 = (int64)size*arrays[i0]->size[j-1];
|
2010-10-12 20:31:40 +08:00
|
|
|
if( total1 != (int)total1 )
|
|
|
|
break;
|
2011-04-17 21:14:45 +08:00
|
|
|
size = (int)total1;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
iterdepth = j;
|
|
|
|
if( iterdepth == d1 )
|
|
|
|
iterdepth = 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
nplanes = 1;
|
|
|
|
for( j = iterdepth-1; j >= 0; j-- )
|
|
|
|
nplanes *= arrays[i0]->size[j];
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
else
|
2011-04-17 21:14:45 +08:00
|
|
|
iterdepth = 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
idx = 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( !planes )
|
|
|
|
return;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
for( i = 0; i < narrays; i++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
CV_Assert(arrays[i] != 0);
|
|
|
|
const Mat& A = *arrays[i];
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( !A.data )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
|
|
|
planes[i] = Mat();
|
|
|
|
continue;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
|
|
|
planes[i] = Mat(1, (int)size, A.type(), A.data);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
|
|
|
|
NAryMatIterator& NAryMatIterator::operator ++()
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
if( idx >= nplanes-1 )
|
|
|
|
return *this;
|
|
|
|
++idx;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( iterdepth == 1 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
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 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
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;
|
2011-07-19 20:27:07 +08:00
|
|
|
int _idx = (int)idx;
|
2011-04-17 21:14:45 +08:00
|
|
|
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;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
NAryMatIterator NAryMatIterator::operator ++(int)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
NAryMatIterator it = *this;
|
2010-05-12 01:44:00 +08:00
|
|
|
++*this;
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// MatConstIterator //
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
Point MatConstIterator::pos() const
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
if( !m )
|
|
|
|
return Point();
|
|
|
|
CV_DbgAssert(m->dims <= 2);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
ptrdiff_t ofs = ptr - m->data;
|
|
|
|
int y = (int)(ofs/m->step[0]);
|
|
|
|
return Point((int)((ofs - y*m->step[0])/elemSize), y);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
void MatConstIterator::pos(int* _idx) const
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
CV_Assert(m != 0 && _idx);
|
|
|
|
ptrdiff_t ofs = ptr - m->data;
|
|
|
|
for( int i = 0; i < m->dims; i++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
size_t s = m->step[i], v = ofs/s;
|
|
|
|
ofs -= v*s;
|
|
|
|
_idx[i] = (int)v;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
ptrdiff_t MatConstIterator::lpos() const
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
if(!m)
|
|
|
|
return 0;
|
|
|
|
if( m->isContinuous() )
|
|
|
|
return (ptr - sliceStart)/elemSize;
|
|
|
|
ptrdiff_t ofs = ptr - m->data;
|
|
|
|
int i, d = m->dims;
|
|
|
|
if( d == 2 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
ptrdiff_t y = ofs/m->step[0];
|
|
|
|
return y*m->cols + (ofs - y*m->step[0])/elemSize;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
ptrdiff_t result = 0;
|
|
|
|
for( i = 0; i < d; i++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
size_t s = m->step[i], v = ofs/s;
|
|
|
|
ofs -= v*s;
|
|
|
|
result = result*m->size[i] + v;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
return result;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
void MatConstIterator::seek(ptrdiff_t ofs, bool relative)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
if( m->isContinuous() )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
ptr = (relative ? ptr : sliceStart) + ofs*elemSize;
|
|
|
|
if( ptr < sliceStart )
|
|
|
|
ptr = sliceStart;
|
|
|
|
else if( ptr > sliceEnd )
|
|
|
|
ptr = sliceEnd;
|
|
|
|
return;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
int d = m->dims;
|
|
|
|
if( d == 2 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
ptrdiff_t ofs0, y;
|
|
|
|
if( relative )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
ofs0 = ptr - m->data;
|
|
|
|
y = ofs0/m->step[0];
|
|
|
|
ofs += y*m->cols + (ofs0 - y*m->step[0])/elemSize;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
y = ofs/m->cols;
|
|
|
|
int y1 = std::min(std::max((int)y, 0), m->rows-1);
|
|
|
|
sliceStart = m->data + y1*m->step[0];
|
2010-12-27 06:18:30 +08:00
|
|
|
sliceEnd = sliceStart + m->cols*elemSize;
|
2010-10-12 20:31:40 +08:00
|
|
|
ptr = y < 0 ? sliceStart : y >= m->rows ? sliceEnd :
|
|
|
|
sliceStart + (ofs - y*m->cols)*elemSize;
|
|
|
|
return;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( relative )
|
|
|
|
ofs += lpos();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( ofs < 0 )
|
|
|
|
ofs = 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
int szi = m->size[d-1];
|
|
|
|
ptrdiff_t t = ofs/szi;
|
|
|
|
int v = (int)(ofs - t*szi);
|
|
|
|
ofs = t;
|
|
|
|
ptr = m->data + v*elemSize;
|
|
|
|
sliceStart = m->data;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
for( int i = d-2; i >= 0; i-- )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
szi = m->size[i];
|
|
|
|
t = ofs/szi;
|
|
|
|
v = (int)(ofs - t*szi);
|
|
|
|
ofs = t;
|
|
|
|
sliceStart += v*m->step[i];
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
sliceEnd = sliceStart + m->size[d-1]*elemSize;
|
|
|
|
if( ofs > 0 )
|
|
|
|
ptr = sliceEnd;
|
|
|
|
else
|
|
|
|
ptr = sliceStart + (ptr - m->data);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
void MatConstIterator::seek(const int* _idx, bool relative)
|
|
|
|
{
|
|
|
|
int i, d = m->dims;
|
|
|
|
ptrdiff_t ofs = 0;
|
|
|
|
if( !_idx )
|
|
|
|
;
|
|
|
|
else if( d == 2 )
|
|
|
|
ofs = _idx[0]*m->size[1] + _idx[1];
|
|
|
|
else
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-12 20:31:40 +08:00
|
|
|
for( i = 0; i < d; i++ )
|
|
|
|
ofs = ofs*m->size[i] + _idx[i];
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
seek(ofs, relative);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////// 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);
|
|
|
|
}
|
|
|
|
|
2013-04-09 17:10:54 +08:00
|
|
|
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)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-04-09 17:10:54 +08:00
|
|
|
static ConvertScaleData getConvertScaleElem(int fromType, int toType)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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;
|
2013-02-18 21:01:21 +08:00
|
|
|
for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) )
|
2010-05-12 01:44:00 +08:00
|
|
|
*(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;
|
2013-02-18 21:01:21 +08:00
|
|
|
for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) )
|
2010-05-12 01:44:00 +08:00
|
|
|
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;
|
|
|
|
valueOffset = (int)alignSize(sizeof(SparseMat::Node) +
|
2010-06-29 22:52:43 +08:00
|
|
|
sizeof(int)*std::max(dims - CV_MAX_DIM, 0), CV_ELEM_SIZE1(_type));
|
2010-05-12 01:44:00 +08:00
|
|
|
nodeSize = alignSize(valueOffset +
|
|
|
|
CV_ELEM_SIZE(_type), (int)sizeof(size_t));
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
SparseMat::SparseMat(const Mat& m)
|
2010-05-12 01:44:00 +08:00
|
|
|
: 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();
|
2012-06-09 23:00:04 +08:00
|
|
|
uchar* dptr = m.data;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
for(;;)
|
|
|
|
{
|
2012-06-09 23:00:04 +08:00
|
|
|
for( i = 0; i < lastSize; i++, dptr += esz )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2012-06-09 23:00:04 +08:00
|
|
|
if( isZeroElem(dptr, esz) )
|
2010-05-12 01:44:00 +08:00
|
|
|
continue;
|
|
|
|
idx[d-1] = i;
|
|
|
|
uchar* to = newNode(idx, hash(idx));
|
2012-06-09 23:00:04 +08:00
|
|
|
copyElem( dptr, to, esz );
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
for( i = d - 2; i >= 0; i-- )
|
|
|
|
{
|
2012-06-09 23:00:04 +08:00
|
|
|
dptr += m.step[i] - m.size[i+1]*m.step[i+1];
|
2010-05-12 01:44:00 +08:00
|
|
|
if( ++idx[i] < m.size[i] )
|
|
|
|
break;
|
|
|
|
idx[i] = 0;
|
|
|
|
}
|
|
|
|
if( i < 0 )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
void SparseMat::create(int d, const int* _sizes, int _type)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
CV_Assert( _sizes && 0 < d && d <= CV_MAX_DIM );
|
|
|
|
for( i = 0; i < d; i++ )
|
|
|
|
CV_Assert( _sizes[i] > 0 );
|
|
|
|
_type = CV_MAT_TYPE(_type);
|
|
|
|
if( hdr && _type == type() && hdr->dims == d && hdr->refcount == 1 )
|
|
|
|
{
|
|
|
|
for( i = 0; i < d; i++ )
|
|
|
|
if( _sizes[i] != hdr->size[i] )
|
|
|
|
break;
|
|
|
|
if( i == d )
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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();
|
|
|
|
size_t i, N = nzcount(), esz = elemSize();
|
|
|
|
|
|
|
|
for( i = 0; i < N; i++, ++from )
|
|
|
|
{
|
|
|
|
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 );
|
|
|
|
m.create( dims(), hdr->size, type() );
|
|
|
|
m = Scalar(0);
|
|
|
|
|
|
|
|
SparseMatConstIterator from = begin();
|
|
|
|
size_t i, N = nzcount(), esz = elemSize();
|
|
|
|
|
|
|
|
for( i = 0; i < N; i++, ++from )
|
|
|
|
{
|
|
|
|
const Node* n = from.node();
|
|
|
|
copyElem( from.ptr, m.ptr(n->idx), esz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
CV_Assert(hdr != 0);
|
|
|
|
if( hdr != m.hdr )
|
|
|
|
m.create( hdr->dims, hdr->size, rtype );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
SparseMatConstIterator from = begin();
|
|
|
|
size_t i, N = nzcount();
|
|
|
|
|
|
|
|
if( alpha == 1 )
|
|
|
|
{
|
2012-08-15 19:28:12 +08:00
|
|
|
ConvertData cvtfunc = getConvertElem(type(), rtype);
|
2010-05-12 01:44:00 +08:00
|
|
|
for( i = 0; i < N; i++, ++from )
|
|
|
|
{
|
|
|
|
const Node* n = from.node();
|
|
|
|
uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval);
|
2012-06-08 01:21:29 +08:00
|
|
|
cvtfunc( from.ptr, to, cn );
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-08-15 19:28:12 +08:00
|
|
|
ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype);
|
2010-05-12 01:44:00 +08:00
|
|
|
for( i = 0; i < N; i++, ++from )
|
|
|
|
{
|
|
|
|
const Node* n = from.node();
|
|
|
|
uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval);
|
2012-06-08 01:21:29 +08:00
|
|
|
cvtfunc( from.ptr, to, cn, alpha, 0 );
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
CV_Assert( hdr );
|
|
|
|
m.create( dims(), hdr->size, rtype );
|
|
|
|
m = Scalar(beta);
|
|
|
|
|
|
|
|
SparseMatConstIterator from = begin();
|
|
|
|
size_t i, N = nzcount();
|
|
|
|
|
|
|
|
if( alpha == 1 && beta == 0 )
|
|
|
|
{
|
2012-08-15 19:28:12 +08:00
|
|
|
ConvertData cvtfunc = getConvertElem(type(), rtype);
|
2010-05-12 01:44:00 +08:00
|
|
|
for( i = 0; i < N; i++, ++from )
|
|
|
|
{
|
|
|
|
const Node* n = from.node();
|
|
|
|
uchar* to = m.ptr(n->idx);
|
|
|
|
cvtfunc( from.ptr, to, cn );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-08-15 19:28:12 +08:00
|
|
|
ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype);
|
2010-05-12 01:44:00 +08:00
|
|
|
for( i = 0; i < N; i++, ++from )
|
|
|
|
{
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2012-03-27 22:43:24 +08:00
|
|
|
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;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2012-03-27 22:43:24 +08:00
|
|
|
if( createMissing )
|
|
|
|
{
|
|
|
|
int idx[] = { i0 };
|
|
|
|
return newNode( idx, h );
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
return createMissing ? newNode(idx, h) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2010-07-16 20:54:53 +08:00
|
|
|
newsize = (size_t)1 << cvCeil(std::log((double)newsize)/CV_LOG2);
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
size_t i, hsize = hdr->hashtab.size();
|
2013-02-25 00:14:01 +08:00
|
|
|
std::vector<size_t> _newh(newsize);
|
2010-05-12 01:44:00 +08:00
|
|
|
size_t* newh = &_newh[0];
|
|
|
|
for( i = 0; i < newsize; i++ )
|
|
|
|
newh[i] = 0;
|
|
|
|
uchar* pool = &hdr->pool[0];
|
|
|
|
for( i = 0; i < hsize; i++ )
|
|
|
|
{
|
|
|
|
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();
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( !hdr->freeList )
|
|
|
|
{
|
|
|
|
size_t i, nsz = hdr->nodeSize, psize = hdr->pool.size(),
|
|
|
|
newpsize = std::max(psize*2, 8*nsz);
|
|
|
|
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];
|
2010-07-16 20:54:53 +08:00
|
|
|
size_t esz = elemSize();
|
2010-05-12 01:44:00 +08:00
|
|
|
uchar* p = &value<uchar>(elem);
|
2010-07-16 20:54:53 +08:00
|
|
|
if( esz == sizeof(float) )
|
2010-05-12 01:44:00 +08:00
|
|
|
*((float*)p) = 0.f;
|
2010-07-16 20:54:53 +08:00
|
|
|
else if( esz == sizeof(double) )
|
2010-05-12 01:44:00 +08:00
|
|
|
*((double*)p) = 0.;
|
|
|
|
else
|
2010-07-16 20:54:53 +08:00
|
|
|
memset(p, 0, esz);
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
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;
|
2013-02-25 00:14:01 +08:00
|
|
|
const std::vector<size_t>& htab = hdr.hashtab;
|
2010-05-12 01:44:00 +08:00
|
|
|
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 )
|
|
|
|
{
|
|
|
|
SparseMatConstIterator it = src.begin();
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
size_t i, N = src.nzcount();
|
|
|
|
normType &= NORM_TYPE_MASK;
|
|
|
|
int type = src.type();
|
|
|
|
double result = 0;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( type == CV_32F )
|
|
|
|
{
|
|
|
|
if( normType == NORM_INF )
|
|
|
|
for( i = 0; i < N; i++, ++it )
|
|
|
|
result = std::max(result, std::abs((double)*(const float*)it.ptr));
|
|
|
|
else if( normType == NORM_L1 )
|
|
|
|
for( i = 0; i < N; i++, ++it )
|
|
|
|
result += std::abs(*(const float*)it.ptr);
|
|
|
|
else
|
|
|
|
for( i = 0; i < N; i++, ++it )
|
|
|
|
{
|
2012-06-08 01:21:29 +08:00
|
|
|
double v = *(const float*)it.ptr;
|
2010-05-12 01:44:00 +08:00
|
|
|
result += v*v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( type == CV_64F )
|
|
|
|
{
|
|
|
|
if( normType == NORM_INF )
|
|
|
|
for( i = 0; i < N; i++, ++it )
|
|
|
|
result = std::max(result, std::abs(*(const double*)it.ptr));
|
|
|
|
else if( normType == NORM_L1 )
|
|
|
|
for( i = 0; i < N; i++, ++it )
|
|
|
|
result += std::abs(*(const double*)it.ptr);
|
|
|
|
else
|
|
|
|
for( i = 0; i < N; i++, ++it )
|
|
|
|
{
|
2012-06-08 01:21:29 +08:00
|
|
|
double v = *(const double*)it.ptr;
|
2010-05-12 01:44:00 +08:00
|
|
|
result += v*v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( normType == NORM_L2 )
|
|
|
|
result = std::sqrt(result);
|
|
|
|
return result;
|
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
void minMaxLoc( const SparseMat& src, double* _minval, double* _maxval, int* _minidx, int* _maxidx )
|
|
|
|
{
|
|
|
|
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;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( type == CV_32F )
|
|
|
|
{
|
|
|
|
float minval = FLT_MAX, maxval = -FLT_MAX;
|
|
|
|
for( i = 0; i < N; i++, ++it )
|
|
|
|
{
|
|
|
|
float v = *(const float*)it.ptr;
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
double v = *(const double*)it.ptr;
|
|
|
|
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" );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
if( _minidx )
|
|
|
|
for( i = 0; i < d; i++ )
|
|
|
|
_minidx[i] = minidx[i];
|
|
|
|
if( _maxidx )
|
|
|
|
for( i = 0; i < d; i++ )
|
|
|
|
_maxidx[i] = maxidx[i];
|
|
|
|
}
|
|
|
|
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
void normalize( const SparseMat& src, SparseMat& dst, double a, int norm_type )
|
|
|
|
{
|
|
|
|
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" );
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
src.convertTo( dst, -1, scale );
|
|
|
|
}
|
2010-11-30 02:14:08 +08:00
|
|
|
|
|
|
|
////////////////////// RotatedRect //////////////////////
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2014-02-19 23:28:40 +08:00
|
|
|
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
|
2014-02-22 02:56:10 +08:00
|
|
|
CV_Assert( abs(vecs[0].dot(vecs[1])) / (norm(vecs[0]) * norm(vecs[1])) <= FLT_EPSILON );
|
2014-02-19 23:28:40 +08:00
|
|
|
|
|
|
|
// 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;
|
2014-02-20 20:21:48 +08:00
|
|
|
if( abs(vecs[1][1]) < abs(vecs[1][0]) ) wd_i = 1;
|
2014-02-19 23:28:40 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-11-30 02:14:08 +08:00
|
|
|
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;
|
2012-06-08 01:21:29 +08:00
|
|
|
|
2010-11-30 02:14:08 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-12-04 19:40:14 +08:00
|
|
|
Rect RotatedRect::boundingRect() const
|
2010-11-30 02:14:08 +08:00
|
|
|
{
|
|
|
|
Point2f pt[4];
|
|
|
|
points(pt);
|
2013-02-25 00:14:01 +08:00
|
|
|
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)));
|
2010-11-30 02:14:08 +08:00
|
|
|
r.width -= r.x - 1;
|
|
|
|
r.height -= r.y - 1;
|
|
|
|
return r;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2012-06-08 01:21:29 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-03-29 01:01:12 +08:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
/* End of file. */
|