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
copy.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 // License Agreement 00010 // For Open Source Computer Vision Library 00011 // 00012 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. 00013 // Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. 00014 // Copyright (C) 2014, Itseez Inc., all rights reserved. 00015 // Third party copyrights are property of their respective owners. 00016 // 00017 // Redistribution and use in source and binary forms, with or without modification, 00018 // are permitted provided that the following conditions are met: 00019 // 00020 // * Redistribution's of source code must retain the above copyright notice, 00021 // this list of conditions and the following disclaimer. 00022 // 00023 // * Redistribution's in binary form must reproduce the above copyright notice, 00024 // this list of conditions and the following disclaimer in the documentation 00025 // and/or other materials provided with the distribution. 00026 // 00027 // * The name of the copyright holders may not be used to endorse or promote products 00028 // derived from this software without specific prior written permission. 00029 // 00030 // This software is provided by the copyright holders and contributors "as is" and 00031 // any express or implied warranties, including, but not limited to, the implied 00032 // warranties of merchantability and fitness for a particular purpose are disclaimed. 00033 // In no event shall the Intel Corporation or contributors be liable for any direct, 00034 // indirect, incidental, special, exemplary, or consequential damages 00035 // (including, but not limited to, procurement of substitute goods or services; 00036 // loss of use, data, or profits; or business interruption) however caused 00037 // and on any theory of liability, whether in contract, strict liability, 00038 // or tort (including negligence or otherwise) arising in any way out of 00039 // the use of this software, even if advised of the possibility of such damage. 00040 // 00041 //M*/ 00042 00043 /* //////////////////////////////////////////////////////////////////// 00044 // 00045 // Mat basic operations: Copy, Set 00046 // 00047 // */ 00048 00049 #include "precomp.hpp" 00050 #include "opencl_kernels_core.hpp" 00051 00052 namespace cv 00053 { 00054 00055 template<typename T> static void 00056 copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size) 00057 { 00058 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep ) 00059 { 00060 const T* src = (const T*)_src; 00061 T* dst = (T*)_dst; 00062 int x = 0; 00063 #if CV_ENABLE_UNROLLED 00064 for( ; x <= size.width - 4; x += 4 ) 00065 { 00066 if( mask[x] ) 00067 dst[x] = src[x]; 00068 if( mask[x+1] ) 00069 dst[x+1] = src[x+1]; 00070 if( mask[x+2] ) 00071 dst[x+2] = src[x+2]; 00072 if( mask[x+3] ) 00073 dst[x+3] = src[x+3]; 00074 } 00075 #endif 00076 for( ; x < size.width; x++ ) 00077 if( mask[x] ) 00078 dst[x] = src[x]; 00079 } 00080 } 00081 00082 template<> void 00083 copyMask_<uchar>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size) 00084 { 00085 CV_IPP_RUN(true, ippiCopy_8u_C1MR(_src, (int)sstep, _dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0) 00086 00087 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep ) 00088 { 00089 const uchar* src = (const uchar*)_src; 00090 uchar* dst = (uchar*)_dst; 00091 int x = 0; 00092 #if CV_SSE4_2 00093 if(USE_SSE4_2)// 00094 { 00095 __m128i zero = _mm_setzero_si128 (); 00096 00097 for( ; x <= size.width - 16; x += 16 ) 00098 { 00099 const __m128i rSrc = _mm_lddqu_si128((const __m128i*)(src+x)); 00100 __m128i _mask = _mm_lddqu_si128((const __m128i*)(mask+x)); 00101 __m128i rDst = _mm_lddqu_si128((__m128i*)(dst+x)); 00102 __m128i _negMask = _mm_cmpeq_epi8(_mask, zero); 00103 rDst = _mm_blendv_epi8(rSrc, rDst, _negMask); 00104 _mm_storeu_si128((__m128i*)(dst + x), rDst); 00105 } 00106 } 00107 #elif CV_NEON 00108 uint8x16_t v_one = vdupq_n_u8(1); 00109 for( ; x <= size.width - 16; x += 16 ) 00110 { 00111 uint8x16_t v_mask = vcgeq_u8(vld1q_u8(mask + x), v_one); 00112 uint8x16_t v_dst = vld1q_u8(dst + x), v_src = vld1q_u8(src + x); 00113 vst1q_u8(dst + x, vbslq_u8(v_mask, v_src, v_dst)); 00114 } 00115 #endif 00116 for( ; x < size.width; x++ ) 00117 if( mask[x] ) 00118 dst[x] = src[x]; 00119 } 00120 } 00121 00122 template<> void 00123 copyMask_<ushort>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size) 00124 { 00125 CV_IPP_RUN(true, ippiCopy_16u_C1MR((const Ipp16u *)_src, (int)sstep, (Ipp16u *)_dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0) 00126 00127 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep ) 00128 { 00129 const ushort* src = (const ushort*)_src; 00130 ushort* dst = (ushort*)_dst; 00131 int x = 0; 00132 #if CV_SSE4_2 00133 if(USE_SSE4_2)// 00134 { 00135 __m128i zero = _mm_setzero_si128 (); 00136 for( ; x <= size.width - 8; x += 8 ) 00137 { 00138 const __m128i rSrc =_mm_lddqu_si128((const __m128i*)(src+x)); 00139 __m128i _mask = _mm_loadl_epi64((const __m128i*)(mask+x)); 00140 _mask = _mm_unpacklo_epi8(_mask, _mask); 00141 __m128i rDst = _mm_lddqu_si128((const __m128i*)(dst+x)); 00142 __m128i _negMask = _mm_cmpeq_epi8(_mask, zero); 00143 rDst = _mm_blendv_epi8(rSrc, rDst, _negMask); 00144 _mm_storeu_si128((__m128i*)(dst + x), rDst); 00145 } 00146 } 00147 #elif CV_NEON 00148 uint8x8_t v_one = vdup_n_u8(1); 00149 for( ; x <= size.width - 8; x += 8 ) 00150 { 00151 uint8x8_t v_mask = vcge_u8(vld1_u8(mask + x), v_one); 00152 uint8x8x2_t v_mask2 = vzip_u8(v_mask, v_mask); 00153 uint16x8_t v_mask_res = vreinterpretq_u16_u8(vcombine_u8(v_mask2.val[0], v_mask2.val[1])); 00154 00155 uint16x8_t v_src = vld1q_u16(src + x), v_dst = vld1q_u16(dst + x); 00156 vst1q_u16(dst + x, vbslq_u16(v_mask_res, v_src, v_dst)); 00157 } 00158 #endif 00159 for( ; x < size.width; x++ ) 00160 if( mask[x] ) 00161 dst[x] = src[x]; 00162 } 00163 } 00164 00165 static void 00166 copyMaskGeneric(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size, void* _esz) 00167 { 00168 size_t k, esz = *(size_t*)_esz; 00169 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep ) 00170 { 00171 const uchar* src = _src; 00172 uchar* dst = _dst; 00173 int x = 0; 00174 for( ; x < size.width; x++, src += esz, dst += esz ) 00175 { 00176 if( !mask[x] ) 00177 continue; 00178 for( k = 0; k < esz; k++ ) 00179 dst[k] = src[k]; 00180 } 00181 } 00182 } 00183 00184 00185 #define DEF_COPY_MASK(suffix, type) \ 00186 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \ 00187 uchar* dst, size_t dstep, Size size, void*) \ 00188 { \ 00189 copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \ 00190 } 00191 00192 #if defined HAVE_IPP 00193 #define DEF_COPY_MASK_F(suffix, type, ippfavor, ipptype) \ 00194 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \ 00195 uchar* dst, size_t dstep, Size size, void*) \ 00196 { \ 00197 CV_IPP_RUN(true, ippiCopy_##ippfavor((const ipptype *)src, (int)sstep, (ipptype *)dst, (int)dstep, ippiSize(size), (const Ipp8u *)mask, (int)mstep) >= 0)\ 00198 copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \ 00199 } 00200 #else 00201 #define DEF_COPY_MASK_F(suffix, type, ippfavor, ipptype) \ 00202 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \ 00203 uchar* dst, size_t dstep, Size size, void*) \ 00204 { \ 00205 copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \ 00206 } 00207 #endif 00208 00209 #if IPP_VERSION_X100 == 901 // bug in IPP 9.0.1 00210 DEF_COPY_MASK(32sC3, Vec3i) 00211 DEF_COPY_MASK(8uC3, Vec3b) 00212 #else 00213 DEF_COPY_MASK_F(8uC3, Vec3b, 8u_C3MR, Ipp8u) 00214 DEF_COPY_MASK_F(32sC3, Vec3i, 32s_C3MR, Ipp32s) 00215 #endif 00216 DEF_COPY_MASK(8u, uchar) 00217 DEF_COPY_MASK(16u, ushort) 00218 DEF_COPY_MASK_F(32s, int, 32s_C1MR, Ipp32s) 00219 DEF_COPY_MASK_F(16uC3, Vec3s, 16u_C3MR, Ipp16u) 00220 DEF_COPY_MASK(32sC2, Vec2i) 00221 DEF_COPY_MASK_F(32sC4, Vec4i, 32s_C4MR, Ipp32s) 00222 DEF_COPY_MASK(32sC6, Vec6i) 00223 DEF_COPY_MASK(32sC8, Vec8i) 00224 00225 BinaryFunc copyMaskTab[] = 00226 { 00227 0, 00228 copyMask8u, 00229 copyMask16u, 00230 copyMask8uC3, 00231 copyMask32s, 00232 0, 00233 copyMask16uC3, 00234 0, 00235 copyMask32sC2, 00236 0, 0, 0, 00237 copyMask32sC3, 00238 0, 0, 0, 00239 copyMask32sC4, 00240 0, 0, 0, 0, 0, 0, 0, 00241 copyMask32sC6, 00242 0, 0, 0, 0, 0, 0, 0, 00243 copyMask32sC8 00244 }; 00245 00246 BinaryFunc getCopyMaskFunc(size_t esz) 00247 { 00248 return esz <= 32 && copyMaskTab[esz] ? copyMaskTab[esz] : copyMaskGeneric; 00249 } 00250 00251 /* dst = src */ 00252 void Mat::copyTo( OutputArray _dst ) const 00253 { 00254 int dtype = _dst.type(); 00255 if( _dst.fixedType() && dtype != type() ) 00256 { 00257 CV_Assert( channels() == CV_MAT_CN(dtype) ); 00258 convertTo( _dst, dtype ); 00259 return; 00260 } 00261 00262 if( empty() ) 00263 { 00264 _dst.release(); 00265 return; 00266 } 00267 00268 if( _dst.isUMat() ) 00269 { 00270 _dst.create( dims, size.p, type() ); 00271 UMat dst = _dst.getUMat(); 00272 00273 size_t i, sz[CV_MAX_DIM], dstofs[CV_MAX_DIM], esz = elemSize(); 00274 for( i = 0; i < (size_t)dims; i++ ) 00275 sz[i] = size.p[i]; 00276 sz[dims-1] *= esz; 00277 dst.ndoffset(dstofs); 00278 dstofs[dims-1] *= esz; 00279 dst.u->currAllocator->upload(dst.u, data, dims, sz, dstofs, dst.step.p, step.p); 00280 return; 00281 } 00282 00283 if( dims <= 2 ) 00284 { 00285 _dst.create( rows, cols, type() ); 00286 Mat dst = _dst.getMat(); 00287 if( data == dst.data ) 00288 return; 00289 00290 if( rows > 0 && cols > 0 ) 00291 { 00292 // For some cases (with vector) dst.size != src.size, so force to column-based form 00293 // It prevents memory corruption in case of column-based src 00294 if (_dst.isVector()) 00295 dst = dst.reshape(0, (int)dst.total()); 00296 00297 const uchar* sptr = data; 00298 uchar* dptr = dst.data; 00299 00300 CV_IPP_RUN( 00301 (size_t)cols*elemSize() <= (size_t)INT_MAX && 00302 (size_t)step <= (size_t)INT_MAX && 00303 (size_t)dst.step <= (size_t)INT_MAX 00304 , 00305 ippiCopy_8u_C1R(sptr, (int)step, dptr, (int)dst.step, ippiSize((int)(cols*elemSize()), rows)) >= 0 00306 ) 00307 00308 Size sz = getContinuousSize(*this, dst); 00309 size_t len = sz.width*elemSize(); 00310 00311 for( ; sz.height--; sptr += step, dptr += dst.step ) 00312 memcpy( dptr, sptr, len ); 00313 } 00314 return; 00315 } 00316 00317 _dst.create( dims, size, type() ); 00318 Mat dst = _dst.getMat(); 00319 if( data == dst.data ) 00320 return; 00321 00322 if( total() != 0 ) 00323 { 00324 const Mat* arrays[] = { this, &dst }; 00325 uchar* ptrs[2]; 00326 NAryMatIterator it(arrays, ptrs, 2); 00327 size_t sz = it.size*elemSize(); 00328 00329 for( size_t i = 0; i < it.nplanes; i++, ++it ) 00330 memcpy(ptrs[1], ptrs[0], sz); 00331 } 00332 } 00333 00334 void Mat::copyTo( OutputArray _dst, InputArray _mask ) const 00335 { 00336 Mat mask = _mask.getMat(); 00337 if( !mask.data ) 00338 { 00339 copyTo(_dst); 00340 return; 00341 } 00342 00343 int cn = channels(), mcn = mask.channels(); 00344 CV_Assert( mask.depth() == CV_8U && (mcn == 1 || mcn == cn) ); 00345 bool colorMask = mcn > 1; 00346 00347 size_t esz = colorMask ? elemSize1() : elemSize(); 00348 BinaryFunc copymask = getCopyMaskFunc(esz); 00349 00350 uchar* data0 = _dst.getMat().data; 00351 _dst.create( dims, size, type() ); 00352 Mat dst = _dst.getMat(); 00353 00354 if( dst.data != data0 ) // do not leave dst uninitialized 00355 dst = Scalar (0); 00356 00357 if( dims <= 2 ) 00358 { 00359 CV_Assert( size() == mask.size() ); 00360 Size sz = getContinuousSize(*this, dst, mask, mcn); 00361 copymask(data, step, mask.data, mask.step, dst.data, dst.step, sz, &esz); 00362 return; 00363 } 00364 00365 const Mat* arrays[] = { this, &dst, &mask, 0 }; 00366 uchar* ptrs[3]; 00367 NAryMatIterator it(arrays, ptrs); 00368 Size sz((int)(it.size*mcn), 1); 00369 00370 for( size_t i = 0; i < it.nplanes; i++, ++it ) 00371 copymask(ptrs[0], 0, ptrs[2], 0, ptrs[1], 0, sz, &esz); 00372 } 00373 00374 Mat& Mat::operator = (const Scalar & s) 00375 { 00376 const Mat* arrays[] = { this }; 00377 uchar* dptr; 00378 NAryMatIterator it(arrays, &dptr, 1); 00379 size_t elsize = it.size*elemSize(); 00380 const int64* is = (const int64*)&s.val[0]; 00381 00382 if( is[0] == 0 && is[1] == 0 && is[2] == 0 && is[3] == 0 ) 00383 { 00384 #if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK 00385 CV_IPP_CHECK() 00386 { 00387 if (dims <= 2 || isContinuous()) 00388 { 00389 IppiSize roisize = { cols, rows }; 00390 if (isContinuous()) 00391 { 00392 roisize.width = (int)total(); 00393 roisize.height = 1; 00394 00395 if (ippsZero_8u(data, static_cast<int>(roisize.width * elemSize())) >= 0) 00396 { 00397 CV_IMPL_ADD(CV_IMPL_IPP) 00398 return *this; 00399 } 00400 setIppErrorStatus(); 00401 } 00402 roisize.width *= (int)elemSize(); 00403 00404 if (ippiSet_8u_C1R(0, data, (int)step, roisize) >= 0) 00405 { 00406 CV_IMPL_ADD(CV_IMPL_IPP) 00407 return *this; 00408 } 00409 setIppErrorStatus(); 00410 } 00411 } 00412 #endif 00413 00414 for( size_t i = 0; i < it.nplanes; i++, ++it ) 00415 memset( dptr, 0, elsize ); 00416 } 00417 else 00418 { 00419 if( it.nplanes > 0 ) 00420 { 00421 double scalar[12]; 00422 scalarToRawData(s, scalar, type(), 12); 00423 size_t blockSize = 12*elemSize1(); 00424 00425 for( size_t j = 0; j < elsize; j += blockSize ) 00426 { 00427 size_t sz = MIN(blockSize, elsize - j); 00428 memcpy( dptr + j, scalar, sz ); 00429 } 00430 } 00431 00432 for( size_t i = 1; i < it.nplanes; i++ ) 00433 { 00434 ++it; 00435 memcpy( dptr, data, elsize ); 00436 } 00437 } 00438 return *this; 00439 } 00440 00441 #if defined HAVE_IPP 00442 static bool ipp_Mat_setTo(Mat *src, Mat &value, Mat &mask) 00443 { 00444 int cn = src->channels(), depth0 = src->depth(); 00445 00446 if (!mask.empty() && (src->dims <= 2 || (src->isContinuous() && mask.isContinuous())) && 00447 (/*depth0 == CV_8U ||*/ depth0 == CV_16U || depth0 == CV_16S || depth0 == CV_32S || depth0 == CV_32F) && 00448 (cn == 1 || cn == 3 || cn == 4)) 00449 { 00450 uchar _buf[32]; 00451 void * buf = _buf; 00452 convertAndUnrollScalar( value, src->type(), _buf, 1 ); 00453 00454 IppStatus status = (IppStatus)-1; 00455 IppiSize roisize = { src->cols, src->rows }; 00456 int mstep = (int)mask.step[0], dstep = (int)src->step[0]; 00457 00458 if (src->isContinuous() && mask.isContinuous()) 00459 { 00460 roisize.width = (int)src->total(); 00461 roisize.height = 1; 00462 } 00463 00464 if (cn == 1) 00465 { 00466 /*if (depth0 == CV_8U) 00467 status = ippiSet_8u_C1MR(*(Ipp8u *)buf, (Ipp8u *)data, dstep, roisize, mask.data, mstep); 00468 else*/ if (depth0 == CV_16U) 00469 status = ippiSet_16u_C1MR(*(Ipp16u *)buf, (Ipp16u *)src->data, dstep, roisize, mask.data, mstep); 00470 else if (depth0 == CV_16S) 00471 status = ippiSet_16s_C1MR(*(Ipp16s *)buf, (Ipp16s *)src->data, dstep, roisize, mask.data, mstep); 00472 else if (depth0 == CV_32S) 00473 status = ippiSet_32s_C1MR(*(Ipp32s *)buf, (Ipp32s *)src->data, dstep, roisize, mask.data, mstep); 00474 else if (depth0 == CV_32F) 00475 status = ippiSet_32f_C1MR(*(Ipp32f *)buf, (Ipp32f *)src->data, dstep, roisize, mask.data, mstep); 00476 } 00477 else if (cn == 3 || cn == 4) 00478 { 00479 00480 #define IPP_SET(ippfavor, ippcn) \ 00481 do \ 00482 { \ 00483 typedef Ipp##ippfavor ipptype; \ 00484 ipptype ippvalue[4] = { ((ipptype *)buf)[0], ((ipptype *)buf)[1], ((ipptype *)buf)[2], ((ipptype *)buf)[3] }; \ 00485 status = ippiSet_##ippfavor##_C##ippcn##MR(ippvalue, (ipptype *)src->data, dstep, roisize, mask.data, mstep); \ 00486 } while ((void)0, 0) 00487 00488 #define IPP_SET_CN(ippcn) \ 00489 do \ 00490 { \ 00491 if (cn == ippcn) \ 00492 { \ 00493 /*if (depth0 == CV_8U) \ 00494 IPP_SET(8u, ippcn); \ 00495 else*/ if (depth0 == CV_16U) \ 00496 IPP_SET(16u, ippcn); \ 00497 else if (depth0 == CV_16S) \ 00498 IPP_SET(16s, ippcn); \ 00499 else if (depth0 == CV_32S) \ 00500 IPP_SET(32s, ippcn); \ 00501 else if (depth0 == CV_32F) \ 00502 IPP_SET(32f, ippcn); \ 00503 } \ 00504 } while ((void)0, 0) 00505 00506 IPP_SET_CN(3); 00507 IPP_SET_CN(4); 00508 00509 #undef IPP_SET_CN 00510 #undef IPP_SET 00511 } 00512 00513 if (status >= 0) 00514 return true; 00515 } 00516 00517 return false; 00518 } 00519 #endif 00520 00521 00522 Mat& Mat::setTo(InputArray _value, InputArray _mask) 00523 { 00524 if( empty() ) 00525 return *this; 00526 00527 Mat value = _value.getMat(), mask = _mask.getMat(); 00528 00529 CV_Assert( checkScalar(value, type(), _value.kind(), _InputArray::MAT )); 00530 CV_Assert( mask.empty() || (mask.type() == CV_8U && size == mask.size) ); 00531 00532 CV_IPP_RUN(true, ipp_Mat_setTo((cv::Mat*)this, value, mask), *this) 00533 00534 size_t esz = elemSize(); 00535 BinaryFunc copymask = getCopyMaskFunc(esz); 00536 00537 const Mat* arrays[] = { this, !mask.empty() ? &mask : 0, 0 }; 00538 uchar* ptrs[2]={0,0}; 00539 NAryMatIterator it(arrays, ptrs); 00540 int totalsz = (int)it.size, blockSize0 = std::min(totalsz, (int)((BLOCK_SIZE + esz-1)/esz)); 00541 AutoBuffer<uchar> _scbuf(blockSize0*esz + 32); 00542 uchar* scbuf = alignPtr((uchar*)_scbuf, (int)sizeof(double)); 00543 convertAndUnrollScalar( value, type(), scbuf, blockSize0 ); 00544 00545 for( size_t i = 0; i < it.nplanes; i++, ++it ) 00546 { 00547 for( int j = 0; j < totalsz; j += blockSize0 ) 00548 { 00549 Size sz(std::min(blockSize0, totalsz - j), 1); 00550 size_t blockSize = sz.width*esz; 00551 if( ptrs[1] ) 00552 { 00553 copymask(scbuf, 0, ptrs[1], 0, ptrs[0], 0, sz, &esz); 00554 ptrs[1] += sz.width; 00555 } 00556 else 00557 memcpy(ptrs[0], scbuf, blockSize); 00558 ptrs[0] += blockSize; 00559 } 00560 } 00561 return *this; 00562 } 00563 00564 00565 static void 00566 flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz ) 00567 { 00568 int i, j, limit = (int)(((size.width + 1)/2)*esz); 00569 AutoBuffer<int> _tab(size.width*esz); 00570 int* tab = _tab; 00571 00572 for( i = 0; i < size.width; i++ ) 00573 for( size_t k = 0; k < esz; k++ ) 00574 tab[i*esz + k] = (int)((size.width - i - 1)*esz + k); 00575 00576 for( ; size.height--; src += sstep, dst += dstep ) 00577 { 00578 for( i = 0; i < limit; i++ ) 00579 { 00580 j = tab[i]; 00581 uchar t0 = src[i], t1 = src[j]; 00582 dst[i] = t1; dst[j] = t0; 00583 } 00584 } 00585 } 00586 00587 static void 00588 flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz ) 00589 { 00590 const uchar* src1 = src0 + (size.height - 1)*sstep; 00591 uchar* dst1 = dst0 + (size.height - 1)*dstep; 00592 size.width *= (int)esz; 00593 00594 for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep, 00595 dst0 += dstep, dst1 -= dstep ) 00596 { 00597 int i = 0; 00598 if( ((size_t)src0|(size_t)dst0|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 ) 00599 { 00600 for( ; i <= size.width - 16; i += 16 ) 00601 { 00602 int t0 = ((int*)(src0 + i))[0]; 00603 int t1 = ((int*)(src1 + i))[0]; 00604 00605 ((int*)(dst0 + i))[0] = t1; 00606 ((int*)(dst1 + i))[0] = t0; 00607 00608 t0 = ((int*)(src0 + i))[1]; 00609 t1 = ((int*)(src1 + i))[1]; 00610 00611 ((int*)(dst0 + i))[1] = t1; 00612 ((int*)(dst1 + i))[1] = t0; 00613 00614 t0 = ((int*)(src0 + i))[2]; 00615 t1 = ((int*)(src1 + i))[2]; 00616 00617 ((int*)(dst0 + i))[2] = t1; 00618 ((int*)(dst1 + i))[2] = t0; 00619 00620 t0 = ((int*)(src0 + i))[3]; 00621 t1 = ((int*)(src1 + i))[3]; 00622 00623 ((int*)(dst0 + i))[3] = t1; 00624 ((int*)(dst1 + i))[3] = t0; 00625 } 00626 00627 for( ; i <= size.width - 4; i += 4 ) 00628 { 00629 int t0 = ((int*)(src0 + i))[0]; 00630 int t1 = ((int*)(src1 + i))[0]; 00631 00632 ((int*)(dst0 + i))[0] = t1; 00633 ((int*)(dst1 + i))[0] = t0; 00634 } 00635 } 00636 00637 for( ; i < size.width; i++ ) 00638 { 00639 uchar t0 = src0[i]; 00640 uchar t1 = src1[i]; 00641 00642 dst0[i] = t1; 00643 dst1[i] = t0; 00644 } 00645 } 00646 } 00647 00648 #ifdef HAVE_OPENCL 00649 00650 enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS }; 00651 00652 static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode ) 00653 { 00654 CV_Assert(flipCode >= -1 && flipCode <= 1); 00655 00656 const ocl::Device & dev = ocl::Device::getDefault(); 00657 int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), 00658 flipType, kercn = std::min(ocl::predictOptimalVectorWidth(_src, _dst), 4); 00659 00660 bool doubleSupport = dev.doubleFPConfig() > 0; 00661 if (!doubleSupport && depth == CV_64F) 00662 kercn = cn; 00663 00664 if (cn > 4) 00665 return false; 00666 00667 const char * kernelName; 00668 if (flipCode == 0) 00669 kernelName = "arithm_flip_rows", flipType = FLIP_ROWS; 00670 else if (flipCode > 0) 00671 kernelName = "arithm_flip_cols", flipType = FLIP_COLS; 00672 else 00673 kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH; 00674 00675 int pxPerWIy = (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1; 00676 kercn = (cn!=3 || flipType == FLIP_ROWS) ? std::max(kercn, cn) : cn; 00677 00678 ocl::Kernel k(kernelName, ocl::core::flip_oclsrc, 00679 format( "-D T=%s -D T1=%s -D cn=%d -D PIX_PER_WI_Y=%d -D kercn=%d", 00680 kercn != cn ? ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)) : ocl::vecopTypeToStr(CV_MAKE_TYPE(depth, kercn)), 00681 kercn != cn ? ocl::typeToStr(depth) : ocl::vecopTypeToStr(depth), cn, pxPerWIy, kercn)); 00682 if (k.empty()) 00683 return false; 00684 00685 Size size = _src.size(); 00686 _dst.create(size, type); 00687 UMat src = _src.getUMat(), dst = _dst.getUMat(); 00688 00689 int cols = size.width * cn / kercn, rows = size.height; 00690 cols = flipType == FLIP_COLS ? (cols + 1) >> 1 : cols; 00691 rows = flipType & FLIP_ROWS ? (rows + 1) >> 1 : rows; 00692 00693 k.args(ocl::KernelArg::ReadOnlyNoSize(src), 00694 ocl::KernelArg::WriteOnly(dst, cn, kercn), rows, cols); 00695 00696 size_t maxWorkGroupSize = dev.maxWorkGroupSize(); 00697 CV_Assert(maxWorkGroupSize % 4 == 0); 00698 00699 size_t globalsize[2] = { (size_t)cols, ((size_t)rows + pxPerWIy - 1) / pxPerWIy }, 00700 localsize[2] = { maxWorkGroupSize / 4, 4 }; 00701 return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false); 00702 } 00703 00704 #endif 00705 00706 #if defined HAVE_IPP 00707 static bool ipp_flip( Mat &src, Mat &dst, int flip_mode ) 00708 { 00709 int type = src.type(); 00710 00711 typedef IppStatus (CV_STDCALL * ippiMirror)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize, IppiAxis flip); 00712 typedef IppStatus (CV_STDCALL * ippiMirrorI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize, IppiAxis flip); 00713 ippiMirror ippFunc = 0; 00714 ippiMirrorI ippFuncI = 0; 00715 00716 if (src.data == dst.data) 00717 { 00718 CV_SUPPRESS_DEPRECATED_START 00719 ippFuncI = 00720 type == CV_8UC1 ? (ippiMirrorI)ippiMirror_8u_C1IR : 00721 type == CV_8UC3 ? (ippiMirrorI)ippiMirror_8u_C3IR : 00722 type == CV_8UC4 ? (ippiMirrorI)ippiMirror_8u_C4IR : 00723 type == CV_16UC1 ? (ippiMirrorI)ippiMirror_16u_C1IR : 00724 type == CV_16UC3 ? (ippiMirrorI)ippiMirror_16u_C3IR : 00725 type == CV_16UC4 ? (ippiMirrorI)ippiMirror_16u_C4IR : 00726 type == CV_16SC1 ? (ippiMirrorI)ippiMirror_16s_C1IR : 00727 type == CV_16SC3 ? (ippiMirrorI)ippiMirror_16s_C3IR : 00728 type == CV_16SC4 ? (ippiMirrorI)ippiMirror_16s_C4IR : 00729 type == CV_32SC1 ? (ippiMirrorI)ippiMirror_32s_C1IR : 00730 type == CV_32SC3 ? (ippiMirrorI)ippiMirror_32s_C3IR : 00731 type == CV_32SC4 ? (ippiMirrorI)ippiMirror_32s_C4IR : 00732 type == CV_32FC1 ? (ippiMirrorI)ippiMirror_32f_C1IR : 00733 type == CV_32FC3 ? (ippiMirrorI)ippiMirror_32f_C3IR : 00734 type == CV_32FC4 ? (ippiMirrorI)ippiMirror_32f_C4IR : 0; 00735 CV_SUPPRESS_DEPRECATED_END 00736 } 00737 else 00738 { 00739 ippFunc = 00740 type == CV_8UC1 ? (ippiMirror)ippiMirror_8u_C1R : 00741 type == CV_8UC3 ? (ippiMirror)ippiMirror_8u_C3R : 00742 type == CV_8UC4 ? (ippiMirror)ippiMirror_8u_C4R : 00743 type == CV_16UC1 ? (ippiMirror)ippiMirror_16u_C1R : 00744 type == CV_16UC3 ? (ippiMirror)ippiMirror_16u_C3R : 00745 type == CV_16UC4 ? (ippiMirror)ippiMirror_16u_C4R : 00746 type == CV_16SC1 ? (ippiMirror)ippiMirror_16s_C1R : 00747 type == CV_16SC3 ? (ippiMirror)ippiMirror_16s_C3R : 00748 type == CV_16SC4 ? (ippiMirror)ippiMirror_16s_C4R : 00749 type == CV_32SC1 ? (ippiMirror)ippiMirror_32s_C1R : 00750 type == CV_32SC3 ? (ippiMirror)ippiMirror_32s_C3R : 00751 type == CV_32SC4 ? (ippiMirror)ippiMirror_32s_C4R : 00752 type == CV_32FC1 ? (ippiMirror)ippiMirror_32f_C1R : 00753 type == CV_32FC3 ? (ippiMirror)ippiMirror_32f_C3R : 00754 type == CV_32FC4 ? (ippiMirror)ippiMirror_32f_C4R : 0; 00755 } 00756 IppiAxis axis = flip_mode == 0 ? ippAxsHorizontal : 00757 flip_mode > 0 ? ippAxsVertical : ippAxsBoth; 00758 IppiSize roisize = { dst.cols, dst.rows }; 00759 00760 if (ippFunc != 0) 00761 { 00762 if (ippFunc(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), axis) >= 0) 00763 return true; 00764 } 00765 else if (ippFuncI != 0) 00766 { 00767 if (ippFuncI(dst.ptr(), (int)dst.step, roisize, axis) >= 0) 00768 return true; 00769 } 00770 00771 return false; 00772 } 00773 #endif 00774 00775 00776 void flip( InputArray _src, OutputArray _dst, int flip_mode ) 00777 { 00778 CV_Assert( _src.dims() <= 2 ); 00779 Size size = _src.size(); 00780 00781 if (flip_mode < 0) 00782 { 00783 if (size.width == 1) 00784 flip_mode = 0; 00785 if (size.height == 1) 00786 flip_mode = 1; 00787 } 00788 00789 if ((size.width == 1 && flip_mode > 0) || 00790 (size.height == 1 && flip_mode == 0) || 00791 (size.height == 1 && size.width == 1 && flip_mode < 0)) 00792 { 00793 return _src.copyTo(_dst); 00794 } 00795 00796 #ifdef HAVE_OPENCL 00797 CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src, _dst, flip_mode)) 00798 #endif 00799 00800 Mat src = _src.getMat(); 00801 int type = src.type(); 00802 _dst.create( size, type ); 00803 Mat dst = _dst.getMat(); 00804 00805 CV_IPP_RUN(true, ipp_flip(src, dst, flip_mode)); 00806 00807 size_t esz = CV_ELEM_SIZE(type); 00808 00809 if( flip_mode <= 0 ) 00810 flipVert( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz ); 00811 else 00812 flipHoriz( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz ); 00813 00814 if( flip_mode < 0 ) 00815 flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz ); 00816 } 00817 00818 #if defined HAVE_OPENCL && !defined __APPLE__ 00819 00820 static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst) 00821 { 00822 if (ny == 1 && nx == 1) 00823 { 00824 _src.copyTo(_dst); 00825 return true; 00826 } 00827 00828 int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), 00829 rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1, 00830 kercn = ocl::predictOptimalVectorWidth(_src, _dst); 00831 00832 ocl::Kernel k("repeat", ocl::core::repeat_oclsrc, 00833 format("-D T=%s -D nx=%d -D ny=%d -D rowsPerWI=%d -D cn=%d", 00834 ocl::memopTypeToStr(CV_MAKE_TYPE(depth, kercn)), 00835 nx, ny, rowsPerWI, kercn)); 00836 if (k.empty()) 00837 return false; 00838 00839 UMat src = _src.getUMat(), dst = _dst.getUMat(); 00840 k.args(ocl::KernelArg::ReadOnly(src, cn, kercn), ocl::KernelArg::WriteOnlyNoSize(dst)); 00841 00842 size_t globalsize[] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI }; 00843 return k.run(2, globalsize, NULL, false); 00844 } 00845 00846 #endif 00847 00848 void repeat(InputArray _src, int ny, int nx, OutputArray _dst) 00849 { 00850 CV_Assert( _src.dims() <= 2 ); 00851 CV_Assert( ny > 0 && nx > 0 ); 00852 00853 Size ssize = _src.size(); 00854 _dst.create(ssize.height*ny, ssize.width*nx, _src.type()); 00855 00856 #if !defined __APPLE__ 00857 #ifdef HAVE_OPENCL 00858 CV_OCL_RUN(_dst.isUMat(), 00859 ocl_repeat(_src, ny, nx, _dst)) 00860 #endif 00861 #endif 00862 00863 Mat src = _src.getMat(), dst = _dst.getMat(); 00864 Size dsize = dst.size(); 00865 int esz = (int)src.elemSize(); 00866 int x, y; 00867 ssize.width *= esz; dsize.width *= esz; 00868 00869 for( y = 0; y < ssize.height; y++ ) 00870 { 00871 for( x = 0; x < dsize.width; x += ssize.width ) 00872 memcpy( dst.ptr(y) + x, src.ptr(y), ssize.width ); 00873 } 00874 00875 for( ; y < dsize.height; y++ ) 00876 memcpy( dst.ptr(y), dst.ptr(y - ssize.height), dsize.width ); 00877 } 00878 00879 Mat repeat(const Mat& src, int ny, int nx) 00880 { 00881 if( nx == 1 && ny == 1 ) 00882 return src; 00883 Mat dst; 00884 repeat(src, ny, nx, dst); 00885 return dst; 00886 } 00887 00888 00889 } // cv 00890 00891 00892 /* 00893 Various border types, image boundaries are denoted with '|' 00894 00895 * BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh 00896 * BORDER_REFLECT: fedcba|abcdefgh|hgfedcb 00897 * BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba 00898 * BORDER_WRAP: cdefgh|abcdefgh|abcdefg 00899 * BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i' 00900 */ 00901 int cv::borderInterpolate( int p, int len, int borderType ) 00902 { 00903 if( (unsigned)p < (unsigned)len ) 00904 ; 00905 else if( borderType == BORDER_REPLICATE ) 00906 p = p < 0 ? 0 : len - 1; 00907 else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 ) 00908 { 00909 int delta = borderType == BORDER_REFLECT_101; 00910 if( len == 1 ) 00911 return 0; 00912 do 00913 { 00914 if( p < 0 ) 00915 p = -p - 1 + delta; 00916 else 00917 p = len - 1 - (p - len) - delta; 00918 } 00919 while( (unsigned)p >= (unsigned)len ); 00920 } 00921 else if( borderType == BORDER_WRAP ) 00922 { 00923 CV_Assert(len > 0); 00924 if( p < 0 ) 00925 p -= ((p-len+1)/len)*len; 00926 if( p >= len ) 00927 p %= len; 00928 } 00929 else if( borderType == BORDER_CONSTANT ) 00930 p = -1; 00931 else 00932 CV_Error( CV_StsBadArg, "Unknown/unsupported border type" ); 00933 return p; 00934 } 00935 00936 namespace 00937 { 00938 00939 void copyMakeBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi, 00940 uchar* dst, size_t dststep, cv::Size dstroi, 00941 int top, int left, int cn, int borderType ) 00942 { 00943 const int isz = (int)sizeof(int); 00944 int i, j, k, elemSize = 1; 00945 bool intMode = false; 00946 00947 if( (cn | srcstep | dststep | (size_t)src | (size_t)dst) % isz == 0 ) 00948 { 00949 cn /= isz; 00950 elemSize = isz; 00951 intMode = true; 00952 } 00953 00954 cv::AutoBuffer<int> _tab((dstroi.width - srcroi.width)*cn); 00955 int* tab = _tab; 00956 int right = dstroi.width - srcroi.width - left; 00957 int bottom = dstroi.height - srcroi.height - top; 00958 00959 for( i = 0; i < left; i++ ) 00960 { 00961 j = cv::borderInterpolate(i - left, srcroi.width, borderType)*cn; 00962 for( k = 0; k < cn; k++ ) 00963 tab[i*cn + k] = j + k; 00964 } 00965 00966 for( i = 0; i < right; i++ ) 00967 { 00968 j = cv::borderInterpolate(srcroi.width + i, srcroi.width, borderType)*cn; 00969 for( k = 0; k < cn; k++ ) 00970 tab[(i+left)*cn + k] = j + k; 00971 } 00972 00973 srcroi.width *= cn; 00974 dstroi.width *= cn; 00975 left *= cn; 00976 right *= cn; 00977 00978 uchar* dstInner = dst + dststep*top + left*elemSize; 00979 00980 for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep ) 00981 { 00982 if( dstInner != src ) 00983 memcpy(dstInner, src, srcroi.width*elemSize); 00984 00985 if( intMode ) 00986 { 00987 const int* isrc = (int*)src; 00988 int* idstInner = (int*)dstInner; 00989 for( j = 0; j < left; j++ ) 00990 idstInner[j - left] = isrc[tab[j]]; 00991 for( j = 0; j < right; j++ ) 00992 idstInner[j + srcroi.width] = isrc[tab[j + left]]; 00993 } 00994 else 00995 { 00996 for( j = 0; j < left; j++ ) 00997 dstInner[j - left] = src[tab[j]]; 00998 for( j = 0; j < right; j++ ) 00999 dstInner[j + srcroi.width] = src[tab[j + left]]; 01000 } 01001 } 01002 01003 dstroi.width *= elemSize; 01004 dst += dststep*top; 01005 01006 for( i = 0; i < top; i++ ) 01007 { 01008 j = cv::borderInterpolate(i - top, srcroi.height, borderType); 01009 memcpy(dst + (i - top)*dststep, dst + j*dststep, dstroi.width); 01010 } 01011 01012 for( i = 0; i < bottom; i++ ) 01013 { 01014 j = cv::borderInterpolate(i + srcroi.height, srcroi.height, borderType); 01015 memcpy(dst + (i + srcroi.height)*dststep, dst + j*dststep, dstroi.width); 01016 } 01017 } 01018 01019 01020 void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi, 01021 uchar* dst, size_t dststep, cv::Size dstroi, 01022 int top, int left, int cn, const uchar* value ) 01023 { 01024 int i, j; 01025 cv::AutoBuffer<uchar> _constBuf(dstroi.width*cn); 01026 uchar* constBuf = _constBuf; 01027 int right = dstroi.width - srcroi.width - left; 01028 int bottom = dstroi.height - srcroi.height - top; 01029 01030 for( i = 0; i < dstroi.width; i++ ) 01031 { 01032 for( j = 0; j < cn; j++ ) 01033 constBuf[i*cn + j] = value[j]; 01034 } 01035 01036 srcroi.width *= cn; 01037 dstroi.width *= cn; 01038 left *= cn; 01039 right *= cn; 01040 01041 uchar* dstInner = dst + dststep*top + left; 01042 01043 for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep ) 01044 { 01045 if( dstInner != src ) 01046 memcpy( dstInner, src, srcroi.width ); 01047 memcpy( dstInner - left, constBuf, left ); 01048 memcpy( dstInner + srcroi.width, constBuf, right ); 01049 } 01050 01051 dst += dststep*top; 01052 01053 for( i = 0; i < top; i++ ) 01054 memcpy(dst + (i - top)*dststep, constBuf, dstroi.width); 01055 01056 for( i = 0; i < bottom; i++ ) 01057 memcpy(dst + (i + srcroi.height)*dststep, constBuf, dstroi.width); 01058 } 01059 01060 } 01061 01062 #ifdef HAVE_OPENCL 01063 01064 namespace cv { 01065 01066 static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom, 01067 int left, int right, int borderType, const Scalar& value ) 01068 { 01069 int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type), 01070 rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1; 01071 bool isolated = (borderType & BORDER_ISOLATED) != 0; 01072 borderType &= ~cv::BORDER_ISOLATED; 01073 01074 if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE || borderType == BORDER_REFLECT || 01075 borderType == BORDER_WRAP || borderType == BORDER_REFLECT_101) || 01076 cn > 4) 01077 return false; 01078 01079 const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" }; 01080 int scalarcn = cn == 3 ? 4 : cn; 01081 int sctype = CV_MAKETYPE(depth, scalarcn); 01082 String buildOptions = format("-D T=%s -D %s -D T1=%s -D cn=%d -D ST=%s -D rowsPerWI=%d", 01083 ocl::memopTypeToStr(type), borderMap[borderType], 01084 ocl::memopTypeToStr(depth), cn, 01085 ocl::memopTypeToStr(sctype), rowsPerWI); 01086 01087 ocl::Kernel k("copyMakeBorder", ocl::core::copymakeborder_oclsrc, buildOptions); 01088 if (k.empty()) 01089 return false; 01090 01091 UMat src = _src.getUMat(); 01092 if( src.isSubmatrix() && !isolated ) 01093 { 01094 Size wholeSize; 01095 Point ofs; 01096 src.locateROI(wholeSize, ofs); 01097 int dtop = std::min(ofs.y, top); 01098 int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom); 01099 int dleft = std::min(ofs.x, left); 01100 int dright = std::min(wholeSize.width - src.cols - ofs.x, right); 01101 src.adjustROI(dtop, dbottom, dleft, dright); 01102 top -= dtop; 01103 left -= dleft; 01104 bottom -= dbottom; 01105 right -= dright; 01106 } 01107 01108 _dst.create(src.rows + top + bottom, src.cols + left + right, type); 01109 UMat dst = _dst.getUMat(); 01110 01111 if (top == 0 && left == 0 && bottom == 0 && right == 0) 01112 { 01113 if(src.u != dst.u || src.step != dst.step) 01114 src.copyTo(dst); 01115 return true; 01116 } 01117 01118 k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst), 01119 top, left, ocl::KernelArg::Constant(Mat(1, 1, sctype, value))); 01120 01121 size_t globalsize[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; 01122 return k.run(2, globalsize, NULL, false); 01123 } 01124 01125 } 01126 01127 #endif 01128 01129 void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom, 01130 int left, int right, int borderType, const Scalar & value ) 01131 { 01132 CV_Assert( top >= 0 && bottom >= 0 && left >= 0 && right >= 0 ); 01133 01134 #ifdef HAVE_OPENCL 01135 CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, 01136 ocl_copyMakeBorder(_src, _dst, top, bottom, left, right, borderType, value)) 01137 #endif 01138 01139 Mat src = _src.getMat(); 01140 int type = src.type(); 01141 01142 if( src.isSubmatrix() && (borderType & BORDER_ISOLATED) == 0 ) 01143 { 01144 Size wholeSize; 01145 Point ofs; 01146 src.locateROI(wholeSize, ofs); 01147 int dtop = std::min(ofs.y, top); 01148 int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom); 01149 int dleft = std::min(ofs.x, left); 01150 int dright = std::min(wholeSize.width - src.cols - ofs.x, right); 01151 src.adjustROI(dtop, dbottom, dleft, dright); 01152 top -= dtop; 01153 left -= dleft; 01154 bottom -= dbottom; 01155 right -= dright; 01156 } 01157 01158 _dst.create( src.rows + top + bottom, src.cols + left + right, type ); 01159 Mat dst = _dst.getMat(); 01160 01161 if(top == 0 && left == 0 && bottom == 0 && right == 0) 01162 { 01163 if(src.data != dst.data || src.step != dst.step) 01164 src.copyTo(dst); 01165 return; 01166 } 01167 01168 borderType &= ~BORDER_ISOLATED; 01169 01170 #if defined HAVE_IPP && IPP_DISABLE_BLOCK 01171 CV_IPP_CHECK() 01172 { 01173 typedef IppStatus (CV_STDCALL * ippiCopyMakeBorder)(const void * pSrc, int srcStep, IppiSize srcRoiSize, void * pDst, 01174 int dstStep, IppiSize dstRoiSize, int topBorderHeight, int leftBorderWidth); 01175 typedef IppStatus (CV_STDCALL * ippiCopyMakeBorderI)(const void * pSrc, int srcDstStep, IppiSize srcRoiSize, IppiSize dstRoiSize, 01176 int topBorderHeight, int leftborderwidth); 01177 typedef IppStatus (CV_STDCALL * ippiCopyConstBorder)(const void * pSrc, int srcStep, IppiSize srcRoiSize, void * pDst, int dstStep, 01178 IppiSize dstRoiSize, int topBorderHeight, int leftBorderWidth, void * value); 01179 01180 IppiSize srcRoiSize = { src.cols, src.rows }, dstRoiSize = { dst.cols, dst.rows }; 01181 ippiCopyMakeBorder ippFunc = 0; 01182 ippiCopyMakeBorderI ippFuncI = 0; 01183 ippiCopyConstBorder ippFuncConst = 0; 01184 bool inplace = dst.datastart == src.datastart; 01185 01186 if (borderType == BORDER_CONSTANT) 01187 { 01188 ippFuncConst = 01189 // type == CV_8UC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_8u_C1R : bug in IPP 8.1 01190 type == CV_16UC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_16u_C1R : 01191 // type == CV_16SC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_16s_C1R : bug in IPP 8.1 01192 // type == CV_32SC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_32s_C1R : bug in IPP 8.1 01193 // type == CV_32FC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_32f_C1R : bug in IPP 8.1 01194 type == CV_8UC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_8u_C3R : 01195 type == CV_16UC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_16u_C3R : 01196 type == CV_16SC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_16s_C3R : 01197 type == CV_32SC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_32s_C3R : 01198 type == CV_32FC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_32f_C3R : 01199 type == CV_8UC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_8u_C4R : 01200 type == CV_16UC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_16u_C4R : 01201 type == CV_16SC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_16s_C4R : 01202 type == CV_32SC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_32s_C4R : 01203 type == CV_32FC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_32f_C4R : 0; 01204 } 01205 else if (borderType == BORDER_WRAP) 01206 { 01207 if (inplace) 01208 { 01209 CV_SUPPRESS_DEPRECATED_START 01210 ippFuncI = 01211 type == CV_32SC1 ? (ippiCopyMakeBorderI)ippiCopyWrapBorder_32s_C1IR : 01212 type == CV_32FC1 ? (ippiCopyMakeBorderI)ippiCopyWrapBorder_32s_C1IR : 0; 01213 CV_SUPPRESS_DEPRECATED_END 01214 } 01215 else 01216 { 01217 ippFunc = 01218 type == CV_32SC1 ? (ippiCopyMakeBorder)ippiCopyWrapBorder_32s_C1R : 01219 type == CV_32FC1 ? (ippiCopyMakeBorder)ippiCopyWrapBorder_32s_C1R : 0; 01220 } 01221 } 01222 else if (borderType == BORDER_REPLICATE) 01223 { 01224 if (inplace) 01225 { 01226 CV_SUPPRESS_DEPRECATED_START 01227 ippFuncI = 01228 type == CV_8UC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_8u_C1IR : 01229 type == CV_16UC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16u_C1IR : 01230 type == CV_16SC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16s_C1IR : 01231 type == CV_32SC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32s_C1IR : 01232 type == CV_32FC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32f_C1IR : 01233 type == CV_8UC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_8u_C3IR : 01234 type == CV_16UC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16u_C3IR : 01235 type == CV_16SC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16s_C3IR : 01236 type == CV_32SC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32s_C3IR : 01237 type == CV_32FC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32f_C3IR : 01238 type == CV_8UC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_8u_C4IR : 01239 type == CV_16UC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16u_C4IR : 01240 type == CV_16SC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16s_C4IR : 01241 type == CV_32SC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32s_C4IR : 01242 type == CV_32FC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32f_C4IR : 0; 01243 CV_SUPPRESS_DEPRECATED_END 01244 } 01245 else 01246 { 01247 ippFunc = 01248 type == CV_8UC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_8u_C1R : 01249 type == CV_16UC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16u_C1R : 01250 type == CV_16SC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16s_C1R : 01251 type == CV_32SC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32s_C1R : 01252 type == CV_32FC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32f_C1R : 01253 type == CV_8UC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_8u_C3R : 01254 type == CV_16UC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16u_C3R : 01255 type == CV_16SC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16s_C3R : 01256 type == CV_32SC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32s_C3R : 01257 type == CV_32FC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32f_C3R : 01258 type == CV_8UC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_8u_C4R : 01259 type == CV_16UC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16u_C4R : 01260 type == CV_16SC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16s_C4R : 01261 type == CV_32SC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32s_C4R : 01262 type == CV_32FC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32f_C4R : 0; 01263 } 01264 } 01265 01266 if (ippFunc || ippFuncI || ippFuncConst) 01267 { 01268 uchar scbuf[32]; 01269 scalarToRawData(value, scbuf, type); 01270 01271 if ( (ippFunc && ippFunc(src.data, (int)src.step, srcRoiSize, dst.data, (int)dst.step, dstRoiSize, top, left) >= 0) || 01272 (ippFuncI && ippFuncI(src.data, (int)src.step, srcRoiSize, dstRoiSize, top, left) >= 0) || 01273 (ippFuncConst && ippFuncConst(src.data, (int)src.step, srcRoiSize, dst.data, (int)dst.step, 01274 dstRoiSize, top, left, scbuf) >= 0)) 01275 { 01276 CV_IMPL_ADD(CV_IMPL_IPP); 01277 return; 01278 } 01279 01280 setIppErrorStatus(); 01281 } 01282 } 01283 #endif 01284 01285 if( borderType != BORDER_CONSTANT ) 01286 copyMakeBorder_8u( src.ptr(), src.step, src.size(), 01287 dst.ptr(), dst.step, dst.size(), 01288 top, left, (int)src.elemSize(), borderType ); 01289 else 01290 { 01291 int cn = src.channels(), cn1 = cn; 01292 AutoBuffer<double> buf(cn); 01293 if( cn > 4 ) 01294 { 01295 CV_Assert( value[0] == value[1] && value[0] == value[2] && value[0] == value[3] ); 01296 cn1 = 1; 01297 } 01298 scalarToRawData(value, buf, CV_MAKETYPE(src.depth(), cn1), cn); 01299 copyMakeConstBorder_8u( src.ptr(), src.step, src.size(), 01300 dst.ptr(), dst.step, dst.size(), 01301 top, left, (int)src.elemSize(), (uchar*)(double*)buf ); 01302 } 01303 } 01304 01305 /* dst = src */ 01306 CV_IMPL void 01307 cvCopy( const void* srcarr, void* dstarr, const void* maskarr ) 01308 { 01309 if( CV_IS_SPARSE_MAT(srcarr) && CV_IS_SPARSE_MAT(dstarr)) 01310 { 01311 CV_Assert( maskarr == 0 ); 01312 CvSparseMat* src1 = (CvSparseMat*)srcarr; 01313 CvSparseMat* dst1 = (CvSparseMat*)dstarr; 01314 CvSparseMatIterator iterator; 01315 CvSparseNode* node; 01316 01317 dst1->dims = src1->dims; 01318 memcpy( dst1->size, src1->size, src1->dims*sizeof(src1->size[0])); 01319 dst1->valoffset = src1->valoffset; 01320 dst1->idxoffset = src1->idxoffset; 01321 cvClearSet( dst1->heap ); 01322 01323 if( src1->heap->active_count >= dst1->hashsize*CV_SPARSE_HASH_RATIO ) 01324 { 01325 cvFree( &dst1->hashtable ); 01326 dst1->hashsize = src1->hashsize; 01327 dst1->hashtable = 01328 (void**)cvAlloc( dst1->hashsize*sizeof(dst1->hashtable[0])); 01329 } 01330 01331 memset( dst1->hashtable, 0, dst1->hashsize*sizeof(dst1->hashtable[0])); 01332 01333 for( node = cvInitSparseMatIterator( src1, &iterator ); 01334 node != 0; node = cvGetNextSparseNode( &iterator )) 01335 { 01336 CvSparseNode* node_copy = (CvSparseNode*)cvSetNew( dst1->heap ); 01337 int tabidx = node->hashval & (dst1->hashsize - 1); 01338 memcpy( node_copy, node, dst1->heap->elem_size ); 01339 node_copy->next = (CvSparseNode*)dst1->hashtable[tabidx]; 01340 dst1->hashtable[tabidx] = node_copy; 01341 } 01342 return; 01343 } 01344 cv::Mat src = cv::cvarrToMat(srcarr, false, true, 1), dst = cv::cvarrToMat(dstarr, false, true, 1); 01345 CV_Assert( src.depth() == dst.depth() && src.size == dst.size ); 01346 01347 int coi1 = 0, coi2 = 0; 01348 if( CV_IS_IMAGE(srcarr) ) 01349 coi1 = cvGetImageCOI((const IplImage*)srcarr); 01350 if( CV_IS_IMAGE(dstarr) ) 01351 coi2 = cvGetImageCOI((const IplImage*)dstarr); 01352 01353 if( coi1 || coi2 ) 01354 { 01355 CV_Assert( (coi1 != 0 || src.channels() == 1) && 01356 (coi2 != 0 || dst.channels() == 1) ); 01357 01358 int pair[] = { std::max(coi1-1, 0), std::max(coi2-1, 0) }; 01359 cv::mixChannels( &src, 1, &dst, 1, pair, 1 ); 01360 return; 01361 } 01362 else 01363 CV_Assert( src.channels() == dst.channels() ); 01364 01365 if( !maskarr ) 01366 src.copyTo(dst); 01367 else 01368 src.copyTo(dst, cv::cvarrToMat(maskarr)); 01369 } 01370 01371 CV_IMPL void 01372 cvSet( void* arr, CvScalar value, const void* maskarr ) 01373 { 01374 cv::Mat m = cv::cvarrToMat(arr); 01375 if( !maskarr ) 01376 m = value; 01377 else 01378 m.setTo(cv::Scalar (value), cv::cvarrToMat(maskarr)); 01379 } 01380 01381 CV_IMPL void 01382 cvSetZero( CvArr* arr ) 01383 { 01384 if( CV_IS_SPARSE_MAT(arr) ) 01385 { 01386 CvSparseMat* mat1 = (CvSparseMat*)arr; 01387 cvClearSet( mat1->heap ); 01388 if( mat1->hashtable ) 01389 memset( mat1->hashtable, 0, mat1->hashsize*sizeof(mat1->hashtable[0])); 01390 return; 01391 } 01392 cv::Mat m = cv::cvarrToMat(arr); 01393 m = cv::Scalar (0); 01394 } 01395 01396 CV_IMPL void 01397 cvFlip( const CvArr* srcarr, CvArr* dstarr, int flip_mode ) 01398 { 01399 cv::Mat src = cv::cvarrToMat(srcarr); 01400 cv::Mat dst; 01401 01402 if (!dstarr) 01403 dst = src; 01404 else 01405 dst = cv::cvarrToMat(dstarr); 01406 01407 CV_Assert( src.type() == dst.type() && src.size() == dst.size() ); 01408 cv::flip( src, dst, flip_mode ); 01409 } 01410 01411 CV_IMPL void 01412 cvRepeat( const CvArr* srcarr, CvArr* dstarr ) 01413 { 01414 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); 01415 CV_Assert( src.type() == dst.type() && 01416 dst.rows % src.rows == 0 && dst.cols % src.cols == 0 ); 01417 cv::repeat(src, dst.rows/src.rows, dst.cols/src.cols, dst); 01418 } 01419 01420 /* End of file. */ 01421
Generated on Tue Jul 12 2022 14:46:29 by
