From af25c7b632b843699b73b5aa04a58c16a6800e48 Mon Sep 17 00:00:00 2001 From: Kwang Son Date: Fri, 16 Apr 2021 15:07:38 +0900 Subject: [PATCH] Add SquatDetector class - get squat similarity score Signed-off-by: Kwang Son --- Fitness/Services/SquatDetector.cs | 65 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Fitness/Services/SquatDetector.cs diff --git a/Fitness/Services/SquatDetector.cs b/Fitness/Services/SquatDetector.cs new file mode 100644 index 0000000..7f0efdb --- /dev/null +++ b/Fitness/Services/SquatDetector.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Numerics; +using Tizen.Multimedia; + +namespace Fitness.Services +{ + /// + /// SquatDetector + /// + public static class SquatDetector + { + // SquatLowerBody is calculation result of squat picture from + // https://review.tizen.org/gerrit/gitweb?p=test/tct/native/api.git;a=blob;f=src/utc/capi-media-vision/res/inference/images/poseLandmark.jpg;h=4bead08b8dc3687f228b5ab885e7136b26331cfb;hb=refs/heads/tizen + // Each below vector is derived from two points respectively, + // 0. RightUpLeg => RightLowLeg, + // 1. RightLowLeg => RightFoot, + // 2. LeftUpLeg => LeftLowLeg, + // 4. LeftLowLeg => LeftFoot + private static readonly List SquatLowerBody = new List(new[] + { + new Vector2(0.6666667F, -0.33333334F), + new Vector2(0F, -1F), + new Vector2(-0.6666667F, -0.33333334F), + new Vector2(0F, -1F), + }); + + /// + /// Return Average of lower body Cosine Similarity between input user pose and ground truth pose + /// + /// user body detection result + /// Float score value. (-1.0 ~ 1.0) + public static float Similarity(List userBody) + { + if (userBody.Count != System.Enum.GetNames(typeof(PoseDetector.BodyPart)).Length) + { + throw new System.ArgumentException("Must have all points which represent user body", "userBody"); + } + + List userSquat = new List(new[] + { + L1UnitVectorize(userBody[(int)PoseDetector.BodyPart.RightUpLeg], userBody[(int)PoseDetector.BodyPart.RightLowLeg]), + L1UnitVectorize(userBody[(int)PoseDetector.BodyPart.RightLowLeg], userBody[(int)PoseDetector.BodyPart.RightFoot]), + L1UnitVectorize(userBody[(int)PoseDetector.BodyPart.LeftUpLeg], userBody[(int)PoseDetector.BodyPart.LeftLowLeg]), + L1UnitVectorize(userBody[(int)PoseDetector.BodyPart.LeftLowLeg], userBody[(int)PoseDetector.BodyPart.LeftFoot]), + }); + + float score = 0F; + + for (int i = 0; i < SquatLowerBody.Count; i++) + { + score += Vector2.Dot(SquatLowerBody[i], userSquat[i]) / SquatLowerBody[i].Length() / userSquat[i].Length(); + } + + return score / SquatLowerBody.Count; + } + + private static Vector2 L1UnitVectorize(Point from, Point to) + { + int vx = from.X - to.X; + int vy = from.Y - to.Y; + float parent = System.Math.Abs(vx) + System.Math.Abs(vy); + return new Vector2(vx / parent, vy / parent); + } + } +} -- 2.7.4