# 【计算机视觉】步态能量图GEI

## 步态剪影

// get resized gait image
if(!walk_img.empty()){
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
Mat walk_img_tmp;
threshold(walk_img,walk_img_tmp,128,255,THRESH_BINARY);
findContours( walk_img_tmp, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
vector<vector<Point> > contours_poly( contours.size() );
vector<Rect> boundRect( contours.size() );
int maxRectHeight=0;
int maxRectId=0;
if(contours.size()>0){
for( int i = 0; i< contours.size(); i++ ){
//drawContours( walk_img, contours, i, Scalar(255,255,255), 2, 8, hierarchy, 0, Point() );
//Approximates a polygonal curve(s) with the specified precision.
approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
//Calculates the up-right bounding rectangle of a point set.
boundRect[i] = boundingRect( Mat(contours_poly[i]) );
if(boundRect[i].height>maxRectHeight){
maxRectHeight = boundRect[i].height;
maxRectId = i;
}
}
//rectangle( walk_img, boundRect[maxRectId].tl(), boundRect[maxRectId].br(), Scalar(255,255,255), 2, 8, 0 );
double aspect_ratio=(double)boundRect[maxRectId].height/boundRect[maxRectId].width;
double base_aspect_ratio=(double)gei_height/gei_width;
aspect_ratios.push_back(aspect_ratio);
if(aspect_ratio>=base_aspect_ratio){
Mat gait_roi=walk_img(boundRect[maxRectId]);
Mat gait_roi_tmp;
double resize_scale=double(gei_height)/gait_roi.rows;
resize(gait_roi,gait_roi_tmp,Size(),resize_scale,resize_scale);
Mat gait_img=Mat::zeros(gei_height,gei_width,CV_8UC1);
for(int i=0;i<gei_height;i++){
uchar* p_tmp=gait_roi_tmp.ptr<uchar>(i);
uchar* p=gait_img.ptr<uchar>(i);
for(int j=(gei_width-gait_roi_tmp.cols)/2,k=0;k<gait_roi_tmp.cols;k++,j++){
p[j]=p_tmp[k];
}
}
gait_imgs.push_back(gait_img);
}
else{
Mat gait_roi=walk_img(boundRect[maxRectId]);
Mat gait_roi_tmp;
double resize_scale=double(gei_width)/gait_roi.cols;
resize(gait_roi,gait_roi_tmp,Size(),resize_scale,resize_scale);
Mat gait_img=Mat::zeros(gei_height,gei_width,CV_8UC1);
int i=(gei_height-gait_roi_tmp.rows)/2;
for(int k=0;k<gait_roi_tmp.rows;k++,i++){
uchar* p_tmp=gait_roi_tmp.ptr<uchar>(k);
uchar* p=gait_img.ptr<uchar>(i);
for(int j=0;j<gei_width;j++){
p[j]=p_tmp[j];
}
}
gait_imgs.push_back(gait_img);
}
}

## 步态能量图GEI

if(aspect_ratios.size()<4)
break;
// get gait feature: gait energy image
vector<int> max_ids;
for(int i=2;i<aspect_ratios.size()-2;i++){
if((aspect_ratios[i]>aspect_ratios[i-1])&&(aspect_ratios[i]>aspect_ratios[i-2])
&&(aspect_ratios[i]>aspect_ratios[i+1])&&(aspect_ratios[i]>aspect_ratios[i+2]))
max_ids.push_back(i);
}
// for all gait cycles
for(int cycle_id=1;cycle_id<max_ids.size();cycle_id++){
int gait_start_id = max_ids[cycle_id-1];
int gait_end_id = max_ids[cycle_id]-1;
Mat gait_energy_img=Mat::zeros(gei_height,gei_width, CV_32F);
if(gait_end_id-gait_start_id>=6 && gait_end_id-gait_start_id<30){
for(int g=gait_start_id;g<=gait_end_id;g++){
Mat gait=gait_imgs[g];
Mat gait_tmp;
gait.convertTo(gait_tmp,CV_32F);
gait_energy_img = gait_energy_img+gait_tmp;
#ifdef GAIT_DEBUG
char tmp[50];
itoa(g,tmp,10);
imshow(tmp,gait);
#endif
}
//waitKey(10000);
gait_energy_img = gait_energy_img/(float)(gait_end_id-gait_start_id+1);
for(int r=0;r<gait_energy_img.rows;r++){
float* p=gait_energy_img.ptr<float>(r);
for(int c=0;c<gait_energy_img.cols;c++)
feature_out<<p[c]<<" ";
}
feature_out<<endl;
label_out<<people_id_iter<<" "<<walk_condition_iter_iter<<endl;
cout<<"gait feature cycle #"<<cycle_id-1<<endl;
#ifdef GAIT_DEBUG
Mat gait_enery_img_show;
gait_energy_img.convertTo(gait_enery_img_show,CV_8UC1);
imshow("GEI",gait_enery_img_show);
waitKey(10000);
#endif
}
}
}