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 + -
显示快捷键?