• hog+svm+检测人(代替默认的参数)


    #include <iostream>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/ml/ml.hpp>
    //#include <opencv2/gpu/gpu.hpp>
    #include <fstream>
    #include <iomanip>

    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/objdetect/objdetect.hpp"

    #define FEATURE_DIM 3780

    using namespace std;
    using namespace cv;


    class MySVM : public CvSVM
    {
    public:
    //获得SVM的决策函数中的alpha数组
    double * get_alpha_vector()
    {
    return this->decision_func->alpha;
    }

    //获得SVM的决策函数中的rho参数,即偏移量
    float get_rho()
    {
    return this->decision_func->rho;
    }
    };
    int main()
    {
    #if 0
    Mat image;
    image = imread("D:\dataset\temp\6.png");
    HOGDescriptor hog;
    vector<float> v_feature;
    hog.compute(image, v_feature, cv::Size(8, 8));
    //hog.compute(image, v_feature, cv::Size(16, 16));

    int featureVecSize = v_feature.size();
    cout << "****************************************haha****************" << endl;
    cout << featureVecSize << endl;
    #else
    //***************************************************************************************************
    // 初始化
    //***************************************************************************************************

    //char positivePath[256] = "D:\dataset\INRIAPerson\Train\pos\"; //改路径
    //char negativePath[256] = "D:\dataset\INRIAPerson\Train\neg\";
    //char testPath[256] = "D:\dataset\INRIAPerson\Test\pos\";
    char positivePath[256] = "D:\dataset\INRIAPerson\train_64x128_H96\pos\";
    char negativePath[256] = "D:\dataset\INRIAPerson\train_64x128_H96\neg\";

    //char testPath[256] = "D:\dataset\INRIAPerson\70X134H96\Test\pos\";
    char testPath[256] = "D:\dataset\INRIAPerson\test_64x128_H96\pos\";
    //char testPath[256] = "D:\dataset\INRIAPerson\test_64x128_H96\neg\";

    char classifierSavePath[256] = "D:\dataset\INRIAPerson\myResult";

    int positiveSampleCount = 614; //改数据
    int negativeSampleCount = 1218;
    //int positiveSampleCount = 100;
    //int negativeSampleCount = 100;
    int totalSampleCount = positiveSampleCount + negativeSampleCount;
    int testSampleCount = 1126;
    //int testSampleCount = 100;

    CvMat *sampleFeaturesMat = cvCreateMat(totalSampleCount, FEATURE_DIM, CV_32FC1); //改向量维数
    cvSetZero(sampleFeaturesMat);
    CvMat *sampleLabelMat = cvCreateMat(totalSampleCount, 1, CV_32FC1);
    cvSetZero(sampleLabelMat);

    //CvMat *testFeaturesMat = cvCreateMat(testSampleCount, FEATURE_DIM, CV_32FC1); //参数1764? 正288,负453
    CvMat *testFeaturesMat = cvCreateMat(1, FEATURE_DIM, CV_32FC1); //参数1764? 正288,负453
    cvSetZero(testFeaturesMat);
    //CvMat *testLabelMat = cvCreateMat(testSampleCount, 1, CV_32FC1);//样本标识
    //cvSetZero(testLabelMat);
    float testLabelMat[288] = { 0.0 };
    //Mat sampleFeaturesMat();

    HOGDescriptor hog(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);//HOG检测器,用来计算HOG描述子的
    vector<float> v_feature;


    //***************************************************************************************************
    // 正例的特征
    //***************************************************************************************************
    //positive文件读入
    //ifstream fin(positivePath, ios::in);
    //if (!fin)
    //{
    // cout << "positivePath can not open the file!" << endl;
    // return -1;
    //}
    char positiveImage[256];
    string path;
    string s_positiveImage;
    for (int i = 0; i < positiveSampleCount; i++)
    {
    //图片名修改
    memset(positiveImage, '', sizeof(positiveImage));
    sprintf(positiveImage, "%d.png", i + 1); //要改成.jpg吗
    s_positiveImage = positiveImage;
    path = positivePath + s_positiveImage;

    Mat image = imread(path);
    if (image.data == NULL)
    {
    cout << "positive image sample load error: " << i << " " << path << endl;
    system("pause");
    continue;
    }
    //hog特征提取
    //gpu::HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9); //貌似还有一些参数,重载了?
    //HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9);
    //HOGDescriptor hog;
    // vector<float> v_feature;
    image = image(Rect(16, 16, 64, 128));
    hog.compute(image, v_feature, cv::Size(8, 8));
    //hog.compute(image, v_feature, cv::Size(16, 16));

    int featureVecSize = v_feature.size();
    //cout << "****************************************haha****************" << endl;
    //cout << featureVecSize<<endl;
    //return 0;
    for (int j = 0; j<featureVecSize; j++)
    {
    //sampleFeaturesMat[i][j] = v_feature[j];
    CV_MAT_ELEM(*sampleFeaturesMat, float, i, j) = v_feature[j]; //CV_MAT_ELEM什么意思
    }
    sampleLabelMat->data.fl[i] = 1; //.fl[]是什么
    cout << "positive" << i + 1 << "is running..." << endl;
    }
    //fclose(fin);
    //***************************************************************************************************
    // 负例的特征
    //***************************************************************************************************
    //negative文件读入
    //ifstream fin(negativePath, ios::in);
    //if (!fin)
    //{
    // cout << "can not open the file!" << endl;
    // return -1;
    //}
    char negativeImage[256] = ""; //初始化吗
    string s_negativeImage;
    for (int i = 0; i < negativeSampleCount; i++)
    {
    //图片名修改
    //hog特征提取
    memset(negativeImage, '', sizeof(negativeImage));
    sprintf(negativeImage, "%d.png", i + 1); //要改成.jpg吗
    s_negativeImage = negativeImage;
    path = negativePath + s_negativeImage;
    //cout << "********************************************************"<<endl;
    //cout << path<<endl;
    Mat image = imread(path);
    if (image.data == NULL)
    {
    cout << "positive image sample load error: " << i << " " << path << endl;
    system("pause");
    continue;
    }
    //hog特征提取
    //gpu::HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9); //貌似还有一些参数,重载了?
    //HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9);
    //HOGDescriptor hog;
    //vector<float> v_feature;
    image = image(Rect(16, 16, 64, 128));
    hog.compute(image, v_feature, cv::Size(8, 8));

    int featureVecSize = v_feature.size();
    //cout << "***************************lalala*****************************" << endl;
    //cout << featureVecSize;

    for (int j = 0; j<featureVecSize; j++)
    {
    CV_MAT_ELEM(*sampleFeaturesMat, float, positiveSampleCount + i, j) = v_feature[j]; //CV_MAT_ELEM什么意思
    }
    sampleLabelMat->data.fl[positiveSampleCount + i] = 0; //.fl[]是什么
    cout << "negative" << i + 1 << "is running..." << endl;
    }

    //**********************************************************************************************
    // Linear SVM训练
    //**********************************************************************************************
    //设置参数
    CvSVMParams params;
    params.svm_type = SVM::C_SVC;
    params.C = 0.01;
    params.kernel_type = SVM::LINEAR;
    //params.term_crit = TermCriteria(CV_TERMCRIT_ITER, (int)1e7, 1e-6);
    params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, FLT_EPSILON);


    //训练
    cout << "Starting training process" << endl;
    //CvSVM svm;
    MySVM svm;
    svm.train(sampleFeaturesMat, sampleLabelMat, Mat(), Mat(), params);
    cout << "Finished training process" << endl;
    //**********************************************************************************************
    // 结果保存
    //**********************************************************************************************
    //classifierSavePath文件读入
    //ifstream fin(classifierSavePath, ios::in);
    //if (!fin)
    //{
    // cout << "positivePath can not open the file!" << endl;
    // return -1;
    //}
    //svm.save(classifierSavePath);
    //cvReleaseMat(&sampleFeaturesMat);
    //cvReleaseMat(&sampleLabelMat);
    //cout << "has saved succeeded! " << endl;

    //**********************************************************************************************
    // 测试
    //**********************************************************************************************
    //test文件读入
    //ifstream fin(testPath, ios::in);
    //if (!fin)
    //{
    // cout << "can not open the file!" << endl;
    // return -1;
    //}
    char testImage[256] = ""; //初始化吗
    string s_testImage;
    for (int i = 0; i < testSampleCount; i++)
    {
    //图片名修改
    //hog特征提取
    memset(testImage, '', sizeof(testImage));
    sprintf(testImage, "%d.png", i + 1); //要改成.jpg吗
    s_testImage = testImage;
    path = testPath + s_testImage;

    Mat image = imread(path);
    if (image.data == NULL)
    {
    cout << "positive image sample load error: " << i << " " << path << endl;
    system("pause");
    continue;
    }
    //hog特征提取
    //gpu::HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9); //貌似还有一些参数,重载了?
    //HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9);
    //HOGDescriptor hog;
    //vector<float> v_feature;
    image = image(Rect(16, 16, 64, 128));
    hog.compute(image, v_feature, cv::Size(8, 8));

    int featureVecSize = v_feature.size();
    //cout << "***************************lalala*****************************" << endl;
    //cout << featureVecSize << endl;
    for (int j = 0; j<featureVecSize; j++)
    {
    //CV_MAT_ELEM(*testFeaturesMat, float, i, j) = v_feature[j]; //CV_MAT_ELEM什么意思
    CV_MAT_ELEM(*testFeaturesMat, float, 0, j) = v_feature[j];
    }
    float response = svm.predict(testFeaturesMat);
    //testLabelMat->data.fl[i] = response; //.fl[]是什么
    testLabelMat[i] = response;
    }
    float right = 0;
    for (int i = 0; i < testSampleCount; i++)
    {
    //if (testLabelMat->data.fl[i] == 1)
    if (testLabelMat[i] == 1)
    {
    right++;
    }
    }
    float radio = right / testSampleCount;
    cout << "the radio of the train is:" << radio << endl;


    /*************************************************************************************************
    线性SVM训练完成后得到的XML文件里面,有一个数组,叫做support vector,还有一个数组,叫做alpha,有一个浮点数,叫做rho;
    将alpha矩阵同support vector相乘,注意,alpha*supportVector,将得到一个列向量。之后,再该列向量的最后添加一个元素rho。
    如此,变得到了一个分类器,利用该分类器,直接替换opencv中行人检测默认的那个分类器(cv::HOGDescriptor::setSVMDetector()),
    就可以利用你的训练样本训练出来的分类器进行行人检测了。
    ***************************************************************************************************/
    int DescriptorDim = svm.get_var_count();//特征向量的维数,即HOG描述子的维数
    int supportVectorNum = svm.get_support_vector_count();//支持向量的个数
    cout << "支持向量个数:" << supportVectorNum << endl;

    Mat alphaMat = Mat::zeros(1, supportVectorNum, CV_32FC1);//alpha向量,长度等于支持向量个数
    Mat supportVectorMat = Mat::zeros(supportVectorNum, DescriptorDim, CV_32FC1);//支持向量矩阵
    Mat resultMat = Mat::zeros(1, DescriptorDim, CV_32FC1);//alpha向量乘以支持向量矩阵的结果

    //将支持向量的数据复制到supportVectorMat矩阵中
    for (int i = 0; i<supportVectorNum; i++)
    {
    const float * pSVData = svm.get_support_vector(i);//返回第i个支持向量的数据指针
    for (int j = 0; j<DescriptorDim; j++)
    {
    //cout<<pData[j]<<" ";
    supportVectorMat.at<float>(i, j) = pSVData[j];
    }
    }

    //将alpha向量的数据复制到alphaMat中
    double * pAlphaData = svm.get_alpha_vector();//返回SVM的决策函数中的alpha向量
    for (int i = 0; i<supportVectorNum; i++)
    {
    alphaMat.at<float>(0, i) = pAlphaData[i];
    }

    //计算-(alphaMat * supportVectorMat),结果放到resultMat中
    //gemm(alphaMat, supportVectorMat, -1, 0, 1, resultMat);//不知道为什么加负号?
    resultMat = -1 * alphaMat * supportVectorMat;

    //得到最终的setSVMDetector(const vector<float>& detector)参数中可用的检测子
    vector<float> myDetector;
    //将resultMat中的数据复制到数组myDetector中
    for (int i = 0; i<DescriptorDim; i++)
    {
    myDetector.push_back(resultMat.at<float>(0, i));
    }
    //最后添加偏移量rho,得到检测子
    myDetector.push_back(svm.get_rho());
    cout << "特征向量维数:" << svm.get_var_count()<< endl;
    cout << "检测子维数:" << myDetector.size() << endl;

    //设置HOGDescriptor的检测子



    //cout << "默认检测子维数" << hog.getDefaultPeopleDetector().size()<<endl;
    //hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
    cout<<"特征描述子:"<<hog.getDescriptorSize()<<endl;
    cout << "描述子维数:" << v_feature.size() << endl;
    hog.setSVMDetector(myDetector); //#############################


    cout << "debug:" << endl;
    //保存检测子参数到文件
    ofstream fout("HOGDetectorForOpenCV.txt");
    for (int i = 0; i<myDetector.size(); i++)
    {
    fout << myDetector[i] << endl;
    }


    /**************读入图片进行HOG行人检测******************/
    //Mat src = imread("00000.jpg");
    //Mat src = imread("2007_000423.jpg");
    Mat src = imread("D:\dataset\temp\1.jpg");
    vector<Rect> found, found_filtered;//矩形框数组
    cout << "进行多尺度HOG人体检测" << endl;
    hog.detectMultiScale(src, found, 0, Size(8, 8), Size(32, 32), 1.05, 2);//对图片进行多尺度行人检测
    cout << "找到的矩形框个数:" << found.size() << endl;

    //找出所有没有嵌套的矩形框r,并放入found_filtered中,如果有嵌套的话,则取外面最大的那个矩形框放入found_filtered中
    for (int i = 0; i < found.size(); i++)
    {
    Rect r = found[i];
    int j = 0;
    for (; j < found.size(); j++)
    if (j != i && (r & found[j]) == r)
    break;
    if (j == found.size())
    found_filtered.push_back(r);
    }

    //画矩形框,因为hog检测出的矩形框比实际人体框要稍微大些,所以这里需要做一些调整
    for (int i = 0; i<found_filtered.size(); i++)
    {
    Rect r = found_filtered[i];
    r.x += cvRound(r.width*0.1);
    r.width = cvRound(r.width*0.8);
    r.y += cvRound(r.height*0.07);
    r.height = cvRound(r.height*0.8);
    rectangle(src, r.tl(), r.br(), Scalar(0, 255, 0), 3);
    }

    imwrite("ImgProcessed.jpg", src);
    namedWindow("src", 0);
    imshow("src", src);
    waitKey();//注意:imshow之后必须加waitKey,否则无法显示图像
    #endif
    return 0;
    }

  • 相关阅读:
    Makefile 文件详细规则
    unrar命令
    Vector容器 和 iteration 迭代器
    python的with语句
    anaconda 使用总结
    vim 保存退出命令集
    Tensorflow实例集
    jupyter notebook 使用例子
    tensorflow 安装教程(最佳)
    Ext.NET 4.1.0 搭建页面布局
  • 原文地址:https://www.cnblogs.com/Wanggcong/p/4784994.html
Copyright © 2020-2023  润新知