1,原理

就是把一张张连续的静态视频进行检测后,写入videos中。

2,代码

//
// Created by MacBook Pro on 2019-06-10.
//


#include
#include
#include
#include
#include
#include
#include
#include

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

//定义HOGxml文件
#define SvmLisrFile "/Users/macbookpro/CLionProjects/pedestrian_detection/data/SVM_HOG_1.xml"
//定义读入图片的文件名
#define ImgListFile "/Users/macbookpro/CLionProjects/pedestrian_detection/img_dir/seq.txt"
//存储的视频路径以及视频名称
#define VideoFile "/Users/macbookpro/CLionProjects/pedestrian_detection/data/Seq8.avi"
//读入图片所在的路径
#define ImgFile "/Users/macbookpro/CLionProjects/pedestrian_detection/normalized_images/seq4/"

int main() {
Mat src;
string ImgName;//图片文件名
//ifstream fin("Seq4List.txt");//打开图片序列的文件列表
ifstream fin(ImgListFile);

namedWindow("ImageSeq", 0);

VideoWriter videoWriter;//视频写入器
videoWriter.open(VideoFile, CAP_OPENCV_MJPEG, 25, Size(1292, 964));//注意若图片尺寸与写入器的尺寸不同的话可能失败
if (!videoWriter.isOpened()) cout << "创建VideoWriter失败" << endl;

// HOGDescriptor people_detect_hog; //HOG特征检测器
// //采用默认的已经训练好了的SVM系数作为检测的模型
// people_detect_hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());

HOGDescriptor hog(Size(64,128),Size(16,16),Size(8,8),Size(8,8),9);
// int DescriptorDim;//HOG描述子的维数,由图片大小、检测窗口大小、块大小、细胞单元中直方图bin个数决定
Ptr<SVM> svm = SVM::create();// 创建分类器

svm = SVM::load(SvmLisrFile);

int svdim = svm ->getVarCount();//特征向量的维数,即HOG描述子的维数
//支持向量的个数
Mat svecsmat = svm ->getSupportVectors();//svecsmat元素的数据类型为float
int numofsv = svecsmat.rows;

// Mat alphamat = Mat::zeros(numofsv, svdim, CV_32F);//alphamat和svindex必须初始化,否则getDecisionFunction()函数会报错
Mat alphamat = Mat::zeros(numofsv, svdim, CV_32F);
Mat svindex = Mat::zeros(1, numofsv,CV_64F);
cout << "after initialize the value of alphamat is " << alphamat.size() << endl;

Mat Result;
double rho = svm ->getDecisionFunction(0, alphamat, svindex);

// cout << "the value of rho is " << rho << endl;
alphamat.convertTo(alphamat, CV_32F);//将alphamat元素的数据类型重新转成CV_32F
// cout << "the value of alphamat is " << alphamat << endl;
// cout << "the size of alphamat is " << alphamat.size() << endl;
// cout << "the size of svecsmat is " << svecsmat.size() << endl;

//计算-(alphaMat * supportVectorMat),结果放到resultMat中
Result = -1 * alphamat * svecsmat;//float

// cout << "the value of svdim is " << svdim << endl;

//得到最终的setSVMDetector(const vector& detector)参数中可用的检测子
vector<float> vec;
//将resultMat中的数据复制到数组vec中
for (int i = 0; i < svdim; ++i)
{
vec.push_back(Result.at<float>(0, i));
}
vec.push_back(rho);

HOGDescriptor hog_test;
hog_test.setSVMDetector(vec);


while (getline(fin, ImgName)) {
cout << "处理:" << ImgName << endl;
string fullName = ImgFile + ImgName;//加上路径名,"\\"表示转义字符"\"
src = imread(fullName);

vector<Rect> found, found_filtered; //矩形框数组
//对输入的图片进行多尺度行人检测,检测窗口移动步长为(8,8)
hog_test.detectMultiScale(src, found, 0, Size(8, 8), Size(32, 32), 1.05, 2);
//找出所有没有嵌套的矩形框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);
}

videoWriter << src;//写入一帧到文件

imshow("ImageSeq", src);
waitKey(50);//注意:imshow之后必须有waitKey(),否则无法显示图像
}

videoWriter.release();
//system("pause");
return 0;
}

3,效果

HOG+SVM静态图像检测并制作视频_#include

HOG+SVM静态图像检测并制作视频_#define_02

4、视频源文件

附带检测图片以及SVM的xml文件

链接: https://pan.baidu.com/s/1RTi_j-5omh8VCojZwrbAgw  密码: ppuf