由於在本項目中需要進行行人檢測,而直接使用hog+svm行人檢測速度太慢,無法檢測視頻流,在知乎上:http://cache.baiducontent.com/c?m=9d78d513d9d437ad4f9b96690c66c0171343f1132bd6a0020fa5843fe2732b415011e3ac27530772d7d20f1416df3a4b9ef72235775d2feddd8eca5ddcc88f356acd6223706bce1b49895eb8cb31749c7f8d19aef858a1e1ad6e8eaed7d7db5456c851&p=913fdc0585cc43b508e2947d0a07c6&newp=89769a4796934eaf5beac128554fbb231610db2151d0d701298ffe0cc4241a1a1a3aecbf27291104d6c67c600aae4f58e9f23c74340634f1f689df08d2ecce7e6f&user=baidu&fm=sc&query=%D0%D0%C8%CB%BC%EC%B2%E2+%D6%AA%BA%F5&qid=be576907001ba612&p1=1 看到張岱坤同學的回答,於是進行實現了下,檢測速率有了很大的提升。
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2\video\video.hpp>
#include<vector>
#include<opencv2\ml\ml.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include<fstream>
#include"HumanDetectionAlth.h"
int main(){
cv::VideoCapture cam("test.avi");
cv::BackgroundSubtractorMOG2 mog;
cv::Mat frame;
cv::Mat fore;
cv::Mat openElement(3,3,CV_8U,cv::Scalar(1));
cv::Mat dilateElement(7,7,CV_8U,cv::Scalar(1));
int sizeMin=200;
int sizeMax=10000;
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Rect>rects;
cv::Rect rect_;
std::vector<cv::Rect>persons;
#if 0
std::vector<float> myDetector;
std::ifstream detectorfile("HOGDetectorForOpenCV.txt");
float temp;
while(!detectorfile.eof()){
detectorfile>>temp;
myDetector.push_back(temp);
}
myDetector.pop_back();
detectorfile.close();
cv::HOGDescriptor myHOG;
myHOG.setSVMDetector(myDetector);
#endif
cv::HOGDescriptor myHOG;
loadDetector(myHOG);
std::vector<cv::Rect> found, found_filtered;
cv::Rect r;
while(1){
cam>>frame;
#if 0
mog(frame,fore,0.01);
cv::threshold(fore,fore,200,255,CV_THRESH_BINARY);
cv::morphologyEx(fore,fore,cv::MORPH_OPEN,openElement,cv::Point(-1,-1),2);
cv::dilate(fore,fore,dilateElement,cv::Point(-1,-1),7);
cv::findContours(fore,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
auto i=contours.begin();
while(i!=contours.end()){
if(i->size()<sizeMin||i->size()>sizeMax)
i=contours.erase(i);
else{
rect_=cv::boundingRect(cv::Mat(*i));
rects.push_back(rect_);
//cv::rectangle(frame,rect_,cv::Scalar(0,255,0),2);
cv::Mat ROI=frame(rect_);
found.clear(), found_filtered.clear();
myHOG.detectMultiScale(ROI, found, 0, cv::Size(8,8), cv::Size(35,35), 1.05, 2);
for(size_t i1=0; i1 < found.size(); i1++){
r = found[i1];
size_t j=0;
for(; j < found.size(); j++)
if(j != i1 && (r & found[j]) == r)
break;
if( j == found.size())
found_filtered.push_back(r);
}
for(int i2=0; i2<found_filtered.size(); i2++){
r = found_filtered[i2];
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(ROI, r, cv::Scalar(0,255,0), 2);
//found.clear(), found_filtered.clear();
}
++i;}
}
contours.clear();
rects.clear();
#endif
mog(frame,fore,0.01);
getROI(fore,rects,contours);
detectPersonInROIs(frame,myHOG,rects,persons,found,found_filtered);
for(auto &i :persons)
cv::rectangle(frame,i,cv::Scalar(0,255,0),2);
cv::imshow("src",frame);
//cv::imshow("res",fore);
if(cv::waitKey(1)=='c')
break;
}
cv::destroyAllWindows();
cam.release();
}
相關自定義的函數如下:
void loadDetector(cv::HOGDescriptor&descriptor){
descriptor.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());
}
void getROI(cv::Mat& foreground,std::vector<cv::Rect>&resROI,std::vector<std::vector<cv::Point>> &contours,double thresholdvalue,int openIteration,int dilateIteration,size_t minSize,size_t maxSize){
resROI.clear();
contours.clear();
cv::Mat openElement(3,3,CV_8U,cv::Scalar(1));
cv::Mat dilateElement(7,7,CV_8U,cv::Scalar(1));
cv::threshold(foreground,foreground,thresholdvalue,255,CV_THRESH_BINARY);
cv::morphologyEx(foreground,foreground,cv::MORPH_OPEN,openElement,cv::Point(-1,-1),openIteration);
cv::dilate(foreground,foreground,dilateElement,cv::Point(-1,-1),dilateIteration);
cv::findContours(foreground,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
auto i=contours.begin();
while(i!=contours.end()){
if(i->size()<minSize||i->size()>maxSize)
i=contours.erase(i);
else{
cv::Rect rect_=cv::boundingRect(cv::Mat(*i));
resROI.push_back(rect_);
++i;
}
}
}
void detectPersonInROIs(cv::Mat&src,cv::HOGDescriptor &myHOG,std::vector<cv::Rect>&ROIs,std::vector<cv::Rect>&persons,std::vector<cv::Rect>&found,std::vector<cv::Rect>&found_filtered){
persons.clear();
found.clear(), found_filtered.clear();
if(ROIs.size()==0)
return ;
cv::Rect r;
for(auto &rect_:ROIs){
cv::Mat ROI=src(rect_);
found.clear(), found_filtered.clear();
myHOG.detectMultiScale(ROI, found, 0, cv::Size(8,8), cv::Size(35,35), 1.05, 2);
for(size_t i1=0; i1 < found.size(); i1++){
r = found[i1];
size_t j=0;
for(; j < found.size(); j++)
if(j != i1 && (r & found[j]) == r)
break;
if( j == found.size())
found_filtered.push_back(r);
}
for(int i2=0; i2<found_filtered.size(); i2++){
r = found_filtered[i2];
r.x =r.x+cvRound(r.width*0.1)+rect_.x;
r.width = cvRound(r.width*0.8);
r.y = r.y+cvRound(r.height*0.07)+rect_.y;
r.height = cvRound(r.height*0.8);
persons.push_back(r);
}
}
}
雖然速率提上來了,但是,還是存在誤檢測的問題,而且當人運動速度比較慢的時候就檢測不到了,這需要進一步的研究。