1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
44 /****************************************************************************************/
46 /* lightweight convolution with 3x3 kernel */
47 void icvSepConvSmall3_32f( float* src, int src_step, float* dst, int dst_step,
48 CvSize src_size, const float* kx, const float* ky, float* buffer )
50 int dst_width, buffer_step = 0;
53 assert( src && dst && src_size.width > 2 && src_size.height > 2 &&
54 (src_step & 3) == 0 && (dst_step & 3) == 0 &&
55 (kx || ky) && (buffer || !kx || !ky));
57 src_step /= sizeof(src[0]);
58 dst_step /= sizeof(dst[0]);
60 dst_width = src_size.width - 2;
64 /* set vars, so that vertical convolution
65 will write results into destination ROI and
66 horizontal convolution won't run */
67 src_size.width = dst_width;
68 buffer_step = dst_step;
73 assert( src_step >= src_size.width && dst_step >= dst_width );
78 /* set vars, so that vertical convolution won't run and
79 horizontal convolution will write results into destination ROI */
81 buffer_step = src_step;
86 for( y = 0; y <= src_size.height; y++, src += src_step,
88 buffer += buffer_step )
90 float* src2 = src + src_step;
91 float* src3 = src + src_step*2;
92 for( x = 0; x < src_size.width; x++ )
94 buffer[x] = (float)(ky[0]*src[x] + ky[1]*src2[x] + ky[2]*src3[x]);
97 for( x = 0; x < dst_width; x++ )
99 dst[x] = (float)(kx[0]*buffer[x] + kx[1]*buffer[x+1] + kx[2]*buffer[x+2]);
105 /****************************************************************************************\
106 Sobel & Scharr Derivative Filters
107 \****************************************************************************************/
112 static void getScharrKernels( Mat& kx, Mat& ky, int dx, int dy, bool normalize, int ktype )
116 CV_Assert( ktype == CV_32F || ktype == CV_64F );
118 if( kx.cols != ksize || kx.rows != 1 || kx.type() != ktype )
119 kx.create( ksize, 1, ktype );
120 if( ky.cols != ksize || ky.rows != 1 || ky.type() != ktype )
121 ky.create( ksize, 1, ktype );
123 CV_Assert( dx >= 0 && dy >= 0 && dx+dy == 1 );
125 for( int k = 0; k < 2; k++ )
127 Mat* kernel = k == 0 ? &kx : &ky;
128 int order = k == 0 ? dx : dy;
132 kerI[0] = 3, kerI[1] = 10, kerI[2] = 3;
133 else if( order == 1 )
134 kerI[0] = -1, kerI[1] = 0, kerI[2] = 1;
136 Mat temp(kernel->rows, kernel->cols, CV_32S, &kerI[0]);
137 double scale = !normalize || order == 1 ? 1. : 1./32;
138 temp.convertTo(*kernel, ktype, scale);
143 static void getSobelKernels( Mat& kx, Mat& ky, int dx, int dy, int _ksize, bool normalize, int ktype )
145 int i, j, ksizeX = _ksize, ksizeY = _ksize;
146 if( ksizeX == 1 && dx > 0 )
148 if( ksizeY == 1 && dy > 0 )
151 CV_Assert( ktype == CV_32F || ktype == CV_64F );
153 if( kx.cols != ksizeX || kx.rows != 1 || kx.type() != ktype )
154 kx.create( ksizeX, 1, ktype );
155 if( ky.cols != ksizeY || ky.rows != 1 || ky.type() != ktype )
156 ky.create( ksizeY, 1, ktype );
158 if( _ksize % 2 == 0 || _ksize > 31 )
159 CV_Error( CV_StsOutOfRange, "The kernel size must be odd and not larger than 31" );
160 vector<int> kerI(std::max(ksizeX, ksizeY) + 1);
162 CV_Assert( dx >= 0 && dy >= 0 && dx+dy > 0 );
164 for( int k = 0; k < 2; k++ )
166 Mat* kernel = k == 0 ? &kx : &ky;
167 int order = k == 0 ? dx : dy;
168 int ksize = k == 0 ? ksizeX : ksizeY;
170 CV_Assert( ksize > order );
174 else if( ksize == 3 )
177 kerI[0] = 1, kerI[1] = 2, kerI[2] = 1;
178 else if( order == 1 )
179 kerI[0] = -1, kerI[1] = 0, kerI[2] = 1;
181 kerI[0] = 1, kerI[1] = -2, kerI[2] = 1;
187 for( i = 0; i < ksize; i++ )
190 for( i = 0; i < ksize - order - 1; i++ )
193 for( j = 1; j <= ksize; j++ )
195 newval = kerI[j]+kerI[j-1];
201 for( i = 0; i < order; i++ )
204 for( j = 1; j <= ksize; j++ )
206 newval = kerI[j-1] - kerI[j];
213 Mat temp(kernel->rows, kernel->cols, CV_32S, &kerI[0]);
214 double scale = !normalize ? 1. : 1./(1 << (ksize-order-1));
215 temp.convertTo(*kernel, ktype, scale);
220 void getDerivKernels( Mat& kx, Mat& ky, int dx, int dy,
221 int ksize, bool normalize, int ktype )
224 getScharrKernels( kx, ky, dx, dy, normalize, ktype );
226 getSobelKernels( kx, ky, dx, dy, ksize, normalize, ktype );
230 Ptr<FilterEngine> createDerivFilter(int srcType, int dstType,
231 int dx, int dy, int ksize, int borderType )
234 getDerivKernels( kx, ky, dx, dy, ksize, false, CV_32F );
235 return createSeparableLinearFilter(srcType, dstType,
236 kx, ky, Point(-1,-1), 0, borderType );
240 void Sobel( const Mat& src, Mat& dst, int ddepth, int dx, int dy,
241 int ksize, double scale, double delta, int borderType )
243 int ktype = std::max(CV_32F, std::max(ddepth, src.depth()));
246 getDerivKernels( kx, ky, dx, dy, ksize, false, ktype );
249 // usually the smoothing part is the slowest to compute,
250 // so try to scale it instead of the faster differenciating part
256 sepFilter2D( src, dst, ddepth, kx, ky, Point(-1,-1), delta, borderType );
260 void Scharr( const Mat& src, Mat& dst, int ddepth, int dx, int dy,
261 double scale, double delta, int borderType )
263 int ktype = std::max(CV_32F, std::max(ddepth, src.depth()));
266 getScharrKernels( kx, ky, dx, dy, false, ktype );
269 // usually the smoothing part is the slowest to compute,
270 // so try to scale it instead of the faster differenciating part
276 sepFilter2D( src, dst, ddepth, kx, ky, Point(-1,-1), delta, borderType );
280 void Laplacian( const Mat& src, Mat& dst, int ddepth, int ksize,
281 double scale, double delta, int borderType )
283 if( ksize == 1 || ksize == 3 )
286 {{0, 1, 0, 1, -4, 1, 0, 1, 0},
287 {2, 0, 2, 0, -8, 0, 2, 0, 2}};
288 Mat kernel(3, 3, CV_32F, K[ksize == 3]);
291 filter2D( src, dst, ddepth, kernel, Point(-1,-1), delta, borderType );
295 const size_t STRIPE_SIZE = 1 << 14;
297 int depth = src.depth();
298 int ktype = std::max(CV_32F, std::max(ddepth, depth));
299 int wdepth = depth == CV_8U && ksize <= 5 ? CV_16S : depth <= CV_32F ? CV_32F : CV_64F;
300 int wtype = CV_MAKETYPE(wdepth, src.channels());
302 getSobelKernels( kd, ks, 2, 0, ksize, false, ktype );
304 ddepth = src.depth();
305 int dtype = CV_MAKETYPE(ddepth, src.channels());
306 dst.create( src.size(), dtype );
308 int dy0 = std::min(std::max((int)(STRIPE_SIZE/(getElemSize(src.type())*src.cols)), 1), src.rows);
309 Ptr<FilterEngine> fx = createSeparableLinearFilter(src.type(),
310 wtype, kd, ks, Point(-1,-1), 0, borderType, borderType, Scalar() );
311 Ptr<FilterEngine> fy = createSeparableLinearFilter(src.type(),
312 wtype, ks, kd, Point(-1,-1), 0, borderType, borderType, Scalar() );
314 int y = fx->start(src), dsty = 0, dy = 0;
316 const uchar* sptr = src.data + y*src.step;
318 Mat d2x( dy0 + kd.rows - 1, src.cols, wtype );
319 Mat d2y( dy0 + kd.rows - 1, src.cols, wtype );
321 for( ; dsty < src.rows; sptr += dy0*src.step, dsty += dy )
323 fx->proceed( sptr, (int)src.step, dy0, d2x.data, (int)d2x.step );
324 dy = fy->proceed( sptr, (int)src.step, dy0, d2y.data, (int)d2y.step );
327 Mat dstripe = dst.rowRange(dsty, dsty + dy);
328 d2x.rows = d2y.rows = dy; // modify the headers, which should work
330 d2x.convertTo( dstripe, dtype, scale, delta );
338 /////////////////////////////////////////////////////////////////////////////////////////
341 cvSobel( const void* srcarr, void* dstarr, int dx, int dy, int aperture_size )
343 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
345 CV_Assert( src.size() == dst.size() && src.channels() == dst.channels() &&
346 ((src.depth() == CV_8U && (dst.depth() == CV_16S || dst.depth() == CV_32F)) ||
347 (src.depth() == CV_32F && dst.depth() == CV_32F)));
349 cv::Sobel( src, dst, dst.depth(), dx, dy, aperture_size, 1, 0, cv::BORDER_REPLICATE );
350 if( CV_IS_IMAGE(srcarr) && ((IplImage*)srcarr)->origin && dy % 2 != 0 )
356 cvLaplace( const void* srcarr, void* dstarr, int aperture_size )
358 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
360 CV_Assert( src.size() == dst.size() && src.channels() == dst.channels() &&
361 ((src.depth() == CV_8U && (dst.depth() == CV_16S || dst.depth() == CV_32F)) ||
362 (src.depth() == CV_32F && dst.depth() == CV_32F)));
364 cv::Laplacian( src, dst, dst.depth(), aperture_size, 1, 0, cv::BORDER_REPLICATE );