http://blog.csdn.net/ningyaliuhebei/article/details/40736377

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

void cvAdaptiveThreshold(
	CvArr* src,//输入图像
	CvArr* dst,//输出图像
	double max_val,//最大值
	int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C,//自适应阈值方法
	int threshold_type=CV_THRESH_BINARY,//阈值类型
	int block_size=3,//邻域大小
	double param1=5//偏移量
	);


自适应阈值方法adaptive_method:

 

CV_ADAPTIVE_THRESH_MEAN_C 加权平均

CV_ADAPTIVE_THRESH_GAUSSIAN_C 高斯加权平均

二、例程:

 

图像阈值函数
cvThreshold(src,dst,double threshold,double max_value,int threshold_type)
threshold为阈值的分解值(T)
max_value为设定的结果值(M)
threshold_type为阈值类型,其中包括如下类型:
CV_THRESH_BINARY             (X>T)?M:0
CV_THRESH_INV                   (X>T)?0:M
CV_THRESH_TRUNC              (X>T)?M:X
CV_THRESH_TOZERO_INV     (X>T)?0:X
CV_THRESH_TOZERO            (X>T)?X:0
2009年3月26日 - 老柯 - 菜鸟的朝圣之路
//WIN7+VS2012+OPENCV2.4.7
//void cvAdaptiveThreshold(
//	CvArr* src,//输入图像
//	CvArr* dst,//输出图像
//	double max_val,//最大值
//	int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C,//自适应阈值方法
//	int threshold_type=CV_THRESH_BINARY,//阈值类型
//	int block_size=3,//邻域大小
//	double param1=5//偏移量
//	);
#include<cv.h>
#include<highgui.h>
#include<stdio.h>
int main(int argc,char** argv)
{
	cvNamedWindow("threshold",1);
	cvNamedWindow("threshold_adp_mean",1);
	cvNamedWindow("threshold_adp_gaussian",1);
	//
	IplImage* src=cvLoadImage(argv[1],0);
	cvNamedWindow("source");
	cvShowImage("source",src);
	IplImage* dst=cvCreateImage(cvGetSize(src),src->depth,1);
	IplImage* dst_adp=cvCreateImage(cvGetSize(src),src->depth,1);
	//
	cvThreshold(src,dst,100,100,CV_THRESH_BINARY);
	cvShowImage("threshold",dst);
	cvAdaptiveThreshold(src,dst_adp,100,
		CV_ADAPTIVE_THRESH_MEAN_C);
	cvShowImage("threshold_adp_mean",dst_adp);
	cvAdaptiveThreshold(src,dst_adp,100,
		CV_ADAPTIVE_THRESH_GAUSSIAN_C);
	cvShowImage("threshold_adp_gaussian",dst_adp);
	// free
	cvWaitKey(0);
	cvDestroyAllWindows();
	cvReleaseImage(&src);
	cvReleaseImage(&dst);
	return 0;
}


三、运行结果

 

 

 

原图像灰度化 固定阈值
高斯阈值 平均阈值

 

 

 

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