Renesas GR-PEACH OpenCV Development / gr-peach-opencv-project-sd-card_update

Fork of gr-peach-opencv-project-sd-card by the do

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers umatrix.cpp Source File

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