睁闭眼状态检测——SVM模型训练

前言

svm训练模型相当简单,难的是提取特征这一步,这里介绍了一个睁闭眼检测功能从提取特征到预测的全过程。

首先,需要准备数据,我这里有睁眼和闭眼的照片各3000张,传统的机器学习方法都需要提取特征,这里检测特征用到了三个,通过程序预先提取出来了;接下来是模型的训练和预测过程。

提取特征:左右开眼率(上下眼皮的特征点距离)、黑色眼球的圆弧度(霍夫变换检测园)、眼球长宽比(人脸特征点)

         

特征提取出来:文件名+三个特征+标签(0睁眼、1闭眼)

然后把三个特征进行归一化,更有利于训练,并去掉了文件名(不需要)

模型训练(python)

这一步主要是把txt文本中的特征读取进来,每一张图片用一行三个特征表示;因此,n张图片转化成一个n行3列的特征矩阵,以及一个n行1列的label矩阵,然后使用svm训练

from numpy import *
import numpy as np
import cv2
import matplotlib.pyplot as plt

def loadDataSet(fileName):
    dataMat = []
    labelMat = []
    with open(fileName) as fr:
        for line in fr.readlines():
            lineArr = line.strip().split('    ')
            dataline = list(map(float, lineArr))
            
            dataMat.append([float(dataline[0]), float(dataline[1]), float(dataline[2])])
            labelMat.append([int(dataline[3])])
    return dataMat, labelMat

#加载训练集
train_data,train_label = loadDataSet('new/img/train-20/right.txt')   #1.加载一个txt数据集
train_data = mat(train_data)
train_data=np.array(train_data, dtype='float32')
train_label = mat(train_label)


#加载测试集
test_data,test_label = loadDataSet('new/img/train-20/test-right.txt')   #1.加载一个txt数据集
test_data = mat(test_data)
test_data=np.array(test_data, dtype='float32')
test_label=mat(test_label)
# print(test_label.shape)


# 创建分类器
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)  # SVM类型
svm.setKernel(cv2.ml.SVM_LINEAR) # 使用线性核
svm.setC(1e-5)

# 训练
ret = svm.train(train_data, cv2.ml.ROW_SAMPLE, train_label)
# svm.save('img/left.xml')

# 支持向量
vec = svm.getSupportVectors()
print("最终结果:",vec)

# 测试
(ret, res) = svm.predict(test_data)
# print(res)

# 准确率
n=0
lens=len(test_data)
for i in range(lens):
    if res[i]==test_label[i]:
        n=n+1

Accuracy=n/lens
print("准确度为:",Accuracy)

最后得到结果如下:

保存的模型:

加载模型预测:

使用svm = cv2.ml.SVM_load()即可加载一个训练好的模型,并且进行预测

# 创建分类器
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)  # SVM类型
svm.setKernel(cv2.ml.SVM_LINEAR) # 使用线性核
svm.setC(1e-5)

svm = cv2.ml.SVM_load("new/img/train-30/svm-right.xml")
svm2 = cv2.ml.SVM_load("new/c++/svm-left.xml")

# 测试
(ret1, res1) = svm.predict(test_data)
(ret2, res2) = svm2.predict(test_data)

再贴个c++版本的svm代码:

#include<opencv2\opencv.hpp> 

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

int main()
{
    float train_data[2850][3];  
    int train_label[2850][1];
    ifstream file1("D:/work/Test/Test2/test2--图像处理/svm--眼睛状态检测/c++/train_data.txt");
    ifstream file2("D:/work/Test/Test2/test2--图像处理/svm--眼睛状态检测/c++/train_label.txt");

    // 训练数据
    for (int i = 0; i < 2850; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            file1 >> train_data[i][j];
            //cout << train_data[i][j] << " ";
        }
        //cout << endl;
    }
    // 训练标签
    for (int i = 0; i < 2850; i++)
    {
        for (int j = 0; j < 1; j++)
        {
            file2 >> train_label[i][j];
            //cout << train_label[i][j] << " ";
        }
        //cout << endl;
    }
    file1.close();
    file2.close();

    Mat dataMat(2850, 3, CV_32FC1, train_data);
    Mat labelMat(2850, 1, CV_32SC1, train_label);


    //训练的初始化
    Ptr<SVM> svm = SVM::create();
    svm->setType(SVM::C_SVC);
    svm->setKernel(SVM::LINEAR);
    svm->setTermCriteria(cv::TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 1500, 1e-5));

    开始训练
    svm->train(dataMat, ROW_SAMPLE, labelMat);
    svm->save("D:/work/Test/Test2/test2--图像处理/svm--眼睛状态检测/c++/svm2.xml");
    svm->load("svm.xml");
    std::cout << "模型训练完毕!" << endl;


    //Mat result;   //返回结果
    //float testData[2][3] = {
    //    { 0.814973, 15.1147, 0.431797 },
    //    { 1.514973, 18.1147, 0.436597 }
    //};   //预测数据
    //Mat test(2, 3, CV_32FC1, testData);    //预测数据

    //svm->predict(test, result);   //进行预测
    //std::cout << "分类结果为:" << endl;
    //std::cout << result << endl;



     把预测结果提取出来
    //int len = test.rows;;
    //for (int i = 0; i < len; i++)
    //{
    //    int a = result.at<Point2f>(i, 0).x;   // 把预测结果提取出来
    //    std::cout << a << endl;
    //}

    return 0;

}

  • 7
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值