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 高斯加权平均
二、例程:
//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
- void cvAnd(
- const CvArr* src1,
- const CvArr* src2,
- CvArr* dst,
- const CvArr* mask = NULL
- );
- void cvAndS(
- const CvArr* src1,
- CvScalar value,
- CvArr* dst,
- const CvArr* mask = NULL
- );
这两个函数在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
 
                    
                     
                    
                 
                    
                 

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号