cvAdaptiveThreshold源代码的解析

函数原型:static void   icvAdaptiveThreshold_MeanC( const CvMat* src, CvMat* dst, int method, int maxValue, int type, int size, double delta )

函数cvAdaptiveThreshold的代码很少,除了一些类型检查的语句,主要的处理部分是由一原型为: “static void icvAdaptiveThreshold_MeanC( const CvMat* src, CvMat* dst, int method, int maxValue, int type, int size, double delta )” 的函数完成的,其输入参数基本照搬cvAdaptiveThreshold的,只是名字不同罢了,src(src)、dst(dst)、method(adaptive_method)、maxValue(对max_value取整)、type(threshold_type)、size(block_size)、delta(param1)。

cvAdaptiveThreshold( const CvArr* src,  CvArr* dst, double max_value,   int adaptive_method CV_DEFAULT(CV_ADAPTIVE_THRESH_MEAN_C),
                                  int threshold_type CV_DEFAULT(CV_THRESH_BINARY),  int block_size CV_DEFAULT(3),  double param1 CV_DEFAULT(5));

首先大体说下cvAdaptiveThreshold函数的功能

(1)函数cvAdaptiveThreshold的确可以将灰度图像二值化,但它的主要功能应该是边缘提取,并且参数param1主要是用来控制边缘的类型和粗细的;

(2)cvAdaptiveThreshold既可以做边缘提取,也可以实现二值化是由你所选择的邻域所确定的,如果你所选择的邻域非常小(比如3×3),那么很显然阈值的“自适应程度”就非常高,这在结果图像中就表现为边缘检测的效果。如果邻域选择的比较大(比如31×31),那么阈值的“自适应程度”就比较低,这在结果图像中就表现为二值化的效果。

(3)一般情况下,滤波器宽度应该大于被识别物体的宽度。block_size太小,无法代表背景,太大的话会影响到临近物体。选定合适的block_size后,我们就可以选定一个更大的阈值param1,更好的抑制噪声;

(4) blockSize 要取奇数,如果取偶数运行后就会报错!!原因看源码,发现要做一个掩模,所以参数必须是奇数。OpenCV也做了一个检测,在函数adaptiveThreshold一开始就有CV_Assert(blockSize % 2 == 1 && blockSize > 1 )。

另补充:

1)自适应二值化计算像素的邻域的平均灰度,来决定二值化的值。

2)如果整个区域几乎是一样灰度的,则无法给出合适的结果了。
3)之所以看起来像边缘检测,是因为窗尺寸设置的小,可以改大一点试一试。
cvAdaptiveThreshold( src, dst, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 21); //窗设置为21

4)自适应阈值化中的阈值完全是由你所选择的邻域所确定的,如果你所选择的邻域非常小(比如3×3),那么很显然阈值的“自适应程度”就非常高,这在结果图像中就表现为边缘检测的效果。如果邻域选择的比较大(比如31×31),那么阈值的“自适应程度”就比较低,这在结果图像中就表现为二值化的效果。
    我目前在做细胞图像分割,在HSV色彩系统中对V通道用自适应阈值化,然后在叠加HS通道处理结果,取得了非常好的效果。

没有万能的二值化方法,具体问题具体分析,自适应二值化对于光照不均的文字,条码等,效果很好。窗口大小选择,考虑被检测物体尺寸。

5)建议使用otsu的自动阈值分割技术

以上参考:http://www.xuebuyuan.com/1932219.html

代码如下:

OpenCV beta 5中的cvAdaptiveThreshold源代码我粗略的看了一下,太简单.
 
算法就是先图象的平滑,均值减去param1 ,
 
static void
icvAdaptiveThreshold_MeanC( const CvMat* src, CvMat* dst, int method,
                            int maxValue, int type, int size, double delta )
{
    CvMat* mean = 0;
    
    CV_FUNCNAME( "icvAdaptiveThreshold_MeanC" );
 
    __BEGIN__;
 
    if( size <= 1 || (size&1) == 0 )
        CV_ERROR( CV_StsOutOfRange, "Neighborhood size must be >=3 and odd (3, 5, 7, ...)" );
 
    if( maxValue < 0 )
    {
        CV_CALL( cvSetZero( dst ));
        EXIT;
    }
 
    CV_CALL( mean=cvCreateMat( src->rows, src->cols, CV_8UC1 ));
    CV_CALL( <span style="color:#009900;">cvSmooth</span>( src, mean, method == CV_ADAPTIVE_THRESH_MEAN_C ?
                       CV_BLUR : CV_GAUSSIAN, size, size ));
      CV_CALL( <span style="color:#009900;">cvSubS</span>( mean, cvRealScalar( delta ), mean ));
    CV_CALL( <span style="color:#cc33cc;">cvCmp</span>( src, mean, dst, type == CV_THRESH_BINARY ? CV_CMP_GT : CV_CMP_LT ));
 
    if( maxValue < 255 )
        CV_CALL( <span style="color:#cc33cc;">cvAndS</span>( dst, cvScalarAll( maxValue ), dst ));
 
    __END__;
 
    cvReleaseMat( &mean );
}
 

