1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
43 #include "precomp.hpp"
44 #include "opencl_kernels_core.hpp"
46 #include "bufferpool.impl.hpp"
48 /****************************************************************************************\
49 * [scaled] Identity matrix initialization *
50 \****************************************************************************************/
54 void MatAllocator::map(UMatData*, int) const
58 void MatAllocator::unmap(UMatData* u) const
60 if(u->urefcount == 0 && u->refcount == 0)
67 void MatAllocator::download(UMatData* u, void* dstptr,
68 int dims, const size_t sz[],
69 const size_t srcofs[], const size_t srcstep[],
70 const size_t dststep[]) const
75 uchar* srcptr = u->data;
76 for( int i = 0; i < dims; i++ )
78 CV_Assert( sz[i] <= (size_t)INT_MAX );
82 srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1);
86 Mat src(dims, isz, CV_8U, srcptr, srcstep);
87 Mat dst(dims, isz, CV_8U, dstptr, dststep);
89 const Mat* arrays[] = { &src, &dst };
91 NAryMatIterator it(arrays, ptrs, 2);
92 size_t j, planesz = it.size;
94 for( j = 0; j < it.nplanes; j++, ++it )
95 memcpy(ptrs[1], ptrs[0], planesz);
99 void MatAllocator::upload(UMatData* u, const void* srcptr, int dims, const size_t sz[],
100 const size_t dstofs[], const size_t dststep[],
101 const size_t srcstep[]) const
106 uchar* dstptr = u->data;
107 for( int i = 0; i < dims; i++ )
109 CV_Assert( sz[i] <= (size_t)INT_MAX );
113 dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1);
117 Mat src(dims, isz, CV_8U, (void*)srcptr, srcstep);
118 Mat dst(dims, isz, CV_8U, dstptr, dststep);
120 const Mat* arrays[] = { &src, &dst };
122 NAryMatIterator it(arrays, ptrs, 2);
123 size_t j, planesz = it.size;
125 for( j = 0; j < it.nplanes; j++, ++it )
126 memcpy(ptrs[1], ptrs[0], planesz);
129 void MatAllocator::copy(UMatData* usrc, UMatData* udst, int dims, const size_t sz[],
130 const size_t srcofs[], const size_t srcstep[],
131 const size_t dstofs[], const size_t dststep[], bool /*sync*/) const
136 uchar* srcptr = usrc->data;
137 uchar* dstptr = udst->data;
138 for( int i = 0; i < dims; i++ )
140 CV_Assert( sz[i] <= (size_t)INT_MAX );
144 srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1);
146 dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1);
150 Mat src(dims, isz, CV_8U, srcptr, srcstep);
151 Mat dst(dims, isz, CV_8U, dstptr, dststep);
153 const Mat* arrays[] = { &src, &dst };
155 NAryMatIterator it(arrays, ptrs, 2);
156 size_t j, planesz = it.size;
158 for( j = 0; j < it.nplanes; j++, ++it )
159 memcpy(ptrs[1], ptrs[0], planesz);
162 BufferPoolController* MatAllocator::getBufferPoolController() const
164 static DummyBufferPoolController dummy;
168 class StdMatAllocator : public MatAllocator
171 UMatData* allocate(int dims, const int* sizes, int type,
172 void* data0, size_t* step, int /*flags*/, UMatUsageFlags /*usageFlags*/) const
174 size_t total = CV_ELEM_SIZE(type);
175 for( int i = dims-1; i >= 0; i-- )
179 if( data0 && step[i] != CV_AUTOSTEP )
181 CV_Assert(total <= step[i]);
189 uchar* data = data0 ? (uchar*)data0 : (uchar*)fastMalloc(total);
190 UMatData* u = new UMatData(this);
191 u->data = u->origdata = data;
194 u->flags |= UMatData::USER_ALLOCATED;
199 bool allocate(UMatData* u, int /*accessFlags*/, UMatUsageFlags /*usageFlags*/) const
205 void deallocate(UMatData* u) const
207 CV_Assert(u->urefcount >= 0);
208 CV_Assert(u->refcount >= 0);
209 if(u && u->refcount == 0)
211 if( !(u->flags & UMatData::USER_ALLOCATED) )
213 fastFree(u->origdata);
222 MatAllocator* Mat::getStdAllocator()
224 static MatAllocator * allocator = new StdMatAllocator();
228 void swap( Mat& a, Mat& b )
230 std::swap(a.flags, b.flags);
231 std::swap(a.dims, b.dims);
232 std::swap(a.rows, b.rows);
233 std::swap(a.cols, b.cols);
234 std::swap(a.data, b.data);
235 std::swap(a.datastart, b.datastart);
236 std::swap(a.dataend, b.dataend);
237 std::swap(a.datalimit, b.datalimit);
238 std::swap(a.allocator, b.allocator);
241 std::swap(a.size.p, b.size.p);
242 std::swap(a.step.p, b.step.p);
243 std::swap(a.step.buf[0], b.step.buf[0]);
244 std::swap(a.step.buf[1], b.step.buf[1]);
246 if( a.step.p == b.step.buf )
248 a.step.p = a.step.buf;
252 if( b.step.p == a.step.buf )
254 b.step.p = b.step.buf;
260 static inline void setSize( Mat& m, int _dims, const int* _sz,
261 const size_t* _steps, bool autoSteps=false )
263 CV_Assert( 0 <= _dims && _dims <= CV_MAX_DIM );
264 if( m.dims != _dims )
266 if( m.step.p != m.step.buf )
269 m.step.p = m.step.buf;
274 m.step.p = (size_t*)fastMalloc(_dims*sizeof(m.step.p[0]) + (_dims+1)*sizeof(m.size.p[0]));
275 m.size.p = (int*)(m.step.p + _dims) + 1;
276 m.size.p[-1] = _dims;
277 m.rows = m.cols = -1;
285 size_t esz = CV_ELEM_SIZE(m.flags), esz1 = CV_ELEM_SIZE1(m.flags), total = esz;
287 for( i = _dims-1; i >= 0; i-- )
295 if (_steps[i] % esz1 != 0)
297 CV_Error(Error::BadStep, "Step must be a multiple of esz1");
300 m.step.p[i] = i < _dims-1 ? _steps[i] : esz;
305 int64 total1 = (int64)total*s;
306 if( (uint64)total1 != (size_t)total1 )
307 CV_Error( CV_StsOutOfRange, "The total matrix size does not fit to \"size_t\" type" );
308 total = (size_t)total1;
320 static void updateContinuityFlag(Mat& m)
323 for( i = 0; i < m.dims; i++ )
329 for( j = m.dims-1; j > i; j-- )
331 if( m.step[j]*m.size[j] < m.step[j-1] )
335 uint64 t = (uint64)m.step[0]*m.size[0];
336 if( j <= i && t == (size_t)t )
337 m.flags |= Mat::CONTINUOUS_FLAG;
339 m.flags &= ~Mat::CONTINUOUS_FLAG;
342 static void finalizeHdr(Mat& m)
344 updateContinuityFlag(m);
347 m.rows = m.cols = -1;
349 m.datastart = m.data = m.u->data;
352 m.datalimit = m.datastart + m.size[0]*m.step[0];
355 m.dataend = m.data + m.size[d-1]*m.step[d-1];
356 for( int i = 0; i < d-1; i++ )
357 m.dataend += (m.size[i] - 1)*m.step[i];
360 m.dataend = m.datalimit;
363 m.dataend = m.datalimit = 0;
367 void Mat::create(int d, const int* _sizes, int _type)
370 CV_Assert(0 <= d && d <= CV_MAX_DIM && _sizes);
371 _type = CV_MAT_TYPE(_type);
373 if( data && (d == dims || (d == 1 && dims <= 2)) && _type == type() )
375 if( d == 2 && rows == _sizes[0] && cols == _sizes[1] )
377 for( i = 0; i < d; i++ )
378 if( size[i] != _sizes[i] )
380 if( i == d && (d > 1 || size[1] == 1))
387 flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL;
388 setSize(*this, d, _sizes, 0, true);
392 MatAllocator *a = allocator, *a0 = getStdAllocator();
394 if( !a || a == tegra::getAllocator() )
395 a = tegra::getAllocator(d, _sizes, _type);
401 u = a->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT);
407 u = a0->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT);
410 CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
417 void Mat::copySize(const Mat& m)
419 setSize(*this, m.dims, 0, 0);
420 for( int i = 0; i < dims; i++ )
427 void Mat::deallocate()
430 (u->currAllocator ? u->currAllocator : allocator ? allocator : getStdAllocator())->unmap(u);
434 Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange)
435 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
436 datalimit(0), allocator(0), u(0), size(&rows)
438 CV_Assert( m.dims >= 2 );
441 AutoBuffer<Range> rs(m.dims);
444 for( int i = 2; i < m.dims; i++ )
445 rs[i] = Range::all();
451 if( _rowRange != Range::all() && _rowRange != Range(0,rows) )
453 CV_Assert( 0 <= _rowRange.start && _rowRange.start <= _rowRange.end && _rowRange.end <= m.rows );
454 rows = _rowRange.size();
455 data += step*_rowRange.start;
456 flags |= SUBMATRIX_FLAG;
459 if( _colRange != Range::all() && _colRange != Range(0,cols) )
461 CV_Assert( 0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols );
462 cols = _colRange.size();
463 data += _colRange.start*elemSize();
464 flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1;
465 flags |= SUBMATRIX_FLAG;
469 flags |= CONTINUOUS_FLAG;
471 if( rows <= 0 || cols <= 0 )
479 Mat::Mat(const Mat& m, const Rect& roi)
480 : flags(m.flags), dims(2), rows(roi.height), cols(roi.width),
481 data(m.data + roi.y*m.step[0]),
482 datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit),
483 allocator(m.allocator), u(m.u), size(&rows)
485 CV_Assert( m.dims <= 2 );
486 flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1;
487 flags |= roi.height == 1 ? CONTINUOUS_FLAG : 0;
489 size_t esz = CV_ELEM_SIZE(flags);
491 CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols &&
492 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows );
494 CV_XADD(&u->refcount, 1);
495 if( roi.width < m.cols || roi.height < m.rows )
496 flags |= SUBMATRIX_FLAG;
498 step[0] = m.step[0]; step[1] = esz;
500 if( rows <= 0 || cols <= 0 )
508 Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _steps)
509 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
510 datalimit(0), allocator(0), u(0), size(&rows)
512 flags |= CV_MAT_TYPE(_type);
513 datastart = data = (uchar*)_data;
514 setSize(*this, _dims, _sizes, _steps, true);
519 Mat::Mat(const Mat& m, const Range* ranges)
520 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
521 datalimit(0), allocator(0), u(0), size(&rows)
526 for( i = 0; i < d; i++ )
529 CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) );
532 for( i = 0; i < d; i++ )
535 if( r != Range::all() && r != Range(0, size.p[i]))
537 size.p[i] = r.end - r.start;
538 data += r.start*step.p[i];
539 flags |= SUBMATRIX_FLAG;
542 updateContinuityFlag(*this);
546 static Mat cvMatNDToMat(const CvMatND* m, bool copyData)
552 thiz.datastart = thiz.data = m->data.ptr;
553 thiz.flags |= CV_MAT_TYPE(m->type);
554 int _sizes[CV_MAX_DIM];
555 size_t _steps[CV_MAX_DIM];
558 for( i = 0; i < d; i++ )
560 _sizes[i] = m->dim[i].size;
561 _steps[i] = m->dim[i].step;
564 setSize(thiz, d, _sizes, _steps);
577 static Mat cvMatToMat(const CvMat* m, bool copyData)
586 thiz.flags = Mat::MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG));
590 thiz.datastart = thiz.data = m->data.ptr;
591 size_t esz = CV_ELEM_SIZE(m->type), minstep = thiz.cols*esz, _step = m->step;
594 thiz.datalimit = thiz.datastart + _step*thiz.rows;
595 thiz.dataend = thiz.datalimit - _step + minstep;
596 thiz.step[0] = _step; thiz.step[1] = esz;
600 thiz.datastart = thiz.dataend = thiz.data = 0;
601 Mat(m->rows, m->cols, m->type, m->data.ptr, m->step).copyTo(thiz);
608 static Mat iplImageToMat(const IplImage* img, bool copyData)
616 CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0);
618 int imgdepth = IPL2CV_DEPTH(img->depth);
620 m.step[0] = img->widthStep;
624 CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL);
625 m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, img->nChannels);
626 m.rows = img->height;
628 m.datastart = m.data = (uchar*)img->imageData;
629 esz = CV_ELEM_SIZE(m.flags);
633 CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL || img->roi->coi != 0);
634 bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE;
635 m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, selectedPlane ? 1 : img->nChannels);
636 m.rows = img->roi->height;
637 m.cols = img->roi->width;
638 esz = CV_ELEM_SIZE(m.flags);
639 m.datastart = m.data = (uchar*)img->imageData +
640 (selectedPlane ? (img->roi->coi - 1)*m.step*img->height : 0) +
641 img->roi->yOffset*m.step[0] + img->roi->xOffset*esz;
643 m.datalimit = m.datastart + m.step.p[0]*m.rows;
644 m.dataend = m.datastart + m.step.p[0]*(m.rows-1) + esz*m.cols;
645 m.flags |= (m.cols*esz == m.step.p[0] || m.rows == 1 ? Mat::CONTINUOUS_FLAG : 0);
652 if( !img->roi || !img->roi->coi ||
653 img->dataOrder == IPL_DATA_ORDER_PLANE)
657 int ch[] = {img->roi->coi - 1, 0};
658 m.create(m2.rows, m2.cols, m2.type());
659 mixChannels(&m2, 1, &m, 1, ch, 1);
666 Mat Mat::diag(int d) const
668 CV_Assert( dims <= 2 );
670 size_t esz = elemSize();
675 len = std::min(cols - d, rows);
680 len = std::min(rows + d, cols);
683 CV_DbgAssert( len > 0 );
685 m.size[0] = m.rows = len;
686 m.size[1] = m.cols = 1;
687 m.step[0] += (len > 1 ? esz : 0);
690 m.flags &= ~CONTINUOUS_FLAG;
692 m.flags |= CONTINUOUS_FLAG;
694 if( size() != Size(1,1) )
695 m.flags |= SUBMATRIX_FLAG;
700 void Mat::pop_back(size_t nelems)
702 CV_Assert( nelems <= (size_t)size.p[0] );
705 *this = rowRange(0, size.p[0] - (int)nelems);
708 size.p[0] -= (int)nelems;
709 dataend -= nelems*step.p[0];
710 /*if( size.p[0] <= 1 )
713 flags |= CONTINUOUS_FLAG;
715 updateContinuityFlag(*this);
721 void Mat::push_back_(const void* elem)
724 if( isSubmatrix() || dataend + step.p[0] > datalimit )
725 reserve( std::max(r + 1, (r*3+1)/2) );
727 size_t esz = elemSize();
728 memcpy(data + r*step.p[0], elem, esz);
730 dataend += step.p[0];
731 if( esz < step.p[0] )
732 flags &= ~CONTINUOUS_FLAG;
735 void Mat::reserve(size_t nelems)
737 const size_t MIN_SIZE = 64;
739 CV_Assert( (int)nelems >= 0 );
740 if( !isSubmatrix() && data + step.p[0]*nelems <= datalimit )
745 if( (size_t)r >= nelems )
748 size.p[0] = std::max((int)nelems, 1);
749 size_t newsize = total()*elemSize();
751 if( newsize < MIN_SIZE )
752 size.p[0] = (int)((MIN_SIZE + newsize - 1)*nelems/newsize);
754 Mat m(dims, size.p, type());
758 Mat mpart = m.rowRange(0, r);
764 dataend = data + step.p[0]*r;
768 void Mat::resize(size_t nelems)
770 int saveRows = size.p[0];
771 if( saveRows == (int)nelems )
773 CV_Assert( (int)nelems >= 0 );
775 if( isSubmatrix() || data + step.p[0]*nelems > datalimit )
778 size.p[0] = (int)nelems;
779 dataend += (size.p[0] - saveRows)*step.p[0];
781 //updateContinuityFlag(*this);
785 void Mat::resize(size_t nelems, const Scalar& s)
787 int saveRows = size.p[0];
790 if( size.p[0] > saveRows )
792 Mat part = rowRange(saveRows, size.p[0]);
797 void Mat::push_back(const Mat& elems)
799 int r = size.p[0], delta = elems.size.p[0];
810 *this = elems.clone();
814 size.p[0] = elems.size.p[0];
815 bool eq = size == elems.size;
818 CV_Error(CV_StsUnmatchedSizes, "");
819 if( type() != elems.type() )
820 CV_Error(CV_StsUnmatchedFormats, "");
822 if( isSubmatrix() || dataend + step.p[0]*delta > datalimit )
823 reserve( std::max(r + delta, (r*3+1)/2) );
826 dataend += step.p[0]*delta;
828 //updateContinuityFlag(*this);
830 if( isContinuous() && elems.isContinuous() )
831 memcpy(data + r*step.p[0], elems.data, elems.total()*elems.elemSize());
834 Mat part = rowRange(r, r + delta);
840 Mat cvarrToMat(const CvArr* arr, bool copyData,
841 bool /*allowND*/, int coiMode, AutoBuffer<double>* abuf )
845 if( CV_IS_MAT_HDR_Z(arr) )
846 return cvMatToMat((const CvMat*)arr, copyData);
847 if( CV_IS_MATND(arr) )
848 return cvMatNDToMat((const CvMatND*)arr, copyData );
849 if( CV_IS_IMAGE(arr) )
851 const IplImage* iplimg = (const IplImage*)arr;
852 if( coiMode == 0 && iplimg->roi && iplimg->roi->coi > 0 )
853 CV_Error(CV_BadCOI, "COI is not supported by the function");
854 return iplImageToMat(iplimg, copyData);
858 CvSeq* seq = (CvSeq*)arr;
859 int total = seq->total, type = CV_MAT_TYPE(seq->flags), esz = seq->elem_size;
862 CV_Assert(total > 0 && CV_ELEM_SIZE(seq->flags) == esz);
863 if(!copyData && seq->first->next == seq->first)
864 return Mat(total, 1, type, seq->first->data);
867 abuf->allocate(((size_t)total*esz + sizeof(double)-1)/sizeof(double));
868 double* bufdata = *abuf;
869 cvCvtSeqToArray(seq, bufdata, CV_WHOLE_SEQ);
870 return Mat(total, 1, type, bufdata);
873 Mat buf(total, 1, type);
874 cvCvtSeqToArray(seq, buf.data, CV_WHOLE_SEQ);
877 CV_Error(CV_StsBadArg, "Unknown array type");
881 void Mat::locateROI( Size& wholeSize, Point& ofs ) const
883 CV_Assert( dims <= 2 && step[0] > 0 );
884 size_t esz = elemSize(), minstep;
885 ptrdiff_t delta1 = data - datastart, delta2 = dataend - datastart;
891 ofs.y = (int)(delta1/step[0]);
892 ofs.x = (int)((delta1 - step[0]*ofs.y)/esz);
893 CV_DbgAssert( data == datastart + ofs.y*step[0] + ofs.x*esz );
895 minstep = (ofs.x + cols)*esz;
896 wholeSize.height = (int)((delta2 - minstep)/step[0] + 1);
897 wholeSize.height = std::max(wholeSize.height, ofs.y + rows);
898 wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz);
899 wholeSize.width = std::max(wholeSize.width, ofs.x + cols);
902 Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright )
904 CV_Assert( dims <= 2 && step[0] > 0 );
905 Size wholeSize; Point ofs;
906 size_t esz = elemSize();
907 locateROI( wholeSize, ofs );
908 int row1 = std::max(ofs.y - dtop, 0), row2 = std::min(ofs.y + rows + dbottom, wholeSize.height);
909 int col1 = std::max(ofs.x - dleft, 0), col2 = std::min(ofs.x + cols + dright, wholeSize.width);
910 data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
911 rows = row2 - row1; cols = col2 - col1;
912 size.p[0] = rows; size.p[1] = cols;
913 if( esz*cols == step[0] || rows == 1 )
914 flags |= CONTINUOUS_FLAG;
916 flags &= ~CONTINUOUS_FLAG;
922 void cv::extractImageCOI(const CvArr* arr, OutputArray _ch, int coi)
924 Mat mat = cvarrToMat(arr, false, true, 1);
925 _ch.create(mat.dims, mat.size, mat.depth());
926 Mat ch = _ch.getMat();
929 CV_Assert( CV_IS_IMAGE(arr) );
930 coi = cvGetImageCOI((const IplImage*)arr)-1;
932 CV_Assert(0 <= coi && coi < mat.channels());
933 int _pairs[] = { coi, 0 };
934 mixChannels( &mat, 1, &ch, 1, _pairs, 1 );
937 void cv::insertImageCOI(InputArray _ch, CvArr* arr, int coi)
939 Mat ch = _ch.getMat(), mat = cvarrToMat(arr, false, true, 1);
942 CV_Assert( CV_IS_IMAGE(arr) );
943 coi = cvGetImageCOI((const IplImage*)arr)-1;
945 CV_Assert(ch.size == mat.size && ch.depth() == mat.depth() && 0 <= coi && coi < mat.channels());
946 int _pairs[] = { 0, coi };
947 mixChannels( &ch, 1, &mat, 1, _pairs, 1 );
953 Mat Mat::reshape(int new_cn, int new_rows) const
958 if( dims > 2 && new_rows == 0 && new_cn != 0 && size[dims-1]*cn % new_cn == 0 )
960 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
961 hdr.step[dims-1] = CV_ELEM_SIZE(hdr.flags);
962 hdr.size[dims-1] = hdr.size[dims-1]*cn / new_cn;
966 CV_Assert( dims <= 2 );
971 int total_width = cols * cn;
973 if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 )
974 new_rows = rows * total_width / new_cn;
976 if( new_rows != 0 && new_rows != rows )
978 int total_size = total_width * rows;
979 if( !isContinuous() )
980 CV_Error( CV_BadStep,
981 "The matrix is not continuous, thus its number of rows can not be changed" );
983 if( (unsigned)new_rows > (unsigned)total_size )
984 CV_Error( CV_StsOutOfRange, "Bad new number of rows" );
986 total_width = total_size / new_rows;
988 if( total_width * new_rows != total_size )
989 CV_Error( CV_StsBadArg, "The total number of matrix elements "
990 "is not divisible by the new number of rows" );
993 hdr.step[0] = total_width * elemSize1();
996 int new_width = total_width / new_cn;
998 if( new_width * new_cn != total_width )
999 CV_Error( CV_BadNumChannels,
1000 "The total width is not divisible by the new number of channels" );
1002 hdr.cols = new_width;
1003 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
1004 hdr.step[1] = CV_ELEM_SIZE(hdr.flags);
1008 Mat Mat::diag(const Mat& d)
1010 CV_Assert( d.cols == 1 || d.rows == 1 );
1011 int len = d.rows + d.cols - 1;
1012 Mat m(len, len, d.type(), Scalar(0));
1021 int Mat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) const
1023 return (depth() == _depth || _depth <= 0) &&
1024 (isContinuous() || !_requireContinuous) &&
1025 ((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) ||
1026 (cols == _elemChannels && channels() == 1))) ||
1027 (dims == 3 && channels() == 1 && size.p[2] == _elemChannels && (size.p[0] == 1 || size.p[1] == 1) &&
1028 (isContinuous() || step.p[1] == step.p[2]*size.p[2])))
1029 ? (int)(total()*channels()/_elemChannels) : -1;
1033 void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
1035 int i, depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
1041 uchar* buf = (uchar*)_buf;
1042 for(i = 0; i < cn; i++)
1043 buf[i] = saturate_cast<uchar>(s.val[i]);
1044 for(; i < unroll_to; i++)
1050 schar* buf = (schar*)_buf;
1051 for(i = 0; i < cn; i++)
1052 buf[i] = saturate_cast<schar>(s.val[i]);
1053 for(; i < unroll_to; i++)
1059 ushort* buf = (ushort*)_buf;
1060 for(i = 0; i < cn; i++)
1061 buf[i] = saturate_cast<ushort>(s.val[i]);
1062 for(; i < unroll_to; i++)
1068 short* buf = (short*)_buf;
1069 for(i = 0; i < cn; i++)
1070 buf[i] = saturate_cast<short>(s.val[i]);
1071 for(; i < unroll_to; i++)
1077 int* buf = (int*)_buf;
1078 for(i = 0; i < cn; i++)
1079 buf[i] = saturate_cast<int>(s.val[i]);
1080 for(; i < unroll_to; i++)
1086 float* buf = (float*)_buf;
1087 for(i = 0; i < cn; i++)
1088 buf[i] = saturate_cast<float>(s.val[i]);
1089 for(; i < unroll_to; i++)
1095 double* buf = (double*)_buf;
1096 for(i = 0; i < cn; i++)
1097 buf[i] = saturate_cast<double>(s.val[i]);
1098 for(; i < unroll_to; i++)
1103 CV_Error(CV_StsUnsupportedFormat,"");
1108 /*************************************************************************************************\
1110 \*************************************************************************************************/
1112 Mat _InputArray::getMat(int i) const
1115 int accessFlags = flags & ACCESS_MASK;
1119 const Mat* m = (const Mat*)obj;
1127 const UMat* m = (const UMat*)obj;
1129 return m->getMat(accessFlags);
1130 return m->getMat(accessFlags).row(i);
1136 return (Mat)*((const MatExpr*)obj);
1142 return Mat(sz, flags, obj);
1145 if( k == STD_VECTOR )
1148 int t = CV_MAT_TYPE(flags);
1149 const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
1151 return !v.empty() ? Mat(size(), t, (void*)&v[0]) : Mat();
1157 if( k == STD_VECTOR_VECTOR )
1160 const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
1161 CV_Assert( 0 <= i && i < (int)vv.size() );
1162 const std::vector<uchar>& v = vv[i];
1164 return !v.empty() ? Mat(size(i), t, (void*)&v[0]) : Mat();
1167 if( k == STD_VECTOR_MAT )
1169 const std::vector<Mat>& v = *(const std::vector<Mat>*)obj;
1170 CV_Assert( 0 <= i && i < (int)v.size() );
1175 if( k == STD_VECTOR_UMAT )
1177 const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
1178 CV_Assert( 0 <= i && i < (int)v.size() );
1180 return v[i].getMat(accessFlags);
1183 if( k == OPENGL_BUFFER )
1186 CV_Error(cv::Error::StsNotImplemented, "You should explicitly call mapHost/unmapHost methods for ogl::Buffer object");
1193 CV_Error(cv::Error::StsNotImplemented, "You should explicitly call download method for cuda::GpuMat object");
1201 const cuda::CudaMem* cuda_mem = (const cuda::CudaMem*)obj;
1203 return cuda_mem->createMatHeader();
1206 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
1210 UMat _InputArray::getUMat(int i) const
1213 int accessFlags = flags & ACCESS_MASK;
1217 const UMat* m = (const UMat*)obj;
1223 if( k == STD_VECTOR_UMAT )
1225 const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
1226 CV_Assert( 0 <= i && i < (int)v.size() );
1233 const Mat* m = (const Mat*)obj;
1235 return m->getUMat(accessFlags);
1236 return m->row(i).getUMat(accessFlags);
1239 return getMat(i).getUMat(accessFlags);
1242 void _InputArray::getMatVector(std::vector<Mat>& mv) const
1245 int accessFlags = flags & ACCESS_MASK;
1249 const Mat& m = *(const Mat*)obj;
1250 int i, n = (int)m.size[0];
1253 for( i = 0; i < n; i++ )
1254 mv[i] = m.dims == 2 ? Mat(1, m.cols, m.type(), (void*)m.ptr(i)) :
1255 Mat(m.dims-1, &m.size[1], m.type(), (void*)m.ptr(i), &m.step[1]);
1261 Mat m = *(const MatExpr*)obj;
1262 int i, n = m.size[0];
1265 for( i = 0; i < n; i++ )
1272 size_t i, n = sz.height, esz = CV_ELEM_SIZE(flags);
1275 for( i = 0; i < n; i++ )
1276 mv[i] = Mat(1, sz.width, CV_MAT_TYPE(flags), (uchar*)obj + esz*sz.width*i);
1280 if( k == STD_VECTOR )
1282 const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
1284 size_t i, n = v.size(), esz = CV_ELEM_SIZE(flags);
1285 int t = CV_MAT_DEPTH(flags), cn = CV_MAT_CN(flags);
1288 for( i = 0; i < n; i++ )
1289 mv[i] = Mat(1, cn, t, (void*)(&v[0] + esz*i));
1299 if( k == STD_VECTOR_VECTOR )
1301 const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
1302 int i, n = (int)vv.size();
1303 int t = CV_MAT_TYPE(flags);
1306 for( i = 0; i < n; i++ )
1308 const std::vector<uchar>& v = vv[i];
1309 mv[i] = Mat(size(i), t, (void*)&v[0]);
1314 if( k == STD_VECTOR_MAT )
1316 const std::vector<Mat>& v = *(const std::vector<Mat>*)obj;
1317 size_t i, n = v.size();
1320 for( i = 0; i < n; i++ )
1325 if( k == STD_VECTOR_UMAT )
1327 const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
1328 size_t i, n = v.size();
1331 for( i = 0; i < n; i++ )
1332 mv[i] = v[i].getMat(accessFlags);
1336 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
1339 void _InputArray::getUMatVector(std::vector<UMat>& umv) const
1342 int accessFlags = flags & ACCESS_MASK;
1350 if( k == STD_VECTOR_MAT )
1352 const std::vector<Mat>& v = *(const std::vector<Mat>*)obj;
1353 size_t i, n = v.size();
1356 for( i = 0; i < n; i++ )
1357 umv[i] = v[i].getUMat(accessFlags);
1361 if( k == STD_VECTOR_UMAT )
1363 const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
1364 size_t i, n = v.size();
1367 for( i = 0; i < n; i++ )
1374 UMat& v = *(UMat*)obj;
1381 Mat& v = *(Mat*)obj;
1383 umv[0] = v.getUMat(accessFlags);
1387 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
1390 cuda::GpuMat _InputArray::getGpuMat() const
1396 const cuda::GpuMat* d_mat = (const cuda::GpuMat*)obj;
1402 const cuda::CudaMem* cuda_mem = (const cuda::CudaMem*)obj;
1403 return cuda_mem->createGpuMatHeader();
1406 if (k == OPENGL_BUFFER)
1408 CV_Error(cv::Error::StsNotImplemented, "You should explicitly call mapDevice/unmapDevice methods for ogl::Buffer object");
1409 return cuda::GpuMat();
1413 return cuda::GpuMat();
1415 CV_Error(cv::Error::StsNotImplemented, "getGpuMat is available only for cuda::GpuMat and cuda::CudaMem");
1416 return cuda::GpuMat();
1419 ogl::Buffer _InputArray::getOGlBuffer() const
1423 CV_Assert(k == OPENGL_BUFFER);
1425 const ogl::Buffer* gl_buf = (const ogl::Buffer*)obj;
1429 int _InputArray::kind() const
1431 return flags & KIND_MASK;
1434 int _InputArray::rows(int i) const
1436 return size(i).height;
1439 int _InputArray::cols(int i) const
1441 return size(i).width;
1444 Size _InputArray::size(int i) const
1451 return ((const Mat*)obj)->size();
1457 return ((const MatExpr*)obj)->size();
1463 return ((const UMat*)obj)->size();
1472 if( k == STD_VECTOR )
1475 const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
1476 const std::vector<int>& iv = *(const std::vector<int>*)obj;
1477 size_t szb = v.size(), szi = iv.size();
1478 return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1);
1484 if( k == STD_VECTOR_VECTOR )
1486 const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
1488 return vv.empty() ? Size() : Size((int)vv.size(), 1);
1489 CV_Assert( i < (int)vv.size() );
1490 const std::vector<std::vector<int> >& ivv = *(const std::vector<std::vector<int> >*)obj;
1492 size_t szb = vv[i].size(), szi = ivv[i].size();
1493 return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1);
1496 if( k == STD_VECTOR_MAT )
1498 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1500 return vv.empty() ? Size() : Size((int)vv.size(), 1);
1501 CV_Assert( i < (int)vv.size() );
1503 return vv[i].size();
1506 if( k == STD_VECTOR_UMAT )
1508 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
1510 return vv.empty() ? Size() : Size((int)vv.size(), 1);
1511 CV_Assert( i < (int)vv.size() );
1513 return vv[i].size();
1516 if( k == OPENGL_BUFFER )
1519 const ogl::Buffer* buf = (const ogl::Buffer*)obj;
1526 const cuda::GpuMat* d_mat = (const cuda::GpuMat*)obj;
1527 return d_mat->size();
1530 CV_Assert( k == CUDA_MEM );
1531 //if( k == CUDA_MEM )
1534 const cuda::CudaMem* cuda_mem = (const cuda::CudaMem*)obj;
1535 return cuda_mem->size();
1539 int _InputArray::sizend(int* arrsz, int i) const
1541 int j, d=0, k = kind();
1548 const Mat& m = *(const Mat*)obj;
1551 for(j = 0; j < d; j++)
1552 arrsz[j] = m.size.p[j];
1554 else if( k == UMAT )
1557 const UMat& m = *(const UMat*)obj;
1560 for(j = 0; j < d; j++)
1561 arrsz[j] = m.size.p[j];
1563 else if( k == STD_VECTOR_MAT && i >= 0 )
1565 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1566 CV_Assert( i < (int)vv.size() );
1567 const Mat& m = vv[i];
1570 for(j = 0; j < d; j++)
1571 arrsz[j] = m.size.p[j];
1573 else if( k == STD_VECTOR_UMAT && i >= 0 )
1575 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
1576 CV_Assert( i < (int)vv.size() );
1577 const UMat& m = vv[i];
1580 for(j = 0; j < d; j++)
1581 arrsz[j] = m.size.p[j];
1585 Size sz2d = size(i);
1589 arrsz[0] = sz2d.height;
1590 arrsz[1] = sz2d.width;
1597 bool _InputArray::sameSize(const _InputArray& arr) const
1599 int k1 = kind(), k2 = arr.kind();
1604 const Mat* m = ((const Mat*)obj);
1606 return m->size == ((const Mat*)arr.obj)->size;
1608 return m->size == ((const UMat*)arr.obj)->size;
1613 else if( k1 == UMAT )
1615 const UMat* m = ((const UMat*)obj);
1617 return m->size == ((const Mat*)arr.obj)->size;
1619 return m->size == ((const UMat*)arr.obj)->size;
1626 if( arr.dims() > 2 )
1628 return sz1 == arr.size();
1631 int _InputArray::dims(int i) const
1638 return ((const Mat*)obj)->dims;
1644 return ((const MatExpr*)obj)->a.dims;
1650 return ((const UMat*)obj)->dims;
1659 if( k == STD_VECTOR )
1668 if( k == STD_VECTOR_VECTOR )
1670 const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
1673 CV_Assert( i < (int)vv.size() );
1677 if( k == STD_VECTOR_MAT )
1679 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1682 CV_Assert( i < (int)vv.size() );
1687 if( k == STD_VECTOR_UMAT )
1689 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
1692 CV_Assert( i < (int)vv.size() );
1697 if( k == OPENGL_BUFFER )
1709 CV_Assert( k == CUDA_MEM );
1710 //if( k == CUDA_MEM )
1717 size_t _InputArray::total(int i) const
1724 return ((const Mat*)obj)->total();
1730 return ((const UMat*)obj)->total();
1733 if( k == STD_VECTOR_MAT )
1735 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1739 CV_Assert( i < (int)vv.size() );
1740 return vv[i].total();
1743 if( k == STD_VECTOR_UMAT )
1745 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
1749 CV_Assert( i < (int)vv.size() );
1750 return vv[i].total();
1753 return size(i).area();
1756 int _InputArray::type(int i) const
1761 return ((const Mat*)obj)->type();
1764 return ((const UMat*)obj)->type();
1767 return ((const MatExpr*)obj)->type();
1769 if( k == MATX || k == STD_VECTOR || k == STD_VECTOR_VECTOR )
1770 return CV_MAT_TYPE(flags);
1775 if( k == STD_VECTOR_UMAT )
1777 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
1780 CV_Assert((flags & FIXED_TYPE) != 0);
1781 return CV_MAT_TYPE(flags);
1783 CV_Assert( i < (int)vv.size() );
1784 return vv[i >= 0 ? i : 0].type();
1787 if( k == STD_VECTOR_MAT )
1789 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1792 CV_Assert((flags & FIXED_TYPE) != 0);
1793 return CV_MAT_TYPE(flags);
1795 CV_Assert( i < (int)vv.size() );
1796 return vv[i >= 0 ? i : 0].type();
1799 if( k == OPENGL_BUFFER )
1800 return ((const ogl::Buffer*)obj)->type();
1803 return ((const cuda::GpuMat*)obj)->type();
1805 CV_Assert( k == CUDA_MEM );
1806 //if( k == CUDA_MEM )
1807 return ((const cuda::CudaMem*)obj)->type();
1810 int _InputArray::depth(int i) const
1812 return CV_MAT_DEPTH(type(i));
1815 int _InputArray::channels(int i) const
1817 return CV_MAT_CN(type(i));
1820 bool _InputArray::empty() const
1825 return ((const Mat*)obj)->empty();
1828 return ((const UMat*)obj)->empty();
1836 if( k == STD_VECTOR )
1838 const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
1845 if( k == STD_VECTOR_VECTOR )
1847 const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj;
1851 if( k == STD_VECTOR_MAT )
1853 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1857 if( k == STD_VECTOR_UMAT )
1859 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
1863 if( k == OPENGL_BUFFER )
1864 return ((const ogl::Buffer*)obj)->empty();
1867 return ((const cuda::GpuMat*)obj)->empty();
1869 CV_Assert( k == CUDA_MEM );
1870 //if( k == CUDA_MEM )
1871 return ((const cuda::CudaMem*)obj)->empty();
1874 bool _InputArray::isContinuous(int i) const
1879 return i < 0 ? ((const Mat*)obj)->isContinuous() : true;
1882 return i < 0 ? ((const UMat*)obj)->isContinuous() : true;
1884 if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR)
1887 if( k == STD_VECTOR_MAT )
1889 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1890 CV_Assert((size_t)i < vv.size());
1891 return vv[i].isContinuous();
1894 if( k == STD_VECTOR_UMAT )
1896 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
1897 CV_Assert((size_t)i < vv.size());
1898 return vv[i].isContinuous();
1901 CV_Error(CV_StsNotImplemented, "Unknown/unsupported array type");
1905 bool _InputArray::isSubmatrix(int i) const
1910 return i < 0 ? ((const Mat*)obj)->isSubmatrix() : false;
1913 return i < 0 ? ((const UMat*)obj)->isSubmatrix() : false;
1915 if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR)
1918 if( k == STD_VECTOR_MAT )
1920 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1921 CV_Assert((size_t)i < vv.size());
1922 return vv[i].isSubmatrix();
1925 if( k == STD_VECTOR_UMAT )
1927 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
1928 CV_Assert((size_t)i < vv.size());
1929 return vv[i].isSubmatrix();
1932 CV_Error(CV_StsNotImplemented, "");
1936 size_t _InputArray::offset(int i) const
1943 const Mat * const m = ((const Mat*)obj);
1944 return (size_t)(m->data - m->datastart);
1950 return ((const UMat*)obj)->offset;
1953 if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR)
1956 if( k == STD_VECTOR_MAT )
1958 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
1961 CV_Assert( i < (int)vv.size() );
1963 return (size_t)(vv[i].data - vv[i].datastart);
1966 if( k == STD_VECTOR_UMAT )
1968 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
1969 CV_Assert((size_t)i < vv.size());
1970 return vv[i].offset;
1976 const cuda::GpuMat * const m = ((const cuda::GpuMat*)obj);
1977 return (size_t)(m->data - m->datastart);
1980 CV_Error(Error::StsNotImplemented, "");
1984 size_t _InputArray::step(int i) const
1991 return ((const Mat*)obj)->step;
1997 return ((const UMat*)obj)->step;
2000 if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR)
2003 if( k == STD_VECTOR_MAT )
2005 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
2008 CV_Assert( i < (int)vv.size() );
2012 if( k == STD_VECTOR_UMAT )
2014 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
2015 CV_Assert((size_t)i < vv.size());
2022 return ((const cuda::GpuMat*)obj)->step;
2025 CV_Error(Error::StsNotImplemented, "");
2029 void _InputArray::copyTo(const _OutputArray& arr) const
2035 else if( k == MAT || k == MATX || k == STD_VECTOR )
2040 else if( k == EXPR )
2042 const MatExpr& e = *((MatExpr*)obj);
2043 if( arr.kind() == MAT )
2044 arr.getMatRef() = e;
2048 else if( k == UMAT )
2049 ((UMat*)obj)->copyTo(arr);
2051 CV_Error(Error::StsNotImplemented, "");
2054 void _InputArray::copyTo(const _OutputArray& arr, const _InputArray & mask) const
2060 else if( k == MAT || k == MATX || k == STD_VECTOR )
2063 m.copyTo(arr, mask);
2065 else if( k == UMAT )
2066 ((UMat*)obj)->copyTo(arr, mask);
2068 CV_Error(Error::StsNotImplemented, "");
2071 bool _OutputArray::fixedSize() const
2073 return (flags & FIXED_SIZE) == FIXED_SIZE;
2076 bool _OutputArray::fixedType() const
2078 return (flags & FIXED_TYPE) == FIXED_TYPE;
2081 void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, int fixedDepthMask) const
2084 if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2086 CV_Assert(!fixedSize() || ((Mat*)obj)->size.operator()() == _sz);
2087 CV_Assert(!fixedType() || ((Mat*)obj)->type() == mtype);
2088 ((Mat*)obj)->create(_sz, mtype);
2091 if( k == UMAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2093 CV_Assert(!fixedSize() || ((UMat*)obj)->size.operator()() == _sz);
2094 CV_Assert(!fixedType() || ((UMat*)obj)->type() == mtype);
2095 ((UMat*)obj)->create(_sz, mtype);
2098 if( k == GPU_MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2100 CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == _sz);
2101 CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype);
2102 ((cuda::GpuMat*)obj)->create(_sz, mtype);
2105 if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2107 CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == _sz);
2108 CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype);
2109 ((ogl::Buffer*)obj)->create(_sz, mtype);
2112 if( k == CUDA_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2114 CV_Assert(!fixedSize() || ((cuda::CudaMem*)obj)->size() == _sz);
2115 CV_Assert(!fixedType() || ((cuda::CudaMem*)obj)->type() == mtype);
2116 ((cuda::CudaMem*)obj)->create(_sz, mtype);
2119 int sizes[] = {_sz.height, _sz.width};
2120 create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
2123 void _OutputArray::create(int _rows, int _cols, int mtype, int i, bool allowTransposed, int fixedDepthMask) const
2126 if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2128 CV_Assert(!fixedSize() || ((Mat*)obj)->size.operator()() == Size(_cols, _rows));
2129 CV_Assert(!fixedType() || ((Mat*)obj)->type() == mtype);
2130 ((Mat*)obj)->create(_rows, _cols, mtype);
2133 if( k == UMAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2135 CV_Assert(!fixedSize() || ((UMat*)obj)->size.operator()() == Size(_cols, _rows));
2136 CV_Assert(!fixedType() || ((UMat*)obj)->type() == mtype);
2137 ((UMat*)obj)->create(_rows, _cols, mtype);
2140 if( k == GPU_MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2142 CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == Size(_cols, _rows));
2143 CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype);
2144 ((cuda::GpuMat*)obj)->create(_rows, _cols, mtype);
2147 if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2149 CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == Size(_cols, _rows));
2150 CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype);
2151 ((ogl::Buffer*)obj)->create(_rows, _cols, mtype);
2154 if( k == CUDA_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 )
2156 CV_Assert(!fixedSize() || ((cuda::CudaMem*)obj)->size() == Size(_cols, _rows));
2157 CV_Assert(!fixedType() || ((cuda::CudaMem*)obj)->type() == mtype);
2158 ((cuda::CudaMem*)obj)->create(_rows, _cols, mtype);
2161 int sizes[] = {_rows, _cols};
2162 create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
2165 void _OutputArray::create(int d, const int* sizes, int mtype, int i,
2166 bool allowTransposed, int fixedDepthMask) const
2169 mtype = CV_MAT_TYPE(mtype);
2174 Mat& m = *(Mat*)obj;
2175 if( allowTransposed )
2177 if( !m.isContinuous() )
2179 CV_Assert(!fixedType() && !fixedSize());
2183 if( d == 2 && m.dims == 2 && m.data &&
2184 m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
2190 if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
2193 CV_Assert(CV_MAT_TYPE(mtype) == m.type());
2197 CV_Assert(m.dims == d);
2198 for(int j = 0; j < d; ++j)
2199 CV_Assert(m.size[j] == sizes[j]);
2201 m.create(d, sizes, mtype);
2208 UMat& m = *(UMat*)obj;
2209 if( allowTransposed )
2211 if( !m.isContinuous() )
2213 CV_Assert(!fixedType() && !fixedSize());
2217 if( d == 2 && m.dims == 2 && !m.empty() &&
2218 m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
2224 if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
2227 CV_Assert(CV_MAT_TYPE(mtype) == m.type());
2231 CV_Assert(m.dims == d);
2232 for(int j = 0; j < d; ++j)
2233 CV_Assert(m.size[j] == sizes[j]);
2235 m.create(d, sizes, mtype);
2242 int type0 = CV_MAT_TYPE(flags);
2243 CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == 1 && ((1 << type0) & fixedDepthMask) != 0) );
2244 CV_Assert( d == 2 && ((sizes[0] == sz.height && sizes[1] == sz.width) ||
2245 (allowTransposed && sizes[0] == sz.width && sizes[1] == sz.height)));
2249 if( k == STD_VECTOR || k == STD_VECTOR_VECTOR )
2251 CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) );
2252 size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0;
2253 std::vector<uchar>* v = (std::vector<uchar>*)obj;
2255 if( k == STD_VECTOR_VECTOR )
2257 std::vector<std::vector<uchar> >& vv = *(std::vector<std::vector<uchar> >*)obj;
2260 CV_Assert(!fixedSize() || len == vv.size());
2264 CV_Assert( i < (int)vv.size() );
2270 int type0 = CV_MAT_TYPE(flags);
2271 CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) );
2273 int esz = CV_ELEM_SIZE(type0);
2274 CV_Assert(!fixedSize() || len == ((std::vector<uchar>*)v)->size() / esz);
2278 ((std::vector<uchar>*)v)->resize(len);
2281 ((std::vector<Vec2b>*)v)->resize(len);
2284 ((std::vector<Vec3b>*)v)->resize(len);
2287 ((std::vector<int>*)v)->resize(len);
2290 ((std::vector<Vec3s>*)v)->resize(len);
2293 ((std::vector<Vec2i>*)v)->resize(len);
2296 ((std::vector<Vec3i>*)v)->resize(len);
2299 ((std::vector<Vec4i>*)v)->resize(len);
2302 ((std::vector<Vec6i>*)v)->resize(len);
2305 ((std::vector<Vec8i>*)v)->resize(len);
2308 ((std::vector<Vec<int, 9> >*)v)->resize(len);
2311 ((std::vector<Vec<int, 12> >*)v)->resize(len);
2314 ((std::vector<Vec<int, 16> >*)v)->resize(len);
2317 ((std::vector<Vec<int, 32> >*)v)->resize(len);
2320 ((std::vector<Vec<int, 64> >*)v)->resize(len);
2323 ((std::vector<Vec<int, 128> >*)v)->resize(len);
2326 CV_Error_(CV_StsBadArg, ("Vectors with element size %d are not supported. Please, modify OutputArray::create()\n", esz));
2333 CV_Error(CV_StsNullPtr, "create() called for the missing output array" );
2337 if( k == STD_VECTOR_MAT )
2339 std::vector<Mat>& v = *(std::vector<Mat>*)obj;
2343 CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) );
2344 size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0, len0 = v.size();
2346 CV_Assert(!fixedSize() || len == len0);
2350 int _type = CV_MAT_TYPE(flags);
2351 for( size_t j = len0; j < len; j++ )
2353 if( v[j].type() == _type )
2355 CV_Assert( v[j].empty() );
2356 v[j].flags = (v[j].flags & ~CV_MAT_TYPE_MASK) | _type;
2362 CV_Assert( i < (int)v.size() );
2365 if( allowTransposed )
2367 if( !m.isContinuous() )
2369 CV_Assert(!fixedType() && !fixedSize());
2373 if( d == 2 && m.dims == 2 && m.data &&
2374 m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
2380 if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
2383 CV_Assert(CV_MAT_TYPE(mtype) == m.type());
2387 CV_Assert(m.dims == d);
2388 for(int j = 0; j < d; ++j)
2389 CV_Assert(m.size[j] == sizes[j]);
2392 m.create(d, sizes, mtype);
2396 if( k == STD_VECTOR_UMAT )
2398 std::vector<UMat>& v = *(std::vector<UMat>*)obj;
2402 CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) );
2403 size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0, len0 = v.size();
2405 CV_Assert(!fixedSize() || len == len0);
2409 int _type = CV_MAT_TYPE(flags);
2410 for( size_t j = len0; j < len; j++ )
2412 if( v[j].type() == _type )
2414 CV_Assert( v[j].empty() );
2415 v[j].flags = (v[j].flags & ~CV_MAT_TYPE_MASK) | _type;
2421 CV_Assert( i < (int)v.size() );
2424 if( allowTransposed )
2426 if( !m.isContinuous() )
2428 CV_Assert(!fixedType() && !fixedSize());
2432 if( d == 2 && m.dims == 2 && m.u &&
2433 m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
2439 if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
2442 CV_Assert(CV_MAT_TYPE(mtype) == m.type());
2446 CV_Assert(m.dims == d);
2447 for(int j = 0; j < d; ++j)
2448 CV_Assert(m.size[j] == sizes[j]);
2451 m.create(d, sizes, mtype);
2455 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
2458 void _OutputArray::createSameSize(const _InputArray& arr, int mtype) const
2460 int arrsz[CV_MAX_DIM], d = arr.sizend(arrsz);
2461 create(d, arrsz, mtype);
2464 void _OutputArray::release() const
2466 CV_Assert(!fixedSize());
2472 ((Mat*)obj)->release();
2478 ((UMat*)obj)->release();
2484 ((cuda::GpuMat*)obj)->release();
2490 ((cuda::CudaMem*)obj)->release();
2494 if( k == OPENGL_BUFFER )
2496 ((ogl::Buffer*)obj)->release();
2503 if( k == STD_VECTOR )
2505 create(Size(), CV_MAT_TYPE(flags));
2509 if( k == STD_VECTOR_VECTOR )
2511 ((std::vector<std::vector<uchar> >*)obj)->clear();
2515 if( k == STD_VECTOR_MAT )
2517 ((std::vector<Mat>*)obj)->clear();
2521 if( k == STD_VECTOR_UMAT )
2523 ((std::vector<UMat>*)obj)->clear();
2527 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
2530 void _OutputArray::clear() const
2536 CV_Assert(!fixedSize());
2537 ((Mat*)obj)->resize(0);
2544 bool _OutputArray::needed() const
2546 return kind() != NONE;
2549 Mat& _OutputArray::getMatRef(int i) const
2554 CV_Assert( k == MAT );
2559 CV_Assert( k == STD_VECTOR_MAT );
2560 std::vector<Mat>& v = *(std::vector<Mat>*)obj;
2561 CV_Assert( i < (int)v.size() );
2566 UMat& _OutputArray::getUMatRef(int i) const
2571 CV_Assert( k == UMAT );
2576 CV_Assert( k == STD_VECTOR_UMAT );
2577 std::vector<UMat>& v = *(std::vector<UMat>*)obj;
2578 CV_Assert( i < (int)v.size() );
2583 cuda::GpuMat& _OutputArray::getGpuMatRef() const
2586 CV_Assert( k == GPU_MAT );
2587 return *(cuda::GpuMat*)obj;
2590 ogl::Buffer& _OutputArray::getOGlBufferRef() const
2593 CV_Assert( k == OPENGL_BUFFER );
2594 return *(ogl::Buffer*)obj;
2597 cuda::CudaMem& _OutputArray::getCudaMemRef() const
2600 CV_Assert( k == CUDA_MEM );
2601 return *(cuda::CudaMem*)obj;
2604 void _OutputArray::setTo(const _InputArray& arr, const _InputArray & mask) const
2610 else if( k == MAT || k == MATX || k == STD_VECTOR )
2615 else if( k == UMAT )
2616 ((UMat*)obj)->setTo(arr, mask);
2617 else if( k == GPU_MAT )
2619 Mat value = arr.getMat();
2620 CV_Assert( checkScalar(value, type(), arr.kind(), _InputArray::GPU_MAT) );
2621 ((cuda::GpuMat*)obj)->setTo(Scalar(Vec<double, 4>((double *)value.data)), mask);
2624 CV_Error(Error::StsNotImplemented, "");
2628 void _OutputArray::assign(const UMat& u) const
2637 u.copyTo(*(Mat*)obj); // TODO check u.getMat()
2641 CV_Error(Error::StsNotImplemented, "");
2646 void _OutputArray::assign(const Mat& m) const
2651 m.copyTo(*(UMat*)obj); // TODO check m.getUMat()
2659 CV_Error(Error::StsNotImplemented, "");
2664 static _InputOutputArray _none;
2665 InputOutputArray noArray() { return _none; }
2669 /*************************************************************************************************\
2671 \*************************************************************************************************/
2673 void cv::hconcat(const Mat* src, size_t nsrc, OutputArray _dst)
2675 if( nsrc == 0 || !src )
2681 int totalCols = 0, cols = 0;
2683 for( i = 0; i < nsrc; i++ )
2685 CV_Assert( src[i].dims <= 2 &&
2686 src[i].rows == src[0].rows &&
2687 src[i].type() == src[0].type());
2688 totalCols += src[i].cols;
2690 _dst.create( src[0].rows, totalCols, src[0].type());
2691 Mat dst = _dst.getMat();
2692 for( i = 0; i < nsrc; i++ )
2694 Mat dpart = dst(Rect(cols, 0, src[i].cols, src[i].rows));
2695 src[i].copyTo(dpart);
2696 cols += src[i].cols;
2700 void cv::hconcat(InputArray src1, InputArray src2, OutputArray dst)
2702 Mat src[] = {src1.getMat(), src2.getMat()};
2703 hconcat(src, 2, dst);
2706 void cv::hconcat(InputArray _src, OutputArray dst)
2708 std::vector<Mat> src;
2709 _src.getMatVector(src);
2710 hconcat(!src.empty() ? &src[0] : 0, src.size(), dst);
2713 void cv::vconcat(const Mat* src, size_t nsrc, OutputArray _dst)
2715 if( nsrc == 0 || !src )
2721 int totalRows = 0, rows = 0;
2723 for( i = 0; i < nsrc; i++ )
2725 CV_Assert(src[i].dims <= 2 &&
2726 src[i].cols == src[0].cols &&
2727 src[i].type() == src[0].type());
2728 totalRows += src[i].rows;
2730 _dst.create( totalRows, src[0].cols, src[0].type());
2731 Mat dst = _dst.getMat();
2732 for( i = 0; i < nsrc; i++ )
2734 Mat dpart(dst, Rect(0, rows, src[i].cols, src[i].rows));
2735 src[i].copyTo(dpart);
2736 rows += src[i].rows;
2740 void cv::vconcat(InputArray src1, InputArray src2, OutputArray dst)
2742 Mat src[] = {src1.getMat(), src2.getMat()};
2743 vconcat(src, 2, dst);
2746 void cv::vconcat(InputArray _src, OutputArray dst)
2748 std::vector<Mat> src;
2749 _src.getMatVector(src);
2750 vconcat(!src.empty() ? &src[0] : 0, src.size(), dst);
2753 //////////////////////////////////////// set identity ////////////////////////////////////////////
2759 static bool ocl_setIdentity( InputOutputArray _m, const Scalar& s )
2761 int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), kercn = cn;
2764 kercn = std::min(ocl::predictOptimalVectorWidth(_m), 4);
2768 int sctype = CV_MAKE_TYPE(depth, cn == 3 ? 4 : cn),
2769 rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1;
2771 ocl::Kernel k("setIdentity", ocl::core::set_identity_oclsrc,
2772 format("-D T=%s -D T1=%s -D cn=%d -D ST=%s -D kercn=%d -D rowsPerWI=%d",
2773 ocl::memopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
2774 ocl::memopTypeToStr(depth), cn,
2775 ocl::memopTypeToStr(sctype),
2780 UMat m = _m.getUMat();
2781 k.args(ocl::KernelArg::WriteOnly(m, cn, kercn),
2782 ocl::KernelArg::Constant(Mat(1, 1, sctype, s)));
2784 size_t globalsize[2] = { m.cols * cn / kercn, (m.rows + rowsPerWI - 1) / rowsPerWI };
2785 return k.run(2, globalsize, NULL, false);
2792 void cv::setIdentity( InputOutputArray _m, const Scalar& s )
2794 CV_Assert( _m.dims() <= 2 );
2796 CV_OCL_RUN(_m.isUMat(),
2797 ocl_setIdentity(_m, s))
2799 Mat m = _m.getMat();
2800 int i, j, rows = m.rows, cols = m.cols, type = m.type();
2802 if( type == CV_32FC1 )
2804 float* data = (float*)m.data;
2805 float val = (float)s[0];
2806 size_t step = m.step/sizeof(data[0]);
2808 for( i = 0; i < rows; i++, data += step )
2810 for( j = 0; j < cols; j++ )
2816 else if( type == CV_64FC1 )
2818 double* data = (double*)m.data;
2820 size_t step = m.step/sizeof(data[0]);
2822 for( i = 0; i < rows; i++, data += step )
2824 for( j = 0; j < cols; j++ )
2825 data[j] = j == i ? val : 0;
2835 //////////////////////////////////////////// trace ///////////////////////////////////////////
2837 cv::Scalar cv::trace( InputArray _m )
2839 Mat m = _m.getMat();
2840 CV_Assert( m.dims <= 2 );
2841 int i, type = m.type();
2842 int nm = std::min(m.rows, m.cols);
2844 if( type == CV_32FC1 )
2846 const float* ptr = (const float*)m.data;
2847 size_t step = m.step/sizeof(ptr[0]) + 1;
2849 for( i = 0; i < nm; i++ )
2854 if( type == CV_64FC1 )
2856 const double* ptr = (const double*)m.data;
2857 size_t step = m.step/sizeof(ptr[0]) + 1;
2859 for( i = 0; i < nm; i++ )
2864 return cv::sum(m.diag());
2867 ////////////////////////////////////// transpose /////////////////////////////////////////
2872 template<typename T> static void
2873 transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz )
2875 int i=0, j, m = sz.width, n = sz.height;
2877 #if CV_ENABLE_UNROLLED
2878 for(; i <= m - 4; i += 4 )
2880 T* d0 = (T*)(dst + dstep*i);
2881 T* d1 = (T*)(dst + dstep*(i+1));
2882 T* d2 = (T*)(dst + dstep*(i+2));
2883 T* d3 = (T*)(dst + dstep*(i+3));
2885 for( j = 0; j <= n - 4; j += 4 )
2887 const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
2888 const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
2889 const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
2890 const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
2892 d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
2893 d1[j] = s0[1]; d1[j+1] = s1[1]; d1[j+2] = s2[1]; d1[j+3] = s3[1];
2894 d2[j] = s0[2]; d2[j+1] = s1[2]; d2[j+2] = s2[2]; d2[j+3] = s3[2];
2895 d3[j] = s0[3]; d3[j+1] = s1[3]; d3[j+2] = s2[3]; d3[j+3] = s3[3];
2900 const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
2901 d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3];
2907 T* d0 = (T*)(dst + dstep*i);
2909 #if CV_ENABLE_UNROLLED
2910 for(; j <= n - 4; j += 4 )
2912 const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
2913 const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
2914 const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
2915 const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
2917 d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
2922 const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
2928 template<typename T> static void
2929 transposeI_( uchar* data, size_t step, int n )
2932 for( i = 0; i < n; i++ )
2934 T* row = (T*)(data + step*i);
2935 uchar* data1 = data + i*sizeof(T);
2936 for( j = i+1; j < n; j++ )
2937 std::swap( row[j], *(T*)(data1 + step*j) );
2941 typedef void (*TransposeFunc)( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz );
2942 typedef void (*TransposeInplaceFunc)( uchar* data, size_t step, int n );
2944 #define DEF_TRANSPOSE_FUNC(suffix, type) \
2945 static void transpose_##suffix( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) \
2946 { transpose_<type>(src, sstep, dst, dstep, sz); } \
2948 static void transposeI_##suffix( uchar* data, size_t step, int n ) \
2949 { transposeI_<type>(data, step, n); }
2951 DEF_TRANSPOSE_FUNC(8u, uchar)
2952 DEF_TRANSPOSE_FUNC(16u, ushort)
2953 DEF_TRANSPOSE_FUNC(8uC3, Vec3b)
2954 DEF_TRANSPOSE_FUNC(32s, int)
2955 DEF_TRANSPOSE_FUNC(16uC3, Vec3s)
2956 DEF_TRANSPOSE_FUNC(32sC2, Vec2i)
2957 DEF_TRANSPOSE_FUNC(32sC3, Vec3i)
2958 DEF_TRANSPOSE_FUNC(32sC4, Vec4i)
2959 DEF_TRANSPOSE_FUNC(32sC6, Vec6i)
2960 DEF_TRANSPOSE_FUNC(32sC8, Vec8i)
2962 static TransposeFunc transposeTab[] =
2964 0, transpose_8u, transpose_16u, transpose_8uC3, transpose_32s, 0, transpose_16uC3, 0,
2965 transpose_32sC2, 0, 0, 0, transpose_32sC3, 0, 0, 0, transpose_32sC4,
2966 0, 0, 0, 0, 0, 0, 0, transpose_32sC6, 0, 0, 0, 0, 0, 0, 0, transpose_32sC8
2969 static TransposeInplaceFunc transposeInplaceTab[] =
2971 0, transposeI_8u, transposeI_16u, transposeI_8uC3, transposeI_32s, 0, transposeI_16uC3, 0,
2972 transposeI_32sC2, 0, 0, 0, transposeI_32sC3, 0, 0, 0, transposeI_32sC4,
2973 0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8
2978 static inline int divUp(int a, int b)
2980 return (a + b - 1) / b;
2983 static bool ocl_transpose( InputArray _src, OutputArray _dst )
2985 const ocl::Device & dev = ocl::Device::getDefault();
2986 const int TILE_DIM = 32, BLOCK_ROWS = 8;
2987 int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
2988 rowsPerWI = dev.isIntel() ? 4 : 1;
2990 UMat src = _src.getUMat();
2991 _dst.create(src.cols, src.rows, type);
2992 UMat dst = _dst.getUMat();
2994 String kernelName("transpose");
2995 bool inplace = dst.u == src.u;
2999 CV_Assert(dst.cols == dst.rows);
3000 kernelName += "_inplace";
3003 ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc,
3004 format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d",
3005 ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth),
3006 cn, TILE_DIM, BLOCK_ROWS, rowsPerWI));
3011 k.args(ocl::KernelArg::ReadWriteNoSize(dst), dst.rows);
3013 k.args(ocl::KernelArg::ReadOnly(src),
3014 ocl::KernelArg::WriteOnlyNoSize(dst));
3016 size_t localsize[2] = { TILE_DIM, BLOCK_ROWS };
3017 size_t globalsize[2] = { src.cols, inplace ? (src.rows + rowsPerWI - 1) / rowsPerWI : (divUp(src.rows, TILE_DIM) * BLOCK_ROWS) };
3019 if (inplace && dev.isIntel())
3022 localsize[1] = dev.maxWorkGroupSize() / localsize[0];
3025 return k.run(2, globalsize, localsize, false);
3032 void cv::transpose( InputArray _src, OutputArray _dst )
3034 int type = _src.type(), esz = CV_ELEM_SIZE(type);
3035 CV_Assert( _src.dims() <= 2 && esz <= 32 );
3037 CV_OCL_RUN(_dst.isUMat(),
3038 ocl_transpose(_src, _dst))
3040 Mat src = _src.getMat();
3047 _dst.create(src.cols, src.rows, src.type());
3048 Mat dst = _dst.getMat();
3050 // handle the case of single-column/single-row matrices, stored in STL vectors.
3051 if( src.rows != dst.cols || src.cols != dst.rows )
3053 CV_Assert( src.size() == dst.size() && (src.cols == 1 || src.rows == 1) );
3058 #if defined HAVE_IPP
3059 typedef IppStatus (CV_STDCALL * ippiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize);
3060 typedef IppStatus (CV_STDCALL * ippiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize);
3061 ippiTranspose ippFunc = 0;
3062 ippiTransposeI ippFuncI = 0;
3064 if (dst.data == src.data && dst.cols == dst.rows)
3066 CV_SUPPRESS_DEPRECATED_START
3068 type == CV_8UC1 ? (ippiTransposeI)ippiTranspose_8u_C1IR :
3069 type == CV_8UC3 ? (ippiTransposeI)ippiTranspose_8u_C3IR :
3070 type == CV_8UC4 ? (ippiTransposeI)ippiTranspose_8u_C4IR :
3071 type == CV_16UC1 ? (ippiTransposeI)ippiTranspose_16u_C1IR :
3072 type == CV_16UC3 ? (ippiTransposeI)ippiTranspose_16u_C3IR :
3073 type == CV_16UC4 ? (ippiTransposeI)ippiTranspose_16u_C4IR :
3074 type == CV_16SC1 ? (ippiTransposeI)ippiTranspose_16s_C1IR :
3075 type == CV_16SC3 ? (ippiTransposeI)ippiTranspose_16s_C3IR :
3076 type == CV_16SC4 ? (ippiTransposeI)ippiTranspose_16s_C4IR :
3077 type == CV_32SC1 ? (ippiTransposeI)ippiTranspose_32s_C1IR :
3078 type == CV_32SC3 ? (ippiTransposeI)ippiTranspose_32s_C3IR :
3079 type == CV_32SC4 ? (ippiTransposeI)ippiTranspose_32s_C4IR :
3080 type == CV_32FC1 ? (ippiTransposeI)ippiTranspose_32f_C1IR :
3081 type == CV_32FC3 ? (ippiTransposeI)ippiTranspose_32f_C3IR :
3082 type == CV_32FC4 ? (ippiTransposeI)ippiTranspose_32f_C4IR : 0;
3083 CV_SUPPRESS_DEPRECATED_END
3088 type == CV_8UC1 ? (ippiTranspose)ippiTranspose_8u_C1R :
3089 type == CV_8UC3 ? (ippiTranspose)ippiTranspose_8u_C3R :
3090 type == CV_8UC4 ? (ippiTranspose)ippiTranspose_8u_C4R :
3091 type == CV_16UC1 ? (ippiTranspose)ippiTranspose_16u_C1R :
3092 type == CV_16UC3 ? (ippiTranspose)ippiTranspose_16u_C3R :
3093 type == CV_16UC4 ? (ippiTranspose)ippiTranspose_16u_C4R :
3094 type == CV_16SC1 ? (ippiTranspose)ippiTranspose_16s_C1R :
3095 type == CV_16SC3 ? (ippiTranspose)ippiTranspose_16s_C3R :
3096 type == CV_16SC4 ? (ippiTranspose)ippiTranspose_16s_C4R :
3097 type == CV_32SC1 ? (ippiTranspose)ippiTranspose_32s_C1R :
3098 type == CV_32SC3 ? (ippiTranspose)ippiTranspose_32s_C3R :
3099 type == CV_32SC4 ? (ippiTranspose)ippiTranspose_32s_C4R :
3100 type == CV_32FC1 ? (ippiTranspose)ippiTranspose_32f_C1R :
3101 type == CV_32FC3 ? (ippiTranspose)ippiTranspose_32f_C3R :
3102 type == CV_32FC4 ? (ippiTranspose)ippiTranspose_32f_C4R : 0;
3105 IppiSize roiSize = { src.cols, src.rows };
3108 if (ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, roiSize) >= 0)
3110 setIppErrorStatus();
3112 else if (ippFuncI != 0)
3114 if (ippFuncI(dst.data, (int)dst.step, roiSize) >= 0)
3116 setIppErrorStatus();
3120 if( dst.data == src.data )
3122 TransposeInplaceFunc func = transposeInplaceTab[esz];
3123 CV_Assert( func != 0 );
3124 CV_Assert( dst.cols == dst.rows );
3125 func( dst.data, dst.step, dst.rows );
3129 TransposeFunc func = transposeTab[esz];
3130 CV_Assert( func != 0 );
3131 func( src.data, src.step, dst.data, dst.step, src.size() );
3136 ////////////////////////////////////// completeSymm /////////////////////////////////////////
3138 void cv::completeSymm( InputOutputArray _m, bool LtoR )
3140 Mat m = _m.getMat();
3141 size_t step = m.step, esz = m.elemSize();
3142 CV_Assert( m.dims <= 2 && m.rows == m.cols );
3145 int j0 = 0, j1 = rows;
3147 uchar* data = m.data;
3148 for( int i = 0; i < rows; i++ )
3150 if( !LtoR ) j1 = i; else j0 = i+1;
3151 for( int j = j0; j < j1; j++ )
3152 memcpy(data + (i*step + j*esz), data + (j*step + i*esz), esz);
3157 cv::Mat cv::Mat::cross(InputArray _m) const
3159 Mat m = _m.getMat();
3160 int tp = type(), d = CV_MAT_DEPTH(tp);
3161 CV_Assert( dims <= 2 && m.dims <= 2 && size() == m.size() && tp == m.type() &&
3162 ((rows == 3 && cols == 1) || (cols*channels() == 3 && rows == 1)));
3163 Mat result(rows, cols, tp);
3167 const float *a = (const float*)data, *b = (const float*)m.data;
3168 float* c = (float*)result.data;
3169 size_t lda = rows > 1 ? step/sizeof(a[0]) : 1;
3170 size_t ldb = rows > 1 ? m.step/sizeof(b[0]) : 1;
3172 c[0] = a[lda] * b[ldb*2] - a[lda*2] * b[ldb];
3173 c[1] = a[lda*2] * b[0] - a[0] * b[ldb*2];
3174 c[2] = a[0] * b[ldb] - a[lda] * b[0];
3176 else if( d == CV_64F )
3178 const double *a = (const double*)data, *b = (const double*)m.data;
3179 double* c = (double*)result.data;
3180 size_t lda = rows > 1 ? step/sizeof(a[0]) : 1;
3181 size_t ldb = rows > 1 ? m.step/sizeof(b[0]) : 1;
3183 c[0] = a[lda] * b[ldb*2] - a[lda*2] * b[ldb];
3184 c[1] = a[lda*2] * b[0] - a[0] * b[ldb*2];
3185 c[2] = a[0] * b[ldb] - a[lda] * b[0];
3192 ////////////////////////////////////////// reduce ////////////////////////////////////////////
3197 template<typename T, typename ST, class Op> static void
3198 reduceR_( const Mat& srcmat, Mat& dstmat )
3200 typedef typename Op::rtype WT;
3201 Size size = srcmat.size();
3202 size.width *= srcmat.channels();
3203 AutoBuffer<WT> buffer(size.width);
3205 ST* dst = (ST*)dstmat.data;
3206 const T* src = (const T*)srcmat.data;
3207 size_t srcstep = srcmat.step/sizeof(src[0]);
3211 for( i = 0; i < size.width; i++ )
3214 for( ; --size.height; )
3218 #if CV_ENABLE_UNROLLED
3219 for(; i <= size.width - 4; i += 4 )
3222 s0 = op(buf[i], (WT)src[i]);
3223 s1 = op(buf[i+1], (WT)src[i+1]);
3224 buf[i] = s0; buf[i+1] = s1;
3226 s0 = op(buf[i+2], (WT)src[i+2]);
3227 s1 = op(buf[i+3], (WT)src[i+3]);
3228 buf[i+2] = s0; buf[i+3] = s1;
3231 for( ; i < size.width; i++ )
3232 buf[i] = op(buf[i], (WT)src[i]);
3235 for( i = 0; i < size.width; i++ )
3236 dst[i] = (ST)buf[i];
3240 template<typename T, typename ST, class Op> static void
3241 reduceC_( const Mat& srcmat, Mat& dstmat )
3243 typedef typename Op::rtype WT;
3244 Size size = srcmat.size();
3245 int i, k, cn = srcmat.channels();
3249 for( int y = 0; y < size.height; y++ )
3251 const T* src = (const T*)(srcmat.data + srcmat.step*y);
3252 ST* dst = (ST*)(dstmat.data + dstmat.step*y);
3253 if( size.width == cn )
3254 for( k = 0; k < cn; k++ )
3258 for( k = 0; k < cn; k++ )
3260 WT a0 = src[k], a1 = src[k+cn];
3261 for( i = 2*cn; i <= size.width - 4*cn; i += 4*cn )
3263 a0 = op(a0, (WT)src[i+k]);
3264 a1 = op(a1, (WT)src[i+k+cn]);
3265 a0 = op(a0, (WT)src[i+k+cn*2]);
3266 a1 = op(a1, (WT)src[i+k+cn*3]);
3269 for( ; i < size.width; i += cn )
3271 a0 = op(a0, (WT)src[i+k]);
3280 typedef void (*ReduceFunc)( const Mat& src, Mat& dst );
3284 #define reduceSumR8u32s reduceR_<uchar, int, OpAdd<int> >
3285 #define reduceSumR8u32f reduceR_<uchar, float, OpAdd<int> >
3286 #define reduceSumR8u64f reduceR_<uchar, double,OpAdd<int> >
3287 #define reduceSumR16u32f reduceR_<ushort,float, OpAdd<float> >
3288 #define reduceSumR16u64f reduceR_<ushort,double,OpAdd<double> >
3289 #define reduceSumR16s32f reduceR_<short, float, OpAdd<float> >
3290 #define reduceSumR16s64f reduceR_<short, double,OpAdd<double> >
3291 #define reduceSumR32f32f reduceR_<float, float, OpAdd<float> >
3292 #define reduceSumR32f64f reduceR_<float, double,OpAdd<double> >
3293 #define reduceSumR64f64f reduceR_<double,double,OpAdd<double> >
3295 #define reduceMaxR8u reduceR_<uchar, uchar, OpMax<uchar> >
3296 #define reduceMaxR16u reduceR_<ushort,ushort,OpMax<ushort> >
3297 #define reduceMaxR16s reduceR_<short, short, OpMax<short> >
3298 #define reduceMaxR32f reduceR_<float, float, OpMax<float> >
3299 #define reduceMaxR64f reduceR_<double,double,OpMax<double> >
3301 #define reduceMinR8u reduceR_<uchar, uchar, OpMin<uchar> >
3302 #define reduceMinR16u reduceR_<ushort,ushort,OpMin<ushort> >
3303 #define reduceMinR16s reduceR_<short, short, OpMin<short> >
3304 #define reduceMinR32f reduceR_<float, float, OpMin<float> >
3305 #define reduceMinR64f reduceR_<double,double,OpMin<double> >
3307 #if IPP_VERSION_X100 > 0
3309 static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat)
3311 cv::Size size = srcmat.size();
3312 IppiSize roisize = { size.width, 1 };
3313 int sstep = (int)srcmat.step, stype = srcmat.type(),
3314 sdepth = CV_MAT_DEPTH(stype), ddepth = dstmat.depth();
3316 typedef IppStatus (CV_STDCALL * ippiSum)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum);
3317 typedef IppStatus (CV_STDCALL * ippiSumHint)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum, IppHintAlgorithm hint);
3318 ippiSum ippFunc = 0;
3319 ippiSumHint ippFuncHint = 0;
3320 cv::ReduceFunc func = 0;
3322 if (ddepth == CV_64F)
3325 stype == CV_8UC1 ? (ippiSum)ippiSum_8u_C1R :
3326 stype == CV_8UC3 ? (ippiSum)ippiSum_8u_C3R :
3327 stype == CV_8UC4 ? (ippiSum)ippiSum_8u_C4R :
3328 stype == CV_16UC1 ? (ippiSum)ippiSum_16u_C1R :
3329 stype == CV_16UC3 ? (ippiSum)ippiSum_16u_C3R :
3330 stype == CV_16UC4 ? (ippiSum)ippiSum_16u_C4R :
3331 stype == CV_16SC1 ? (ippiSum)ippiSum_16s_C1R :
3332 stype == CV_16SC3 ? (ippiSum)ippiSum_16s_C3R :
3333 stype == CV_16SC4 ? (ippiSum)ippiSum_16s_C4R : 0;
3335 stype == CV_32FC1 ? (ippiSumHint)ippiSum_32f_C1R :
3336 stype == CV_32FC3 ? (ippiSumHint)ippiSum_32f_C3R :
3337 stype == CV_32FC4 ? (ippiSumHint)ippiSum_32f_C4R : 0;
3339 sdepth == CV_8U ? (cv::ReduceFunc)cv::reduceC_<uchar, double, cv::OpAdd<double> > :
3340 sdepth == CV_16U ? (cv::ReduceFunc)cv::reduceC_<ushort, double, cv::OpAdd<double> > :
3341 sdepth == CV_16S ? (cv::ReduceFunc)cv::reduceC_<short, double, cv::OpAdd<double> > :
3342 sdepth == CV_32F ? (cv::ReduceFunc)cv::reduceC_<float, double, cv::OpAdd<double> > : 0;
3344 CV_Assert(!(ippFunc && ippFuncHint) && func);
3348 for (int y = 0; y < size.height; ++y)
3349 if (ippFunc(srcmat.data + sstep * y, sstep, roisize, dstmat.ptr<Ipp64f>(y)) < 0)
3351 setIppErrorStatus();
3352 cv::Mat dstroi = dstmat.rowRange(y, y + 1);
3353 func(srcmat.rowRange(y, y + 1), dstroi);
3357 else if (ippFuncHint)
3359 for (int y = 0; y < size.height; ++y)
3360 if (ippFuncHint(srcmat.data + sstep * y, sstep, roisize, dstmat.ptr<Ipp64f>(y), ippAlgHintAccurate) < 0)
3362 setIppErrorStatus();
3363 cv::Mat dstroi = dstmat.rowRange(y, y + 1);
3364 func(srcmat.rowRange(y, y + 1), dstroi);
3369 func(srcmat, dstmat);
3374 #define reduceSumC8u32s reduceC_<uchar, int, OpAdd<int> >
3375 #define reduceSumC8u32f reduceC_<uchar, float, OpAdd<int> >
3376 #define reduceSumC16u32f reduceC_<ushort,float, OpAdd<float> >
3377 #define reduceSumC16s32f reduceC_<short, float, OpAdd<float> >
3378 #define reduceSumC32f32f reduceC_<float, float, OpAdd<float> >
3379 #define reduceSumC64f64f reduceC_<double,double,OpAdd<double> >
3381 #if IPP_VERSION_X100 > 0
3382 #define reduceSumC8u64f reduceSumC_8u16u16s32f_64f
3383 #define reduceSumC16u64f reduceSumC_8u16u16s32f_64f
3384 #define reduceSumC16s64f reduceSumC_8u16u16s32f_64f
3385 #define reduceSumC32f64f reduceSumC_8u16u16s32f_64f
3387 #define reduceSumC8u64f reduceC_<uchar, double,OpAdd<int> >
3388 #define reduceSumC16u64f reduceC_<ushort,double,OpAdd<double> >
3389 #define reduceSumC16s64f reduceC_<short, double,OpAdd<double> >
3390 #define reduceSumC32f64f reduceC_<float, double,OpAdd<double> >
3393 #if IPP_VERSION_X100 > 0
3394 #define REDUCE_OP(favor, optype, type1, type2) \
3395 static inline void reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \
3397 typedef Ipp##favor IppType; \
3398 cv::Size size = srcmat.size(); \
3399 IppiSize roisize = ippiSize(size.width, 1);\
3400 int sstep = (int)srcmat.step; \
3402 if (srcmat.channels() == 1) \
3404 for (int y = 0; y < size.height; ++y) \
3405 if (ippi##optype##_##favor##_C1R(srcmat.ptr<IppType>(y), sstep, roisize, dstmat.ptr<IppType>(y)) < 0) \
3407 setIppErrorStatus(); \
3408 cv::Mat dstroi = dstmat.rowRange(y, y + 1); \
3409 cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat.rowRange(y, y + 1), dstroi); \
3413 cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat, dstmat); \
3417 #if IPP_VERSION_X100 > 0
3418 REDUCE_OP(8u, Max, uchar, uchar)
3419 REDUCE_OP(16u, Max, ushort, ushort)
3420 REDUCE_OP(16s, Max, short, short)
3421 REDUCE_OP(32f, Max, float, float)
3423 #define reduceMaxC8u reduceC_<uchar, uchar, OpMax<uchar> >
3424 #define reduceMaxC16u reduceC_<ushort,ushort,OpMax<ushort> >
3425 #define reduceMaxC16s reduceC_<short, short, OpMax<short> >
3426 #define reduceMaxC32f reduceC_<float, float, OpMax<float> >
3428 #define reduceMaxC64f reduceC_<double,double,OpMax<double> >
3430 #if IPP_VERSION_X100 > 0
3431 REDUCE_OP(8u, Min, uchar, uchar)
3432 REDUCE_OP(16u, Min, ushort, ushort)
3433 REDUCE_OP(16s, Min, short, short)
3434 REDUCE_OP(32f, Min, float, float)
3436 #define reduceMinC8u reduceC_<uchar, uchar, OpMin<uchar> >
3437 #define reduceMinC16u reduceC_<ushort,ushort,OpMin<ushort> >
3438 #define reduceMinC16s reduceC_<short, short, OpMin<short> >
3439 #define reduceMinC32f reduceC_<float, float, OpMin<float> >
3441 #define reduceMinC64f reduceC_<double,double,OpMin<double> >
3447 static bool ocl_reduce(InputArray _src, OutputArray _dst,
3448 int dim, int op, int op0, int stype, int dtype)
3450 const int min_opt_cols = 128, buf_cols = 32;
3451 int sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype),
3452 ddepth = CV_MAT_DEPTH(dtype), ddepth0 = ddepth;
3453 const ocl::Device &defDev = ocl::Device::getDefault();
3454 bool doubleSupport = defDev.doubleFPConfig() > 0;
3456 size_t wgs = defDev.maxWorkGroupSize();
3457 bool useOptimized = 1 == dim && _src.cols() > min_opt_cols && (wgs >= buf_cols);
3459 if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F))
3462 if ((op == CV_REDUCE_SUM && sdepth == CV_32F) || op == CV_REDUCE_MIN || op == CV_REDUCE_MAX)
3465 if (op == CV_REDUCE_AVG)
3467 if (sdepth < CV_32S && ddepth < CV_32S)
3471 const char * const ops[4] = { "OCL_CV_REDUCE_SUM", "OCL_CV_REDUCE_AVG",
3472 "OCL_CV_REDUCE_MAX", "OCL_CV_REDUCE_MIN" };
3473 int wdepth = std::max(ddepth, CV_32F);
3476 size_t tileHeight = (size_t)(wgs / buf_cols);
3477 if (defDev.isIntel())
3479 static const size_t maxItemInGroupCount = 16;
3480 tileHeight = min(tileHeight, defDev.localMemSize() / buf_cols / CV_ELEM_SIZE(CV_MAKETYPE(wdepth, cn)) / maxItemInGroupCount);
3483 cv::String build_opt = format("-D OP_REDUCE_PRE -D BUF_COLS=%d -D TILE_HEIGHT=%d -D %s -D dim=1"
3484 " -D cn=%d -D ddepth=%d"
3485 " -D srcT=%s -D bufT=%s -D dstT=%s"
3486 " -D convertToWT=%s -D convertToBufT=%s -D convertToDT=%s%s",
3487 buf_cols, tileHeight, ops[op], cn, ddepth,
3488 ocl::typeToStr(sdepth),
3489 ocl::typeToStr(ddepth),
3490 ocl::typeToStr(ddepth0),
3491 ocl::convertTypeStr(ddepth, wdepth, 1, cvt[0]),
3492 ocl::convertTypeStr(sdepth, ddepth, 1, cvt[1]),
3493 ocl::convertTypeStr(wdepth, ddepth0, 1, cvt[2]),
3494 doubleSupport ? " -D DOUBLE_SUPPORT" : "");
3495 ocl::Kernel k("reduce_horz_opt", ocl::core::reduce2_oclsrc, build_opt);
3498 UMat src = _src.getUMat();
3499 Size dsize(1, src.rows);
3500 _dst.create(dsize, dtype);
3501 UMat dst = _dst.getUMat();
3503 if (op0 == CV_REDUCE_AVG)
3504 k.args(ocl::KernelArg::ReadOnly(src),
3505 ocl::KernelArg::WriteOnlyNoSize(dst), 1.0f / src.cols);
3507 k.args(ocl::KernelArg::ReadOnly(src),
3508 ocl::KernelArg::WriteOnlyNoSize(dst));
3510 size_t localSize[2] = { buf_cols, tileHeight};
3511 size_t globalSize[2] = { buf_cols, src.rows };
3512 return k.run(2, globalSize, localSize, false);
3517 cv::String build_opt = format("-D %s -D dim=%d -D cn=%d -D ddepth=%d"
3518 " -D srcT=%s -D dstT=%s -D dstT0=%s -D convertToWT=%s"
3519 " -D convertToDT=%s -D convertToDT0=%s%s",
3520 ops[op], dim, cn, ddepth, ocl::typeToStr(useOptimized ? ddepth : sdepth),
3521 ocl::typeToStr(ddepth), ocl::typeToStr(ddepth0),
3522 ocl::convertTypeStr(ddepth, wdepth, 1, cvt[0]),
3523 ocl::convertTypeStr(sdepth, ddepth, 1, cvt[0]),
3524 ocl::convertTypeStr(wdepth, ddepth0, 1, cvt[1]),
3525 doubleSupport ? " -D DOUBLE_SUPPORT" : "");
3527 ocl::Kernel k("reduce", ocl::core::reduce2_oclsrc, build_opt);
3531 UMat src = _src.getUMat();
3532 Size dsize(dim == 0 ? src.cols : 1, dim == 0 ? 1 : src.rows);
3533 _dst.create(dsize, dtype);
3534 UMat dst = _dst.getUMat();
3536 ocl::KernelArg srcarg = ocl::KernelArg::ReadOnly(src),
3537 temparg = ocl::KernelArg::WriteOnlyNoSize(dst);
3539 if (op0 == CV_REDUCE_AVG)
3540 k.args(srcarg, temparg, 1.0f / (dim == 0 ? src.rows : src.cols));
3542 k.args(srcarg, temparg);
3544 size_t globalsize = std::max(dsize.width, dsize.height);
3545 return k.run(1, &globalsize, NULL, false);
3553 void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype)
3555 CV_Assert( _src.dims() <= 2 );
3557 int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
3559 dtype = _dst.fixedType() ? _dst.type() : stype;
3560 dtype = CV_MAKETYPE(dtype >= 0 ? dtype : stype, cn);
3561 int ddepth = CV_MAT_DEPTH(dtype);
3563 CV_Assert( cn == CV_MAT_CN(dtype) );
3564 CV_Assert( op == CV_REDUCE_SUM || op == CV_REDUCE_MAX ||
3565 op == CV_REDUCE_MIN || op == CV_REDUCE_AVG );
3567 CV_OCL_RUN(_dst.isUMat(),
3568 ocl_reduce(_src, _dst, dim, op, op0, stype, dtype))
3570 Mat src = _src.getMat();
3571 _dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1, dtype);
3572 Mat dst = _dst.getMat(), temp = dst;
3574 if( op == CV_REDUCE_AVG )
3577 if( sdepth < CV_32S && ddepth < CV_32S )
3579 temp.create(dst.rows, dst.cols, CV_32SC(cn));
3584 ReduceFunc func = 0;
3587 if( op == CV_REDUCE_SUM )
3589 if(sdepth == CV_8U && ddepth == CV_32S)
3590 func = GET_OPTIMIZED(reduceSumR8u32s);
3591 else if(sdepth == CV_8U && ddepth == CV_32F)
3592 func = reduceSumR8u32f;
3593 else if(sdepth == CV_8U && ddepth == CV_64F)
3594 func = reduceSumR8u64f;
3595 else if(sdepth == CV_16U && ddepth == CV_32F)
3596 func = reduceSumR16u32f;
3597 else if(sdepth == CV_16U && ddepth == CV_64F)
3598 func = reduceSumR16u64f;
3599 else if(sdepth == CV_16S && ddepth == CV_32F)
3600 func = reduceSumR16s32f;
3601 else if(sdepth == CV_16S && ddepth == CV_64F)
3602 func = reduceSumR16s64f;
3603 else if(sdepth == CV_32F && ddepth == CV_32F)
3604 func = GET_OPTIMIZED(reduceSumR32f32f);
3605 else if(sdepth == CV_32F && ddepth == CV_64F)
3606 func = reduceSumR32f64f;
3607 else if(sdepth == CV_64F && ddepth == CV_64F)
3608 func = reduceSumR64f64f;
3610 else if(op == CV_REDUCE_MAX)
3612 if(sdepth == CV_8U && ddepth == CV_8U)
3613 func = GET_OPTIMIZED(reduceMaxR8u);
3614 else if(sdepth == CV_16U && ddepth == CV_16U)
3615 func = reduceMaxR16u;
3616 else if(sdepth == CV_16S && ddepth == CV_16S)
3617 func = reduceMaxR16s;
3618 else if(sdepth == CV_32F && ddepth == CV_32F)
3619 func = GET_OPTIMIZED(reduceMaxR32f);
3620 else if(sdepth == CV_64F && ddepth == CV_64F)
3621 func = reduceMaxR64f;
3623 else if(op == CV_REDUCE_MIN)
3625 if(sdepth == CV_8U && ddepth == CV_8U)
3626 func = GET_OPTIMIZED(reduceMinR8u);
3627 else if(sdepth == CV_16U && ddepth == CV_16U)
3628 func = reduceMinR16u;
3629 else if(sdepth == CV_16S && ddepth == CV_16S)
3630 func = reduceMinR16s;
3631 else if(sdepth == CV_32F && ddepth == CV_32F)
3632 func = GET_OPTIMIZED(reduceMinR32f);
3633 else if(sdepth == CV_64F && ddepth == CV_64F)
3634 func = reduceMinR64f;
3639 if(op == CV_REDUCE_SUM)
3641 if(sdepth == CV_8U && ddepth == CV_32S)
3642 func = GET_OPTIMIZED(reduceSumC8u32s);
3643 else if(sdepth == CV_8U && ddepth == CV_32F)
3644 func = reduceSumC8u32f;
3645 else if(sdepth == CV_8U && ddepth == CV_64F)
3646 func = reduceSumC8u64f;
3647 else if(sdepth == CV_16U && ddepth == CV_32F)
3648 func = reduceSumC16u32f;
3649 else if(sdepth == CV_16U && ddepth == CV_64F)
3650 func = reduceSumC16u64f;
3651 else if(sdepth == CV_16S && ddepth == CV_32F)
3652 func = reduceSumC16s32f;
3653 else if(sdepth == CV_16S && ddepth == CV_64F)
3654 func = reduceSumC16s64f;
3655 else if(sdepth == CV_32F && ddepth == CV_32F)
3656 func = GET_OPTIMIZED(reduceSumC32f32f);
3657 else if(sdepth == CV_32F && ddepth == CV_64F)
3658 func = reduceSumC32f64f;
3659 else if(sdepth == CV_64F && ddepth == CV_64F)
3660 func = reduceSumC64f64f;
3662 else if(op == CV_REDUCE_MAX)
3664 if(sdepth == CV_8U && ddepth == CV_8U)
3665 func = GET_OPTIMIZED(reduceMaxC8u);
3666 else if(sdepth == CV_16U && ddepth == CV_16U)
3667 func = reduceMaxC16u;
3668 else if(sdepth == CV_16S && ddepth == CV_16S)
3669 func = reduceMaxC16s;
3670 else if(sdepth == CV_32F && ddepth == CV_32F)
3671 func = GET_OPTIMIZED(reduceMaxC32f);
3672 else if(sdepth == CV_64F && ddepth == CV_64F)
3673 func = reduceMaxC64f;
3675 else if(op == CV_REDUCE_MIN)
3677 if(sdepth == CV_8U && ddepth == CV_8U)
3678 func = GET_OPTIMIZED(reduceMinC8u);
3679 else if(sdepth == CV_16U && ddepth == CV_16U)
3680 func = reduceMinC16u;
3681 else if(sdepth == CV_16S && ddepth == CV_16S)
3682 func = reduceMinC16s;
3683 else if(sdepth == CV_32F && ddepth == CV_32F)
3684 func = GET_OPTIMIZED(reduceMinC32f);
3685 else if(sdepth == CV_64F && ddepth == CV_64F)
3686 func = reduceMinC64f;
3691 CV_Error( CV_StsUnsupportedFormat,
3692 "Unsupported combination of input and output array formats" );
3696 if( op0 == CV_REDUCE_AVG )
3697 temp.convertTo(dst, dst.type(), 1./(dim == 0 ? src.rows : src.cols));
3701 //////////////////////////////////////// sort ///////////////////////////////////////////
3706 #if IPP_VERSION_X100 > 0
3707 #define USE_IPP_SORT
3709 typedef IppStatus (CV_STDCALL * IppSortFunc)(void *, int);
3710 typedef IppSortFunc IppFlipFunc;
3712 static IppSortFunc getSortFunc(int depth, bool sortDescending)
3714 if (!sortDescending)
3715 return depth == CV_8U ? (IppSortFunc)ippsSortAscend_8u_I :
3716 /*depth == CV_16U ? (IppSortFunc)ippsSortAscend_16u_I :
3717 depth == CV_16S ? (IppSortFunc)ippsSortAscend_16s_I :
3718 depth == CV_32S ? (IppSortFunc)ippsSortAscend_32s_I :
3719 depth == CV_32F ? (IppSortFunc)ippsSortAscend_32f_I :
3720 depth == CV_64F ? (IppSortFunc)ippsSortAscend_64f_I :*/ 0;
3722 return depth == CV_8U ? (IppSortFunc)ippsSortDescend_8u_I :
3723 /*depth == CV_16U ? (IppSortFunc)ippsSortDescend_16u_I :
3724 depth == CV_16S ? (IppSortFunc)ippsSortDescend_16s_I :
3725 depth == CV_32S ? (IppSortFunc)ippsSortDescend_32s_I :
3726 depth == CV_32F ? (IppSortFunc)ippsSortDescend_32f_I :
3727 depth == CV_64F ? (IppSortFunc)ippsSortDescend_64f_I :*/ 0;
3730 static IppFlipFunc getFlipFunc(int depth)
3732 CV_SUPPRESS_DEPRECATED_START
3734 depth == CV_8U || depth == CV_8S ? (IppFlipFunc)ippsFlip_8u_I :
3735 depth == CV_16U || depth == CV_16S ? (IppFlipFunc)ippsFlip_16u_I :
3736 depth == CV_32S || depth == CV_32F ? (IppFlipFunc)ippsFlip_32f_I :
3737 depth == CV_64F ? (IppFlipFunc)ippsFlip_64f_I : 0;
3738 CV_SUPPRESS_DEPRECATED_END
3744 template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
3749 bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
3750 bool inplace = src.data == dst.data;
3751 bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;
3754 n = src.rows, len = src.cols;
3757 n = src.cols, len = src.rows;
3763 int depth = src.depth();
3764 IppSortFunc ippSortFunc = getSortFunc(depth, sortDescending);
3765 IppFlipFunc ippFlipFunc = getFlipFunc(depth);
3768 for( i = 0; i < n; i++ )
3773 T* dptr = (T*)(dst.data + dst.step*i);
3776 const T* sptr = (const T*)(src.data + src.step*i);
3777 memcpy(dptr, sptr, sizeof(T) * len);
3783 for( j = 0; j < len; j++ )
3784 ptr[j] = ((const T*)(src.data + src.step*j))[i];
3788 if (!ippSortFunc || ippSortFunc(ptr, len) < 0)
3793 setIppErrorStatus();
3795 std::sort( ptr, ptr + len );
3796 if( sortDescending )
3799 if (!ippFlipFunc || ippFlipFunc(ptr, len) < 0)
3803 setIppErrorStatus();
3805 for( j = 0; j < len/2; j++ )
3806 std::swap(ptr[j], ptr[len-1-j]);
3812 for( j = 0; j < len; j++ )
3813 ((T*)(dst.data + dst.step*j))[i] = ptr[j];
3817 template<typename _Tp> class LessThanIdx
3820 LessThanIdx( const _Tp* _arr ) : arr(_arr) {}
3821 bool operator()(int a, int b) const { return arr[a] < arr[b]; }
3825 #if defined USE_IPP_SORT && 0
3827 typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(void *, int *, int);
3829 static IppSortIndexFunc getSortIndexFunc(int depth, bool sortDescending)
3831 if (!sortDescending)
3832 return depth == CV_8U ? (IppSortIndexFunc)ippsSortIndexAscend_8u_I :
3833 depth == CV_16U ? (IppSortIndexFunc)ippsSortIndexAscend_16u_I :
3834 depth == CV_16S ? (IppSortIndexFunc)ippsSortIndexAscend_16s_I :
3835 depth == CV_32S ? (IppSortIndexFunc)ippsSortIndexAscend_32s_I :
3836 depth == CV_32F ? (IppSortIndexFunc)ippsSortIndexAscend_32f_I :
3837 depth == CV_64F ? (IppSortIndexFunc)ippsSortIndexAscend_64f_I : 0;
3839 return depth == CV_8U ? (IppSortIndexFunc)ippsSortIndexDescend_8u_I :
3840 depth == CV_16U ? (IppSortIndexFunc)ippsSortIndexDescend_16u_I :
3841 depth == CV_16S ? (IppSortIndexFunc)ippsSortIndexDescend_16s_I :
3842 depth == CV_32S ? (IppSortIndexFunc)ippsSortIndexDescend_32s_I :
3843 depth == CV_32F ? (IppSortIndexFunc)ippsSortIndexDescend_32f_I :
3844 depth == CV_64F ? (IppSortIndexFunc)ippsSortIndexDescend_64f_I : 0;
3849 template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
3852 AutoBuffer<int> ibuf;
3856 bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
3857 bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;
3859 CV_Assert( src.data != dst.data );
3862 n = src.rows, len = src.cols;
3865 n = src.cols, len = src.rows;
3872 #if defined USE_IPP_SORT && 0
3873 int depth = src.depth();
3874 IppSortIndexFunc ippFunc = getSortIndexFunc(depth, sortDescending);
3875 IppFlipFunc ippFlipFunc = getFlipFunc(depth);
3878 for( i = 0; i < n; i++ )
3885 ptr = (T*)(src.data + src.step*i);
3886 iptr = (int*)(dst.data + dst.step*i);
3890 for( j = 0; j < len; j++ )
3891 ptr[j] = ((const T*)(src.data + src.step*j))[i];
3893 for( j = 0; j < len; j++ )
3896 #if defined USE_IPP_SORT && 0
3897 if (sortRows || !ippFunc || ippFunc(ptr, iptr, len) < 0)
3900 #if defined USE_IPP_SORT && 0
3901 setIppErrorStatus();
3903 std::sort( iptr, iptr + len, LessThanIdx<T>(ptr) );
3904 if( sortDescending )
3906 #if defined USE_IPP_SORT && 0
3907 if (!ippFlipFunc || ippFlipFunc(iptr, len) < 0)
3910 #if defined USE_IPP_SORT && 0
3911 setIppErrorStatus();
3913 for( j = 0; j < len/2; j++ )
3914 std::swap(iptr[j], iptr[len-1-j]);
3920 for( j = 0; j < len; j++ )
3921 ((int*)(dst.data + dst.step*j))[i] = iptr[j];
3925 typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags);
3929 void cv::sort( InputArray _src, OutputArray _dst, int flags )
3931 static SortFunc tab[] =
3933 sort_<uchar>, sort_<schar>, sort_<ushort>, sort_<short>,
3934 sort_<int>, sort_<float>, sort_<double>, 0
3936 Mat src = _src.getMat();
3937 SortFunc func = tab[src.depth()];
3938 CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 );
3939 _dst.create( src.size(), src.type() );
3940 Mat dst = _dst.getMat();
3941 func( src, dst, flags );
3944 void cv::sortIdx( InputArray _src, OutputArray _dst, int flags )
3946 static SortFunc tab[] =
3948 sortIdx_<uchar>, sortIdx_<schar>, sortIdx_<ushort>, sortIdx_<short>,
3949 sortIdx_<int>, sortIdx_<float>, sortIdx_<double>, 0
3951 Mat src = _src.getMat();
3952 SortFunc func = tab[src.depth()];
3953 CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 );
3955 Mat dst = _dst.getMat();
3956 if( dst.data == src.data )
3958 _dst.create( src.size(), CV_32S );
3959 dst = _dst.getMat();
3960 func( src, dst, flags );
3964 ////////////////////////////////////////// kmeans ////////////////////////////////////////////
3969 static void generateRandomCenter(const std::vector<Vec2f>& box, float* center, RNG& rng)
3971 size_t j, dims = box.size();
3972 float margin = 1.f/dims;
3973 for( j = 0; j < dims; j++ )
3974 center[j] = ((float)rng*(1.f+margin*2.f)-margin)*(box[j][1] - box[j][0]) + box[j][0];
3977 class KMeansPPDistanceComputer : public ParallelLoopBody
3980 KMeansPPDistanceComputer( float *_tdist2,
3993 void operator()( const cv::Range& range ) const
3995 const int begin = range.start;
3996 const int end = range.end;
3998 for ( int i = begin; i<end; i++ )
4000 tdist2[i] = std::min(normL2Sqr_(data + step*i, data + stepci, dims), dist[i]);
4005 KMeansPPDistanceComputer& operator=(const KMeansPPDistanceComputer&); // to quiet MSVC
4012 const size_t stepci;
4016 k-means center initialization using the following algorithm:
4017 Arthur & Vassilvitskii (2007) k-means++: The Advantages of Careful Seeding
4019 static void generateCentersPP(const Mat& _data, Mat& _out_centers,
4020 int K, RNG& rng, int trials)
4022 int i, j, k, dims = _data.cols, N = _data.rows;
4023 const float* data = _data.ptr<float>(0);
4024 size_t step = _data.step/sizeof(data[0]);
4025 std::vector<int> _centers(K);
4026 int* centers = &_centers[0];
4027 std::vector<float> _dist(N*3);
4028 float* dist = &_dist[0], *tdist = dist + N, *tdist2 = tdist + N;
4031 centers[0] = (unsigned)rng % N;
4033 for( i = 0; i < N; i++ )
4035 dist[i] = normL2Sqr_(data + step*i, data + step*centers[0], dims);
4039 for( k = 1; k < K; k++ )
4041 double bestSum = DBL_MAX;
4042 int bestCenter = -1;
4044 for( j = 0; j < trials; j++ )
4046 double p = (double)rng*sum0, s = 0;
4047 for( i = 0; i < N-1; i++ )
4048 if( (p -= dist[i]) <= 0 )
4052 parallel_for_(Range(0, N),
4053 KMeansPPDistanceComputer(tdist2, data, dist, dims, step, step*ci));
4054 for( i = 0; i < N; i++ )
4063 std::swap(tdist, tdist2);
4066 centers[k] = bestCenter;
4068 std::swap(dist, tdist);
4071 for( k = 0; k < K; k++ )
4073 const float* src = data + step*centers[k];
4074 float* dst = _out_centers.ptr<float>(k);
4075 for( j = 0; j < dims; j++ )
4080 class KMeansDistanceComputer : public ParallelLoopBody
4083 KMeansDistanceComputer( double *_distances,
4086 const Mat& _centers )
4087 : distances(_distances),
4094 void operator()( const Range& range ) const
4096 const int begin = range.start;
4097 const int end = range.end;
4098 const int K = centers.rows;
4099 const int dims = centers.cols;
4101 const float *sample;
4102 for( int i = begin; i<end; ++i)
4104 sample = data.ptr<float>(i);
4106 double min_dist = DBL_MAX;
4108 for( int k = 0; k < K; k++ )
4110 const float* center = centers.ptr<float>(k);
4111 const double dist = normL2Sqr_(sample, center, dims);
4113 if( min_dist > dist )
4120 distances[i] = min_dist;
4126 KMeansDistanceComputer& operator=(const KMeansDistanceComputer&); // to quiet MSVC
4136 double cv::kmeans( InputArray _data, int K,
4137 InputOutputArray _bestLabels,
4138 TermCriteria criteria, int attempts,
4139 int flags, OutputArray _centers )
4141 const int SPP_TRIALS = 3;
4142 Mat data0 = _data.getMat();
4143 bool isrow = data0.rows == 1 && data0.channels() > 1;
4144 int N = !isrow ? data0.rows : data0.cols;
4145 int dims = (!isrow ? data0.cols : 1)*data0.channels();
4146 int type = data0.depth();
4148 attempts = std::max(attempts, 1);
4149 CV_Assert( data0.dims <= 2 && type == CV_32F && K > 0 );
4150 CV_Assert( N >= K );
4152 Mat data(N, dims, CV_32F, data0.data, isrow ? dims * sizeof(float) : static_cast<size_t>(data0.step));
4154 _bestLabels.create(N, 1, CV_32S, -1, true);
4156 Mat _labels, best_labels = _bestLabels.getMat();
4157 if( flags & CV_KMEANS_USE_INITIAL_LABELS )
4159 CV_Assert( (best_labels.cols == 1 || best_labels.rows == 1) &&
4160 best_labels.cols*best_labels.rows == N &&
4161 best_labels.type() == CV_32S &&
4162 best_labels.isContinuous());
4163 best_labels.copyTo(_labels);
4167 if( !((best_labels.cols == 1 || best_labels.rows == 1) &&
4168 best_labels.cols*best_labels.rows == N &&
4169 best_labels.type() == CV_32S &&
4170 best_labels.isContinuous()))
4171 best_labels.create(N, 1, CV_32S);
4172 _labels.create(best_labels.size(), best_labels.type());
4174 int* labels = _labels.ptr<int>();
4176 Mat centers(K, dims, type), old_centers(K, dims, type), temp(1, dims, type);
4177 std::vector<int> counters(K);
4178 std::vector<Vec2f> _box(dims);
4179 Vec2f* box = &_box[0];
4180 double best_compactness = DBL_MAX, compactness = 0;
4181 RNG& rng = theRNG();
4182 int a, iter, i, j, k;
4184 if( criteria.type & TermCriteria::EPS )
4185 criteria.epsilon = std::max(criteria.epsilon, 0.);
4187 criteria.epsilon = FLT_EPSILON;
4188 criteria.epsilon *= criteria.epsilon;
4190 if( criteria.type & TermCriteria::COUNT )
4191 criteria.maxCount = std::min(std::max(criteria.maxCount, 2), 100);
4193 criteria.maxCount = 100;
4198 criteria.maxCount = 2;
4201 const float* sample = data.ptr<float>(0);
4202 for( j = 0; j < dims; j++ )
4203 box[j] = Vec2f(sample[j], sample[j]);
4205 for( i = 1; i < N; i++ )
4207 sample = data.ptr<float>(i);
4208 for( j = 0; j < dims; j++ )
4210 float v = sample[j];
4211 box[j][0] = std::min(box[j][0], v);
4212 box[j][1] = std::max(box[j][1], v);
4216 for( a = 0; a < attempts; a++ )
4218 double max_center_shift = DBL_MAX;
4221 swap(centers, old_centers);
4223 if( iter == 0 && (a > 0 || !(flags & KMEANS_USE_INITIAL_LABELS)) )
4225 if( flags & KMEANS_PP_CENTERS )
4226 generateCentersPP(data, centers, K, rng, SPP_TRIALS);
4229 for( k = 0; k < K; k++ )
4230 generateRandomCenter(_box, centers.ptr<float>(k), rng);
4235 if( iter == 0 && a == 0 && (flags & KMEANS_USE_INITIAL_LABELS) )
4237 for( i = 0; i < N; i++ )
4238 CV_Assert( (unsigned)labels[i] < (unsigned)K );
4242 centers = Scalar(0);
4243 for( k = 0; k < K; k++ )
4246 for( i = 0; i < N; i++ )
4248 sample = data.ptr<float>(i);
4250 float* center = centers.ptr<float>(k);
4252 #if CV_ENABLE_UNROLLED
4253 for(; j <= dims - 4; j += 4 )
4255 float t0 = center[j] + sample[j];
4256 float t1 = center[j+1] + sample[j+1];
4261 t0 = center[j+2] + sample[j+2];
4262 t1 = center[j+3] + sample[j+3];
4268 for( ; j < dims; j++ )
4269 center[j] += sample[j];
4274 max_center_shift = 0;
4276 for( k = 0; k < K; k++ )
4278 if( counters[k] != 0 )
4281 // if some cluster appeared to be empty then:
4282 // 1. find the biggest cluster
4283 // 2. find the farthest from the center point in the biggest cluster
4284 // 3. exclude the farthest point from the biggest cluster and form a new 1-point cluster.
4286 for( int k1 = 1; k1 < K; k1++ )
4288 if( counters[max_k] < counters[k1] )
4292 double max_dist = 0;
4293 int farthest_i = -1;
4294 float* new_center = centers.ptr<float>(k);
4295 float* old_center = centers.ptr<float>(max_k);
4296 float* _old_center = temp.ptr<float>(); // normalized
4297 float scale = 1.f/counters[max_k];
4298 for( j = 0; j < dims; j++ )
4299 _old_center[j] = old_center[j]*scale;
4301 for( i = 0; i < N; i++ )
4303 if( labels[i] != max_k )
4305 sample = data.ptr<float>(i);
4306 double dist = normL2Sqr_(sample, _old_center, dims);
4308 if( max_dist <= dist )
4317 labels[farthest_i] = k;
4318 sample = data.ptr<float>(farthest_i);
4320 for( j = 0; j < dims; j++ )
4322 old_center[j] -= sample[j];
4323 new_center[j] += sample[j];
4327 for( k = 0; k < K; k++ )
4329 float* center = centers.ptr<float>(k);
4330 CV_Assert( counters[k] != 0 );
4332 float scale = 1.f/counters[k];
4333 for( j = 0; j < dims; j++ )
4339 const float* old_center = old_centers.ptr<float>(k);
4340 for( j = 0; j < dims; j++ )
4342 double t = center[j] - old_center[j];
4345 max_center_shift = std::max(max_center_shift, dist);
4350 if( ++iter == MAX(criteria.maxCount, 2) || max_center_shift <= criteria.epsilon )
4354 Mat dists(1, N, CV_64F);
4355 double* dist = dists.ptr<double>(0);
4356 parallel_for_(Range(0, N),
4357 KMeansDistanceComputer(dist, labels, data, centers));
4359 for( i = 0; i < N; i++ )
4361 compactness += dist[i];
4365 if( compactness < best_compactness )
4367 best_compactness = compactness;
4368 if( _centers.needed() )
4369 centers.copyTo(_centers);
4370 _labels.copyTo(best_labels);
4374 return best_compactness;
4378 CV_IMPL void cvSetIdentity( CvArr* arr, CvScalar value )
4380 cv::Mat m = cv::cvarrToMat(arr);
4381 cv::setIdentity(m, value);
4385 CV_IMPL CvScalar cvTrace( const CvArr* arr )
4387 return cv::trace(cv::cvarrToMat(arr));
4391 CV_IMPL void cvTranspose( const CvArr* srcarr, CvArr* dstarr )
4393 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
4395 CV_Assert( src.rows == dst.cols && src.cols == dst.rows && src.type() == dst.type() );
4396 transpose( src, dst );
4400 CV_IMPL void cvCompleteSymm( CvMat* matrix, int LtoR )
4402 cv::Mat m = cv::cvarrToMat(matrix);
4403 cv::completeSymm( m, LtoR != 0 );
4407 CV_IMPL void cvCrossProduct( const CvArr* srcAarr, const CvArr* srcBarr, CvArr* dstarr )
4409 cv::Mat srcA = cv::cvarrToMat(srcAarr), dst = cv::cvarrToMat(dstarr);
4411 CV_Assert( srcA.size() == dst.size() && srcA.type() == dst.type() );
4412 srcA.cross(cv::cvarrToMat(srcBarr)).copyTo(dst);
4417 cvReduce( const CvArr* srcarr, CvArr* dstarr, int dim, int op )
4419 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
4422 dim = src.rows > dst.rows ? 0 : src.cols > dst.cols ? 1 : dst.cols == 1;
4425 CV_Error( CV_StsOutOfRange, "The reduced dimensionality index is out of range" );
4427 if( (dim == 0 && (dst.cols != src.cols || dst.rows != 1)) ||
4428 (dim == 1 && (dst.rows != src.rows || dst.cols != 1)) )
4429 CV_Error( CV_StsBadSize, "The output array size is incorrect" );
4431 if( src.channels() != dst.channels() )
4432 CV_Error( CV_StsUnmatchedFormats, "Input and output arrays must have the same number of channels" );
4434 cv::reduce(src, dst, dim, op, dst.type());
4439 cvRange( CvArr* arr, double start, double end )
4443 CvMat stub, *mat = (CvMat*)arr;
4450 if( !CV_IS_MAT(mat) )
4451 mat = cvGetMat( mat, &stub);
4455 type = CV_MAT_TYPE(mat->type);
4456 delta = (end-start)/(rows*cols);
4458 if( CV_IS_MAT_CONT(mat->type) )
4465 step = mat->step / CV_ELEM_SIZE(type);
4467 if( type == CV_32SC1 )
4469 int* idata = mat->data.i;
4470 int ival = cvRound(val), idelta = cvRound(delta);
4472 if( fabs(val - ival) < DBL_EPSILON &&
4473 fabs(delta - idelta) < DBL_EPSILON )
4475 for( i = 0; i < rows; i++, idata += step )
4476 for( j = 0; j < cols; j++, ival += idelta )
4481 for( i = 0; i < rows; i++, idata += step )
4482 for( j = 0; j < cols; j++, val += delta )
4483 idata[j] = cvRound(val);
4486 else if( type == CV_32FC1 )
4488 float* fdata = mat->data.fl;
4489 for( i = 0; i < rows; i++, fdata += step )
4490 for( j = 0; j < cols; j++, val += delta )
4491 fdata[j] = (float)val;
4494 CV_Error( CV_StsUnsupportedFormat, "The function only supports 32sC1 and 32fC1 datatypes" );
4497 return ok ? arr : 0;
4502 cvSort( const CvArr* _src, CvArr* _dst, CvArr* _idx, int flags )
4504 cv::Mat src = cv::cvarrToMat(_src);
4508 cv::Mat idx0 = cv::cvarrToMat(_idx), idx = idx0;
4509 CV_Assert( src.size() == idx.size() && idx.type() == CV_32S && src.data != idx.data );
4510 cv::sortIdx( src, idx, flags );
4511 CV_Assert( idx0.data == idx.data );
4516 cv::Mat dst0 = cv::cvarrToMat(_dst), dst = dst0;
4517 CV_Assert( src.size() == dst.size() && src.type() == dst.type() );
4518 cv::sort( src, dst, flags );
4519 CV_Assert( dst0.data == dst.data );
4525 cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels,
4526 CvTermCriteria termcrit, int attempts, CvRNG*,
4527 int flags, CvArr* _centers, double* _compactness )
4529 cv::Mat data = cv::cvarrToMat(_samples), labels = cv::cvarrToMat(_labels), centers;
4532 centers = cv::cvarrToMat(_centers);
4534 centers = centers.reshape(1);
4535 data = data.reshape(1);
4537 CV_Assert( !centers.empty() );
4538 CV_Assert( centers.rows == cluster_count );
4539 CV_Assert( centers.cols == data.cols );
4540 CV_Assert( centers.depth() == data.depth() );
4542 CV_Assert( labels.isContinuous() && labels.type() == CV_32S &&
4543 (labels.cols == 1 || labels.rows == 1) &&
4544 labels.cols + labels.rows - 1 == data.rows );
4546 double compactness = cv::kmeans(data, cluster_count, labels, termcrit, attempts,
4547 flags, _centers ? cv::_OutputArray(centers) : cv::_OutputArray() );
4549 *_compactness = compactness;
4553 ///////////////////////////// n-dimensional matrices ////////////////////////////
4558 Mat Mat::reshape(int _cn, int _newndims, const int* _newsz) const
4560 if(_newndims == dims)
4563 return reshape(_cn);
4565 return reshape(_cn, _newsz[0]);
4568 CV_Error(CV_StsNotImplemented, "");
4573 NAryMatIterator::NAryMatIterator()
4574 : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
4578 NAryMatIterator::NAryMatIterator(const Mat** _arrays, Mat* _planes, int _narrays)
4579 : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
4581 init(_arrays, _planes, 0, _narrays);
4584 NAryMatIterator::NAryMatIterator(const Mat** _arrays, uchar** _ptrs, int _narrays)
4585 : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
4587 init(_arrays, 0, _ptrs, _narrays);
4590 void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, uchar** _ptrs, int _narrays)
4592 CV_Assert( _arrays && (_ptrs || _planes) );
4593 int i, j, d1=0, i0 = -1, d = -1;
4604 for( i = 0; _arrays[i] != 0; i++ )
4607 CV_Assert(narrays <= 1000);
4612 for( i = 0; i < narrays; i++ )
4614 CV_Assert(arrays[i] != 0);
4615 const Mat& A = *arrays[i];
4627 // find the first dimensionality which is different from 1;
4628 // in any of the arrays the first "d1" step do not affect the continuity
4629 for( d1 = 0; d1 < d; d1++ )
4630 if( A.size[d1] > 1 )
4634 CV_Assert( A.size == arrays[i0]->size );
4636 if( !A.isContinuous() )
4638 CV_Assert( A.step[d-1] == A.elemSize() );
4639 for( j = d-1; j > d1; j-- )
4640 if( A.step[j]*A.size[j] < A.step[j-1] )
4642 iterdepth = std::max(iterdepth, j);
4648 size = arrays[i0]->size[d-1];
4649 for( j = d-1; j > iterdepth; j-- )
4651 int64 total1 = (int64)size*arrays[i0]->size[j-1];
4652 if( total1 != (int)total1 )
4658 if( iterdepth == d1 )
4662 for( j = iterdepth-1; j >= 0; j-- )
4663 nplanes *= arrays[i0]->size[j];
4673 for( i = 0; i < narrays; i++ )
4675 CV_Assert(arrays[i] != 0);
4676 const Mat& A = *arrays[i];
4684 planes[i] = Mat(1, (int)size, A.type(), A.data);
4689 NAryMatIterator& NAryMatIterator::operator ++()
4691 if( idx >= nplanes-1 )
4695 if( iterdepth == 1 )
4699 for( int i = 0; i < narrays; i++ )
4703 ptrs[i] = arrays[i]->data + arrays[i]->step[0]*idx;
4708 for( int i = 0; i < narrays; i++ )
4710 if( !planes[i].data )
4712 planes[i].data = arrays[i]->data + arrays[i]->step[0]*idx;
4718 for( int i = 0; i < narrays; i++ )
4720 const Mat& A = *arrays[i];
4723 int _idx = (int)idx;
4724 uchar* data = A.data;
4725 for( int j = iterdepth-1; j >= 0 && _idx > 0; j-- )
4727 int szi = A.size[j], t = _idx/szi;
4728 data += (_idx - t * szi)*A.step[j];
4734 planes[i].data = data;
4741 NAryMatIterator NAryMatIterator::operator ++(int)
4743 NAryMatIterator it = *this;
4748 ///////////////////////////////////////////////////////////////////////////
4749 // MatConstIterator //
4750 ///////////////////////////////////////////////////////////////////////////
4752 Point MatConstIterator::pos() const
4756 CV_DbgAssert(m->dims <= 2);
4758 ptrdiff_t ofs = ptr - m->data;
4759 int y = (int)(ofs/m->step[0]);
4760 return Point((int)((ofs - y*m->step[0])/elemSize), y);
4763 void MatConstIterator::pos(int* _idx) const
4765 CV_Assert(m != 0 && _idx);
4766 ptrdiff_t ofs = ptr - m->data;
4767 for( int i = 0; i < m->dims; i++ )
4769 size_t s = m->step[i], v = ofs/s;
4775 ptrdiff_t MatConstIterator::lpos() const
4779 if( m->isContinuous() )
4780 return (ptr - sliceStart)/elemSize;
4781 ptrdiff_t ofs = ptr - m->data;
4785 ptrdiff_t y = ofs/m->step[0];
4786 return y*m->cols + (ofs - y*m->step[0])/elemSize;
4788 ptrdiff_t result = 0;
4789 for( i = 0; i < d; i++ )
4791 size_t s = m->step[i], v = ofs/s;
4793 result = result*m->size[i] + v;
4798 void MatConstIterator::seek(ptrdiff_t ofs, bool relative)
4800 if( m->isContinuous() )
4802 ptr = (relative ? ptr : sliceStart) + ofs*elemSize;
4803 if( ptr < sliceStart )
4805 else if( ptr > sliceEnd )
4816 ofs0 = ptr - m->data;
4817 y = ofs0/m->step[0];
4818 ofs += y*m->cols + (ofs0 - y*m->step[0])/elemSize;
4821 int y1 = std::min(std::max((int)y, 0), m->rows-1);
4822 sliceStart = m->data + y1*m->step[0];
4823 sliceEnd = sliceStart + m->cols*elemSize;
4824 ptr = y < 0 ? sliceStart : y >= m->rows ? sliceEnd :
4825 sliceStart + (ofs - y*m->cols)*elemSize;
4835 int szi = m->size[d-1];
4836 ptrdiff_t t = ofs/szi;
4837 int v = (int)(ofs - t*szi);
4839 ptr = m->data + v*elemSize;
4840 sliceStart = m->data;
4842 for( int i = d-2; i >= 0; i-- )
4846 v = (int)(ofs - t*szi);
4848 sliceStart += v*m->step[i];
4851 sliceEnd = sliceStart + m->size[d-1]*elemSize;
4855 ptr = sliceStart + (ptr - m->data);
4858 void MatConstIterator::seek(const int* _idx, bool relative)
4865 ofs = _idx[0]*m->size[1] + _idx[1];
4868 for( i = 0; i < d; i++ )
4869 ofs = ofs*m->size[i] + _idx[i];
4871 seek(ofs, relative);
4874 //////////////////////////////// SparseMat ////////////////////////////////
4876 template<typename T1, typename T2> void
4877 convertData_(const void* _from, void* _to, int cn)
4879 const T1* from = (const T1*)_from;
4882 *to = saturate_cast<T2>(*from);
4884 for( int i = 0; i < cn; i++ )
4885 to[i] = saturate_cast<T2>(from[i]);
4888 template<typename T1, typename T2> void
4889 convertScaleData_(const void* _from, void* _to, int cn, double alpha, double beta)
4891 const T1* from = (const T1*)_from;
4894 *to = saturate_cast<T2>(*from*alpha + beta);
4896 for( int i = 0; i < cn; i++ )
4897 to[i] = saturate_cast<T2>(from[i]*alpha + beta);
4900 typedef void (*ConvertData)(const void* from, void* to, int cn);
4901 typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alpha, double beta);
4903 static ConvertData getConvertElem(int fromType, int toType)
4905 static ConvertData tab[][8] =
4906 {{ convertData_<uchar, uchar>, convertData_<uchar, schar>,
4907 convertData_<uchar, ushort>, convertData_<uchar, short>,
4908 convertData_<uchar, int>, convertData_<uchar, float>,
4909 convertData_<uchar, double>, 0 },
4911 { convertData_<schar, uchar>, convertData_<schar, schar>,
4912 convertData_<schar, ushort>, convertData_<schar, short>,
4913 convertData_<schar, int>, convertData_<schar, float>,
4914 convertData_<schar, double>, 0 },
4916 { convertData_<ushort, uchar>, convertData_<ushort, schar>,
4917 convertData_<ushort, ushort>, convertData_<ushort, short>,
4918 convertData_<ushort, int>, convertData_<ushort, float>,
4919 convertData_<ushort, double>, 0 },
4921 { convertData_<short, uchar>, convertData_<short, schar>,
4922 convertData_<short, ushort>, convertData_<short, short>,
4923 convertData_<short, int>, convertData_<short, float>,
4924 convertData_<short, double>, 0 },
4926 { convertData_<int, uchar>, convertData_<int, schar>,
4927 convertData_<int, ushort>, convertData_<int, short>,
4928 convertData_<int, int>, convertData_<int, float>,
4929 convertData_<int, double>, 0 },
4931 { convertData_<float, uchar>, convertData_<float, schar>,
4932 convertData_<float, ushort>, convertData_<float, short>,
4933 convertData_<float, int>, convertData_<float, float>,
4934 convertData_<float, double>, 0 },
4936 { convertData_<double, uchar>, convertData_<double, schar>,
4937 convertData_<double, ushort>, convertData_<double, short>,
4938 convertData_<double, int>, convertData_<double, float>,
4939 convertData_<double, double>, 0 },
4941 { 0, 0, 0, 0, 0, 0, 0, 0 }};
4943 ConvertData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)];
4944 CV_Assert( func != 0 );
4948 static ConvertScaleData getConvertScaleElem(int fromType, int toType)
4950 static ConvertScaleData tab[][8] =
4951 {{ convertScaleData_<uchar, uchar>, convertScaleData_<uchar, schar>,
4952 convertScaleData_<uchar, ushort>, convertScaleData_<uchar, short>,
4953 convertScaleData_<uchar, int>, convertScaleData_<uchar, float>,
4954 convertScaleData_<uchar, double>, 0 },
4956 { convertScaleData_<schar, uchar>, convertScaleData_<schar, schar>,
4957 convertScaleData_<schar, ushort>, convertScaleData_<schar, short>,
4958 convertScaleData_<schar, int>, convertScaleData_<schar, float>,
4959 convertScaleData_<schar, double>, 0 },
4961 { convertScaleData_<ushort, uchar>, convertScaleData_<ushort, schar>,
4962 convertScaleData_<ushort, ushort>, convertScaleData_<ushort, short>,
4963 convertScaleData_<ushort, int>, convertScaleData_<ushort, float>,
4964 convertScaleData_<ushort, double>, 0 },
4966 { convertScaleData_<short, uchar>, convertScaleData_<short, schar>,
4967 convertScaleData_<short, ushort>, convertScaleData_<short, short>,
4968 convertScaleData_<short, int>, convertScaleData_<short, float>,
4969 convertScaleData_<short, double>, 0 },
4971 { convertScaleData_<int, uchar>, convertScaleData_<int, schar>,
4972 convertScaleData_<int, ushort>, convertScaleData_<int, short>,
4973 convertScaleData_<int, int>, convertScaleData_<int, float>,
4974 convertScaleData_<int, double>, 0 },
4976 { convertScaleData_<float, uchar>, convertScaleData_<float, schar>,
4977 convertScaleData_<float, ushort>, convertScaleData_<float, short>,
4978 convertScaleData_<float, int>, convertScaleData_<float, float>,
4979 convertScaleData_<float, double>, 0 },
4981 { convertScaleData_<double, uchar>, convertScaleData_<double, schar>,
4982 convertScaleData_<double, ushort>, convertScaleData_<double, short>,
4983 convertScaleData_<double, int>, convertScaleData_<double, float>,
4984 convertScaleData_<double, double>, 0 },
4986 { 0, 0, 0, 0, 0, 0, 0, 0 }};
4988 ConvertScaleData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)];
4989 CV_Assert( func != 0 );
4993 enum { HASH_SIZE0 = 8 };
4995 static inline void copyElem(const uchar* from, uchar* to, size_t elemSize)
4998 for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) )
4999 *(int*)(to + i) = *(const int*)(from + i);
5000 for( ; i < elemSize; i++ )
5004 static inline bool isZeroElem(const uchar* data, size_t elemSize)
5007 for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) )
5008 if( *(int*)(data + i) != 0 )
5010 for( ; i < elemSize; i++ )
5016 SparseMat::Hdr::Hdr( int _dims, const int* _sizes, int _type )
5021 valueOffset = (int)alignSize(sizeof(SparseMat::Node) +
5022 sizeof(int)*std::max(dims - CV_MAX_DIM, 0), CV_ELEM_SIZE1(_type));
5023 nodeSize = alignSize(valueOffset +
5024 CV_ELEM_SIZE(_type), (int)sizeof(size_t));
5027 for( i = 0; i < dims; i++ )
5028 size[i] = _sizes[i];
5029 for( ; i < CV_MAX_DIM; i++ )
5034 void SparseMat::Hdr::clear()
5037 hashtab.resize(HASH_SIZE0);
5039 pool.resize(nodeSize);
5040 nodeCount = freeList = 0;
5044 SparseMat::SparseMat(const Mat& m)
5045 : flags(MAGIC_VAL), hdr(0)
5047 create( m.dims, m.size, m.type() );
5049 int i, idx[CV_MAX_DIM] = {0}, d = m.dims, lastSize = m.size[d - 1];
5050 size_t esz = m.elemSize();
5051 uchar* dptr = m.data;
5055 for( i = 0; i < lastSize; i++, dptr += esz )
5057 if( isZeroElem(dptr, esz) )
5060 uchar* to = newNode(idx, hash(idx));
5061 copyElem( dptr, to, esz );
5064 for( i = d - 2; i >= 0; i-- )
5066 dptr += m.step[i] - m.size[i+1]*m.step[i+1];
5067 if( ++idx[i] < m.size[i] )
5076 void SparseMat::create(int d, const int* _sizes, int _type)
5079 CV_Assert( _sizes && 0 < d && d <= CV_MAX_DIM );
5080 for( i = 0; i < d; i++ )
5081 CV_Assert( _sizes[i] > 0 );
5082 _type = CV_MAT_TYPE(_type);
5083 if( hdr && _type == type() && hdr->dims == d && hdr->refcount == 1 )
5085 for( i = 0; i < d; i++ )
5086 if( _sizes[i] != hdr->size[i] )
5095 flags = MAGIC_VAL | _type;
5096 hdr = new Hdr(d, _sizes, _type);
5099 void SparseMat::copyTo( SparseMat& m ) const
5108 m.create( hdr->dims, hdr->size, type() );
5109 SparseMatConstIterator from = begin();
5110 size_t i, N = nzcount(), esz = elemSize();
5112 for( i = 0; i < N; i++, ++from )
5114 const Node* n = from.node();
5115 uchar* to = m.newNode(n->idx, n->hashval);
5116 copyElem( from.ptr, to, esz );
5120 void SparseMat::copyTo( Mat& m ) const
5123 m.create( dims(), hdr->size, type() );
5126 SparseMatConstIterator from = begin();
5127 size_t i, N = nzcount(), esz = elemSize();
5129 for( i = 0; i < N; i++, ++from )
5131 const Node* n = from.node();
5132 copyElem( from.ptr, m.ptr(n->idx), esz);
5137 void SparseMat::convertTo( SparseMat& m, int rtype, double alpha ) const
5139 int cn = channels();
5142 rtype = CV_MAKETYPE(rtype, cn);
5143 if( hdr == m.hdr && rtype != type() )
5146 convertTo(temp, rtype, alpha);
5151 CV_Assert(hdr != 0);
5153 m.create( hdr->dims, hdr->size, rtype );
5155 SparseMatConstIterator from = begin();
5156 size_t i, N = nzcount();
5160 ConvertData cvtfunc = getConvertElem(type(), rtype);
5161 for( i = 0; i < N; i++, ++from )
5163 const Node* n = from.node();
5164 uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval);
5165 cvtfunc( from.ptr, to, cn );
5170 ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype);
5171 for( i = 0; i < N; i++, ++from )
5173 const Node* n = from.node();
5174 uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval);
5175 cvtfunc( from.ptr, to, cn, alpha, 0 );
5181 void SparseMat::convertTo( Mat& m, int rtype, double alpha, double beta ) const
5183 int cn = channels();
5186 rtype = CV_MAKETYPE(rtype, cn);
5189 m.create( dims(), hdr->size, rtype );
5192 SparseMatConstIterator from = begin();
5193 size_t i, N = nzcount();
5195 if( alpha == 1 && beta == 0 )
5197 ConvertData cvtfunc = getConvertElem(type(), rtype);
5198 for( i = 0; i < N; i++, ++from )
5200 const Node* n = from.node();
5201 uchar* to = m.ptr(n->idx);
5202 cvtfunc( from.ptr, to, cn );
5207 ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype);
5208 for( i = 0; i < N; i++, ++from )
5210 const Node* n = from.node();
5211 uchar* to = m.ptr(n->idx);
5212 cvtfunc( from.ptr, to, cn, alpha, beta );
5217 void SparseMat::clear()
5223 uchar* SparseMat::ptr(int i0, bool createMissing, size_t* hashval)
5225 CV_Assert( hdr && hdr->dims == 1 );
5226 size_t h = hashval ? *hashval : hash(i0);
5227 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
5228 uchar* pool = &hdr->pool[0];
5231 Node* elem = (Node*)(pool + nidx);
5232 if( elem->hashval == h && elem->idx[0] == i0 )
5233 return &value<uchar>(elem);
5240 return newNode( idx, h );
5245 uchar* SparseMat::ptr(int i0, int i1, bool createMissing, size_t* hashval)
5247 CV_Assert( hdr && hdr->dims == 2 );
5248 size_t h = hashval ? *hashval : hash(i0, i1);
5249 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
5250 uchar* pool = &hdr->pool[0];
5253 Node* elem = (Node*)(pool + nidx);
5254 if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 )
5255 return &value<uchar>(elem);
5261 int idx[] = { i0, i1 };
5262 return newNode( idx, h );
5267 uchar* SparseMat::ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval)
5269 CV_Assert( hdr && hdr->dims == 3 );
5270 size_t h = hashval ? *hashval : hash(i0, i1, i2);
5271 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
5272 uchar* pool = &hdr->pool[0];
5275 Node* elem = (Node*)(pool + nidx);
5276 if( elem->hashval == h && elem->idx[0] == i0 &&
5277 elem->idx[1] == i1 && elem->idx[2] == i2 )
5278 return &value<uchar>(elem);
5284 int idx[] = { i0, i1, i2 };
5285 return newNode( idx, h );
5290 uchar* SparseMat::ptr(const int* idx, bool createMissing, size_t* hashval)
5293 int i, d = hdr->dims;
5294 size_t h = hashval ? *hashval : hash(idx);
5295 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx];
5296 uchar* pool = &hdr->pool[0];
5299 Node* elem = (Node*)(pool + nidx);
5300 if( elem->hashval == h )
5302 for( i = 0; i < d; i++ )
5303 if( elem->idx[i] != idx[i] )
5306 return &value<uchar>(elem);
5311 return createMissing ? newNode(idx, h) : 0;
5314 void SparseMat::erase(int i0, int i1, size_t* hashval)
5316 CV_Assert( hdr && hdr->dims == 2 );
5317 size_t h = hashval ? *hashval : hash(i0, i1);
5318 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0;
5319 uchar* pool = &hdr->pool[0];
5322 Node* elem = (Node*)(pool + nidx);
5323 if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 )
5330 removeNode(hidx, nidx, previdx);
5333 void SparseMat::erase(int i0, int i1, int i2, size_t* hashval)
5335 CV_Assert( hdr && hdr->dims == 3 );
5336 size_t h = hashval ? *hashval : hash(i0, i1, i2);
5337 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0;
5338 uchar* pool = &hdr->pool[0];
5341 Node* elem = (Node*)(pool + nidx);
5342 if( elem->hashval == h && elem->idx[0] == i0 &&
5343 elem->idx[1] == i1 && elem->idx[2] == i2 )
5350 removeNode(hidx, nidx, previdx);
5353 void SparseMat::erase(const int* idx, size_t* hashval)
5356 int i, d = hdr->dims;
5357 size_t h = hashval ? *hashval : hash(idx);
5358 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0;
5359 uchar* pool = &hdr->pool[0];
5362 Node* elem = (Node*)(pool + nidx);
5363 if( elem->hashval == h )
5365 for( i = 0; i < d; i++ )
5366 if( elem->idx[i] != idx[i] )
5376 removeNode(hidx, nidx, previdx);
5379 void SparseMat::resizeHashTab(size_t newsize)
5381 newsize = std::max(newsize, (size_t)8);
5382 if((newsize & (newsize-1)) != 0)
5383 newsize = (size_t)1 << cvCeil(std::log((double)newsize)/CV_LOG2);
5385 size_t i, hsize = hdr->hashtab.size();
5386 std::vector<size_t> _newh(newsize);
5387 size_t* newh = &_newh[0];
5388 for( i = 0; i < newsize; i++ )
5390 uchar* pool = &hdr->pool[0];
5391 for( i = 0; i < hsize; i++ )
5393 size_t nidx = hdr->hashtab[i];
5396 Node* elem = (Node*)(pool + nidx);
5397 size_t next = elem->next;
5398 size_t newhidx = elem->hashval & (newsize - 1);
5399 elem->next = newh[newhidx];
5400 newh[newhidx] = nidx;
5404 hdr->hashtab = _newh;
5407 uchar* SparseMat::newNode(const int* idx, size_t hashval)
5409 const int HASH_MAX_FILL_FACTOR=3;
5411 size_t hsize = hdr->hashtab.size();
5412 if( ++hdr->nodeCount > hsize*HASH_MAX_FILL_FACTOR )
5414 resizeHashTab(std::max(hsize*2, (size_t)8));
5415 hsize = hdr->hashtab.size();
5418 if( !hdr->freeList )
5420 size_t i, nsz = hdr->nodeSize, psize = hdr->pool.size(),
5421 newpsize = std::max(psize*2, 8*nsz);
5422 hdr->pool.resize(newpsize);
5423 uchar* pool = &hdr->pool[0];
5424 hdr->freeList = std::max(psize, nsz);
5425 for( i = hdr->freeList; i < newpsize - nsz; i += nsz )
5426 ((Node*)(pool + i))->next = i + nsz;
5427 ((Node*)(pool + i))->next = 0;
5429 size_t nidx = hdr->freeList;
5430 Node* elem = (Node*)&hdr->pool[nidx];
5431 hdr->freeList = elem->next;
5432 elem->hashval = hashval;
5433 size_t hidx = hashval & (hsize - 1);
5434 elem->next = hdr->hashtab[hidx];
5435 hdr->hashtab[hidx] = nidx;
5437 int i, d = hdr->dims;
5438 for( i = 0; i < d; i++ )
5439 elem->idx[i] = idx[i];
5440 size_t esz = elemSize();
5441 uchar* p = &value<uchar>(elem);
5442 if( esz == sizeof(float) )
5444 else if( esz == sizeof(double) )
5453 void SparseMat::removeNode(size_t hidx, size_t nidx, size_t previdx)
5455 Node* n = node(nidx);
5458 Node* prev = node(previdx);
5459 prev->next = n->next;
5462 hdr->hashtab[hidx] = n->next;
5463 n->next = hdr->freeList;
5464 hdr->freeList = nidx;
5469 SparseMatConstIterator::SparseMatConstIterator(const SparseMat* _m)
5470 : m((SparseMat*)_m), hashidx(0), ptr(0)
5474 SparseMat::Hdr& hdr = *m->hdr;
5475 const std::vector<size_t>& htab = hdr.hashtab;
5476 size_t i, hsize = htab.size();
5477 for( i = 0; i < hsize; i++ )
5479 size_t nidx = htab[i];
5483 ptr = &hdr.pool[nidx] + hdr.valueOffset;
5489 SparseMatConstIterator& SparseMatConstIterator::operator ++()
5491 if( !ptr || !m || !m->hdr )
5493 SparseMat::Hdr& hdr = *m->hdr;
5494 size_t next = ((const SparseMat::Node*)(ptr - hdr.valueOffset))->next;
5497 ptr = &hdr.pool[next] + hdr.valueOffset;
5500 size_t i = hashidx + 1, sz = hdr.hashtab.size();
5501 for( ; i < sz; i++ )
5503 size_t nidx = hdr.hashtab[i];
5507 ptr = &hdr.pool[nidx] + hdr.valueOffset;
5517 double norm( const SparseMat& src, int normType )
5519 SparseMatConstIterator it = src.begin();
5521 size_t i, N = src.nzcount();
5522 normType &= NORM_TYPE_MASK;
5523 int type = src.type();
5526 CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
5528 if( type == CV_32F )
5530 if( normType == NORM_INF )
5531 for( i = 0; i < N; i++, ++it )
5532 result = std::max(result, std::abs((double)it.value<float>()));
5533 else if( normType == NORM_L1 )
5534 for( i = 0; i < N; i++, ++it )
5535 result += std::abs(it.value<float>());
5537 for( i = 0; i < N; i++, ++it )
5539 double v = it.value<float>();
5543 else if( type == CV_64F )
5545 if( normType == NORM_INF )
5546 for( i = 0; i < N; i++, ++it )
5547 result = std::max(result, std::abs(it.value<double>()));
5548 else if( normType == NORM_L1 )
5549 for( i = 0; i < N; i++, ++it )
5550 result += std::abs(it.value<double>());
5552 for( i = 0; i < N; i++, ++it )
5554 double v = it.value<double>();
5559 CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" );
5561 if( normType == NORM_L2 )
5562 result = std::sqrt(result);
5566 void minMaxLoc( const SparseMat& src, double* _minval, double* _maxval, int* _minidx, int* _maxidx )
5568 SparseMatConstIterator it = src.begin();
5569 size_t i, N = src.nzcount(), d = src.hdr ? src.hdr->dims : 0;
5570 int type = src.type();
5571 const int *minidx = 0, *maxidx = 0;
5573 if( type == CV_32F )
5575 float minval = FLT_MAX, maxval = -FLT_MAX;
5576 for( i = 0; i < N; i++, ++it )
5578 float v = it.value<float>();
5582 minidx = it.node()->idx;
5587 maxidx = it.node()->idx;
5595 else if( type == CV_64F )
5597 double minval = DBL_MAX, maxval = -DBL_MAX;
5598 for( i = 0; i < N; i++, ++it )
5600 double v = it.value<float>();
5604 minidx = it.node()->idx;
5609 maxidx = it.node()->idx;
5618 CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" );
5621 for( i = 0; i < d; i++ )
5622 _minidx[i] = minidx[i];
5624 for( i = 0; i < d; i++ )
5625 _maxidx[i] = maxidx[i];
5629 void normalize( const SparseMat& src, SparseMat& dst, double a, int norm_type )
5632 if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C )
5634 scale = norm( src, norm_type );
5635 scale = scale > DBL_EPSILON ? a/scale : 0.;
5638 CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" );
5640 src.convertTo( dst, -1, scale );
5643 ////////////////////// RotatedRect //////////////////////
5645 RotatedRect::RotatedRect(const Point2f& _point1, const Point2f& _point2, const Point2f& _point3)
5647 Point2f _center = 0.5f * (_point1 + _point3);
5649 vecs[0] = Vec2f(_point1 - _point2);
5650 vecs[1] = Vec2f(_point2 - _point3);
5651 // check that given sides are perpendicular
5652 CV_Assert( abs(vecs[0].dot(vecs[1])) / (norm(vecs[0]) * norm(vecs[1])) <= FLT_EPSILON );
5654 // wd_i stores which vector (0,1) or (1,2) will make the width
5655 // One of them will definitely have slope within -1 to 1
5657 if( abs(vecs[1][1]) < abs(vecs[1][0]) ) wd_i = 1;
5658 int ht_i = (wd_i + 1) % 2;
5660 float _angle = atan(vecs[wd_i][1] / vecs[wd_i][0]) * 180.0f / (float) CV_PI;
5661 float _width = (float) norm(vecs[wd_i]);
5662 float _height = (float) norm(vecs[ht_i]);
5665 size = Size2f(_width, _height);
5669 void RotatedRect::points(Point2f pt[]) const
5671 double _angle = angle*CV_PI/180.;
5672 float b = (float)cos(_angle)*0.5f;
5673 float a = (float)sin(_angle)*0.5f;
5675 pt[0].x = center.x - a*size.height - b*size.width;
5676 pt[0].y = center.y + b*size.height - a*size.width;
5677 pt[1].x = center.x + a*size.height - b*size.width;
5678 pt[1].y = center.y - b*size.height - a*size.width;
5679 pt[2].x = 2*center.x - pt[0].x;
5680 pt[2].y = 2*center.y - pt[0].y;
5681 pt[3].x = 2*center.x - pt[1].x;
5682 pt[3].y = 2*center.y - pt[1].y;
5685 Rect RotatedRect::boundingRect() const
5689 Rect r(cvFloor(std::min(std::min(std::min(pt[0].x, pt[1].x), pt[2].x), pt[3].x)),
5690 cvFloor(std::min(std::min(std::min(pt[0].y, pt[1].y), pt[2].y), pt[3].y)),
5691 cvCeil(std::max(std::max(std::max(pt[0].x, pt[1].x), pt[2].x), pt[3].x)),
5692 cvCeil(std::max(std::max(std::max(pt[0].y, pt[1].y), pt[2].y), pt[3].y)));
5694 r.height -= r.y - 1;
5702 CvMatND::CvMatND(const cv::Mat& m)
5704 cvInitMatNDHeader(this, m.dims, m.size, m.type(), m.data );
5706 for( i = 0; i < d; i++ )
5707 dim[i].step = (int)m.step[i];
5708 type |= m.flags & cv::Mat::CONTINUOUS_FLAG;
5711 _IplImage::_IplImage(const cv::Mat& m)
5713 CV_Assert( m.dims <= 2 );
5714 cvInitImageHeader(this, m.size(), cvIplDepth(m.flags), m.channels());
5715 cvSetData(this, m.data, (int)m.step[0]);
5718 CvSparseMat* cvCreateSparseMat(const cv::SparseMat& sm)
5723 CvSparseMat* m = cvCreateSparseMat(sm.hdr->dims, sm.hdr->size, sm.type());
5725 cv::SparseMatConstIterator from = sm.begin();
5726 size_t i, N = sm.nzcount(), esz = sm.elemSize();
5728 for( i = 0; i < N; i++, ++from )
5730 const cv::SparseMat::Node* n = from.node();
5731 uchar* to = cvPtrND(m, n->idx, 0, -2, 0);
5732 cv::copyElem(from.ptr, to, esz);
5737 void CvSparseMat::copyToSparseMat(cv::SparseMat& m) const
5739 m.create( dims, &size[0], type );
5741 CvSparseMatIterator it;
5742 CvSparseNode* n = cvInitSparseMatIterator(this, &it);
5743 size_t esz = m.elemSize();
5745 for( ; n != 0; n = cvGetNextSparseNode(&it) )
5747 const int* idx = CV_NODE_IDX(this, n);
5748 uchar* to = m.newNode(idx, m.hash(idx));
5749 cv::copyElem((const uchar*)CV_NODE_VAL(this, n), to, esz);