天天看点

OpenCV自学笔记18. 基于SVM和神经网络的车牌识别(二)

基于SVM和神经网络的车牌识别(二)

本系列文章参考自《深入理解OpenCV实用计算机视觉项目解析》仅作学习用途

基于SVM的图像分类

在​​上一篇​​中,我们最后得到的图像,有一定可能不是车牌,所以需要加入一个分类的程序,把车牌和非车牌分开。在书中,使用SVM实现分类的功能。

书上没有给出创建训练和测试图像数据的步骤,但是给了一个xml文件(见下图),文件中是用于训练和测试的文本数据,下面直接使用这个xml文件,训练我们的分类器。

OpenCV自学笔记18. 基于SVM和神经网络的车牌识别(二)
本篇使用的测试图片是:
OpenCV自学笔记18. 基于SVM和神经网络的车牌识别(二)
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <ml.hpp>

using namespace std;
using namespace cv;
using namespace ml;


/* 基于SVM的图像分类 */
bool classification(Mat image_crop) {

    // Step0. 处理输入图像,对大小和type都有具体的规定
    // rows = 33, cols = 144, type = 5 (CV_32FC1)
    Mat src;
    src.create(33, 144, CV_32FC1);
    resize(image_crop, src, src.size(), 0, 0, INTER_CUBIC);
    src.convertTo(src, CV_32FC1);
    src = src.reshape(1, 1);    

    // Step1. 设置训练数据
    // 这里基于OpenCV310,写法可能与OpenCV249等不同
    FileStorage fs;
    fs.open("SVM.xml", FileStorage::READ);
    Mat trainingDataMat;
    Mat classesMat;
    fs["TrainingData"] >> trainingDataMat;
    fs["classes"] >> classesMat;
    Ptr<TrainData> trainingData = TrainData::create(trainingDataMat, ROW_SAMPLE, classesMat);

    // Step2. 创建分类器,并设置参数
    SVM::ParamTypes params;
    SVM::KernelTypes kernel_type = SVM::LINEAR;
    Ptr<SVM> svm = SVM::create();
    svm->setKernel(kernel_type);

    // Step3. 训练分类器
    svm->trainAuto(trainingData);

    // Step4. 预测
    // 1表示是车牌,0表示非车牌
    int response = svm->predict(src);
    return response;
}


int main() {
    Mat src = imread("2715DTZ.jpg", 0);
    bool flag = classification(src);
    cout << "flag = " <<  flag << endl;
    waitKey();
    return 0;
}      
程序的运行结果为:
OpenCV自学笔记18. 基于SVM和神经网络的车牌识别(二)

感觉这个分类器有时候并不准确,对于下面这张图,分类的结果就是非车牌

(T_T)。由于没有自己做数据,猜测训练数据中的车牌都比较方方正正,角度也近似水平,如果能增大训练样本,应该会更准确一些。

  1. SVM
  2. OpenCV SVM :​​http://docs.opencv.org/master/d1/d2d/classcv_1_1ml_1_1SVM.html​​
  3. SVM 使用方法

继续阅读