3. 你能从图6-5显示的滤波器里建立一个可分核吗?如果可以,显示一下?
图6-5如下所示。
核的部分点有负数,想求出与该核效果等同的分核,则需要知道这些数与图像中的像素数据计算时相互之间是什么具体关系,计算是如何进行的。因此,解答此题目我认为要查看OpenCV源代码中cvSobel()函数的具体实现,至少要搞清楚当aperture_size等于CV_SCHARR时的计算方式。
于是找到cvSobel的具体实现位置:cvderiv.cpp
- CV_IMPL void
- cvSobel( const void* srcarr, void* dstarr, int dx, int dy, int aperture_size )
- {
- CvSepFilter filter;
- void* buffer = 0;
- int local_alloc = 0;
- CV_FUNCNAME( "cvSobel" );
- __BEGIN__;
- int origin = 0;
- int src_type, dst_type;
- CvMat srcstub, *src = (CvMat*)srcarr;
- CvMat dststub, *dst = (CvMat*)dstarr;
- if( !CV_IS_MAT(src) )
- CV_CALL( src = cvGetMat( src, &srcstub ));
- if( !CV_IS_MAT(dst) )
- CV_CALL( dst = cvGetMat( dst, &dststub ));
- if( CV_IS_IMAGE_HDR( srcarr ))
- origin = ((IplImage*)srcarr)->origin;
- src_type = CV_MAT_TYPE( src->type );
- dst_type = CV_MAT_TYPE( dst->type );
- if( !CV_ARE_SIZES_EQ( src, dst ))
- CV_ERROR( CV_StsBadArg, "src and dst have different sizes" );
- if( ((aperture_size == CV_SCHARR || aperture_size == 3 || aperture_size == 5) &&
- dx <= 2 && dy <= 2 && dx + dy <= 2 && icvFilterSobelNegVertBorder_8u16s_C1R_p) &&
- (src_type == CV_8UC1 && dst_type == CV_16SC1 ||
- src_type == CV_32FC1 && dst_type == CV_32FC1) )
- {
- CvDerivGetBufSizeIPPFunc ipp_sobel_getbufsize_func = 0;
- CvDerivIPPFunc_8u ipp_sobel_func_8u = 0;
- CvDerivIPPFunc_32f ipp_sobel_func_32f = 0;
- CvDeriv3x3GetBufSizeIPPFunc ipp_scharr_getbufsize_func = 0;
- CvDeriv3x3IPPFunc_8u ipp_scharr_func_8u = 0;
- CvDeriv3x3IPPFunc_32f ipp_scharr_func_32f = 0;
- if( aperture_size == CV_SCHARR )
- {
- if( dx == 1 && dy == 0 )
- {
- if( src_type == CV_8U )
- ipp_scharr_func_8u = icvFilterScharrVertBorder_8u16s_C1R_p,
- ipp_scharr_getbufsize_func = icvFilterScharrVertGetBufSize_8u16s_C1R_p;
- else
- ipp_scharr_func_32f = icvFilterScharrVertBorder_32f_C1R_p,
- ipp_scharr_getbufsize_func = icvFilterScharrVertGetBufSize_32f_C1R_p;
- }
- else if( dx == 0 && dy == 1 )
- {
- if( src_type == CV_8U )
- ipp_scharr_func_8u = icvFilterScharrHorizBorder_8u16s_C1R_p,
- ipp_scharr_getbufsize_func = icvFilterScharrHorizGetBufSize_8u16s_C1R_p;
- else
- ipp_scharr_func_32f = icvFilterScharrHorizBorder_32f_C1R_p,
- ipp_scharr_getbufsize_func = icvFilterScharrHorizGetBufSize_32f_C1R_p;
- }
- else
- CV_ERROR( CV_StsBadArg, "Scharr filter can only be used to compute 1st image derivatives" );
- }
- else
- {
- if( dx == 1 && dy == 0 )
- {
- if( src_type == CV_8U )
- ipp_sobel_func_8u = icvFilterSobelNegVertBorder_8u16s_C1R_p,
- ipp_sobel_getbufsize_func = icvFilterSobelNegVertGetBufSize_8u16s_C1R_p;
- else
- ipp_sobel_func_32f = icvFilterSobelNegVertBorder_32f_C1R_p,
- ipp_sobel_getbufsize_func = icvFilterSobelNegVertGetBufSize_32f_C1R_p;
- }
- else if( dx == 0 && dy == 1 )
- {
- if( src_type == CV_8U )
- ipp_sobel_func_8u = icvFilterSobelHorizBorder_8u16s_C1R_p,
- ipp_sobel_getbufsize_func = icvFilterSobelHorizGetBufSize_8u16s_C1R_p;
- else
- ipp_sobel_func_32f = icvFilterSobelHorizBorder_32f_C1R_p,
- ipp_sobel_getbufsize_func = icvFilterSobelHorizGetBufSize_32f_C1R_p;
- }
- else if( dx == 2 && dy == 0 )
- {
- if( src_type == CV_8U )
- ipp_sobel_func_8u = icvFilterSobelVertSecondBorder_8u16s_C1R_p,
- ipp_sobel_getbufsize_func = icvFilterSobelVertSecondGetBufSize_8u16s_C1R_p;
- else
- ipp_sobel_func_32f = icvFilterSobelVertSecondBorder_32f_C1R_p,
- ipp_sobel_getbufsize_func = icvFilterSobelVertSecondGetBufSize_32f_C1R_p;
- }
- else if( dx == 0 && dy == 2 )
- {
- if( src_type == CV_8U )
- ipp_sobel_func_8u = icvFilterSobelHorizSecondBorder_8u16s_C1R_p,
- ipp_sobel_getbufsize_func = icvFilterSobelHorizSecondGetBufSize_8u16s_C1R_p;
- else
- ipp_sobel_func_32f = icvFilterSobelHorizSecondBorder_32f_C1R_p,
- ipp_sobel_getbufsize_func = icvFilterSobelHorizSecondGetBufSize_32f_C1R_p;
- }
- else if( dx == 1 && dy == 1 )
- {
- if( src_type == CV_8U )
- ipp_sobel_func_8u = icvFilterSobelCrossBorder_8u16s_C1R_p,
- ipp_sobel_getbufsize_func = icvFilterSobelCrossGetBufSize_8u16s_C1R_p;
- else
- ipp_sobel_func_32f = icvFilterSobelCrossBorder_32f_C1R_p,
- ipp_sobel_getbufsize_func = icvFilterSobelCrossGetBufSize_32f_C1R_p;
- }
- }
- if( (ipp_sobel_func_8u || ipp_sobel_func_32f) && ipp_sobel_getbufsize_func ||
- (ipp_scharr_func_8u || ipp_scharr_func_32f) && ipp_scharr_getbufsize_func )
- {
- int bufsize = 0, masksize = aperture_size == 3 ? 33 : 55;
- CvSize size = cvGetMatSize( src );
- uchar* src_ptr = src->data.ptr;
- uchar* dst_ptr = dst->data.ptr;
- int src_step = src->step ? src->step : CV_STUB_STEP;
- int dst_step = dst->step ? dst->step : CV_STUB_STEP;
- const int bordertype = 1; // replication border
- CvStatus status;
- status = ipp_sobel_getbufsize_func ?
- ipp_sobel_getbufsize_func( size, masksize, &bufsize ) :
- ipp_scharr_getbufsize_func( size, &bufsize );
- if( status >= 0 )
- {
- if( bufsize <= CV_MAX_LOCAL_SIZE )
- {
- buffer = cvStackAlloc( bufsize );
- local_alloc = 1;
- }
- else
- CV_CALL( buffer = cvAlloc( bufsize ));
-
- status =
- ipp_sobel_func_8u ? ipp_sobel_func_8u( src_ptr, src_step, dst_ptr, dst_step,
- size, masksize, bordertype, 0, buffer ) :
- ipp_sobel_func_32f ? ipp_sobel_func_32f( src_ptr, src_step, dst_ptr, dst_step,
- size, masksize, bordertype, 0, buffer ) :
- ipp_scharr_func_8u ? ipp_scharr_func_8u( src_ptr, src_step, dst_ptr, dst_step,
- size, bordertype, 0, buffer ) :
- ipp_scharr_func_32f ? ipp_scharr_func_32f( src_ptr, src_step, dst_ptr, dst_step,
- size, bordertype, 0, buffer ) :
- CV_NOTDEFINED_ERR;
- }
- if( status >= 0 &&
- (dx == 0 && dy == 1 && origin || dx == 1 && dy == 1 && !origin)) // negate the output
- cvSubRS( dst, cvScalarAll(0), dst );
- if( status >= 0 )
- EXIT;
- }
- }
- CV_CALL( filter.init_deriv( src->cols, src_type, dst_type, dx, dy,
- aperture_size, origin ? CvSepFilter::FLIP_KERNEL : 0));
- CV_CALL( filter.process( src, dst ));
- __END__;
- if( buffer && !local_alloc )
- cvFree( &buffer );
- }
其中分析关键部分
- if( aperture_size == CV_SCHARR )
- {
- if( dx == 1 && dy == 0 )
- {
- if( src_type == CV_8U )
- ipp_scharr_func_8u = icvFilterScharrVertBorder_8u16s_C1R_p,
- ipp_scharr_getbufsize_func = icvFilterScharrVertGetBufSize_8u16s_C1R_p;
- else
- ipp_scharr_func_32f = icvFilterScharrVertBorder_32f_C1R_p,
- ipp_scharr_getbufsize_func = icvFilterScharrVertGetBufSize_32f_C1R_p;
- }
- else if( dx == 0 && dy == 1 )
- {
- if( src_type == CV_8U )
- ipp_scharr_func_8u = icvFilterScharrHorizBorder_8u16s_C1R_p,
- ipp_scharr_getbufsize_func = icvFilterScharrHorizGetBufSize_8u16s_C1R_p;
- else
- ipp_scharr_func_32f = icvFilterScharrHorizBorder_32f_C1R_p,
- ipp_scharr_getbufsize_func = icvFilterScharrHorizGetBufSize_32f_C1R_p;
- }
- else
- CV_ERROR( CV_StsBadArg, "Scharr filter can only be used to compute 1st image derivatives" );
- }
其中dx和dy是在x和y这两个方向上求导的阶数。通常为0和1,最多2。0表示这个方向上没有求导。如果调用cvSobel()并且传递CV_SCHARR后,就会进入该if条件。从此处可以看出,该版本opencv只能支持x和y方向上的0或1阶导数。进入该if条件后只对ipp_scharr_func_8u或ipp_scharr_func_32f和ipp_scharr_getbufsize_func这两个变量赋了一个值。真正的计算在后边。
- if( (ipp_sobel_func_8u || ipp_sobel_func_32f) && ipp_sobel_getbufsize_func ||
- (ipp_scharr_func_8u || ipp_scharr_func_32f) && ipp_scharr_getbufsize_func )
- {
- int bufsize = 0, masksize = aperture_size == 3 ? 33 : 55;
- CvSize size = cvGetMatSize( src );
- uchar* src_ptr = src->data.ptr;
- uchar* dst_ptr = dst->data.ptr;
- int src_step = src->step ? src->step : CV_STUB_STEP;
- int dst_step = dst->step ? dst->step : CV_STUB_STEP;
- const int bordertype = 1; // replication border
- CvStatus status;
- status = ipp_sobel_getbufsize_func ?
- ipp_sobel_getbufsize_func( size, masksize, &bufsize ) :
- ipp_scharr_getbufsize_func( size, &bufsize );
- if( status >= 0 )
- {
- if( bufsize <= CV_MAX_LOCAL_SIZE )
- {
- buffer = cvStackAlloc( bufsize );
- local_alloc = 1;
- }
- else
- CV_CALL( buffer = cvAlloc( bufsize ));
-
- status =
- ipp_sobel_func_8u ? ipp_sobel_func_8u( src_ptr, src_step, dst_ptr, dst_step,
- size, masksize, bordertype, 0, buffer ) :
- ipp_sobel_func_32f ? ipp_sobel_func_32f( src_ptr, src_step, dst_ptr, dst_step,
- size, masksize, bordertype, 0, buffer ) :
- ipp_scharr_func_8u ? ipp_scharr_func_8u( src_ptr, src_step, dst_ptr, dst_step,
- size, bordertype, 0, buffer ) :
- ipp_scharr_func_32f ? ipp_scharr_func_32f( src_ptr, src_step, dst_ptr, dst_step,
- size, bordertype, 0, buffer ) :
- CV_NOTDEFINED_ERR;
- }
- if( status >= 0 &&
- (dx == 0 && dy == 1 && origin || dx == 1 && dy == 1 && !origin)) // negate the output
- cvSubRS( dst, cvScalarAll(0), dst );
- if( status >= 0 )
- EXIT;
- }
由返回status值的ipp_scharr_func_8u或ipp_scharr_func_32f计算。这两个是函数指针变量,拿ipp_scharr_func_8u来讲,他被赋值为icvFilterScharrHorizBorder_8u16s_C1R_p,而icvFilterScharrHorizBorder_8u16s_C1R_p由icvFilterScharrHorizBorder_32f_C1R_t定义。最终通过[cxmisc.h]IPCVAPI_EX()转到[cxmisc.h]IPCVAPI(type,declspec,name,args)调用
extern name##_t name##_p。
------------
未完待续
------------
阅读(1856) | 评论(0) | 转发(0) |