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
deriv.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 // Intel License Agreement 00011 // For Open Source Computer Vision Library 00012 // 00013 // Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 #include "precomp.hpp" 00044 #include "opencl_kernels_imgproc.hpp" 00045 00046 /****************************************************************************************\ 00047 Sobel & Scharr Derivative Filters 00048 \****************************************************************************************/ 00049 00050 namespace cv 00051 { 00052 00053 static void getScharrKernels( OutputArray _kx, OutputArray _ky, 00054 int dx, int dy, bool normalize, int ktype ) 00055 { 00056 const int ksize = 3; 00057 00058 CV_Assert( ktype == CV_32F || ktype == CV_64F ); 00059 _kx.create(ksize, 1, ktype, -1, true); 00060 _ky.create(ksize, 1, ktype, -1, true); 00061 Mat kx = _kx.getMat(); 00062 Mat ky = _ky.getMat(); 00063 00064 CV_Assert( dx >= 0 && dy >= 0 && dx+dy == 1 ); 00065 00066 for( int k = 0; k < 2; k++ ) 00067 { 00068 Mat* kernel = k == 0 ? &kx : &ky; 00069 int order = k == 0 ? dx : dy; 00070 int kerI[3]; 00071 00072 if( order == 0 ) 00073 kerI[0] = 3, kerI[1] = 10, kerI[2] = 3; 00074 else if( order == 1 ) 00075 kerI[0] = -1, kerI[1] = 0, kerI[2] = 1; 00076 00077 Mat temp(kernel->rows, kernel->cols, CV_32S, &kerI[0]); 00078 double scale = !normalize || order == 1 ? 1. : 1./32; 00079 temp.convertTo(*kernel, ktype, scale); 00080 } 00081 } 00082 00083 00084 static void getSobelKernels( OutputArray _kx, OutputArray _ky, 00085 int dx, int dy, int _ksize, bool normalize, int ktype ) 00086 { 00087 int i, j, ksizeX = _ksize, ksizeY = _ksize; 00088 if( ksizeX == 1 && dx > 0 ) 00089 ksizeX = 3; 00090 if( ksizeY == 1 && dy > 0 ) 00091 ksizeY = 3; 00092 00093 CV_Assert( ktype == CV_32F || ktype == CV_64F ); 00094 00095 _kx.create(ksizeX, 1, ktype, -1, true); 00096 _ky.create(ksizeY, 1, ktype, -1, true); 00097 Mat kx = _kx.getMat(); 00098 Mat ky = _ky.getMat(); 00099 00100 if( _ksize % 2 == 0 || _ksize > 31 ) 00101 CV_Error( CV_StsOutOfRange, "The kernel size must be odd and not larger than 31" ); 00102 std::vector<int> kerI(std::max(ksizeX, ksizeY) + 1); 00103 00104 CV_Assert( dx >= 0 && dy >= 0 && dx+dy > 0 ); 00105 00106 for( int k = 0; k < 2; k++ ) 00107 { 00108 Mat* kernel = k == 0 ? &kx : &ky; 00109 int order = k == 0 ? dx : dy; 00110 int ksize = k == 0 ? ksizeX : ksizeY; 00111 00112 CV_Assert( ksize > order ); 00113 00114 if( ksize == 1 ) 00115 kerI[0] = 1; 00116 else if( ksize == 3 ) 00117 { 00118 if( order == 0 ) 00119 kerI[0] = 1, kerI[1] = 2, kerI[2] = 1; 00120 else if( order == 1 ) 00121 kerI[0] = -1, kerI[1] = 0, kerI[2] = 1; 00122 else 00123 kerI[0] = 1, kerI[1] = -2, kerI[2] = 1; 00124 } 00125 else 00126 { 00127 int oldval, newval; 00128 kerI[0] = 1; 00129 for( i = 0; i < ksize; i++ ) 00130 kerI[i+1] = 0; 00131 00132 for( i = 0; i < ksize - order - 1; i++ ) 00133 { 00134 oldval = kerI[0]; 00135 for( j = 1; j <= ksize; j++ ) 00136 { 00137 newval = kerI[j]+kerI[j-1]; 00138 kerI[j-1] = oldval; 00139 oldval = newval; 00140 } 00141 } 00142 00143 for( i = 0; i < order; i++ ) 00144 { 00145 oldval = -kerI[0]; 00146 for( j = 1; j <= ksize; j++ ) 00147 { 00148 newval = kerI[j-1] - kerI[j]; 00149 kerI[j-1] = oldval; 00150 oldval = newval; 00151 } 00152 } 00153 } 00154 00155 Mat temp(kernel->rows, kernel->cols, CV_32S, &kerI[0]); 00156 double scale = !normalize ? 1. : 1./(1 << (ksize-order-1)); 00157 temp.convertTo(*kernel, ktype, scale); 00158 } 00159 } 00160 00161 } 00162 00163 void cv::getDerivKernels( OutputArray kx, OutputArray ky, int dx, int dy, 00164 int ksize, bool normalize, int ktype ) 00165 { 00166 if( ksize <= 0 ) 00167 getScharrKernels( kx, ky, dx, dy, normalize, ktype ); 00168 else 00169 getSobelKernels( kx, ky, dx, dy, ksize, normalize, ktype ); 00170 } 00171 00172 00173 cv::Ptr<cv::FilterEngine> cv::createDerivFilter(int srcType, int dstType, 00174 int dx, int dy, int ksize, int borderType ) 00175 { 00176 Mat kx, ky; 00177 getDerivKernels( kx, ky, dx, dy, ksize, false, CV_32F ); 00178 return createSeparableLinearFilter(srcType, dstType, 00179 kx, ky, Point(-1,-1), 0, borderType ); 00180 } 00181 00182 #ifdef HAVE_IPP 00183 namespace cv 00184 { 00185 static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) 00186 { 00187 #if IPP_VERSION_X100 >= 810 00188 if ((0 > dx) || (0 > dy) || (1 != dx + dy)) 00189 return false; 00190 if (fabs(delta) > FLT_EPSILON) 00191 return false; 00192 00193 IppiBorderType ippiBorderType = ippiGetBorderType(borderType & (~BORDER_ISOLATED)); 00194 if ((int)ippiBorderType < 0) 00195 return false; 00196 00197 int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); 00198 if (ddepth < 0) 00199 ddepth = sdepth; 00200 int dtype = CV_MAKETYPE(ddepth, cn); 00201 00202 Mat src = _src.getMat(); 00203 if (0 == (BORDER_ISOLATED & borderType)) 00204 { 00205 Size size; Point offset; 00206 src.locateROI(size, offset); 00207 if (0 < offset.x) 00208 ippiBorderType = (IppiBorderType)(ippiBorderType | ippBorderInMemLeft); 00209 if (0 < offset.y) 00210 ippiBorderType = (IppiBorderType)(ippiBorderType | ippBorderInMemTop); 00211 if (offset.x + src.cols < size.width) 00212 ippiBorderType = (IppiBorderType)(ippiBorderType | ippBorderInMemRight); 00213 if (offset.y + src.rows < size.height) 00214 ippiBorderType = (IppiBorderType)(ippiBorderType | ippBorderInMemBottom); 00215 } 00216 00217 bool horz = (0 == dx) && (1 == dy); 00218 IppiSize roiSize = {src.cols, src.rows}; 00219 00220 _dst.create( _src.size(), dtype); 00221 Mat dst = _dst.getMat(); 00222 IppStatus sts = ippStsErr; 00223 if ((CV_8U == stype) && (CV_16S == dtype)) 00224 { 00225 int bufferSize = 0; Ipp8u *pBuffer; 00226 if (horz) 00227 { 00228 if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp8u, ipp16s, 1, &bufferSize)) 00229 return false; 00230 pBuffer = ippsMalloc_8u(bufferSize); 00231 if (NULL == pBuffer) 00232 return false; 00233 sts = ippiFilterScharrHorizMaskBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr<Ipp16s>(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); 00234 } 00235 else 00236 { 00237 if (0 > ippiFilterScharrVertMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp8u, ipp16s, 1, &bufferSize)) 00238 return false; 00239 pBuffer = ippsMalloc_8u(bufferSize); 00240 if (NULL == pBuffer) 00241 return false; 00242 sts = ippiFilterScharrVertMaskBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr<Ipp16s>(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); 00243 } 00244 ippsFree(pBuffer); 00245 } 00246 else if ((CV_16S == stype) && (CV_16S == dtype)) 00247 { 00248 int bufferSize = 0; Ipp8u *pBuffer; 00249 if (horz) 00250 { 00251 if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp16s, ipp16s, 1, &bufferSize)) 00252 return false; 00253 pBuffer = ippsMalloc_8u(bufferSize); 00254 if (NULL == pBuffer) 00255 return false; 00256 sts = ippiFilterScharrHorizMaskBorder_16s_C1R(src.ptr<Ipp16s>(), (int)src.step, dst.ptr<Ipp16s>(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); 00257 } 00258 else 00259 { 00260 if (0 > ippiFilterScharrVertMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp16s, ipp16s, 1, &bufferSize)) 00261 return false; 00262 pBuffer = ippsMalloc_8u(bufferSize); 00263 if (NULL == pBuffer) 00264 return false; 00265 sts = ippiFilterScharrVertMaskBorder_16s_C1R(src.ptr<Ipp16s>(), (int)src.step, dst.ptr<Ipp16s>(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); 00266 } 00267 ippsFree(pBuffer); 00268 } 00269 else if ((CV_32F == stype) && (CV_32F == dtype)) 00270 { 00271 int bufferSize = 0; Ipp8u *pBuffer; 00272 if (horz) 00273 { 00274 if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp32f, ipp32f, 1, &bufferSize)) 00275 return false; 00276 pBuffer = ippsMalloc_8u(bufferSize); 00277 if (NULL == pBuffer) 00278 return false; 00279 sts = ippiFilterScharrHorizMaskBorder_32f_C1R(src.ptr<Ipp32f>(), (int)src.step, dst.ptr<Ipp32f>(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); 00280 } 00281 else 00282 { 00283 if (0 > ippiFilterScharrVertMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp32f, ipp32f, 1, &bufferSize)) 00284 return false; 00285 pBuffer = ippsMalloc_8u(bufferSize); 00286 if (NULL == pBuffer) 00287 return false; 00288 sts = ippiFilterScharrVertMaskBorder_32f_C1R(src.ptr<Ipp32f>(), (int)src.step, dst.ptr<Ipp32f>(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); 00289 } 00290 ippsFree(pBuffer); 00291 if (sts < 0) 00292 return false;; 00293 00294 if (FLT_EPSILON < fabs(scale - 1.0)) 00295 sts = ippiMulC_32f_C1R(dst.ptr<Ipp32f>(), (int)dst.step, (Ipp32f)scale, dst.ptr<Ipp32f>(), (int)dst.step, roiSize); 00296 } 00297 return (0 <= sts); 00298 #else 00299 CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ddepth); CV_UNUSED(dx); CV_UNUSED(dy); CV_UNUSED(scale); CV_UNUSED(delta); CV_UNUSED(borderType); 00300 return false; 00301 #endif 00302 } 00303 00304 static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) 00305 { 00306 if ((borderType != BORDER_REPLICATE) || ((3 != ksize) && (5 != ksize))) 00307 return false; 00308 if (fabs(delta) > FLT_EPSILON) 00309 return false; 00310 if (1 != _src.channels()) 00311 return false; 00312 00313 int bufSize = 0; 00314 cv::AutoBuffer<char> buffer; 00315 Mat src = _src.getMat(), dst = _dst.getMat(); 00316 if ( ddepth < 0 ) 00317 ddepth = src.depth(); 00318 00319 IppiSize roi = {src.cols, src.rows}; 00320 IppiMaskSize kernel = (IppiMaskSize)(ksize*10+ksize); 00321 00322 if (src.type() == CV_8U && dst.type() == CV_16S && scale == 1) 00323 { 00324 if ((dx == 1) && (dy == 0)) 00325 { 00326 #if IPP_VERSION_X100 >= 900 00327 if (0 > ippiFilterSobelNegVertBorderGetBufferSize(roi, kernel, ipp8u, ipp16s, 1,&bufSize)) 00328 return false; 00329 buffer.allocate(bufSize); 00330 #else 00331 if (0 > ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) 00332 return false; 00333 buffer.allocate(bufSize); 00334 #endif 00335 00336 if (0 > ippiFilterSobelNegVertBorder_8u16s_C1R(src.ptr<Ipp8u>(), (int)src.step, 00337 dst.ptr<Ipp16s>(), (int)dst.step, roi, kernel, 00338 ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) 00339 return false; 00340 return true; 00341 } 00342 00343 if ((dx == 0) && (dy == 1)) 00344 { 00345 #if IPP_VERSION_X100 >= 900 00346 if (0 > ippiFilterSobelHorizBorderGetBufferSize(roi, kernel, ipp8u, ipp16s, 1,&bufSize)) 00347 return false; 00348 buffer.allocate(bufSize); 00349 #else 00350 if (0 > ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) 00351 return false; 00352 buffer.allocate(bufSize); 00353 #endif 00354 00355 if (0 > ippiFilterSobelHorizBorder_8u16s_C1R(src.ptr<Ipp8u>(), (int)src.step, 00356 dst.ptr<Ipp16s>(), (int)dst.step, roi, kernel, 00357 ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) 00358 return false; 00359 return true; 00360 } 00361 00362 #if !defined(HAVE_IPP_ICV_ONLY) 00363 if ((dx == 2) && (dy == 0)) 00364 { 00365 #if IPP_VERSION_X100 >= 900 00366 if (0 > ippiFilterSobelVertSecondBorderGetBufferSize(roi, kernel, ipp8u, ipp16s, 1,&bufSize)) 00367 return false; 00368 buffer.allocate(bufSize); 00369 #else 00370 if (0 > ippiFilterSobelVertSecondGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) 00371 return false; 00372 buffer.allocate(bufSize); 00373 #endif 00374 00375 if (0 > ippiFilterSobelVertSecondBorder_8u16s_C1R(src.ptr<Ipp8u>(), (int)src.step, 00376 dst.ptr<Ipp16s>(), (int)dst.step, roi, kernel, 00377 ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) 00378 return false; 00379 return true; 00380 } 00381 00382 if ((dx == 0) && (dy == 2)) 00383 { 00384 #if IPP_VERSION_X100 >= 900 00385 if (0 > ippiFilterSobelHorizSecondBorderGetBufferSize(roi, kernel, ipp8u, ipp16s, 1,&bufSize)) 00386 return false; 00387 buffer.allocate(bufSize); 00388 #else 00389 if (0 > ippiFilterSobelHorizSecondGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) 00390 return false; 00391 buffer.allocate(bufSize); 00392 #endif 00393 00394 if (0 > ippiFilterSobelHorizSecondBorder_8u16s_C1R(src.ptr<Ipp8u>(), (int)src.step, 00395 dst.ptr<Ipp16s>(), (int)dst.step, roi, kernel, 00396 ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) 00397 return false; 00398 return true; 00399 } 00400 #endif 00401 } 00402 00403 if (src.type() == CV_32F && dst.type() == CV_32F) 00404 { 00405 #if IPP_DISABLE_BLOCK 00406 if ((dx == 1) && (dy == 0)) 00407 { 00408 #if IPP_VERSION_X100 >= 900 00409 if (0 > ippiFilterSobelNegVertBorderGetBufferSize(roi, kernel, ipp32f, ipp32f, 1,&bufSize)) 00410 return false; 00411 buffer.allocate(bufSize); 00412 #else 00413 if (0 > ippiFilterSobelNegVertGetBufferSize_32f_C1R(roi, kernel, &bufSize)) 00414 return false; 00415 buffer.allocate(bufSize); 00416 #endif 00417 00418 if (0 > ippiFilterSobelNegVertBorder_32f_C1R(src.ptr<Ipp32f>(), (int)src.step, 00419 dst.ptr<Ipp32f>(), (int)dst.step, roi, kernel, 00420 ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) 00421 return false; 00422 if(scale != 1) 00423 ippiMulC_32f_C1R(dst.ptr<Ipp32f>(), (int)dst.step, (Ipp32f)scale, dst.ptr<Ipp32f>(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); 00424 return true; 00425 } 00426 00427 if ((dx == 0) && (dy == 1)) 00428 { 00429 #if IPP_VERSION_X100 >= 900 00430 if (0 > ippiFilterSobelHorizBorderGetBufferSize(roi, kernel, ipp32f, ipp32f, 1,&bufSize)) 00431 return false; 00432 buffer.allocate(bufSize); 00433 #else 00434 if (0 > ippiFilterSobelHorizGetBufferSize_32f_C1R(roi, kernel,&bufSize)) 00435 return false; 00436 buffer.allocate(bufSize); 00437 #endif 00438 00439 if (0 > ippiFilterSobelHorizBorder_32f_C1R(src.ptr<Ipp32f>(), (int)src.step, 00440 dst.ptr<Ipp32f>(), (int)dst.step, roi, kernel, 00441 ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) 00442 return false; 00443 if(scale != 1) 00444 ippiMulC_32f_C1R(dst.ptr<Ipp32f>(), (int)dst.step, (Ipp32f)scale, dst.ptr<Ipp32f>(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); 00445 return true; 00446 } 00447 #endif 00448 #if !defined(HAVE_IPP_ICV_ONLY) 00449 if((dx == 2) && (dy == 0)) 00450 { 00451 #if IPP_VERSION_X100 >= 900 00452 if (0 > ippiFilterSobelVertSecondBorderGetBufferSize(roi, kernel, ipp32f, ipp32f, 1,&bufSize)) 00453 return false; 00454 buffer.allocate(bufSize); 00455 #else 00456 if (0 > ippiFilterSobelVertSecondGetBufferSize_32f_C1R(roi, kernel,&bufSize)) 00457 return false; 00458 buffer.allocate(bufSize); 00459 #endif 00460 00461 if (0 > ippiFilterSobelVertSecondBorder_32f_C1R(src.ptr<Ipp32f>(), (int)src.step, 00462 dst.ptr<Ipp32f>(), (int)dst.step, roi, kernel, 00463 ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) 00464 return false; 00465 if(scale != 1) 00466 ippiMulC_32f_C1R(dst.ptr<Ipp32f>(), (int)dst.step, (Ipp32f)scale, dst.ptr<Ipp32f>(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); 00467 return true; 00468 } 00469 00470 if((dx == 0) && (dy == 2)) 00471 { 00472 #if IPP_VERSION_X100 >= 900 00473 if (0 > ippiFilterSobelHorizSecondBorderGetBufferSize(roi, kernel, ipp32f, ipp32f, 1,&bufSize)) 00474 return false; 00475 buffer.allocate(bufSize); 00476 #else 00477 if (0 > ippiFilterSobelHorizSecondGetBufferSize_32f_C1R(roi, kernel,&bufSize)) 00478 return false; 00479 buffer.allocate(bufSize); 00480 #endif 00481 00482 if (0 > ippiFilterSobelHorizSecondBorder_32f_C1R(src.ptr<Ipp32f>(), (int)src.step, 00483 dst.ptr<Ipp32f>(), (int)dst.step, roi, kernel, 00484 ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) 00485 return false; 00486 00487 if(scale != 1) 00488 ippiMulC_32f_C1R(dst.ptr<Ipp32f>(), (int)dst.step, (Ipp32f)scale, dst.ptr<Ipp32f>(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); 00489 return true; 00490 } 00491 #endif 00492 } 00493 return false; 00494 } 00495 00496 static bool ipp_sobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) 00497 { 00498 if (ksize < 0) 00499 { 00500 if (IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)) 00501 return true; 00502 } 00503 else if (0 < ksize) 00504 { 00505 if (IPPDerivSobel(_src, _dst, ddepth, dx, dy, ksize, scale, delta, borderType)) 00506 return true; 00507 } 00508 return false; 00509 } 00510 } 00511 #endif 00512 00513 void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, 00514 int ksize, double scale, double delta, int borderType ) 00515 { 00516 int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); 00517 if (ddepth < 0) 00518 ddepth = sdepth; 00519 int dtype = CV_MAKE_TYPE(ddepth, cn); 00520 _dst.create( _src.size(), dtype ); 00521 00522 #ifdef HAVE_TEGRA_OPTIMIZATION 00523 if (tegra::useTegra() && scale == 1.0 && delta == 0) 00524 { 00525 Mat src = _src.getMat(), dst = _dst.getMat(); 00526 if (ksize == 3 && tegra::sobel3x3(src, dst, dx, dy, borderType)) 00527 return; 00528 if (ksize == -1 && tegra::scharr(src, dst, dx, dy, borderType)) 00529 return; 00530 } 00531 #endif 00532 00533 CV_IPP_RUN(true, ipp_sobel(_src, _dst, ddepth, dx, dy, ksize, scale, delta, borderType)); 00534 00535 int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); 00536 00537 Mat kx, ky; 00538 getDerivKernels( kx, ky, dx, dy, ksize, false, ktype ); 00539 if( scale != 1 ) 00540 { 00541 // usually the smoothing part is the slowest to compute, 00542 // so try to scale it instead of the faster differenciating part 00543 if( dx == 0 ) 00544 kx *= scale; 00545 else 00546 ky *= scale; 00547 } 00548 sepFilter2D( _src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType ); 00549 } 00550 00551 00552 void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, 00553 double scale, double delta, int borderType ) 00554 { 00555 int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); 00556 if (ddepth < 0) 00557 ddepth = sdepth; 00558 int dtype = CV_MAKETYPE(ddepth, cn); 00559 _dst.create( _src.size(), dtype ); 00560 00561 #ifdef HAVE_TEGRA_OPTIMIZATION 00562 if (tegra::useTegra() && scale == 1.0 && delta == 0) 00563 { 00564 Mat src = _src.getMat(), dst = _dst.getMat(); 00565 if (tegra::scharr(src, dst, dx, dy, borderType)) 00566 return; 00567 } 00568 #endif 00569 00570 CV_IPP_RUN(true, IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)); 00571 00572 int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); 00573 00574 Mat kx, ky; 00575 getScharrKernels( kx, ky, dx, dy, false, ktype ); 00576 if( scale != 1 ) 00577 { 00578 // usually the smoothing part is the slowest to compute, 00579 // so try to scale it instead of the faster differenciating part 00580 if( dx == 0 ) 00581 kx *= scale; 00582 else 00583 ky *= scale; 00584 } 00585 sepFilter2D( _src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType ); 00586 } 00587 00588 #ifdef HAVE_OPENCL 00589 00590 namespace cv { 00591 00592 #define LAPLACIAN_LOCAL_MEM(tileX, tileY, ksize, elsize) (((tileX) + 2 * (int)((ksize) / 2)) * (3 * (tileY) + 2 * (int)((ksize) / 2)) * elsize) 00593 00594 static bool ocl_Laplacian5(InputArray _src, OutputArray _dst, 00595 const Mat & kd, const Mat & ks, double scale, double delta, 00596 int borderType, int depth, int ddepth) 00597 { 00598 const size_t tileSizeX = 16; 00599 const size_t tileSizeYmin = 8; 00600 00601 const ocl::Device dev = ocl::Device::getDefault(); 00602 00603 int stype = _src.type(); 00604 int sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype), esz = CV_ELEM_SIZE(stype); 00605 00606 bool doubleSupport = dev.doubleFPConfig() > 0; 00607 if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F)) 00608 return false; 00609 00610 Mat kernelX = kd.reshape(1, 1); 00611 if (kernelX.cols % 2 != 1) 00612 return false; 00613 Mat kernelY = ks.reshape(1, 1); 00614 if (kernelY.cols % 2 != 1) 00615 return false; 00616 CV_Assert(kernelX.cols == kernelY.cols); 00617 00618 size_t wgs = dev.maxWorkGroupSize(); 00619 size_t lmsz = dev.localMemSize(); 00620 size_t src_step = _src.step(), src_offset = _src.offset(); 00621 const size_t tileSizeYmax = wgs / tileSizeX; 00622 00623 // workaround for Nvidia: 3 channel vector type takes 4*elem_size in local memory 00624 int loc_mem_cn = dev.vendorID() == ocl::Device::VENDOR_NVIDIA && cn == 3 ? 4 : cn; 00625 00626 if (((src_offset % src_step) % esz == 0) && 00627 ( 00628 (borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE) || 00629 ((borderType == BORDER_REFLECT || borderType == BORDER_WRAP || borderType == BORDER_REFLECT_101) && 00630 (_src.cols() >= (int) (kernelX.cols + tileSizeX) && _src.rows() >= (int) (kernelY.cols + tileSizeYmax))) 00631 ) && 00632 (tileSizeX * tileSizeYmin <= wgs) && 00633 (LAPLACIAN_LOCAL_MEM(tileSizeX, tileSizeYmin, kernelX.cols, loc_mem_cn * 4) <= lmsz) 00634 ) 00635 { 00636 Size size = _src.size(), wholeSize; 00637 Point origin; 00638 int dtype = CV_MAKE_TYPE(ddepth, cn); 00639 int wdepth = CV_32F; 00640 00641 size_t tileSizeY = tileSizeYmax; 00642 while ((tileSizeX * tileSizeY > wgs) || (LAPLACIAN_LOCAL_MEM(tileSizeX, tileSizeY, kernelX.cols, loc_mem_cn * 4) > lmsz)) 00643 { 00644 tileSizeY /= 2; 00645 } 00646 size_t lt2[2] = { tileSizeX, tileSizeY}; 00647 size_t gt2[2] = { lt2[0] * (1 + (size.width - 1) / lt2[0]), lt2[1] }; 00648 00649 char cvt[2][40]; 00650 const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", 00651 "BORDER_REFLECT_101" }; 00652 00653 String opts = cv::format("-D BLK_X=%d -D BLK_Y=%d -D RADIUS=%d%s%s" 00654 " -D convertToWT=%s -D convertToDT=%s" 00655 " -D %s -D srcT1=%s -D dstT1=%s -D WT1=%s" 00656 " -D srcT=%s -D dstT=%s -D WT=%s" 00657 " -D CN=%d ", 00658 (int)lt2[0], (int)lt2[1], kernelX.cols / 2, 00659 ocl::kernelToStr(kernelX, wdepth, "KERNEL_MATRIX_X").c_str(), 00660 ocl::kernelToStr(kernelY, wdepth, "KERNEL_MATRIX_Y").c_str(), 00661 ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]), 00662 ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]), 00663 borderMap[borderType], 00664 ocl::typeToStr(sdepth), ocl::typeToStr(ddepth), ocl::typeToStr(wdepth), 00665 ocl::typeToStr(CV_MAKETYPE(sdepth, cn)), 00666 ocl::typeToStr(CV_MAKETYPE(ddepth, cn)), 00667 ocl::typeToStr(CV_MAKETYPE(wdepth, cn)), 00668 cn); 00669 00670 ocl::Kernel k("laplacian", ocl::imgproc::laplacian5_oclsrc, opts); 00671 if (k.empty()) 00672 return false; 00673 UMat src = _src.getUMat(); 00674 _dst.create(size, dtype); 00675 UMat dst = _dst.getUMat(); 00676 00677 int src_offset_x = static_cast<int>((src_offset % src_step) / esz); 00678 int src_offset_y = static_cast<int>(src_offset / src_step); 00679 00680 src.locateROI(wholeSize, origin); 00681 00682 k.args(ocl::KernelArg::PtrReadOnly(src), (int)src_step, src_offset_x, src_offset_y, 00683 wholeSize.height, wholeSize.width, ocl::KernelArg::WriteOnly(dst), 00684 static_cast<float>(scale), static_cast<float>(delta)); 00685 00686 return k.run(2, gt2, lt2, false); 00687 } 00688 int iscale = cvRound(scale), idelta = cvRound(delta); 00689 bool floatCoeff = std::fabs(delta - idelta) > DBL_EPSILON || std::fabs(scale - iscale) > DBL_EPSILON; 00690 int wdepth = std::max(depth, floatCoeff ? CV_32F : CV_32S), kercn = 1; 00691 00692 if (!doubleSupport && wdepth == CV_64F) 00693 return false; 00694 00695 char cvt[2][40]; 00696 ocl::Kernel k("sumConvert", ocl::imgproc::laplacian5_oclsrc, 00697 format("-D ONLY_SUM_CONVERT " 00698 "-D srcT=%s -D WT=%s -D dstT=%s -D coeffT=%s -D wdepth=%d " 00699 "-D convertToWT=%s -D convertToDT=%s%s", 00700 ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)), 00701 ocl::typeToStr(CV_MAKE_TYPE(wdepth, kercn)), 00702 ocl::typeToStr(CV_MAKE_TYPE(ddepth, kercn)), 00703 ocl::typeToStr(wdepth), wdepth, 00704 ocl::convertTypeStr(depth, wdepth, kercn, cvt[0]), 00705 ocl::convertTypeStr(wdepth, ddepth, kercn, cvt[1]), 00706 doubleSupport ? " -D DOUBLE_SUPPORT" : "")); 00707 if (k.empty()) 00708 return false; 00709 00710 UMat d2x, d2y; 00711 sepFilter2D(_src, d2x, depth, kd, ks, Point(-1, -1), 0, borderType); 00712 sepFilter2D(_src, d2y, depth, ks, kd, Point(-1, -1), 0, borderType); 00713 00714 UMat dst = _dst.getUMat(); 00715 00716 ocl::KernelArg d2xarg = ocl::KernelArg::ReadOnlyNoSize(d2x), 00717 d2yarg = ocl::KernelArg::ReadOnlyNoSize(d2y), 00718 dstarg = ocl::KernelArg::WriteOnly(dst, cn, kercn); 00719 00720 if (wdepth >= CV_32F) 00721 k.args(d2xarg, d2yarg, dstarg, (float)scale, (float)delta); 00722 else 00723 k.args(d2xarg, d2yarg, dstarg, iscale, idelta); 00724 00725 size_t globalsize[] = { (size_t)dst.cols * cn / kercn, (size_t)dst.rows }; 00726 return k.run(2, globalsize, NULL, false); 00727 } 00728 00729 } 00730 00731 #endif 00732 00733 #if defined(HAVE_IPP) 00734 namespace cv 00735 { 00736 static bool ipp_Laplacian(InputArray _src, OutputArray _dst, int ddepth, int ksize, 00737 double scale, double delta, int borderType) 00738 { 00739 int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); 00740 if (ddepth < 0) 00741 ddepth = sdepth; 00742 _dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) ); 00743 00744 int iscale = saturate_cast<int>(scale), idelta = saturate_cast<int>(delta); 00745 bool floatScale = std::fabs(scale - iscale) > DBL_EPSILON, needScale = iscale != 1; 00746 bool floatDelta = std::fabs(delta - idelta) > DBL_EPSILON, needDelta = delta != 0; 00747 int borderTypeNI = borderType & ~BORDER_ISOLATED; 00748 Mat src = _src.getMat(), dst = _dst.getMat(); 00749 00750 if (src.data != dst.data) 00751 { 00752 Ipp32s bufsize; 00753 IppStatus status = (IppStatus)-1; 00754 IppiSize roisize = { src.cols, src.rows }; 00755 IppiMaskSize masksize = ksize == 3 ? ippMskSize3x3 : ippMskSize5x5; 00756 IppiBorderType borderTypeIpp = ippiGetBorderType(borderTypeNI); 00757 00758 #define IPP_FILTER_LAPLACIAN(ippsrctype, ippdsttype, ippfavor) \ 00759 do \ 00760 { \ 00761 if (borderTypeIpp >= 0 && ippiFilterLaplacianGetBufferSize_##ippfavor##_C1R(roisize, masksize, &bufsize) >= 0) \ 00762 { \ 00763 Ipp8u * buffer = ippsMalloc_8u(bufsize); \ 00764 status = ippiFilterLaplacianBorder_##ippfavor##_C1R(src.ptr<ippsrctype>(), (int)src.step, dst.ptr<ippdsttype>(), \ 00765 (int)dst.step, roisize, masksize, borderTypeIpp, 0, buffer); \ 00766 ippsFree(buffer); \ 00767 } \ 00768 } while ((void)0, 0) 00769 00770 CV_SUPPRESS_DEPRECATED_START 00771 if (sdepth == CV_8U && ddepth == CV_16S && !floatScale && !floatDelta) 00772 { 00773 IPP_FILTER_LAPLACIAN(Ipp8u, Ipp16s, 8u16s); 00774 00775 if (needScale && status >= 0) 00776 status = ippiMulC_16s_C1IRSfs((Ipp16s)iscale, dst.ptr<Ipp16s>(), (int)dst.step, roisize, 0); 00777 if (needDelta && status >= 0) 00778 status = ippiAddC_16s_C1IRSfs((Ipp16s)idelta, dst.ptr<Ipp16s>(), (int)dst.step, roisize, 0); 00779 } 00780 else if (sdepth == CV_32F && ddepth == CV_32F) 00781 { 00782 IPP_FILTER_LAPLACIAN(Ipp32f, Ipp32f, 32f); 00783 00784 if (needScale && status >= 0) 00785 status = ippiMulC_32f_C1IR((Ipp32f)scale, dst.ptr<Ipp32f>(), (int)dst.step, roisize); 00786 if (needDelta && status >= 0) 00787 status = ippiAddC_32f_C1IR((Ipp32f)delta, dst.ptr<Ipp32f>(), (int)dst.step, roisize); 00788 } 00789 CV_SUPPRESS_DEPRECATED_END 00790 00791 if (status >= 0) 00792 return true; 00793 } 00794 00795 #undef IPP_FILTER_LAPLACIAN 00796 return false; 00797 } 00798 } 00799 #endif 00800 00801 00802 void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize, 00803 double scale, double delta, int borderType ) 00804 { 00805 int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); 00806 if (ddepth < 0) 00807 ddepth = sdepth; 00808 _dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) ); 00809 00810 CV_IPP_RUN((ksize == 3 || ksize == 5) && ((borderType & BORDER_ISOLATED) != 0 || !_src.isSubmatrix()) && 00811 ((stype == CV_8UC1 && ddepth == CV_16S) || (ddepth == CV_32F && stype == CV_32FC1)) && (!cv::ocl::useOpenCL()), 00812 ipp_Laplacian(_src, _dst, ddepth, ksize, scale, delta, borderType)); 00813 00814 00815 #ifdef HAVE_TEGRA_OPTIMIZATION 00816 if (tegra::useTegra() && scale == 1.0 && delta == 0) 00817 { 00818 Mat src = _src.getMat(), dst = _dst.getMat(); 00819 if (ksize == 1 && tegra::laplace1(src, dst, borderType)) 00820 return; 00821 if (ksize == 3 && tegra::laplace3(src, dst, borderType)) 00822 return; 00823 if (ksize == 5 && tegra::laplace5(src, dst, borderType)) 00824 return; 00825 } 00826 #endif 00827 00828 if( ksize == 1 || ksize == 3 ) 00829 { 00830 float K[2][9] = 00831 { 00832 { 0, 1, 0, 1, -4, 1, 0, 1, 0 }, 00833 { 2, 0, 2, 0, -8, 0, 2, 0, 2 } 00834 }; 00835 Mat kernel(3, 3, CV_32F, K[ksize == 3]); 00836 if( scale != 1 ) 00837 kernel *= scale; 00838 filter2D( _src, _dst, ddepth, kernel, Point(-1, -1), delta, borderType ); 00839 } 00840 else 00841 { 00842 int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); 00843 int wdepth = sdepth == CV_8U && ksize <= 5 ? CV_16S : sdepth <= CV_32F ? CV_32F : CV_64F; 00844 int wtype = CV_MAKETYPE(wdepth, cn); 00845 Mat kd, ks; 00846 getSobelKernels( kd, ks, 2, 0, ksize, false, ktype ); 00847 00848 #ifdef HAVE_OPENCL 00849 CV_OCL_RUN(_dst.isUMat(), 00850 ocl_Laplacian5(_src, _dst, kd, ks, scale, 00851 delta, borderType, wdepth, ddepth)) 00852 #endif 00853 00854 const size_t STRIPE_SIZE = 1 << 14; 00855 Ptr<FilterEngine> fx = createSeparableLinearFilter(stype, 00856 wtype, kd, ks, Point(-1,-1), 0, borderType, borderType, Scalar () ); 00857 Ptr<FilterEngine> fy = createSeparableLinearFilter(stype, 00858 wtype, ks, kd, Point(-1,-1), 0, borderType, borderType, Scalar () ); 00859 00860 Mat src = _src.getMat(), dst = _dst.getMat(); 00861 int y = fx->start(src), dsty = 0, dy = 0; 00862 fy->start(src); 00863 const uchar* sptr = src.ptr() + src.step[0] * y; 00864 00865 int dy0 = std::min(std::max((int)(STRIPE_SIZE/(CV_ELEM_SIZE(stype)*src.cols)), 1), src.rows); 00866 Mat d2x( dy0 + kd.rows - 1, src.cols, wtype ); 00867 Mat d2y( dy0 + kd.rows - 1, src.cols, wtype ); 00868 00869 for( ; dsty < src.rows; sptr += dy0*src.step, dsty += dy ) 00870 { 00871 fx->proceed( sptr, (int)src.step, dy0, d2x.ptr(), (int)d2x.step ); 00872 dy = fy->proceed( sptr, (int)src.step, dy0, d2y.ptr(), (int)d2y.step ); 00873 if( dy > 0 ) 00874 { 00875 Mat dstripe = dst.rowRange(dsty, dsty + dy); 00876 d2x.rows = d2y.rows = dy; // modify the headers, which should work 00877 d2x += d2y; 00878 d2x.convertTo( dstripe, ddepth, scale, delta ); 00879 } 00880 } 00881 } 00882 } 00883 00884 ///////////////////////////////////////////////////////////////////////////////////////// 00885 00886 CV_IMPL void 00887 cvSobel( const void* srcarr, void* dstarr, int dx, int dy, int aperture_size ) 00888 { 00889 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); 00890 00891 CV_Assert( src.size() == dst.size() && src.channels() == dst.channels() ); 00892 00893 cv::Sobel( src, dst, dst.depth(), dx, dy, aperture_size, 1, 0, cv::BORDER_REPLICATE ); 00894 if( CV_IS_IMAGE(srcarr) && ((IplImage*)srcarr)->origin && dy % 2 != 0 ) 00895 dst *= -1; 00896 } 00897 00898 00899 CV_IMPL void 00900 cvLaplace( const void* srcarr, void* dstarr, int aperture_size ) 00901 { 00902 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); 00903 00904 CV_Assert( src.size() == dst.size() && src.channels() == dst.channels() ); 00905 00906 cv::Laplacian( src, dst, dst.depth(), aperture_size, 1, 0, cv::BORDER_REPLICATE ); 00907 } 00908 00909 /* End of file. */ 00910
Generated on Tue Jul 12 2022 14:46:32 by
1.7.2