CV_IMPL void  cvAdaptiveThreshold( const void *srcIm, void *dstIm, double maxValue,
                     int method, int type, int blockSize, double param1 )
{
    CvMat src_stub, dst_stub;
    CvMat *src = 0, *dst = 0;
 
    CV_FUNCNAME( "cvAdaptiveThreshold" );
 
    __BEGIN__;
 
    if( type != CV_THRESH_BINARY && type != CV_THRESH_BINARY_INV )
        CV_ERROR( CV_StsBadArg, "Only CV_TRESH_BINARY and CV_THRESH_BINARY_INV "
                                "threshold types are acceptable" );
 
    CV_CALL( src = cvGetMat( srcIm, &src_stub ));
    CV_CALL( dst = cvGetMat( dstIm, &dst_stub ));
 
    if( !CV_ARE_CNS_EQ( src, dst ))
        CV_ERROR( CV_StsUnmatchedFormats, "" );
 
    if( CV_MAT_TYPE(dst->type) != CV_8UC1 )
        CV_ERROR( CV_StsUnsupportedFormat, "" );
 
    if( !CV_ARE_SIZES_EQ( src, dst ) )
        CV_ERROR( CV_StsUnmatchedSizes, "" );
 
    switch( method )
    {
    case CV_ADAPTIVE_THRESH_MEAN_C:
    case CV_ADAPTIVE_THRESH_GAUSSIAN_C:
        CV_CALL( icvAdaptiveThreshold_MeanC( src, dst, method, cvRound(maxValue),type,
                                             blockSize, param1 ));
        break;
    default:
        CV_ERROR( CV_BADCOEF_ERR, "" );
    }
 
    __END__;
}

void cvCmp(const CvArr* src1, constCvArr* src2, CvArr* dst, int cmp_op);//两矩阵比较运算
CV_CMP_EQ -src1(I) 是否相等
CV_CMP_GT -src1(I) 是否大于
CV_CMP_GE -src1(I) 是否大于等于
CV_CMP_LT -src1(I) 是否小于
CV_CMP_LE -src1(I) 是否小于等于
CV_CMP_NE -src1(I) 是否不等
如果判断为假,dst设为0,如果判断为真,dst设为0xff
void cvCmpS(const CvArr* src, double value, CvArr* dst, intcmp_op);//矩阵和一个数字比较运算

详细见博文:http://blog.csdn.net/zhurui_idea/article/details/28388911

cvsetData博文:http://blog.csdn.net/zhang11wu4/article/details/8020794

calcCovarMatrix函数是用来求取向量集的协方差矩阵,参考说明文档试了试,虽然运行成功,但仍然发现有些问题没有解决。

calcCovarMatrix(const Mat*samples, int nsamples, Mat& covar, Mat& mean, int flags, int ctype=CV_64F)

samples: 输入的向量集,它们可以是若干个同样形式的向量组成,也可以是一个矩阵的若干行组成

nsamples:  输入的向量的数目。

covar:  输出的协方差矩阵。

mean: 输出的均值矩阵。

flags: 操作标志,分别有:CV_COVAR_SCRAMBLED,CV_COVAR_NORMAL,CV_COVAR_USE_AVG,CV_COVAR_SCALE,CV_COVAR_ROWS,CV_COVAR_COLS.

cvGetReal2D-openCV里面的一个函数 作用:返回单通道数组的指定元素 格式:double cvGetReal2D( const CvArr* arr, int idx0, int idx1 );

 cvAnd和cvAndS

 
 
  1. void cvAnd(
  2. const CvArr* src1,
  3. const CvArr* src2,
  4. CvArr* dst,
  5. const CvArr* mask = NULL
  6. );
  7. void cvAndS(
  8. const CvArr* src1,
  9. CvScalar value,
  10. CvArr* dst,
  11. const CvArr* mask = NULL
  12. );

这两个函数在src1数组上做按位与运算,在cvAnd()中每个dst元素都是由相应的src1和src2两个元素进行位与运算得出的。在cvAndS()中,位与运算由常标量value得出。同一般函数一样,如果mask是非空,就只计算非0 mask元素所对应的dst元素。不知道为什么要这么做???????????

尽管支持所有的数据类型,但是对于cvAnd()来说,src1和src2要保持相同的数据类型。如果元素都是浮点型的,则使用该浮点数的按位表示。【52】
CV_THRESH_BINARY_INV参数二值化取反的效果http://www.xuebuyuan.com/1877486.html

cvThreshold的用法 http://blog.csdn.net/zrongh/article/details/7343702

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值