📄 cvfilter.cpp
字号:
CvBaseImageFilter::clear();
}
CvSepFilter::~CvSepFilter()
{
clear();
}
#undef FILTER_BITS
#define FILTER_BITS 8
void CvSepFilter::init( int _max_width, int _src_type, int _dst_type,
const CvMat* _kx, const CvMat* _ky,
CvPoint _anchor, int _border_mode,
CvScalar _border_value )
{
CV_FUNCNAME( "CvSepFilter::init" );
__BEGIN__;
CvSize _ksize;
int filter_type;
int i, xsz, ysz;
int convert_filters = 0;
double xsum = 0, ysum = 0;
const float eps = FLT_EPSILON*100.f;
if( !CV_IS_MAT(_kx) || !CV_IS_MAT(_ky) ||
_kx->cols != 1 && _kx->rows != 1 ||
_ky->cols != 1 && _ky->rows != 1 ||
CV_MAT_CN(_kx->type) != 1 || CV_MAT_CN(_ky->type) != 1 ||
!CV_ARE_TYPES_EQ(_kx,_ky) )
CV_ERROR( CV_StsBadArg,
"Both kernels must be valid 1d single-channel vectors of the same types" );
if( CV_MAT_CN(_src_type) != CV_MAT_CN(_dst_type) )
CV_ERROR( CV_StsUnmatchedFormats, "Input and output must have the same number of channels" );
filter_type = MAX( CV_32F, CV_MAT_DEPTH(_kx->type) );
_ksize.width = _kx->rows + _kx->cols - 1;
_ksize.height = _ky->rows + _ky->cols - 1;
CV_CALL( CvBaseImageFilter::init( _max_width, _src_type, _dst_type, 1, _ksize,
_anchor, _border_mode, _border_value ));
if( !(kx && CV_ARE_SIZES_EQ(kx,_kx)) )
{
cvReleaseMat( &kx );
CV_CALL( kx = cvCreateMat( _kx->rows, _kx->cols, filter_type ));
}
if( !(ky && CV_ARE_SIZES_EQ(ky,_ky)) )
{
cvReleaseMat( &ky );
CV_CALL( ky = cvCreateMat( _ky->rows, _ky->cols, filter_type ));
}
CV_CALL( cvConvert( _kx, kx ));
CV_CALL( cvConvert( _ky, ky ));
xsz = kx->rows + kx->cols - 1;
ysz = ky->rows + ky->cols - 1;
kx_flags = ky_flags = ASYMMETRICAL + SYMMETRICAL + POSITIVE + SUM_TO_1 + INTEGER;
if( !(xsz & 1) )
kx_flags &= ~(ASYMMETRICAL + SYMMETRICAL);
if( !(ysz & 1) )
ky_flags &= ~(ASYMMETRICAL + SYMMETRICAL);
for( i = 0; i < xsz; i++ )
{
float v = kx->data.fl[i];
xsum += v;
if( v < 0 )
kx_flags &= ~POSITIVE;
if( fabs(v - cvRound(v)) > eps )
kx_flags &= ~INTEGER;
if( fabs(v - kx->data.fl[xsz - i - 1]) > eps )
kx_flags &= ~SYMMETRICAL;
if( fabs(v + kx->data.fl[xsz - i - 1]) > eps )
kx_flags &= ~ASYMMETRICAL;
}
if( fabs(xsum - 1.) > eps )
kx_flags &= ~SUM_TO_1;
for( i = 0; i < ysz; i++ )
{
float v = ky->data.fl[i];
ysum += v;
if( v < 0 )
ky_flags &= ~POSITIVE;
if( fabs(v - cvRound(v)) > eps )
ky_flags &= ~INTEGER;
if( fabs(v - ky->data.fl[ysz - i - 1]) > eps )
ky_flags &= ~SYMMETRICAL;
if( fabs(v + ky->data.fl[ysz - i - 1]) > eps )
ky_flags &= ~ASYMMETRICAL;
}
if( fabs(ysum - 1.) > eps )
ky_flags &= ~SUM_TO_1;
x_func = 0;
y_func = 0;
if( CV_MAT_DEPTH(src_type) == CV_8U )
{
if( CV_MAT_DEPTH(dst_type) == CV_8U &&
((kx_flags&ky_flags) & (SYMMETRICAL + POSITIVE + SUM_TO_1)) == SYMMETRICAL + POSITIVE + SUM_TO_1 )
{
x_func = (CvRowFilterFunc)icvFilterRowSymm_8u32s;
y_func = (CvColumnFilterFunc)icvFilterColSymm_32s8u;
kx_flags &= ~INTEGER;
ky_flags &= ~INTEGER;
convert_filters = 1;
}
else if( CV_MAT_DEPTH(dst_type) == CV_16S &&
(kx_flags & (SYMMETRICAL + ASYMMETRICAL)) && (kx_flags & INTEGER) &&
(ky_flags & (SYMMETRICAL + ASYMMETRICAL)) && (ky_flags & INTEGER) )
{
x_func = (CvRowFilterFunc)icvFilterRowSymm_8u32s;
y_func = (CvColumnFilterFunc)icvFilterColSymm_32s16s;
convert_filters = 1;
}
else
{
if( CV_MAT_DEPTH(dst_type) > CV_32F )
CV_ERROR( CV_StsUnsupportedFormat, "8u->64f separable filtering is not supported" );
if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
x_func = (CvRowFilterFunc)icvFilterRowSymm_8u32f;
else
x_func = (CvRowFilterFunc)icvFilterRow_8u32f;
}
}
else if( CV_MAT_DEPTH(src_type) == CV_16U )
{
if( CV_MAT_DEPTH(dst_type) > CV_32F )
CV_ERROR( CV_StsUnsupportedFormat, "16u->64f separable filtering is not supported" );
if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
x_func = (CvRowFilterFunc)icvFilterRowSymm_16u32f;
else
x_func = (CvRowFilterFunc)icvFilterRow_16u32f;
}
else if( CV_MAT_DEPTH(src_type) == CV_16S )
{
if( CV_MAT_DEPTH(dst_type) > CV_32F )
CV_ERROR( CV_StsUnsupportedFormat, "16s->64f separable filtering is not supported" );
if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
x_func = (CvRowFilterFunc)icvFilterRowSymm_16s32f;
else
x_func = (CvRowFilterFunc)icvFilterRow_16s32f;
}
else if( CV_MAT_DEPTH(src_type) == CV_32F )
{
if( CV_MAT_DEPTH(dst_type) != CV_32F )
CV_ERROR( CV_StsUnsupportedFormat, "When the input has 32f data type, the output must also have 32f type" );
if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
x_func = (CvRowFilterFunc)icvFilterRowSymm_32f;
else
x_func = (CvRowFilterFunc)icvFilterRow_32f;
}
else
CV_ERROR( CV_StsUnsupportedFormat, "Unknown or unsupported input data type" );
if( !y_func )
{
if( CV_MAT_DEPTH(dst_type) == CV_8U )
{
if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
y_func = (CvColumnFilterFunc)icvFilterColSymm_32f8u;
else
y_func = (CvColumnFilterFunc)icvFilterCol_32f8u;
}
else if( CV_MAT_DEPTH(dst_type) == CV_16U )
{
if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
y_func = (CvColumnFilterFunc)icvFilterColSymm_32f16u;
else
y_func = (CvColumnFilterFunc)icvFilterCol_32f16u;
}
else if( CV_MAT_DEPTH(dst_type) == CV_16S )
{
if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
y_func = (CvColumnFilterFunc)icvFilterColSymm_32f16s;
else
y_func = (CvColumnFilterFunc)icvFilterCol_32f16s;
}
else if( CV_MAT_DEPTH(dst_type) == CV_32F )
{
if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
y_func = (CvColumnFilterFunc)icvFilterColSymm_32f;
else
y_func = (CvColumnFilterFunc)icvFilterCol_32f;
}
else
CV_ERROR( CV_StsUnsupportedFormat, "Unknown or unsupported input data type" );
}
if( convert_filters )
{
int scale = kx_flags & ky_flags & INTEGER ? 1 : (1 << FILTER_BITS);
int sum;
for( i = sum = 0; i < xsz; i++ )
{
int t = cvRound(kx->data.fl[i]*scale);
kx->data.i[i] = t;
sum += t;
}
if( scale > 1 )
kx->data.i[xsz/2] += scale - sum;
for( i = sum = 0; i < ysz; i++ )
{
int t = cvRound(ky->data.fl[i]*scale);
ky->data.i[i] = t;
sum += t;
}
if( scale > 1 )
ky->data.i[ysz/2] += scale - sum;
kx->type = (kx->type & ~CV_MAT_DEPTH_MASK) | CV_32S;
ky->type = (ky->type & ~CV_MAT_DEPTH_MASK) | CV_32S;
}
__END__;
}
void CvSepFilter::init( int _max_width, int _src_type, int _dst_type,
bool _is_separable, CvSize _ksize,
CvPoint _anchor, int _border_mode,
CvScalar _border_value )
{
CvBaseImageFilter::init( _max_width, _src_type, _dst_type, _is_separable,
_ksize, _anchor, _border_mode, _border_value );
}
static void
icvFilterRowSymm_8u32s( const uchar* src, int* dst, void* params )
{
const CvSepFilter* state = (const CvSepFilter*)params;
const CvMat* _kx = state->get_x_kernel();
const int* kx = _kx->data.i;
int ksize = _kx->cols + _kx->rows - 1;
int i = 0, j, k, width = state->get_width();
int cn = CV_MAT_CN(state->get_src_type());
int ksize2 = ksize/2, ksize2n = ksize2*cn;
int is_symm = state->get_x_kernel_flags() & CvSepFilter::SYMMETRICAL;
const uchar* s = src + ksize2n;
kx += ksize2;
width *= cn;
if( is_symm )
{
if( ksize == 1 && kx[0] == 1 )
{
for( i = 0; i <= width - 2; i += 2 )
{
int s0 = s[i], s1 = s[i+1];
dst[i] = s0; dst[i+1] = s1;
}
s += i;
}
else if( ksize == 3 )
{
if( kx[0] == 2 && kx[1] == 1 )
for( ; i <= width - 2; i += 2, s += 2 )
{
int s0 = s[-cn] + s[0]*2 + s[cn], s1 = s[1-cn] + s[1]*2 + s[1+cn];
dst[i] = s0; dst[i+1] = s1;
}
else if( kx[0] == 10 && kx[1] == 3 )
for( ; i <= width - 2; i += 2, s += 2 )
{
int s0 = s[0]*10 + (s[-cn] + s[cn])*3, s1 = s[1]*10 + (s[1-cn] + s[1+cn])*3;
dst[i] = s0; dst[i+1] = s1;
}
else if( kx[0] == 2*64 && kx[1] == 1*64 )
for( ; i <= width - 2; i += 2, s += 2 )
{
int s0 = (s[0]*2 + s[-cn] + s[cn]) << 6;
int s1 = (s[1]*2 + s[1-cn] + s[1+cn]) << 6;
dst[i] = s0; dst[i+1] = s1;
}
else
{
int k0 = kx[0], k1 = kx[1];
for( ; i <= width - 2; i += 2, s += 2 )
{
int s0 = s[0]*k0 + (s[-cn] + s[cn])*k1, s1 = s[1]*k0 + (s[1-cn] + s[1+cn])*k1;
dst[i] = s0; dst[i+1] = s1;
}
}
}
else if( ksize == 5 )
{
int k0 = kx[0], k1 = kx[1], k2 = kx[2];
if( k0 == 6*16 && k1 == 4*16 && k2 == 1*16 )
for( ; i <= width - 2; i += 2, s += 2 )
{
int s0 = (s[0]*6 + (s[-cn] + s[cn])*4 + (s[-cn*2] + s[cn*2])*1) << 4;
int s1 = (s[1]*6 + (s[1-cn] + s[1+cn])*4 + (s[1-cn*2] + s[1+cn*2])*1) << 4;
dst[i] = s0; dst[i+1] = s1;
}
else
for( ; i <= width - 2; i += 2, s += 2 )
{
int s0 = s[0]*k0 + (s[-cn] + s[cn])*k1 + (s[-cn*2] + s[cn*2])*k2;
int s1 = s[1]*k0 + (s[1-cn] + s[1+cn])*k1 + (s[1-cn*2] + s[1+cn*2])*k2;
dst[i] = s0; dst[i+1] = s1;
}
}
else
for( ; i <= width - 4; i += 4, s += 4 )
{
int f = kx[0];
int s0 = f*s[0], s1 = f*s[1], s2 = f*s[2], s3 = f*s[3];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -