📄 cvfilter.cpp
字号:
/*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"
/****************************************************************************************\
Base Image Filter
\****************************************************************************************/
static void default_x_filter_func( const uchar*, uchar*, void* )
{
}
static void default_y_filter_func( uchar**, uchar*, int, int, void* )
{
}
CvBaseImageFilter::CvBaseImageFilter()
{
min_depth = CV_8U;
buffer = 0;
rows = 0;
max_width = 0;
x_func = default_x_filter_func;
y_func = default_y_filter_func;
}
CvBaseImageFilter::CvBaseImageFilter( int _max_width, int _src_type, int _dst_type,
bool _is_separable, CvSize _ksize, CvPoint _anchor,
int _border_mode, CvScalar _border_value )
{
min_depth = CV_8U;
buffer = 0;
rows = 0;
max_width = 0;
x_func = default_x_filter_func;
y_func = default_y_filter_func;
init( _max_width, _src_type, _dst_type, _is_separable,
_ksize, _anchor, _border_mode, _border_value );
}
void CvBaseImageFilter::clear()
{
cvFree( &buffer );
rows = 0;
}
CvBaseImageFilter::~CvBaseImageFilter()
{
clear();
}
void CvBaseImageFilter::get_work_params()
{
int min_rows = max_ky*2 + 3, rows = MAX(min_rows,10), row_sz;
int width = max_width, trow_sz = 0;
if( is_separable )
{
int max_depth = MAX(CV_MAT_DEPTH(src_type), CV_MAT_DEPTH(dst_type));
int max_cn = MAX(CV_MAT_CN(src_type), CV_MAT_CN(dst_type));
max_depth = MAX( max_depth, min_depth );
work_type = CV_MAKETYPE( max_depth, max_cn );
trow_sz = cvAlign( (max_width + ksize.width - 1)*CV_ELEM_SIZE(src_type), ALIGN );
}
else
{
work_type = src_type;
width += ksize.width - 1;
}
row_sz = cvAlign( width*CV_ELEM_SIZE(work_type), ALIGN );
buf_size = rows*row_sz;
buf_size = MIN( buf_size, 1 << 16 );
buf_size = MAX( buf_size, min_rows*row_sz );
max_rows = (buf_size/row_sz)*3 + max_ky*2 + 8;
buf_size += trow_sz;
}
void CvBaseImageFilter::init( int _max_width, int _src_type, int _dst_type,
bool _is_separable, CvSize _ksize, CvPoint _anchor,
int _border_mode, CvScalar _border_value )
{
CV_FUNCNAME( "CvBaseImageFilter::init" );
__BEGIN__;
int total_buf_sz, src_pix_sz, row_tab_sz, bsz;
uchar* ptr;
if( !(buffer && _max_width <= max_width && _src_type == src_type &&
_dst_type == dst_type && _is_separable == is_separable &&
_ksize.width == ksize.width && _ksize.height == ksize.height &&
_anchor.x == anchor.x && _anchor.y == anchor.y) )
clear();
is_separable = _is_separable != 0;
max_width = _max_width; //MAX(_max_width,_ksize.width);
src_type = CV_MAT_TYPE(_src_type);
dst_type = CV_MAT_TYPE(_dst_type);
ksize = _ksize;
anchor = _anchor;
if( anchor.x == -1 )
anchor.x = ksize.width / 2;
if( anchor.y == -1 )
anchor.y = ksize.height / 2;
max_ky = MAX( anchor.y, ksize.height - anchor.y - 1 );
border_mode = _border_mode;
border_value = _border_value;
if( ksize.width <= 0 || ksize.height <= 0 ||
(unsigned)anchor.x >= (unsigned)ksize.width ||
(unsigned)anchor.y >= (unsigned)ksize.height )
CV_ERROR( CV_StsOutOfRange, "invalid kernel size and/or anchor position" );
if( border_mode != IPL_BORDER_CONSTANT && border_mode != IPL_BORDER_REPLICATE &&
border_mode != IPL_BORDER_REFLECT && border_mode != IPL_BORDER_REFLECT_101 )
CV_ERROR( CV_StsBadArg, "Invalid/unsupported border mode" );
get_work_params();
prev_width = 0;
prev_x_range = cvSlice(0,0);
buf_size = cvAlign( buf_size, ALIGN );
src_pix_sz = CV_ELEM_SIZE(src_type);
border_tab_sz1 = anchor.x*src_pix_sz;
border_tab_sz = (ksize.width-1)*src_pix_sz;
bsz = cvAlign( border_tab_sz*sizeof(int), ALIGN );
assert( max_rows > max_ky*2 );
row_tab_sz = cvAlign( max_rows*sizeof(uchar*), ALIGN );
total_buf_sz = buf_size + row_tab_sz + bsz;
CV_CALL( ptr = buffer = (uchar*)cvAlloc( total_buf_sz ));
rows = (uchar**)ptr;
ptr += row_tab_sz;
border_tab = (int*)ptr;
ptr += bsz;
buf_start = ptr;
const_row = 0;
if( border_mode == IPL_BORDER_CONSTANT )
cvScalarToRawData( &border_value, border_tab, src_type, 0 );
__END__;
}
void CvBaseImageFilter::start_process( CvSlice x_range, int width )
{
int mode = border_mode;
int pix_sz = CV_ELEM_SIZE(src_type), work_pix_sz = CV_ELEM_SIZE(work_type);
int bsz = buf_size, bw = x_range.end_index - x_range.start_index, bw1 = bw + ksize.width - 1;
int tr_step = cvAlign(bw1*pix_sz, ALIGN );
int i, j, k, ofs;
if( x_range.start_index == prev_x_range.start_index &&
x_range.end_index == prev_x_range.end_index &&
width == prev_width )
return;
prev_x_range = x_range;
prev_width = width;
if( !is_separable )
bw = bw1;
else
bsz -= tr_step;
buf_step = cvAlign(bw*work_pix_sz, ALIGN);
if( mode == IPL_BORDER_CONSTANT )
bsz -= buf_step;
buf_max_count = bsz/buf_step;
buf_max_count = MIN( buf_max_count, max_rows - max_ky*2 );
buf_end = buf_start + buf_max_count*buf_step;
if( mode == IPL_BORDER_CONSTANT )
{
int i, tab_len = ksize.width*pix_sz;
uchar* bt = (uchar*)border_tab;
uchar* trow = buf_end;
const_row = buf_end + (is_separable ? 1 : 0)*tr_step;
for( i = pix_sz; i < tab_len; i++ )
bt[i] = bt[i - pix_sz];
for( i = 0; i < pix_sz; i++ )
trow[i] = bt[i];
for( i = pix_sz; i < tr_step; i++ )
trow[i] = trow[i - pix_sz];
if( is_separable )
x_func( trow, const_row, this );
return;
}
if( x_range.end_index - x_range.start_index <= 1 )
mode = IPL_BORDER_REPLICATE;
width = (width - 1)*pix_sz;
ofs = (anchor.x-x_range.start_index)*pix_sz;
for( k = 0; k < 2; k++ )
{
int idx, delta;
int i1, i2, di;
if( k == 0 )
{
idx = (x_range.start_index - 1)*pix_sz;
delta = di = -pix_sz;
i1 = border_tab_sz1 - pix_sz;
i2 = -pix_sz;
}
else
{
idx = x_range.end_index*pix_sz;
delta = di = pix_sz;
i1 = border_tab_sz1;
i2 = border_tab_sz;
}
if( (unsigned)idx > (unsigned)width )
{
int shift = mode == IPL_BORDER_REFLECT_101 ? pix_sz : 0;
idx = k == 0 ? shift : width - shift;
delta = -delta;
}
for( i = i1; i != i2; i += di )
{
for( j = 0; j < pix_sz; j++ )
border_tab[i + j] = idx + ofs + j;
if( mode != IPL_BORDER_REPLICATE )
{
if( delta > 0 && idx == width ||
delta < 0 && idx == 0 )
{
if( mode == IPL_BORDER_REFLECT_101 )
idx -= delta*2;
delta = -delta;
}
else
idx += delta;
}
}
}
}
void CvBaseImageFilter::make_y_border( int row_count, int top_rows, int bottom_rows )
{
int i;
if( border_mode == IPL_BORDER_CONSTANT ||
border_mode == IPL_BORDER_REPLICATE )
{
uchar* row1 = border_mode == IPL_BORDER_CONSTANT ? const_row : rows[max_ky];
for( i = 0; i < top_rows && rows[i] == 0; i++ )
rows[i] = row1;
row1 = border_mode == IPL_BORDER_CONSTANT ? const_row : rows[row_count-1];
for( i = 0; i < bottom_rows; i++ )
rows[i + row_count] = row1;
}
else
{
int j, dj = 1, shift = border_mode == IPL_BORDER_REFLECT_101;
for( i = top_rows-1, j = top_rows+shift; i >= 0; i-- )
{
if( rows[i] == 0 )
rows[i] = rows[j];
j += dj;
if( dj > 0 && j >= row_count )
{
if( !bottom_rows )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -