以下摘录自
http://blog.csdn.net/zhaocj?viewmode=contents
Opencv2.4.9源码分析要点摘录
Boosting
AdaBoost的计算步骤:
1、设有n个样本x1, …, xn,它们所希望得到的输出(即分类)为y1, …, yn,y∈{-1, 1};
2、初始化每个样本的权值;
3、进行迭代:m = 1, …, M
①找到使误差率 最小的弱分类器km(x);
②计算km(x)的权值;
③得到新的强分类器;
④更新每个样本的权值;
⑤对权值wi(m+1)进行归一化处理,使∑iwi(m+1)= 1;
4、得到最终的强分类器
构建Boosting的参数:
CvBoostParams::CvBoostParams()
{
......
}
CvBoostParams::CvBoostParams( int _boost_type, int _weak_count,
double _weight_trim_rate, int _max_depth,
bool _use_surrogates, const float* _priors )
{
......
}
其中参数的含义为:
boost_type表示Boosting算法的类型,可以是CvBoost::DISCRETE、CvBoost::REAL、CvBoost::LOGIT或
CvBoost::GENTLE这4类中的任意一个,OpenCV推荐使用GentleAdaBoost或Real AdaBoost算法
_weak_count表示弱分类器的数量,即迭代的次数
_weight_trim_rate表示裁剪率,在0~1之间,默认值为0.95,在迭代过程中,那些归一化后的样本权值
wi(m)小于该裁剪率的样本将不进入下次迭代
_max_depth表示构建决策树的最大深度
_use_surrogates表示在构建决策树时,是否使用替代分叉属性
_priors表示样本的先验概率
CvBoost类的两个构造函数:
CvBoost::CvBoost( const Mat& _train_data, int _tflag,
const Mat& _responses, const Mat& _var_idx,
const Mat& _sample_idx, const Mat& _var_type,
const Mat& _missing_mask,
CvBoostParams _params )
{
......
}
CvBoost::CvBoost()
{
......
}
两个train函数:
bool CvBoost::train( CvMLData* _data, //训练样本数据
CvBoostParams _params, //构建Boosting的参数
bool update )
//update表示是更新分类器,还是重新创建分类器,默认是false,表示重新创建
{
......
}
bool
CvBoost::train( const CvMat* _train_data, int _tflag,
const CvMat* _responses, const CvMat* _var_idx,
const CvMat* _sample_idx, const CvMat* _var_type,
const CvMat* _missing_mask,
CvBoostParams _params, bool _update )
{
......
}
更新权值函数,当要初始化权值时,参数tree为0,表示此时还没有弱分类器:
void
CvBoost::update_weights( CvBoostTree* tree ) {
......
}
更新权值的核心函数:
void
CvBoost::update_weights_impl( CvBoostTree* tree, double initial_weights[2] )
{
......
}
从上面的train函数可以看出,它主要是调用do_train函数,而CvBoostTree类没有do_train函数,因此
train函数是调用CvBoostTree类的父类CvDTree中的do_train函数:
bool CvDTree::do_train( const CvMat* _subsample_idx )
{
......
}
递归调用try_split_node函数,完成决策树的构造:
void
CvBoostTree::try_split_node( CvDTreeNode* node )
{
......
}
预测函数predict:
float
CvBoost::predict( const CvMat* _sample, const CvMat* _missing,
CvMat* weak_responses, CvSlice slice,
bool raw_mode, bool return_sum ) const
{
......
}
OpenCV是用决策树来得到弱分类器的,因此实现弱分类器的类CvBoostTree继承于构建决策树的类
CvDTree,CvBoostTree类内的train函数和try_split_node函数都是虚函数,它们是针对用于弱分类器设
计的决策树的特殊性而重写的函数,这样的虚函数还有许多,如find_surrogate_split_ord、
find_split_ord_class、calc_node_value等。与CvDTree类的不同的地方;
1、构建弱分类器的每个样本都有权值,即wi(m),在决策树中被称为是先验概率;
2、用于衡量分类树纯度的不仅有基尼指数,还有错误分类率这种方法;
3、弱分类器只是一个用于研究两类问题的决策树,所有要相对简单一点;
4、不同的弱分类器所应用的训练样本的数量可能会不同。
HoughLines
霍夫变换是一种特征提取技术。经典的霍夫变换能够识别出图像中的直线,后来又发展到能够识别出任
意形状,但更常见的识别形状是圆和椭圆。函数HoughLines的作用就是能够检测出边缘图像中的直线。
函数HoughLines的霍夫变换直线检测的步骤:
1、对边缘图像进行霍夫空间变换;
2、在4邻域内找到霍夫空间变换的极大值;
3、对这些极大值安装由大到小顺序进行排序,极大值越大,越有可能是直线;
4、输出直线。
函数HoughLines的原型为:
void HoughLines(InputArray image,OutputArray lines, double rho, double theta, int
threshold, double srn=0,double stn=0 )
image为输入图像,要求是单通道的二值图像
lines为输出直线向量,两个元素的向量(ρ,θ)代表一条直线,ρ是从原点(图像的左上角)的距离
,θ是直线的角度(单位是弧度),0表示垂直线,π/2表示水平线
rho为距离分辨率
theta为角度分辨率
threshold为阈值,在步骤2中,只有大于该值的点才有可能被当作极大值,即至少有多少条正弦曲线交
于一点才被认为是直线
srn和stn在多尺度霍夫变换的时候才会使用,在这里我们只研究经典霍夫变换
HoughLines函数是在sources/modules/imgproc/src/hough.cpp文件中定义的;
cvHoughLines2函数是霍夫变换直线检测的关键,函数的输出为所检测到的直线序列,它的第3个形
参“srn == 0 && stn == 0 ? CV_HOUGH_STANDARD :CV_HOUGH_MULTI_SCALE”表示的是该霍夫变换是经
典霍夫变换还是多尺度霍夫变换,它是由变量srn和stn决定的,只要这两个变量有一个不为0,就进行多
尺度霍夫变换,否则为经典霍夫变换。另外cvHoughLines2函数不仅可以用于经典霍夫变换和多尺度霍夫
变换,还可以用于概率霍夫变换。
CV_IMPL CvSeq*
cvHoughLines2( CvArr* src_image, void* lineStorage, int method,
double rho, double theta, int threshold,
double param1, double param2 )
{
......
}
对于经典霍夫变换,调用的是icvHoughLinesStandard函数:
static void
icvHoughLinesStandard( const CvMat* img, float rho, float theta,
int threshold, CvSeq *lines, int linesMax )
{
......
}
由于函数HoughLines只输出直线所对应的角度和距离,所以在进行直线检测的时候还要把其转换为直角
坐标系下的数据,另外输入图像还必须是边缘图像;