1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 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. 8 // 9 // 10 // Intel License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000, Intel Corporation, all rights reserved. 14 // Third party copyrights are property of their respective owners. 15 // 16 // Redistribution and use in source and binary forms, with or without modification, 17 // are permitted provided that the following conditions are met: 18 // 19 // * Redistribution's of source code must retain the above copyright notice, 20 // this list of conditions and the following disclaimer. 21 // 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. 25 // 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. 28 // 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. 39 // 40 //M*/ 41 42 #include "_cv.h" 43 44 /****************************************************************************************/ 45 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 ) 49 { 50 int dst_width, buffer_step = 0; 51 int x, y; 52 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)); 56 57 src_step /= sizeof(src[0]); 58 dst_step /= sizeof(dst[0]); 59 60 dst_width = src_size.width - 2; 61 62 if( !kx ) 63 { 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; 69 buffer = dst; 70 dst_width = 0; 71 } 72 73 assert( src_step >= src_size.width && dst_step >= dst_width ); 74 75 src_size.height -= 3; 76 if( !ky ) 77 { 78 /* set vars, so that vertical convolution won't run and 79 horizontal convolution will write results into destination ROI */ 80 src_size.height += 3; 81 buffer_step = src_step; 82 buffer = src; 83 src_size.width = 0; 84 } 85 86 for( y = 0; y <= src_size.height; y++, src += src_step, 87 dst += dst_step, 88 buffer += buffer_step ) 89 { 90 float* src2 = src + src_step; 91 float* src3 = src + src_step*2; 92 for( x = 0; x < src_size.width; x++ ) 93 { 94 buffer[x] = (float)(ky[0]*src[x] + ky[1]*src2[x] + ky[2]*src3[x]); 95 } 96 97 for( x = 0; x < dst_width; x++ ) 98 { 99 dst[x] = (float)(kx[0]*buffer[x] + kx[1]*buffer[x+1] + kx[2]*buffer[x+2]); 100 } 101 } 102 } 103 104 105 /****************************************************************************************\ 106 Sobel & Scharr Derivative Filters 107 \****************************************************************************************/ 108 109 /////////////////////////////// Old IPP derivative filters /////////////////////////////// 110 // still used in corner detectors (see cvcorner.cpp) 111 112 icvFilterSobelVert_8u16s_C1R_t icvFilterSobelVert_8u16s_C1R_p = 0; 113 icvFilterSobelHoriz_8u16s_C1R_t icvFilterSobelHoriz_8u16s_C1R_p = 0; 114 icvFilterSobelVertSecond_8u16s_C1R_t icvFilterSobelVertSecond_8u16s_C1R_p = 0; 115 icvFilterSobelHorizSecond_8u16s_C1R_t icvFilterSobelHorizSecond_8u16s_C1R_p = 0; 116 icvFilterSobelCross_8u16s_C1R_t icvFilterSobelCross_8u16s_C1R_p = 0; 117 118 icvFilterSobelVert_32f_C1R_t icvFilterSobelVert_32f_C1R_p = 0; 119 icvFilterSobelHoriz_32f_C1R_t icvFilterSobelHoriz_32f_C1R_p = 0; 120 icvFilterSobelVertSecond_32f_C1R_t icvFilterSobelVertSecond_32f_C1R_p = 0; 121 icvFilterSobelHorizSecond_32f_C1R_t icvFilterSobelHorizSecond_32f_C1R_p = 0; 122 icvFilterSobelCross_32f_C1R_t icvFilterSobelCross_32f_C1R_p = 0; 123 124 icvFilterScharrVert_8u16s_C1R_t icvFilterScharrVert_8u16s_C1R_p = 0; 125 icvFilterScharrHoriz_8u16s_C1R_t icvFilterScharrHoriz_8u16s_C1R_p = 0; 126 icvFilterScharrVert_32f_C1R_t icvFilterScharrVert_32f_C1R_p = 0; 127 icvFilterScharrHoriz_32f_C1R_t icvFilterScharrHoriz_32f_C1R_p = 0; 128 129 ///////////////////////////////// New IPP derivative filters ///////////////////////////// 130 131 #define IPCV_FILTER_PTRS( name ) \ 132 icvFilter##name##GetBufSize_8u16s_C1R_t \ 133 icvFilter##name##GetBufSize_8u16s_C1R_p = 0; \ 134 icvFilter##name##Border_8u16s_C1R_t \ 135 icvFilter##name##Border_8u16s_C1R_p = 0; \ 136 icvFilter##name##GetBufSize_32f_C1R_t \ 137 icvFilter##name##GetBufSize_32f_C1R_p = 0; \ 138 icvFilter##name##Border_32f_C1R_t \ 139 icvFilter##name##Border_32f_C1R_p = 0; 140 141 IPCV_FILTER_PTRS( ScharrHoriz ) 142 IPCV_FILTER_PTRS( ScharrVert ) 143 IPCV_FILTER_PTRS( SobelHoriz ) 144 IPCV_FILTER_PTRS( SobelNegVert ) 145 IPCV_FILTER_PTRS( SobelHorizSecond ) 146 IPCV_FILTER_PTRS( SobelVertSecond ) 147 IPCV_FILTER_PTRS( SobelCross ) 148 IPCV_FILTER_PTRS( Laplacian ) 149 150 typedef CvStatus (CV_STDCALL * CvDeriv3x3GetBufSizeIPPFunc) 151 ( CvSize roi, int* bufsize ); 152 153 typedef CvStatus (CV_STDCALL * CvDerivGetBufSizeIPPFunc) 154 ( CvSize roi, int masksize, int* bufsize ); 155 156 typedef CvStatus (CV_STDCALL * CvDeriv3x3IPPFunc_8u ) 157 ( const void* src, int srcstep, void* dst, int dststep, 158 CvSize size, int bordertype, uchar bordervalue, void* buffer ); 159 160 typedef CvStatus (CV_STDCALL * CvDeriv3x3IPPFunc_32f ) 161 ( const void* src, int srcstep, void* dst, int dststep, 162 CvSize size, int bordertype, float bordervalue, void* buffer ); 163 164 typedef CvStatus (CV_STDCALL * CvDerivIPPFunc_8u ) 165 ( const void* src, int srcstep, void* dst, int dststep, 166 CvSize size, int masksize, int bordertype, 167 uchar bordervalue, void* buffer ); 168 169 typedef CvStatus (CV_STDCALL * CvDerivIPPFunc_32f ) 170 ( const void* src, int srcstep, void* dst, int dststep, 171 CvSize size, int masksize, int bordertype, 172 float bordervalue, void* buffer ); 173 174 ////////////////////////////////////////////////////////////////////////////////////////// 175 176 CV_IMPL void 177 cvSobel( const void* srcarr, void* dstarr, int dx, int dy, int aperture_size ) 178 { 179 CvSepFilter filter; 180 void* buffer = 0; 181 int local_alloc = 0; 182 183 CV_FUNCNAME( "cvSobel" ); 184 185 __BEGIN__; 186 187 int origin = 0; 188 int src_type, dst_type; 189 CvMat srcstub, *src = (CvMat*)srcarr; 190 CvMat dststub, *dst = (CvMat*)dstarr; 191 192 if( !CV_IS_MAT(src) ) 193 CV_CALL( src = cvGetMat( src, &srcstub )); 194 if( !CV_IS_MAT(dst) ) 195 CV_CALL( dst = cvGetMat( dst, &dststub )); 196 197 if( CV_IS_IMAGE_HDR( srcarr )) 198 origin = ((IplImage*)srcarr)->origin; 199 200 src_type = CV_MAT_TYPE( src->type ); 201 dst_type = CV_MAT_TYPE( dst->type ); 202 203 if( !CV_ARE_SIZES_EQ( src, dst )) 204 CV_ERROR( CV_StsBadArg, "src and dst have different sizes" ); 205 206 if( ((aperture_size == CV_SCHARR || aperture_size == 3 || aperture_size == 5) && 207 dx <= 2 && dy <= 2 && dx + dy <= 2 && icvFilterSobelNegVertBorder_8u16s_C1R_p) && 208 (src_type == CV_8UC1 && dst_type == CV_16SC1/* || 209 src_type == CV_32FC1 && dst_type == CV_32FC1*/) ) 210 { 211 CvDerivGetBufSizeIPPFunc ipp_sobel_getbufsize_func = 0; 212 CvDerivIPPFunc_8u ipp_sobel_func_8u = 0; 213 CvDerivIPPFunc_32f ipp_sobel_func_32f = 0; 214 215 CvDeriv3x3GetBufSizeIPPFunc ipp_scharr_getbufsize_func = 0; 216 CvDeriv3x3IPPFunc_8u ipp_scharr_func_8u = 0; 217 CvDeriv3x3IPPFunc_32f ipp_scharr_func_32f = 0; 218 219 if( aperture_size == CV_SCHARR ) 220 { 221 if( dx == 1 && dy == 0 ) 222 { 223 if( src_type == CV_8U ) 224 ipp_scharr_func_8u = icvFilterScharrVertBorder_8u16s_C1R_p, 225 ipp_scharr_getbufsize_func = icvFilterScharrVertGetBufSize_8u16s_C1R_p; 226 else 227 ipp_scharr_func_32f = icvFilterScharrVertBorder_32f_C1R_p, 228 ipp_scharr_getbufsize_func = icvFilterScharrVertGetBufSize_32f_C1R_p; 229 } 230 else if( dx == 0 && dy == 1 ) 231 { 232 if( src_type == CV_8U ) 233 ipp_scharr_func_8u = icvFilterScharrHorizBorder_8u16s_C1R_p, 234 ipp_scharr_getbufsize_func = icvFilterScharrHorizGetBufSize_8u16s_C1R_p; 235 else 236 ipp_scharr_func_32f = icvFilterScharrHorizBorder_32f_C1R_p, 237 ipp_scharr_getbufsize_func = icvFilterScharrHorizGetBufSize_32f_C1R_p; 238 } 239 else 240 CV_ERROR( CV_StsBadArg, "Scharr filter can only be used to compute 1st image derivatives" ); 241 } 242 else 243 { 244 if( dx == 1 && dy == 0 ) 245 { 246 if( src_type == CV_8U ) 247 ipp_sobel_func_8u = icvFilterSobelNegVertBorder_8u16s_C1R_p, 248 ipp_sobel_getbufsize_func = icvFilterSobelNegVertGetBufSize_8u16s_C1R_p; 249 else 250 ipp_sobel_func_32f = icvFilterSobelNegVertBorder_32f_C1R_p, 251 ipp_sobel_getbufsize_func = icvFilterSobelNegVertGetBufSize_32f_C1R_p; 252 } 253 else if( dx == 0 && dy == 1 ) 254 { 255 if( src_type == CV_8U ) 256 ipp_sobel_func_8u = icvFilterSobelHorizBorder_8u16s_C1R_p, 257 ipp_sobel_getbufsize_func = icvFilterSobelHorizGetBufSize_8u16s_C1R_p; 258 else 259 ipp_sobel_func_32f = icvFilterSobelHorizBorder_32f_C1R_p, 260 ipp_sobel_getbufsize_func = icvFilterSobelHorizGetBufSize_32f_C1R_p; 261 } 262 else if( dx == 2 && dy == 0 ) 263 { 264 if( src_type == CV_8U ) 265 ipp_sobel_func_8u = icvFilterSobelVertSecondBorder_8u16s_C1R_p, 266 ipp_sobel_getbufsize_func = icvFilterSobelVertSecondGetBufSize_8u16s_C1R_p; 267 else 268 ipp_sobel_func_32f = icvFilterSobelVertSecondBorder_32f_C1R_p, 269 ipp_sobel_getbufsize_func = icvFilterSobelVertSecondGetBufSize_32f_C1R_p; 270 } 271 else if( dx == 0 && dy == 2 ) 272 { 273 if( src_type == CV_8U ) 274 ipp_sobel_func_8u = icvFilterSobelHorizSecondBorder_8u16s_C1R_p, 275 ipp_sobel_getbufsize_func = icvFilterSobelHorizSecondGetBufSize_8u16s_C1R_p; 276 else 277 ipp_sobel_func_32f = icvFilterSobelHorizSecondBorder_32f_C1R_p, 278 ipp_sobel_getbufsize_func = icvFilterSobelHorizSecondGetBufSize_32f_C1R_p; 279 } 280 else if( dx == 1 && dy == 1 ) 281 { 282 if( src_type == CV_8U ) 283 ipp_sobel_func_8u = icvFilterSobelCrossBorder_8u16s_C1R_p, 284 ipp_sobel_getbufsize_func = icvFilterSobelCrossGetBufSize_8u16s_C1R_p; 285 else 286 ipp_sobel_func_32f = icvFilterSobelCrossBorder_32f_C1R_p, 287 ipp_sobel_getbufsize_func = icvFilterSobelCrossGetBufSize_32f_C1R_p; 288 } 289 } 290 291 if( ((ipp_sobel_func_8u || ipp_sobel_func_32f) && ipp_sobel_getbufsize_func) || 292 ((ipp_scharr_func_8u || ipp_scharr_func_32f) && ipp_scharr_getbufsize_func) ) 293 { 294 int bufsize = 0, masksize = aperture_size == 3 ? 33 : 55; 295 CvSize size = cvGetMatSize( src ); 296 uchar* src_ptr = src->data.ptr; 297 uchar* dst_ptr = dst->data.ptr; 298 int src_step = src->step ? src->step : CV_STUB_STEP; 299 int dst_step = dst->step ? dst->step : CV_STUB_STEP; 300 const int bordertype = 1; // replication border 301 CvStatus status; 302 303 status = ipp_sobel_getbufsize_func ? 304 ipp_sobel_getbufsize_func( size, masksize, &bufsize ) : 305 ipp_scharr_getbufsize_func( size, &bufsize ); 306 307 if( status >= 0 ) 308 { 309 if( bufsize <= CV_MAX_LOCAL_SIZE ) 310 { 311 buffer = cvStackAlloc( bufsize ); 312 local_alloc = 1; 313 } 314 else 315 CV_CALL( buffer = cvAlloc( bufsize )); 316 317 status = 318 ipp_sobel_func_8u ? ipp_sobel_func_8u( src_ptr, src_step, dst_ptr, dst_step, 319 size, masksize, bordertype, 0, buffer ) : 320 ipp_sobel_func_32f ? ipp_sobel_func_32f( src_ptr, src_step, dst_ptr, dst_step, 321 size, masksize, bordertype, 0, buffer ) : 322 ipp_scharr_func_8u ? ipp_scharr_func_8u( src_ptr, src_step, dst_ptr, dst_step, 323 size, bordertype, 0, buffer ) : 324 ipp_scharr_func_32f ? ipp_scharr_func_32f( src_ptr, src_step, dst_ptr, dst_step, 325 size, bordertype, 0, buffer ) : 326 CV_NOTDEFINED_ERR; 327 } 328 329 if( status >= 0 && 330 ((dx == 0 && dy == 1 && origin) || (dx == 1 && dy == 1 && !origin))) // negate the output 331 cvSubRS( dst, cvScalarAll(0), dst ); 332 333 if( status >= 0 ) 334 EXIT; 335 } 336 } 337 338 CV_CALL( filter.init_deriv( src->cols, src_type, dst_type, dx, dy, 339 aperture_size, origin ? CvSepFilter::FLIP_KERNEL : 0)); 340 CV_CALL( filter.process( src, dst )); 341 342 __END__; 343 344 if( buffer && !local_alloc ) 345 cvFree( &buffer ); 346 } 347 348 349 /****************************************************************************************\ 350 Laplacian Filter 351 \****************************************************************************************/ 352 353 static void icvLaplaceRow_8u32s( const uchar* src, int* dst, void* params ); 354 static void icvLaplaceRow_8u32f( const uchar* src, float* dst, void* params ); 355 static void icvLaplaceRow_32f( const float* src, float* dst, void* params ); 356 static void icvLaplaceCol_32s16s( const int** src, short* dst, int dst_step, 357 int count, void* params ); 358 static void icvLaplaceCol_32f( const float** src, float* dst, int dst_step, 359 int count, void* params ); 360 361 CvLaplaceFilter::CvLaplaceFilter() 362 { 363 normalized = basic_laplacian = false; 364 } 365 366 367 CvLaplaceFilter::CvLaplaceFilter( int _max_width, int _src_type, int _dst_type, bool _normalized, 368 int _ksize, int _border_mode, CvScalar _border_value ) 369 { 370 normalized = basic_laplacian = false; 371 init( _max_width, _src_type, _dst_type, _normalized, _ksize, _border_mode, _border_value ); 372 } 373 374 375 CvLaplaceFilter::~CvLaplaceFilter() 376 { 377 clear(); 378 } 379 380 381 void CvLaplaceFilter::get_work_params() 382 { 383 int min_rows = max_ky*2 + 3, rows = MAX(min_rows,10), row_sz; 384 int width = max_width, trow_sz = 0; 385 int dst_depth = CV_MAT_DEPTH(dst_type); 386 int work_depth = dst_depth < CV_32F ? CV_32S : CV_32F; 387 work_type = CV_MAKETYPE( work_depth, CV_MAT_CN(dst_type)*2 ); 388 trow_sz = cvAlign( (max_width + ksize.width - 1)*CV_ELEM_SIZE(src_type), ALIGN ); 389 row_sz = cvAlign( width*CV_ELEM_SIZE(work_type), ALIGN ); 390 buf_size = rows*row_sz; 391 buf_size = MIN( buf_size, 1 << 16 ); 392 buf_size = MAX( buf_size, min_rows*row_sz ); 393 max_rows = (buf_size/row_sz)*3 + max_ky*2 + 8; 394 buf_size += trow_sz; 395 } 396 397 398 void CvLaplaceFilter::init( int _max_width, int _src_type, int _dst_type, bool _normalized, 399 int _ksize0, int _border_mode, CvScalar _border_value ) 400 { 401 CvMat *kx = 0, *ky = 0; 402 403 CV_FUNCNAME( "CvLaplaceFilter::init" ); 404 405 __BEGIN__; 406 407 int src_depth = CV_MAT_DEPTH(_src_type), dst_depth = CV_MAT_DEPTH(_dst_type); 408 int _ksize = MAX( _ksize0, 3 ); 409 410 normalized = _normalized; 411 basic_laplacian = _ksize0 == 1; 412 413 if( ((src_depth != CV_8U || (dst_depth != CV_16S && dst_depth != CV_32F)) && 414 (src_depth != CV_32F || dst_depth != CV_32F)) || 415 CV_MAT_CN(_src_type) != CV_MAT_CN(_dst_type) ) 416 CV_ERROR( CV_StsUnmatchedFormats, 417 "Laplacian can either transform 8u->16s, or 8u->32f, or 32f->32f.\n" 418 "The number of channels must be the same." ); 419 420 if( _ksize < 1 || _ksize > CV_MAX_SOBEL_KSIZE || _ksize % 2 == 0 ) 421 CV_ERROR( CV_StsOutOfRange, "kernel size must be within 1..7 and odd" ); 422 423 CV_CALL( kx = cvCreateMat( 1, _ksize, CV_32F )); 424 CV_CALL( ky = cvCreateMat( 1, _ksize, CV_32F )); 425 426 CvSepFilter::init_sobel_kernel( kx, ky, 2, 0, 0 ); 427 CvSepFilter::init( _max_width, _src_type, _dst_type, kx, ky, 428 cvPoint(-1,-1), _border_mode, _border_value ); 429 430 x_func = 0; 431 y_func = 0; 432 433 if( src_depth == CV_8U ) 434 { 435 if( dst_depth == CV_16S ) 436 { 437 x_func = (CvRowFilterFunc)icvLaplaceRow_8u32s; 438 y_func = (CvColumnFilterFunc)icvLaplaceCol_32s16s; 439 } 440 else if( dst_depth == CV_32F ) 441 { 442 x_func = (CvRowFilterFunc)icvLaplaceRow_8u32f; 443 y_func = (CvColumnFilterFunc)icvLaplaceCol_32f; 444 } 445 } 446 else if( src_depth == CV_32F ) 447 { 448 if( dst_depth == CV_32F ) 449 { 450 x_func = (CvRowFilterFunc)icvLaplaceRow_32f; 451 y_func = (CvColumnFilterFunc)icvLaplaceCol_32f; 452 } 453 } 454 455 if( !x_func || !y_func ) 456 CV_ERROR( CV_StsUnsupportedFormat, "" ); 457 458 __END__; 459 460 cvReleaseMat( &kx ); 461 cvReleaseMat( &ky ); 462 } 463 464 465 void CvLaplaceFilter::init( int _max_width, int _src_type, int _dst_type, 466 bool _is_separable, CvSize _ksize, 467 CvPoint _anchor, int _border_mode, 468 CvScalar _border_value ) 469 { 470 CvSepFilter::init( _max_width, _src_type, _dst_type, _is_separable, 471 _ksize, _anchor, _border_mode, _border_value ); 472 } 473 474 475 void CvLaplaceFilter::init( int _max_width, int _src_type, int _dst_type, 476 const CvMat* _kx, const CvMat* _ky, 477 CvPoint _anchor, int _border_mode, 478 CvScalar _border_value ) 479 { 480 CvSepFilter::init( _max_width, _src_type, _dst_type, _kx, _ky, 481 _anchor, _border_mode, _border_value ); 482 } 483 484 485 #define ICV_LAPLACE_ROW( flavor, srctype, dsttype, load_macro ) \ 486 static void \ 487 icvLaplaceRow_##flavor( const srctype* src, dsttype* dst, void* params )\ 488 { \ 489 const CvLaplaceFilter* state = (const CvLaplaceFilter*)params; \ 490 const CvMat* _kx = state->get_x_kernel(); \ 491 const CvMat* _ky = state->get_y_kernel(); \ 492 const dsttype* kx = (dsttype*)_kx->data.ptr; \ 493 const dsttype* ky = (dsttype*)_ky->data.ptr; \ 494 int ksize = _kx->cols + _kx->rows - 1; \ 495 int i = 0, j, k, width = state->get_width(); \ 496 int cn = CV_MAT_CN(state->get_src_type()); \ 497 int ksize2 = ksize/2, ksize2n = ksize2*cn; \ 498 const srctype* s = src + ksize2n; \ 499 bool basic_laplacian = state->is_basic_laplacian(); \ 500 \ 501 kx += ksize2; \ 502 ky += ksize2; \ 503 width *= cn; \ 504 \ 505 if( basic_laplacian ) \ 506 for( i = 0; i < width; i++ ) \ 507 { \ 508 dsttype s0 = load_macro(s[i]); \ 509 dsttype s1 = (dsttype)(s[i-cn] - s0*2 + s[i+cn]); \ 510 dst[i] = s0; dst[i+width] = s1; \ 511 } \ 512 else if( ksize == 3 ) \ 513 for( i = 0; i < width; i++ ) \ 514 { \ 515 dsttype s0 = (dsttype)(s[i-cn] + s[i]*2 + s[i+cn]); \ 516 dsttype s1 = (dsttype)(s[i-cn] - s[i]*2 + s[i+cn]); \ 517 dst[i] = s0; dst[i+width] = s1; \ 518 } \ 519 else if( ksize == 5 ) \ 520 for( i = 0; i < width; i++ ) \ 521 { \ 522 dsttype s0 = (dsttype)(s[i-2*cn]+(s[i-cn]+s[i+cn])*4+s[i]*6+s[i+2*cn]);\ 523 dsttype s1 = (dsttype)(s[i-2*cn]-s[i]*2+s[i+2*cn]); \ 524 dst[i] = s0; dst[i+width] = s1; \ 525 } \ 526 else \ 527 for( i = 0; i < width; i++, s++ ) \ 528 { \ 529 dsttype s0 = ky[0]*load_macro(s[0]), s1 = kx[0]*load_macro(s[0]);\ 530 for( k = 1, j = cn; k <= ksize2; k++, j += cn ) \ 531 { \ 532 dsttype t = load_macro(s[j] + s[-j]); \ 533 s0 += ky[k]*t; s1 += kx[k]*t; \ 534 } \ 535 dst[i] = s0; dst[i+width] = s1; \ 536 } \ 537 } 538 539 ICV_LAPLACE_ROW( 8u32s, uchar, int, CV_NOP ) 540 ICV_LAPLACE_ROW( 8u32f, uchar, float, CV_8TO32F ) 541 ICV_LAPLACE_ROW( 32f, float, float, CV_NOP ) 542 543 static void 544 icvLaplaceCol_32s16s( const int** src, short* dst, 545 int dst_step, int count, void* params ) 546 { 547 const CvLaplaceFilter* state = (const CvLaplaceFilter*)params; 548 const CvMat* _kx = state->get_x_kernel(); 549 const CvMat* _ky = state->get_y_kernel(); 550 const int* kx = (const int*)_kx->data.ptr; 551 const int* ky = (const int*)_ky->data.ptr; 552 int ksize = _kx->cols + _kx->rows - 1, ksize2 = ksize/2; 553 int i = 0, k, width = state->get_width(); 554 int cn = CV_MAT_CN(state->get_src_type()); 555 bool basic_laplacian = state->is_basic_laplacian(); 556 bool normalized = state->is_normalized(); 557 int shift = ksize - 1, delta = (1 << shift) >> 1; 558 559 width *= cn; 560 src += ksize2; 561 kx += ksize2; 562 ky += ksize2; 563 dst_step /= sizeof(dst[0]); 564 565 if( basic_laplacian || !normalized ) 566 { 567 normalized = false; 568 shift = delta = 0; 569 } 570 571 for( ; count--; dst += dst_step, src++ ) 572 { 573 if( ksize == 3 ) 574 { 575 const int *src0 = src[-1], *src1 = src[0], *src2 = src[1]; 576 if( basic_laplacian ) 577 { 578 for( i = 0; i <= width - 2; i += 2 ) 579 { 580 int s0 = src0[i] - src1[i]*2 + src2[i] + src1[i+width]; 581 int s1 = src0[i+1] - src1[i+1]*2 + src2[i+1] + src1[i+width+1]; 582 dst[i] = (short)s0; dst[i+1] = (short)s1; 583 } 584 585 for( ; i < width; i++ ) 586 dst[i] = (short)(src0[i] - src1[i]*2 + src2[i] + src1[i+width]); 587 } 588 else if( !normalized ) 589 for( i = 0; i <= width - 2; i += 2 ) 590 { 591 int s0 = src0[i] - src1[i]*2 + src2[i] + 592 src0[i+width] + src1[i+width]*2 + src2[i+width]; 593 int s1 = src0[i+1] - src1[i+1]*2 + src2[i+1] + 594 src0[i+width+1] + src1[i+width+1]*2 + src2[i+width+1]; 595 dst[i] = (short)s0; dst[i+1] = (short)s1; 596 } 597 else 598 for( i = 0; i <= width - 2; i += 2 ) 599 { 600 int s0 = CV_DESCALE(src0[i] - src1[i]*2 + src2[i] + 601 src0[i+width] + src1[i+width]*2 + src2[i+width], 2); 602 int s1 = CV_DESCALE(src0[i+1] - src1[i+1]*2 + src2[i+1] + 603 src0[i+width+1] + src1[i+width+1]*2 + src2[i+width+1],2); 604 dst[i] = (short)s0; dst[i+1] = (short)s1; 605 } 606 } 607 else if( ksize == 5 ) 608 { 609 const int *src0 = src[-2], *src1 = src[-1], *src2 = src[0], *src3 = src[1], *src4 = src[2]; 610 611 if( !normalized ) 612 for( i = 0; i <= width - 2; i += 2 ) 613 { 614 int s0 = src0[i] - src2[i]*2 + src4[i] + src0[i+width] + src4[i+width] + 615 (src1[i+width] + src3[i+width])*4 + src2[i+width]*6; 616 int s1 = src0[i+1] - src2[i+1]*2 + src4[i+1] + src0[i+width+1] + 617 src4[i+width+1] + (src1[i+width+1] + src3[i+width+1])*4 + 618 src2[i+width+1]*6; 619 dst[i] = (short)s0; dst[i+1] = (short)s1; 620 } 621 else 622 for( i = 0; i <= width - 2; i += 2 ) 623 { 624 int s0 = CV_DESCALE(src0[i] - src2[i]*2 + src4[i] + 625 src0[i+width] + src4[i+width] + 626 (src1[i+width] + src3[i+width])*4 + src2[i+width]*6, 4); 627 int s1 = CV_DESCALE(src0[i+1] - src2[i+1]*2 + src4[i+1] + 628 src0[i+width+1] + src4[i+width+1] + 629 (src1[i+width+1] + src3[i+width+1])*4 + src2[i+width+1]*6, 4); 630 dst[i] = (short)s0; dst[i+1] = (short)s1; 631 } 632 } 633 else 634 { 635 if( !normalized ) 636 for( i = 0; i <= width - 2; i += 2 ) 637 { 638 int s0 = kx[0]*src[0][i] + ky[0]*src[0][i+width]; 639 int s1 = kx[0]*src[0][i+1] + ky[0]*src[0][i+width+1]; 640 641 for( k = 1; k <= ksize2; k++ ) 642 { 643 const int* src1 = src[k] + i, *src2 = src[-k] + i; 644 int fx = kx[k], fy = ky[k]; 645 s0 += fx*(src1[0] + src2[0]) + fy*(src1[width] + src2[width]); 646 s1 += fx*(src1[1] + src2[1]) + fy*(src1[width+1] + src2[width+1]); 647 } 648 649 dst[i] = CV_CAST_16S(s0); dst[i+1] = CV_CAST_16S(s1); 650 } 651 else 652 for( i = 0; i <= width - 2; i += 2 ) 653 { 654 int s0 = kx[0]*src[0][i] + ky[0]*src[0][i+width]; 655 int s1 = kx[0]*src[0][i+1] + ky[0]*src[0][i+width+1]; 656 657 for( k = 1; k <= ksize2; k++ ) 658 { 659 const int* src1 = src[k] + i, *src2 = src[-k] + i; 660 int fx = kx[k], fy = ky[k]; 661 s0 += fx*(src1[0] + src2[0]) + fy*(src1[width] + src2[width]); 662 s1 += fx*(src1[1] + src2[1]) + fy*(src1[width+1] + src2[width+1]); 663 } 664 665 s0 = CV_DESCALE( s0, shift ); s1 = CV_DESCALE( s1, shift ); 666 dst[i] = (short)s0; dst[i+1] = (short)s1; 667 } 668 } 669 670 for( ; i < width; i++ ) 671 { 672 int s0 = kx[0]*src[0][i] + ky[0]*src[0][i+width]; 673 for( k = 1; k <= ksize2; k++ ) 674 { 675 const int* src1 = src[k] + i, *src2 = src[-k] + i; 676 s0 += kx[k]*(src1[0] + src2[0]) + ky[k]*(src1[width] + src2[width]); 677 } 678 s0 = (s0 + delta) >> shift; 679 dst[i] = CV_CAST_16S(s0); 680 } 681 } 682 } 683 684 685 static void 686 icvLaplaceCol_32f( const float** src, float* dst, 687 int dst_step, int count, void* params ) 688 { 689 const CvLaplaceFilter* state = (const CvLaplaceFilter*)params; 690 const CvMat* _kx = state->get_x_kernel(); 691 const CvMat* _ky = state->get_y_kernel(); 692 const float* kx = (const float*)_kx->data.ptr; 693 const float* ky = (const float*)_ky->data.ptr; 694 int ksize = _kx->cols + _kx->rows - 1, ksize2 = ksize/2; 695 int i = 0, k, width = state->get_width(); 696 int cn = CV_MAT_CN(state->get_src_type()); 697 bool basic_laplacian = state->is_basic_laplacian(); 698 bool normalized = state->is_normalized(); 699 float scale = 1.f/(1 << (ksize - 1)); 700 701 width *= cn; 702 src += ksize2; 703 kx += ksize2; 704 ky += ksize2; 705 dst_step /= sizeof(dst[0]); 706 707 if( basic_laplacian || !normalized ) 708 { 709 normalized = false; 710 scale = 1.f; 711 } 712 713 for( ; count--; dst += dst_step, src++ ) 714 { 715 if( ksize == 3 ) 716 { 717 const float *src0 = src[-1], *src1 = src[0], *src2 = src[1]; 718 if( basic_laplacian ) 719 { 720 for( i = 0; i <= width - 2; i += 2 ) 721 { 722 float s0 = src0[i] - src1[i]*2 + src2[i] + src1[i+width]; 723 float s1 = src0[i+1] - src1[i+1]*2 + src2[i+1] + src1[i+width+1]; 724 dst[i] = s0; dst[i+1] = s1; 725 } 726 727 for( ; i < width; i++ ) 728 dst[i] = src0[i] - src1[i]*2 + src2[i] + src1[i+width]; 729 } 730 else if( !normalized ) 731 for( i = 0; i <= width - 2; i += 2 ) 732 { 733 float s0 = src0[i] - src1[i]*2 + src2[i] + 734 src0[i+width] + src1[i+width]*2 + src2[i+width]; 735 float s1 = src0[i+1] - src1[i+1]*2 + src2[i+1] + 736 src0[i+width+1] + src1[i+width+1]*2 + src2[i+width+1]; 737 dst[i] = s0; dst[i+1] = s1; 738 } 739 else 740 for( i = 0; i <= width - 2; i += 2 ) 741 { 742 float s0 = (src0[i] - src1[i]*2 + src2[i] + 743 src0[i+width] + src1[i+width]*2 + src2[i+width])*scale; 744 float s1 = (src0[i+1] - src1[i+1]*2 + src2[i+1] + 745 src0[i+width+1] + src1[i+width+1]*2 + src2[i+width+1])*scale; 746 dst[i] = s0; dst[i+1] = s1; 747 } 748 } 749 else if( ksize == 5 ) 750 { 751 const float *src0 = src[-2], *src1 = src[-1], *src2 = src[0], *src3 = src[1], *src4 = src[2]; 752 for( i = 0; i <= width - 2; i += 2 ) 753 { 754 float s0 = (src0[i] - src2[i]*2 + src4[i] + 755 src0[i+width] + src4[i+width] + 756 (src1[i+width] + src3[i+width])*4 + src2[i+width]*6)*scale; 757 float s1 = (src0[i+1] - src2[i+1]*2 + src4[i+1] + 758 src0[i+width+1] + src4[i+width+1] + 759 (src1[i+width+1] + src3[i+width+1])*4 + src2[i+width+1]*6)*scale; 760 dst[i] = s0; dst[i+1] = s1; 761 } 762 } 763 else 764 { 765 for( i = 0; i <= width - 2; i += 2 ) 766 { 767 float s0 = kx[0]*src[0][i] + ky[0]*src[0][i+width]; 768 float s1 = kx[0]*src[0][i+1] + ky[0]*src[0][i+width+1]; 769 770 for( k = 1; k <= ksize2; k++ ) 771 { 772 const float* src1 = src[k] + i, *src2 = src[-k] + i; 773 float fx = kx[k], fy = ky[k]; 774 s0 += fx*(src1[0] + src2[0]) + fy*(src1[width] + src2[width]); 775 s1 += fx*(src1[1] + src2[1]) + fy*(src1[width+1] + src2[width+1]); 776 } 777 778 s0 *= scale; s1 *= scale; 779 dst[i] = s0; dst[i+1] = s1; 780 } 781 } 782 783 for( ; i < width; i++ ) 784 { 785 float s0 = kx[0]*src[0][i] + ky[0]*src[0][i+width]; 786 for( k = 1; k <= ksize2; k++ ) 787 { 788 const float* src1 = src[k] + i, *src2 = src[-k] + i; 789 s0 += kx[k]*(src1[0] + src2[0]) + ky[k]*(src1[width] + src2[width]); 790 } 791 dst[i] = s0*scale; 792 } 793 } 794 } 795 796 797 CV_IMPL void 798 cvLaplace( const void* srcarr, void* dstarr, int aperture_size ) 799 { 800 CvLaplaceFilter laplacian; 801 void* buffer = 0; 802 int local_alloc = 0; 803 804 CV_FUNCNAME( "cvLaplace" ); 805 806 __BEGIN__; 807 808 CvMat srcstub, *src = (CvMat*)srcarr; 809 CvMat dststub, *dst = (CvMat*)dstarr; 810 int src_type, dst_type; 811 812 CV_CALL( src = cvGetMat( src, &srcstub )); 813 CV_CALL( dst = cvGetMat( dst, &dststub )); 814 815 src_type = CV_MAT_TYPE(src->type); 816 dst_type = CV_MAT_TYPE(dst->type); 817 818 if( (aperture_size == 3 || aperture_size == 5) && 819 (src_type == CV_8UC1 && dst_type == CV_16SC1/* || 820 src_type == CV_32FC1 && dst_type == CV_32FC1*/) ) 821 { 822 CvDerivGetBufSizeIPPFunc ipp_laplace_getbufsize_func = 0; 823 CvDerivIPPFunc_8u ipp_laplace_func_8u = 0; 824 CvDerivIPPFunc_32f ipp_laplace_func_32f = 0; 825 826 if( src_type == CV_8U ) 827 ipp_laplace_func_8u = icvFilterLaplacianBorder_8u16s_C1R_p, 828 ipp_laplace_getbufsize_func = icvFilterLaplacianGetBufSize_8u16s_C1R_p; 829 else 830 ipp_laplace_func_32f = icvFilterLaplacianBorder_32f_C1R_p, 831 ipp_laplace_getbufsize_func = icvFilterLaplacianGetBufSize_32f_C1R_p; 832 833 if( (ipp_laplace_func_8u || ipp_laplace_func_32f) && ipp_laplace_getbufsize_func ) 834 { 835 int bufsize = 0, masksize = aperture_size == 3 ? 33 : 55; 836 CvSize size = cvGetMatSize( src ); 837 uchar* src_ptr = src->data.ptr; 838 uchar* dst_ptr = dst->data.ptr; 839 int src_step = src->step ? src->step : CV_STUB_STEP; 840 int dst_step = dst->step ? dst->step : CV_STUB_STEP; 841 const int bordertype = 1; // replication border 842 CvStatus status; 843 844 status = ipp_laplace_getbufsize_func( size, masksize, &bufsize ); 845 846 if( status >= 0 ) 847 { 848 if( bufsize <= CV_MAX_LOCAL_SIZE ) 849 { 850 buffer = cvStackAlloc( bufsize ); 851 local_alloc = 1; 852 } 853 else 854 CV_CALL( buffer = cvAlloc( bufsize )); 855 856 status = 857 ipp_laplace_func_8u ? ipp_laplace_func_8u( src_ptr, src_step, dst_ptr, dst_step, 858 size, masksize, bordertype, 0, buffer ) : 859 ipp_laplace_func_32f ? ipp_laplace_func_32f( src_ptr, src_step, dst_ptr, dst_step, 860 size, masksize, bordertype, 0, buffer ) : 861 CV_NOTDEFINED_ERR; 862 } 863 864 if( status >= 0 ) 865 EXIT; 866 } 867 } 868 869 CV_CALL( laplacian.init( src->cols, src_type, dst_type, 870 false, aperture_size )); 871 CV_CALL( laplacian.process( src, dst )); 872 873 __END__; 874 875 if( buffer && !local_alloc ) 876 cvFree( &buffer ); 877 } 878 879 /* End of file. */ 880