#include #include #include using namespace cv; using namespace std; typedef struct face_landmark_node { int frame; int indice; float x; float y; struct face_landmark_node *next; } face_landmark_node; static void draw_point (Mat &img, Point2f fp, Scalar color) { circle (img, fp, 3, color, CV_FILLED, CV_AA, 0); } static void draw_delaunay (Mat &img, Subdiv2D &subdiv, Scalar delaunay_color) { vector triangleList; subdiv.getTriangleList(triangleList); vector pt(3); Size size = img.size(); Rect rect(0,0, size.width, size.height); for (size_t i = 0; i < triangleList.size(); i++) { Vec6f t = triangleList[i]; pt[0] = Point(cvRound(t[0]), cvRound(t[1])); pt[1] = Point(cvRound(t[2]), cvRound(t[3])); pt[2] = Point(cvRound(t[4]), cvRound(t[5])); // Draw rectangles completely inside the image. if (rect.contains(pt[0]) && rect.contains(pt[1]) && rect.contains(pt[2])) { line (img, pt[0], pt[1], delaunay_color, 1, CV_AA, 0); line (img, pt[1], pt[2], delaunay_color, 1, CV_AA, 0); line (img, pt[2], pt[0], delaunay_color, 1, CV_AA, 0); } } } static void run (face_landmark_node *face_landmark_list_head) { face_landmark_node *face_landmark_element; Scalar delaunay_color(255,0,0), points_color(0, 0, 255); // Note: delaunay_color and points_color are in BGR (BLUE, GREEN, RED) format Mat source_image; Size source_image_resolution; char input_filename[1280], output_filename[1280]; // 1024 bytes for path + 256 bytes for filename = 1280 bytes. memset (&input_filename, 0, sizeof(input_filename) - 1); memset (&output_filename, 0, sizeof(input_filename) - 1); strncpy (&input_filename[0], "rob.png", sizeof(input_filename) - 1); snprintf (&output_filename[0], sizeof(output_filename) - 1, "OUTPUT-%s", &input_filename[0]); if (input_filename[0] != '\0') { source_image = imread (&input_filename[0]); if (!source_image.empty()) { source_image_resolution = source_image.size(); Rect rect(0, 0, source_image_resolution.width, source_image_resolution.height); Subdiv2D subdiv(rect); face_landmark_element = face_landmark_list_head; while (face_landmark_element != NULL) { subdiv.insert(Point2f(face_landmark_element->x, face_landmark_element->y)); face_landmark_element = face_landmark_element->next; } draw_delaunay (source_image, subdiv, delaunay_color); face_landmark_element = face_landmark_list_head; while (face_landmark_element != NULL) { draw_point (source_image, Point2f(face_landmark_element->x, face_landmark_element->y), points_color); face_landmark_element = face_landmark_element->next; } imwrite (&output_filename[0], source_image); } } } face_landmark_node * add_face_landmark_element (face_landmark_node *face_landmark_list_head, int frame, int indice, float pixel_location_x, float pixel_location_y) { face_landmark_node *new_face_landmark_element, *face_landmark_element, *previous_face_landmark_element; new_face_landmark_element = (face_landmark_node *) malloc (sizeof (face_landmark_node)); if (new_face_landmark_element != NULL) { new_face_landmark_element->frame = frame; new_face_landmark_element->indice = indice; new_face_landmark_element->x = pixel_location_x; new_face_landmark_element->y = pixel_location_y; new_face_landmark_element->next = NULL; if (face_landmark_list_head != NULL) { face_landmark_element = face_landmark_list_head; while (face_landmark_element->next != NULL) { face_landmark_element = face_landmark_element->next; } face_landmark_element->next = new_face_landmark_element; } else { face_landmark_list_head = new_face_landmark_element; } } return face_landmark_list_head; } face_landmark_node * load_face_landmark_data (face_landmark_node *face_landmark_list_head) { face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 0, 124.0f, 594.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 1, 121.0f, 677.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 2, 127.0f, 756.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 3, 138.0f, 832.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 4, 208.0f, 951.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 5, 312.0f, 1032.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 6, 394.0f, 1048.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 7, 475.0f, 1031.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 8, 567.0f, 950.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 9, 624.0f, 847.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 10, 636.0f, 772.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 11, 639.0f, 685.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 12, 633.0f, 593.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 13, 509.0f, 350.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 14, 389.0f, 325.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 15, 267.0f, 353.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 16, 275.0f, 509.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 17, 221.0f, 506.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 18, 174.0f, 540.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 19, 222.0f, 540.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 20, 271.0f, 543.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 21, 324.0f, 542.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 22, 435.0f, 539.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 23, 488.0f, 504.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 24, 546.0f, 503.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 25, 591.0f, 543.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 26, 543.0f, 538.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 27, 492.0f, 540.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 28, 498.0f, 566.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 29, 258.0f, 568.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 30, 300.0f, 601.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 31, 278.0f, 587.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 32, 256.0f, 580.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 33, 235.0f, 585.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 34, 214.0f, 598.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 35, 235.0f, 608.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 36, 256.0f, 613.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 37, 278.0f, 609.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 38, 256.0f, 596.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 39, 498.0f, 593.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 40, 455.0f, 599.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 41, 477.0f, 583.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 42, 498.0f, 577.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 43, 520.0f, 583.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 44, 541.0f, 595.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 45, 520.0f, 605.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 46, 499.0f, 609.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 47, 477.0f, 606.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 48, 423.0f, 678.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 49, 381.0f, 679.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 50, 339.0f, 681.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 51, 333.0f, 758.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 52, 384.0f, 740.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 53, 435.0f, 754.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 54, 470.0f, 715.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 55, 460.0f, 753.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 56, 386.0f, 779.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 57, 307.0f, 758.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 58, 294.0f, 718.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 59, 263.0f, 834.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 60, 316.0f, 820.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 61, 361.0f, 818.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 62, 388.0f, 824.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 63, 413.0f, 816.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 64, 458.0f, 816.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 65, 511.0f, 825.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 66, 444.0f, 835.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 67, 388.0f, 843.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 68, 330.0f, 840.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 69, 329.0f, 845.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 70, 388.0f, 851.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 71, 444.0f, 842.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 72, 476.0f, 853.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 73, 434.0f, 868.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 74, 389.0f, 873.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 75, 342.0f, 872.0f); face_landmark_list_head = add_face_landmark_element (face_landmark_list_head, 1, 76, 300.0f, 860.0f); return face_landmark_list_head; } int main (int argc, char *argv[]) { face_landmark_node *face_landmark_list_head, *face_landmark_element; face_landmark_list_head = NULL; face_landmark_list_head = load_face_landmark_data (face_landmark_list_head); run (face_landmark_list_head); while (face_landmark_list_head != NULL) { face_landmark_element = face_landmark_list_head; face_landmark_list_head = face_landmark_list_head->next; free (face_landmark_element); face_landmark_element = NULL; } exit (0); }