cvsmooth.cpp.svn-base
来自「非结构化路识别」· SVN-BASE 代码 · 共 1,957 行 · 第 1/5 页
SVN-BASE
1,957 行
/*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"
/****************************************************************************************\
Initialization
\****************************************************************************************/
IPCVAPI_IMPL( CvStatus, icvFilterInitAlloc, (
int roiWidth, CvDataType dataType, int channels,
CvSize elSize, CvPoint elAnchor,
const void* elData, int elementType,
struct CvFilterState ** filterState ))
{
CvFilterState *state = 0;
const int align = sizeof(long);
int ker_size = 0;
int buffer_step = 0;
int buffer_size;
int bt_pix, bt_pix_n;
int aligned_hdr_size = icvAlign((int)sizeof(*state),align);
int temp_lines = dataType == cv8u ? 1 : 2;
int binaryElement = ICV_KERNEL_TYPE(elementType) == ICV_BINARY_KERNEL;
int separableElement = ICV_KERNEL_TYPE(elementType) == ICV_SEPARABLE_KERNEL;
char *ptr;
if( !filterState )
return CV_NULLPTR_ERR;
*filterState = 0;
if( roiWidth <= 0 )
return CV_BADSIZE_ERR;
if( dataType != cv8u && dataType != cv32s && dataType != cv32f )
return CV_BADDEPTH_ERR;
if( channels < 1 || channels > 4 )
return CV_UNSUPPORTED_CHANNELS_ERR;
if( elSize.width <= 0 || elSize.height <= 0 )
return CV_BADSIZE_ERR;
if( (unsigned) elAnchor.x >= (unsigned) elSize.width ||
(unsigned) elAnchor.y >= (unsigned) elSize.height )
return CV_BADRANGE_ERR;
bt_pix = dataType == cv8u ? 1 : dataType == cv32s ? sizeof(int) : sizeof(float);
bt_pix_n = bt_pix * channels;
if( elData )
ker_size = binaryElement ? (elSize.width + 1) * elSize.height * 2 :
separableElement ? (elSize.width + elSize.height)*bt_pix :
elSize.width * elSize.height * bt_pix;
buffer_step = icvAlign((roiWidth + elSize.width+1 + CV_MORPH_ALIGN*4)*bt_pix_n, align);
buffer_size = (elSize.height + temp_lines) * (buffer_step + sizeof(void*)) +
ker_size + aligned_hdr_size + elSize.width * bt_pix_n;
buffer_size = icvAlign(buffer_size + align, align);
state = (CvFilterState*)icvAlloc( buffer_size );
if( !state )
return CV_OUTOFMEM_ERR;
ptr = (char*)state;
state->buffer_step = buffer_step;
state->crows = 0;
state->ker_x = elAnchor.x;
state->ker_y = elAnchor.y;
state->ker_height = elSize.height;
state->ker_width = elSize.width;
state->kerType = elementType;
state->divisor = 1;
state->max_width = roiWidth;
state->dataType = dataType;
state->channels = channels;
state->origin = 0;
ptr += icvAlign( aligned_hdr_size + elAnchor.x * bt_pix_n, CV_MORPH_ALIGN * bt_pix );
state->buffer = ptr;
ptr += buffer_step * elSize.height;
state->tbuf = ptr;
ptr += buffer_step * temp_lines;
state->rows = (char**)ptr;
ptr += sizeof(state->rows[0])*elSize.height;
state->ker0 = state->ker1 = 0;
if( elData )
{
state->ker0 = (uchar*)ptr;
if( binaryElement )
{
int i, mask_size = elSize.width * elSize.height;
state->ker1 = (uchar*)(ptr + (ker_size >> 1));
for( i = 0; i < mask_size; i++ )
{
int t = ((int*)elData)[i] ? -1 : 0;
state->ker0[i] = (uchar)t;
state->ker1[i] = (uchar)~t;
}
}
else
{
memcpy( state->ker0, elData, ker_size );
state->ker1 = (uchar*)(separableElement ? ptr + elSize.width*bt_pix : 0);
}
}
*filterState = state;
return CV_OK;
}
IPCVAPI_IMPL( CvStatus, icvFilterFree, (CvFilterState ** filterState) )
{
if( !filterState )
return CV_NULLPTR_ERR;
icvFree( (void **) filterState );
return CV_OK;
}
#define SMALL_GAUSSIAN_SIZE 7
static CvStatus
icvSmoothInitAlloc( int roiWidth, CvDataType /*dataType*/, int channels,
CvSize elSize, int smoothtype,
struct CvFilterState** filterState )
{
static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
{
{1.f},
{0.25f, 0.5f, 0.25f},
{0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f},
{0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125}
};
CvPoint elAnchor = { elSize.width/2, elSize.height/2 };
float* dataX = 0;
CvStatus status;
if( smoothtype == CV_GAUSSIAN )
{
int i, n = elSize.width, m = elSize.height;
float* dataY;
dataX = (float*)alloca( (elSize.width + elSize.height)*sizeof(dataX[0]));
dataY = dataX + elSize.width;
if( n <= SMALL_GAUSSIAN_SIZE )
{
assert( n%2 == 1 );
memcpy( dataX, small_gaussian_tab[n>>1], n*sizeof(dataX[0]));
}
else
{
double sigmaX = (n/2 - 1)*0.3 + 0.8;
double scaleX = 0.39894228040143267793994605993438/sigmaX;
double scale2X = -0.5/(sigmaX*sigmaX);
double sumX;
sumX = dataX[n/2] = (float)scaleX;
for( i = 1; i < (n+1)/2; i++ )
{
dataX[n/2+i] = dataX[n/2-i] = (float)(exp(scale2X*i*i)*scaleX);
sumX += dataX[n/2+i]*2;
}
// adjust endpoints to make sum = 1
dataX[0] = dataX[n-1] = (float)(dataX[0] + (1 - sumX)*0.5);
}
if( m == n )
{
memcpy( dataY, dataX, n*sizeof(dataX[0]));
}
else if( m <= SMALL_GAUSSIAN_SIZE )
{
assert( m%2 == 1 );
memcpy( dataY, small_gaussian_tab[m>>1], m*sizeof(dataY[0]));
}
else
{
double sigmaY = (m/2 - 1)*0.3 + 0.8;
double scaleY = 0.39894228040143267793994605993438/sigmaY;
double scale2Y = -0.5/(sigmaY*sigmaY);
double sumY;
sumY = dataY[m/2] = (float)scaleY;
for( i = 1; i < (m+1)/2; i++ )
{
dataY[m/2+i] = dataY[m/2-i] = (float)(exp(scale2Y*i*i)*scaleY);
sumY += dataY[m/2+i]*2;
}
if( m > 1 )
dataY[0] = dataY[m-1] = (float)(dataY[0] + (1 - sumY)*0.5);
else
dataY[0] = 1.f;
}
}
status = icvFilterInitAlloc( roiWidth, cv32f, channels, elSize,
elAnchor, dataX, ICV_SEPARABLE_KERNEL, filterState );
if( status < 0 )
return status;
if( filterState && *filterState )
{
if( smoothtype == CV_BLUR )
(*filterState)->divisor = elSize.width * elSize.height;
else if( smoothtype == CV_GAUSSIAN )
(*filterState)->divisor = (double)(1 << elSize.width) * (1 << elSize.height);
}
return filterState != 0 ? CV_OK : CV_NOTDEFINED_ERR;
}
static CvStatus
icvSmoothFree( CvFilterState ** filterState )
{
return icvFilterFree( filterState );
}
/****************************************************************************************\
Simple Blur
\****************************************************************************************/
IPCVAPI( CvStatus,
icvBlur_8u_CnR, ( uchar* src, int srcStep,
uchar* dst, int dstStep, CvSize * roiSize,
CvFilterState* state, int stage ));
IPCVAPI_IMPL( CvStatus,
icvBlur_8u_CnR, ( uchar* src, int srcStep,
uchar* dst, int dstStep, CvSize * roiSize,
CvFilterState* state, int stage ))
{
int width = roiSize->width;
int src_height = roiSize->height;
int dst_height = src_height;
int x, y = 0, i;
int ker_x = state->ker_x;
int ker_y = state->ker_y;
int ker_width = state->ker_width;
int ker_height = state->ker_height;
int ker_right = ker_width - ker_x;
int crows = state->crows;
int **rows = (int**)(state->rows);
uchar *tbuf = (uchar*)(state->tbuf);
int *sumbuf = (int*)((char*)state->tbuf + state->buffer_step);
int *trow, *trow2;
int channels = state->channels;
int ker_x_n = ker_x * channels;
int ker_width_n = ker_width * channels;
int ker_right_n = ker_right * channels;
int width_n = width * channels;
int is_small_width = width < MAX( ker_x, ker_right );
int starting_flag = 0;
int width_rest = width_n & (CV_MORPH_ALIGN - 1);
int divisor = cvRound(state->divisor);
CvFastDiv fastdiv = icvFastDiv( divisor );
/* initialize cyclic buffer when starting */
if( stage == CV_WHOLE || stage == CV_START )
{
for( i = 0; i < ker_height; i++ )
rows[i] = (int*)(state->buffer + state->buffer_step * i);
crows = ker_y;
if( stage != CV_WHOLE )
dst_height -= ker_height - ker_y - 1;
starting_flag = 1;
}
if( stage == CV_END )
dst_height += ker_height - ker_y - 1;
do
{
int need_copy = is_small_width | (y == 0);
uchar *tsrc;
int *tdst;
uchar *tdst2;
int *saved_row = rows[ker_y];
/* fill cyclic buffer - horizontal filtering */
for( ; crows < ker_height; crows++ )
{
tsrc = src - ker_x_n;
tdst = rows[crows];
if( src_height-- <= 0 )
{
if( stage != CV_WHOLE && stage != CV_END )
break;
/* duplicate last row */
trow = rows[crows - 1];
CV_COPY( tdst, trow, width_n, x );
continue;
}
need_copy |= src_height == 1;
if( ker_width > 1 )
{
if( need_copy )
{
tsrc = tbuf - ker_x_n;
CV_COPY( tbuf, src, width_n, x );
}
else
{
CV_COPY( tbuf - ker_x_n, src - ker_x_n, ker_x_n, x );
CV_COPY( tbuf, src + width_n, ker_right_n, x );
}
if( channels == 1 )
{
/* make replication borders */
uchar pix = tsrc[ker_x];
int t0 = 0;
CV_SET( tsrc, pix, ker_x, x );
pix = tsrc[width + ker_x - 1];
CV_SET( tsrc + width + ker_x, pix, ker_right, x );
for( i = 0; i < ker_width_n - 1; i++ )
t0 += tsrc[i];
/* horizontal blurring */
for( i = ker_width_n; i < width_n + ker_width_n; i++ )
{
t0 += tsrc[i-1];
tdst[i-ker_width_n] = t0;
t0 -= tsrc[i - ker_width_n];
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?