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 deriv.cpp Source File

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