SVM分类器实践,检测是否有篮球

对于svm的原理在上一章有了一个基础的了解,主要是用的OPencv提供的相关算法去实现的。要彻底了解SVM需要,还需要继续花时间和精力。这里来了解一些如何使用SVM分类器进行物体识别。这次就以识别篮球为例子。

首先我们要对一个环境进行训练。我们需要一个正采样和一个负采样。我们在工作目录下建立一个train目录
这里写图片描述

在train目录下,pos放置的是有篮球的图片,neg目录下放置的是没有篮球的图片
这里写图片描述

neg.lst 和 pos.lst 文件是图片目录的位置

train/neg/0.bmp
train/neg/1.bmp
train/neg/2.bmp
.......
train/neg/19.bmp
train/neg/20.bmp

以下是训练的代码

#include <iostream>  
#include <fstream>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/objdetect/objdetect.hpp>  
#include <opencv2/ml/ml.hpp>  

#define PosSamNum 16    //正样本个数  
#define NegSamNum 21   //负样本个数  

std::string train_image_folder = "./";
std::string test_image_folder = "./";

void train() {

    std::cout << "start traning..." << std::endl;

    std::ifstream train_pos_file(train_image_folder + "train/pos.lst");
    std::ifstream train_neg_file(train_image_folder + "train/neg.lst");

    std::string image_name; //图片路径

    cv::Mat src;

    //定义HOG检测器
    int descriptor_dim = 0;
    //                    检测窗口(64,128),  块尺寸(16,16),   块步长(8,8),   cell尺寸(8,8),直方图bin个数9 
    cv::HOGDescriptor hog(cv::Size(64, 128), cv::Size(16, 16), cv::Size(8, 8), cv::Size(8, 8), 9);//HOG检测器,用来计算HOG描述子的
    std::vector<float> descriptors; //HOG描述子向量


    cv::Mat sample_features; //所有训练样本的特征向量组成的矩阵,行数等于所有样本的个数,列数等于HOG描述子维数  
    cv::Mat sample_labels;  //训练样本的类别向量,行数等于所有样本的个数,列数等于1;1表示有人,-1表示无人  

                            //获取训练数据的正样本
    for (int num = 0; num<PosSamNum && getline(train_pos_file, image_name); num++)
    {
        image_name = train_image_folder + image_name;
        src = cv::imread(image_name, 0);

        cv::resize(src, src, cv::Size(96, 160)); //统一训练格式

        if (src.empty()) {
            std::cout << "no image in pos image path:" << image_name << std::endl;
            exit(0);
        }

        hog.compute(src, descriptors, cv::Size(8, 8));

        if (num == 0) {
            std::cout << "Init feature size..." << std::endl;
            descriptor_dim = descriptors.size();
            sample_features = cv::Mat::zeros(PosSamNum + NegSamNum, descriptor_dim, CV_32FC1);
            sample_labels = cv::Mat::zeros(PosSamNum + NegSamNum, 1, CV_32SC1); //注意这里必须要32SC1,不能用32FC1
        }

        for (int i = 0; i<descriptor_dim; i++) {
            sample_features.at<float>(num, i) = descriptors[i];
        }
        sample_labels.at<int>(num, 0) = 1; //正样本类别为1,有人

        std::cout << "finish Pos " << num << " " << image_name << std::endl;

    }

    //获取训练数据的负样本
    for (int num = 0; num<NegSamNum && getline(train_neg_file, image_name); num++) {
        image_name = train_image_folder + image_name;
        src = cv::imread(image_name, 0);
        if (src.empty()) {
            std::cout << "no image in neg image path..." << std::endl;
            exit(0);
        }
        cv::resize(src, src, cv::Size(96, 160));

        hog.compute(src, descriptors, cv::Size(8, 8));

        for (int i = 0; i<descriptor_dim; i++) {
            sample_features.at<float>(num + PosSamNum, i) = descriptors[i];
        }
        sample_labels.at<int>(num + PosSamNum, 0) = -1; //正样本类别为-1,没有人

        std::cout << "finish Neg " << num << " " << image_name << std::endl;
    }


    //训练SVM分类器
    std::cout << "start svm training..." << std::endl;
    cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
    svm->setType(cv::ml::SVM::C_SVC);
    svm->setKernel(cv::ml::SVM::LINEAR);
    svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 1e-6));
    svm->train(sample_features, cv::ml::ROW_SAMPLE, sample_labels);

    //保存SVM分类器
    std::cout << "start saving svm file..." << std::endl;
    svm->save("test_svm.xml");

    std::cout << "finish training..." << std::endl;
    return;
}


int main(int argc, char* argv[]) {

    train();
    return 0;
}

执行完这个程序后会生成一个test_svm.xml文件这里写图片描述

之后就可以读取test_svm.txt文件对环境进行识别是否有篮球

#include <iostream>  
#include <fstream>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/objdetect/objdetect.hpp>  
#include <opencv2/ml/ml.hpp>  

int main() 
{
    cv::VideoCapture capture(0);
    cv::Mat test_image;

    while (true)
    {
        capture >> test_image;
        if (test_image.empty()) {
            std::cout << "Input test image path is error!" << std::endl;
            return -1;
        }

        //获取特征并组织为单行的格式
        cv::resize(test_image, test_image, cv::Size(96, 160)); //训练样本的尺寸是(96,160),修改训练数据后,要同步修改
        cv::HOGDescriptor hog(cv::Size(64, 128), cv::Size(16, 16), cv::Size(8, 8), cv::Size(8, 8), 9);
        std::vector<float> descriptors;
        hog.compute(test_image, descriptors, cv::Size(8, 8));
        cv::Mat test_feature = cv::Mat::zeros(1, descriptors.size(), CV_32FC1);
        for (int i = 0; i<descriptors.size(); i++) {
            test_feature.at<float>(0, i) = descriptors[i];
        }

        //加载SVM
        cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
        svm = cv::ml::SVM::load("./test_svm.xml");

        //输出结果
        cv::Mat result;
        svm->predict(test_feature, result);
        float res = result.at<float>(0, 0);
        cv::imshow("", test_image);
        if (res == 1) {
            std::cout << "Result: 1 " << std::endl;
        }
        else if (res == -1) {
            std::cout << "Result: -1" << std::endl;
        }
        cv::waitKey(1);
    }
    return 0;
}

执行后 如果返回1,就证明环境下有篮球,如果为-1,就是没有篮球

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值