1/*M/////////////////////////////////////////////////////////////////////////////////////// 2// 3// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4// 5// By downloading, copying, installing or using the software you agree to this license. 6// If you do not agree to this license, do not download, install, 7// copy or use the software. 8// 9// 10// License Agreement 11// For Open Source Computer Vision Library 12// 13// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. 14// Copyright (C) 2009, Willow Garage Inc., all rights reserved. 15// Third party copyrights are property of their respective owners. 16// 17// Redistribution and use in source and binary forms, with or without modification, 18// are permitted provided that the following conditions are met: 19// 20// * Redistribution's of source code must retain the above copyright notice, 21// this list of conditions and the following disclaimer. 22// 23// * Redistribution's in binary form must reproduce the above copyright notice, 24// this list of conditions and the following disclaimer in the documentation 25// and/or other materials provided with the distribution. 26// 27// * The name of the copyright holders may not be used to endorse or promote products 28// derived from this software without specific prior written permission. 29// 30// This software is provided by the copyright holders and contributors "as is" and 31// any express or implied warranties, including, but not limited to, the implied 32// warranties of merchantability and fitness for a particular purpose are disclaimed. 33// In no event shall the Intel Corporation or contributors be liable for any direct, 34// indirect, incidental, special, exemplary, or consequential damages 35// (including, but not limited to, procurement of substitute goods or services; 36// loss of use, data, or profits; or business interruption) however caused 37// and on any theory of liability, whether in contract, strict liability, 38// or tort (including negligence or otherwise) arising in any way out of 39// the use of this software, even if advised of the possibility of such damage. 40// 41//M*/ 42 43#include "precomp.hpp" 44#include "opencl_kernels_core.hpp" 45 46#include "bufferpool.impl.hpp" 47 48/****************************************************************************************\ 49* [scaled] Identity matrix initialization * 50\****************************************************************************************/ 51 52namespace cv { 53 54void MatAllocator::map(UMatData*, int) const 55{ 56} 57 58void MatAllocator::unmap(UMatData* u) const 59{ 60 if(u->urefcount == 0 && u->refcount == 0) 61 { 62 deallocate(u); 63 u = NULL; 64 } 65} 66 67void 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 71{ 72 if(!u) 73 return; 74 int isz[CV_MAX_DIM]; 75 uchar* srcptr = u->data; 76 for( int i = 0; i < dims; i++ ) 77 { 78 CV_Assert( sz[i] <= (size_t)INT_MAX ); 79 if( sz[i] == 0 ) 80 return; 81 if( srcofs ) 82 srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1); 83 isz[i] = (int)sz[i]; 84 } 85 86 Mat src(dims, isz, CV_8U, srcptr, srcstep); 87 Mat dst(dims, isz, CV_8U, dstptr, dststep); 88 89 const Mat* arrays[] = { &src, &dst }; 90 uchar* ptrs[2]; 91 NAryMatIterator it(arrays, ptrs, 2); 92 size_t j, planesz = it.size; 93 94 for( j = 0; j < it.nplanes; j++, ++it ) 95 memcpy(ptrs[1], ptrs[0], planesz); 96} 97 98 99void 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 102{ 103 if(!u) 104 return; 105 int isz[CV_MAX_DIM]; 106 uchar* dstptr = u->data; 107 for( int i = 0; i < dims; i++ ) 108 { 109 CV_Assert( sz[i] <= (size_t)INT_MAX ); 110 if( sz[i] == 0 ) 111 return; 112 if( dstofs ) 113 dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1); 114 isz[i] = (int)sz[i]; 115 } 116 117 Mat src(dims, isz, CV_8U, (void*)srcptr, srcstep); 118 Mat dst(dims, isz, CV_8U, dstptr, dststep); 119 120 const Mat* arrays[] = { &src, &dst }; 121 uchar* ptrs[2]; 122 NAryMatIterator it(arrays, ptrs, 2); 123 size_t j, planesz = it.size; 124 125 for( j = 0; j < it.nplanes; j++, ++it ) 126 memcpy(ptrs[1], ptrs[0], planesz); 127} 128 129void MatAllocator::copy(UMatData* usrc, UMatData* udst, int dims, const size_t sz[], 130 const size_t srcofs[], const size_t srcstep[], 131 const size_t dstofs[], const size_t dststep[], bool /*sync*/) const 132{ 133 if(!usrc || !udst) 134 return; 135 int isz[CV_MAX_DIM]; 136 uchar* srcptr = usrc->data; 137 uchar* dstptr = udst->data; 138 for( int i = 0; i < dims; i++ ) 139 { 140 CV_Assert( sz[i] <= (size_t)INT_MAX ); 141 if( sz[i] == 0 ) 142 return; 143 if( srcofs ) 144 srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1); 145 if( dstofs ) 146 dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1); 147 isz[i] = (int)sz[i]; 148 } 149 150 Mat src(dims, isz, CV_8U, srcptr, srcstep); 151 Mat dst(dims, isz, CV_8U, dstptr, dststep); 152 153 const Mat* arrays[] = { &src, &dst }; 154 uchar* ptrs[2]; 155 NAryMatIterator it(arrays, ptrs, 2); 156 size_t j, planesz = it.size; 157 158 for( j = 0; j < it.nplanes; j++, ++it ) 159 memcpy(ptrs[1], ptrs[0], planesz); 160} 161 162BufferPoolController* MatAllocator::getBufferPoolController(const char* id) const 163{ 164 (void)id; 165 static DummyBufferPoolController dummy; 166 return &dummy; 167} 168 169class StdMatAllocator : public MatAllocator 170{ 171public: 172 UMatData* allocate(int dims, const int* sizes, int type, 173 void* data0, size_t* step, int /*flags*/, UMatUsageFlags /*usageFlags*/) const 174 { 175 size_t total = CV_ELEM_SIZE(type); 176 for( int i = dims-1; i >= 0; i-- ) 177 { 178 if( step ) 179 { 180 if( data0 && step[i] != CV_AUTOSTEP ) 181 { 182 CV_Assert(total <= step[i]); 183 total = step[i]; 184 } 185 else 186 step[i] = total; 187 } 188 total *= sizes[i]; 189 } 190 uchar* data = data0 ? (uchar*)data0 : (uchar*)fastMalloc(total); 191 UMatData* u = new UMatData(this); 192 u->data = u->origdata = data; 193 u->size = total; 194 if(data0) 195 u->flags |= UMatData::USER_ALLOCATED; 196 197 return u; 198 } 199 200 bool allocate(UMatData* u, int /*accessFlags*/, UMatUsageFlags /*usageFlags*/) const 201 { 202 if(!u) return false; 203 return true; 204 } 205 206 void deallocate(UMatData* u) const 207 { 208 if(!u) 209 return; 210 211 CV_Assert(u->urefcount >= 0); 212 CV_Assert(u->refcount >= 0); 213 if(u->refcount == 0) 214 { 215 if( !(u->flags & UMatData::USER_ALLOCATED) ) 216 { 217 fastFree(u->origdata); 218 u->origdata = 0; 219 } 220 delete u; 221 } 222 } 223}; 224 225MatAllocator* Mat::getStdAllocator() 226{ 227 static StdMatAllocator allocator; 228 return &allocator; 229} 230 231void swap( Mat& a, Mat& b ) 232{ 233 std::swap(a.flags, b.flags); 234 std::swap(a.dims, b.dims); 235 std::swap(a.rows, b.rows); 236 std::swap(a.cols, b.cols); 237 std::swap(a.data, b.data); 238 std::swap(a.datastart, b.datastart); 239 std::swap(a.dataend, b.dataend); 240 std::swap(a.datalimit, b.datalimit); 241 std::swap(a.allocator, b.allocator); 242 std::swap(a.u, b.u); 243 244 std::swap(a.size.p, b.size.p); 245 std::swap(a.step.p, b.step.p); 246 std::swap(a.step.buf[0], b.step.buf[0]); 247 std::swap(a.step.buf[1], b.step.buf[1]); 248 249 if( a.step.p == b.step.buf ) 250 { 251 a.step.p = a.step.buf; 252 a.size.p = &a.rows; 253 } 254 255 if( b.step.p == a.step.buf ) 256 { 257 b.step.p = b.step.buf; 258 b.size.p = &b.rows; 259 } 260} 261 262 263static inline void setSize( Mat& m, int _dims, const int* _sz, 264 const size_t* _steps, bool autoSteps=false ) 265{ 266 CV_Assert( 0 <= _dims && _dims <= CV_MAX_DIM ); 267 if( m.dims != _dims ) 268 { 269 if( m.step.p != m.step.buf ) 270 { 271 fastFree(m.step.p); 272 m.step.p = m.step.buf; 273 m.size.p = &m.rows; 274 } 275 if( _dims > 2 ) 276 { 277 m.step.p = (size_t*)fastMalloc(_dims*sizeof(m.step.p[0]) + (_dims+1)*sizeof(m.size.p[0])); 278 m.size.p = (int*)(m.step.p + _dims) + 1; 279 m.size.p[-1] = _dims; 280 m.rows = m.cols = -1; 281 } 282 } 283 284 m.dims = _dims; 285 if( !_sz ) 286 return; 287 288 size_t esz = CV_ELEM_SIZE(m.flags), esz1 = CV_ELEM_SIZE1(m.flags), total = esz; 289 int i; 290 for( i = _dims-1; i >= 0; i-- ) 291 { 292 int s = _sz[i]; 293 CV_Assert( s >= 0 ); 294 m.size.p[i] = s; 295 296 if( _steps ) 297 { 298 if (_steps[i] % esz1 != 0) 299 { 300 CV_Error(Error::BadStep, "Step must be a multiple of esz1"); 301 } 302 303 m.step.p[i] = i < _dims-1 ? _steps[i] : esz; 304 } 305 else if( autoSteps ) 306 { 307 m.step.p[i] = total; 308 int64 total1 = (int64)total*s; 309 if( (uint64)total1 != (size_t)total1 ) 310 CV_Error( CV_StsOutOfRange, "The total matrix size does not fit to \"size_t\" type" ); 311 total = (size_t)total1; 312 } 313 } 314 315 if( _dims == 1 ) 316 { 317 m.dims = 2; 318 m.cols = 1; 319 m.step[1] = esz; 320 } 321} 322 323static void updateContinuityFlag(Mat& m) 324{ 325 int i, j; 326 for( i = 0; i < m.dims; i++ ) 327 { 328 if( m.size[i] > 1 ) 329 break; 330 } 331 332 for( j = m.dims-1; j > i; j-- ) 333 { 334 if( m.step[j]*m.size[j] < m.step[j-1] ) 335 break; 336 } 337 338 uint64 t = (uint64)m.step[0]*m.size[0]; 339 if( j <= i && t == (size_t)t ) 340 m.flags |= Mat::CONTINUOUS_FLAG; 341 else 342 m.flags &= ~Mat::CONTINUOUS_FLAG; 343} 344 345static void finalizeHdr(Mat& m) 346{ 347 updateContinuityFlag(m); 348 int d = m.dims; 349 if( d > 2 ) 350 m.rows = m.cols = -1; 351 if(m.u) 352 m.datastart = m.data = m.u->data; 353 if( m.data ) 354 { 355 m.datalimit = m.datastart + m.size[0]*m.step[0]; 356 if( m.size[0] > 0 ) 357 { 358 m.dataend = m.ptr() + m.size[d-1]*m.step[d-1]; 359 for( int i = 0; i < d-1; i++ ) 360 m.dataend += (m.size[i] - 1)*m.step[i]; 361 } 362 else 363 m.dataend = m.datalimit; 364 } 365 else 366 m.dataend = m.datalimit = 0; 367} 368 369 370void Mat::create(int d, const int* _sizes, int _type) 371{ 372 int i; 373 CV_Assert(0 <= d && d <= CV_MAX_DIM && _sizes); 374 _type = CV_MAT_TYPE(_type); 375 376 if( data && (d == dims || (d == 1 && dims <= 2)) && _type == type() ) 377 { 378 if( d == 2 && rows == _sizes[0] && cols == _sizes[1] ) 379 return; 380 for( i = 0; i < d; i++ ) 381 if( size[i] != _sizes[i] ) 382 break; 383 if( i == d && (d > 1 || size[1] == 1)) 384 return; 385 } 386 387 release(); 388 if( d == 0 ) 389 return; 390 flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL; 391 setSize(*this, d, _sizes, 0, true); 392 393 if( total() > 0 ) 394 { 395 MatAllocator *a = allocator, *a0 = getStdAllocator(); 396#ifdef HAVE_TGPU 397 if( !a || a == tegra::getAllocator() ) 398 a = tegra::getAllocator(d, _sizes, _type); 399#endif 400 if(!a) 401 a = a0; 402 try 403 { 404 u = a->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT); 405 CV_Assert(u != 0); 406 } 407 catch(...) 408 { 409 if(a != a0) 410 u = a0->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT); 411 CV_Assert(u != 0); 412 } 413 CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) ); 414 } 415 416 addref(); 417 finalizeHdr(*this); 418} 419 420void Mat::copySize(const Mat& m) 421{ 422 setSize(*this, m.dims, 0, 0); 423 for( int i = 0; i < dims; i++ ) 424 { 425 size[i] = m.size[i]; 426 step[i] = m.step[i]; 427 } 428} 429 430void Mat::deallocate() 431{ 432 if(u) 433 (u->currAllocator ? u->currAllocator : allocator ? allocator : getStdAllocator())->unmap(u); 434 u = NULL; 435} 436 437Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange) 438 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), 439 datalimit(0), allocator(0), u(0), size(&rows) 440{ 441 CV_Assert( m.dims >= 2 ); 442 if( m.dims > 2 ) 443 { 444 AutoBuffer<Range> rs(m.dims); 445 rs[0] = _rowRange; 446 rs[1] = _colRange; 447 for( int i = 2; i < m.dims; i++ ) 448 rs[i] = Range::all(); 449 *this = m(rs); 450 return; 451 } 452 453 *this = m; 454 if( _rowRange != Range::all() && _rowRange != Range(0,rows) ) 455 { 456 CV_Assert( 0 <= _rowRange.start && _rowRange.start <= _rowRange.end && _rowRange.end <= m.rows ); 457 rows = _rowRange.size(); 458 data += step*_rowRange.start; 459 flags |= SUBMATRIX_FLAG; 460 } 461 462 if( _colRange != Range::all() && _colRange != Range(0,cols) ) 463 { 464 CV_Assert( 0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols ); 465 cols = _colRange.size(); 466 data += _colRange.start*elemSize(); 467 flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1; 468 flags |= SUBMATRIX_FLAG; 469 } 470 471 if( rows == 1 ) 472 flags |= CONTINUOUS_FLAG; 473 474 if( rows <= 0 || cols <= 0 ) 475 { 476 release(); 477 rows = cols = 0; 478 } 479} 480 481 482Mat::Mat(const Mat& m, const Rect& roi) 483 : flags(m.flags), dims(2), rows(roi.height), cols(roi.width), 484 data(m.data + roi.y*m.step[0]), 485 datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit), 486 allocator(m.allocator), u(m.u), size(&rows) 487{ 488 CV_Assert( m.dims <= 2 ); 489 flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1; 490 flags |= roi.height == 1 ? CONTINUOUS_FLAG : 0; 491 492 size_t esz = CV_ELEM_SIZE(flags); 493 data += roi.x*esz; 494 CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 495 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows ); 496 if( u ) 497 CV_XADD(&u->refcount, 1); 498 if( roi.width < m.cols || roi.height < m.rows ) 499 flags |= SUBMATRIX_FLAG; 500 501 step[0] = m.step[0]; step[1] = esz; 502 503 if( rows <= 0 || cols <= 0 ) 504 { 505 release(); 506 rows = cols = 0; 507 } 508} 509 510 511Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _steps) 512 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), 513 datalimit(0), allocator(0), u(0), size(&rows) 514{ 515 flags |= CV_MAT_TYPE(_type); 516 datastart = data = (uchar*)_data; 517 setSize(*this, _dims, _sizes, _steps, true); 518 finalizeHdr(*this); 519} 520 521 522Mat::Mat(const Mat& m, const Range* ranges) 523 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), 524 datalimit(0), allocator(0), u(0), size(&rows) 525{ 526 int i, d = m.dims; 527 528 CV_Assert(ranges); 529 for( i = 0; i < d; i++ ) 530 { 531 Range r = ranges[i]; 532 CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) ); 533 } 534 *this = m; 535 for( i = 0; i < d; i++ ) 536 { 537 Range r = ranges[i]; 538 if( r != Range::all() && r != Range(0, size.p[i])) 539 { 540 size.p[i] = r.end - r.start; 541 data += r.start*step.p[i]; 542 flags |= SUBMATRIX_FLAG; 543 } 544 } 545 updateContinuityFlag(*this); 546} 547 548 549static Mat cvMatNDToMat(const CvMatND* m, bool copyData) 550{ 551 Mat thiz; 552 553 if( !m ) 554 return thiz; 555 thiz.datastart = thiz.data = m->data.ptr; 556 thiz.flags |= CV_MAT_TYPE(m->type); 557 int _sizes[CV_MAX_DIM]; 558 size_t _steps[CV_MAX_DIM]; 559 560 int i, d = m->dims; 561 for( i = 0; i < d; i++ ) 562 { 563 _sizes[i] = m->dim[i].size; 564 _steps[i] = m->dim[i].step; 565 } 566 567 setSize(thiz, d, _sizes, _steps); 568 finalizeHdr(thiz); 569 570 if( copyData ) 571 { 572 Mat temp(thiz); 573 thiz.release(); 574 temp.copyTo(thiz); 575 } 576 577 return thiz; 578} 579 580static Mat cvMatToMat(const CvMat* m, bool copyData) 581{ 582 Mat thiz; 583 584 if( !m ) 585 return thiz; 586 587 if( !copyData ) 588 { 589 thiz.flags = Mat::MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG)); 590 thiz.dims = 2; 591 thiz.rows = m->rows; 592 thiz.cols = m->cols; 593 thiz.datastart = thiz.data = m->data.ptr; 594 size_t esz = CV_ELEM_SIZE(m->type), minstep = thiz.cols*esz, _step = m->step; 595 if( _step == 0 ) 596 _step = minstep; 597 thiz.datalimit = thiz.datastart + _step*thiz.rows; 598 thiz.dataend = thiz.datalimit - _step + minstep; 599 thiz.step[0] = _step; thiz.step[1] = esz; 600 } 601 else 602 { 603 thiz.datastart = thiz.dataend = thiz.data = 0; 604 Mat(m->rows, m->cols, m->type, m->data.ptr, m->step).copyTo(thiz); 605 } 606 607 return thiz; 608} 609 610 611static Mat iplImageToMat(const IplImage* img, bool copyData) 612{ 613 Mat m; 614 615 if( !img ) 616 return m; 617 618 m.dims = 2; 619 CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0); 620 621 int imgdepth = IPL2CV_DEPTH(img->depth); 622 size_t esz; 623 m.step[0] = img->widthStep; 624 625 if(!img->roi) 626 { 627 CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL); 628 m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, img->nChannels); 629 m.rows = img->height; 630 m.cols = img->width; 631 m.datastart = m.data = (uchar*)img->imageData; 632 esz = CV_ELEM_SIZE(m.flags); 633 } 634 else 635 { 636 CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL || img->roi->coi != 0); 637 bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE; 638 m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, selectedPlane ? 1 : img->nChannels); 639 m.rows = img->roi->height; 640 m.cols = img->roi->width; 641 esz = CV_ELEM_SIZE(m.flags); 642 m.datastart = m.data = (uchar*)img->imageData + 643 (selectedPlane ? (img->roi->coi - 1)*m.step*img->height : 0) + 644 img->roi->yOffset*m.step[0] + img->roi->xOffset*esz; 645 } 646 m.datalimit = m.datastart + m.step.p[0]*m.rows; 647 m.dataend = m.datastart + m.step.p[0]*(m.rows-1) + esz*m.cols; 648 m.flags |= (m.cols*esz == m.step.p[0] || m.rows == 1 ? Mat::CONTINUOUS_FLAG : 0); 649 m.step[1] = esz; 650 651 if( copyData ) 652 { 653 Mat m2 = m; 654 m.release(); 655 if( !img->roi || !img->roi->coi || 656 img->dataOrder == IPL_DATA_ORDER_PLANE) 657 m2.copyTo(m); 658 else 659 { 660 int ch[] = {img->roi->coi - 1, 0}; 661 m.create(m2.rows, m2.cols, m2.type()); 662 mixChannels(&m2, 1, &m, 1, ch, 1); 663 } 664 } 665 666 return m; 667} 668 669Mat Mat::diag(int d) const 670{ 671 CV_Assert( dims <= 2 ); 672 Mat m = *this; 673 size_t esz = elemSize(); 674 int len; 675 676 if( d >= 0 ) 677 { 678 len = std::min(cols - d, rows); 679 m.data += esz*d; 680 } 681 else 682 { 683 len = std::min(rows + d, cols); 684 m.data -= step[0]*d; 685 } 686 CV_DbgAssert( len > 0 ); 687 688 m.size[0] = m.rows = len; 689 m.size[1] = m.cols = 1; 690 m.step[0] += (len > 1 ? esz : 0); 691 692 if( m.rows > 1 ) 693 m.flags &= ~CONTINUOUS_FLAG; 694 else 695 m.flags |= CONTINUOUS_FLAG; 696 697 if( size() != Size(1,1) ) 698 m.flags |= SUBMATRIX_FLAG; 699 700 return m; 701} 702 703void Mat::pop_back(size_t nelems) 704{ 705 CV_Assert( nelems <= (size_t)size.p[0] ); 706 707 if( isSubmatrix() ) 708 *this = rowRange(0, size.p[0] - (int)nelems); 709 else 710 { 711 size.p[0] -= (int)nelems; 712 dataend -= nelems*step.p[0]; 713 /*if( size.p[0] <= 1 ) 714 { 715 if( dims <= 2 ) 716 flags |= CONTINUOUS_FLAG; 717 else 718 updateContinuityFlag(*this); 719 }*/ 720 } 721} 722 723 724void Mat::push_back_(const void* elem) 725{ 726 int r = size.p[0]; 727 if( isSubmatrix() || dataend + step.p[0] > datalimit ) 728 reserve( std::max(r + 1, (r*3+1)/2) ); 729 730 size_t esz = elemSize(); 731 memcpy(data + r*step.p[0], elem, esz); 732 size.p[0] = r + 1; 733 dataend += step.p[0]; 734 if( esz < step.p[0] ) 735 flags &= ~CONTINUOUS_FLAG; 736} 737 738void Mat::reserve(size_t nelems) 739{ 740 const size_t MIN_SIZE = 64; 741 742 CV_Assert( (int)nelems >= 0 ); 743 if( !isSubmatrix() && data + step.p[0]*nelems <= datalimit ) 744 return; 745 746 int r = size.p[0]; 747 748 if( (size_t)r >= nelems ) 749 return; 750 751 size.p[0] = std::max((int)nelems, 1); 752 size_t newsize = total()*elemSize(); 753 754 if( newsize < MIN_SIZE ) 755 size.p[0] = (int)((MIN_SIZE + newsize - 1)*nelems/newsize); 756 757 Mat m(dims, size.p, type()); 758 size.p[0] = r; 759 if( r > 0 ) 760 { 761 Mat mpart = m.rowRange(0, r); 762 copyTo(mpart); 763 } 764 765 *this = m; 766 size.p[0] = r; 767 dataend = data + step.p[0]*r; 768} 769 770 771void Mat::resize(size_t nelems) 772{ 773 int saveRows = size.p[0]; 774 if( saveRows == (int)nelems ) 775 return; 776 CV_Assert( (int)nelems >= 0 ); 777 778 if( isSubmatrix() || data + step.p[0]*nelems > datalimit ) 779 reserve(nelems); 780 781 size.p[0] = (int)nelems; 782 dataend += (size.p[0] - saveRows)*step.p[0]; 783 784 //updateContinuityFlag(*this); 785} 786 787 788void Mat::resize(size_t nelems, const Scalar& s) 789{ 790 int saveRows = size.p[0]; 791 resize(nelems); 792 793 if( size.p[0] > saveRows ) 794 { 795 Mat part = rowRange(saveRows, size.p[0]); 796 part = s; 797 } 798} 799 800void Mat::push_back(const Mat& elems) 801{ 802 int r = size.p[0], delta = elems.size.p[0]; 803 if( delta == 0 ) 804 return; 805 if( this == &elems ) 806 { 807 Mat tmp = elems; 808 push_back(tmp); 809 return; 810 } 811 if( !data ) 812 { 813 *this = elems.clone(); 814 return; 815 } 816 817 size.p[0] = elems.size.p[0]; 818 bool eq = size == elems.size; 819 size.p[0] = r; 820 if( !eq ) 821 CV_Error(CV_StsUnmatchedSizes, ""); 822 if( type() != elems.type() ) 823 CV_Error(CV_StsUnmatchedFormats, ""); 824 825 if( isSubmatrix() || dataend + step.p[0]*delta > datalimit ) 826 reserve( std::max(r + delta, (r*3+1)/2) ); 827 828 size.p[0] += delta; 829 dataend += step.p[0]*delta; 830 831 //updateContinuityFlag(*this); 832 833 if( isContinuous() && elems.isContinuous() ) 834 memcpy(data + r*step.p[0], elems.data, elems.total()*elems.elemSize()); 835 else 836 { 837 Mat part = rowRange(r, r + delta); 838 elems.copyTo(part); 839 } 840} 841 842 843Mat cvarrToMat(const CvArr* arr, bool copyData, 844 bool /*allowND*/, int coiMode, AutoBuffer<double>* abuf ) 845{ 846 if( !arr ) 847 return Mat(); 848 if( CV_IS_MAT_HDR_Z(arr) ) 849 return cvMatToMat((const CvMat*)arr, copyData); 850 if( CV_IS_MATND(arr) ) 851 return cvMatNDToMat((const CvMatND*)arr, copyData ); 852 if( CV_IS_IMAGE(arr) ) 853 { 854 const IplImage* iplimg = (const IplImage*)arr; 855 if( coiMode == 0 && iplimg->roi && iplimg->roi->coi > 0 ) 856 CV_Error(CV_BadCOI, "COI is not supported by the function"); 857 return iplImageToMat(iplimg, copyData); 858 } 859 if( CV_IS_SEQ(arr) ) 860 { 861 CvSeq* seq = (CvSeq*)arr; 862 int total = seq->total, type = CV_MAT_TYPE(seq->flags), esz = seq->elem_size; 863 if( total == 0 ) 864 return Mat(); 865 CV_Assert(total > 0 && CV_ELEM_SIZE(seq->flags) == esz); 866 if(!copyData && seq->first->next == seq->first) 867 return Mat(total, 1, type, seq->first->data); 868 if( abuf ) 869 { 870 abuf->allocate(((size_t)total*esz + sizeof(double)-1)/sizeof(double)); 871 double* bufdata = *abuf; 872 cvCvtSeqToArray(seq, bufdata, CV_WHOLE_SEQ); 873 return Mat(total, 1, type, bufdata); 874 } 875 876 Mat buf(total, 1, type); 877 cvCvtSeqToArray(seq, buf.ptr(), CV_WHOLE_SEQ); 878 return buf; 879 } 880 CV_Error(CV_StsBadArg, "Unknown array type"); 881 return Mat(); 882} 883 884void Mat::locateROI( Size& wholeSize, Point& ofs ) const 885{ 886 CV_Assert( dims <= 2 && step[0] > 0 ); 887 size_t esz = elemSize(), minstep; 888 ptrdiff_t delta1 = data - datastart, delta2 = dataend - datastart; 889 890 if( delta1 == 0 ) 891 ofs.x = ofs.y = 0; 892 else 893 { 894 ofs.y = (int)(delta1/step[0]); 895 ofs.x = (int)((delta1 - step[0]*ofs.y)/esz); 896 CV_DbgAssert( data == datastart + ofs.y*step[0] + ofs.x*esz ); 897 } 898 minstep = (ofs.x + cols)*esz; 899 wholeSize.height = (int)((delta2 - minstep)/step[0] + 1); 900 wholeSize.height = std::max(wholeSize.height, ofs.y + rows); 901 wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz); 902 wholeSize.width = std::max(wholeSize.width, ofs.x + cols); 903} 904 905Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright ) 906{ 907 CV_Assert( dims <= 2 && step[0] > 0 ); 908 Size wholeSize; Point ofs; 909 size_t esz = elemSize(); 910 locateROI( wholeSize, ofs ); 911 int row1 = std::max(ofs.y - dtop, 0), row2 = std::min(ofs.y + rows + dbottom, wholeSize.height); 912 int col1 = std::max(ofs.x - dleft, 0), col2 = std::min(ofs.x + cols + dright, wholeSize.width); 913 data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz; 914 rows = row2 - row1; cols = col2 - col1; 915 size.p[0] = rows; size.p[1] = cols; 916 if( esz*cols == step[0] || rows == 1 ) 917 flags |= CONTINUOUS_FLAG; 918 else 919 flags &= ~CONTINUOUS_FLAG; 920 return *this; 921} 922 923} 924 925void cv::extractImageCOI(const CvArr* arr, OutputArray _ch, int coi) 926{ 927 Mat mat = cvarrToMat(arr, false, true, 1); 928 _ch.create(mat.dims, mat.size, mat.depth()); 929 Mat ch = _ch.getMat(); 930 if(coi < 0) 931 { 932 CV_Assert( CV_IS_IMAGE(arr) ); 933 coi = cvGetImageCOI((const IplImage*)arr)-1; 934 } 935 CV_Assert(0 <= coi && coi < mat.channels()); 936 int _pairs[] = { coi, 0 }; 937 mixChannels( &mat, 1, &ch, 1, _pairs, 1 ); 938} 939 940void cv::insertImageCOI(InputArray _ch, CvArr* arr, int coi) 941{ 942 Mat ch = _ch.getMat(), mat = cvarrToMat(arr, false, true, 1); 943 if(coi < 0) 944 { 945 CV_Assert( CV_IS_IMAGE(arr) ); 946 coi = cvGetImageCOI((const IplImage*)arr)-1; 947 } 948 CV_Assert(ch.size == mat.size && ch.depth() == mat.depth() && 0 <= coi && coi < mat.channels()); 949 int _pairs[] = { 0, coi }; 950 mixChannels( &ch, 1, &mat, 1, _pairs, 1 ); 951} 952 953namespace cv 954{ 955 956Mat Mat::reshape(int new_cn, int new_rows) const 957{ 958 int cn = channels(); 959 Mat hdr = *this; 960 961 if( dims > 2 && new_rows == 0 && new_cn != 0 && size[dims-1]*cn % new_cn == 0 ) 962 { 963 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT); 964 hdr.step[dims-1] = CV_ELEM_SIZE(hdr.flags); 965 hdr.size[dims-1] = hdr.size[dims-1]*cn / new_cn; 966 return hdr; 967 } 968 969 CV_Assert( dims <= 2 ); 970 971 if( new_cn == 0 ) 972 new_cn = cn; 973 974 int total_width = cols * cn; 975 976 if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 ) 977 new_rows = rows * total_width / new_cn; 978 979 if( new_rows != 0 && new_rows != rows ) 980 { 981 int total_size = total_width * rows; 982 if( !isContinuous() ) 983 CV_Error( CV_BadStep, 984 "The matrix is not continuous, thus its number of rows can not be changed" ); 985 986 if( (unsigned)new_rows > (unsigned)total_size ) 987 CV_Error( CV_StsOutOfRange, "Bad new number of rows" ); 988 989 total_width = total_size / new_rows; 990 991 if( total_width * new_rows != total_size ) 992 CV_Error( CV_StsBadArg, "The total number of matrix elements " 993 "is not divisible by the new number of rows" ); 994 995 hdr.rows = new_rows; 996 hdr.step[0] = total_width * elemSize1(); 997 } 998 999 int new_width = total_width / new_cn; 1000 1001 if( new_width * new_cn != total_width ) 1002 CV_Error( CV_BadNumChannels, 1003 "The total width is not divisible by the new number of channels" ); 1004 1005 hdr.cols = new_width; 1006 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT); 1007 hdr.step[1] = CV_ELEM_SIZE(hdr.flags); 1008 return hdr; 1009} 1010 1011Mat Mat::diag(const Mat& d) 1012{ 1013 CV_Assert( d.cols == 1 || d.rows == 1 ); 1014 int len = d.rows + d.cols - 1; 1015 Mat m(len, len, d.type(), Scalar(0)); 1016 Mat md = m.diag(); 1017 if( d.cols == 1 ) 1018 d.copyTo(md); 1019 else 1020 transpose(d, md); 1021 return m; 1022} 1023 1024int Mat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) const 1025{ 1026 return (depth() == _depth || _depth <= 0) && 1027 (isContinuous() || !_requireContinuous) && 1028 ((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) || 1029 (cols == _elemChannels && channels() == 1))) || 1030 (dims == 3 && channels() == 1 && size.p[2] == _elemChannels && (size.p[0] == 1 || size.p[1] == 1) && 1031 (isContinuous() || step.p[1] == step.p[2]*size.p[2]))) 1032 ? (int)(total()*channels()/_elemChannels) : -1; 1033} 1034 1035 1036void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to) 1037{ 1038 int i, depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); 1039 CV_Assert(cn <= 4); 1040 switch(depth) 1041 { 1042 case CV_8U: 1043 { 1044 uchar* buf = (uchar*)_buf; 1045 for(i = 0; i < cn; i++) 1046 buf[i] = saturate_cast<uchar>(s.val[i]); 1047 for(; i < unroll_to; i++) 1048 buf[i] = buf[i-cn]; 1049 } 1050 break; 1051 case CV_8S: 1052 { 1053 schar* buf = (schar*)_buf; 1054 for(i = 0; i < cn; i++) 1055 buf[i] = saturate_cast<schar>(s.val[i]); 1056 for(; i < unroll_to; i++) 1057 buf[i] = buf[i-cn]; 1058 } 1059 break; 1060 case CV_16U: 1061 { 1062 ushort* buf = (ushort*)_buf; 1063 for(i = 0; i < cn; i++) 1064 buf[i] = saturate_cast<ushort>(s.val[i]); 1065 for(; i < unroll_to; i++) 1066 buf[i] = buf[i-cn]; 1067 } 1068 break; 1069 case CV_16S: 1070 { 1071 short* buf = (short*)_buf; 1072 for(i = 0; i < cn; i++) 1073 buf[i] = saturate_cast<short>(s.val[i]); 1074 for(; i < unroll_to; i++) 1075 buf[i] = buf[i-cn]; 1076 } 1077 break; 1078 case CV_32S: 1079 { 1080 int* buf = (int*)_buf; 1081 for(i = 0; i < cn; i++) 1082 buf[i] = saturate_cast<int>(s.val[i]); 1083 for(; i < unroll_to; i++) 1084 buf[i] = buf[i-cn]; 1085 } 1086 break; 1087 case CV_32F: 1088 { 1089 float* buf = (float*)_buf; 1090 for(i = 0; i < cn; i++) 1091 buf[i] = saturate_cast<float>(s.val[i]); 1092 for(; i < unroll_to; i++) 1093 buf[i] = buf[i-cn]; 1094 } 1095 break; 1096 case CV_64F: 1097 { 1098 double* buf = (double*)_buf; 1099 for(i = 0; i < cn; i++) 1100 buf[i] = saturate_cast<double>(s.val[i]); 1101 for(; i < unroll_to; i++) 1102 buf[i] = buf[i-cn]; 1103 break; 1104 } 1105 default: 1106 CV_Error(CV_StsUnsupportedFormat,""); 1107 } 1108} 1109 1110 1111/*************************************************************************************************\ 1112 Input/Output Array 1113\*************************************************************************************************/ 1114 1115Mat _InputArray::getMat_(int i) const 1116{ 1117 int k = kind(); 1118 int accessFlags = flags & ACCESS_MASK; 1119 1120 if( k == MAT ) 1121 { 1122 const Mat* m = (const Mat*)obj; 1123 if( i < 0 ) 1124 return *m; 1125 return m->row(i); 1126 } 1127 1128 if( k == UMAT ) 1129 { 1130 const UMat* m = (const UMat*)obj; 1131 if( i < 0 ) 1132 return m->getMat(accessFlags); 1133 return m->getMat(accessFlags).row(i); 1134 } 1135 1136 if( k == EXPR ) 1137 { 1138 CV_Assert( i < 0 ); 1139 return (Mat)*((const MatExpr*)obj); 1140 } 1141 1142 if( k == MATX ) 1143 { 1144 CV_Assert( i < 0 ); 1145 return Mat(sz, flags, obj); 1146 } 1147 1148 if( k == STD_VECTOR ) 1149 { 1150 CV_Assert( i < 0 ); 1151 int t = CV_MAT_TYPE(flags); 1152 const std::vector<uchar>& v = *(const std::vector<uchar>*)obj; 1153 1154 return !v.empty() ? Mat(size(), t, (void*)&v[0]) : Mat(); 1155 } 1156 1157 if( k == STD_BOOL_VECTOR ) 1158 { 1159 CV_Assert( i < 0 ); 1160 int t = CV_8U; 1161 const std::vector<bool>& v = *(const std::vector<bool>*)obj; 1162 int j, n = (int)v.size(); 1163 if( n == 0 ) 1164 return Mat(); 1165 Mat m(1, n, t); 1166 uchar* dst = m.data; 1167 for( j = 0; j < n; j++ ) 1168 dst[j] = (uchar)v[j]; 1169 return m; 1170 } 1171 1172 if( k == NONE ) 1173 return Mat(); 1174 1175 if( k == STD_VECTOR_VECTOR ) 1176 { 1177 int t = type(i); 1178 const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj; 1179 CV_Assert( 0 <= i && i < (int)vv.size() ); 1180 const std::vector<uchar>& v = vv[i]; 1181 1182 return !v.empty() ? Mat(size(i), t, (void*)&v[0]) : Mat(); 1183 } 1184 1185 if( k == STD_VECTOR_MAT ) 1186 { 1187 const std::vector<Mat>& v = *(const std::vector<Mat>*)obj; 1188 CV_Assert( 0 <= i && i < (int)v.size() ); 1189 1190 return v[i]; 1191 } 1192 1193 if( k == STD_VECTOR_UMAT ) 1194 { 1195 const std::vector<UMat>& v = *(const std::vector<UMat>*)obj; 1196 CV_Assert( 0 <= i && i < (int)v.size() ); 1197 1198 return v[i].getMat(accessFlags); 1199 } 1200 1201 if( k == OPENGL_BUFFER ) 1202 { 1203 CV_Assert( i < 0 ); 1204 CV_Error(cv::Error::StsNotImplemented, "You should explicitly call mapHost/unmapHost methods for ogl::Buffer object"); 1205 return Mat(); 1206 } 1207 1208 if( k == CUDA_GPU_MAT ) 1209 { 1210 CV_Assert( i < 0 ); 1211 CV_Error(cv::Error::StsNotImplemented, "You should explicitly call download method for cuda::GpuMat object"); 1212 return Mat(); 1213 } 1214 1215 if( k == CUDA_HOST_MEM ) 1216 { 1217 CV_Assert( i < 0 ); 1218 1219 const cuda::HostMem* cuda_mem = (const cuda::HostMem*)obj; 1220 1221 return cuda_mem->createMatHeader(); 1222 } 1223 1224 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); 1225 return Mat(); 1226} 1227 1228UMat _InputArray::getUMat(int i) const 1229{ 1230 int k = kind(); 1231 int accessFlags = flags & ACCESS_MASK; 1232 1233 if( k == UMAT ) 1234 { 1235 const UMat* m = (const UMat*)obj; 1236 if( i < 0 ) 1237 return *m; 1238 return m->row(i); 1239 } 1240 1241 if( k == STD_VECTOR_UMAT ) 1242 { 1243 const std::vector<UMat>& v = *(const std::vector<UMat>*)obj; 1244 CV_Assert( 0 <= i && i < (int)v.size() ); 1245 1246 return v[i]; 1247 } 1248 1249 if( k == MAT ) 1250 { 1251 const Mat* m = (const Mat*)obj; 1252 if( i < 0 ) 1253 return m->getUMat(accessFlags); 1254 return m->row(i).getUMat(accessFlags); 1255 } 1256 1257 return getMat(i).getUMat(accessFlags); 1258} 1259 1260void _InputArray::getMatVector(std::vector<Mat>& mv) const 1261{ 1262 int k = kind(); 1263 int accessFlags = flags & ACCESS_MASK; 1264 1265 if( k == MAT ) 1266 { 1267 const Mat& m = *(const Mat*)obj; 1268 int i, n = (int)m.size[0]; 1269 mv.resize(n); 1270 1271 for( i = 0; i < n; i++ ) 1272 mv[i] = m.dims == 2 ? Mat(1, m.cols, m.type(), (void*)m.ptr(i)) : 1273 Mat(m.dims-1, &m.size[1], m.type(), (void*)m.ptr(i), &m.step[1]); 1274 return; 1275 } 1276 1277 if( k == EXPR ) 1278 { 1279 Mat m = *(const MatExpr*)obj; 1280 int i, n = m.size[0]; 1281 mv.resize(n); 1282 1283 for( i = 0; i < n; i++ ) 1284 mv[i] = m.row(i); 1285 return; 1286 } 1287 1288 if( k == MATX ) 1289 { 1290 size_t i, n = sz.height, esz = CV_ELEM_SIZE(flags); 1291 mv.resize(n); 1292 1293 for( i = 0; i < n; i++ ) 1294 mv[i] = Mat(1, sz.width, CV_MAT_TYPE(flags), (uchar*)obj + esz*sz.width*i); 1295 return; 1296 } 1297 1298 if( k == STD_VECTOR ) 1299 { 1300 const std::vector<uchar>& v = *(const std::vector<uchar>*)obj; 1301 1302 size_t i, n = v.size(), esz = CV_ELEM_SIZE(flags); 1303 int t = CV_MAT_DEPTH(flags), cn = CV_MAT_CN(flags); 1304 mv.resize(n); 1305 1306 for( i = 0; i < n; i++ ) 1307 mv[i] = Mat(1, cn, t, (void*)(&v[0] + esz*i)); 1308 return; 1309 } 1310 1311 if( k == NONE ) 1312 { 1313 mv.clear(); 1314 return; 1315 } 1316 1317 if( k == STD_VECTOR_VECTOR ) 1318 { 1319 const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj; 1320 int i, n = (int)vv.size(); 1321 int t = CV_MAT_TYPE(flags); 1322 mv.resize(n); 1323 1324 for( i = 0; i < n; i++ ) 1325 { 1326 const std::vector<uchar>& v = vv[i]; 1327 mv[i] = Mat(size(i), t, (void*)&v[0]); 1328 } 1329 return; 1330 } 1331 1332 if( k == STD_VECTOR_MAT ) 1333 { 1334 const std::vector<Mat>& v = *(const std::vector<Mat>*)obj; 1335 size_t i, n = v.size(); 1336 mv.resize(n); 1337 1338 for( i = 0; i < n; i++ ) 1339 mv[i] = v[i]; 1340 return; 1341 } 1342 1343 if( k == STD_VECTOR_UMAT ) 1344 { 1345 const std::vector<UMat>& v = *(const std::vector<UMat>*)obj; 1346 size_t i, n = v.size(); 1347 mv.resize(n); 1348 1349 for( i = 0; i < n; i++ ) 1350 mv[i] = v[i].getMat(accessFlags); 1351 return; 1352 } 1353 1354 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); 1355} 1356 1357void _InputArray::getUMatVector(std::vector<UMat>& umv) const 1358{ 1359 int k = kind(); 1360 int accessFlags = flags & ACCESS_MASK; 1361 1362 if( k == NONE ) 1363 { 1364 umv.clear(); 1365 return; 1366 } 1367 1368 if( k == STD_VECTOR_MAT ) 1369 { 1370 const std::vector<Mat>& v = *(const std::vector<Mat>*)obj; 1371 size_t i, n = v.size(); 1372 umv.resize(n); 1373 1374 for( i = 0; i < n; i++ ) 1375 umv[i] = v[i].getUMat(accessFlags); 1376 return; 1377 } 1378 1379 if( k == STD_VECTOR_UMAT ) 1380 { 1381 const std::vector<UMat>& v = *(const std::vector<UMat>*)obj; 1382 size_t i, n = v.size(); 1383 umv.resize(n); 1384 1385 for( i = 0; i < n; i++ ) 1386 umv[i] = v[i]; 1387 return; 1388 } 1389 1390 if( k == UMAT ) 1391 { 1392 UMat& v = *(UMat*)obj; 1393 umv.resize(1); 1394 umv[0] = v; 1395 return; 1396 } 1397 if( k == MAT ) 1398 { 1399 Mat& v = *(Mat*)obj; 1400 umv.resize(1); 1401 umv[0] = v.getUMat(accessFlags); 1402 return; 1403 } 1404 1405 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); 1406} 1407 1408cuda::GpuMat _InputArray::getGpuMat() const 1409{ 1410 int k = kind(); 1411 1412 if (k == CUDA_GPU_MAT) 1413 { 1414 const cuda::GpuMat* d_mat = (const cuda::GpuMat*)obj; 1415 return *d_mat; 1416 } 1417 1418 if (k == CUDA_HOST_MEM) 1419 { 1420 const cuda::HostMem* cuda_mem = (const cuda::HostMem*)obj; 1421 return cuda_mem->createGpuMatHeader(); 1422 } 1423 1424 if (k == OPENGL_BUFFER) 1425 { 1426 CV_Error(cv::Error::StsNotImplemented, "You should explicitly call mapDevice/unmapDevice methods for ogl::Buffer object"); 1427 return cuda::GpuMat(); 1428 } 1429 1430 if (k == NONE) 1431 return cuda::GpuMat(); 1432 1433 CV_Error(cv::Error::StsNotImplemented, "getGpuMat is available only for cuda::GpuMat and cuda::HostMem"); 1434 return cuda::GpuMat(); 1435} 1436 1437ogl::Buffer _InputArray::getOGlBuffer() const 1438{ 1439 int k = kind(); 1440 1441 CV_Assert(k == OPENGL_BUFFER); 1442 1443 const ogl::Buffer* gl_buf = (const ogl::Buffer*)obj; 1444 return *gl_buf; 1445} 1446 1447int _InputArray::kind() const 1448{ 1449 return flags & KIND_MASK; 1450} 1451 1452int _InputArray::rows(int i) const 1453{ 1454 return size(i).height; 1455} 1456 1457int _InputArray::cols(int i) const 1458{ 1459 return size(i).width; 1460} 1461 1462Size _InputArray::size(int i) const 1463{ 1464 int k = kind(); 1465 1466 if( k == MAT ) 1467 { 1468 CV_Assert( i < 0 ); 1469 return ((const Mat*)obj)->size(); 1470 } 1471 1472 if( k == EXPR ) 1473 { 1474 CV_Assert( i < 0 ); 1475 return ((const MatExpr*)obj)->size(); 1476 } 1477 1478 if( k == UMAT ) 1479 { 1480 CV_Assert( i < 0 ); 1481 return ((const UMat*)obj)->size(); 1482 } 1483 1484 if( k == MATX ) 1485 { 1486 CV_Assert( i < 0 ); 1487 return sz; 1488 } 1489 1490 if( k == STD_VECTOR ) 1491 { 1492 CV_Assert( i < 0 ); 1493 const std::vector<uchar>& v = *(const std::vector<uchar>*)obj; 1494 const std::vector<int>& iv = *(const std::vector<int>*)obj; 1495 size_t szb = v.size(), szi = iv.size(); 1496 return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1); 1497 } 1498 1499 if( k == STD_BOOL_VECTOR ) 1500 { 1501 CV_Assert( i < 0 ); 1502 const std::vector<bool>& v = *(const std::vector<bool>*)obj; 1503 return Size((int)v.size(), 1); 1504 } 1505 1506 if( k == NONE ) 1507 return Size(); 1508 1509 if( k == STD_VECTOR_VECTOR ) 1510 { 1511 const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj; 1512 if( i < 0 ) 1513 return vv.empty() ? Size() : Size((int)vv.size(), 1); 1514 CV_Assert( i < (int)vv.size() ); 1515 const std::vector<std::vector<int> >& ivv = *(const std::vector<std::vector<int> >*)obj; 1516 1517 size_t szb = vv[i].size(), szi = ivv[i].size(); 1518 return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1); 1519 } 1520 1521 if( k == STD_VECTOR_MAT ) 1522 { 1523 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj; 1524 if( i < 0 ) 1525 return vv.empty() ? Size() : Size((int)vv.size(), 1); 1526 CV_Assert( i < (int)vv.size() ); 1527 1528 return vv[i].size(); 1529 } 1530 1531 if( k == STD_VECTOR_UMAT ) 1532 { 1533 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj; 1534 if( i < 0 ) 1535 return vv.empty() ? Size() : Size((int)vv.size(), 1); 1536 CV_Assert( i < (int)vv.size() ); 1537 1538 return vv[i].size(); 1539 } 1540 1541 if( k == OPENGL_BUFFER ) 1542 { 1543 CV_Assert( i < 0 ); 1544 const ogl::Buffer* buf = (const ogl::Buffer*)obj; 1545 return buf->size(); 1546 } 1547 1548 if( k == CUDA_GPU_MAT ) 1549 { 1550 CV_Assert( i < 0 ); 1551 const cuda::GpuMat* d_mat = (const cuda::GpuMat*)obj; 1552 return d_mat->size(); 1553 } 1554 1555 if( k == CUDA_HOST_MEM ) 1556 { 1557 CV_Assert( i < 0 ); 1558 const cuda::HostMem* cuda_mem = (const cuda::HostMem*)obj; 1559 return cuda_mem->size(); 1560 } 1561 1562 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); 1563 return Size(); 1564} 1565 1566int _InputArray::sizend(int* arrsz, int i) const 1567{ 1568 int j, d=0, k = kind(); 1569 1570 if( k == NONE ) 1571 ; 1572 else if( k == MAT ) 1573 { 1574 CV_Assert( i < 0 ); 1575 const Mat& m = *(const Mat*)obj; 1576 d = m.dims; 1577 if(arrsz) 1578 for(j = 0; j < d; j++) 1579 arrsz[j] = m.size.p[j]; 1580 } 1581 else if( k == UMAT ) 1582 { 1583 CV_Assert( i < 0 ); 1584 const UMat& m = *(const UMat*)obj; 1585 d = m.dims; 1586 if(arrsz) 1587 for(j = 0; j < d; j++) 1588 arrsz[j] = m.size.p[j]; 1589 } 1590 else if( k == STD_VECTOR_MAT && i >= 0 ) 1591 { 1592 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj; 1593 CV_Assert( i < (int)vv.size() ); 1594 const Mat& m = vv[i]; 1595 d = m.dims; 1596 if(arrsz) 1597 for(j = 0; j < d; j++) 1598 arrsz[j] = m.size.p[j]; 1599 } 1600 else if( k == STD_VECTOR_UMAT && i >= 0 ) 1601 { 1602 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj; 1603 CV_Assert( i < (int)vv.size() ); 1604 const UMat& m = vv[i]; 1605 d = m.dims; 1606 if(arrsz) 1607 for(j = 0; j < d; j++) 1608 arrsz[j] = m.size.p[j]; 1609 } 1610 else 1611 { 1612 Size sz2d = size(i); 1613 d = 2; 1614 if(arrsz) 1615 { 1616 arrsz[0] = sz2d.height; 1617 arrsz[1] = sz2d.width; 1618 } 1619 } 1620 1621 return d; 1622} 1623 1624bool _InputArray::sameSize(const _InputArray& arr) const 1625{ 1626 int k1 = kind(), k2 = arr.kind(); 1627 Size sz1; 1628 1629 if( k1 == MAT ) 1630 { 1631 const Mat* m = ((const Mat*)obj); 1632 if( k2 == MAT ) 1633 return m->size == ((const Mat*)arr.obj)->size; 1634 if( k2 == UMAT ) 1635 return m->size == ((const UMat*)arr.obj)->size; 1636 if( m->dims > 2 ) 1637 return false; 1638 sz1 = m->size(); 1639 } 1640 else if( k1 == UMAT ) 1641 { 1642 const UMat* m = ((const UMat*)obj); 1643 if( k2 == MAT ) 1644 return m->size == ((const Mat*)arr.obj)->size; 1645 if( k2 == UMAT ) 1646 return m->size == ((const UMat*)arr.obj)->size; 1647 if( m->dims > 2 ) 1648 return false; 1649 sz1 = m->size(); 1650 } 1651 else 1652 sz1 = size(); 1653 if( arr.dims() > 2 ) 1654 return false; 1655 return sz1 == arr.size(); 1656} 1657 1658int _InputArray::dims(int i) const 1659{ 1660 int k = kind(); 1661 1662 if( k == MAT ) 1663 { 1664 CV_Assert( i < 0 ); 1665 return ((const Mat*)obj)->dims; 1666 } 1667 1668 if( k == EXPR ) 1669 { 1670 CV_Assert( i < 0 ); 1671 return ((const MatExpr*)obj)->a.dims; 1672 } 1673 1674 if( k == UMAT ) 1675 { 1676 CV_Assert( i < 0 ); 1677 return ((const UMat*)obj)->dims; 1678 } 1679 1680 if( k == MATX ) 1681 { 1682 CV_Assert( i < 0 ); 1683 return 2; 1684 } 1685 1686 if( k == STD_VECTOR || k == STD_BOOL_VECTOR ) 1687 { 1688 CV_Assert( i < 0 ); 1689 return 2; 1690 } 1691 1692 if( k == NONE ) 1693 return 0; 1694 1695 if( k == STD_VECTOR_VECTOR ) 1696 { 1697 const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj; 1698 if( i < 0 ) 1699 return 1; 1700 CV_Assert( i < (int)vv.size() ); 1701 return 2; 1702 } 1703 1704 if( k == STD_VECTOR_MAT ) 1705 { 1706 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj; 1707 if( i < 0 ) 1708 return 1; 1709 CV_Assert( i < (int)vv.size() ); 1710 1711 return vv[i].dims; 1712 } 1713 1714 if( k == STD_VECTOR_UMAT ) 1715 { 1716 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj; 1717 if( i < 0 ) 1718 return 1; 1719 CV_Assert( i < (int)vv.size() ); 1720 1721 return vv[i].dims; 1722 } 1723 1724 if( k == OPENGL_BUFFER ) 1725 { 1726 CV_Assert( i < 0 ); 1727 return 2; 1728 } 1729 1730 if( k == CUDA_GPU_MAT ) 1731 { 1732 CV_Assert( i < 0 ); 1733 return 2; 1734 } 1735 1736 if( k == CUDA_HOST_MEM ) 1737 { 1738 CV_Assert( i < 0 ); 1739 return 2; 1740 } 1741 1742 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); 1743 return 0; 1744} 1745 1746size_t _InputArray::total(int i) const 1747{ 1748 int k = kind(); 1749 1750 if( k == MAT ) 1751 { 1752 CV_Assert( i < 0 ); 1753 return ((const Mat*)obj)->total(); 1754 } 1755 1756 if( k == UMAT ) 1757 { 1758 CV_Assert( i < 0 ); 1759 return ((const UMat*)obj)->total(); 1760 } 1761 1762 if( k == STD_VECTOR_MAT ) 1763 { 1764 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj; 1765 if( i < 0 ) 1766 return vv.size(); 1767 1768 CV_Assert( i < (int)vv.size() ); 1769 return vv[i].total(); 1770 } 1771 1772 if( k == STD_VECTOR_UMAT ) 1773 { 1774 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj; 1775 if( i < 0 ) 1776 return vv.size(); 1777 1778 CV_Assert( i < (int)vv.size() ); 1779 return vv[i].total(); 1780 } 1781 1782 return size(i).area(); 1783} 1784 1785int _InputArray::type(int i) const 1786{ 1787 int k = kind(); 1788 1789 if( k == MAT ) 1790 return ((const Mat*)obj)->type(); 1791 1792 if( k == UMAT ) 1793 return ((const UMat*)obj)->type(); 1794 1795 if( k == EXPR ) 1796 return ((const MatExpr*)obj)->type(); 1797 1798 if( k == MATX || k == STD_VECTOR || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) 1799 return CV_MAT_TYPE(flags); 1800 1801 if( k == NONE ) 1802 return -1; 1803 1804 if( k == STD_VECTOR_UMAT ) 1805 { 1806 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj; 1807 if( vv.empty() ) 1808 { 1809 CV_Assert((flags & FIXED_TYPE) != 0); 1810 return CV_MAT_TYPE(flags); 1811 } 1812 CV_Assert( i < (int)vv.size() ); 1813 return vv[i >= 0 ? i : 0].type(); 1814 } 1815 1816 if( k == STD_VECTOR_MAT ) 1817 { 1818 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj; 1819 if( vv.empty() ) 1820 { 1821 CV_Assert((flags & FIXED_TYPE) != 0); 1822 return CV_MAT_TYPE(flags); 1823 } 1824 CV_Assert( i < (int)vv.size() ); 1825 return vv[i >= 0 ? i : 0].type(); 1826 } 1827 1828 if( k == OPENGL_BUFFER ) 1829 return ((const ogl::Buffer*)obj)->type(); 1830 1831 if( k == CUDA_GPU_MAT ) 1832 return ((const cuda::GpuMat*)obj)->type(); 1833 1834 if( k == CUDA_HOST_MEM ) 1835 return ((const cuda::HostMem*)obj)->type(); 1836 1837 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); 1838 return 0; 1839} 1840 1841int _InputArray::depth(int i) const 1842{ 1843 return CV_MAT_DEPTH(type(i)); 1844} 1845 1846int _InputArray::channels(int i) const 1847{ 1848 return CV_MAT_CN(type(i)); 1849} 1850 1851bool _InputArray::empty() const 1852{ 1853 int k = kind(); 1854 1855 if( k == MAT ) 1856 return ((const Mat*)obj)->empty(); 1857 1858 if( k == UMAT ) 1859 return ((const UMat*)obj)->empty(); 1860 1861 if( k == EXPR ) 1862 return false; 1863 1864 if( k == MATX ) 1865 return false; 1866 1867 if( k == STD_VECTOR ) 1868 { 1869 const std::vector<uchar>& v = *(const std::vector<uchar>*)obj; 1870 return v.empty(); 1871 } 1872 1873 if( k == STD_BOOL_VECTOR ) 1874 { 1875 const std::vector<bool>& v = *(const std::vector<bool>*)obj; 1876 return v.empty(); 1877 } 1878 1879 if( k == NONE ) 1880 return true; 1881 1882 if( k == STD_VECTOR_VECTOR ) 1883 { 1884 const std::vector<std::vector<uchar> >& vv = *(const std::vector<std::vector<uchar> >*)obj; 1885 return vv.empty(); 1886 } 1887 1888 if( k == STD_VECTOR_MAT ) 1889 { 1890 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj; 1891 return vv.empty(); 1892 } 1893 1894 if( k == STD_VECTOR_UMAT ) 1895 { 1896 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj; 1897 return vv.empty(); 1898 } 1899 1900 if( k == OPENGL_BUFFER ) 1901 return ((const ogl::Buffer*)obj)->empty(); 1902 1903 if( k == CUDA_GPU_MAT ) 1904 return ((const cuda::GpuMat*)obj)->empty(); 1905 1906 if( k == CUDA_HOST_MEM ) 1907 return ((const cuda::HostMem*)obj)->empty(); 1908 1909 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); 1910 return true; 1911} 1912 1913bool _InputArray::isContinuous(int i) const 1914{ 1915 int k = kind(); 1916 1917 if( k == MAT ) 1918 return i < 0 ? ((const Mat*)obj)->isContinuous() : true; 1919 1920 if( k == UMAT ) 1921 return i < 0 ? ((const UMat*)obj)->isContinuous() : true; 1922 1923 if( k == EXPR || k == MATX || k == STD_VECTOR || 1924 k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) 1925 return true; 1926 1927 if( k == STD_VECTOR_MAT ) 1928 { 1929 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj; 1930 CV_Assert((size_t)i < vv.size()); 1931 return vv[i].isContinuous(); 1932 } 1933 1934 if( k == STD_VECTOR_UMAT ) 1935 { 1936 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj; 1937 CV_Assert((size_t)i < vv.size()); 1938 return vv[i].isContinuous(); 1939 } 1940 1941 CV_Error(CV_StsNotImplemented, "Unknown/unsupported array type"); 1942 return false; 1943} 1944 1945bool _InputArray::isSubmatrix(int i) const 1946{ 1947 int k = kind(); 1948 1949 if( k == MAT ) 1950 return i < 0 ? ((const Mat*)obj)->isSubmatrix() : false; 1951 1952 if( k == UMAT ) 1953 return i < 0 ? ((const UMat*)obj)->isSubmatrix() : false; 1954 1955 if( k == EXPR || k == MATX || k == STD_VECTOR || 1956 k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) 1957 return false; 1958 1959 if( k == STD_VECTOR_MAT ) 1960 { 1961 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj; 1962 CV_Assert((size_t)i < vv.size()); 1963 return vv[i].isSubmatrix(); 1964 } 1965 1966 if( k == STD_VECTOR_UMAT ) 1967 { 1968 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj; 1969 CV_Assert((size_t)i < vv.size()); 1970 return vv[i].isSubmatrix(); 1971 } 1972 1973 CV_Error(CV_StsNotImplemented, ""); 1974 return false; 1975} 1976 1977size_t _InputArray::offset(int i) const 1978{ 1979 int k = kind(); 1980 1981 if( k == MAT ) 1982 { 1983 CV_Assert( i < 0 ); 1984 const Mat * const m = ((const Mat*)obj); 1985 return (size_t)(m->ptr() - m->datastart); 1986 } 1987 1988 if( k == UMAT ) 1989 { 1990 CV_Assert( i < 0 ); 1991 return ((const UMat*)obj)->offset; 1992 } 1993 1994 if( k == EXPR || k == MATX || k == STD_VECTOR || 1995 k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) 1996 return 0; 1997 1998 if( k == STD_VECTOR_MAT ) 1999 { 2000 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj; 2001 if( i < 0 ) 2002 return 1; 2003 CV_Assert( i < (int)vv.size() ); 2004 2005 return (size_t)(vv[i].ptr() - vv[i].datastart); 2006 } 2007 2008 if( k == STD_VECTOR_UMAT ) 2009 { 2010 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj; 2011 CV_Assert((size_t)i < vv.size()); 2012 return vv[i].offset; 2013 } 2014 2015 if( k == CUDA_GPU_MAT ) 2016 { 2017 CV_Assert( i < 0 ); 2018 const cuda::GpuMat * const m = ((const cuda::GpuMat*)obj); 2019 return (size_t)(m->data - m->datastart); 2020 } 2021 2022 CV_Error(Error::StsNotImplemented, ""); 2023 return 0; 2024} 2025 2026size_t _InputArray::step(int i) const 2027{ 2028 int k = kind(); 2029 2030 if( k == MAT ) 2031 { 2032 CV_Assert( i < 0 ); 2033 return ((const Mat*)obj)->step; 2034 } 2035 2036 if( k == UMAT ) 2037 { 2038 CV_Assert( i < 0 ); 2039 return ((const UMat*)obj)->step; 2040 } 2041 2042 if( k == EXPR || k == MATX || k == STD_VECTOR || 2043 k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) 2044 return 0; 2045 2046 if( k == STD_VECTOR_MAT ) 2047 { 2048 const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj; 2049 if( i < 0 ) 2050 return 1; 2051 CV_Assert( i < (int)vv.size() ); 2052 return vv[i].step; 2053 } 2054 2055 if( k == STD_VECTOR_UMAT ) 2056 { 2057 const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj; 2058 CV_Assert((size_t)i < vv.size()); 2059 return vv[i].step; 2060 } 2061 2062 if( k == CUDA_GPU_MAT ) 2063 { 2064 CV_Assert( i < 0 ); 2065 return ((const cuda::GpuMat*)obj)->step; 2066 } 2067 2068 CV_Error(Error::StsNotImplemented, ""); 2069 return 0; 2070} 2071 2072void _InputArray::copyTo(const _OutputArray& arr) const 2073{ 2074 int k = kind(); 2075 2076 if( k == NONE ) 2077 arr.release(); 2078 else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_BOOL_VECTOR ) 2079 { 2080 Mat m = getMat(); 2081 m.copyTo(arr); 2082 } 2083 else if( k == EXPR ) 2084 { 2085 const MatExpr& e = *((MatExpr*)obj); 2086 if( arr.kind() == MAT ) 2087 arr.getMatRef() = e; 2088 else 2089 Mat(e).copyTo(arr); 2090 } 2091 else if( k == UMAT ) 2092 ((UMat*)obj)->copyTo(arr); 2093 else 2094 CV_Error(Error::StsNotImplemented, ""); 2095} 2096 2097void _InputArray::copyTo(const _OutputArray& arr, const _InputArray & mask) const 2098{ 2099 int k = kind(); 2100 2101 if( k == NONE ) 2102 arr.release(); 2103 else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_BOOL_VECTOR ) 2104 { 2105 Mat m = getMat(); 2106 m.copyTo(arr, mask); 2107 } 2108 else if( k == UMAT ) 2109 ((UMat*)obj)->copyTo(arr, mask); 2110 else 2111 CV_Error(Error::StsNotImplemented, ""); 2112} 2113 2114bool _OutputArray::fixedSize() const 2115{ 2116 return (flags & FIXED_SIZE) == FIXED_SIZE; 2117} 2118 2119bool _OutputArray::fixedType() const 2120{ 2121 return (flags & FIXED_TYPE) == FIXED_TYPE; 2122} 2123 2124void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, int fixedDepthMask) const 2125{ 2126 int k = kind(); 2127 if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 ) 2128 { 2129 CV_Assert(!fixedSize() || ((Mat*)obj)->size.operator()() == _sz); 2130 CV_Assert(!fixedType() || ((Mat*)obj)->type() == mtype); 2131 ((Mat*)obj)->create(_sz, mtype); 2132 return; 2133 } 2134 if( k == UMAT && i < 0 && !allowTransposed && fixedDepthMask == 0 ) 2135 { 2136 CV_Assert(!fixedSize() || ((UMat*)obj)->size.operator()() == _sz); 2137 CV_Assert(!fixedType() || ((UMat*)obj)->type() == mtype); 2138 ((UMat*)obj)->create(_sz, mtype); 2139 return; 2140 } 2141 if( k == CUDA_GPU_MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 ) 2142 { 2143 CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == _sz); 2144 CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype); 2145 ((cuda::GpuMat*)obj)->create(_sz, mtype); 2146 return; 2147 } 2148 if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 ) 2149 { 2150 CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == _sz); 2151 CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype); 2152 ((ogl::Buffer*)obj)->create(_sz, mtype); 2153 return; 2154 } 2155 if( k == CUDA_HOST_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 ) 2156 { 2157 CV_Assert(!fixedSize() || ((cuda::HostMem*)obj)->size() == _sz); 2158 CV_Assert(!fixedType() || ((cuda::HostMem*)obj)->type() == mtype); 2159 ((cuda::HostMem*)obj)->create(_sz, mtype); 2160 return; 2161 } 2162 int sizes[] = {_sz.height, _sz.width}; 2163 create(2, sizes, mtype, i, allowTransposed, fixedDepthMask); 2164} 2165 2166void _OutputArray::create(int _rows, int _cols, int mtype, int i, bool allowTransposed, int fixedDepthMask) const 2167{ 2168 int k = kind(); 2169 if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 ) 2170 { 2171 CV_Assert(!fixedSize() || ((Mat*)obj)->size.operator()() == Size(_cols, _rows)); 2172 CV_Assert(!fixedType() || ((Mat*)obj)->type() == mtype); 2173 ((Mat*)obj)->create(_rows, _cols, mtype); 2174 return; 2175 } 2176 if( k == UMAT && i < 0 && !allowTransposed && fixedDepthMask == 0 ) 2177 { 2178 CV_Assert(!fixedSize() || ((UMat*)obj)->size.operator()() == Size(_cols, _rows)); 2179 CV_Assert(!fixedType() || ((UMat*)obj)->type() == mtype); 2180 ((UMat*)obj)->create(_rows, _cols, mtype); 2181 return; 2182 } 2183 if( k == CUDA_GPU_MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 ) 2184 { 2185 CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == Size(_cols, _rows)); 2186 CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype); 2187 ((cuda::GpuMat*)obj)->create(_rows, _cols, mtype); 2188 return; 2189 } 2190 if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 ) 2191 { 2192 CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == Size(_cols, _rows)); 2193 CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype); 2194 ((ogl::Buffer*)obj)->create(_rows, _cols, mtype); 2195 return; 2196 } 2197 if( k == CUDA_HOST_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 ) 2198 { 2199 CV_Assert(!fixedSize() || ((cuda::HostMem*)obj)->size() == Size(_cols, _rows)); 2200 CV_Assert(!fixedType() || ((cuda::HostMem*)obj)->type() == mtype); 2201 ((cuda::HostMem*)obj)->create(_rows, _cols, mtype); 2202 return; 2203 } 2204 int sizes[] = {_rows, _cols}; 2205 create(2, sizes, mtype, i, allowTransposed, fixedDepthMask); 2206} 2207 2208void _OutputArray::create(int d, const int* sizes, int mtype, int i, 2209 bool allowTransposed, int fixedDepthMask) const 2210{ 2211 int k = kind(); 2212 mtype = CV_MAT_TYPE(mtype); 2213 2214 if( k == MAT ) 2215 { 2216 CV_Assert( i < 0 ); 2217 Mat& m = *(Mat*)obj; 2218 if( allowTransposed ) 2219 { 2220 if( !m.isContinuous() ) 2221 { 2222 CV_Assert(!fixedType() && !fixedSize()); 2223 m.release(); 2224 } 2225 2226 if( d == 2 && m.dims == 2 && m.data && 2227 m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] ) 2228 return; 2229 } 2230 2231 if(fixedType()) 2232 { 2233 if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 ) 2234 mtype = m.type(); 2235 else 2236 CV_Assert(CV_MAT_TYPE(mtype) == m.type()); 2237 } 2238 if(fixedSize()) 2239 { 2240 CV_Assert(m.dims == d); 2241 for(int j = 0; j < d; ++j) 2242 CV_Assert(m.size[j] == sizes[j]); 2243 } 2244 m.create(d, sizes, mtype); 2245 return; 2246 } 2247 2248 if( k == UMAT ) 2249 { 2250 CV_Assert( i < 0 ); 2251 UMat& m = *(UMat*)obj; 2252 if( allowTransposed ) 2253 { 2254 if( !m.isContinuous() ) 2255 { 2256 CV_Assert(!fixedType() && !fixedSize()); 2257 m.release(); 2258 } 2259 2260 if( d == 2 && m.dims == 2 && !m.empty() && 2261 m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] ) 2262 return; 2263 } 2264 2265 if(fixedType()) 2266 { 2267 if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 ) 2268 mtype = m.type(); 2269 else 2270 CV_Assert(CV_MAT_TYPE(mtype) == m.type()); 2271 } 2272 if(fixedSize()) 2273 { 2274 CV_Assert(m.dims == d); 2275 for(int j = 0; j < d; ++j) 2276 CV_Assert(m.size[j] == sizes[j]); 2277 } 2278 m.create(d, sizes, mtype); 2279 return; 2280 } 2281 2282 if( k == MATX ) 2283 { 2284 CV_Assert( i < 0 ); 2285 int type0 = CV_MAT_TYPE(flags); 2286 CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == 1 && ((1 << type0) & fixedDepthMask) != 0) ); 2287 CV_Assert( d == 2 && ((sizes[0] == sz.height && sizes[1] == sz.width) || 2288 (allowTransposed && sizes[0] == sz.width && sizes[1] == sz.height))); 2289 return; 2290 } 2291 2292 if( k == STD_VECTOR || k == STD_VECTOR_VECTOR ) 2293 { 2294 CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) ); 2295 size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0; 2296 std::vector<uchar>* v = (std::vector<uchar>*)obj; 2297 2298 if( k == STD_VECTOR_VECTOR ) 2299 { 2300 std::vector<std::vector<uchar> >& vv = *(std::vector<std::vector<uchar> >*)obj; 2301 if( i < 0 ) 2302 { 2303 CV_Assert(!fixedSize() || len == vv.size()); 2304 vv.resize(len); 2305 return; 2306 } 2307 CV_Assert( i < (int)vv.size() ); 2308 v = &vv[i]; 2309 } 2310 else 2311 CV_Assert( i < 0 ); 2312 2313 int type0 = CV_MAT_TYPE(flags); 2314 CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) ); 2315 2316 int esz = CV_ELEM_SIZE(type0); 2317 CV_Assert(!fixedSize() || len == ((std::vector<uchar>*)v)->size() / esz); 2318 switch( esz ) 2319 { 2320 case 1: 2321 ((std::vector<uchar>*)v)->resize(len); 2322 break; 2323 case 2: 2324 ((std::vector<Vec2b>*)v)->resize(len); 2325 break; 2326 case 3: 2327 ((std::vector<Vec3b>*)v)->resize(len); 2328 break; 2329 case 4: 2330 ((std::vector<int>*)v)->resize(len); 2331 break; 2332 case 6: 2333 ((std::vector<Vec3s>*)v)->resize(len); 2334 break; 2335 case 8: 2336 ((std::vector<Vec2i>*)v)->resize(len); 2337 break; 2338 case 12: 2339 ((std::vector<Vec3i>*)v)->resize(len); 2340 break; 2341 case 16: 2342 ((std::vector<Vec4i>*)v)->resize(len); 2343 break; 2344 case 24: 2345 ((std::vector<Vec6i>*)v)->resize(len); 2346 break; 2347 case 32: 2348 ((std::vector<Vec8i>*)v)->resize(len); 2349 break; 2350 case 36: 2351 ((std::vector<Vec<int, 9> >*)v)->resize(len); 2352 break; 2353 case 48: 2354 ((std::vector<Vec<int, 12> >*)v)->resize(len); 2355 break; 2356 case 64: 2357 ((std::vector<Vec<int, 16> >*)v)->resize(len); 2358 break; 2359 case 128: 2360 ((std::vector<Vec<int, 32> >*)v)->resize(len); 2361 break; 2362 case 256: 2363 ((std::vector<Vec<int, 64> >*)v)->resize(len); 2364 break; 2365 case 512: 2366 ((std::vector<Vec<int, 128> >*)v)->resize(len); 2367 break; 2368 default: 2369 CV_Error_(CV_StsBadArg, ("Vectors with element size %d are not supported. Please, modify OutputArray::create()\n", esz)); 2370 } 2371 return; 2372 } 2373 2374 if( k == NONE ) 2375 { 2376 CV_Error(CV_StsNullPtr, "create() called for the missing output array" ); 2377 return; 2378 } 2379 2380 if( k == STD_VECTOR_MAT ) 2381 { 2382 std::vector<Mat>& v = *(std::vector<Mat>*)obj; 2383 2384 if( i < 0 ) 2385 { 2386 CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) ); 2387 size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0, len0 = v.size(); 2388 2389 CV_Assert(!fixedSize() || len == len0); 2390 v.resize(len); 2391 if( fixedType() ) 2392 { 2393 int _type = CV_MAT_TYPE(flags); 2394 for( size_t j = len0; j < len; j++ ) 2395 { 2396 if( v[j].type() == _type ) 2397 continue; 2398 CV_Assert( v[j].empty() ); 2399 v[j].flags = (v[j].flags & ~CV_MAT_TYPE_MASK) | _type; 2400 } 2401 } 2402 return; 2403 } 2404 2405 CV_Assert( i < (int)v.size() ); 2406 Mat& m = v[i]; 2407 2408 if( allowTransposed ) 2409 { 2410 if( !m.isContinuous() ) 2411 { 2412 CV_Assert(!fixedType() && !fixedSize()); 2413 m.release(); 2414 } 2415 2416 if( d == 2 && m.dims == 2 && m.data && 2417 m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] ) 2418 return; 2419 } 2420 2421 if(fixedType()) 2422 { 2423 if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 ) 2424 mtype = m.type(); 2425 else 2426 CV_Assert(CV_MAT_TYPE(mtype) == m.type()); 2427 } 2428 if(fixedSize()) 2429 { 2430 CV_Assert(m.dims == d); 2431 for(int j = 0; j < d; ++j) 2432 CV_Assert(m.size[j] == sizes[j]); 2433 } 2434 2435 m.create(d, sizes, mtype); 2436 return; 2437 } 2438 2439 if( k == STD_VECTOR_UMAT ) 2440 { 2441 std::vector<UMat>& v = *(std::vector<UMat>*)obj; 2442 2443 if( i < 0 ) 2444 { 2445 CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) ); 2446 size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0, len0 = v.size(); 2447 2448 CV_Assert(!fixedSize() || len == len0); 2449 v.resize(len); 2450 if( fixedType() ) 2451 { 2452 int _type = CV_MAT_TYPE(flags); 2453 for( size_t j = len0; j < len; j++ ) 2454 { 2455 if( v[j].type() == _type ) 2456 continue; 2457 CV_Assert( v[j].empty() ); 2458 v[j].flags = (v[j].flags & ~CV_MAT_TYPE_MASK) | _type; 2459 } 2460 } 2461 return; 2462 } 2463 2464 CV_Assert( i < (int)v.size() ); 2465 UMat& m = v[i]; 2466 2467 if( allowTransposed ) 2468 { 2469 if( !m.isContinuous() ) 2470 { 2471 CV_Assert(!fixedType() && !fixedSize()); 2472 m.release(); 2473 } 2474 2475 if( d == 2 && m.dims == 2 && m.u && 2476 m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] ) 2477 return; 2478 } 2479 2480 if(fixedType()) 2481 { 2482 if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 ) 2483 mtype = m.type(); 2484 else 2485 CV_Assert(CV_MAT_TYPE(mtype) == m.type()); 2486 } 2487 if(fixedSize()) 2488 { 2489 CV_Assert(m.dims == d); 2490 for(int j = 0; j < d; ++j) 2491 CV_Assert(m.size[j] == sizes[j]); 2492 } 2493 2494 m.create(d, sizes, mtype); 2495 return; 2496 } 2497 2498 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); 2499} 2500 2501void _OutputArray::createSameSize(const _InputArray& arr, int mtype) const 2502{ 2503 int arrsz[CV_MAX_DIM], d = arr.sizend(arrsz); 2504 create(d, arrsz, mtype); 2505} 2506 2507void _OutputArray::release() const 2508{ 2509 CV_Assert(!fixedSize()); 2510 2511 int k = kind(); 2512 2513 if( k == MAT ) 2514 { 2515 ((Mat*)obj)->release(); 2516 return; 2517 } 2518 2519 if( k == UMAT ) 2520 { 2521 ((UMat*)obj)->release(); 2522 return; 2523 } 2524 2525 if( k == CUDA_GPU_MAT ) 2526 { 2527 ((cuda::GpuMat*)obj)->release(); 2528 return; 2529 } 2530 2531 if( k == CUDA_HOST_MEM ) 2532 { 2533 ((cuda::HostMem*)obj)->release(); 2534 return; 2535 } 2536 2537 if( k == OPENGL_BUFFER ) 2538 { 2539 ((ogl::Buffer*)obj)->release(); 2540 return; 2541 } 2542 2543 if( k == NONE ) 2544 return; 2545 2546 if( k == STD_VECTOR ) 2547 { 2548 create(Size(), CV_MAT_TYPE(flags)); 2549 return; 2550 } 2551 2552 if( k == STD_VECTOR_VECTOR ) 2553 { 2554 ((std::vector<std::vector<uchar> >*)obj)->clear(); 2555 return; 2556 } 2557 2558 if( k == STD_VECTOR_MAT ) 2559 { 2560 ((std::vector<Mat>*)obj)->clear(); 2561 return; 2562 } 2563 2564 if( k == STD_VECTOR_UMAT ) 2565 { 2566 ((std::vector<UMat>*)obj)->clear(); 2567 return; 2568 } 2569 2570 CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); 2571} 2572 2573void _OutputArray::clear() const 2574{ 2575 int k = kind(); 2576 2577 if( k == MAT ) 2578 { 2579 CV_Assert(!fixedSize()); 2580 ((Mat*)obj)->resize(0); 2581 return; 2582 } 2583 2584 release(); 2585} 2586 2587bool _OutputArray::needed() const 2588{ 2589 return kind() != NONE; 2590} 2591 2592Mat& _OutputArray::getMatRef(int i) const 2593{ 2594 int k = kind(); 2595 if( i < 0 ) 2596 { 2597 CV_Assert( k == MAT ); 2598 return *(Mat*)obj; 2599 } 2600 else 2601 { 2602 CV_Assert( k == STD_VECTOR_MAT ); 2603 std::vector<Mat>& v = *(std::vector<Mat>*)obj; 2604 CV_Assert( i < (int)v.size() ); 2605 return v[i]; 2606 } 2607} 2608 2609UMat& _OutputArray::getUMatRef(int i) const 2610{ 2611 int k = kind(); 2612 if( i < 0 ) 2613 { 2614 CV_Assert( k == UMAT ); 2615 return *(UMat*)obj; 2616 } 2617 else 2618 { 2619 CV_Assert( k == STD_VECTOR_UMAT ); 2620 std::vector<UMat>& v = *(std::vector<UMat>*)obj; 2621 CV_Assert( i < (int)v.size() ); 2622 return v[i]; 2623 } 2624} 2625 2626cuda::GpuMat& _OutputArray::getGpuMatRef() const 2627{ 2628 int k = kind(); 2629 CV_Assert( k == CUDA_GPU_MAT ); 2630 return *(cuda::GpuMat*)obj; 2631} 2632 2633ogl::Buffer& _OutputArray::getOGlBufferRef() const 2634{ 2635 int k = kind(); 2636 CV_Assert( k == OPENGL_BUFFER ); 2637 return *(ogl::Buffer*)obj; 2638} 2639 2640cuda::HostMem& _OutputArray::getHostMemRef() const 2641{ 2642 int k = kind(); 2643 CV_Assert( k == CUDA_HOST_MEM ); 2644 return *(cuda::HostMem*)obj; 2645} 2646 2647void _OutputArray::setTo(const _InputArray& arr, const _InputArray & mask) const 2648{ 2649 int k = kind(); 2650 2651 if( k == NONE ) 2652 ; 2653 else if( k == MAT || k == MATX || k == STD_VECTOR ) 2654 { 2655 Mat m = getMat(); 2656 m.setTo(arr, mask); 2657 } 2658 else if( k == UMAT ) 2659 ((UMat*)obj)->setTo(arr, mask); 2660 else if( k == CUDA_GPU_MAT ) 2661 { 2662 Mat value = arr.getMat(); 2663 CV_Assert( checkScalar(value, type(), arr.kind(), _InputArray::CUDA_GPU_MAT) ); 2664 ((cuda::GpuMat*)obj)->setTo(Scalar(Vec<double, 4>(value.ptr<double>())), mask); 2665 } 2666 else 2667 CV_Error(Error::StsNotImplemented, ""); 2668} 2669 2670 2671void _OutputArray::assign(const UMat& u) const 2672{ 2673 int k = kind(); 2674 if (k == UMAT) 2675 { 2676 *(UMat*)obj = u; 2677 } 2678 else if (k == MAT) 2679 { 2680 u.copyTo(*(Mat*)obj); // TODO check u.getMat() 2681 } 2682 else if (k == MATX) 2683 { 2684 u.copyTo(getMat()); // TODO check u.getMat() 2685 } 2686 else 2687 { 2688 CV_Error(Error::StsNotImplemented, ""); 2689 } 2690} 2691 2692 2693void _OutputArray::assign(const Mat& m) const 2694{ 2695 int k = kind(); 2696 if (k == UMAT) 2697 { 2698 m.copyTo(*(UMat*)obj); // TODO check m.getUMat() 2699 } 2700 else if (k == MAT) 2701 { 2702 *(Mat*)obj = m; 2703 } 2704 else if (k == MATX) 2705 { 2706 m.copyTo(getMat()); 2707 } 2708 else 2709 { 2710 CV_Error(Error::StsNotImplemented, ""); 2711 } 2712} 2713 2714 2715static _InputOutputArray _none; 2716InputOutputArray noArray() { return _none; } 2717 2718} 2719 2720/*************************************************************************************************\ 2721 Matrix Operations 2722\*************************************************************************************************/ 2723 2724void cv::hconcat(const Mat* src, size_t nsrc, OutputArray _dst) 2725{ 2726 if( nsrc == 0 || !src ) 2727 { 2728 _dst.release(); 2729 return; 2730 } 2731 2732 int totalCols = 0, cols = 0; 2733 size_t i; 2734 for( i = 0; i < nsrc; i++ ) 2735 { 2736 CV_Assert( src[i].dims <= 2 && 2737 src[i].rows == src[0].rows && 2738 src[i].type() == src[0].type()); 2739 totalCols += src[i].cols; 2740 } 2741 _dst.create( src[0].rows, totalCols, src[0].type()); 2742 Mat dst = _dst.getMat(); 2743 for( i = 0; i < nsrc; i++ ) 2744 { 2745 Mat dpart = dst(Rect(cols, 0, src[i].cols, src[i].rows)); 2746 src[i].copyTo(dpart); 2747 cols += src[i].cols; 2748 } 2749} 2750 2751void cv::hconcat(InputArray src1, InputArray src2, OutputArray dst) 2752{ 2753 Mat src[] = {src1.getMat(), src2.getMat()}; 2754 hconcat(src, 2, dst); 2755} 2756 2757void cv::hconcat(InputArray _src, OutputArray dst) 2758{ 2759 std::vector<Mat> src; 2760 _src.getMatVector(src); 2761 hconcat(!src.empty() ? &src[0] : 0, src.size(), dst); 2762} 2763 2764void cv::vconcat(const Mat* src, size_t nsrc, OutputArray _dst) 2765{ 2766 if( nsrc == 0 || !src ) 2767 { 2768 _dst.release(); 2769 return; 2770 } 2771 2772 int totalRows = 0, rows = 0; 2773 size_t i; 2774 for( i = 0; i < nsrc; i++ ) 2775 { 2776 CV_Assert(src[i].dims <= 2 && 2777 src[i].cols == src[0].cols && 2778 src[i].type() == src[0].type()); 2779 totalRows += src[i].rows; 2780 } 2781 _dst.create( totalRows, src[0].cols, src[0].type()); 2782 Mat dst = _dst.getMat(); 2783 for( i = 0; i < nsrc; i++ ) 2784 { 2785 Mat dpart(dst, Rect(0, rows, src[i].cols, src[i].rows)); 2786 src[i].copyTo(dpart); 2787 rows += src[i].rows; 2788 } 2789} 2790 2791void cv::vconcat(InputArray src1, InputArray src2, OutputArray dst) 2792{ 2793 Mat src[] = {src1.getMat(), src2.getMat()}; 2794 vconcat(src, 2, dst); 2795} 2796 2797void cv::vconcat(InputArray _src, OutputArray dst) 2798{ 2799 std::vector<Mat> src; 2800 _src.getMatVector(src); 2801 vconcat(!src.empty() ? &src[0] : 0, src.size(), dst); 2802} 2803 2804//////////////////////////////////////// set identity //////////////////////////////////////////// 2805 2806#ifdef HAVE_OPENCL 2807 2808namespace cv { 2809 2810static bool ocl_setIdentity( InputOutputArray _m, const Scalar& s ) 2811{ 2812 int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), kercn = cn, rowsPerWI = 1; 2813 int sctype = CV_MAKE_TYPE(depth, cn == 3 ? 4 : cn); 2814 if (ocl::Device::getDefault().isIntel()) 2815 { 2816 rowsPerWI = 4; 2817 if (cn == 1) 2818 { 2819 kercn = std::min(ocl::predictOptimalVectorWidth(_m), 4); 2820 if (kercn != 4) 2821 kercn = 1; 2822 } 2823 } 2824 2825 ocl::Kernel k("setIdentity", ocl::core::set_identity_oclsrc, 2826 format("-D T=%s -D T1=%s -D cn=%d -D ST=%s -D kercn=%d -D rowsPerWI=%d", 2827 ocl::memopTypeToStr(CV_MAKE_TYPE(depth, kercn)), 2828 ocl::memopTypeToStr(depth), cn, 2829 ocl::memopTypeToStr(sctype), 2830 kercn, rowsPerWI)); 2831 if (k.empty()) 2832 return false; 2833 2834 UMat m = _m.getUMat(); 2835 k.args(ocl::KernelArg::WriteOnly(m, cn, kercn), 2836 ocl::KernelArg::Constant(Mat(1, 1, sctype, s))); 2837 2838 size_t globalsize[2] = { m.cols * cn / kercn, (m.rows + rowsPerWI - 1) / rowsPerWI }; 2839 return k.run(2, globalsize, NULL, false); 2840} 2841 2842} 2843 2844#endif 2845 2846void cv::setIdentity( InputOutputArray _m, const Scalar& s ) 2847{ 2848 CV_Assert( _m.dims() <= 2 ); 2849 2850 CV_OCL_RUN(_m.isUMat(), 2851 ocl_setIdentity(_m, s)) 2852 2853 Mat m = _m.getMat(); 2854 int i, j, rows = m.rows, cols = m.cols, type = m.type(); 2855 2856 if( type == CV_32FC1 ) 2857 { 2858 float* data = m.ptr<float>(); 2859 float val = (float)s[0]; 2860 size_t step = m.step/sizeof(data[0]); 2861 2862 for( i = 0; i < rows; i++, data += step ) 2863 { 2864 for( j = 0; j < cols; j++ ) 2865 data[j] = 0; 2866 if( i < cols ) 2867 data[i] = val; 2868 } 2869 } 2870 else if( type == CV_64FC1 ) 2871 { 2872 double* data = m.ptr<double>(); 2873 double val = s[0]; 2874 size_t step = m.step/sizeof(data[0]); 2875 2876 for( i = 0; i < rows; i++, data += step ) 2877 { 2878 for( j = 0; j < cols; j++ ) 2879 data[j] = j == i ? val : 0; 2880 } 2881 } 2882 else 2883 { 2884 m = Scalar(0); 2885 m.diag() = s; 2886 } 2887} 2888 2889//////////////////////////////////////////// trace /////////////////////////////////////////// 2890 2891cv::Scalar cv::trace( InputArray _m ) 2892{ 2893 Mat m = _m.getMat(); 2894 CV_Assert( m.dims <= 2 ); 2895 int i, type = m.type(); 2896 int nm = std::min(m.rows, m.cols); 2897 2898 if( type == CV_32FC1 ) 2899 { 2900 const float* ptr = m.ptr<float>(); 2901 size_t step = m.step/sizeof(ptr[0]) + 1; 2902 double _s = 0; 2903 for( i = 0; i < nm; i++ ) 2904 _s += ptr[i*step]; 2905 return _s; 2906 } 2907 2908 if( type == CV_64FC1 ) 2909 { 2910 const double* ptr = m.ptr<double>(); 2911 size_t step = m.step/sizeof(ptr[0]) + 1; 2912 double _s = 0; 2913 for( i = 0; i < nm; i++ ) 2914 _s += ptr[i*step]; 2915 return _s; 2916 } 2917 2918 return cv::sum(m.diag()); 2919} 2920 2921////////////////////////////////////// transpose ///////////////////////////////////////// 2922 2923namespace cv 2924{ 2925 2926template<typename T> static void 2927transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) 2928{ 2929 int i=0, j, m = sz.width, n = sz.height; 2930 2931 #if CV_ENABLE_UNROLLED 2932 for(; i <= m - 4; i += 4 ) 2933 { 2934 T* d0 = (T*)(dst + dstep*i); 2935 T* d1 = (T*)(dst + dstep*(i+1)); 2936 T* d2 = (T*)(dst + dstep*(i+2)); 2937 T* d3 = (T*)(dst + dstep*(i+3)); 2938 2939 for( j = 0; j <= n - 4; j += 4 ) 2940 { 2941 const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j); 2942 const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1)); 2943 const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2)); 2944 const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3)); 2945 2946 d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0]; 2947 d1[j] = s0[1]; d1[j+1] = s1[1]; d1[j+2] = s2[1]; d1[j+3] = s3[1]; 2948 d2[j] = s0[2]; d2[j+1] = s1[2]; d2[j+2] = s2[2]; d2[j+3] = s3[2]; 2949 d3[j] = s0[3]; d3[j+1] = s1[3]; d3[j+2] = s2[3]; d3[j+3] = s3[3]; 2950 } 2951 2952 for( ; j < n; j++ ) 2953 { 2954 const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep); 2955 d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3]; 2956 } 2957 } 2958 #endif 2959 for( ; i < m; i++ ) 2960 { 2961 T* d0 = (T*)(dst + dstep*i); 2962 j = 0; 2963 #if CV_ENABLE_UNROLLED 2964 for(; j <= n - 4; j += 4 ) 2965 { 2966 const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j); 2967 const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1)); 2968 const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2)); 2969 const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3)); 2970 2971 d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0]; 2972 } 2973 #endif 2974 for( ; j < n; j++ ) 2975 { 2976 const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep); 2977 d0[j] = s0[0]; 2978 } 2979 } 2980} 2981 2982template<typename T> static void 2983transposeI_( uchar* data, size_t step, int n ) 2984{ 2985 int i, j; 2986 for( i = 0; i < n; i++ ) 2987 { 2988 T* row = (T*)(data + step*i); 2989 uchar* data1 = data + i*sizeof(T); 2990 for( j = i+1; j < n; j++ ) 2991 std::swap( row[j], *(T*)(data1 + step*j) ); 2992 } 2993} 2994 2995typedef void (*TransposeFunc)( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ); 2996typedef void (*TransposeInplaceFunc)( uchar* data, size_t step, int n ); 2997 2998#define DEF_TRANSPOSE_FUNC(suffix, type) \ 2999static void transpose_##suffix( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) \ 3000{ transpose_<type>(src, sstep, dst, dstep, sz); } \ 3001\ 3002static void transposeI_##suffix( uchar* data, size_t step, int n ) \ 3003{ transposeI_<type>(data, step, n); } 3004 3005DEF_TRANSPOSE_FUNC(8u, uchar) 3006DEF_TRANSPOSE_FUNC(16u, ushort) 3007DEF_TRANSPOSE_FUNC(8uC3, Vec3b) 3008DEF_TRANSPOSE_FUNC(32s, int) 3009DEF_TRANSPOSE_FUNC(16uC3, Vec3s) 3010DEF_TRANSPOSE_FUNC(32sC2, Vec2i) 3011DEF_TRANSPOSE_FUNC(32sC3, Vec3i) 3012DEF_TRANSPOSE_FUNC(32sC4, Vec4i) 3013DEF_TRANSPOSE_FUNC(32sC6, Vec6i) 3014DEF_TRANSPOSE_FUNC(32sC8, Vec8i) 3015 3016static TransposeFunc transposeTab[] = 3017{ 3018 0, transpose_8u, transpose_16u, transpose_8uC3, transpose_32s, 0, transpose_16uC3, 0, 3019 transpose_32sC2, 0, 0, 0, transpose_32sC3, 0, 0, 0, transpose_32sC4, 3020 0, 0, 0, 0, 0, 0, 0, transpose_32sC6, 0, 0, 0, 0, 0, 0, 0, transpose_32sC8 3021}; 3022 3023static TransposeInplaceFunc transposeInplaceTab[] = 3024{ 3025 0, transposeI_8u, transposeI_16u, transposeI_8uC3, transposeI_32s, 0, transposeI_16uC3, 0, 3026 transposeI_32sC2, 0, 0, 0, transposeI_32sC3, 0, 0, 0, transposeI_32sC4, 3027 0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8 3028}; 3029 3030#ifdef HAVE_OPENCL 3031 3032static inline int divUp(int a, int b) 3033{ 3034 return (a + b - 1) / b; 3035} 3036 3037static bool ocl_transpose( InputArray _src, OutputArray _dst ) 3038{ 3039 const ocl::Device & dev = ocl::Device::getDefault(); 3040 const int TILE_DIM = 32, BLOCK_ROWS = 8; 3041 int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type), 3042 rowsPerWI = dev.isIntel() ? 4 : 1; 3043 3044 UMat src = _src.getUMat(); 3045 _dst.create(src.cols, src.rows, type); 3046 UMat dst = _dst.getUMat(); 3047 3048 String kernelName("transpose"); 3049 bool inplace = dst.u == src.u; 3050 3051 if (inplace) 3052 { 3053 CV_Assert(dst.cols == dst.rows); 3054 kernelName += "_inplace"; 3055 } 3056 else 3057 { 3058 // check required local memory size 3059 size_t required_local_memory = (size_t) TILE_DIM*(TILE_DIM+1)*CV_ELEM_SIZE(type); 3060 if (required_local_memory > ocl::Device::getDefault().localMemSize()) 3061 return false; 3062 } 3063 3064 ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc, 3065 format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d%s", 3066 ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth), 3067 cn, TILE_DIM, BLOCK_ROWS, rowsPerWI, inplace ? " -D INPLACE" : "")); 3068 if (k.empty()) 3069 return false; 3070 3071 if (inplace) 3072 k.args(ocl::KernelArg::ReadWriteNoSize(dst), dst.rows); 3073 else 3074 k.args(ocl::KernelArg::ReadOnly(src), 3075 ocl::KernelArg::WriteOnlyNoSize(dst)); 3076 3077 size_t localsize[2] = { TILE_DIM, BLOCK_ROWS }; 3078 size_t globalsize[2] = { src.cols, inplace ? (src.rows + rowsPerWI - 1) / rowsPerWI : (divUp(src.rows, TILE_DIM) * BLOCK_ROWS) }; 3079 3080 if (inplace && dev.isIntel()) 3081 { 3082 localsize[0] = 16; 3083 localsize[1] = dev.maxWorkGroupSize() / localsize[0]; 3084 } 3085 3086 return k.run(2, globalsize, localsize, false); 3087} 3088 3089#endif 3090 3091} 3092 3093void cv::transpose( InputArray _src, OutputArray _dst ) 3094{ 3095 int type = _src.type(), esz = CV_ELEM_SIZE(type); 3096 CV_Assert( _src.dims() <= 2 && esz <= 32 ); 3097 3098 CV_OCL_RUN(_dst.isUMat(), 3099 ocl_transpose(_src, _dst)) 3100 3101 Mat src = _src.getMat(); 3102 if( src.empty() ) 3103 { 3104 _dst.release(); 3105 return; 3106 } 3107 3108 _dst.create(src.cols, src.rows, src.type()); 3109 Mat dst = _dst.getMat(); 3110 3111 // handle the case of single-column/single-row matrices, stored in STL vectors. 3112 if( src.rows != dst.cols || src.cols != dst.rows ) 3113 { 3114 CV_Assert( src.size() == dst.size() && (src.cols == 1 || src.rows == 1) ); 3115 src.copyTo(dst); 3116 return; 3117 } 3118 3119#if defined HAVE_IPP 3120 CV_IPP_CHECK() 3121 { 3122 typedef IppStatus (CV_STDCALL * ippiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize); 3123 typedef IppStatus (CV_STDCALL * ippiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize); 3124 ippiTranspose ippFunc = 0; 3125 ippiTransposeI ippFuncI = 0; 3126 3127 if (dst.data == src.data && dst.cols == dst.rows) 3128 { 3129 CV_SUPPRESS_DEPRECATED_START 3130 ippFuncI = 3131 type == CV_8UC1 ? (ippiTransposeI)ippiTranspose_8u_C1IR : 3132 type == CV_8UC3 ? (ippiTransposeI)ippiTranspose_8u_C3IR : 3133 type == CV_8UC4 ? (ippiTransposeI)ippiTranspose_8u_C4IR : 3134 type == CV_16UC1 ? (ippiTransposeI)ippiTranspose_16u_C1IR : 3135 type == CV_16UC3 ? (ippiTransposeI)ippiTranspose_16u_C3IR : 3136 type == CV_16UC4 ? (ippiTransposeI)ippiTranspose_16u_C4IR : 3137 type == CV_16SC1 ? (ippiTransposeI)ippiTranspose_16s_C1IR : 3138 type == CV_16SC3 ? (ippiTransposeI)ippiTranspose_16s_C3IR : 3139 type == CV_16SC4 ? (ippiTransposeI)ippiTranspose_16s_C4IR : 3140 type == CV_32SC1 ? (ippiTransposeI)ippiTranspose_32s_C1IR : 3141 type == CV_32SC3 ? (ippiTransposeI)ippiTranspose_32s_C3IR : 3142 type == CV_32SC4 ? (ippiTransposeI)ippiTranspose_32s_C4IR : 3143 type == CV_32FC1 ? (ippiTransposeI)ippiTranspose_32f_C1IR : 3144 type == CV_32FC3 ? (ippiTransposeI)ippiTranspose_32f_C3IR : 3145 type == CV_32FC4 ? (ippiTransposeI)ippiTranspose_32f_C4IR : 0; 3146 CV_SUPPRESS_DEPRECATED_END 3147 } 3148 else 3149 { 3150 ippFunc = 3151 type == CV_8UC1 ? (ippiTranspose)ippiTranspose_8u_C1R : 3152 type == CV_8UC3 ? (ippiTranspose)ippiTranspose_8u_C3R : 3153 type == CV_8UC4 ? (ippiTranspose)ippiTranspose_8u_C4R : 3154 type == CV_16UC1 ? (ippiTranspose)ippiTranspose_16u_C1R : 3155 type == CV_16UC3 ? (ippiTranspose)ippiTranspose_16u_C3R : 3156 type == CV_16UC4 ? (ippiTranspose)ippiTranspose_16u_C4R : 3157 type == CV_16SC1 ? (ippiTranspose)ippiTranspose_16s_C1R : 3158 type == CV_16SC3 ? (ippiTranspose)ippiTranspose_16s_C3R : 3159 type == CV_16SC4 ? (ippiTranspose)ippiTranspose_16s_C4R : 3160 type == CV_32SC1 ? (ippiTranspose)ippiTranspose_32s_C1R : 3161 type == CV_32SC3 ? (ippiTranspose)ippiTranspose_32s_C3R : 3162 type == CV_32SC4 ? (ippiTranspose)ippiTranspose_32s_C4R : 3163 type == CV_32FC1 ? (ippiTranspose)ippiTranspose_32f_C1R : 3164 type == CV_32FC3 ? (ippiTranspose)ippiTranspose_32f_C3R : 3165 type == CV_32FC4 ? (ippiTranspose)ippiTranspose_32f_C4R : 0; 3166 } 3167 3168 IppiSize roiSize = { src.cols, src.rows }; 3169 if (ippFunc != 0) 3170 { 3171 if (ippFunc(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize) >= 0) 3172 { 3173 CV_IMPL_ADD(CV_IMPL_IPP); 3174 return; 3175 } 3176 setIppErrorStatus(); 3177 } 3178 else if (ippFuncI != 0) 3179 { 3180 if (ippFuncI(dst.ptr(), (int)dst.step, roiSize) >= 0) 3181 { 3182 CV_IMPL_ADD(CV_IMPL_IPP); 3183 return; 3184 } 3185 setIppErrorStatus(); 3186 } 3187 } 3188#endif 3189 3190 if( dst.data == src.data ) 3191 { 3192 TransposeInplaceFunc func = transposeInplaceTab[esz]; 3193 CV_Assert( func != 0 ); 3194 CV_Assert( dst.cols == dst.rows ); 3195 func( dst.ptr(), dst.step, dst.rows ); 3196 } 3197 else 3198 { 3199 TransposeFunc func = transposeTab[esz]; 3200 CV_Assert( func != 0 ); 3201 func( src.ptr(), src.step, dst.ptr(), dst.step, src.size() ); 3202 } 3203} 3204 3205 3206////////////////////////////////////// completeSymm ///////////////////////////////////////// 3207 3208void cv::completeSymm( InputOutputArray _m, bool LtoR ) 3209{ 3210 Mat m = _m.getMat(); 3211 size_t step = m.step, esz = m.elemSize(); 3212 CV_Assert( m.dims <= 2 && m.rows == m.cols ); 3213 3214 int rows = m.rows; 3215 int j0 = 0, j1 = rows; 3216 3217 uchar* data = m.ptr(); 3218 for( int i = 0; i < rows; i++ ) 3219 { 3220 if( !LtoR ) j1 = i; else j0 = i+1; 3221 for( int j = j0; j < j1; j++ ) 3222 memcpy(data + (i*step + j*esz), data + (j*step + i*esz), esz); 3223 } 3224} 3225 3226 3227cv::Mat cv::Mat::cross(InputArray _m) const 3228{ 3229 Mat m = _m.getMat(); 3230 int tp = type(), d = CV_MAT_DEPTH(tp); 3231 CV_Assert( dims <= 2 && m.dims <= 2 && size() == m.size() && tp == m.type() && 3232 ((rows == 3 && cols == 1) || (cols*channels() == 3 && rows == 1))); 3233 Mat result(rows, cols, tp); 3234 3235 if( d == CV_32F ) 3236 { 3237 const float *a = (const float*)data, *b = (const float*)m.data; 3238 float* c = (float*)result.data; 3239 size_t lda = rows > 1 ? step/sizeof(a[0]) : 1; 3240 size_t ldb = rows > 1 ? m.step/sizeof(b[0]) : 1; 3241 3242 c[0] = a[lda] * b[ldb*2] - a[lda*2] * b[ldb]; 3243 c[1] = a[lda*2] * b[0] - a[0] * b[ldb*2]; 3244 c[2] = a[0] * b[ldb] - a[lda] * b[0]; 3245 } 3246 else if( d == CV_64F ) 3247 { 3248 const double *a = (const double*)data, *b = (const double*)m.data; 3249 double* c = (double*)result.data; 3250 size_t lda = rows > 1 ? step/sizeof(a[0]) : 1; 3251 size_t ldb = rows > 1 ? m.step/sizeof(b[0]) : 1; 3252 3253 c[0] = a[lda] * b[ldb*2] - a[lda*2] * b[ldb]; 3254 c[1] = a[lda*2] * b[0] - a[0] * b[ldb*2]; 3255 c[2] = a[0] * b[ldb] - a[lda] * b[0]; 3256 } 3257 3258 return result; 3259} 3260 3261 3262////////////////////////////////////////// reduce //////////////////////////////////////////// 3263 3264namespace cv 3265{ 3266 3267template<typename T, typename ST, class Op> static void 3268reduceR_( const Mat& srcmat, Mat& dstmat ) 3269{ 3270 typedef typename Op::rtype WT; 3271 Size size = srcmat.size(); 3272 size.width *= srcmat.channels(); 3273 AutoBuffer<WT> buffer(size.width); 3274 WT* buf = buffer; 3275 ST* dst = dstmat.ptr<ST>(); 3276 const T* src = srcmat.ptr<T>(); 3277 size_t srcstep = srcmat.step/sizeof(src[0]); 3278 int i; 3279 Op op; 3280 3281 for( i = 0; i < size.width; i++ ) 3282 buf[i] = src[i]; 3283 3284 for( ; --size.height; ) 3285 { 3286 src += srcstep; 3287 i = 0; 3288 #if CV_ENABLE_UNROLLED 3289 for(; i <= size.width - 4; i += 4 ) 3290 { 3291 WT s0, s1; 3292 s0 = op(buf[i], (WT)src[i]); 3293 s1 = op(buf[i+1], (WT)src[i+1]); 3294 buf[i] = s0; buf[i+1] = s1; 3295 3296 s0 = op(buf[i+2], (WT)src[i+2]); 3297 s1 = op(buf[i+3], (WT)src[i+3]); 3298 buf[i+2] = s0; buf[i+3] = s1; 3299 } 3300 #endif 3301 for( ; i < size.width; i++ ) 3302 buf[i] = op(buf[i], (WT)src[i]); 3303 } 3304 3305 for( i = 0; i < size.width; i++ ) 3306 dst[i] = (ST)buf[i]; 3307} 3308 3309 3310template<typename T, typename ST, class Op> static void 3311reduceC_( const Mat& srcmat, Mat& dstmat ) 3312{ 3313 typedef typename Op::rtype WT; 3314 Size size = srcmat.size(); 3315 int i, k, cn = srcmat.channels(); 3316 size.width *= cn; 3317 Op op; 3318 3319 for( int y = 0; y < size.height; y++ ) 3320 { 3321 const T* src = srcmat.ptr<T>(y); 3322 ST* dst = dstmat.ptr<ST>(y); 3323 if( size.width == cn ) 3324 for( k = 0; k < cn; k++ ) 3325 dst[k] = src[k]; 3326 else 3327 { 3328 for( k = 0; k < cn; k++ ) 3329 { 3330 WT a0 = src[k], a1 = src[k+cn]; 3331 for( i = 2*cn; i <= size.width - 4*cn; i += 4*cn ) 3332 { 3333 a0 = op(a0, (WT)src[i+k]); 3334 a1 = op(a1, (WT)src[i+k+cn]); 3335 a0 = op(a0, (WT)src[i+k+cn*2]); 3336 a1 = op(a1, (WT)src[i+k+cn*3]); 3337 } 3338 3339 for( ; i < size.width; i += cn ) 3340 { 3341 a0 = op(a0, (WT)src[i+k]); 3342 } 3343 a0 = op(a0, a1); 3344 dst[k] = (ST)a0; 3345 } 3346 } 3347 } 3348} 3349 3350typedef void (*ReduceFunc)( const Mat& src, Mat& dst ); 3351 3352} 3353 3354#define reduceSumR8u32s reduceR_<uchar, int, OpAdd<int> > 3355#define reduceSumR8u32f reduceR_<uchar, float, OpAdd<int> > 3356#define reduceSumR8u64f reduceR_<uchar, double,OpAdd<int> > 3357#define reduceSumR16u32f reduceR_<ushort,float, OpAdd<float> > 3358#define reduceSumR16u64f reduceR_<ushort,double,OpAdd<double> > 3359#define reduceSumR16s32f reduceR_<short, float, OpAdd<float> > 3360#define reduceSumR16s64f reduceR_<short, double,OpAdd<double> > 3361#define reduceSumR32f32f reduceR_<float, float, OpAdd<float> > 3362#define reduceSumR32f64f reduceR_<float, double,OpAdd<double> > 3363#define reduceSumR64f64f reduceR_<double,double,OpAdd<double> > 3364 3365#define reduceMaxR8u reduceR_<uchar, uchar, OpMax<uchar> > 3366#define reduceMaxR16u reduceR_<ushort,ushort,OpMax<ushort> > 3367#define reduceMaxR16s reduceR_<short, short, OpMax<short> > 3368#define reduceMaxR32f reduceR_<float, float, OpMax<float> > 3369#define reduceMaxR64f reduceR_<double,double,OpMax<double> > 3370 3371#define reduceMinR8u reduceR_<uchar, uchar, OpMin<uchar> > 3372#define reduceMinR16u reduceR_<ushort,ushort,OpMin<ushort> > 3373#define reduceMinR16s reduceR_<short, short, OpMin<short> > 3374#define reduceMinR32f reduceR_<float, float, OpMin<float> > 3375#define reduceMinR64f reduceR_<double,double,OpMin<double> > 3376 3377#if IPP_VERSION_X100 > 0 3378 3379static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat) 3380{ 3381 cv::Size size = srcmat.size(); 3382 IppiSize roisize = { size.width, 1 }; 3383 int sstep = (int)srcmat.step, stype = srcmat.type(), 3384 sdepth = CV_MAT_DEPTH(stype), ddepth = dstmat.depth(); 3385 3386 typedef IppStatus (CV_STDCALL * ippiSum)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum); 3387 typedef IppStatus (CV_STDCALL * ippiSumHint)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum, IppHintAlgorithm hint); 3388 ippiSum ippFunc = 0; 3389 ippiSumHint ippFuncHint = 0; 3390 cv::ReduceFunc func = 0; 3391 3392 if (ddepth == CV_64F) 3393 { 3394 ippFunc = 3395 stype == CV_8UC1 ? (ippiSum)ippiSum_8u_C1R : 3396 stype == CV_8UC3 ? (ippiSum)ippiSum_8u_C3R : 3397 stype == CV_8UC4 ? (ippiSum)ippiSum_8u_C4R : 3398 stype == CV_16UC1 ? (ippiSum)ippiSum_16u_C1R : 3399 stype == CV_16UC3 ? (ippiSum)ippiSum_16u_C3R : 3400 stype == CV_16UC4 ? (ippiSum)ippiSum_16u_C4R : 3401 stype == CV_16SC1 ? (ippiSum)ippiSum_16s_C1R : 3402 stype == CV_16SC3 ? (ippiSum)ippiSum_16s_C3R : 3403 stype == CV_16SC4 ? (ippiSum)ippiSum_16s_C4R : 0; 3404 ippFuncHint = 3405 stype == CV_32FC1 ? (ippiSumHint)ippiSum_32f_C1R : 3406 stype == CV_32FC3 ? (ippiSumHint)ippiSum_32f_C3R : 3407 stype == CV_32FC4 ? (ippiSumHint)ippiSum_32f_C4R : 0; 3408 func = 3409 sdepth == CV_8U ? (cv::ReduceFunc)cv::reduceC_<uchar, double, cv::OpAdd<double> > : 3410 sdepth == CV_16U ? (cv::ReduceFunc)cv::reduceC_<ushort, double, cv::OpAdd<double> > : 3411 sdepth == CV_16S ? (cv::ReduceFunc)cv::reduceC_<short, double, cv::OpAdd<double> > : 3412 sdepth == CV_32F ? (cv::ReduceFunc)cv::reduceC_<float, double, cv::OpAdd<double> > : 0; 3413 } 3414 CV_Assert(!(ippFunc && ippFuncHint) && func); 3415 3416 CV_IPP_CHECK() 3417 { 3418 if (ippFunc) 3419 { 3420 for (int y = 0; y < size.height; ++y) 3421 if (ippFunc(srcmat.ptr(y), sstep, roisize, dstmat.ptr<Ipp64f>(y)) < 0) 3422 { 3423 setIppErrorStatus(); 3424 cv::Mat dstroi = dstmat.rowRange(y, y + 1); 3425 func(srcmat.rowRange(y, y + 1), dstroi); 3426 } 3427 CV_IMPL_ADD(CV_IMPL_IPP); 3428 return; 3429 } 3430 else if (ippFuncHint) 3431 { 3432 for (int y = 0; y < size.height; ++y) 3433 if (ippFuncHint(srcmat.ptr(y), sstep, roisize, dstmat.ptr<Ipp64f>(y), ippAlgHintAccurate) < 0) 3434 { 3435 setIppErrorStatus(); 3436 cv::Mat dstroi = dstmat.rowRange(y, y + 1); 3437 func(srcmat.rowRange(y, y + 1), dstroi); 3438 } 3439 CV_IMPL_ADD(CV_IMPL_IPP); 3440 return; 3441 } 3442 } 3443 3444 func(srcmat, dstmat); 3445} 3446 3447#endif 3448 3449#define reduceSumC8u32s reduceC_<uchar, int, OpAdd<int> > 3450#define reduceSumC8u32f reduceC_<uchar, float, OpAdd<int> > 3451#define reduceSumC16u32f reduceC_<ushort,float, OpAdd<float> > 3452#define reduceSumC16s32f reduceC_<short, float, OpAdd<float> > 3453#define reduceSumC32f32f reduceC_<float, float, OpAdd<float> > 3454#define reduceSumC64f64f reduceC_<double,double,OpAdd<double> > 3455 3456#if IPP_VERSION_X100 > 0 3457#define reduceSumC8u64f reduceSumC_8u16u16s32f_64f 3458#define reduceSumC16u64f reduceSumC_8u16u16s32f_64f 3459#define reduceSumC16s64f reduceSumC_8u16u16s32f_64f 3460#define reduceSumC32f64f reduceSumC_8u16u16s32f_64f 3461#else 3462#define reduceSumC8u64f reduceC_<uchar, double,OpAdd<int> > 3463#define reduceSumC16u64f reduceC_<ushort,double,OpAdd<double> > 3464#define reduceSumC16s64f reduceC_<short, double,OpAdd<double> > 3465#define reduceSumC32f64f reduceC_<float, double,OpAdd<double> > 3466#endif 3467 3468#if IPP_VERSION_X100 > 0 3469#define REDUCE_OP(favor, optype, type1, type2) \ 3470static inline void reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \ 3471{ \ 3472 typedef Ipp##favor IppType; \ 3473 cv::Size size = srcmat.size(); \ 3474 IppiSize roisize = ippiSize(size.width, 1);\ 3475 int sstep = (int)srcmat.step; \ 3476 \ 3477 if (CV_IPP_CHECK_COND && (srcmat.channels() == 1)) \ 3478 { \ 3479 for (int y = 0; y < size.height; ++y) \ 3480 if (ippi##optype##_##favor##_C1R(srcmat.ptr<IppType>(y), sstep, roisize, dstmat.ptr<IppType>(y)) < 0) \ 3481 { \ 3482 setIppErrorStatus(); \ 3483 cv::Mat dstroi = dstmat.rowRange(y, y + 1); \ 3484 cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat.rowRange(y, y + 1), dstroi); \ 3485 } \ 3486 else \ 3487 { \ 3488 CV_IMPL_ADD(CV_IMPL_IPP);\ 3489 } \ 3490 return; \ 3491 } \ 3492 cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat, dstmat); \ 3493} 3494#endif 3495 3496#if IPP_VERSION_X100 > 0 3497REDUCE_OP(8u, Max, uchar, uchar) 3498REDUCE_OP(16u, Max, ushort, ushort) 3499REDUCE_OP(16s, Max, short, short) 3500REDUCE_OP(32f, Max, float, float) 3501#else 3502#define reduceMaxC8u reduceC_<uchar, uchar, OpMax<uchar> > 3503#define reduceMaxC16u reduceC_<ushort,ushort,OpMax<ushort> > 3504#define reduceMaxC16s reduceC_<short, short, OpMax<short> > 3505#define reduceMaxC32f reduceC_<float, float, OpMax<float> > 3506#endif 3507#define reduceMaxC64f reduceC_<double,double,OpMax<double> > 3508 3509#if IPP_VERSION_X100 > 0 3510REDUCE_OP(8u, Min, uchar, uchar) 3511REDUCE_OP(16u, Min, ushort, ushort) 3512REDUCE_OP(16s, Min, short, short) 3513REDUCE_OP(32f, Min, float, float) 3514#else 3515#define reduceMinC8u reduceC_<uchar, uchar, OpMin<uchar> > 3516#define reduceMinC16u reduceC_<ushort,ushort,OpMin<ushort> > 3517#define reduceMinC16s reduceC_<short, short, OpMin<short> > 3518#define reduceMinC32f reduceC_<float, float, OpMin<float> > 3519#endif 3520#define reduceMinC64f reduceC_<double,double,OpMin<double> > 3521 3522#ifdef HAVE_OPENCL 3523 3524namespace cv { 3525 3526static bool ocl_reduce(InputArray _src, OutputArray _dst, 3527 int dim, int op, int op0, int stype, int dtype) 3528{ 3529 const int min_opt_cols = 128, buf_cols = 32; 3530 int sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype), 3531 ddepth = CV_MAT_DEPTH(dtype), ddepth0 = ddepth; 3532 const ocl::Device &defDev = ocl::Device::getDefault(); 3533 bool doubleSupport = defDev.doubleFPConfig() > 0; 3534 3535 size_t wgs = defDev.maxWorkGroupSize(); 3536 bool useOptimized = 1 == dim && _src.cols() > min_opt_cols && (wgs >= buf_cols); 3537 3538 if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F)) 3539 return false; 3540 3541 if (op == CV_REDUCE_AVG) 3542 { 3543 if (sdepth < CV_32S && ddepth < CV_32S) 3544 ddepth = CV_32S; 3545 } 3546 3547 const char * const ops[4] = { "OCL_CV_REDUCE_SUM", "OCL_CV_REDUCE_AVG", 3548 "OCL_CV_REDUCE_MAX", "OCL_CV_REDUCE_MIN" }; 3549 int wdepth = std::max(ddepth, CV_32F); 3550 if (useOptimized) 3551 { 3552 size_t tileHeight = (size_t)(wgs / buf_cols); 3553 if (defDev.isIntel()) 3554 { 3555 static const size_t maxItemInGroupCount = 16; 3556 tileHeight = min(tileHeight, defDev.localMemSize() / buf_cols / CV_ELEM_SIZE(CV_MAKETYPE(wdepth, cn)) / maxItemInGroupCount); 3557 } 3558 char cvt[3][40]; 3559 cv::String build_opt = format("-D OP_REDUCE_PRE -D BUF_COLS=%d -D TILE_HEIGHT=%d -D %s -D dim=1" 3560 " -D cn=%d -D ddepth=%d" 3561 " -D srcT=%s -D bufT=%s -D dstT=%s" 3562 " -D convertToWT=%s -D convertToBufT=%s -D convertToDT=%s%s", 3563 buf_cols, tileHeight, ops[op], cn, ddepth, 3564 ocl::typeToStr(sdepth), 3565 ocl::typeToStr(ddepth), 3566 ocl::typeToStr(ddepth0), 3567 ocl::convertTypeStr(ddepth, wdepth, 1, cvt[0]), 3568 ocl::convertTypeStr(sdepth, ddepth, 1, cvt[1]), 3569 ocl::convertTypeStr(wdepth, ddepth0, 1, cvt[2]), 3570 doubleSupport ? " -D DOUBLE_SUPPORT" : ""); 3571 ocl::Kernel k("reduce_horz_opt", ocl::core::reduce2_oclsrc, build_opt); 3572 if (k.empty()) 3573 return false; 3574 UMat src = _src.getUMat(); 3575 Size dsize(1, src.rows); 3576 _dst.create(dsize, dtype); 3577 UMat dst = _dst.getUMat(); 3578 3579 if (op0 == CV_REDUCE_AVG) 3580 k.args(ocl::KernelArg::ReadOnly(src), 3581 ocl::KernelArg::WriteOnlyNoSize(dst), 1.0f / src.cols); 3582 else 3583 k.args(ocl::KernelArg::ReadOnly(src), 3584 ocl::KernelArg::WriteOnlyNoSize(dst)); 3585 3586 size_t localSize[2] = { buf_cols, tileHeight}; 3587 size_t globalSize[2] = { buf_cols, src.rows }; 3588 return k.run(2, globalSize, localSize, false); 3589 } 3590 else 3591 { 3592 char cvt[2][40]; 3593 cv::String build_opt = format("-D %s -D dim=%d -D cn=%d -D ddepth=%d" 3594 " -D srcT=%s -D dstT=%s -D dstT0=%s -D convertToWT=%s" 3595 " -D convertToDT=%s -D convertToDT0=%s%s", 3596 ops[op], dim, cn, ddepth, ocl::typeToStr(useOptimized ? ddepth : sdepth), 3597 ocl::typeToStr(ddepth), ocl::typeToStr(ddepth0), 3598 ocl::convertTypeStr(ddepth, wdepth, 1, cvt[0]), 3599 ocl::convertTypeStr(sdepth, ddepth, 1, cvt[0]), 3600 ocl::convertTypeStr(wdepth, ddepth0, 1, cvt[1]), 3601 doubleSupport ? " -D DOUBLE_SUPPORT" : ""); 3602 3603 ocl::Kernel k("reduce", ocl::core::reduce2_oclsrc, build_opt); 3604 if (k.empty()) 3605 return false; 3606 3607 UMat src = _src.getUMat(); 3608 Size dsize(dim == 0 ? src.cols : 1, dim == 0 ? 1 : src.rows); 3609 _dst.create(dsize, dtype); 3610 UMat dst = _dst.getUMat(); 3611 3612 ocl::KernelArg srcarg = ocl::KernelArg::ReadOnly(src), 3613 temparg = ocl::KernelArg::WriteOnlyNoSize(dst); 3614 3615 if (op0 == CV_REDUCE_AVG) 3616 k.args(srcarg, temparg, 1.0f / (dim == 0 ? src.rows : src.cols)); 3617 else 3618 k.args(srcarg, temparg); 3619 3620 size_t globalsize = std::max(dsize.width, dsize.height); 3621 return k.run(1, &globalsize, NULL, false); 3622 } 3623} 3624 3625} 3626 3627#endif 3628 3629void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype) 3630{ 3631 CV_Assert( _src.dims() <= 2 ); 3632 int op0 = op; 3633 int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); 3634 if( dtype < 0 ) 3635 dtype = _dst.fixedType() ? _dst.type() : stype; 3636 dtype = CV_MAKETYPE(dtype >= 0 ? dtype : stype, cn); 3637 int ddepth = CV_MAT_DEPTH(dtype); 3638 3639 CV_Assert( cn == CV_MAT_CN(dtype) ); 3640 CV_Assert( op == CV_REDUCE_SUM || op == CV_REDUCE_MAX || 3641 op == CV_REDUCE_MIN || op == CV_REDUCE_AVG ); 3642 3643 CV_OCL_RUN(_dst.isUMat(), 3644 ocl_reduce(_src, _dst, dim, op, op0, stype, dtype)) 3645 3646 Mat src = _src.getMat(); 3647 _dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1, dtype); 3648 Mat dst = _dst.getMat(), temp = dst; 3649 3650 if( op == CV_REDUCE_AVG ) 3651 { 3652 op = CV_REDUCE_SUM; 3653 if( sdepth < CV_32S && ddepth < CV_32S ) 3654 { 3655 temp.create(dst.rows, dst.cols, CV_32SC(cn)); 3656 ddepth = CV_32S; 3657 } 3658 } 3659 3660 ReduceFunc func = 0; 3661 if( dim == 0 ) 3662 { 3663 if( op == CV_REDUCE_SUM ) 3664 { 3665 if(sdepth == CV_8U && ddepth == CV_32S) 3666 func = GET_OPTIMIZED(reduceSumR8u32s); 3667 else if(sdepth == CV_8U && ddepth == CV_32F) 3668 func = reduceSumR8u32f; 3669 else if(sdepth == CV_8U && ddepth == CV_64F) 3670 func = reduceSumR8u64f; 3671 else if(sdepth == CV_16U && ddepth == CV_32F) 3672 func = reduceSumR16u32f; 3673 else if(sdepth == CV_16U && ddepth == CV_64F) 3674 func = reduceSumR16u64f; 3675 else if(sdepth == CV_16S && ddepth == CV_32F) 3676 func = reduceSumR16s32f; 3677 else if(sdepth == CV_16S && ddepth == CV_64F) 3678 func = reduceSumR16s64f; 3679 else if(sdepth == CV_32F && ddepth == CV_32F) 3680 func = GET_OPTIMIZED(reduceSumR32f32f); 3681 else if(sdepth == CV_32F && ddepth == CV_64F) 3682 func = reduceSumR32f64f; 3683 else if(sdepth == CV_64F && ddepth == CV_64F) 3684 func = reduceSumR64f64f; 3685 } 3686 else if(op == CV_REDUCE_MAX) 3687 { 3688 if(sdepth == CV_8U && ddepth == CV_8U) 3689 func = GET_OPTIMIZED(reduceMaxR8u); 3690 else if(sdepth == CV_16U && ddepth == CV_16U) 3691 func = reduceMaxR16u; 3692 else if(sdepth == CV_16S && ddepth == CV_16S) 3693 func = reduceMaxR16s; 3694 else if(sdepth == CV_32F && ddepth == CV_32F) 3695 func = GET_OPTIMIZED(reduceMaxR32f); 3696 else if(sdepth == CV_64F && ddepth == CV_64F) 3697 func = reduceMaxR64f; 3698 } 3699 else if(op == CV_REDUCE_MIN) 3700 { 3701 if(sdepth == CV_8U && ddepth == CV_8U) 3702 func = GET_OPTIMIZED(reduceMinR8u); 3703 else if(sdepth == CV_16U && ddepth == CV_16U) 3704 func = reduceMinR16u; 3705 else if(sdepth == CV_16S && ddepth == CV_16S) 3706 func = reduceMinR16s; 3707 else if(sdepth == CV_32F && ddepth == CV_32F) 3708 func = GET_OPTIMIZED(reduceMinR32f); 3709 else if(sdepth == CV_64F && ddepth == CV_64F) 3710 func = reduceMinR64f; 3711 } 3712 } 3713 else 3714 { 3715 if(op == CV_REDUCE_SUM) 3716 { 3717 if(sdepth == CV_8U && ddepth == CV_32S) 3718 func = GET_OPTIMIZED(reduceSumC8u32s); 3719 else if(sdepth == CV_8U && ddepth == CV_32F) 3720 func = reduceSumC8u32f; 3721 else if(sdepth == CV_8U && ddepth == CV_64F) 3722 func = reduceSumC8u64f; 3723 else if(sdepth == CV_16U && ddepth == CV_32F) 3724 func = reduceSumC16u32f; 3725 else if(sdepth == CV_16U && ddepth == CV_64F) 3726 func = reduceSumC16u64f; 3727 else if(sdepth == CV_16S && ddepth == CV_32F) 3728 func = reduceSumC16s32f; 3729 else if(sdepth == CV_16S && ddepth == CV_64F) 3730 func = reduceSumC16s64f; 3731 else if(sdepth == CV_32F && ddepth == CV_32F) 3732 func = GET_OPTIMIZED(reduceSumC32f32f); 3733 else if(sdepth == CV_32F && ddepth == CV_64F) 3734 func = reduceSumC32f64f; 3735 else if(sdepth == CV_64F && ddepth == CV_64F) 3736 func = reduceSumC64f64f; 3737 } 3738 else if(op == CV_REDUCE_MAX) 3739 { 3740 if(sdepth == CV_8U && ddepth == CV_8U) 3741 func = GET_OPTIMIZED(reduceMaxC8u); 3742 else if(sdepth == CV_16U && ddepth == CV_16U) 3743 func = reduceMaxC16u; 3744 else if(sdepth == CV_16S && ddepth == CV_16S) 3745 func = reduceMaxC16s; 3746 else if(sdepth == CV_32F && ddepth == CV_32F) 3747 func = GET_OPTIMIZED(reduceMaxC32f); 3748 else if(sdepth == CV_64F && ddepth == CV_64F) 3749 func = reduceMaxC64f; 3750 } 3751 else if(op == CV_REDUCE_MIN) 3752 { 3753 if(sdepth == CV_8U && ddepth == CV_8U) 3754 func = GET_OPTIMIZED(reduceMinC8u); 3755 else if(sdepth == CV_16U && ddepth == CV_16U) 3756 func = reduceMinC16u; 3757 else if(sdepth == CV_16S && ddepth == CV_16S) 3758 func = reduceMinC16s; 3759 else if(sdepth == CV_32F && ddepth == CV_32F) 3760 func = GET_OPTIMIZED(reduceMinC32f); 3761 else if(sdepth == CV_64F && ddepth == CV_64F) 3762 func = reduceMinC64f; 3763 } 3764 } 3765 3766 if( !func ) 3767 CV_Error( CV_StsUnsupportedFormat, 3768 "Unsupported combination of input and output array formats" ); 3769 3770 func( src, temp ); 3771 3772 if( op0 == CV_REDUCE_AVG ) 3773 temp.convertTo(dst, dst.type(), 1./(dim == 0 ? src.rows : src.cols)); 3774} 3775 3776 3777//////////////////////////////////////// sort /////////////////////////////////////////// 3778 3779namespace cv 3780{ 3781 3782#if IPP_VERSION_X100 > 0 3783#define USE_IPP_SORT 3784 3785typedef IppStatus (CV_STDCALL * IppSortFunc)(void *, int); 3786typedef IppSortFunc IppFlipFunc; 3787 3788static IppSortFunc getSortFunc(int depth, bool sortDescending) 3789{ 3790 if (!sortDescending) 3791 return depth == CV_8U ? (IppSortFunc)ippsSortAscend_8u_I : 3792 /*depth == CV_16U ? (IppSortFunc)ippsSortAscend_16u_I : 3793 depth == CV_16S ? (IppSortFunc)ippsSortAscend_16s_I : 3794 depth == CV_32S ? (IppSortFunc)ippsSortAscend_32s_I : 3795 depth == CV_32F ? (IppSortFunc)ippsSortAscend_32f_I : 3796 depth == CV_64F ? (IppSortFunc)ippsSortAscend_64f_I :*/ 0; 3797 else 3798 return depth == CV_8U ? (IppSortFunc)ippsSortDescend_8u_I : 3799 /*depth == CV_16U ? (IppSortFunc)ippsSortDescend_16u_I : 3800 depth == CV_16S ? (IppSortFunc)ippsSortDescend_16s_I : 3801 depth == CV_32S ? (IppSortFunc)ippsSortDescend_32s_I : 3802 depth == CV_32F ? (IppSortFunc)ippsSortDescend_32f_I : 3803 depth == CV_64F ? (IppSortFunc)ippsSortDescend_64f_I :*/ 0; 3804} 3805 3806static IppFlipFunc getFlipFunc(int depth) 3807{ 3808 CV_SUPPRESS_DEPRECATED_START 3809 return 3810 depth == CV_8U || depth == CV_8S ? (IppFlipFunc)ippsFlip_8u_I : 3811 depth == CV_16U || depth == CV_16S ? (IppFlipFunc)ippsFlip_16u_I : 3812 depth == CV_32S || depth == CV_32F ? (IppFlipFunc)ippsFlip_32f_I : 3813 depth == CV_64F ? (IppFlipFunc)ippsFlip_64f_I : 0; 3814 CV_SUPPRESS_DEPRECATED_END 3815} 3816 3817 3818#endif 3819 3820template<typename T> static void sort_( const Mat& src, Mat& dst, int flags ) 3821{ 3822 AutoBuffer<T> buf; 3823 T* bptr; 3824 int i, j, n, len; 3825 bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW; 3826 bool inplace = src.data == dst.data; 3827 bool sortDescending = (flags & CV_SORT_DESCENDING) != 0; 3828 3829 if( sortRows ) 3830 n = src.rows, len = src.cols; 3831 else 3832 { 3833 n = src.cols, len = src.rows; 3834 buf.allocate(len); 3835 } 3836 bptr = (T*)buf; 3837 3838#ifdef USE_IPP_SORT 3839 int depth = src.depth(); 3840 IppSortFunc ippSortFunc = 0; 3841 IppFlipFunc ippFlipFunc = 0; 3842 CV_IPP_CHECK() 3843 { 3844 ippSortFunc = getSortFunc(depth, sortDescending); 3845 ippFlipFunc = getFlipFunc(depth); 3846 } 3847#endif 3848 3849 for( i = 0; i < n; i++ ) 3850 { 3851 T* ptr = bptr; 3852 if( sortRows ) 3853 { 3854 T* dptr = dst.ptr<T>(i); 3855 if( !inplace ) 3856 { 3857 const T* sptr = src.ptr<T>(i); 3858 memcpy(dptr, sptr, sizeof(T) * len); 3859 } 3860 ptr = dptr; 3861 } 3862 else 3863 { 3864 for( j = 0; j < len; j++ ) 3865 ptr[j] = src.ptr<T>(j)[i]; 3866 } 3867 3868#ifdef USE_IPP_SORT 3869 if (!ippSortFunc || ippSortFunc(ptr, len) < 0) 3870#endif 3871 { 3872#ifdef USE_IPP_SORT 3873 if (depth == CV_8U) 3874 setIppErrorStatus(); 3875#endif 3876 std::sort( ptr, ptr + len ); 3877 if( sortDescending ) 3878 { 3879#ifdef USE_IPP_SORT 3880 if (!ippFlipFunc || ippFlipFunc(ptr, len) < 0) 3881#endif 3882 { 3883#ifdef USE_IPP_SORT 3884 setIppErrorStatus(); 3885#endif 3886 for( j = 0; j < len/2; j++ ) 3887 std::swap(ptr[j], ptr[len-1-j]); 3888 } 3889#ifdef USE_IPP_SORT 3890 else 3891 { 3892 CV_IMPL_ADD(CV_IMPL_IPP); 3893 } 3894#endif 3895 } 3896 } 3897#ifdef USE_IPP_SORT 3898 else 3899 { 3900 CV_IMPL_ADD(CV_IMPL_IPP); 3901 } 3902#endif 3903 3904 if( !sortRows ) 3905 for( j = 0; j < len; j++ ) 3906 dst.ptr<T>(j)[i] = ptr[j]; 3907 } 3908} 3909 3910template<typename _Tp> class LessThanIdx 3911{ 3912public: 3913 LessThanIdx( const _Tp* _arr ) : arr(_arr) {} 3914 bool operator()(int a, int b) const { return arr[a] < arr[b]; } 3915 const _Tp* arr; 3916}; 3917 3918#if defined USE_IPP_SORT && 0 3919 3920typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(void *, int *, int); 3921 3922static IppSortIndexFunc getSortIndexFunc(int depth, bool sortDescending) 3923{ 3924 if (!sortDescending) 3925 return depth == CV_8U ? (IppSortIndexFunc)ippsSortIndexAscend_8u_I : 3926 depth == CV_16U ? (IppSortIndexFunc)ippsSortIndexAscend_16u_I : 3927 depth == CV_16S ? (IppSortIndexFunc)ippsSortIndexAscend_16s_I : 3928 depth == CV_32S ? (IppSortIndexFunc)ippsSortIndexAscend_32s_I : 3929 depth == CV_32F ? (IppSortIndexFunc)ippsSortIndexAscend_32f_I : 3930 depth == CV_64F ? (IppSortIndexFunc)ippsSortIndexAscend_64f_I : 0; 3931 else 3932 return depth == CV_8U ? (IppSortIndexFunc)ippsSortIndexDescend_8u_I : 3933 depth == CV_16U ? (IppSortIndexFunc)ippsSortIndexDescend_16u_I : 3934 depth == CV_16S ? (IppSortIndexFunc)ippsSortIndexDescend_16s_I : 3935 depth == CV_32S ? (IppSortIndexFunc)ippsSortIndexDescend_32s_I : 3936 depth == CV_32F ? (IppSortIndexFunc)ippsSortIndexDescend_32f_I : 3937 depth == CV_64F ? (IppSortIndexFunc)ippsSortIndexDescend_64f_I : 0; 3938} 3939 3940#endif 3941 3942template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags ) 3943{ 3944 AutoBuffer<T> buf; 3945 AutoBuffer<int> ibuf; 3946 T* bptr; 3947 int* _iptr; 3948 int i, j, n, len; 3949 bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW; 3950 bool sortDescending = (flags & CV_SORT_DESCENDING) != 0; 3951 3952 CV_Assert( src.data != dst.data ); 3953 3954 if( sortRows ) 3955 n = src.rows, len = src.cols; 3956 else 3957 { 3958 n = src.cols, len = src.rows; 3959 buf.allocate(len); 3960 ibuf.allocate(len); 3961 } 3962 bptr = (T*)buf; 3963 _iptr = (int*)ibuf; 3964 3965#if defined USE_IPP_SORT && 0 3966 int depth = src.depth(); 3967 IppSortIndexFunc ippFunc = 0; 3968 IppFlipFunc ippFlipFunc = 0; 3969 CV_IPP_CHECK() 3970 { 3971 ippFunc = getSortIndexFunc(depth, sortDescending); 3972 ippFlipFunc = getFlipFunc(depth); 3973 } 3974#endif 3975 3976 for( i = 0; i < n; i++ ) 3977 { 3978 T* ptr = bptr; 3979 int* iptr = _iptr; 3980 3981 if( sortRows ) 3982 { 3983 ptr = (T*)(src.data + src.step*i); 3984 iptr = dst.ptr<int>(i); 3985 } 3986 else 3987 { 3988 for( j = 0; j < len; j++ ) 3989 ptr[j] = src.ptr<T>(j)[i]; 3990 } 3991 for( j = 0; j < len; j++ ) 3992 iptr[j] = j; 3993 3994#if defined USE_IPP_SORT && 0 3995 if (sortRows || !ippFunc || ippFunc(ptr, iptr, len) < 0) 3996#endif 3997 { 3998#if defined USE_IPP_SORT && 0 3999 setIppErrorStatus(); 4000#endif 4001 std::sort( iptr, iptr + len, LessThanIdx<T>(ptr) ); 4002 if( sortDescending ) 4003 { 4004#if defined USE_IPP_SORT && 0 4005 if (!ippFlipFunc || ippFlipFunc(iptr, len) < 0) 4006#endif 4007 { 4008#if defined USE_IPP_SORT && 0 4009 setIppErrorStatus(); 4010#endif 4011 for( j = 0; j < len/2; j++ ) 4012 std::swap(iptr[j], iptr[len-1-j]); 4013 } 4014#if defined USE_IPP_SORT && 0 4015 else 4016 { 4017 CV_IMPL_ADD(CV_IMPL_IPP); 4018 } 4019#endif 4020 } 4021 } 4022#if defined USE_IPP_SORT && 0 4023 else 4024 { 4025 CV_IMPL_ADD(CV_IMPL_IPP); 4026 } 4027#endif 4028 4029 if( !sortRows ) 4030 for( j = 0; j < len; j++ ) 4031 dst.ptr<int>(j)[i] = iptr[j]; 4032 } 4033} 4034 4035typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags); 4036 4037} 4038 4039void cv::sort( InputArray _src, OutputArray _dst, int flags ) 4040{ 4041 static SortFunc tab[] = 4042 { 4043 sort_<uchar>, sort_<schar>, sort_<ushort>, sort_<short>, 4044 sort_<int>, sort_<float>, sort_<double>, 0 4045 }; 4046 Mat src = _src.getMat(); 4047 SortFunc func = tab[src.depth()]; 4048 CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 ); 4049 _dst.create( src.size(), src.type() ); 4050 Mat dst = _dst.getMat(); 4051 func( src, dst, flags ); 4052} 4053 4054void cv::sortIdx( InputArray _src, OutputArray _dst, int flags ) 4055{ 4056 static SortFunc tab[] = 4057 { 4058 sortIdx_<uchar>, sortIdx_<schar>, sortIdx_<ushort>, sortIdx_<short>, 4059 sortIdx_<int>, sortIdx_<float>, sortIdx_<double>, 0 4060 }; 4061 Mat src = _src.getMat(); 4062 SortFunc func = tab[src.depth()]; 4063 CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 ); 4064 4065 Mat dst = _dst.getMat(); 4066 if( dst.data == src.data ) 4067 _dst.release(); 4068 _dst.create( src.size(), CV_32S ); 4069 dst = _dst.getMat(); 4070 func( src, dst, flags ); 4071} 4072 4073 4074CV_IMPL void cvSetIdentity( CvArr* arr, CvScalar value ) 4075{ 4076 cv::Mat m = cv::cvarrToMat(arr); 4077 cv::setIdentity(m, value); 4078} 4079 4080 4081CV_IMPL CvScalar cvTrace( const CvArr* arr ) 4082{ 4083 return cv::trace(cv::cvarrToMat(arr)); 4084} 4085 4086 4087CV_IMPL void cvTranspose( const CvArr* srcarr, CvArr* dstarr ) 4088{ 4089 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); 4090 4091 CV_Assert( src.rows == dst.cols && src.cols == dst.rows && src.type() == dst.type() ); 4092 transpose( src, dst ); 4093} 4094 4095 4096CV_IMPL void cvCompleteSymm( CvMat* matrix, int LtoR ) 4097{ 4098 cv::Mat m = cv::cvarrToMat(matrix); 4099 cv::completeSymm( m, LtoR != 0 ); 4100} 4101 4102 4103CV_IMPL void cvCrossProduct( const CvArr* srcAarr, const CvArr* srcBarr, CvArr* dstarr ) 4104{ 4105 cv::Mat srcA = cv::cvarrToMat(srcAarr), dst = cv::cvarrToMat(dstarr); 4106 4107 CV_Assert( srcA.size() == dst.size() && srcA.type() == dst.type() ); 4108 srcA.cross(cv::cvarrToMat(srcBarr)).copyTo(dst); 4109} 4110 4111 4112CV_IMPL void 4113cvReduce( const CvArr* srcarr, CvArr* dstarr, int dim, int op ) 4114{ 4115 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); 4116 4117 if( dim < 0 ) 4118 dim = src.rows > dst.rows ? 0 : src.cols > dst.cols ? 1 : dst.cols == 1; 4119 4120 if( dim > 1 ) 4121 CV_Error( CV_StsOutOfRange, "The reduced dimensionality index is out of range" ); 4122 4123 if( (dim == 0 && (dst.cols != src.cols || dst.rows != 1)) || 4124 (dim == 1 && (dst.rows != src.rows || dst.cols != 1)) ) 4125 CV_Error( CV_StsBadSize, "The output array size is incorrect" ); 4126 4127 if( src.channels() != dst.channels() ) 4128 CV_Error( CV_StsUnmatchedFormats, "Input and output arrays must have the same number of channels" ); 4129 4130 cv::reduce(src, dst, dim, op, dst.type()); 4131} 4132 4133 4134CV_IMPL CvArr* 4135cvRange( CvArr* arr, double start, double end ) 4136{ 4137 int ok = 0; 4138 4139 CvMat stub, *mat = (CvMat*)arr; 4140 double delta; 4141 int type, step; 4142 double val = start; 4143 int i, j; 4144 int rows, cols; 4145 4146 if( !CV_IS_MAT(mat) ) 4147 mat = cvGetMat( mat, &stub); 4148 4149 rows = mat->rows; 4150 cols = mat->cols; 4151 type = CV_MAT_TYPE(mat->type); 4152 delta = (end-start)/(rows*cols); 4153 4154 if( CV_IS_MAT_CONT(mat->type) ) 4155 { 4156 cols *= rows; 4157 rows = 1; 4158 step = 1; 4159 } 4160 else 4161 step = mat->step / CV_ELEM_SIZE(type); 4162 4163 if( type == CV_32SC1 ) 4164 { 4165 int* idata = mat->data.i; 4166 int ival = cvRound(val), idelta = cvRound(delta); 4167 4168 if( fabs(val - ival) < DBL_EPSILON && 4169 fabs(delta - idelta) < DBL_EPSILON ) 4170 { 4171 for( i = 0; i < rows; i++, idata += step ) 4172 for( j = 0; j < cols; j++, ival += idelta ) 4173 idata[j] = ival; 4174 } 4175 else 4176 { 4177 for( i = 0; i < rows; i++, idata += step ) 4178 for( j = 0; j < cols; j++, val += delta ) 4179 idata[j] = cvRound(val); 4180 } 4181 } 4182 else if( type == CV_32FC1 ) 4183 { 4184 float* fdata = mat->data.fl; 4185 for( i = 0; i < rows; i++, fdata += step ) 4186 for( j = 0; j < cols; j++, val += delta ) 4187 fdata[j] = (float)val; 4188 } 4189 else 4190 CV_Error( CV_StsUnsupportedFormat, "The function only supports 32sC1 and 32fC1 datatypes" ); 4191 4192 ok = 1; 4193 return ok ? arr : 0; 4194} 4195 4196 4197CV_IMPL void 4198cvSort( const CvArr* _src, CvArr* _dst, CvArr* _idx, int flags ) 4199{ 4200 cv::Mat src = cv::cvarrToMat(_src); 4201 4202 if( _idx ) 4203 { 4204 cv::Mat idx0 = cv::cvarrToMat(_idx), idx = idx0; 4205 CV_Assert( src.size() == idx.size() && idx.type() == CV_32S && src.data != idx.data ); 4206 cv::sortIdx( src, idx, flags ); 4207 CV_Assert( idx0.data == idx.data ); 4208 } 4209 4210 if( _dst ) 4211 { 4212 cv::Mat dst0 = cv::cvarrToMat(_dst), dst = dst0; 4213 CV_Assert( src.size() == dst.size() && src.type() == dst.type() ); 4214 cv::sort( src, dst, flags ); 4215 CV_Assert( dst0.data == dst.data ); 4216 } 4217} 4218 4219 4220CV_IMPL int 4221cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels, 4222 CvTermCriteria termcrit, int attempts, CvRNG*, 4223 int flags, CvArr* _centers, double* _compactness ) 4224{ 4225 cv::Mat data = cv::cvarrToMat(_samples), labels = cv::cvarrToMat(_labels), centers; 4226 if( _centers ) 4227 { 4228 centers = cv::cvarrToMat(_centers); 4229 4230 centers = centers.reshape(1); 4231 data = data.reshape(1); 4232 4233 CV_Assert( !centers.empty() ); 4234 CV_Assert( centers.rows == cluster_count ); 4235 CV_Assert( centers.cols == data.cols ); 4236 CV_Assert( centers.depth() == data.depth() ); 4237 } 4238 CV_Assert( labels.isContinuous() && labels.type() == CV_32S && 4239 (labels.cols == 1 || labels.rows == 1) && 4240 labels.cols + labels.rows - 1 == data.rows ); 4241 4242 double compactness = cv::kmeans(data, cluster_count, labels, termcrit, attempts, 4243 flags, _centers ? cv::_OutputArray(centers) : cv::_OutputArray() ); 4244 if( _compactness ) 4245 *_compactness = compactness; 4246 return 1; 4247} 4248 4249///////////////////////////// n-dimensional matrices //////////////////////////// 4250 4251namespace cv 4252{ 4253 4254Mat Mat::reshape(int _cn, int _newndims, const int* _newsz) const 4255{ 4256 if(_newndims == dims) 4257 { 4258 if(_newsz == 0) 4259 return reshape(_cn); 4260 if(_newndims == 2) 4261 return reshape(_cn, _newsz[0]); 4262 } 4263 4264 CV_Error(CV_StsNotImplemented, ""); 4265 // TBD 4266 return Mat(); 4267} 4268 4269NAryMatIterator::NAryMatIterator() 4270 : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) 4271{ 4272} 4273 4274NAryMatIterator::NAryMatIterator(const Mat** _arrays, Mat* _planes, int _narrays) 4275: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) 4276{ 4277 init(_arrays, _planes, 0, _narrays); 4278} 4279 4280NAryMatIterator::NAryMatIterator(const Mat** _arrays, uchar** _ptrs, int _narrays) 4281 : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) 4282{ 4283 init(_arrays, 0, _ptrs, _narrays); 4284} 4285 4286void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, uchar** _ptrs, int _narrays) 4287{ 4288 CV_Assert( _arrays && (_ptrs || _planes) ); 4289 int i, j, d1=0, i0 = -1, d = -1; 4290 4291 arrays = _arrays; 4292 ptrs = _ptrs; 4293 planes = _planes; 4294 narrays = _narrays; 4295 nplanes = 0; 4296 size = 0; 4297 4298 if( narrays < 0 ) 4299 { 4300 for( i = 0; _arrays[i] != 0; i++ ) 4301 ; 4302 narrays = i; 4303 CV_Assert(narrays <= 1000); 4304 } 4305 4306 iterdepth = 0; 4307 4308 for( i = 0; i < narrays; i++ ) 4309 { 4310 CV_Assert(arrays[i] != 0); 4311 const Mat& A = *arrays[i]; 4312 if( ptrs ) 4313 ptrs[i] = A.data; 4314 4315 if( !A.data ) 4316 continue; 4317 4318 if( i0 < 0 ) 4319 { 4320 i0 = i; 4321 d = A.dims; 4322 4323 // find the first dimensionality which is different from 1; 4324 // in any of the arrays the first "d1" step do not affect the continuity 4325 for( d1 = 0; d1 < d; d1++ ) 4326 if( A.size[d1] > 1 ) 4327 break; 4328 } 4329 else 4330 CV_Assert( A.size == arrays[i0]->size ); 4331 4332 if( !A.isContinuous() ) 4333 { 4334 CV_Assert( A.step[d-1] == A.elemSize() ); 4335 for( j = d-1; j > d1; j-- ) 4336 if( A.step[j]*A.size[j] < A.step[j-1] ) 4337 break; 4338 iterdepth = std::max(iterdepth, j); 4339 } 4340 } 4341 4342 if( i0 >= 0 ) 4343 { 4344 size = arrays[i0]->size[d-1]; 4345 for( j = d-1; j > iterdepth; j-- ) 4346 { 4347 int64 total1 = (int64)size*arrays[i0]->size[j-1]; 4348 if( total1 != (int)total1 ) 4349 break; 4350 size = (int)total1; 4351 } 4352 4353 iterdepth = j; 4354 if( iterdepth == d1 ) 4355 iterdepth = 0; 4356 4357 nplanes = 1; 4358 for( j = iterdepth-1; j >= 0; j-- ) 4359 nplanes *= arrays[i0]->size[j]; 4360 } 4361 else 4362 iterdepth = 0; 4363 4364 idx = 0; 4365 4366 if( !planes ) 4367 return; 4368 4369 for( i = 0; i < narrays; i++ ) 4370 { 4371 CV_Assert(arrays[i] != 0); 4372 const Mat& A = *arrays[i]; 4373 4374 if( !A.data ) 4375 { 4376 planes[i] = Mat(); 4377 continue; 4378 } 4379 4380 planes[i] = Mat(1, (int)size, A.type(), A.data); 4381 } 4382} 4383 4384 4385NAryMatIterator& NAryMatIterator::operator ++() 4386{ 4387 if( idx >= nplanes-1 ) 4388 return *this; 4389 ++idx; 4390 4391 if( iterdepth == 1 ) 4392 { 4393 if( ptrs ) 4394 { 4395 for( int i = 0; i < narrays; i++ ) 4396 { 4397 if( !ptrs[i] ) 4398 continue; 4399 ptrs[i] = arrays[i]->data + arrays[i]->step[0]*idx; 4400 } 4401 } 4402 if( planes ) 4403 { 4404 for( int i = 0; i < narrays; i++ ) 4405 { 4406 if( !planes[i].data ) 4407 continue; 4408 planes[i].data = arrays[i]->data + arrays[i]->step[0]*idx; 4409 } 4410 } 4411 } 4412 else 4413 { 4414 for( int i = 0; i < narrays; i++ ) 4415 { 4416 const Mat& A = *arrays[i]; 4417 if( !A.data ) 4418 continue; 4419 int _idx = (int)idx; 4420 uchar* data = A.data; 4421 for( int j = iterdepth-1; j >= 0 && _idx > 0; j-- ) 4422 { 4423 int szi = A.size[j], t = _idx/szi; 4424 data += (_idx - t * szi)*A.step[j]; 4425 _idx = t; 4426 } 4427 if( ptrs ) 4428 ptrs[i] = data; 4429 if( planes ) 4430 planes[i].data = data; 4431 } 4432 } 4433 4434 return *this; 4435} 4436 4437NAryMatIterator NAryMatIterator::operator ++(int) 4438{ 4439 NAryMatIterator it = *this; 4440 ++*this; 4441 return it; 4442} 4443 4444/////////////////////////////////////////////////////////////////////////// 4445// MatConstIterator // 4446/////////////////////////////////////////////////////////////////////////// 4447 4448Point MatConstIterator::pos() const 4449{ 4450 if( !m ) 4451 return Point(); 4452 CV_DbgAssert(m->dims <= 2); 4453 4454 ptrdiff_t ofs = ptr - m->ptr(); 4455 int y = (int)(ofs/m->step[0]); 4456 return Point((int)((ofs - y*m->step[0])/elemSize), y); 4457} 4458 4459void MatConstIterator::pos(int* _idx) const 4460{ 4461 CV_Assert(m != 0 && _idx); 4462 ptrdiff_t ofs = ptr - m->ptr(); 4463 for( int i = 0; i < m->dims; i++ ) 4464 { 4465 size_t s = m->step[i], v = ofs/s; 4466 ofs -= v*s; 4467 _idx[i] = (int)v; 4468 } 4469} 4470 4471ptrdiff_t MatConstIterator::lpos() const 4472{ 4473 if(!m) 4474 return 0; 4475 if( m->isContinuous() ) 4476 return (ptr - sliceStart)/elemSize; 4477 ptrdiff_t ofs = ptr - m->ptr(); 4478 int i, d = m->dims; 4479 if( d == 2 ) 4480 { 4481 ptrdiff_t y = ofs/m->step[0]; 4482 return y*m->cols + (ofs - y*m->step[0])/elemSize; 4483 } 4484 ptrdiff_t result = 0; 4485 for( i = 0; i < d; i++ ) 4486 { 4487 size_t s = m->step[i], v = ofs/s; 4488 ofs -= v*s; 4489 result = result*m->size[i] + v; 4490 } 4491 return result; 4492} 4493 4494void MatConstIterator::seek(ptrdiff_t ofs, bool relative) 4495{ 4496 if( m->isContinuous() ) 4497 { 4498 ptr = (relative ? ptr : sliceStart) + ofs*elemSize; 4499 if( ptr < sliceStart ) 4500 ptr = sliceStart; 4501 else if( ptr > sliceEnd ) 4502 ptr = sliceEnd; 4503 return; 4504 } 4505 4506 int d = m->dims; 4507 if( d == 2 ) 4508 { 4509 ptrdiff_t ofs0, y; 4510 if( relative ) 4511 { 4512 ofs0 = ptr - m->ptr(); 4513 y = ofs0/m->step[0]; 4514 ofs += y*m->cols + (ofs0 - y*m->step[0])/elemSize; 4515 } 4516 y = ofs/m->cols; 4517 int y1 = std::min(std::max((int)y, 0), m->rows-1); 4518 sliceStart = m->ptr(y1); 4519 sliceEnd = sliceStart + m->cols*elemSize; 4520 ptr = y < 0 ? sliceStart : y >= m->rows ? sliceEnd : 4521 sliceStart + (ofs - y*m->cols)*elemSize; 4522 return; 4523 } 4524 4525 if( relative ) 4526 ofs += lpos(); 4527 4528 if( ofs < 0 ) 4529 ofs = 0; 4530 4531 int szi = m->size[d-1]; 4532 ptrdiff_t t = ofs/szi; 4533 int v = (int)(ofs - t*szi); 4534 ofs = t; 4535 ptr = m->ptr() + v*elemSize; 4536 sliceStart = m->ptr(); 4537 4538 for( int i = d-2; i >= 0; i-- ) 4539 { 4540 szi = m->size[i]; 4541 t = ofs/szi; 4542 v = (int)(ofs - t*szi); 4543 ofs = t; 4544 sliceStart += v*m->step[i]; 4545 } 4546 4547 sliceEnd = sliceStart + m->size[d-1]*elemSize; 4548 if( ofs > 0 ) 4549 ptr = sliceEnd; 4550 else 4551 ptr = sliceStart + (ptr - m->ptr()); 4552} 4553 4554void MatConstIterator::seek(const int* _idx, bool relative) 4555{ 4556 int i, d = m->dims; 4557 ptrdiff_t ofs = 0; 4558 if( !_idx ) 4559 ; 4560 else if( d == 2 ) 4561 ofs = _idx[0]*m->size[1] + _idx[1]; 4562 else 4563 { 4564 for( i = 0; i < d; i++ ) 4565 ofs = ofs*m->size[i] + _idx[i]; 4566 } 4567 seek(ofs, relative); 4568} 4569 4570//////////////////////////////// SparseMat //////////////////////////////// 4571 4572template<typename T1, typename T2> void 4573convertData_(const void* _from, void* _to, int cn) 4574{ 4575 const T1* from = (const T1*)_from; 4576 T2* to = (T2*)_to; 4577 if( cn == 1 ) 4578 *to = saturate_cast<T2>(*from); 4579 else 4580 for( int i = 0; i < cn; i++ ) 4581 to[i] = saturate_cast<T2>(from[i]); 4582} 4583 4584template<typename T1, typename T2> void 4585convertScaleData_(const void* _from, void* _to, int cn, double alpha, double beta) 4586{ 4587 const T1* from = (const T1*)_from; 4588 T2* to = (T2*)_to; 4589 if( cn == 1 ) 4590 *to = saturate_cast<T2>(*from*alpha + beta); 4591 else 4592 for( int i = 0; i < cn; i++ ) 4593 to[i] = saturate_cast<T2>(from[i]*alpha + beta); 4594} 4595 4596typedef void (*ConvertData)(const void* from, void* to, int cn); 4597typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alpha, double beta); 4598 4599static ConvertData getConvertElem(int fromType, int toType) 4600{ 4601 static ConvertData tab[][8] = 4602 {{ convertData_<uchar, uchar>, convertData_<uchar, schar>, 4603 convertData_<uchar, ushort>, convertData_<uchar, short>, 4604 convertData_<uchar, int>, convertData_<uchar, float>, 4605 convertData_<uchar, double>, 0 }, 4606 4607 { convertData_<schar, uchar>, convertData_<schar, schar>, 4608 convertData_<schar, ushort>, convertData_<schar, short>, 4609 convertData_<schar, int>, convertData_<schar, float>, 4610 convertData_<schar, double>, 0 }, 4611 4612 { convertData_<ushort, uchar>, convertData_<ushort, schar>, 4613 convertData_<ushort, ushort>, convertData_<ushort, short>, 4614 convertData_<ushort, int>, convertData_<ushort, float>, 4615 convertData_<ushort, double>, 0 }, 4616 4617 { convertData_<short, uchar>, convertData_<short, schar>, 4618 convertData_<short, ushort>, convertData_<short, short>, 4619 convertData_<short, int>, convertData_<short, float>, 4620 convertData_<short, double>, 0 }, 4621 4622 { convertData_<int, uchar>, convertData_<int, schar>, 4623 convertData_<int, ushort>, convertData_<int, short>, 4624 convertData_<int, int>, convertData_<int, float>, 4625 convertData_<int, double>, 0 }, 4626 4627 { convertData_<float, uchar>, convertData_<float, schar>, 4628 convertData_<float, ushort>, convertData_<float, short>, 4629 convertData_<float, int>, convertData_<float, float>, 4630 convertData_<float, double>, 0 }, 4631 4632 { convertData_<double, uchar>, convertData_<double, schar>, 4633 convertData_<double, ushort>, convertData_<double, short>, 4634 convertData_<double, int>, convertData_<double, float>, 4635 convertData_<double, double>, 0 }, 4636 4637 { 0, 0, 0, 0, 0, 0, 0, 0 }}; 4638 4639 ConvertData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)]; 4640 CV_Assert( func != 0 ); 4641 return func; 4642} 4643 4644static ConvertScaleData getConvertScaleElem(int fromType, int toType) 4645{ 4646 static ConvertScaleData tab[][8] = 4647 {{ convertScaleData_<uchar, uchar>, convertScaleData_<uchar, schar>, 4648 convertScaleData_<uchar, ushort>, convertScaleData_<uchar, short>, 4649 convertScaleData_<uchar, int>, convertScaleData_<uchar, float>, 4650 convertScaleData_<uchar, double>, 0 }, 4651 4652 { convertScaleData_<schar, uchar>, convertScaleData_<schar, schar>, 4653 convertScaleData_<schar, ushort>, convertScaleData_<schar, short>, 4654 convertScaleData_<schar, int>, convertScaleData_<schar, float>, 4655 convertScaleData_<schar, double>, 0 }, 4656 4657 { convertScaleData_<ushort, uchar>, convertScaleData_<ushort, schar>, 4658 convertScaleData_<ushort, ushort>, convertScaleData_<ushort, short>, 4659 convertScaleData_<ushort, int>, convertScaleData_<ushort, float>, 4660 convertScaleData_<ushort, double>, 0 }, 4661 4662 { convertScaleData_<short, uchar>, convertScaleData_<short, schar>, 4663 convertScaleData_<short, ushort>, convertScaleData_<short, short>, 4664 convertScaleData_<short, int>, convertScaleData_<short, float>, 4665 convertScaleData_<short, double>, 0 }, 4666 4667 { convertScaleData_<int, uchar>, convertScaleData_<int, schar>, 4668 convertScaleData_<int, ushort>, convertScaleData_<int, short>, 4669 convertScaleData_<int, int>, convertScaleData_<int, float>, 4670 convertScaleData_<int, double>, 0 }, 4671 4672 { convertScaleData_<float, uchar>, convertScaleData_<float, schar>, 4673 convertScaleData_<float, ushort>, convertScaleData_<float, short>, 4674 convertScaleData_<float, int>, convertScaleData_<float, float>, 4675 convertScaleData_<float, double>, 0 }, 4676 4677 { convertScaleData_<double, uchar>, convertScaleData_<double, schar>, 4678 convertScaleData_<double, ushort>, convertScaleData_<double, short>, 4679 convertScaleData_<double, int>, convertScaleData_<double, float>, 4680 convertScaleData_<double, double>, 0 }, 4681 4682 { 0, 0, 0, 0, 0, 0, 0, 0 }}; 4683 4684 ConvertScaleData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)]; 4685 CV_Assert( func != 0 ); 4686 return func; 4687} 4688 4689enum { HASH_SIZE0 = 8 }; 4690 4691static inline void copyElem(const uchar* from, uchar* to, size_t elemSize) 4692{ 4693 size_t i; 4694 for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) ) 4695 *(int*)(to + i) = *(const int*)(from + i); 4696 for( ; i < elemSize; i++ ) 4697 to[i] = from[i]; 4698} 4699 4700static inline bool isZeroElem(const uchar* data, size_t elemSize) 4701{ 4702 size_t i; 4703 for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) ) 4704 if( *(int*)(data + i) != 0 ) 4705 return false; 4706 for( ; i < elemSize; i++ ) 4707 if( data[i] != 0 ) 4708 return false; 4709 return true; 4710} 4711 4712SparseMat::Hdr::Hdr( int _dims, const int* _sizes, int _type ) 4713{ 4714 refcount = 1; 4715 4716 dims = _dims; 4717 valueOffset = (int)alignSize(sizeof(SparseMat::Node) - MAX_DIM*sizeof(int) + 4718 dims*sizeof(int), CV_ELEM_SIZE1(_type)); 4719 nodeSize = alignSize(valueOffset + 4720 CV_ELEM_SIZE(_type), (int)sizeof(size_t)); 4721 4722 int i; 4723 for( i = 0; i < dims; i++ ) 4724 size[i] = _sizes[i]; 4725 for( ; i < CV_MAX_DIM; i++ ) 4726 size[i] = 0; 4727 clear(); 4728} 4729 4730void SparseMat::Hdr::clear() 4731{ 4732 hashtab.clear(); 4733 hashtab.resize(HASH_SIZE0); 4734 pool.clear(); 4735 pool.resize(nodeSize); 4736 nodeCount = freeList = 0; 4737} 4738 4739 4740SparseMat::SparseMat(const Mat& m) 4741: flags(MAGIC_VAL), hdr(0) 4742{ 4743 create( m.dims, m.size, m.type() ); 4744 4745 int i, idx[CV_MAX_DIM] = {0}, d = m.dims, lastSize = m.size[d - 1]; 4746 size_t esz = m.elemSize(); 4747 const uchar* dptr = m.ptr(); 4748 4749 for(;;) 4750 { 4751 for( i = 0; i < lastSize; i++, dptr += esz ) 4752 { 4753 if( isZeroElem(dptr, esz) ) 4754 continue; 4755 idx[d-1] = i; 4756 uchar* to = newNode(idx, hash(idx)); 4757 copyElem( dptr, to, esz ); 4758 } 4759 4760 for( i = d - 2; i >= 0; i-- ) 4761 { 4762 dptr += m.step[i] - m.size[i+1]*m.step[i+1]; 4763 if( ++idx[i] < m.size[i] ) 4764 break; 4765 idx[i] = 0; 4766 } 4767 if( i < 0 ) 4768 break; 4769 } 4770} 4771 4772void SparseMat::create(int d, const int* _sizes, int _type) 4773{ 4774 int i; 4775 CV_Assert( _sizes && 0 < d && d <= CV_MAX_DIM ); 4776 for( i = 0; i < d; i++ ) 4777 CV_Assert( _sizes[i] > 0 ); 4778 _type = CV_MAT_TYPE(_type); 4779 if( hdr && _type == type() && hdr->dims == d && hdr->refcount == 1 ) 4780 { 4781 for( i = 0; i < d; i++ ) 4782 if( _sizes[i] != hdr->size[i] ) 4783 break; 4784 if( i == d ) 4785 { 4786 clear(); 4787 return; 4788 } 4789 } 4790 release(); 4791 flags = MAGIC_VAL | _type; 4792 hdr = new Hdr(d, _sizes, _type); 4793} 4794 4795void SparseMat::copyTo( SparseMat& m ) const 4796{ 4797 if( hdr == m.hdr ) 4798 return; 4799 if( !hdr ) 4800 { 4801 m.release(); 4802 return; 4803 } 4804 m.create( hdr->dims, hdr->size, type() ); 4805 SparseMatConstIterator from = begin(); 4806 size_t i, N = nzcount(), esz = elemSize(); 4807 4808 for( i = 0; i < N; i++, ++from ) 4809 { 4810 const Node* n = from.node(); 4811 uchar* to = m.newNode(n->idx, n->hashval); 4812 copyElem( from.ptr, to, esz ); 4813 } 4814} 4815 4816void SparseMat::copyTo( Mat& m ) const 4817{ 4818 CV_Assert( hdr ); 4819 int ndims = dims(); 4820 m.create( ndims, hdr->size, type() ); 4821 m = Scalar(0); 4822 4823 SparseMatConstIterator from = begin(); 4824 size_t i, N = nzcount(), esz = elemSize(); 4825 4826 for( i = 0; i < N; i++, ++from ) 4827 { 4828 const Node* n = from.node(); 4829 copyElem( from.ptr, (ndims > 1 ? m.ptr(n->idx) : m.ptr(n->idx[0])), esz); 4830 } 4831} 4832 4833 4834void SparseMat::convertTo( SparseMat& m, int rtype, double alpha ) const 4835{ 4836 int cn = channels(); 4837 if( rtype < 0 ) 4838 rtype = type(); 4839 rtype = CV_MAKETYPE(rtype, cn); 4840 if( hdr == m.hdr && rtype != type() ) 4841 { 4842 SparseMat temp; 4843 convertTo(temp, rtype, alpha); 4844 m = temp; 4845 return; 4846 } 4847 4848 CV_Assert(hdr != 0); 4849 if( hdr != m.hdr ) 4850 m.create( hdr->dims, hdr->size, rtype ); 4851 4852 SparseMatConstIterator from = begin(); 4853 size_t i, N = nzcount(); 4854 4855 if( alpha == 1 ) 4856 { 4857 ConvertData cvtfunc = getConvertElem(type(), rtype); 4858 for( i = 0; i < N; i++, ++from ) 4859 { 4860 const Node* n = from.node(); 4861 uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval); 4862 cvtfunc( from.ptr, to, cn ); 4863 } 4864 } 4865 else 4866 { 4867 ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype); 4868 for( i = 0; i < N; i++, ++from ) 4869 { 4870 const Node* n = from.node(); 4871 uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval); 4872 cvtfunc( from.ptr, to, cn, alpha, 0 ); 4873 } 4874 } 4875} 4876 4877 4878void SparseMat::convertTo( Mat& m, int rtype, double alpha, double beta ) const 4879{ 4880 int cn = channels(); 4881 if( rtype < 0 ) 4882 rtype = type(); 4883 rtype = CV_MAKETYPE(rtype, cn); 4884 4885 CV_Assert( hdr ); 4886 m.create( dims(), hdr->size, rtype ); 4887 m = Scalar(beta); 4888 4889 SparseMatConstIterator from = begin(); 4890 size_t i, N = nzcount(); 4891 4892 if( alpha == 1 && beta == 0 ) 4893 { 4894 ConvertData cvtfunc = getConvertElem(type(), rtype); 4895 for( i = 0; i < N; i++, ++from ) 4896 { 4897 const Node* n = from.node(); 4898 uchar* to = m.ptr(n->idx); 4899 cvtfunc( from.ptr, to, cn ); 4900 } 4901 } 4902 else 4903 { 4904 ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype); 4905 for( i = 0; i < N; i++, ++from ) 4906 { 4907 const Node* n = from.node(); 4908 uchar* to = m.ptr(n->idx); 4909 cvtfunc( from.ptr, to, cn, alpha, beta ); 4910 } 4911 } 4912} 4913 4914void SparseMat::clear() 4915{ 4916 if( hdr ) 4917 hdr->clear(); 4918} 4919 4920uchar* SparseMat::ptr(int i0, bool createMissing, size_t* hashval) 4921{ 4922 CV_Assert( hdr && hdr->dims == 1 ); 4923 size_t h = hashval ? *hashval : hash(i0); 4924 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; 4925 uchar* pool = &hdr->pool[0]; 4926 while( nidx != 0 ) 4927 { 4928 Node* elem = (Node*)(pool + nidx); 4929 if( elem->hashval == h && elem->idx[0] == i0 ) 4930 return &value<uchar>(elem); 4931 nidx = elem->next; 4932 } 4933 4934 if( createMissing ) 4935 { 4936 int idx[] = { i0 }; 4937 return newNode( idx, h ); 4938 } 4939 return 0; 4940} 4941 4942uchar* SparseMat::ptr(int i0, int i1, bool createMissing, size_t* hashval) 4943{ 4944 CV_Assert( hdr && hdr->dims == 2 ); 4945 size_t h = hashval ? *hashval : hash(i0, i1); 4946 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; 4947 uchar* pool = &hdr->pool[0]; 4948 while( nidx != 0 ) 4949 { 4950 Node* elem = (Node*)(pool + nidx); 4951 if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 ) 4952 return &value<uchar>(elem); 4953 nidx = elem->next; 4954 } 4955 4956 if( createMissing ) 4957 { 4958 int idx[] = { i0, i1 }; 4959 return newNode( idx, h ); 4960 } 4961 return 0; 4962} 4963 4964uchar* SparseMat::ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval) 4965{ 4966 CV_Assert( hdr && hdr->dims == 3 ); 4967 size_t h = hashval ? *hashval : hash(i0, i1, i2); 4968 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; 4969 uchar* pool = &hdr->pool[0]; 4970 while( nidx != 0 ) 4971 { 4972 Node* elem = (Node*)(pool + nidx); 4973 if( elem->hashval == h && elem->idx[0] == i0 && 4974 elem->idx[1] == i1 && elem->idx[2] == i2 ) 4975 return &value<uchar>(elem); 4976 nidx = elem->next; 4977 } 4978 4979 if( createMissing ) 4980 { 4981 int idx[] = { i0, i1, i2 }; 4982 return newNode( idx, h ); 4983 } 4984 return 0; 4985} 4986 4987uchar* SparseMat::ptr(const int* idx, bool createMissing, size_t* hashval) 4988{ 4989 CV_Assert( hdr ); 4990 int i, d = hdr->dims; 4991 size_t h = hashval ? *hashval : hash(idx); 4992 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; 4993 uchar* pool = &hdr->pool[0]; 4994 while( nidx != 0 ) 4995 { 4996 Node* elem = (Node*)(pool + nidx); 4997 if( elem->hashval == h ) 4998 { 4999 for( i = 0; i < d; i++ ) 5000 if( elem->idx[i] != idx[i] ) 5001 break; 5002 if( i == d ) 5003 return &value<uchar>(elem); 5004 } 5005 nidx = elem->next; 5006 } 5007 5008 return createMissing ? newNode(idx, h) : 0; 5009} 5010 5011void SparseMat::erase(int i0, int i1, size_t* hashval) 5012{ 5013 CV_Assert( hdr && hdr->dims == 2 ); 5014 size_t h = hashval ? *hashval : hash(i0, i1); 5015 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0; 5016 uchar* pool = &hdr->pool[0]; 5017 while( nidx != 0 ) 5018 { 5019 Node* elem = (Node*)(pool + nidx); 5020 if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 ) 5021 break; 5022 previdx = nidx; 5023 nidx = elem->next; 5024 } 5025 5026 if( nidx ) 5027 removeNode(hidx, nidx, previdx); 5028} 5029 5030void SparseMat::erase(int i0, int i1, int i2, size_t* hashval) 5031{ 5032 CV_Assert( hdr && hdr->dims == 3 ); 5033 size_t h = hashval ? *hashval : hash(i0, i1, i2); 5034 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0; 5035 uchar* pool = &hdr->pool[0]; 5036 while( nidx != 0 ) 5037 { 5038 Node* elem = (Node*)(pool + nidx); 5039 if( elem->hashval == h && elem->idx[0] == i0 && 5040 elem->idx[1] == i1 && elem->idx[2] == i2 ) 5041 break; 5042 previdx = nidx; 5043 nidx = elem->next; 5044 } 5045 5046 if( nidx ) 5047 removeNode(hidx, nidx, previdx); 5048} 5049 5050void SparseMat::erase(const int* idx, size_t* hashval) 5051{ 5052 CV_Assert( hdr ); 5053 int i, d = hdr->dims; 5054 size_t h = hashval ? *hashval : hash(idx); 5055 size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0; 5056 uchar* pool = &hdr->pool[0]; 5057 while( nidx != 0 ) 5058 { 5059 Node* elem = (Node*)(pool + nidx); 5060 if( elem->hashval == h ) 5061 { 5062 for( i = 0; i < d; i++ ) 5063 if( elem->idx[i] != idx[i] ) 5064 break; 5065 if( i == d ) 5066 break; 5067 } 5068 previdx = nidx; 5069 nidx = elem->next; 5070 } 5071 5072 if( nidx ) 5073 removeNode(hidx, nidx, previdx); 5074} 5075 5076void SparseMat::resizeHashTab(size_t newsize) 5077{ 5078 newsize = std::max(newsize, (size_t)8); 5079 if((newsize & (newsize-1)) != 0) 5080 newsize = (size_t)1 << cvCeil(std::log((double)newsize)/CV_LOG2); 5081 5082 size_t i, hsize = hdr->hashtab.size(); 5083 std::vector<size_t> _newh(newsize); 5084 size_t* newh = &_newh[0]; 5085 for( i = 0; i < newsize; i++ ) 5086 newh[i] = 0; 5087 uchar* pool = &hdr->pool[0]; 5088 for( i = 0; i < hsize; i++ ) 5089 { 5090 size_t nidx = hdr->hashtab[i]; 5091 while( nidx ) 5092 { 5093 Node* elem = (Node*)(pool + nidx); 5094 size_t next = elem->next; 5095 size_t newhidx = elem->hashval & (newsize - 1); 5096 elem->next = newh[newhidx]; 5097 newh[newhidx] = nidx; 5098 nidx = next; 5099 } 5100 } 5101 hdr->hashtab = _newh; 5102} 5103 5104uchar* SparseMat::newNode(const int* idx, size_t hashval) 5105{ 5106 const int HASH_MAX_FILL_FACTOR=3; 5107 assert(hdr); 5108 size_t hsize = hdr->hashtab.size(); 5109 if( ++hdr->nodeCount > hsize*HASH_MAX_FILL_FACTOR ) 5110 { 5111 resizeHashTab(std::max(hsize*2, (size_t)8)); 5112 hsize = hdr->hashtab.size(); 5113 } 5114 5115 if( !hdr->freeList ) 5116 { 5117 size_t i, nsz = hdr->nodeSize, psize = hdr->pool.size(), 5118 newpsize = std::max(psize*3/2, 8*nsz); 5119 newpsize = (newpsize/nsz)*nsz; 5120 hdr->pool.resize(newpsize); 5121 uchar* pool = &hdr->pool[0]; 5122 hdr->freeList = std::max(psize, nsz); 5123 for( i = hdr->freeList; i < newpsize - nsz; i += nsz ) 5124 ((Node*)(pool + i))->next = i + nsz; 5125 ((Node*)(pool + i))->next = 0; 5126 } 5127 size_t nidx = hdr->freeList; 5128 Node* elem = (Node*)&hdr->pool[nidx]; 5129 hdr->freeList = elem->next; 5130 elem->hashval = hashval; 5131 size_t hidx = hashval & (hsize - 1); 5132 elem->next = hdr->hashtab[hidx]; 5133 hdr->hashtab[hidx] = nidx; 5134 5135 int i, d = hdr->dims; 5136 for( i = 0; i < d; i++ ) 5137 elem->idx[i] = idx[i]; 5138 size_t esz = elemSize(); 5139 uchar* p = &value<uchar>(elem); 5140 if( esz == sizeof(float) ) 5141 *((float*)p) = 0.f; 5142 else if( esz == sizeof(double) ) 5143 *((double*)p) = 0.; 5144 else 5145 memset(p, 0, esz); 5146 5147 return p; 5148} 5149 5150 5151void SparseMat::removeNode(size_t hidx, size_t nidx, size_t previdx) 5152{ 5153 Node* n = node(nidx); 5154 if( previdx ) 5155 { 5156 Node* prev = node(previdx); 5157 prev->next = n->next; 5158 } 5159 else 5160 hdr->hashtab[hidx] = n->next; 5161 n->next = hdr->freeList; 5162 hdr->freeList = nidx; 5163 --hdr->nodeCount; 5164} 5165 5166 5167SparseMatConstIterator::SparseMatConstIterator(const SparseMat* _m) 5168: m((SparseMat*)_m), hashidx(0), ptr(0) 5169{ 5170 if(!_m || !_m->hdr) 5171 return; 5172 SparseMat::Hdr& hdr = *m->hdr; 5173 const std::vector<size_t>& htab = hdr.hashtab; 5174 size_t i, hsize = htab.size(); 5175 for( i = 0; i < hsize; i++ ) 5176 { 5177 size_t nidx = htab[i]; 5178 if( nidx ) 5179 { 5180 hashidx = i; 5181 ptr = &hdr.pool[nidx] + hdr.valueOffset; 5182 return; 5183 } 5184 } 5185} 5186 5187SparseMatConstIterator& SparseMatConstIterator::operator ++() 5188{ 5189 if( !ptr || !m || !m->hdr ) 5190 return *this; 5191 SparseMat::Hdr& hdr = *m->hdr; 5192 size_t next = ((const SparseMat::Node*)(ptr - hdr.valueOffset))->next; 5193 if( next ) 5194 { 5195 ptr = &hdr.pool[next] + hdr.valueOffset; 5196 return *this; 5197 } 5198 size_t i = hashidx + 1, sz = hdr.hashtab.size(); 5199 for( ; i < sz; i++ ) 5200 { 5201 size_t nidx = hdr.hashtab[i]; 5202 if( nidx ) 5203 { 5204 hashidx = i; 5205 ptr = &hdr.pool[nidx] + hdr.valueOffset; 5206 return *this; 5207 } 5208 } 5209 hashidx = sz; 5210 ptr = 0; 5211 return *this; 5212} 5213 5214 5215double norm( const SparseMat& src, int normType ) 5216{ 5217 SparseMatConstIterator it = src.begin(); 5218 5219 size_t i, N = src.nzcount(); 5220 normType &= NORM_TYPE_MASK; 5221 int type = src.type(); 5222 double result = 0; 5223 5224 CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 ); 5225 5226 if( type == CV_32F ) 5227 { 5228 if( normType == NORM_INF ) 5229 for( i = 0; i < N; i++, ++it ) 5230 result = std::max(result, std::abs((double)it.value<float>())); 5231 else if( normType == NORM_L1 ) 5232 for( i = 0; i < N; i++, ++it ) 5233 result += std::abs(it.value<float>()); 5234 else 5235 for( i = 0; i < N; i++, ++it ) 5236 { 5237 double v = it.value<float>(); 5238 result += v*v; 5239 } 5240 } 5241 else if( type == CV_64F ) 5242 { 5243 if( normType == NORM_INF ) 5244 for( i = 0; i < N; i++, ++it ) 5245 result = std::max(result, std::abs(it.value<double>())); 5246 else if( normType == NORM_L1 ) 5247 for( i = 0; i < N; i++, ++it ) 5248 result += std::abs(it.value<double>()); 5249 else 5250 for( i = 0; i < N; i++, ++it ) 5251 { 5252 double v = it.value<double>(); 5253 result += v*v; 5254 } 5255 } 5256 else 5257 CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" ); 5258 5259 if( normType == NORM_L2 ) 5260 result = std::sqrt(result); 5261 return result; 5262} 5263 5264void minMaxLoc( const SparseMat& src, double* _minval, double* _maxval, int* _minidx, int* _maxidx ) 5265{ 5266 SparseMatConstIterator it = src.begin(); 5267 size_t i, N = src.nzcount(), d = src.hdr ? src.hdr->dims : 0; 5268 int type = src.type(); 5269 const int *minidx = 0, *maxidx = 0; 5270 5271 if( type == CV_32F ) 5272 { 5273 float minval = FLT_MAX, maxval = -FLT_MAX; 5274 for( i = 0; i < N; i++, ++it ) 5275 { 5276 float v = it.value<float>(); 5277 if( v < minval ) 5278 { 5279 minval = v; 5280 minidx = it.node()->idx; 5281 } 5282 if( v > maxval ) 5283 { 5284 maxval = v; 5285 maxidx = it.node()->idx; 5286 } 5287 } 5288 if( _minval ) 5289 *_minval = minval; 5290 if( _maxval ) 5291 *_maxval = maxval; 5292 } 5293 else if( type == CV_64F ) 5294 { 5295 double minval = DBL_MAX, maxval = -DBL_MAX; 5296 for( i = 0; i < N; i++, ++it ) 5297 { 5298 double v = it.value<double>(); 5299 if( v < minval ) 5300 { 5301 minval = v; 5302 minidx = it.node()->idx; 5303 } 5304 if( v > maxval ) 5305 { 5306 maxval = v; 5307 maxidx = it.node()->idx; 5308 } 5309 } 5310 if( _minval ) 5311 *_minval = minval; 5312 if( _maxval ) 5313 *_maxval = maxval; 5314 } 5315 else 5316 CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" ); 5317 5318 if( _minidx ) 5319 for( i = 0; i < d; i++ ) 5320 _minidx[i] = minidx[i]; 5321 if( _maxidx ) 5322 for( i = 0; i < d; i++ ) 5323 _maxidx[i] = maxidx[i]; 5324} 5325 5326 5327void normalize( const SparseMat& src, SparseMat& dst, double a, int norm_type ) 5328{ 5329 double scale = 1; 5330 if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C ) 5331 { 5332 scale = norm( src, norm_type ); 5333 scale = scale > DBL_EPSILON ? a/scale : 0.; 5334 } 5335 else 5336 CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" ); 5337 5338 src.convertTo( dst, -1, scale ); 5339} 5340 5341////////////////////// RotatedRect ////////////////////// 5342 5343RotatedRect::RotatedRect(const Point2f& _point1, const Point2f& _point2, const Point2f& _point3) 5344{ 5345 Point2f _center = 0.5f * (_point1 + _point3); 5346 Vec2f vecs[2]; 5347 vecs[0] = Vec2f(_point1 - _point2); 5348 vecs[1] = Vec2f(_point2 - _point3); 5349 // check that given sides are perpendicular 5350 CV_Assert( abs(vecs[0].dot(vecs[1])) / (norm(vecs[0]) * norm(vecs[1])) <= FLT_EPSILON ); 5351 5352 // wd_i stores which vector (0,1) or (1,2) will make the width 5353 // One of them will definitely have slope within -1 to 1 5354 int wd_i = 0; 5355 if( abs(vecs[1][1]) < abs(vecs[1][0]) ) wd_i = 1; 5356 int ht_i = (wd_i + 1) % 2; 5357 5358 float _angle = atan(vecs[wd_i][1] / vecs[wd_i][0]) * 180.0f / (float) CV_PI; 5359 float _width = (float) norm(vecs[wd_i]); 5360 float _height = (float) norm(vecs[ht_i]); 5361 5362 center = _center; 5363 size = Size2f(_width, _height); 5364 angle = _angle; 5365} 5366 5367void RotatedRect::points(Point2f pt[]) const 5368{ 5369 double _angle = angle*CV_PI/180.; 5370 float b = (float)cos(_angle)*0.5f; 5371 float a = (float)sin(_angle)*0.5f; 5372 5373 pt[0].x = center.x - a*size.height - b*size.width; 5374 pt[0].y = center.y + b*size.height - a*size.width; 5375 pt[1].x = center.x + a*size.height - b*size.width; 5376 pt[1].y = center.y - b*size.height - a*size.width; 5377 pt[2].x = 2*center.x - pt[0].x; 5378 pt[2].y = 2*center.y - pt[0].y; 5379 pt[3].x = 2*center.x - pt[1].x; 5380 pt[3].y = 2*center.y - pt[1].y; 5381} 5382 5383Rect RotatedRect::boundingRect() const 5384{ 5385 Point2f pt[4]; 5386 points(pt); 5387 Rect r(cvFloor(std::min(std::min(std::min(pt[0].x, pt[1].x), pt[2].x), pt[3].x)), 5388 cvFloor(std::min(std::min(std::min(pt[0].y, pt[1].y), pt[2].y), pt[3].y)), 5389 cvCeil(std::max(std::max(std::max(pt[0].x, pt[1].x), pt[2].x), pt[3].x)), 5390 cvCeil(std::max(std::max(std::max(pt[0].y, pt[1].y), pt[2].y), pt[3].y))); 5391 r.width -= r.x - 1; 5392 r.height -= r.y - 1; 5393 return r; 5394} 5395 5396} 5397 5398// glue 5399 5400CvMatND::CvMatND(const cv::Mat& m) 5401{ 5402 cvInitMatNDHeader(this, m.dims, m.size, m.type(), m.data ); 5403 int i, d = m.dims; 5404 for( i = 0; i < d; i++ ) 5405 dim[i].step = (int)m.step[i]; 5406 type |= m.flags & cv::Mat::CONTINUOUS_FLAG; 5407} 5408 5409_IplImage::_IplImage(const cv::Mat& m) 5410{ 5411 CV_Assert( m.dims <= 2 ); 5412 cvInitImageHeader(this, m.size(), cvIplDepth(m.flags), m.channels()); 5413 cvSetData(this, m.data, (int)m.step[0]); 5414} 5415 5416CvSparseMat* cvCreateSparseMat(const cv::SparseMat& sm) 5417{ 5418 if( !sm.hdr ) 5419 return 0; 5420 5421 CvSparseMat* m = cvCreateSparseMat(sm.hdr->dims, sm.hdr->size, sm.type()); 5422 5423 cv::SparseMatConstIterator from = sm.begin(); 5424 size_t i, N = sm.nzcount(), esz = sm.elemSize(); 5425 5426 for( i = 0; i < N; i++, ++from ) 5427 { 5428 const cv::SparseMat::Node* n = from.node(); 5429 uchar* to = cvPtrND(m, n->idx, 0, -2, 0); 5430 cv::copyElem(from.ptr, to, esz); 5431 } 5432 return m; 5433} 5434 5435void CvSparseMat::copyToSparseMat(cv::SparseMat& m) const 5436{ 5437 m.create( dims, &size[0], type ); 5438 5439 CvSparseMatIterator it; 5440 CvSparseNode* n = cvInitSparseMatIterator(this, &it); 5441 size_t esz = m.elemSize(); 5442 5443 for( ; n != 0; n = cvGetNextSparseNode(&it) ) 5444 { 5445 const int* idx = CV_NODE_IDX(this, n); 5446 uchar* to = m.newNode(idx, m.hash(idx)); 5447 cv::copyElem((const uchar*)CV_NODE_VAL(this, n), to, esz); 5448 } 5449} 5450 5451 5452/* End of file. */ 5453