Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of gr-peach-opencv-project-sd-card by
umatrix.cpp
00001 /*M/////////////////////////////////////////////////////////////////////////////////////// 00002 // 00003 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 00004 // 00005 // By downloading, copying, installing or using the software you agree to this license. 00006 // If you do not agree to this license, do not download, install, 00007 // copy or use the software. 00008 // 00009 // 00010 // License Agreement 00011 // For Open Source Computer Vision Library 00012 // 00013 // Copyright (C) 2014, Itseez Inc., all rights reserved. 00014 // Third party copyrights are property of their respective owners. 00015 // 00016 // Redistribution and use in source and binary forms, with or without modification, 00017 // are permitted provided that the following conditions are met: 00018 // 00019 // * Redistribution's of source code must retain the above copyright notice, 00020 // this list of conditions and the following disclaimer. 00021 // 00022 // * Redistribution's in binary form must reproduce the above copyright notice, 00023 // this list of conditions and the following disclaimer in the documentation 00024 // and/or other materials provided with the distribution. 00025 // 00026 // * The name of the copyright holders may not be used to endorse or promote products 00027 // derived from this software without specific prior written permission. 00028 // 00029 // This software is provided by the copyright holders and contributors "as is" and 00030 // any express or implied warranties, including, but not limited to, the implied 00031 // warranties of merchantability and fitness for a particular purpose are disclaimed. 00032 // In no event shall the Intel Corporation or contributors be liable for any direct, 00033 // indirect, incidental, special, exemplary, or consequential damages 00034 // (including, but not limited to, procurement of substitute goods or services; 00035 // loss of use, data, or profits; or business interruption) however caused 00036 // and on any theory of liability, whether in contract, strict liability, 00037 // or tort (including negligence or otherwise) arising in any way out of 00038 // the use of this software, even if advised of the possibility of such damage. 00039 // 00040 //M*/ 00041 00042 #include "precomp.hpp" 00043 #include "opencl_kernels_core.hpp" 00044 00045 ///////////////////////////////// UMat implementation /////////////////////////////// 00046 00047 namespace cv { 00048 00049 // forward decls, implementation is below in this file 00050 void setSize(UMat& m, int _dims, const int* _sz, const size_t* _steps, 00051 bool autoSteps = false); 00052 00053 void updateContinuityFlag(UMat& m); 00054 void finalizeHdr(UMat& m); 00055 00056 // it should be a prime number for the best hash function 00057 enum { UMAT_NLOCKS = 31 }; 00058 static Mutex umatLocks[UMAT_NLOCKS]; 00059 00060 UMatData::UMatData(const MatAllocator* allocator) 00061 { 00062 prevAllocator = currAllocator = allocator; 00063 urefcount = refcount = mapcount = 0; 00064 data = origdata = 0; 00065 size = 0; 00066 flags = 0; 00067 handle = 0; 00068 userdata = 0; 00069 allocatorFlags_ = 0; 00070 originalUMatData = NULL; 00071 } 00072 00073 UMatData::~UMatData() 00074 { 00075 prevAllocator = currAllocator = 0; 00076 urefcount = refcount = 0; 00077 CV_Assert(mapcount == 0); 00078 data = origdata = 0; 00079 size = 0; 00080 flags = 0; 00081 handle = 0; 00082 userdata = 0; 00083 allocatorFlags_ = 0; 00084 if (originalUMatData) 00085 { 00086 UMatData* u = originalUMatData; 00087 CV_XADD(&(u->urefcount), -1); 00088 CV_XADD(&(u->refcount), -1); 00089 bool showWarn = false; 00090 if (u->refcount == 0) 00091 { 00092 if (u->urefcount > 0) 00093 showWarn = true; 00094 // simulate Mat::deallocate 00095 if (u->mapcount != 0) 00096 { 00097 (u->currAllocator ? u->currAllocator : /* TODO allocator ? allocator :*/ Mat::getDefaultAllocator())->unmap(u); 00098 } 00099 else 00100 { 00101 // we don't do "map", so we can't do "unmap" 00102 } 00103 } 00104 if (u->refcount == 0 && u->urefcount == 0) // oops, we need to free resources 00105 { 00106 showWarn = true; 00107 // simulate UMat::deallocate 00108 u->currAllocator->deallocate(u); 00109 } 00110 #ifndef NDEBUG 00111 if (showWarn) 00112 { 00113 static int warn_message_showed = 0; 00114 if (warn_message_showed++ < 100) 00115 { 00116 fflush(stdout); 00117 fprintf(stderr, "\n! OPENCV warning: getUMat()/getMat() call chain possible problem." 00118 "\n! Base object is dead, while nested/derived object is still alive or processed." 00119 "\n! Please check lifetime of UMat/Mat objects!\n"); 00120 fflush(stderr); 00121 } 00122 } 00123 #else 00124 (void)showWarn; 00125 #endif 00126 originalUMatData = NULL; 00127 } 00128 } 00129 00130 void UMatData::lock() 00131 { 00132 umatLocks[(size_t)(void*)this % UMAT_NLOCKS].lock(); 00133 } 00134 00135 void UMatData::unlock() 00136 { 00137 umatLocks[(size_t)(void*)this % UMAT_NLOCKS].unlock(); 00138 } 00139 00140 00141 MatAllocator* UMat ::getStdAllocator() 00142 { 00143 #ifdef HAVE_OPENCL 00144 if( ocl::haveOpenCL() && ocl::useOpenCL() ) 00145 return ocl::getOpenCLAllocator(); 00146 #endif 00147 return Mat::getDefaultAllocator(); 00148 } 00149 00150 void swap( UMat & a, UMat & b ) 00151 { 00152 std::swap(a.flags , b.flags ); 00153 std::swap(a.dims, b.dims); 00154 std::swap(a.rows, b.rows); 00155 std::swap(a.cols, b.cols); 00156 std::swap(a.allocator, b.allocator); 00157 std::swap(a.u, b.u); 00158 std::swap(a.offset, b.offset); 00159 00160 std::swap(a.size.p, b.size.p); 00161 std::swap(a.step.p, b.step.p); 00162 std::swap(a.step.buf[0], b.step.buf[0]); 00163 std::swap(a.step.buf[1], b.step.buf[1]); 00164 00165 if( a.step.p == b.step.buf ) 00166 { 00167 a.step.p = a.step.buf; 00168 a.size.p = &a.rows; 00169 } 00170 00171 if( b.step.p == a.step.buf ) 00172 { 00173 b.step.p = b.step.buf; 00174 b.size.p = &b.rows; 00175 } 00176 } 00177 00178 00179 void setSize( UMat& m, int _dims, const int* _sz, 00180 const size_t* _steps, bool autoSteps ) 00181 { 00182 CV_Assert( 0 <= _dims && _dims <= CV_MAX_DIM ); 00183 if( m.dims != _dims ) 00184 { 00185 if( m.step.p != m.step.buf ) 00186 { 00187 fastFree(m.step.p); 00188 m.step.p = m.step.buf; 00189 m.size.p = &m.rows; 00190 } 00191 if( _dims > 2 ) 00192 { 00193 m.step.p = (size_t*)fastMalloc(_dims*sizeof(m.step.p[0]) + (_dims+1)*sizeof(m.size.p[0])); 00194 m.size.p = (int*)(m.step.p + _dims) + 1; 00195 m.size.p[-1] = _dims; 00196 m.rows = m.cols = -1; 00197 } 00198 } 00199 00200 m.dims = _dims; 00201 if( !_sz ) 00202 return; 00203 00204 size_t esz = CV_ELEM_SIZE(m.flags), total = esz; 00205 int i; 00206 for( i = _dims-1; i >= 0; i-- ) 00207 { 00208 int s = _sz[i]; 00209 CV_Assert( s >= 0 ); 00210 m.size.p[i] = s; 00211 00212 if( _steps ) 00213 m.step.p[i] = i < _dims-1 ? _steps[i] : esz; 00214 else if( autoSteps ) 00215 { 00216 m.step.p[i] = total; 00217 int64 total1 = (int64)total*s; 00218 if( (uint64)total1 != (size_t)total1 ) 00219 CV_Error( CV_StsOutOfRange, "The total matrix size does not fit to \"size_t\" type" ); 00220 total = (size_t)total1; 00221 } 00222 } 00223 00224 if( _dims == 1 ) 00225 { 00226 m.dims = 2; 00227 m.cols = 1; 00228 m.step[1] = esz; 00229 } 00230 } 00231 00232 00233 void updateContinuityFlag(UMat& m) 00234 { 00235 int i, j; 00236 for( i = 0; i < m.dims; i++ ) 00237 { 00238 if( m.size[i] > 1 ) 00239 break; 00240 } 00241 00242 for( j = m.dims-1; j > i; j-- ) 00243 { 00244 if( m.step[j]*m.size[j] < m.step[j-1] ) 00245 break; 00246 } 00247 00248 uint64 total = (uint64)m.step[0]*m.size[0]; 00249 if( j <= i && total == (size_t)total ) 00250 m.flags |= UMat::CONTINUOUS_FLAG; 00251 else 00252 m.flags &= ~UMat::CONTINUOUS_FLAG; 00253 } 00254 00255 00256 void finalizeHdr(UMat& m) 00257 { 00258 updateContinuityFlag(m); 00259 int d = m.dims; 00260 if( d > 2 ) 00261 m.rows = m.cols = -1; 00262 } 00263 00264 00265 UMat Mat::getUMat(int accessFlags, UMatUsageFlags usageFlags) const 00266 { 00267 UMat hdr; 00268 if(!data) 00269 return hdr; 00270 Size wholeSize; 00271 Point ofs; 00272 locateROI(wholeSize, ofs); 00273 Size sz(cols, rows); 00274 if (ofs.x != 0 || ofs.y != 0) 00275 { 00276 Mat src = *this; 00277 int dtop = ofs.y; 00278 int dbottom = wholeSize.height - src.rows - ofs.y; 00279 int dleft = ofs.x; 00280 int dright = wholeSize.width - src.cols - ofs.x; 00281 src.adjustROI(dtop, dbottom, dleft, dright); 00282 return src.getUMat(accessFlags, usageFlags)(cv::Rect(ofs.x, ofs.y, sz.width, sz.height)); 00283 } 00284 CV_Assert(data == datastart); 00285 00286 accessFlags |= ACCESS_RW; 00287 UMatData* new_u = NULL; 00288 { 00289 MatAllocator *a = allocator, *a0 = getDefaultAllocator(); 00290 if(!a) 00291 a = a0; 00292 new_u = a->allocate(dims, size.p, type(), data, step.p, accessFlags, usageFlags); 00293 } 00294 bool allocated = false; 00295 //try 00296 // { 00297 allocated = UMat::getStdAllocator()->allocate(new_u, accessFlags, usageFlags); 00298 //} 00299 // catch (const cv::Exception& e) 00300 // { 00301 // fprintf(stderr, "Exception: %s\n", e.what()); 00302 // } 00303 if (!allocated) 00304 { 00305 allocated = getDefaultAllocator()->allocate(new_u, accessFlags, usageFlags); 00306 CV_Assert(allocated); 00307 } 00308 if (u != NULL) 00309 { 00310 #ifdef HAVE_OPENCL 00311 if (ocl::useOpenCL() && new_u->currAllocator == ocl::getOpenCLAllocator()) 00312 { 00313 CV_Assert(new_u->tempUMat()); 00314 } 00315 #endif 00316 new_u->originalUMatData = u; 00317 CV_XADD(&(u->refcount), 1); 00318 CV_XADD(&(u->urefcount), 1); 00319 } 00320 hdr.flags = flags ; 00321 setSize(hdr, dims, size.p, step.p); 00322 finalizeHdr(hdr); 00323 hdr.u = new_u; 00324 hdr.offset = 0; //data - datastart; 00325 hdr.addref(); 00326 return hdr; 00327 } 00328 00329 void UMat::create(int d, const int* _sizes, int _type, UMatUsageFlags _usageFlags) 00330 { 00331 this->usageFlags = _usageFlags; 00332 00333 int i; 00334 CV_Assert(0 <= d && d <= CV_MAX_DIM && _sizes); 00335 _type = CV_MAT_TYPE(_type); 00336 00337 if( u && (d == dims || (d == 1 && dims <= 2)) && _type == type() ) 00338 { 00339 if( d == 2 && rows == _sizes[0] && cols == _sizes[1] ) 00340 return; 00341 for( i = 0; i < d; i++ ) 00342 if( size[i] != _sizes[i] ) 00343 break; 00344 if( i == d && (d > 1 || size[1] == 1)) 00345 return; 00346 } 00347 00348 release(); 00349 if( d == 0 ) 00350 return; 00351 flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL; 00352 setSize(*this, d, _sizes, 0, true); 00353 offset = 0; 00354 00355 if( total() > 0 ) 00356 { 00357 MatAllocator *a = allocator, *a0 = getStdAllocator(); 00358 if (!a) 00359 { 00360 a = a0; 00361 a0 = Mat::getDefaultAllocator(); 00362 } 00363 //try 00364 // { 00365 u = a->allocate(dims, size, _type, 0, step.p, 0, usageFlags); 00366 CV_Assert(u != 0); 00367 //} 00368 // catch(...) 00369 // { 00370 // if(a != a0) 00371 // u = a0->allocate(dims, size, _type, 0, step.p, 0, usageFlags); 00372 // CV_Assert(u != 0); 00373 // } 00374 CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags ) ); 00375 } 00376 00377 finalizeHdr(*this); 00378 addref(); 00379 } 00380 00381 void UMat::copySize(const UMat & m) 00382 { 00383 setSize(*this, m.dims, 0, 0); 00384 for( int i = 0; i < dims; i++ ) 00385 { 00386 size[i] = m.size[i]; 00387 step[i] = m.step[i]; 00388 } 00389 } 00390 00391 00392 UMat::~UMat() 00393 { 00394 release(); 00395 if( step.p != step.buf ) 00396 fastFree(step.p); 00397 } 00398 00399 void UMat::deallocate() 00400 { 00401 u->currAllocator->deallocate(u); 00402 u = NULL; 00403 } 00404 00405 00406 UMat::UMat(const UMat & m, const Range& _rowRange, const Range& _colRange) 00407 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows) 00408 { 00409 CV_Assert( m.dims >= 2 ); 00410 if( m.dims > 2 ) 00411 { 00412 AutoBuffer<Range> rs(m.dims); 00413 rs[0] = _rowRange; 00414 rs[1] = _colRange; 00415 for( int i = 2; i < m.dims; i++ ) 00416 rs[i] = Range::all(); 00417 *this = m(rs); 00418 return; 00419 } 00420 00421 *this = m; 00422 if( _rowRange != Range::all() && _rowRange != Range(0,rows) ) 00423 { 00424 CV_Assert( 0 <= _rowRange.start && _rowRange.start <= _rowRange.end && _rowRange.end <= m.rows ); 00425 rows = _rowRange.size(); 00426 offset += step*_rowRange.start; 00427 flags |= SUBMATRIX_FLAG; 00428 } 00429 00430 if( _colRange != Range::all() && _colRange != Range(0,cols) ) 00431 { 00432 CV_Assert( 0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols ); 00433 cols = _colRange.size(); 00434 offset += _colRange.start*elemSize(); 00435 flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1; 00436 flags |= SUBMATRIX_FLAG; 00437 } 00438 00439 if( rows == 1 ) 00440 flags |= CONTINUOUS_FLAG; 00441 00442 if( rows <= 0 || cols <= 0 ) 00443 { 00444 release(); 00445 rows = cols = 0; 00446 } 00447 } 00448 00449 00450 UMat::UMat(const UMat & m, const Rect& roi) 00451 : flags(m.flags), dims(2), rows(roi.height), cols(roi.width), 00452 allocator(m.allocator), usageFlags(m.usageFlags), u(m.u), offset(m.offset + roi.y*m.step[0]), size(&rows) 00453 { 00454 CV_Assert( m.dims <= 2 ); 00455 flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1; 00456 flags |= roi.height == 1 ? CONTINUOUS_FLAG : 0; 00457 00458 size_t esz = CV_ELEM_SIZE(flags ); 00459 offset += roi.x*esz; 00460 CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 00461 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows ); 00462 if( u ) 00463 CV_XADD(&(u->urefcount), 1); 00464 if( roi.width < m.cols || roi.height < m.rows ) 00465 flags |= SUBMATRIX_FLAG; 00466 00467 step[0] = m.step[0]; step[1] = esz; 00468 00469 if( rows <= 0 || cols <= 0 ) 00470 { 00471 release(); 00472 rows = cols = 0; 00473 } 00474 } 00475 00476 00477 UMat::UMat(const UMat& m, const Range* ranges) 00478 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows) 00479 { 00480 int i, d = m.dims; 00481 00482 CV_Assert(ranges); 00483 for( i = 0; i < d; i++ ) 00484 { 00485 Range r = ranges[i]; 00486 CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) ); 00487 } 00488 *this = m; 00489 for( i = 0; i < d; i++ ) 00490 { 00491 Range r = ranges[i]; 00492 if( r != Range::all() && r != Range(0, size.p[i])) 00493 { 00494 size.p[i] = r.end - r.start; 00495 offset += r.start*step.p[i]; 00496 flags |= SUBMATRIX_FLAG; 00497 } 00498 } 00499 updateContinuityFlag(*this); 00500 } 00501 00502 UMat UMat::diag(int d) const 00503 { 00504 CV_Assert( dims <= 2 ); 00505 UMat m = *this; 00506 size_t esz = elemSize(); 00507 int len; 00508 00509 if( d >= 0 ) 00510 { 00511 len = std::min(cols - d, rows); 00512 m.offset += esz*d; 00513 } 00514 else 00515 { 00516 len = std::min(rows + d, cols); 00517 m.offset -= step[0]*d; 00518 } 00519 CV_DbgAssert( len > 0 ); 00520 00521 m.size[0] = m.rows = len; 00522 m.size[1] = m.cols = 1; 00523 m.step[0] += (len > 1 ? esz : 0); 00524 00525 if( m.rows > 1 ) 00526 m.flags &= ~CONTINUOUS_FLAG; 00527 else 00528 m.flags |= CONTINUOUS_FLAG; 00529 00530 if( size() != Size(1,1) ) 00531 m.flags |= SUBMATRIX_FLAG; 00532 00533 return m; 00534 } 00535 00536 void UMat::locateROI( Size& wholeSize, Point & ofs ) const 00537 { 00538 CV_Assert( dims <= 2 && step[0] > 0 ); 00539 size_t esz = elemSize(), minstep; 00540 ptrdiff_t delta1 = (ptrdiff_t)offset, delta2 = (ptrdiff_t)u->size; 00541 00542 if( delta1 == 0 ) 00543 ofs.x = ofs.y = 0; 00544 else 00545 { 00546 ofs.y = (int)(delta1/step[0]); 00547 ofs.x = (int)((delta1 - step[0]*ofs.y)/esz); 00548 CV_DbgAssert( offset == (size_t)(ofs.y*step[0] + ofs.x*esz) ); 00549 } 00550 minstep = (ofs.x + cols)*esz; 00551 wholeSize.height = (int)((delta2 - minstep)/step[0] + 1); 00552 wholeSize.height = std::max(wholeSize.height, ofs.y + rows); 00553 wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz); 00554 wholeSize.width = std::max(wholeSize.width, ofs.x + cols); 00555 } 00556 00557 00558 UMat & UMat::adjustROI( int dtop, int dbottom, int dleft, int dright ) 00559 { 00560 CV_Assert( dims <= 2 && step[0] > 0 ); 00561 Size wholeSize; Point ofs; 00562 size_t esz = elemSize(); 00563 locateROI( wholeSize, ofs ); 00564 int row1 = std::max(ofs.y - dtop, 0), row2 = std::min(ofs.y + rows + dbottom, wholeSize.height); 00565 int col1 = std::max(ofs.x - dleft, 0), col2 = std::min(ofs.x + cols + dright, wholeSize.width); 00566 offset += (row1 - ofs.y)*step + (col1 - ofs.x)*esz; 00567 rows = row2 - row1; cols = col2 - col1; 00568 size.p[0] = rows; size.p[1] = cols; 00569 if( esz*cols == step[0] || rows == 1 ) 00570 flags |= CONTINUOUS_FLAG; 00571 else 00572 flags &= ~CONTINUOUS_FLAG; 00573 return *this; 00574 } 00575 00576 00577 UMat UMat::reshape(int new_cn, int new_rows) const 00578 { 00579 int cn = channels(); 00580 UMat hdr = *this; 00581 00582 if( dims > 2 && new_rows == 0 && new_cn != 0 && size[dims-1]*cn % new_cn == 0 ) 00583 { 00584 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT); 00585 hdr.step[dims-1] = CV_ELEM_SIZE(hdr.flags ); 00586 hdr.size[dims-1] = hdr.size[dims-1]*cn / new_cn; 00587 return hdr; 00588 } 00589 00590 CV_Assert( dims <= 2 ); 00591 00592 if( new_cn == 0 ) 00593 new_cn = cn; 00594 00595 int total_width = cols * cn; 00596 00597 if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 ) 00598 new_rows = rows * total_width / new_cn; 00599 00600 if( new_rows != 0 && new_rows != rows ) 00601 { 00602 int total_size = total_width * rows; 00603 if( !isContinuous() ) 00604 CV_Error( CV_BadStep, 00605 "The matrix is not continuous, thus its number of rows can not be changed" ); 00606 00607 if( (unsigned)new_rows > (unsigned)total_size ) 00608 CV_Error( CV_StsOutOfRange, "Bad new number of rows" ); 00609 00610 total_width = total_size / new_rows; 00611 00612 if( total_width * new_rows != total_size ) 00613 CV_Error( CV_StsBadArg, "The total number of matrix elements " 00614 "is not divisible by the new number of rows" ); 00615 00616 hdr.rows = new_rows; 00617 hdr.step[0] = total_width * elemSize1(); 00618 } 00619 00620 int new_width = total_width / new_cn; 00621 00622 if( new_width * new_cn != total_width ) 00623 CV_Error( CV_BadNumChannels, 00624 "The total width is not divisible by the new number of channels" ); 00625 00626 hdr.cols = new_width; 00627 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT); 00628 hdr.step[1] = CV_ELEM_SIZE(hdr.flags ); 00629 return hdr; 00630 } 00631 00632 UMat UMat::diag(const UMat & d) 00633 { 00634 CV_Assert( d.cols == 1 || d.rows == 1 ); 00635 int len = d.rows + d.cols - 1; 00636 UMat m(len, len, d.type(), Scalar (0)); 00637 UMat md = m.diag(); 00638 if( d.cols == 1 ) 00639 d.copyTo(md); 00640 else 00641 transpose(d, md); 00642 return m; 00643 } 00644 00645 int UMat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) const 00646 { 00647 return (depth() == _depth || _depth <= 0) && 00648 (isContinuous() || !_requireContinuous) && 00649 ((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) || 00650 (cols == _elemChannels && channels() == 1))) || 00651 (dims == 3 && channels() == 1 && size.p[2] == _elemChannels && (size.p[0] == 1 || size.p[1] == 1) && 00652 (isContinuous() || step.p[1] == step.p[2]*size.p[2]))) 00653 ? (int)(total()*channels()/_elemChannels) : -1; 00654 } 00655 00656 UMat UMat::reshape(int _cn, int _newndims, const int* _newsz) const 00657 { 00658 if(_newndims == dims) 00659 { 00660 if(_newsz == 0) 00661 return reshape(_cn); 00662 if(_newndims == 2) 00663 return reshape(_cn, _newsz[0]); 00664 } 00665 00666 if (isContinuous()) 00667 { 00668 CV_Assert(_cn >= 0 && _newndims > 0 && _newndims <= CV_MAX_DIM && _newsz); 00669 00670 if (_cn == 0) 00671 _cn = this->channels(); 00672 else 00673 CV_Assert(_cn <= CV_CN_MAX); 00674 00675 size_t total_elem1_ref = this->total() * this->channels(); 00676 size_t total_elem1 = _cn; 00677 00678 AutoBuffer<int, 4> newsz_buf( (size_t)_newndims ); 00679 00680 for (int i = 0; i < _newndims; i++) 00681 { 00682 CV_Assert(_newsz[i] >= 0); 00683 00684 if (_newsz[i] > 0) 00685 newsz_buf[i] = _newsz[i]; 00686 else if (i < dims) 00687 newsz_buf[i] = this->size[i]; 00688 else 00689 CV_Error(CV_StsOutOfRange, "Copy dimension (which has zero size) is not present in source matrix"); 00690 00691 total_elem1 *= (size_t)newsz_buf[i]; 00692 } 00693 00694 if (total_elem1 != total_elem1_ref) 00695 CV_Error(CV_StsUnmatchedSizes, "Requested and source matrices have different count of elements"); 00696 00697 UMat hdr = *this; 00698 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((_cn-1) << CV_CN_SHIFT); 00699 setSize(hdr, _newndims, (int*)newsz_buf, NULL, true); 00700 00701 return hdr; 00702 } 00703 00704 CV_Error(CV_StsNotImplemented, "Reshaping of n-dimensional non-continuous matrices is not supported yet"); 00705 // TBD 00706 return UMat(); 00707 } 00708 00709 Mat UMat::getMat(int accessFlags) const 00710 { 00711 if(!u) 00712 return Mat(); 00713 // TODO Support ACCESS_READ (ACCESS_WRITE) without unnecessary data transfers 00714 accessFlags |= ACCESS_RW; 00715 UMatDataAutoLock autolock(u); 00716 if(CV_XADD(&u->refcount, 1) == 0) 00717 u->currAllocator->map(u, accessFlags); 00718 if (u->data != 0) 00719 { 00720 Mat hdr(dims, size.p, type(), u->data + offset, step.p); 00721 hdr.flags = flags ; 00722 hdr.u = u; 00723 hdr.datastart = u->data; 00724 hdr.data = u->data + offset; 00725 hdr.datalimit = hdr.dataend = u->data + u->size; 00726 return hdr; 00727 } 00728 else 00729 { 00730 CV_XADD(&u->refcount, -1); 00731 CV_Assert(u->data != 0 && "Error mapping of UMat to host memory."); 00732 return Mat(); 00733 } 00734 } 00735 00736 void* UMat::handle(int accessFlags) const 00737 { 00738 if( !u ) 00739 return 0; 00740 00741 CV_Assert(u->refcount == 0); 00742 CV_Assert(!u->deviceCopyObsolete() || u->copyOnMap()); 00743 if (u->deviceCopyObsolete()) 00744 { 00745 u->currAllocator->unmap(u); 00746 } 00747 00748 if ((accessFlags & ACCESS_WRITE) != 0) 00749 u->markHostCopyObsolete(true); 00750 00751 return u->handle; 00752 } 00753 00754 void UMat::ndoffset(size_t* ofs) const 00755 { 00756 // offset = step[0]*ofs[0] + step[1]*ofs[1] + step[2]*ofs[2] + ...; 00757 size_t val = offset; 00758 for( int i = 0; i < dims; i++ ) 00759 { 00760 size_t s = step.p[i]; 00761 ofs[i] = val / s; 00762 val -= ofs[i]*s; 00763 } 00764 } 00765 00766 void UMat::copyTo(OutputArray _dst) const 00767 { 00768 int dtype = _dst.type(); 00769 if( _dst.fixedType() && dtype != type() ) 00770 { 00771 CV_Assert( channels() == CV_MAT_CN(dtype) ); 00772 convertTo( _dst, dtype ); 00773 return; 00774 } 00775 00776 if( empty() ) 00777 { 00778 _dst.release(); 00779 return; 00780 } 00781 00782 size_t i, sz[CV_MAX_DIM], srcofs[CV_MAX_DIM], dstofs[CV_MAX_DIM], esz = elemSize(); 00783 for( i = 0; i < (size_t)dims; i++ ) 00784 sz[i] = size.p[i]; 00785 sz[dims-1] *= esz; 00786 ndoffset(srcofs); 00787 srcofs[dims-1] *= esz; 00788 00789 _dst.create( dims, size.p, type() ); 00790 if( _dst.isUMat() ) 00791 { 00792 UMat dst = _dst.getUMat(); 00793 if( u == dst.u && dst.offset == offset ) 00794 return; 00795 00796 if (u->currAllocator == dst.u->currAllocator) 00797 { 00798 dst.ndoffset(dstofs); 00799 dstofs[dims-1] *= esz; 00800 u->currAllocator->copy(u, dst.u, dims, sz, srcofs, step.p, dstofs, dst.step.p, false); 00801 return; 00802 } 00803 } 00804 00805 Mat dst = _dst.getMat(); 00806 u->currAllocator->download(u, dst.ptr(), dims, sz, srcofs, step.p, dst.step.p); 00807 } 00808 00809 void UMat::copyTo(OutputArray _dst, InputArray _mask) const 00810 { 00811 if( _mask.empty() ) 00812 { 00813 copyTo(_dst); 00814 return; 00815 } 00816 #ifdef HAVE_OPENCL 00817 int cn = channels(), mtype = _mask.type(), mdepth = CV_MAT_DEPTH(mtype), mcn = CV_MAT_CN(mtype); 00818 CV_Assert( mdepth == CV_8U && (mcn == 1 || mcn == cn) ); 00819 00820 if (ocl::useOpenCL() && _dst.isUMat() && dims <= 2) 00821 { 00822 UMatData * prevu = _dst.getUMat().u; 00823 _dst.create( dims, size, type() ); 00824 00825 UMat dst = _dst.getUMat(); 00826 00827 bool haveDstUninit = false; 00828 if( prevu != dst.u ) // do not leave dst uninitialized 00829 haveDstUninit = true; 00830 00831 String opts = format("-D COPY_TO_MASK -D T1=%s -D scn=%d -D mcn=%d%s", 00832 ocl::memopTypeToStr(depth()), cn, mcn, 00833 haveDstUninit ? " -D HAVE_DST_UNINIT" : ""); 00834 00835 ocl::Kernel k("copyToMask", ocl::core::copyset_oclsrc, opts); 00836 if (!k.empty()) 00837 { 00838 k.args(ocl::KernelArg::ReadOnlyNoSize(*this), 00839 ocl::KernelArg::ReadOnlyNoSize(_mask.getUMat()), 00840 haveDstUninit ? ocl::KernelArg::WriteOnly(dst) : 00841 ocl::KernelArg::ReadWrite(dst)); 00842 00843 size_t globalsize[2] = { (size_t)cols, (size_t)rows }; 00844 if (k.run(2, globalsize, NULL, false)) 00845 { 00846 CV_IMPL_ADD(CV_IMPL_OCL); 00847 return; 00848 } 00849 } 00850 } 00851 #endif 00852 Mat src = getMat(ACCESS_READ); 00853 src.copyTo(_dst, _mask); 00854 } 00855 00856 void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const 00857 { 00858 bool noScale = std::fabs(alpha - 1) < DBL_EPSILON && std::fabs(beta) < DBL_EPSILON; 00859 int stype = type(), cn = CV_MAT_CN(stype); 00860 00861 if( _type < 0 ) 00862 _type = _dst.fixedType() ? _dst.type() : stype; 00863 else 00864 _type = CV_MAKETYPE(CV_MAT_DEPTH(_type), cn); 00865 00866 int sdepth = CV_MAT_DEPTH(stype), ddepth = CV_MAT_DEPTH(_type); 00867 if( sdepth == ddepth && noScale ) 00868 { 00869 copyTo(_dst); 00870 return; 00871 } 00872 #ifdef HAVE_OPENCL 00873 bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; 00874 bool needDouble = sdepth == CV_64F || ddepth == CV_64F; 00875 if( dims <= 2 && cn && _dst.isUMat() && ocl::useOpenCL() && 00876 ((needDouble && doubleSupport) || !needDouble) ) 00877 { 00878 int wdepth = std::max(CV_32F, sdepth), rowsPerWI = 4; 00879 00880 char cvt[2][40]; 00881 ocl::Kernel k("convertTo", ocl::core::convert_oclsrc, 00882 format("-D srcT=%s -D WT=%s -D dstT=%s -D convertToWT=%s -D convertToDT=%s%s%s", 00883 ocl::typeToStr(sdepth), ocl::typeToStr(wdepth), ocl::typeToStr(ddepth), 00884 ocl::convertTypeStr(sdepth, wdepth, 1, cvt[0]), 00885 ocl::convertTypeStr(wdepth, ddepth, 1, cvt[1]), 00886 doubleSupport ? " -D DOUBLE_SUPPORT" : "", noScale ? " -D NO_SCALE" : "")); 00887 if (!k.empty()) 00888 { 00889 UMat src = *this; 00890 _dst.create( size(), _type ); 00891 UMat dst = _dst.getUMat(); 00892 00893 float alphaf = (float)alpha, betaf = (float)beta; 00894 ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src), 00895 dstarg = ocl::KernelArg::WriteOnly(dst, cn); 00896 00897 if (noScale) 00898 k.args(srcarg, dstarg, rowsPerWI); 00899 else if (wdepth == CV_32F) 00900 k.args(srcarg, dstarg, alphaf, betaf, rowsPerWI); 00901 else 00902 k.args(srcarg, dstarg, alpha, beta, rowsPerWI); 00903 00904 size_t globalsize[2] = { (size_t)dst.cols * cn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; 00905 if (k.run(2, globalsize, NULL, false)) 00906 { 00907 CV_IMPL_ADD(CV_IMPL_OCL); 00908 return; 00909 } 00910 } 00911 } 00912 #endif 00913 Mat m = getMat(ACCESS_READ); 00914 m.convertTo(_dst, _type, alpha, beta); 00915 } 00916 00917 UMat & UMat::setTo(InputArray _value, InputArray _mask) 00918 { 00919 bool haveMask = !_mask.empty(); 00920 #ifdef HAVE_OPENCL 00921 int tp = type(), cn = CV_MAT_CN(tp), d = CV_MAT_DEPTH(tp); 00922 00923 if( dims <= 2 && cn <= 4 && CV_MAT_DEPTH(tp) < CV_64F && ocl::useOpenCL() ) 00924 { 00925 Mat value = _value.getMat(); 00926 CV_Assert( checkScalar(value, type(), _value.kind(), _InputArray::UMAT) ); 00927 int kercn = haveMask || cn == 3 ? cn : std::max(cn, ocl::predictOptimalVectorWidth(*this)), 00928 kertp = CV_MAKE_TYPE(d, kercn); 00929 00930 double buf[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 00931 0, 0, 0, 0, 0, 0, 0, 0 }; 00932 convertAndUnrollScalar(value, tp, (uchar *)buf, kercn / cn); 00933 00934 int scalarcn = kercn == 3 ? 4 : kercn, rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1; 00935 String opts = format("-D dstT=%s -D rowsPerWI=%d -D dstST=%s -D dstT1=%s -D cn=%d", 00936 ocl::memopTypeToStr(kertp), rowsPerWI, 00937 ocl::memopTypeToStr(CV_MAKETYPE(d, scalarcn)), 00938 ocl::memopTypeToStr(d), kercn); 00939 00940 ocl::Kernel setK(haveMask ? "setMask" : "set", ocl::core::copyset_oclsrc, opts); 00941 if( !setK.empty() ) 00942 { 00943 ocl::KernelArg scalararg(0, 0, 0, 0, buf, CV_ELEM_SIZE(d) * scalarcn); 00944 UMat mask; 00945 00946 if( haveMask ) 00947 { 00948 mask = _mask.getUMat(); 00949 CV_Assert( mask.size() == size() && mask.type() == CV_8UC1 ); 00950 ocl::KernelArg maskarg = ocl::KernelArg::ReadOnlyNoSize(mask), 00951 dstarg = ocl::KernelArg::ReadWrite(*this); 00952 setK.args(maskarg, dstarg, scalararg); 00953 } 00954 else 00955 { 00956 ocl::KernelArg dstarg = ocl::KernelArg::WriteOnly(*this, cn, kercn); 00957 setK.args(dstarg, scalararg); 00958 } 00959 00960 size_t globalsize[] = { (size_t)cols * cn / kercn, ((size_t)rows + rowsPerWI - 1) / rowsPerWI }; 00961 if( setK.run(2, globalsize, NULL, false) ) 00962 { 00963 CV_IMPL_ADD(CV_IMPL_OCL); 00964 return *this; 00965 } 00966 } 00967 } 00968 #endif 00969 Mat m = getMat(haveMask ? ACCESS_RW : ACCESS_WRITE); 00970 m.setTo(_value, _mask); 00971 return *this; 00972 } 00973 00974 UMat & UMat::operator = (const Scalar & s) 00975 { 00976 setTo(s); 00977 return *this; 00978 } 00979 00980 UMat UMat::t() const 00981 { 00982 UMat m; 00983 transpose(*this, m); 00984 return m; 00985 } 00986 00987 UMat UMat::inv(int method) const 00988 { 00989 UMat m; 00990 invert(*this, m, method); 00991 return m; 00992 } 00993 00994 UMat UMat::mul(InputArray m, double scale) const 00995 { 00996 UMat dst; 00997 multiply(*this, m, dst, scale); 00998 return dst; 00999 } 01000 01001 #ifdef HAVE_OPENCL 01002 01003 static bool ocl_dot( InputArray _src1, InputArray _src2, double & res ) 01004 { 01005 UMat src1 = _src1.getUMat().reshape(1), src2 = _src2.getUMat().reshape(1); 01006 01007 int type = src1.type(), depth = CV_MAT_DEPTH(type), 01008 kercn = ocl::predictOptimalVectorWidth(src1, src2); 01009 bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; 01010 01011 if ( !doubleSupport && depth == CV_64F ) 01012 return false; 01013 01014 int dbsize = ocl::Device::getDefault().maxComputeUnits(); 01015 size_t wgs = ocl::Device::getDefault().maxWorkGroupSize(); 01016 int ddepth = std::max(CV_32F, depth); 01017 01018 int wgs2_aligned = 1; 01019 while (wgs2_aligned < (int)wgs) 01020 wgs2_aligned <<= 1; 01021 wgs2_aligned >>= 1; 01022 01023 char cvt[40]; 01024 ocl::Kernel k("reduce", ocl::core::reduce_oclsrc, 01025 format("-D srcT=%s -D srcT1=%s -D dstT=%s -D dstTK=%s -D ddepth=%d -D convertToDT=%s -D OP_DOT " 01026 "-D WGS=%d -D WGS2_ALIGNED=%d%s%s%s -D kercn=%d", 01027 ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)), ocl::typeToStr(depth), 01028 ocl::typeToStr(ddepth), ocl::typeToStr(CV_MAKE_TYPE(ddepth, kercn)), 01029 ddepth, ocl::convertTypeStr(depth, ddepth, kercn, cvt), 01030 (int)wgs, wgs2_aligned, doubleSupport ? " -D DOUBLE_SUPPORT" : "", 01031 _src1.isContinuous() ? " -D HAVE_SRC_CONT" : "", 01032 _src2.isContinuous() ? " -D HAVE_SRC2_CONT" : "", kercn)); 01033 if (k.empty()) 01034 return false; 01035 01036 UMat db(1, dbsize, ddepth); 01037 01038 ocl::KernelArg src1arg = ocl::KernelArg::ReadOnlyNoSize(src1), 01039 src2arg = ocl::KernelArg::ReadOnlyNoSize(src2), 01040 dbarg = ocl::KernelArg::PtrWriteOnly(db); 01041 01042 k.args(src1arg, src1.cols, (int)src1.total(), dbsize, dbarg, src2arg); 01043 01044 size_t globalsize = dbsize * wgs; 01045 if (k.run(1, &globalsize, &wgs, false)) 01046 { 01047 res = sum(db.getMat(ACCESS_READ))[0]; 01048 return true; 01049 } 01050 return false; 01051 } 01052 01053 #endif 01054 01055 double UMat::dot(InputArray m) const 01056 { 01057 CV_Assert(m.sameSize(*this) && m.type() == type()); 01058 01059 #ifdef HAVE_OPENCL 01060 double r = 0; 01061 CV_OCL_RUN_(dims <= 2, ocl_dot(*this, m, r), r) 01062 #endif 01063 01064 return getMat(ACCESS_READ).dot(m); 01065 } 01066 01067 UMat UMat::zeros(int rows, int cols, int type) 01068 { 01069 return UMat(rows, cols, type, Scalar::all(0)); 01070 } 01071 01072 UMat UMat::zeros(Size size, int type) 01073 { 01074 return UMat(size, type, Scalar::all(0)); 01075 } 01076 01077 UMat UMat::zeros(int ndims, const int* sz, int type) 01078 { 01079 return UMat(ndims, sz, type, Scalar::all(0)); 01080 } 01081 01082 UMat UMat::ones(int rows, int cols, int type) 01083 { 01084 return UMat::ones(Size(cols, rows), type); 01085 } 01086 01087 UMat UMat::ones(Size size, int type) 01088 { 01089 return UMat(size, type, Scalar(1)); 01090 } 01091 01092 UMat UMat::ones(int ndims, const int* sz, int type) 01093 { 01094 return UMat(ndims, sz, type, Scalar(1)); 01095 } 01096 01097 UMat UMat::eye(int rows, int cols, int type) 01098 { 01099 return UMat::eye(Size(cols, rows), type); 01100 } 01101 01102 UMat UMat::eye(Size size, int type) 01103 { 01104 UMat m(size, type); 01105 setIdentity(m); 01106 return m; 01107 } 01108 01109 } 01110 01111 /* End of file. */ 01112
Generated on Tue Jul 12 2022 14:47:44 by
