【opencv】示例-train_HOG.cpp 训练和测试基于支持向量机(SVM)的行人检测器

aed69e4f2a0a27cd431dce62ee6b2fdd.png

#include "opencv2/imgproc.hpp"  // 包含OpenCV图像处理头文件
#include "opencv2/highgui.hpp"  // 包含OpenCV高层GUI(图形用户界面)头文件
#include "opencv2/ml.hpp"       // 包含OpenCV机器学习模块头文件
#include "opencv2/objdetect.hpp"// 包含OpenCV目标检测模块头文件
#include "opencv2/videoio.hpp"  // 包含OpenCV视频I/O模块头文件
#include <iostream>             // 包含输入输出流头文件
#include <time.h>               // 包含C标准库时间操作头文件


using namespace cv;             // 使用cv命名空间
using namespace cv::ml;         // 使用cv::ml命名空间
using namespace std;            // 使用std命名空间


// 函数声明区
vector< float > get_svm_detector( const Ptr< SVM >& svm );  // 获取SVM检测器的函数声明
void convert_to_ml( const vector< Mat > & train_samples, Mat& trainData );  // 将训练样本转换为机器学习算法格式的函数声明
void load_images( const String & dirname, vector< Mat > & img_lst, bool showImages );  // 加载图片的函数声明
void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, const Size & size );  // 获取负样本的函数声明
void computeHOGs( const Size wsize, const vector< Mat > & img_lst, vector< Mat > & gradient_lst, bool use_flip );  // 计算HOG特征的函数声明
void test_trained_detector( String obj_det_filename, String test_dir, String videofilename );  // 测试训练好的检测器的函数声明


// 获取SVM支持向量机的检测器
vector< float > get_svm_detector( const Ptr< SVM >& svm )
{
    // 获取支持向量
    Mat sv = svm->getSupportVectors();
    const int sv_total = sv.rows;
    // 获取决策函数
    Mat alpha, svidx;
    double rho = svm->getDecisionFunction( 0, alpha, svidx );


    // 检查维度和数据类型是否一致
    CV_Assert( alpha.total() == 1 && svidx.total() == 1 && sv_total == 1 );
    CV_Assert( (alpha.type() == CV_64F && alpha.at<double>(0) == 1.) ||
               (alpha.type() == CV_32F && alpha.at<float>(0) == 1.f) );
    CV_Assert( sv.type() == CV_32F );


    // 预备HOG检测器向量
    vector< float > hog_detector( sv.cols + 1 );
    memcpy( &hog_detector[0], sv.ptr(), sv.cols*sizeof( hog_detector[0] ) );
    hog_detector[sv.cols] = (float)-rho; // 最后一个元素是偏移量rho
    return hog_detector; // 返回HOG检测器
}


/*
* 将训练/测试集转换为OpenCV机器学习算法可以使用的格式。
* TrainData是一个矩阵,大小为(#samples x max(#cols,#rows) per sample),数据类型为32FC1。
* 如果需要,会进行样本的转置。
*/
void convert_to_ml( const vector< Mat > & train_samples, Mat& trainData )
{
    // 转换数据
    const int rows = (int)train_samples.size();
    const int cols = (int)max( train_samples[0].cols, train_samples[0].rows );
    Mat tmp( 1, cols, CV_32FC1 ); // 用于必要时的转置
    trainData = Mat( rows, cols, CV_32FC1 );


    // 遍历训练样本并将它们转换为一维特征向量
    for( size_t i = 0 ; i < train_samples.size(); ++i )
    {
        // 确保每个训练样本是一维的
        CV_Assert( train_samples[i].cols == 1 || train_samples[i].rows == 1 );
        
        // 如果样本是列向量,需要进行转置
        if( train_samples[i].cols == 1 )
        {
            transpose( train_samples[i], tmp );
            tmp.copyTo( trainData.row( (int)i ) );
        }
        // 如果样本已经是行向量,直接复制
        else if( train_samples[i].rows == 1 )
        {
            train_samples[i].copyTo( trainData.row( (int)i ) );
        }
    }
}


// 加载图片的函数实现
void load_images( const String & dirname, vector< Mat > & img_lst, bool showImages = false )
{
    vector< String > files; // 文件名的字符串数组
    glob( dirname, files ); // 读取目录下的所有文件名


    // 遍历文件名,加载每张图片
    for ( size_t i = 0; i < files.size(); ++i )
    {
        Mat img = imread( files[i] ); // 读取图片
        // 若图片为空,则输出无效并继续
        if ( img.empty() )
        {
            cout << files[i] << " is invalid!" << endl; // 如果图片无效,则输出错误信息
            continue;
        }
        // 如果需要显示图片,则显示每一张载入的图片
        if ( showImages )
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值