static void bow_gesture (Salut *self, SkeltrackJointList list) { SkeltrackJoint *head, *previous_head; if (list == NULL) return; head = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_HEAD); if (head == NULL) return; previous_head = self->gesture_list[self->gesture_index]; if (previous_head != NULL) { gfloat x, y, z, d; gint dist = 100; gint min_head_distance = 150; x = previous_head->x - head->x; y = previous_head->y - head->y; z = previous_head->z - head->z; d = sqrt (x * x + y * y + z * z); if (d >= dist) { if (ABS (previous_head->z - head->z) > 100 && previous_head->z > head->z && previous_head->screen_y < head->screen_y) { self->gesture_list[++self->gesture_index] = skeltrack_joint_copy (head); } else if (sqrt (x * x + y * y) > min_head_distance || (ABS (previous_head->z - head->z) > min_head_distance && previous_head->z < head->z)) { skeltrack_joint_free (self->gesture_list[self->gesture_index]); self->gesture_list[self->gesture_index] = NULL; } if (self->gesture_index == 2) { if (self->callback != NULL) self->callback(self->callback_data); for (; self->gesture_index >= 0; self->gesture_index--) { skeltrack_joint_free (self->gesture_list[self->gesture_index]); self->gesture_list[self->gesture_index] = NULL; } self->gesture_index = 0; } } } else { self->gesture_list[self->gesture_index] = skeltrack_joint_copy (head); } }
static gboolean on_skeleton_draw (ClutterCanvas *canvas, cairo_t *cairo, gint width, gint height, gpointer user_data) { ClutterColor *color; SkeltrackJoint *head, *left_hand, *right_hand, *left_shoulder, *right_shoulder, *left_elbow, *right_elbow; if (list == NULL) return FALSE; head = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_HEAD); left_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_HAND); right_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_HAND); left_shoulder = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_SHOULDER); right_shoulder = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_SHOULDER); left_elbow = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_ELBOW); right_elbow = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_ELBOW); /* Paint it white */ color = clutter_color_new (255, 255, 255, 255); clutter_cairo_set_source_color (cairo, color); cairo_rectangle (cairo, 0, 0, width, height); cairo_fill (cairo); clutter_color_free (color); paint_joint (cairo, head, 50, "#FFF800"); connect_joints (cairo, left_shoulder, right_shoulder, "#afafaf"); connect_joints (cairo, left_shoulder, left_elbow, "#afafaf"); connect_joints (cairo, right_shoulder, right_elbow, "#afafaf"); connect_joints (cairo, right_hand, right_elbow, "#afafaf"); connect_joints (cairo, left_hand, left_elbow, "#afafaf"); paint_joint (cairo, left_hand, 30, "#C2FF00"); paint_joint (cairo, right_hand, 30, "#00FAFF"); skeltrack_joint_list_free (list); list = NULL; return FALSE; }
static void on_texture_draw (ClutterCairoTexture *texture, cairo_t *cairo, gpointer user_data) { guint width, height; ClutterColor *color; SkeltrackJoint *head, *left_hand, *right_hand, *left_shoulder, *right_shoulder, *left_elbow, *right_elbow; if (list == NULL) return; head = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_HEAD); left_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_HAND); right_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_HAND); left_shoulder = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_SHOULDER); right_shoulder = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_SHOULDER); left_elbow = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_ELBOW); right_elbow = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_ELBOW); /* Paint it white */ clutter_cairo_texture_clear (texture); clutter_cairo_texture_get_surface_size (texture, &width, &height); color = clutter_color_new (255, 255, 255, 255); clutter_cairo_set_source_color (cairo, color); cairo_rectangle (cairo, 0, 0, width, height); cairo_fill (cairo); clutter_color_free (color); paint_joint (cairo, head, 50, "#FFF800"); connect_joints (cairo, left_shoulder, right_shoulder, "#afafaf"); connect_joints (cairo, left_shoulder, left_elbow, "#afafaf"); connect_joints (cairo, right_shoulder, right_elbow, "#afafaf"); connect_joints (cairo, right_hand, right_elbow, "#afafaf"); connect_joints (cairo, left_hand, left_elbow, "#afafaf"); paint_joint (cairo, left_hand, 30, "#C2FF00"); paint_joint (cairo, right_hand, 30, "#00FAFF"); skeltrack_joint_list_free (list); list = NULL; }
static gboolean hands_are_praying (guint16* depth, guint width, guint height, SkeltrackJointList list) { guint x, y, z; SkeltrackJoint *head, *left_elbow, *left_shoulder, *right_shoulder, *right_elbow; CvSeq *defects = NULL; if (list == NULL) return FALSE; head = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_HEAD); right_elbow = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_ELBOW); left_elbow = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_ELBOW); right_shoulder = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_SHOULDER); left_shoulder = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_SHOULDER); if (head == NULL || right_elbow == NULL || left_elbow == NULL || ((right_elbow->y < right_shoulder->y) && (left_elbow->y < left_shoulder->y))) return FALSE; x = head->screen_x; y = right_elbow->screen_y; z = ((gfloat) (right_shoulder->z + left_shoulder->z)) / 2.0 - 300; defects = get_defects (depth, width, height, x, y, z); if (defects) { guint i, sum; sum = 0; for (i = 0; i < defects->total; i++) { gfloat orientation; CvConvexityDefect *defect = CV_GET_SEQ_ELEM (CvConvexityDefect, defects, i); orientation = get_orientation_angle (defect->start, defect->depth_point, defect->end); orientation = ((gint) (orientation / M_PI * 180.0)) % 360; if (defect->depth > 20.0 && orientation < 180 && orientation > 0 && ABS (orientation - 90) > 25) { gfloat x1, x2, sig_x1, sig_x2; x1 = defect->start->x - defect->depth_point->x; x2 = defect->end->x - defect->depth_point->x; sig_x1 = x1 / ABS (x1); sig_x2 = x2 / ABS (x2); if (sig_x1 != sig_x2 || (x1 == 0 || x2 == 0)) { continue; } cvSeqRemove(defects, i); i--; } else { cvSeqRemove(defects, i); i--; } } if (defects->total > 1) { for (i = 1; i < defects->total; i++) { gfloat dist_hand1, dist_hand2, dist_depth_points; CvConvexityDefect *defect1, *defect2; CvPoint *defect1_top_point, *defect2_top_point; defect1 = CV_GET_SEQ_ELEM (CvConvexityDefect, defects, i); defect2 = CV_GET_SEQ_ELEM (CvConvexityDefect, defects, i - 1); if (defect1->end->y < defect1->start->y) defect1_top_point = defect1->end; else defect1_top_point = defect1->start; if (defect2->end->y < defect2->start->y) defect2_top_point = defect2->end; else defect2_top_point = defect2->start; dist_hand1 = get_points_distance (defect1_top_point, defect1->depth_point); dist_hand2 = get_points_distance (defect2_top_point, defect2->depth_point); dist_depth_points = get_points_distance (defect1->depth_point, defect2->depth_point); if (dist_depth_points < MAX (dist_hand1, dist_hand2)) sum++; } } if (sum > 0) return TRUE; } return FALSE; }
static CvSeq * get_finger_defects (guint16* depth, guint width, guint height, SkeltrackJointList list) { CvSeq *defects = NULL; SkeltrackJoint *head, *left_hand, *right_hand, *hand = NULL; if (list == NULL) return NULL; head = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_HEAD); right_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_HAND); left_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_HAND); if (head == NULL || (left_hand == NULL && right_hand == NULL)) return NULL; if (right_hand == NULL) hand = left_hand; else if (left_hand == NULL) hand = right_hand; else { if (right_hand->z < left_hand->z && ABS (right_hand->z - head->z) > 150) { hand = right_hand; } else if (left_hand->z < right_hand->z && ABS (left_hand->z - head->z) > 150) { hand = left_hand; } } if (hand == NULL) return NULL; defects = get_defects (depth, width, height, hand->screen_x, hand->screen_y, hand->z); if (defects) { gfloat angle; guint i; for (i = 0; i < defects->total; i++) { CvConvexityDefect *defect = CV_GET_SEQ_ELEM (CvConvexityDefect, defects, i); angle = get_angle (defect->start, defect->depth_point, defect->end); if (angle > M_PI_2) { cvSeqRemove(defects, i); i--; } } return defects; } return NULL; }
static void hello_gesture (Salut *self, SkeltrackJointList list) { SkeltrackJoint *head, *left_hand, *left_elbow, *right_hand, *right_elbow, *elbow = NULL, *hand = NULL; if (list == NULL) return; head = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_HEAD); right_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_HAND); left_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_HAND); right_elbow = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_ELBOW); left_elbow = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_ELBOW); if (head == NULL || (left_hand == NULL && right_hand == NULL)) return; if (can_wave_hello (right_hand, right_elbow)) { hand = right_hand; elbow = right_elbow; } else if (can_wave_hello (left_hand, left_elbow)) { hand = left_hand; elbow = left_elbow; } if (hand && elbow) { SkeltrackJoint *previous_hand = self->gesture_list[self->gesture_index]; SkeltrackJoint *previous_elbow = self->gesture_list[self->gesture_index + 1]; /* Check if the hand has moved beyond the X coord of the elbow (in comparison with the previous values) */ if (previous_hand == NULL || get_sign (previous_hand->x - previous_elbow->x) != get_sign (hand->x - elbow->x)) { if (previous_hand) self->gesture_index += 2; self->gesture_list[self->gesture_index] = skeltrack_joint_copy (hand); self->gesture_list[self->gesture_index + 1] = skeltrack_joint_copy (elbow); } if (self->gesture_index == 8) { gint i; for (i = 0; i <= self->gesture_index; i += 2) { hand = self->gesture_list[i]; elbow = self->gesture_list[i + 1]; skeltrack_joint_free (hand); skeltrack_joint_free (elbow); self->gesture_list[i] = NULL; self->gesture_list[i + 1] = NULL; } if (self->callback != NULL) self->callback (self->callback); self->gesture_index = 0; } } else if (self->gesture_list[self->gesture_index]) { skeltrack_joint_free(self->gesture_list[self->gesture_index + 1]); self->gesture_list[self->gesture_index + 1] = NULL; skeltrack_joint_free(self->gesture_list[self->gesture_index]); self->gesture_list[self->gesture_index] = NULL; if (self->gesture_index > 0) self->gesture_index-=2; } }
static void curtsy_gesture (Salut *self, SkeltrackJointList list) { SkeltrackJoint *head, *left_hand, *right_hand, *left_elbow, *right_elbow; if (list == NULL) return; head = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_HEAD); right_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_HAND); left_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_HAND); right_elbow = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_ELBOW); left_elbow = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_ELBOW); if (head == NULL || (left_hand == NULL || right_hand == NULL)) return; if (head) { /* Check if arms are in the correct pose, if not, clean the list so far */ if (USE_HANDS_IN_CURTSY && (right_hand->y < head->y || left_hand->y < head->y || right_hand->x > right_elbow->x || left_hand->x < left_elbow->x)) { for (; self->gesture_index >= 0; self->gesture_index--) { skeltrack_joint_free (self->gesture_list[self->gesture_index]); self->gesture_list[self->gesture_index] = NULL; } self->gesture_index = 0; } SkeltrackJoint *previous_head = self->gesture_list[self->gesture_index]; if (previous_head != NULL) { gfloat x, y, z, d; gint dist_with_previous_head = 150; gint min_head_movement = 100; x = previous_head->x - head->x; y = previous_head->y - head->y; z = previous_head->z - head->z; d = sqrt (x * x + y * y + z * z); if (d >= dist_with_previous_head) { if (ABS (previous_head->z - head->z) < min_head_movement && ABS (previous_head->y - head->y) > min_head_movement) { /* Movement reached lowest point (initial movement) */ if (self->gesture_index == 0 && previous_head->y < head->y) { self->gesture_list[++self->gesture_index] = skeltrack_joint_copy (head); } /* Movement went back up (final movement) */ else if (self->gesture_index == 1 && previous_head->y > head->y) { self->gesture_list[++self->gesture_index] = skeltrack_joint_copy (head); } } else { skeltrack_joint_free (self->gesture_list[self->gesture_index]); self->gesture_list[self->gesture_index] = NULL; if (self->gesture_index > 0) self->gesture_index--; self->gesture_list[self->gesture_index] = skeltrack_joint_copy (head); } if (self->gesture_index == 2) { if (self->callback != NULL) self->callback(self->callback_data); for (; self->gesture_index >= 0; self->gesture_index--) { skeltrack_joint_free (self->gesture_list[self->gesture_index]); self->gesture_list[self->gesture_index] = NULL; } self->gesture_index = 0; } } } else { self->gesture_list[self->gesture_index] = skeltrack_joint_copy (head); } } }
static void kiss_gesture (Salut *self, SkeltrackJointList list) { SkeltrackJoint *head, *left_hand, *right_hand, *hand, *previous_hand; if (list == NULL) return; head = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_HEAD); right_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_RIGHT_HAND); left_hand = skeltrack_joint_list_get_joint (list, SKELTRACK_JOINT_ID_LEFT_HAND); hand = NULL; previous_hand = NULL; if (head == NULL || (left_hand == NULL && right_hand == NULL)) { for (self->gesture_index = 3; self->gesture_index >= 0; self->gesture_index--) { skeltrack_joint_free (self->gesture_list[self->gesture_index]); self->gesture_list[self->gesture_index] = NULL; } self->gesture_index = 0; return; } if (right_hand == NULL) hand = left_hand; else if (left_hand == NULL) hand = right_hand; if (hand == NULL) { if (left_hand->y < right_hand->y) hand = left_hand; else hand = right_hand; } previous_hand = NULL; if (self->gesture_index == 0) { if (self->gesture_list[0] == NULL) { self->gesture_list[0] = skeltrack_joint_copy (head); } } else { previous_hand = self->gesture_list[self->gesture_index]; } if (previous_hand == NULL) { guint initial_hand_head_max_dist = 400; if (get_distance (hand, head) < initial_hand_head_max_dist) { self->gesture_index++; self->gesture_list[self->gesture_index] = skeltrack_joint_copy (hand); } } else { guint dist = get_distance (previous_hand, hand); if ((dist > 200) && (dist < 500) && (hand->z < previous_hand->z)) { self->gesture_list[++self->gesture_index] = skeltrack_joint_copy (hand); } } if (self->gesture_index == -1 || self->gesture_index == 3) { if (self->gesture_index == 3 && self->callback) self->callback (self->callback_data); for (self->gesture_index = 3; self->gesture_index >= 0; self->gesture_index--) { skeltrack_joint_free (self->gesture_list[self->gesture_index]); self->gesture_list[self->gesture_index] = NULL; } self->gesture_index = 0; } }