OpenCV 2.4+ C++ SVM文字识别

  • 时间:
  • 浏览:0
  • 来源:大发uu快3_uu快3官方网站_大发uu快3官方网站

OpenCV 2.4+ C++ SVM文字识别

2012-11-27 09:26  Justany_WhiteSnow  阅读(...)  评论()  编辑  收藏

积极分子知识

下面原来都全是必备知识,统统可能性你想了解更多内容,可参考这两篇文章。

OpenCV 2.4+ C++ SVM介绍

OpenCV 2.4+ C++ SVM线性不可分正确处理

SVM划分的意义

到此,亲戚亲戚当我们当我们 可能性对SVM有一定的了解了。原来 这有哪几次用呢?回到上一篇文章结果图:

你这类 结果图的意义在于,他成功从二维划分了分类的区域。于是可能性原来 ,有原来新的样本在绿色区域,没法 亲戚亲戚当我们当我们 就都也能把他当成是绿色的点。

可能性这都也能像更高维度推广,统统可能性亲戚亲戚当我们当我们 能对样品映射成高维度空间的点,当有足够多的样品时,亲戚亲戚当我们当我们 同样都也能找到原来高维度的超平面划分,使得同一类样品的映射点在同一区域,于是当有新样品落在哪几次区域是,亲戚亲戚当我们当我们 都也能把它当成是你这类 类型的样本。

通俗这类

可能性亲戚亲戚当我们当我们 能更加通俗这类 。比如亲戚亲戚当我们当我们 来识别男性和女孩子。

亲戚亲戚当我们当我们 发现男性和女孩子可能性头发长度不一样,可能性胸围不一样,于是亲戚亲戚当我们当我们 对样本个体产生原来 的这类映射:

    人 —> (头发长度, 胸围)

于是亲戚亲戚当我们当我们 将每个样品映射到二维平面,其中“头发的长度”和“胸围的长度”分别是x轴和y轴。亲戚亲戚当我们当我们 把哪几次样品丢给SVM学习,则他会寻找出原来合理的x和y的区域来划分男性和女孩子。

当然,全是可能性这类 男的头发比女的还长,有的男性的胸围比女孩子还大,哪几次统统错分点,它们也影响着划分。

最后,当亲戚亲戚当我们当我们 把原来人映射到你这类 二维空间时,SVM就都也能根据以往的学习,猜一猜你这当时人到底是哪几次性别。

亲戚亲戚当我们当我们 学到了哪几次呢?

好吧,底部形态要找准这类 ,统统可能性遇到下面的悲剧……

可能性这是老板,你可就死翘翘了……

简单的文字识别

当然计算机没没法 厉害能看出你的胸围可能性头发长短。他都也能这类 他能拿出的东西,不怎么计算机通常“都看”的是下面的你这类 东东……

亲戚亲戚当我们当我们 都也能对文字找到他的底部形态,来映射到高维空间。

还记得小学原来 练字的米字格么?这似乎暗示了亲戚亲戚当我们当我们 ,嘴笨 每当时人写的字千差万别,统统亲戚亲戚当我们当我们 却具有一定的特点。

亲戚亲戚当我们当我们 尝试原来 做,取原来字,确定原来含晒 该字的正方形区域,将你这类 正方形区域分割成8*8个小格,统计每个小格中像素的数量,以哪几次数量为维度进行映射。

OK,明白了原理让亲戚亲戚当我们当我们 之前 结速了了吧。

被提醒了,没法 补充一句:你这类 例子在实际中用来辨认是不可行的。

样本获取

可能性通常文字样本全是白底黑字的,而手写也都也能直接获取写入的数据而无视背景,统统亲戚亲戚当我们当我们 暂且都也能对样本进行提取,但亲戚亲戚当我们当我们 都也能对他定位,并弄成至少的大小。

比如,你没法 正确处理他们没法 写字……

坑爹啊,好好的没法 大地方你就躲在左上角……

之前 结速了了定位

void getROI(Mat& src, Mat& dst){
    int left, right, top, bottom;
    left = src.cols;
    right = 0;
    top = src.rows;
    bottom = 0;

    //得到区域
    for(int i=0; i<src.rows; i++)
    {
        for(int j=0; j<src.cols; j++)
        {
            if(src.at<uchar>(i, j) > 0)
            {
                if(j<left) left = j;
                if(j>right) right = j;
                if(i<top) top = i;
                if(i>bottom) bottom = i;
            }
        }
    }

    int width = right - left;
    int height = bottom - top;

    //创建存储矩阵
    dst = Mat::zeros(width, height, CV_8UC1);

    Rect dstRect(left, top, width, height);
    dst(dstRect);
}

这段代码通过遍历所有图像矩阵的元素,来获取该样本的定位和大小。并把样本提取出来。

重新缩放

Mat dst = Mat::zeros(8, 8, CV_8UC1);

resize(src, dst, dst.size());

进行缩放,把所有样本变成8*8的大小。为了简便,亲戚亲戚当我们当我们 把像素几次变成了像素的灰度值。

resize的API:

调整图片大小

C++: void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )
参数
  • src – 输入图像。
  • dst – 输出图像;它有原来dsize (当其不为0时) 可能性你这类 size由 src.size(),fxfy算出dst的类型和src相同。
  • dsize –

    输出图像的大小,可能性取值为0,则:

    dsize可能性fxfy都也能有这类大小决定方法不为0。

  • fx –

    水平轴缩放因子,当取值为0时,则为:

  • fy –

    垂直轴缩放因子,当取值为0时,则为:

  • interpolation –

    插值方法

    • INTER_NEAREST - 最近邻值插入方法。
    • INTER_LINEAR - 双线性插值(默认方法)。
    • INTER_AREA - 使用象素关系重采样。当图像缩小原来 ,该方法都也能正确处理波纹总出 。当图像放大时,这类于 CV_INTER_NN 方法。
    • INTER_CUBIC - 立方插值。
    • INTER_LANCZOS4 - 8x8的Lanczos插入方法。

准备样本数据

Mat data = Mat::zeros(total, 64, CV_32FC1);    //样本数据矩阵  
Mat res = Mat::zeros(total, 1, CV_32SC1);    //样本标签矩阵

res.at<double>(k, 1) = label;    //对第k个样本添加分类标签

//对第k个样本添加数据
for(int i = 0; i<8; i++)  {  
    for(int j = 0; j<8; j++)  {  
        res.at<double>(k, i * 8 + j) = dst.at<double>(i, j);  
    }  
}

将原来 的结果,输入样本,并添加标签。

训练

CvSVM svm = CvSVM();   
CvSVMParams param;   
CvTermCriteria criteria;  
  
criteria= cvTermCriteria(CV_TERMCRIT_EPS, 10000,  FLT_EPSILON);   
param= CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 8.0, 1.0, 10.0, 0.5, 0.1, NULL, criteria);   
  
svm.train(data, res, Mat(), Mat(), param);  
svm.save( "SVM_DATA.xml" );  

之前 结速了了训练并保存训练数据。

使用

CvSVM svm = CvSVM();   
svm.load( "SVM_DATA.xml" );
svm.predict(m);        //对样本向量m检测

 参考资料

 使用OPENCV训练手写数字识别分类器 . firefight . 2011-05-28

  • 分类 Computer Vision
  • 标签 OpenCV