📄 gestures.c~
字号:
}/** * * * Estimate the position of the user's torso and right-hand based on face dimensions * * */void body_dimensions(void){ int height; // NOTE: change the following anthropometrical assumptions // if required to fit your needs. They are product of some measures // I have read in Mexican books on anthropology and modified on-the-fly. // TODO: change this for a smarter approach, probably using silhouettes. // face width = height * 0.15; face width is 15% of the user's height height = (int)(face->width / 0.15); // torso width = 2.2 times the face width torso.width = (int)(face->width * 2.2); // torso height = 1.5 times the torso width torso.height = (int)(torso.width * 1.5); // from the center of the face (X-axis), rest half of the torso width torso.x = (int)((face->x + (face->width / 2)) - (torso.width / 2)); // shoulder height = y-component of the // face's upper corner plus 0.30 times the user's height torso.y = (int)(face->y + (height * 0.30)); // height of the right-hand, // y-component of the torso's upper corner plus // 0.90 times the torso height expected_hand_pos.y = (int)(torso.y + torso.height * 0.90); // x-component of the torso upper corner minus // 40% of the torso width expected_hand_pos.x = (int)(torso.x - (torso.width * 0.40)); // expected_hand_position = %15 of the torso width expected_hand_pos.width = (int)(torso.width * 0.5); // expected_hand_position = 1.5 times face height expected_hand_pos.height = (int)(face->height * 1.5); }/** * * * calculate the normalized color histogram of the estimated torso subregion * * */void get_torso_color(void){ cvSetImageROI( frame, cvRect( torso.x, torso.y, torso.width, torso.height)); IplImage* b_plane = cvCreateImage( cvGetSize(frame), 8, 1 ); IplImage* g_plane = cvCreateImage( cvGetSize(frame), 8, 1 ); IplImage* r_plane = cvCreateImage( cvGetSize(frame), 8, 1 ); IplImage* planes[] = { b_plane, g_plane, r_plane }; // BGR pixel order cvCvtPixToPlane( frame, b_plane, g_plane, r_plane, 0 ); cvCalcHist( planes, torso_hist, 0, 0 ); cvNormalizeHist( torso_hist, 1.0 ); cvResetImageROI( frame );}/** * * * Hand segmentation and tracking * * */void hand_tracking(void){ // variables used with Camshift algorithm CvBox2D track_box; CvConnectedComp track_comp; // update the position of the region of interest in which the tracking is focused update_roi_position(); // hand segmentation using Camshift cvSetImageROI(frame, roi); back_projection(); cvCamShift( backproject, cvRect(0, 0, roi.width, roi.height), cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ), &track_comp, &track_box ); // adjust the hand coordinates to the // original image coordinate system hand->x = frame->roi->xOffset + track_comp.rect.x; hand->y = frame->roi->yOffset + track_comp.rect.y; hand->width = track_comp.rect.width; hand->height = track_comp.rect.height; cvResetImageROI(frame); cvReleaseImage( &backproject );}/** * * * Update the position of the region of interest according to the hand position * * */void update_roi_position(void){ // change the value of the lenght variable to modify // the size of the ROI int xcenter, ycenter, lenght = 80; xcenter = (int)(hand->x + (hand->width / 2)); roi.x = (int)(xcenter - (lenght / 2)); ycenter = (int)(hand->y + (hand->height / 2)); roi.y = (int)(ycenter - (lenght / 2)); roi.width = roi.height = lenght; // Validate the image boundaries if (roi.x < 0){ roi.x = 0; } if (roi.y < 0){ roi.y = 0; } if (roi.x + roi.width >= frame->width) { roi.x = frame->width - roi.width; } if (roi.y + roi.height >= frame->height) { roi.y = frame->height - roi.height; }}/** * * * * * */void queue_observations(void){ static int save_flag = 0; static int step = 1; static int cont = 0; FILE *stream; // spatial criteria to start/stop queueing observations // i.e., it is assumed that a gesture sample begins and ends // with the hand at the same region (defined by the initial_hand_pos variable) if (!is_at_init_pos()) { // record observations every four images if (step == 1){ record_hand_position(); save_flag = 1; T = T + 1; } // end step == 1 step = step + 1; if (step == 4) { step = 1; } } else { // is_at_init_pos // if save_flag == 1, and the hand is at the initial position, // save the observation sequence to a file if (save_flag){ if ((stream = fopen(observations_filename, "at")) == NULL){ printf("Error: cannot create the observations file %s \n", observations_filename); } fprintf(stream, "T:%d\n", T); for (int i = 0; i < T; i++){ fprintf(stream, "(%d %d %d %d %d %d %d %d %d %d)", O[i].x_hu, O[i].y_hu, O[i].x_hl, O[i].y_hl, O[i].x_tu, O[i].y_tu, O[i].x_tl, O[i].y_tl, O[i].x_fc, O[i].y_fc); } fprintf(stream, "\n"); fclose(stream); fprintf(stdout, "%d gestures saved\n", ++cont); T = 0; save_flag = 0; step = 1; } // save_flag } // End is_at_init_pos }/** * * * Get the color of a pixel (x,y) of the original image * * */void get_pixel_color(int x, int y, unsigned char *color){ int offset = 0; if (x < 0) { x = 0; } if (x >= frame->width) { x = frame->width - 1; } if (y < 0) { y = 0; } if (y >= frame->height) { y = frame->height - 1; } // Clean memory memset(color, 0, 3); // (x,y) relative to the actual roi (if defined) if (frame->roi){ if (x >= frame->roi->width) { x = frame->roi->width - 1; } if (y >= frame->roi->height) { y = frame->roi->height - 1; } x += frame->roi->xOffset; y += frame->roi->yOffset; } offset += y * frame->widthStep; // Offset offset += frame->nChannels * x; // Assume BGR pixel order color[0] = (unsigned char)frame->imageData[offset++]; color[1] = (unsigned char)frame->imageData[offset++]; color[2] = (unsigned char)frame->imageData[offset];}/** * * Get a backprojection from the combined skin-color histogram * */void back_projection (void){ IplImage* channels[3]; backproject = cvCreateImage( cvGetSize(frame), 8, 1 ); IplImage* b_channel = cvCreateImage( cvGetSize(frame), 8, 1 ); IplImage* g_channel = cvCreateImage( cvGetSize(frame), 8, 1 ); IplImage* r_channel = cvCreateImage( cvGetSize(frame), 8, 1 ); cvCvtPixToPlane( frame, b_channel, g_channel, r_channel, 0 ); channels[0] = b_channel; channels[1] = g_channel; channels[2] = r_channel; cvCalcBackProject( &channels, backproject, combined_skin_hist ); cvShowImage( "backprojection", backproject ); cvReleaseImage( &b_channel ); cvReleaseImage( &g_channel ); cvReleaseImage( &r_channel );}/** * * Record posture information of the face, torso and right-hand * */void record_hand_position(void){ // face (x,y) center // I wish I had paid more attention to // my advisors suggestions and recorded for my experiments // the whole coordinates of the face rectangle... O[T].x_fc = (int)(face->x + (face->width / 2)); O[T].y_fc = (int)(face->y + (face->height / 2)); // torso rectangle // upper corner O[T].x_tu = torso.x; O[T].y_tu = torso.y; // lower corner O[T].x_tl = torso.x + torso.width; O[T].y_tl = torso.y + torso.height; // hand rectangle // upper corner O[T].x_hu = hand->x; O[T].y_hu = hand->y; // lower corner O[T].x_hl = hand->x + hand->width; O[T].y_hl = hand->y + hand->height; }/** * * Verify if the center of the right-hand is at the initial_hand_pos region * */int is_at_init_pos (void){ int xcenter = hand->x + (hand->width / 2); int ycenter = hand->y + (hand->height / 2); if ((initial_hand_pos.x < xcenter) && ((initial_hand_pos.x + initial_hand_pos.width) > xcenter) && (initial_hand_pos.y < ycenter) && ((initial_hand_pos.y + initial_hand_pos.height) > ycenter)) { return 1; } return 0; }/** * * draw hand, torso, and face subregions into the original image * */void draw(void){ if ( face ){ cvRectangle( frame, cvPoint(face->x, face->y), cvPoint(face->x + face->width, face->y + face->height), CV_RGB(0,255,0), 2, 8, 0 ); // comment this if you do not want the estimated torso and hand position to be displayed // /* cvRectangle(frame, cvPoint(expected_hand_pos.x, expected_hand_pos.y), cvPoint(expected_hand_pos.x + expected_hand_pos.width, expected_hand_pos.y + expected_hand_pos.height), CV_RGB(0,0,255), 2, 8, 0 ); cvRectangle( frame, cvPoint(torso.x, torso.y), cvPoint(torso.x + torso.width, torso.y + torso.height), CV_RGB(0,255,255), 2, 8, 0 ); // */ } if ( hand ){ cvRectangle( frame, cvPoint(roi.x, roi.y), cvPoint(roi.x + roi.width, roi.y + roi.height), CV_RGB(255,255,0), 2, 8, 0 ); cvRectangle( frame, cvPoint(hand->x, hand->y), cvPoint(hand->x + hand->width, hand->y + hand->height), CV_RGB(0,255,0), 2, 8, 0 ); // comment this if you do not want the initial hand position to be displayed // /* cvRectangle( frame, cvPoint(initial_hand_pos.x, initial_hand_pos.y), cvPoint(initial_hand_pos.x + initial_hand_pos.width, initial_hand_pos.y + initial_hand_pos.height), CV_RGB(255,0,0), 2, 8, 0 ); //*/ }}/** * * Get the command-line options * */void get_options ( int argc, char** argv, char* classifier ){ int c; int option_index = 0; int flag = 0; static struct option long_options[4] = { {"cascade", 1, 0, 'c'}, {"file", 1, 0, 'f'}, {"help", 1, 0, 'h'}, {0, 0, 0, 0} }; // Defaults sprintf(classifier, "./haarcascade/haarcascade_frontalface_alt.xml"); sprintf(observations_filename, "observations.obs"); fprintf(stdout, " This is part of the visual recongition of gestures project\n" " at SourceForge [http://visualgestures.sourceforge.net]\n\n" " Visual extraction of posture information Copyright (C) <2004,2008> Hector Hugo Aviles-Arriaga\n" " This program comes with ABSOLUTELY NO WARRANTY.\n" " This is free software, and you are welcome to redistribute it\n" " under the terms of the GNU General Public License as published by\n" " the Free Software Foundation, either version 3 of the License, or\n" " (at your option) any later version.\n"); while (1) { c = getopt_long (argc, argv, "c:f:h", long_options, &option_index); if (c == -1) break; switch (c) { case 'c': sprintf(classifier, optarg); flag += 1; break; case 'f': sprintf(observations_filename, optarg); flag += 1; break; case 'h': case '?': case ':': usage(argv[0]); } } if (flag < 2) { usage(argv[0]); }}/** * * program usage * */void usage(char * prog){ fprintf(stdout, "\nUsage: %s [ options ]" "\nOptions: \n -c, --cascade=\"<cascade_path>\"" "\n -f, --file filename.obs" "\n -h, --help\n", prog); exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -