+++ /dev/null
-/*M///////////////////////////////////////////////////////////////////////////////////////
-//
-// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
-//
-// By downloading, copying, installing or using the software you agree to this license.
-// If you do not agree to this license, do not download, install,
-// copy or use the software.
-//
-//
-// Intel License Agreement
-// For Open Source Computer Vision Library
-//
-// Copyright (C) 2000, Intel Corporation, all rights reserved.
-// Third party copyrights are property of their respective owners.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// * Redistribution's of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// * Redistribution's in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// * The name of Intel Corporation may not be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// This software is provided by the copyright holders and contributors "as is" and
-// any express or implied warranties, including, but not limited to, the implied
-// warranties of merchantability and fitness for a particular purpose are disclaimed.
-// In no event shall the Intel Corporation or contributors be liable for any direct,
-// indirect, incidental, special, exemplary, or consequential damages
-// (including, but not limited to, procurement of substitute goods or services;
-// loss of use, data, or profits; or business interruption) however caused
-// and on any theory of liability, whether in contract, strict liability,
-// or tort (including negligence or otherwise) arising in any way out of
-// the use of this software, even if advised of the possibility of such damage.
-//
-//M*/
-
-#include "_cv.h"
-
-/*
- * This file includes the code, contributed by Simon Perreault
- * (the function icvMedianBlur_8u_CnR_O1)
- *
- * Constant-time median filtering -- http://nomis80.org/ctmf.html
- * Copyright (C) 2006 Simon Perreault
- *
- * Contact:
- * Laboratoire de vision et systemes numeriques
- * Pavillon Adrien-Pouliot
- * Universite Laval
- * Sainte-Foy, Quebec, Canada
- * G1K 7P4
- *
- * perreaul@gel.ulaval.ca
- */
-
-// uncomment the line below to force SSE2 mode
-//#define CV_SSE2 1
-
-/****************************************************************************************\
- Box Filter
-\****************************************************************************************/
-
-static void icvSumRow_8u32s( const uchar* src0, int* dst, void* params );
-static void icvSumRow_32f64f( const float* src0, double* dst, void* params );
-static void icvSumCol_32s8u( const int** src, uchar* dst, int dst_step,
- int count, void* params );
-static void icvSumCol_32s16s( const int** src, short* dst, int dst_step,
- int count, void* params );
-static void icvSumCol_32s32s( const int** src, int* dst, int dst_step,
- int count, void* params );
-static void icvSumCol_64f32f( const double** src, float* dst, int dst_step,
- int count, void* params );
-
-CvBoxFilter::CvBoxFilter()
-{
- min_depth = CV_32S;
- sum = 0;
- sum_count = 0;
- normalized = false;
-}
-
-
-CvBoxFilter::CvBoxFilter( int _max_width, int _src_type, int _dst_type,
- bool _normalized, CvSize _ksize,
- CvPoint _anchor, int _border_mode,
- CvScalar _border_value )
-{
- min_depth = CV_32S;
- sum = 0;
- sum_count = 0;
- normalized = false;
- init( _max_width, _src_type, _dst_type, _normalized,
- _ksize, _anchor, _border_mode, _border_value );
-}
-
-
-CvBoxFilter::~CvBoxFilter()
-{
- clear();
-}
-
-
-void CvBoxFilter::init( int _max_width, int _src_type, int _dst_type,
- bool _normalized, CvSize _ksize,
- CvPoint _anchor, int _border_mode,
- CvScalar _border_value )
-{
- CV_FUNCNAME( "CvBoxFilter::init" );
-
- __BEGIN__;
-
- sum = 0;
- normalized = _normalized;
-
- if( normalized && CV_MAT_TYPE(_src_type) != CV_MAT_TYPE(_dst_type) ||
- !normalized && CV_MAT_CN(_src_type) != CV_MAT_CN(_dst_type))
- CV_ERROR( CV_StsUnmatchedFormats,
- "In case of normalized box filter input and output must have the same type.\n"
- "In case of unnormalized box filter the number of input and output channels must be the same" );
-
- min_depth = CV_MAT_DEPTH(_src_type) == CV_8U ? CV_32S : CV_64F;
-
- CvBaseImageFilter::init( _max_width, _src_type, _dst_type, 1, _ksize,
- _anchor, _border_mode, _border_value );
-
- scale = normalized ? 1./(ksize.width*ksize.height) : 1;
-
- if( CV_MAT_DEPTH(src_type) == CV_8U )
- x_func = (CvRowFilterFunc)icvSumRow_8u32s;
- else if( CV_MAT_DEPTH(src_type) == CV_32F )
- x_func = (CvRowFilterFunc)icvSumRow_32f64f;
- else
- CV_ERROR( CV_StsUnsupportedFormat, "Unknown/unsupported input image format" );
-
- if( CV_MAT_DEPTH(dst_type) == CV_8U )
- {
- if( !normalized )
- CV_ERROR( CV_StsBadArg, "Only normalized box filter can be used for 8u->8u transformation" );
- y_func = (CvColumnFilterFunc)icvSumCol_32s8u;
- }
- else if( CV_MAT_DEPTH(dst_type) == CV_16S )
- {
- if( normalized || CV_MAT_DEPTH(src_type) != CV_8U )
- CV_ERROR( CV_StsBadArg, "Only 8u->16s unnormalized box filter is supported in case of 16s output" );
- y_func = (CvColumnFilterFunc)icvSumCol_32s16s;
- }
- else if( CV_MAT_DEPTH(dst_type) == CV_32S )
- {
- if( normalized || CV_MAT_DEPTH(src_type) != CV_8U )
- CV_ERROR( CV_StsBadArg, "Only 8u->32s unnormalized box filter is supported in case of 32s output");
-
- y_func = (CvColumnFilterFunc)icvSumCol_32s32s;
- }
- else if( CV_MAT_DEPTH(dst_type) == CV_32F )
- {
- if( CV_MAT_DEPTH(src_type) != CV_32F )
- CV_ERROR( CV_StsBadArg, "Only 32f->32f box filter (normalized or not) is supported in case of 32f output" );
- y_func = (CvColumnFilterFunc)icvSumCol_64f32f;
- }
- else{
- CV_ERROR( CV_StsBadArg, "Unknown/unsupported destination image format" );
- }
-
- __END__;
-}
-
-
-void CvBoxFilter::start_process( CvSlice x_range, int width )
-{
- CvBaseImageFilter::start_process( x_range, width );
- int i, psz = CV_ELEM_SIZE(work_type);
- uchar* s;
- buf_end -= buf_step;
- buf_max_count--;
- assert( buf_max_count >= max_ky*2 + 1 );
- s = sum = buf_end + cvAlign((width + ksize.width - 1)*CV_ELEM_SIZE(src_type), ALIGN);
- sum_count = 0;
-
- width *= psz;
- for( i = 0; i < width; i++ )
- s[i] = (uchar)0;
-}
-
-
-static void
-icvSumRow_8u32s( const uchar* src, int* dst, void* params )
-{
- const CvBoxFilter* state = (const CvBoxFilter*)params;
- int ksize = state->get_kernel_size().width;
- int width = state->get_width();
- int cn = CV_MAT_CN(state->get_src_type());
- int i, k;
-
- width = (width - 1)*cn; ksize *= cn;
-
- for( k = 0; k < cn; k++, src++, dst++ )
- {
- int s = 0;
- for( i = 0; i < ksize; i += cn )
- s += src[i];
- dst[0] = s;
- for( i = 0; i < width; i += cn )
- {
- s += src[i+ksize] - src[i];
- dst[i+cn] = s;
- }
- }
-}
-
-
-static void
-icvSumRow_32f64f( const float* src, double* dst, void* params )
-{
- const CvBoxFilter* state = (const CvBoxFilter*)params;
- int ksize = state->get_kernel_size().width;
- int width = state->get_width();
- int cn = CV_MAT_CN(state->get_src_type());
- int i, k;
-
- width = (width - 1)*cn; ksize *= cn;
-
- for( k = 0; k < cn; k++, src++, dst++ )
- {
- double s = 0;
- for( i = 0; i < ksize; i += cn )
- s += src[i];
- dst[0] = s;
- for( i = 0; i < width; i += cn )
- {
- s += (double)src[i+ksize] - src[i];
- dst[i+cn] = s;
- }
- }
-}
-
-
-static void
-icvSumCol_32s8u( const int** src, uchar* dst,
- int dst_step, int count, void* params )
-{
-#define BLUR_SHIFT 24
- CvBoxFilter* state = (CvBoxFilter*)params;
- int ksize = state->get_kernel_size().height;
- int i, width = state->get_width();
- int cn = CV_MAT_CN(state->get_src_type());
- double scale = state->get_scale();
- int iscale = cvFloor(scale*(1 << BLUR_SHIFT));
- int* sum = (int*)state->get_sum_buf();
- int* _sum_count = state->get_sum_count_ptr();
- int sum_count = *_sum_count;
-
- width *= cn;
- src += sum_count;
- count += ksize - 1 - sum_count;
-
- for( ; count--; src++ )
- {
- const int* sp = src[0];
- if( sum_count+1 < ksize )
- {
- for( i = 0; i <= width - 2; i += 2 )
- {
- int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
- sum[i] = s0; sum[i+1] = s1;
- }
-
- for( ; i < width; i++ )
- sum[i] += sp[i];
-
- sum_count++;
- }
- else
- {
- const int* sm = src[-ksize+1];
- for( i = 0; i <= width - 2; i += 2 )
- {
- int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
- int t0 = CV_DESCALE(s0*iscale, BLUR_SHIFT), t1 = CV_DESCALE(s1*iscale, BLUR_SHIFT);
- s0 -= sm[i]; s1 -= sm[i+1];
- sum[i] = s0; sum[i+1] = s1;
- dst[i] = (uchar)t0; dst[i+1] = (uchar)t1;
- }
-
- for( ; i < width; i++ )
- {
- int s0 = sum[i] + sp[i], t0 = CV_DESCALE(s0*iscale, BLUR_SHIFT);
- sum[i] = s0 - sm[i]; dst[i] = (uchar)t0;
- }
- dst += dst_step;
- }
- }
-
- *_sum_count = sum_count;
-#undef BLUR_SHIFT
-}
-
-
-static void
-icvSumCol_32s16s( const int** src, short* dst,
- int dst_step, int count, void* params )
-{
- CvBoxFilter* state = (CvBoxFilter*)params;
- int ksize = state->get_kernel_size().height;
- int ktotal = ksize*state->get_kernel_size().width;
- int i, width = state->get_width();
- int cn = CV_MAT_CN(state->get_src_type());
- int* sum = (int*)state->get_sum_buf();
- int* _sum_count = state->get_sum_count_ptr();
- int sum_count = *_sum_count;
-
- dst_step /= sizeof(dst[0]);
- width *= cn;
- src += sum_count;
- count += ksize - 1 - sum_count;
-
- for( ; count--; src++ )
- {
- const int* sp = src[0];
- if( sum_count+1 < ksize )
- {
- for( i = 0; i <= width - 2; i += 2 )
- {
- int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
- sum[i] = s0; sum[i+1] = s1;
- }
-
- for( ; i < width; i++ )
- sum[i] += sp[i];
-
- sum_count++;
- }
- else if( ktotal < 128 )
- {
- const int* sm = src[-ksize+1];
- for( i = 0; i <= width - 2; i += 2 )
- {
- int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
- dst[i] = (short)s0; dst[i+1] = (short)s1;
- s0 -= sm[i]; s1 -= sm[i+1];
- sum[i] = s0; sum[i+1] = s1;
- }
-
- for( ; i < width; i++ )
- {
- int s0 = sum[i] + sp[i];
- dst[i] = (short)s0;
- sum[i] = s0 - sm[i];
- }
- dst += dst_step;
- }
- else
- {
- const int* sm = src[-ksize+1];
- for( i = 0; i <= width - 2; i += 2 )
- {
- int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
- dst[i] = CV_CAST_16S(s0); dst[i+1] = CV_CAST_16S(s1);
- s0 -= sm[i]; s1 -= sm[i+1];
- sum[i] = s0; sum[i+1] = s1;
- }
-
- for( ; i < width; i++ )
- {
- int s0 = sum[i] + sp[i];
- dst[i] = CV_CAST_16S(s0);
- sum[i] = s0 - sm[i];
- }
- dst += dst_step;
- }
- }
-
- *_sum_count = sum_count;
-}
-
-static void
-icvSumCol_32s32s( const int** src, int * dst,
- int dst_step, int count, void* params )
-{
- CvBoxFilter* state = (CvBoxFilter*)params;
- int ksize = state->get_kernel_size().height;
- int i, width = state->get_width();
- int cn = CV_MAT_CN(state->get_src_type());
- int* sum = (int*)state->get_sum_buf();
- int* _sum_count = state->get_sum_count_ptr();
- int sum_count = *_sum_count;
-
- dst_step /= sizeof(dst[0]);
- width *= cn;
- src += sum_count;
- count += ksize - 1 - sum_count;
-
- for( ; count--; src++ )
- {
- const int* sp = src[0];
- if( sum_count+1 < ksize )
- {
- for( i = 0; i <= width - 2; i += 2 )
- {
- int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
- sum[i] = s0; sum[i+1] = s1;
- }
-
- for( ; i < width; i++ )
- sum[i] += sp[i];
-
- sum_count++;
- }
- else
- {
- const int* sm = src[-ksize+1];
- for( i = 0; i <= width - 2; i += 2 )
- {
- int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
- dst[i] = s0; dst[i+1] = s1;
- s0 -= sm[i]; s1 -= sm[i+1];
- sum[i] = s0; sum[i+1] = s1;
- }
-
- for( ; i < width; i++ )
- {
- int s0 = sum[i] + sp[i];
- dst[i] = s0;
- sum[i] = s0 - sm[i];
- }
- dst += dst_step;
- }
- }
-
- *_sum_count = sum_count;
-}
-
-
-static void
-icvSumCol_64f32f( const double** src, float* dst,
- int dst_step, int count, void* params )
-{
- CvBoxFilter* state = (CvBoxFilter*)params;
- int ksize = state->get_kernel_size().height;
- int i, width = state->get_width();
- int cn = CV_MAT_CN(state->get_src_type());
- double scale = state->get_scale();
- bool normalized = state->is_normalized();
- double* sum = (double*)state->get_sum_buf();
- int* _sum_count = state->get_sum_count_ptr();
- int sum_count = *_sum_count;
-
- dst_step /= sizeof(dst[0]);
- width *= cn;
- src += sum_count;
- count += ksize - 1 - sum_count;
-
- for( ; count--; src++ )
- {
- const double* sp = src[0];
- if( sum_count+1 < ksize )
- {
- for( i = 0; i <= width - 2; i += 2 )
- {
- double s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
- sum[i] = s0; sum[i+1] = s1;
- }
-
- for( ; i < width; i++ )
- sum[i] += sp[i];
-
- sum_count++;
- }
- else
- {
- const double* sm = src[-ksize+1];
- if( normalized )
- for( i = 0; i <= width - 2; i += 2 )
- {
- double s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
- double t0 = s0*scale, t1 = s1*scale;
- s0 -= sm[i]; s1 -= sm[i+1];
- dst[i] = (float)t0; dst[i+1] = (float)t1;
- sum[i] = s0; sum[i+1] = s1;
- }
- else
- for( i = 0; i <= width - 2; i += 2 )
- {
- double s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
- dst[i] = (float)s0; dst[i+1] = (float)s1;
- s0 -= sm[i]; s1 -= sm[i+1];
- sum[i] = s0; sum[i+1] = s1;
- }
-
- for( ; i < width; i++ )
- {
- double s0 = sum[i] + sp[i], t0 = s0*scale;
- sum[i] = s0 - sm[i]; dst[i] = (float)t0;
- }
- dst += dst_step;
- }
- }
-
- *_sum_count = sum_count;
-}
-
-
-/****************************************************************************************\
- Median Filter
-\****************************************************************************************/
-
-#define CV_MINMAX_8U(a,b) \
- (t = CV_FAST_CAST_8U((a) - (b)), (b) += t, a -= t)
-
-#if CV_SSE2 && !defined __SSE2__
-#define __SSE2__ 1
-#include "emmintrin.h"
-#endif
-
-#if defined(__VEC__) || defined(__ALTIVEC__)
-#include <altivec.h>
-#undef bool
-#endif
-
-#if defined(__GNUC__)
-#define align(x) __attribute__ ((aligned (x)))
-#elif CV_SSE2 && (defined(__ICL) || (_MSC_VER >= 1300))
-#define align(x) __declspec(align(x))
-#else
-#define align(x)
-#endif
-
-#if _MSC_VER >= 1200
-#pragma warning( disable: 4244 )
-#endif
-
-/**
- * This structure represents a two-tier histogram. The first tier (known as the
- * "coarse" level) is 4 bit wide and the second tier (known as the "fine" level)
- * is 8 bit wide. Pixels inserted in the fine level also get inserted into the
- * coarse bucket designated by the 4 MSBs of the fine bucket value.
- *
- * The structure is aligned on 16 bits, which is a prerequisite for SIMD
- * instructions. Each bucket is 16 bit wide, which means that extra care must be
- * taken to prevent overflow.
- */
-typedef struct align(16)
-{
- ushort coarse[16];
- ushort fine[16][16];
-} Histogram;
-
-/**
- * HOP is short for Histogram OPeration. This macro makes an operation \a op on
- * histogram \a h for pixel value \a x. It takes care of handling both levels.
- */
-#define HOP(h,x,op) \
- h.coarse[x>>4] op; \
- *((ushort*) h.fine + x) op;
-
-#define COP(c,j,x,op) \
- h_coarse[ 16*(n*c+j) + (x>>4) ] op; \
- h_fine[ 16 * (n*(16*c+(x>>4)) + j) + (x & 0xF) ] op;
-
-#if defined __SSE2__ || defined __MMX__ || defined __ALTIVEC__
-#define MEDIAN_HAVE_SIMD 1
-#else
-#define MEDIAN_HAVE_SIMD 0
-#endif
-
-/**
- * Adds histograms \a x and \a y and stores the result in \a y. Makes use of
- * SSE2, MMX or Altivec, if available.
- */
-#if defined(__SSE2__)
-static inline void histogram_add( const ushort x[16], ushort y[16] )
-{
- _mm_store_si128( (__m128i*) &y[0], _mm_add_epi16(
- _mm_load_si128((__m128i*) &y[0]), _mm_load_si128((__m128i*) &x[0] )));
- _mm_store_si128( (__m128i*) &y[8], _mm_add_epi16(
- _mm_load_si128((__m128i*) &y[8]), _mm_load_si128((__m128i*) &x[8] )));
-}
-#elif defined(__MMX__)
-static inline void histogram_add( const ushort x[16], ushort y[16] )
-{
- *(__m64*) &y[0] = _mm_add_pi16( *(__m64*) &y[0], *(__m64*) &x[0] );
- *(__m64*) &y[4] = _mm_add_pi16( *(__m64*) &y[4], *(__m64*) &x[4] );
- *(__m64*) &y[8] = _mm_add_pi16( *(__m64*) &y[8], *(__m64*) &x[8] );
- *(__m64*) &y[12] = _mm_add_pi16( *(__m64*) &y[12], *(__m64*) &x[12] );
-}
-#elif defined(__ALTIVEC__)
-static inline void histogram_add( const ushort x[16], ushort y[16] )
-{
- *(vector ushort*) &y[0] = vec_add( *(vector ushort*) &y[0], *(vector ushort*) &x[0] );
- *(vector ushort*) &y[8] = vec_add( *(vector ushort*) &y[8], *(vector ushort*) &x[8] );
-}
-#else
-static inline void histogram_add( const ushort x[16], ushort y[16] )
-{
- int i;
- for( i = 0; i < 16; ++i )
- y[i] = (ushort)(y[i] + x[i]);
-}
-#endif
-
-/**
- * Subtracts histogram \a x from \a y and stores the result in \a y. Makes use
- * of SSE2, MMX or Altivec, if available.
- */
-#if defined(__SSE2__)
-static inline void histogram_sub( const ushort x[16], ushort y[16] )
-{
- _mm_store_si128( (__m128i*) &y[0], _mm_sub_epi16(
- _mm_load_si128((__m128i*) &y[0]), _mm_load_si128((__m128i*) &x[0] )));
- _mm_store_si128( (__m128i*) &y[8], _mm_sub_epi16(
- _mm_load_si128((__m128i*) &y[8]), _mm_load_si128((__m128i*) &x[8] )));
-}
-#elif defined(__MMX__)
-static inline void histogram_sub( const ushort x[16], ushort y[16] )
-{
- *(__m64*) &y[0] = _mm_sub_pi16( *(__m64*) &y[0], *(__m64*) &x[0] );
- *(__m64*) &y[4] = _mm_sub_pi16( *(__m64*) &y[4], *(__m64*) &x[4] );
- *(__m64*) &y[8] = _mm_sub_pi16( *(__m64*) &y[8], *(__m64*) &x[8] );
- *(__m64*) &y[12] = _mm_sub_pi16( *(__m64*) &y[12], *(__m64*) &x[12] );
-}
-#elif defined(__ALTIVEC__)
-static inline void histogram_sub( const ushort x[16], ushort y[16] )
-{
- *(vector ushort*) &y[0] = vec_sub( *(vector ushort*) &y[0], *(vector ushort*) &x[0] );
- *(vector ushort*) &y[8] = vec_sub( *(vector ushort*) &y[8], *(vector ushort*) &x[8] );
-}
-#else
-static inline void histogram_sub( const ushort x[16], ushort y[16] )
-{
- int i;
- for( i = 0; i < 16; ++i )
- y[i] = (ushort)(y[i] - x[i]);
-}
-#endif
-
-static inline void histogram_muladd( int a, const ushort x[16],
- ushort y[16] )
-{
- int i;
- for ( i = 0; i < 16; ++i )
- y[i] = (ushort)(y[i] + a * x[i]);
-}
-
-static CvStatus CV_STDCALL
-icvMedianBlur_8u_CnR_O1( uchar* src, int src_step, uchar* dst, int dst_step,
- CvSize size, int kernel_size, int cn, int pad_left, int pad_right )
-{
- int r = (kernel_size-1)/2;
- const int m = size.height, n = size.width;
- int i, j, k, c;
- const unsigned char *p, *q;
- Histogram H[4];
- ushort *h_coarse, *h_fine, luc[4][16];
-
- if( size.height < r || size.width < r )
- return CV_BADSIZE_ERR;
-
- assert( src );
- assert( dst );
- assert( r >= 0 );
- assert( size.width >= 2*r+1 );
- assert( size.height >= 2*r+1 );
- assert( src_step != 0 );
- assert( dst_step != 0 );
-
- h_coarse = (ushort*) cvAlloc( 1 * 16 * n * cn * sizeof(ushort) );
- h_fine = (ushort*) cvAlloc( 16 * 16 * n * cn * sizeof(ushort) );
- memset( h_coarse, 0, 1 * 16 * n * cn * sizeof(ushort) );
- memset( h_fine, 0, 16 * 16 * n * cn * sizeof(ushort) );
-
- /* First row initialization */
- for ( j = 0; j < n; ++j ) {
- for ( c = 0; c < cn; ++c ) {
- COP( c, j, src[cn*j+c], += r+1 );
- }
- }
- for ( i = 0; i < r; ++i ) {
- for ( j = 0; j < n; ++j ) {
- for ( c = 0; c < cn; ++c ) {
- COP( c, j, src[src_step*i+cn*j+c], ++ );
- }
- }
- }
-
- for ( i = 0; i < m; ++i ) {
-
- /* Update column histograms for entire row. */
- p = src + src_step * MAX( 0, i-r-1 );
- q = p + cn * n;
- for ( j = 0; p != q; ++j ) {
- for ( c = 0; c < cn; ++c, ++p ) {
- COP( c, j, *p, -- );
- }
- }
-
- p = src + src_step * MIN( m-1, i+r );
- q = p + cn * n;
- for ( j = 0; p != q; ++j ) {
- for ( c = 0; c < cn; ++c, ++p ) {
- COP( c, j, *p, ++ );
- }
- }
-
- /* First column initialization */
- memset( H, 0, cn*sizeof(H[0]) );
- memset( luc, 0, cn*sizeof(luc[0]) );
- if ( pad_left ) {
- for ( c = 0; c < cn; ++c ) {
- histogram_muladd( r, &h_coarse[16*n*c], H[c].coarse );
- }
- }
- for ( j = 0; j < (pad_left ? r : 2*r); ++j ) {
- for ( c = 0; c < cn; ++c ) {
- histogram_add( &h_coarse[16*(n*c+j)], H[c].coarse );
- }
- }
- for ( c = 0; c < cn; ++c ) {
- for ( k = 0; k < 16; ++k ) {
- histogram_muladd( 2*r+1, &h_fine[16*n*(16*c+k)], &H[c].fine[k][0] );
- }
- }
-
- for ( j = pad_left ? 0 : r; j < (pad_right ? n : n-r); ++j ) {
- for ( c = 0; c < cn; ++c ) {
- int t = 2*r*r + 2*r, b, sum = 0;
- ushort* segment;
-
- histogram_add( &h_coarse[16*(n*c + MIN(j+r,n-1))], H[c].coarse );
-
- /* Find median at coarse level */
- for ( k = 0; k < 16 ; ++k ) {
- sum += H[c].coarse[k];
- if ( sum > t ) {
- sum -= H[c].coarse[k];
- break;
- }
- }
- assert( k < 16 );
-
- /* Update corresponding histogram segment */
- if ( luc[c][k] <= j-r ) {
- memset( &H[c].fine[k], 0, 16 * sizeof(ushort) );
- for ( luc[c][k] = j-r; luc[c][k] < MIN(j+r+1,n); ++luc[c][k] ) {
- histogram_add( &h_fine[16*(n*(16*c+k)+luc[c][k])], H[c].fine[k] );
- }
- if ( luc[c][k] < j+r+1 ) {
- histogram_muladd( j+r+1 - n, &h_fine[16*(n*(16*c+k)+(n-1))], &H[c].fine[k][0] );
- luc[c][k] = (ushort)(j+r+1);
- }
- }
- else {
- for ( ; luc[c][k] < j+r+1; ++luc[c][k] ) {
- histogram_sub( &h_fine[16*(n*(16*c+k)+MAX(luc[c][k]-2*r-1,0))], H[c].fine[k] );
- histogram_add( &h_fine[16*(n*(16*c+k)+MIN(luc[c][k],n-1))], H[c].fine[k] );
- }
- }
-
- histogram_sub( &h_coarse[16*(n*c+MAX(j-r,0))], H[c].coarse );
-
- /* Find median in segment */
- segment = H[c].fine[k];
- for ( b = 0; b < 16 ; ++b ) {
- sum += segment[b];
- if ( sum > t ) {
- dst[dst_step*i+cn*j+c] = (uchar)(16*k + b);
- break;
- }
- }
- assert( b < 16 );
- }
- }
- }
-
-#if defined(__MMX__)
- _mm_empty();
-#endif
-
- cvFree(&h_coarse);
- cvFree(&h_fine);
-
-#undef HOP
-#undef COP
- return CV_OK;
-}
-
-
-#if _MSC_VER >= 1200
-#pragma warning( default: 4244 )
-#endif
-
-
-static CvStatus CV_STDCALL
-icvMedianBlur_8u_CnR_Om( uchar* src, int src_step, uchar* dst, int dst_step,
- CvSize size, int m, int cn )
-{
- #define N 16
- int zone0[4][N];
- int zone1[4][N*N];
- int x, y;
- int n2 = m*m/2;
- int nx = (m + 1)/2 - 1;
- uchar* src_max = src + size.height*src_step;
- uchar* src_right = src + size.width*cn;
-
- #define UPDATE_ACC01( pix, cn, op ) \
- { \
- int p = (pix); \
- zone1[cn][p] op; \
- zone0[cn][p >> 4] op; \
- }
-
- if( size.height < nx || size.width < nx )
- return CV_BADSIZE_ERR;
-
- if( m == 3 )
- {
- size.width *= cn;
-
- for( y = 0; y < size.height; y++, dst += dst_step )
- {
- const uchar* src0 = src + src_step*(y-1);
- const uchar* src1 = src0 + src_step;
- const uchar* src2 = src1 + src_step;
- if( y == 0 )
- src0 = src1;
- else if( y == size.height - 1 )
- src2 = src1;
-
- for( x = 0; x < 2*cn; x++ )
- {
- int x0 = x < cn ? x : size.width - 3*cn + x;
- int x2 = x < cn ? x + cn : size.width - 2*cn + x;
- int x1 = x < cn ? x0 : x2, t;
-
- int p0 = src0[x0], p1 = src0[x1], p2 = src0[x2];
- int p3 = src1[x0], p4 = src1[x1], p5 = src1[x2];
- int p6 = src2[x0], p7 = src2[x1], p8 = src2[x2];
-
- CV_MINMAX_8U(p1, p2); CV_MINMAX_8U(p4, p5);
- CV_MINMAX_8U(p7, p8); CV_MINMAX_8U(p0, p1);
- CV_MINMAX_8U(p3, p4); CV_MINMAX_8U(p6, p7);
- CV_MINMAX_8U(p1, p2); CV_MINMAX_8U(p4, p5);
- CV_MINMAX_8U(p7, p8); CV_MINMAX_8U(p0, p3);
- CV_MINMAX_8U(p5, p8); CV_MINMAX_8U(p4, p7);
- CV_MINMAX_8U(p3, p6); CV_MINMAX_8U(p1, p4);
- CV_MINMAX_8U(p2, p5); CV_MINMAX_8U(p4, p7);
- CV_MINMAX_8U(p4, p2); CV_MINMAX_8U(p6, p4);
- CV_MINMAX_8U(p4, p2);
- dst[x1] = (uchar)p4;
- }
-
- for( x = cn; x < size.width - cn; x++ )
- {
- int p0 = src0[x-cn], p1 = src0[x], p2 = src0[x+cn];
- int p3 = src1[x-cn], p4 = src1[x], p5 = src1[x+cn];
- int p6 = src2[x-cn], p7 = src2[x], p8 = src2[x+cn];
- int t;
-
- CV_MINMAX_8U(p1, p2); CV_MINMAX_8U(p4, p5);
- CV_MINMAX_8U(p7, p8); CV_MINMAX_8U(p0, p1);
- CV_MINMAX_8U(p3, p4); CV_MINMAX_8U(p6, p7);
- CV_MINMAX_8U(p1, p2); CV_MINMAX_8U(p4, p5);
- CV_MINMAX_8U(p7, p8); CV_MINMAX_8U(p0, p3);
- CV_MINMAX_8U(p5, p8); CV_MINMAX_8U(p4, p7);
- CV_MINMAX_8U(p3, p6); CV_MINMAX_8U(p1, p4);
- CV_MINMAX_8U(p2, p5); CV_MINMAX_8U(p4, p7);
- CV_MINMAX_8U(p4, p2); CV_MINMAX_8U(p6, p4);
- CV_MINMAX_8U(p4, p2);
-
- dst[x] = (uchar)p4;
- }
- }
-
- return CV_OK;
- }
-
- for( x = 0; x < size.width; x++, dst += cn )
- {
- uchar* dst_cur = dst;
- uchar* src_top = src;
- uchar* src_bottom = src;
- int k, c;
- int x0 = -1;
- int src_step1 = src_step, dst_step1 = dst_step;
-
- if( x % 2 != 0 )
- {
- src_bottom = src_top += src_step*(size.height-1);
- dst_cur += dst_step*(size.height-1);
- src_step1 = -src_step1;
- dst_step1 = -dst_step1;
- }
-
- if( x <= m/2 )
- nx++;
-
- if( nx < m )
- x0 = x < m/2 ? 0 : (nx-1)*cn;
-
- // init accumulator
- memset( zone0, 0, sizeof(zone0[0])*cn );
- memset( zone1, 0, sizeof(zone1[0])*cn );
-
- for( y = 0; y <= m/2; y++ )
- {
- for( c = 0; c < cn; c++ )
- {
- if( y > 0 )
- {
- if( x0 >= 0 )
- UPDATE_ACC01( src_bottom[x0+c], c, += (m - nx) );
- for( k = 0; k < nx*cn; k += cn )
- UPDATE_ACC01( src_bottom[k+c], c, ++ );
- }
- else
- {
- if( x0 >= 0 )
- UPDATE_ACC01( src_bottom[x0+c], c, += (m - nx)*(m/2+1) );
- for( k = 0; k < nx*cn; k += cn )
- UPDATE_ACC01( src_bottom[k+c], c, += m/2+1 );
- }
- }
-
- if( src_step1 > 0 && y < size.height-1 ||
- src_step1 < 0 && size.height-y-1 > 0 )
- src_bottom += src_step1;
- }
-
- for( y = 0; y < size.height; y++, dst_cur += dst_step1 )
- {
- // find median
- for( c = 0; c < cn; c++ )
- {
- int s = 0;
- for( k = 0; ; k++ )
- {
- int t = s + zone0[c][k];
- if( t > n2 ) break;
- s = t;
- }
-
- for( k *= N; ;k++ )
- {
- s += zone1[c][k];
- if( s > n2 ) break;
- }
-
- dst_cur[c] = (uchar)k;
- }
-
- if( y+1 == size.height )
- break;
-
- if( cn == 1 )
- {
- for( k = 0; k < nx; k++ )
- {
- int p = src_top[k];
- int q = src_bottom[k];
- zone1[0][p]--;
- zone0[0][p>>4]--;
- zone1[0][q]++;
- zone0[0][q>>4]++;
- }
- }
- else if( cn == 3 )
- {
- for( k = 0; k < nx*3; k += 3 )
- {
- UPDATE_ACC01( src_top[k], 0, -- );
- UPDATE_ACC01( src_top[k+1], 1, -- );
- UPDATE_ACC01( src_top[k+2], 2, -- );
-
- UPDATE_ACC01( src_bottom[k], 0, ++ );
- UPDATE_ACC01( src_bottom[k+1], 1, ++ );
- UPDATE_ACC01( src_bottom[k+2], 2, ++ );
- }
- }
- else
- {
- assert( cn == 4 );
- for( k = 0; k < nx*4; k += 4 )
- {
- UPDATE_ACC01( src_top[k], 0, -- );
- UPDATE_ACC01( src_top[k+1], 1, -- );
- UPDATE_ACC01( src_top[k+2], 2, -- );
- UPDATE_ACC01( src_top[k+3], 3, -- );
-
- UPDATE_ACC01( src_bottom[k], 0, ++ );
- UPDATE_ACC01( src_bottom[k+1], 1, ++ );
- UPDATE_ACC01( src_bottom[k+2], 2, ++ );
- UPDATE_ACC01( src_bottom[k+3], 3, ++ );
- }
- }
-
- if( x0 >= 0 )
- {
- for( c = 0; c < cn; c++ )
- {
- UPDATE_ACC01( src_top[x0+c], c, -= (m - nx) );
- UPDATE_ACC01( src_bottom[x0+c], c, += (m - nx) );
- }
- }
-
- if( src_step1 > 0 && src_bottom + src_step1 < src_max ||
- src_step1 < 0 && src_bottom + src_step1 >= src )
- src_bottom += src_step1;
-
- if( y >= m/2 )
- src_top += src_step1;
- }
-
- if( x >= m/2 )
- src += cn;
- if( src + nx*cn > src_right ) nx--;
- }
-#undef N
-#undef UPDATE_ACC
- return CV_OK;
-}
-
-
-/****************************************************************************************\
- Bilateral Filtering
-\****************************************************************************************/
-
-static void
-icvBilateralFiltering_8u( const CvMat* src, CvMat* dst, int d,
- double sigma_color, double sigma_space )
-{
- CvMat* temp = 0;
- float* color_weight = 0;
- float* space_weight = 0;
- int* space_ofs = 0;
-
- CV_FUNCNAME( "icvBilateralFiltering_8u" );
-
- __BEGIN__;
-
- double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
- double gauss_space_coeff = -0.5/(sigma_space*sigma_space);
- int cn = CV_MAT_CN(src->type);
- int i, j, k, maxk, radius;
- CvSize size = cvGetMatSize(src);
-
- if( CV_MAT_TYPE(src->type) != CV_8UC1 &&
- CV_MAT_TYPE(src->type) != CV_8UC3 ||
- !CV_ARE_TYPES_EQ(src, dst) )
- CV_ERROR( CV_StsUnsupportedFormat,
- "Both source and destination must be 8-bit, single-channel or 3-channel images" );
-
- if( sigma_color <= 0 )
- sigma_color = 1;
- if( sigma_space <= 0 )
- sigma_space = 1;
-
- if( d == 0 )
- radius = cvRound(sigma_space*1.5);
- else
- radius = d/2;
- radius = MAX(radius, 1);
- d = radius*2 + 1;
-
- CV_CALL( temp = cvCreateMat( src->rows + radius*2,
- src->cols + radius*2, src->type ));
- CV_CALL( cvCopyMakeBorder( src, temp, cvPoint(radius,radius), IPL_BORDER_REPLICATE ));
- CV_CALL( color_weight = (float*)cvAlloc(cn*256*sizeof(color_weight[0])));
- CV_CALL( space_weight = (float*)cvAlloc(d*d*sizeof(space_weight[0])));
- CV_CALL( space_ofs = (int*)cvAlloc(d*d*sizeof(space_ofs[0])));
-
- // initialize color-related bilateral filter coefficients
- for( i = 0; i < 256*cn; i++ )
- color_weight[i] = (float)exp(i*i*gauss_color_coeff);
-
- // initialize space-related bilateral filter coefficients
- for( i = -radius, maxk = 0; i <= radius; i++ )
- for( j = -radius; j <= radius; j++ )
- {
- double r = sqrt((double)i*i + (double)j*j);
- if( r > radius )
- continue;
- space_weight[maxk] = (float)exp(r*r*gauss_space_coeff);
- space_ofs[maxk++] = i*temp->step + j*cn;
- }
-
- for( i = 0; i < size.height; i++ )
- {
- const uchar* sptr = temp->data.ptr + (i+radius)*temp->step + radius*cn;
- uchar* dptr = dst->data.ptr + i*dst->step;
-
- if( cn == 1 )
- {
- for( j = 0; j < size.width; j++ )
- {
- float sum = 0, wsum = 0;
- int val0 = sptr[j];
- for( k = 0; k < maxk; k++ )
- {
- int val = sptr[j + space_ofs[k]];
- float w = space_weight[k]*color_weight[abs(val - val0)];
- sum += val*w;
- wsum += w;
- }
- // overflow is not possible here => there is no need to use CV_CAST_8U
- dptr[j] = (uchar)cvRound(sum/wsum);
- }
- }
- else
- {
- assert( cn == 3 );
- for( j = 0; j < size.width*3; j += 3 )
- {
- float sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0;
- int b0 = sptr[j], g0 = sptr[j+1], r0 = sptr[j+2];
- for( k = 0; k < maxk; k++ )
- {
- const uchar* sptr_k = sptr + j + space_ofs[k];
- int b = sptr_k[0], g = sptr_k[1], r = sptr_k[2];
- float w = space_weight[k]*color_weight[abs(b - b0) +
- abs(g - g0) + abs(r - r0)];
- sum_b += b*w; sum_g += g*w; sum_r += r*w;
- wsum += w;
- }
- wsum = 1.f/wsum;
- b0 = cvRound(sum_b*wsum);
- g0 = cvRound(sum_g*wsum);
- r0 = cvRound(sum_r*wsum);
- dptr[j] = (uchar)b0; dptr[j+1] = (uchar)g0; dptr[j+2] = (uchar)r0;
- }
- }
- }
-
- __END__;
-
- cvReleaseMat( &temp );
- cvFree( &color_weight );
- cvFree( &space_weight );
- cvFree( &space_ofs );
-}
-
-
-static void icvBilateralFiltering_32f( const CvMat* src, CvMat* dst, int d,
- double sigma_color, double sigma_space )
-{
- CvMat* temp = 0;
- float* space_weight = 0;
- int* space_ofs = 0;
- float *expLUT = 0;
-
- CV_FUNCNAME( "icvBilateralFiltering_32f" );
-
- __BEGIN__;
-
- double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
- double gauss_space_coeff = -0.5/(sigma_space*sigma_space);
- int cn = CV_MAT_CN(src->type);
- int i, j, k, maxk, radius;
- double minValSrc=-1, maxValSrc=1;
- const int kExpNumBinsPerChannel = 1 << 12;
- int kExpNumBins = 0;
- float lastExpVal = 1.f;
- int temp_step;
- float len, scale_index;
- CvMat src_reshaped;
-
- CvSize size = cvGetMatSize(src);
-
- if( CV_MAT_TYPE(src->type) != CV_32FC1 &&
- CV_MAT_TYPE(src->type) != CV_32FC3 ||
- !CV_ARE_TYPES_EQ(src, dst) )
- CV_ERROR( CV_StsUnsupportedFormat,
- "Both source and destination must be 32-bit float, single-channel or 3-channel images" );
-
- if( sigma_color <= 0 )
- sigma_color = 1;
- if( sigma_space <= 0 )
- sigma_space = 1;
-
- if( d == 0 )
- radius = cvRound(sigma_space*1.5);
- else
- radius = d/2;
- radius = MAX(radius, 1);
- d = radius*2 + 1;
- // compute the min/max range for the input image (even if multichannel)
-
- CV_CALL( cvReshape( src, &src_reshaped, 1 ) );
- CV_CALL( cvMinMaxLoc(&src_reshaped, &minValSrc, &maxValSrc) );
-
- // temporary copy of the image with borders for easy processing
- CV_CALL( temp = cvCreateMat( src->rows + radius*2,
- src->cols + radius*2, src->type ));
- temp_step = temp->step/sizeof(float);
- CV_CALL( cvCopyMakeBorder( src, temp, cvPoint(radius,radius), IPL_BORDER_REPLICATE ));
- // allocate lookup tables
- CV_CALL( space_weight = (float*)cvAlloc(d*d*sizeof(space_weight[0])));
- CV_CALL( space_ofs = (int*)cvAlloc(d*d*sizeof(space_ofs[0])));
-
- // assign a length which is slightly more than needed
- len = (float)(maxValSrc - minValSrc) * cn;
- kExpNumBins = kExpNumBinsPerChannel * cn;
- CV_CALL( expLUT = (float*)cvAlloc((kExpNumBins+2) * sizeof(expLUT[0])));
- scale_index = kExpNumBins/len;
-
- // initialize the exp LUT
- for( i = 0; i < kExpNumBins+2; i++ )
- {
- if( lastExpVal > 0.f )
- {
- double val = i / scale_index;
- expLUT[i] = (float)exp(val * val * gauss_color_coeff);
- lastExpVal = expLUT[i];
- }
- else
- expLUT[i] = 0.f;
- }
-
- // initialize space-related bilateral filter coefficients
- for( i = -radius, maxk = 0; i <= radius; i++ )
- for( j = -radius; j <= radius; j++ )
- {
- double r = sqrt((double)i*i + (double)j*j);
- if( r > radius )
- continue;
- space_weight[maxk] = (float)exp(r*r*gauss_space_coeff);
- space_ofs[maxk++] = i*temp_step + j*cn;
- }
-
- for( i = 0; i < size.height; i++ )
- {
- const float* sptr = temp->data.fl + (i+radius)*temp_step + radius*cn;
- float* dptr = (float*)(dst->data.ptr + i*dst->step);
-
- if( cn == 1 )
- {
- for( j = 0; j < size.width; j++ )
- {
- float sum = 0, wsum = 0;
- float val0 = sptr[j];
- for( k = 0; k < maxk; k++ )
- {
- float val = sptr[j + space_ofs[k]];
- float alpha = (float)(fabs(val - val0)*scale_index);
- int idx = cvFloor(alpha);
- alpha -= idx;
- float w = space_weight[k]*(expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx]));
- sum += val*w;
- wsum += w;
- }
- dptr[j] = (float)(sum/wsum);
- }
- }
- else
- {
- assert( cn == 3 );
- for( j = 0; j < size.width*3; j += 3 )
- {
- float sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0;
- float b0 = sptr[j], g0 = sptr[j+1], r0 = sptr[j+2];
- for( k = 0; k < maxk; k++ )
- {
- const float* sptr_k = sptr + j + space_ofs[k];
- float b = sptr_k[0], g = sptr_k[1], r = sptr_k[2];
- float alpha = (float)((fabs(b - b0) + fabs(g - g0) + fabs(r - r0))*scale_index);
- int idx = cvFloor(alpha);
- alpha -= idx;
- float w = space_weight[k]*(expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx]));
- sum_b += b*w; sum_g += g*w; sum_r += r*w;
- wsum += w;
- }
- wsum = 1.f/wsum;
- b0 = sum_b*wsum;
- g0 = sum_g*wsum;
- r0 = sum_r*wsum;
- dptr[j] = b0; dptr[j+1] = g0; dptr[j+2] = r0;
- }
- }
- }
-
- __END__;
-
- cvReleaseMat( &temp );
- cvFree( &space_weight );
- cvFree( &space_ofs );
- cvFree( &expLUT );
-}
-
-//////////////////////////////// IPP smoothing functions /////////////////////////////////
-
-icvFilterMedian_8u_C1R_t icvFilterMedian_8u_C1R_p = 0;
-icvFilterMedian_8u_C3R_t icvFilterMedian_8u_C3R_p = 0;
-icvFilterMedian_8u_C4R_t icvFilterMedian_8u_C4R_p = 0;
-
-icvFilterBox_8u_C1R_t icvFilterBox_8u_C1R_p = 0;
-icvFilterBox_8u_C3R_t icvFilterBox_8u_C3R_p = 0;
-icvFilterBox_8u_C4R_t icvFilterBox_8u_C4R_p = 0;
-icvFilterBox_32f_C1R_t icvFilterBox_32f_C1R_p = 0;
-icvFilterBox_32f_C3R_t icvFilterBox_32f_C3R_p = 0;
-icvFilterBox_32f_C4R_t icvFilterBox_32f_C4R_p = 0;
-
-typedef CvStatus (CV_STDCALL * CvSmoothFixedIPPFunc)
-( const void* src, int srcstep, void* dst, int dststep,
- CvSize size, CvSize ksize, CvPoint anchor );
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-CV_IMPL void
-cvSmooth( const void* srcarr, void* dstarr, int smooth_type,
- int param1, int param2, double param3, double param4 )
-{
- CvBoxFilter box_filter;
- CvSepFilter gaussian_filter;
-
- CvMat* temp = 0;
-
- CV_FUNCNAME( "cvSmooth" );
-
- __BEGIN__;
-
- int coi1 = 0, coi2 = 0;
- CvMat srcstub, *src = (CvMat*)srcarr;
- CvMat dststub, *dst = (CvMat*)dstarr;
- CvSize size;
- int src_type, dst_type, depth, cn;
- double sigma1 = 0, sigma2 = 0;
- bool have_ipp = icvFilterMedian_8u_C1R_p != 0;
-
- CV_CALL( src = cvGetMat( src, &srcstub, &coi1 ));
- CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 ));
-
- if( coi1 != 0 || coi2 != 0 )
- CV_ERROR( CV_BadCOI, "" );
-
- src_type = CV_MAT_TYPE( src->type );
- dst_type = CV_MAT_TYPE( dst->type );
- depth = CV_MAT_DEPTH(src_type);
- cn = CV_MAT_CN(src_type);
- size = cvGetMatSize(src);
-
- if( !CV_ARE_SIZES_EQ( src, dst ))
- CV_ERROR( CV_StsUnmatchedSizes, "" );
-
- if( smooth_type != CV_BLUR_NO_SCALE && !CV_ARE_TYPES_EQ( src, dst ))
- CV_ERROR( CV_StsUnmatchedFormats,
- "The specified smoothing algorithm requires input and ouput arrays be of the same type" );
-
- if( smooth_type == CV_BLUR || smooth_type == CV_BLUR_NO_SCALE ||
- smooth_type == CV_GAUSSIAN || smooth_type == CV_MEDIAN )
- {
- // automatic detection of kernel size from sigma
- if( smooth_type == CV_GAUSSIAN )
- {
- sigma1 = param3;
- sigma2 = param4 ? param4 : param3;
-
- if( param1 == 0 && sigma1 > 0 )
- param1 = cvRound(sigma1*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
- if( param2 == 0 && sigma2 > 0 )
- param2 = cvRound(sigma2*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
- }
-
- if( param2 == 0 )
- param2 = size.height == 1 ? 1 : param1;
- if( param1 < 1 || (param1 & 1) == 0 || param2 < 1 || (param2 & 1) == 0 )
- CV_ERROR( CV_StsOutOfRange,
- "Both mask width and height must be >=1 and odd" );
-
- if( param1 == 1 && param2 == 1 )
- {
- cvConvert( src, dst );
- EXIT;
- }
- }
-
- if( have_ipp && (smooth_type == CV_BLUR || (smooth_type == CV_MEDIAN && param1 <= 15)) &&
- size.width >= param1 && size.height >= param2 && param1 > 1 && param2 > 1 )
- {
- CvSmoothFixedIPPFunc ipp_median_box_func = 0;
-
- if( smooth_type == CV_BLUR )
- {
- ipp_median_box_func =
- src_type == CV_8UC1 ? icvFilterBox_8u_C1R_p :
- src_type == CV_8UC3 ? icvFilterBox_8u_C3R_p :
- src_type == CV_8UC4 ? icvFilterBox_8u_C4R_p :
- src_type == CV_32FC1 ? icvFilterBox_32f_C1R_p :
- src_type == CV_32FC3 ? icvFilterBox_32f_C3R_p :
- src_type == CV_32FC4 ? icvFilterBox_32f_C4R_p : 0;
- }
- else if( smooth_type == CV_MEDIAN )
- {
- ipp_median_box_func =
- src_type == CV_8UC1 ? icvFilterMedian_8u_C1R_p :
- src_type == CV_8UC3 ? icvFilterMedian_8u_C3R_p :
- src_type == CV_8UC4 ? icvFilterMedian_8u_C4R_p : 0;
- }
-
- if( ipp_median_box_func )
- {
- CvSize el_size = { param1, param2 };
- CvPoint el_anchor = { param1/2, param2/2 };
- int stripe_size = 1 << 14; // the optimal value may depend on CPU cache,
- // overhead of the current IPP code etc.
- const uchar* shifted_ptr;
- int y, dy = 0;
- int temp_step, dst_step = dst->step;
-
- CV_CALL( temp = icvIPPFilterInit( src, stripe_size, el_size ));
-
- shifted_ptr = temp->data.ptr +
- el_anchor.y*temp->step + el_anchor.x*CV_ELEM_SIZE(src_type);
- temp_step = temp->step ? temp->step : CV_STUB_STEP;
-
- for( y = 0; y < src->rows; y += dy )
- {
- dy = icvIPPFilterNextStripe( src, temp, y, el_size, el_anchor );
- IPPI_CALL( ipp_median_box_func( shifted_ptr, temp_step,
- dst->data.ptr + y*dst_step, dst_step, cvSize(src->cols, dy),
- el_size, el_anchor ));
- }
- EXIT;
- }
- }
-
- if( smooth_type == CV_BLUR || smooth_type == CV_BLUR_NO_SCALE )
- {
- CV_CALL( box_filter.init( src->cols, src_type, dst_type,
- smooth_type == CV_BLUR, cvSize(param1, param2) ));
- CV_CALL( box_filter.process( src, dst ));
- }
- else if( smooth_type == CV_MEDIAN )
- {
- int img_size_mp = size.width*size.height;
- img_size_mp = (img_size_mp + (1<<19)) >> 20;
-
- if( depth != CV_8U || cn != 1 && cn != 3 && cn != 4 )
- CV_ERROR( CV_StsUnsupportedFormat,
- "Median filter only supports 8uC1, 8uC3 and 8uC4 images" );
-
- if( size.width < param1*2 || size.height < param1*2 ||
- param1 <= 3 + (img_size_mp < 1 ? 12 : img_size_mp < 4 ? 6 : 2)*(MEDIAN_HAVE_SIMD ? 1 : 3))
- {
- // Special case optimized for 3x3
- IPPI_CALL( icvMedianBlur_8u_CnR_Om( src->data.ptr, src->step,
- dst->data.ptr, dst->step, size, param1, cn ));
- }
- else
- {
- const int r = (param1 - 1) / 2;
- const int CACHE_SIZE = (int) ( 0.95 * 256 * 1024 / cn ); // assume a 256 kB cache size
- const int STRIPES = (int) cvCeil( (double) (size.width - 2*r) /
- (CACHE_SIZE / sizeof(Histogram) - 2*r) );
- const int STRIPE_SIZE = (int) cvCeil(
- (double) ( size.width + STRIPES*2*r - 2*r ) / STRIPES );
-
- for( int i = 0; i < size.width; i += STRIPE_SIZE - 2*r )
- {
- int stripe = STRIPE_SIZE;
- // Make sure that the filter kernel fits into one stripe.
- if( i + STRIPE_SIZE - 2*r >= size.width ||
- size.width - (i + STRIPE_SIZE - 2*r) < 2*r+1 )
- stripe = size.width - i;
-
- IPPI_CALL( icvMedianBlur_8u_CnR_O1( src->data.ptr + cn*i, src->step,
- dst->data.ptr + cn*i, dst->step, cvSize(stripe, size.height),
- param1, cn, i == 0, stripe == size.width - i ));
-
- if( stripe == size.width - i )
- break;
- }
- }
- }
- else if( smooth_type == CV_GAUSSIAN )
- {
- CvSize ksize = { param1, param2 };
- float* kx = (float*)cvStackAlloc( ksize.width*sizeof(kx[0]) );
- float* ky = (float*)cvStackAlloc( ksize.height*sizeof(ky[0]) );
- CvMat KX = cvMat( 1, ksize.width, CV_32F, kx );
- CvMat KY = cvMat( 1, ksize.height, CV_32F, ky );
-
- CvSepFilter::init_gaussian_kernel( &KX, sigma1 );
- if( ksize.width != ksize.height || fabs(sigma1 - sigma2) > FLT_EPSILON )
- CvSepFilter::init_gaussian_kernel( &KY, sigma2 );
- else
- KY.data.fl = kx;
-
- if( have_ipp && size.width >= param1*3 &&
- size.height >= param2 && param1 > 1 && param2 > 1 )
- {
- int done;
- CV_CALL( done = icvIPPSepFilter( src, dst, &KX, &KY,
- cvPoint(ksize.width/2,ksize.height/2)));
- if( done )
- EXIT;
- }
-
- CV_CALL( gaussian_filter.init( src->cols, src_type, dst_type, &KX, &KY ));
- CV_CALL( gaussian_filter.process( src, dst ));
- }
- else if( smooth_type == CV_BILATERAL )
- {
- if( param2 != 0 && (param2 != param1 || param1 % 2 == 0) )
- CV_ERROR( CV_StsBadSize, "Bilateral filter only supports square windows of odd size" );
-
- switch( src_type )
- {
- case CV_32FC1:
- case CV_32FC3:
- CV_CALL( icvBilateralFiltering_32f( src, dst, param1, param3, param4 ));
- break;
- case CV_8UC1:
- case CV_8UC3:
- CV_CALL( icvBilateralFiltering_8u( src, dst, param1, param3, param4 ));
- break;
- default:
- CV_ERROR( CV_StsUnsupportedFormat,
- "Unknown/unsupported format: bilateral filter only supports 8uC1, 8uC3, 32fC1 and 32fC3 formats" );
- }
- }
-
- __END__;
-
- cvReleaseMat( &temp );
-}
-
-/* End of file. */