Compare commits

..

No commits in common. "main" and "body_lengths" have entirely different histories.

6 changed files with 226 additions and 538 deletions

View File

@ -1,15 +1,57 @@
measurements: measurements:
- name: shoulder_length
landmarks:
- left_shoulder
- right_shoulder
- name: arm_length - name: arm_length
landmarks: landmarks:
- left_shoulder - 11
- left_elbow - 13
- left_wrist - 15
- name: leg_length - name: leg_length
landmarks: landmarks:
- left_hip - 23
- left_knee - 25
- left_ankle - 27
- name: shoulder_length
landmarks:
- 11
- 12
- name: neck_to_hip_length
landmarks:
- 11
- 23
#0 - nose
#1 - left eye (inner)
#2 - left eye
#3 - left eye (outer)
#4 - right eye (inner)
#5 - right eye
#6 - right eye (outer)
#7 - left ear
#8 - right ear
#9 - mouth (left)
#10 - mouth (right)
#11 - left shoulder
#12 - right shoulder
#13 - left elbow
#14 - right elbow
#15 - left wrist
#16 - right wrist
#17 - left pinky
#18 - right pinky
#19 - left index
#20 - right index
#21 - left thumb
#22 - right thumb
#23 - left hip
#24 - right hip
#25 - left knee
#26 - right knee
#27 - left ankle
#28 - right ankle
#29 - left heel
#30 - right heel
#31 - left foot index
#32 - right foot index

Binary file not shown.

View File

@ -1,289 +0,0 @@
const fs = require("fs");
const path = require("path");
const { ArgumentParser } = require("argparse");
const cv = require("@techstark/opencv-js");
const yaml = require("js-yaml");
const { Pose, POSE_LANDMARKS } = require("@mediapipe/pose");
const logging = console;
const warnings = console;
class Landmarker {
static resizedHeight = 256;
static resizedWidth = 256;
constructor() {
this.args = this.parseArgs();
this.measurements = this.loadLandmarks();
if (!this.args.frontImage) {
throw new Error("Front image needs to be passed");
}
if (!this.args.sideImage) {
throw new Error("Side image needs to be passed");
}
this.frontImage = cv.imread(this.args.frontImage);
this.sideImage = cv.imread(this.args.sideImage);
this.frontImageResized = cv.resize(
this.frontImage,
new cv.Size(Landmarker.resizedWidth, Landmarker.resizedHeight),
);
this.sideImageResized = cv.resize(
this.sideImage,
new cv.Size(Landmarker.resizedWidth, Landmarker.resizedHeight),
);
this.distances = {};
this.personHeight = this.args.personHeight;
this.pixelHeight = this.args.pixelHeight;
this.pose = new Pose({
locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/pose/${file}`;
},
});
this.landmarksIndices = [
POSE_LANDMARKS.LEFT_SHOULDER,
POSE_LANDMARKS.RIGHT_SHOULDER,
POSE_LANDMARKS.LEFT_ELBOW,
POSE_LANDMARKS.RIGHT_ELBOW,
POSE_LANDMARKS.LEFT_WRIST,
POSE_LANDMARKS.RIGHT_WRIST,
POSE_LANDMARKS.LEFT_HIP,
POSE_LANDMARKS.RIGHT_HIP,
POSE_LANDMARKS.LEFT_KNEE,
POSE_LANDMARKS.RIGHT_KNEE,
POSE_LANDMARKS.LEFT_ANKLE,
POSE_LANDMARKS.RIGHT_ANKLE,
];
}
loadLandmarks() {
const file = fs.readFileSync(this.args.yamlFile, "utf8");
const landmarksData = yaml.load(file);
const measurements = {};
for (const measurement of landmarksData.measurements) {
measurements[measurement.name] = measurement.landmarks;
}
return measurements;
}
parseArgs() {
const parser = new ArgumentParser({
description: "Process images and calculate measurements",
});
parser.add_argument("--front", {
dest: "frontImage",
required: true,
help: "Path to the front image",
});
parser.add_argument("--side", {
dest: "sideImage",
required: true,
help: "Path to the side image",
});
parser.add_argument("--poseDetectionConfidence", {
dest: "poseDetectionConfidence",
default: 0.5,
type: "float",
help: "Confidence score for pose detection",
});
parser.add_argument("--poseTrackingConfidence", {
dest: "poseTrackingConfidence",
default: 0.5,
type: "float",
help: "Confidence score for pose tracking",
});
parser.add_argument("--personHeight", {
dest: "personHeight",
required: true,
type: "int",
help: "Person height in cm",
});
parser.add_argument("--pixelHeight", {
dest: "pixelHeight",
type: "int",
help: "Pixel height of person",
});
parser.add_argument("--measurement", {
dest: "measurement",
nargs: "+",
type: "str",
help: "Type of measurement",
});
parser.add_argument("--yamlFile", {
dest: "yamlFile",
required: true,
help: "Path to the YAML file containing landmarks",
});
return parser.parse_args();
}
async run() {
await this.pose.initialize();
const { frontResults, sideResults } = await this.processImages();
this.getCenterTopPoint(sideResults);
const table = [];
if (this.args.measurement) {
for (const m of this.args.measurement) {
if (!this.measurements[m]) {
throw new Error("Incorrect input (input not present in config.yml)");
} else {
const distance = this.calculateDistanceBetweenLandmarks(
frontResults,
m,
);
table.push([m, distance]);
}
}
} else {
for (const m in this.measurements) {
const distance = this.calculateDistanceBetweenLandmarks(
frontResults,
m,
);
table.push([m, distance]);
}
}
console.table(table);
this.pose.close();
}
async processImages() {
const frontResults = await this.pose.estimatePoses(this.frontImageResized);
const sideResults = await this.pose.estimatePoses(this.sideImageResized);
this.sideImageKeypoints = this.sideImageResized.clone();
this.frontImageKeypoints = this.frontImageResized.clone();
if (frontResults[0].landmarks) {
this.drawLandmarks(
this.frontImageKeypoints,
frontResults[0].landmarks,
this.landmarksIndices,
);
}
if (sideResults[0].landmarks) {
this.drawLandmarks(
this.sideImageKeypoints,
sideResults[0].landmarks,
this.landmarksIndices,
);
}
return {
frontResults: frontResults[0],
sideResults: sideResults[0],
};
}
pixelToMetricRatio() {
const pixelToMetricRatio = this.personHeight / this.pixelHeight;
logging.debug("pixelToMetricRatio %s", pixelToMetricRatio);
return pixelToMetricRatio;
}
drawLandmarks(image, landmarks, indices) {
for (const idx of indices) {
const landmark = landmarks[idx];
const h = image.rows;
const w = image.cols;
const cx = Math.round(landmark.x * w);
const cy = Math.round(landmark.y * h);
this.circle(image, cx, cy);
}
}
circle(image, cx, cy) {
cv.circle(image, new cv.Point(cx, cy), 2, new cv.Scalar(255, 0, 0), -1);
}
calculateDistanceBetweenLandmarks(frontResults, measurementName) {
if (!frontResults.landmarks) {
return;
}
const landmarks = frontResults.landmarks;
const landmarkNames = this.measurements[measurementName];
let totalDistance = 0;
for (let i = 0; i < landmarkNames.length - 1; i++) {
const current = landmarks[landmarkNames[i]];
const next = landmarks[landmarkNames[i + 1]];
const pixelDistance = this.euclideanDistance(
current.x * Landmarker.resizedWidth,
current.y * Landmarker.resizedHeight,
next.x * Landmarker.resizedWidth,
next.y * Landmarker.resizedHeight,
);
const realDistance = pixelDistance * this.pixelToMetricRatio();
totalDistance += realDistance;
}
return totalDistance;
}
euclideanDistance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}
getCenterTopPoint(sideResults) {
const grayImage = cv.cvtColor(this.sideImageKeypoints, cv.COLOR_BGR2GRAY);
const blurredImage = cv.GaussianBlur(grayImage, new cv.Size(5, 5), 0);
const roi = blurredImage.roi(
new cv.Rect(
0,
0,
this.sideImageResized.cols,
Math.floor(this.sideImageResized.rows / 2),
),
);
this.edges = cv.Canny(roi, 50, 150);
const contours = this.edges.findContours(
cv.RETR_EXTERNAL,
cv.CHAIN_APPROX_SIMPLE,
);
let xt, yt;
this.topmostPoint = null;
for (const contour of contours) {
const [xt, yt] = contour.minEnclosingCircle();
if (this.topmostPoint === null || yt < this.topmostPoint[1]) {
this.topmostPoint = [xt, yt];
}
}
const { x, y } = sideResults.landmarks[POSE_LANDMARKS.NOSE];
const centerPoint = [
x * Landmarker.resizedWidth,
y * Landmarker.resizedHeight,
];
this.pixelHeight = Math.abs(centerPoint[1] - this.topmostPoint[1]);
cv.circle(
this.sideImageKeypoints,
new cv.Point(centerPoint[0], centerPoint[1]),
2,
new cv.Scalar(255, 0, 0),
-1,
);
cv.circle(
this.sideImageKeypoints,
new cv.Point(this.topmostPoint[0], this.topmostPoint[1]),
2,
new cv.Scalar(255, 0, 0),
-1,
);
}
}
const landmarker = new Landmarker();
landmarker.run().catch((error) => {
console.error(error);
});

View File

@ -1,126 +1,75 @@
import logging
import os
import warnings import warnings
import sys import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
from tabulate import tabulate from tabulate import tabulate
import math import math
import argparse import argparse
import cv2 import cv2
from mediapipe.python.solutions import ( from mediapipe.python.solutions import pose
pose, import logging
)
import yaml warnings.filterwarnings("ignore",
logging.basicConfig(level=logging.INFO) category=UserWarning,
warnings.filterwarnings( module="google.protobuf")
"ignore",
category=UserWarning, os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
module="google.protobuf",
)
LANDMARK_NAME_TO_INDEX = {
"nose": 0,
"left_eye_inner": 1,
"left_eye": 2,
"left_eye_outer": 3,
"right_eye_inner": 4,
"right_eye": 5,
"right_eye_outer": 6,
"left_ear": 7,
"right_ear": 8,
"mouth_left": 9,
"mouth_right": 10,
"left_shoulder": 11,
"right_shoulder": 12,
"left_elbow": 13,
"right_elbow": 14,
"left_wrist": 15,
"right_wrist": 16,
"left_pinky": 17,
"right_pinky": 18,
"left_index": 19,
"right_index": 20,
"left_thumb": 21,
"right_thumb": 22,
"left_hip": 23,
"right_hip": 24,
"left_knee": 25,
"right_knee": 26,
"left_ankle": 27,
"right_ankle": 28,
"left_heel": 29,
"right_heel": 30,
"left_foot_index": 31,
"right_foot_index": 32,
}
class Landmarker: class Landmarker:
resized_height = 256 resized_height = 256
resized_width = 256 resized_width = 300
def __init__(self) -> None: def __init__(self) -> None:
self.args = self.parse_args() args = self.parse_args()
self.measurements = self.load_landmarks() if args.front_image == None:
if self.args.front_image is None:
raise Exception("front image needs to be passed") raise Exception("front image needs to be passed")
if self.args.side_image is None: if args.side_image == None:
raise Exception("side image needs to be passed") raise Exception("side image needs to be passed")
self.front_image = cv2.imread(self.args.front_image) self.front_image = cv2.imread(args.front_image)
self.side_image = cv2.imread(self.args.side_image) self.side_image = cv2.imread(args.side_image)
self.front_image_resized = cv2.resize(self.front_image, (self.resized_height, self.resized_width)) self.front_image_resized = cv2.resize(
self.side_image_resized = cv2.resize(self.side_image, (self.resized_height, self.resized_width)) self.front_image, (self.resized_height, self.resized_width))
self.side_image_resized = cv2.resize(
self.side_image, (self.resized_height, self.resized_width))
self.distances = {} self.distances = {}
self.person_height = self.args.person_height self.person_height = args.person_height
self.pixel_height = self.args.pixel_height self.pixel_height = args.pixel_height
self.pose = pose.Pose( self.pose = pose.Pose(
static_image_mode=True, static_image_mode=True,
min_detection_confidence=self.args.pose_detection_confidence, min_detection_confidence=args.pose_detection_confidence,
min_tracking_confidence=self.args.pose_tracking_confidence, min_tracking_confidence=args.pose_tracking_confidence,
) )
self.landmarks_to_calculate = []
self.landmarks_indices = [ self.landmarks_indices = [
LANDMARK_NAME_TO_INDEX["left_shoulder"], pose.PoseLandmark.LEFT_SHOULDER.value,
LANDMARK_NAME_TO_INDEX["right_shoulder"], pose.PoseLandmark.RIGHT_SHOULDER.value,
LANDMARK_NAME_TO_INDEX["left_elbow"], pose.PoseLandmark.LEFT_ELBOW.value,
LANDMARK_NAME_TO_INDEX["right_elbow"], pose.PoseLandmark.RIGHT_ELBOW.value,
LANDMARK_NAME_TO_INDEX["left_wrist"], pose.PoseLandmark.LEFT_WRIST.value,
LANDMARK_NAME_TO_INDEX["right_wrist"], pose.PoseLandmark.RIGHT_WRIST.value,
LANDMARK_NAME_TO_INDEX["left_hip"], pose.PoseLandmark.LEFT_HIP.value,
LANDMARK_NAME_TO_INDEX["right_hip"], pose.PoseLandmark.RIGHT_HIP.value,
LANDMARK_NAME_TO_INDEX["left_knee"], pose.PoseLandmark.LEFT_KNEE.value,
LANDMARK_NAME_TO_INDEX["right_knee"], pose.PoseLandmark.RIGHT_KNEE.value,
LANDMARK_NAME_TO_INDEX["left_ankle"], pose.PoseLandmark.LEFT_ANKLE.value,
LANDMARK_NAME_TO_INDEX["right_ankle"], pose.PoseLandmark.RIGHT_ANKLE.value,
] ]
def load_landmarks(self):
with open(self.args.yaml_file, "r") as file:
landmarks_data = yaml.safe_load(file)
measurements = {}
for measurement in landmarks_data["measurements"]:
measurements[measurement["name"]] = [LANDMARK_NAME_TO_INDEX[l] for l in measurement["landmarks"]]
return measurements
def parse_args(self): def parse_args(self):
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument("--front",
"--front", dest="front_image",
dest="front_image", type=str,
type=str, help="Front image")
help="Front image", parser.add_argument("--side",
) dest="side_image",
parser.add_argument( type=str,
"--side", help="Side image")
dest="side_image",
type=str,
help="Side image",
)
parser.add_argument( parser.add_argument(
"--pose_detection_confidence", "--pose_detection_confidence",
dest="pose_detection_confidence", dest="pose_detection_confidence",
@ -137,74 +86,43 @@ class Landmarker:
) )
parser.add_argument( parser.add_argument(
"--person_height", "--person_height",
# default=153,
dest="person_height", dest="person_height",
type=int, type=int,
help="person height of person", help="person height of person",
) )
parser.add_argument( parser.add_argument(
"--pixel_height", "--pixel_height",
# default=216,
dest="pixel_height", dest="pixel_height",
type=int, type=int,
help="pixel height of person", help="pixel height of person",
) )
parser.add_argument(
"--measurement",
dest="measurement",
nargs="+",
type=str,
help="Type of measurement",
)
parser.add_argument(
"--yaml_file",
dest="yaml_file",
type=str,
help="Path to the YAML file containing landmarks",
)
return parser.parse_args() return parser.parse_args()
def run(self): def run(self):
front_results, _ = self.process_images()
logging.warning("person's height: %s", self.person_height)
logging.warning("person's pixel height: %s", self.pixel_height)
front_results, side_results = self.process_images()
self.get_center_top_point(front_results) self.get_center_top_point(front_results)
table = [] self.calculate_distance_betn_landmarks(front_results)
if self.args.measurement:
for m in self.args.measurement:
if m not in self.measurements:
raise Exception("Incorrect input (input not present in config.yml)")
else:
distance = self.calculate_distance_betn_landmarks(front_results, m)
table.append([m, distance])
else:
for m in self.measurements:
distance = self.calculate_distance_betn_landmarks(front_results, m)
table.append([m, distance])
output = tabulate( self.output()
table,
headers=[ self.display_images()
"measurement",
"Distance (cm)",
],
tablefmt="plain",
)
print(output)
self.pose.close() self.pose.close()
def process_images(self): def process_images(self):
front_results = self.pose.process( front_results = self.pose.process(
cv2.cvtColor( cv2.cvtColor(self.front_image_resized, cv2.COLOR_BGR2RGB))
self.front_image_resized,
cv2.COLOR_BGR2RGB,
)
)
side_results = self.pose.process( side_results = self.pose.process(
cv2.cvtColor( cv2.cvtColor(self.side_image_resized, cv2.COLOR_BGR2RGB))
self.side_image_resized,
cv2.COLOR_BGR2RGB,
)
)
self.side_image_keypoints = self.side_image_resized.copy() self.side_image_keypoints = self.side_image_resized.copy()
self.front_image_keypoints = self.front_image_resized.copy() self.front_image_keypoints = self.front_image_resized.copy()
@ -221,18 +139,12 @@ class Landmarker:
side_results.pose_landmarks, # type: ignore# type: ignore side_results.pose_landmarks, # type: ignore# type: ignore
self.landmarks_indices, self.landmarks_indices,
) )
return ( return front_results, side_results
front_results,
side_results,
)
def pixel_to_metric_ratio(self): def pixel_to_metric_ratio(self):
self.pixel_height = self.pixel_distance * 2 self.pixel_height = self.pixel_distance * 2
pixel_to_metric_ratio = self.person_height / self.pixel_height pixel_to_metric_ratio = self.person_height / self.pixel_height
logging.debug( logging.warning("pixel_to_metric_ratio %s", pixel_to_metric_ratio)
"pixel_to_metric_ratio %s",
pixel_to_metric_ratio,
)
return pixel_to_metric_ratio return pixel_to_metric_ratio
def draw_landmarks(self, image, landmarks, indices): def draw_landmarks(self, image, landmarks, indices):
@ -243,85 +155,118 @@ class Landmarker:
self.circle(image, cx, cy) self.circle(image, cx, cy)
def circle(self, image, cx, cy): def circle(self, image, cx, cy):
return cv2.circle( return cv2.circle(image, (cx, cy), 2, (255, 0, 0), -1)
image,
(cx, cy),
2,
(255, 0, 0),
-1,
)
def calculate_distance_betn_landmarks( def output(self):
self, table = []
front_results, for landmark, distance in self.distances.items():
measurement_name, table.append([landmark.replace("_", " "), distance])
): output = tabulate(table,
headers=["measurement", "value"],
tablefmt="grid")
print(output)
def calculate_distance_betn_landmarks(self, front_results, landmarks=[]):
if not front_results.pose_landmarks: if not front_results.pose_landmarks:
return return
landmarks = front_results.pose_landmarks.landmark landmarks = front_results.pose_landmarks.landmark
landmark_names = self.measurements[measurement_name] leg_landmarks = [
pose.PoseLandmark.LEFT_HIP,
pose.PoseLandmark.LEFT_KNEE,
pose.PoseLandmark.LEFT_ANKLE,
]
hand_landmarks = [
pose.PoseLandmark.LEFT_SHOULDER,
pose.PoseLandmark.LEFT_ELBOW,
pose.PoseLandmark.LEFT_WRIST,
]
self.landmarks_to_calculate = leg_landmarks + hand_landmarks
# self.landmarks_to_calculate = [
# pose.PoseLandmark.LEFT_SHOULDER,
# pose.PoseLandmark.LEFT_ELBOW,
# pose.PoseLandmark.LEFT_WRIST,
# ]
total_distance = 0 table = []
for idx in range(len(landmark_names) - 1): for idx, l in enumerate(self.landmarks_to_calculate):
_current = landmarks[landmark_names[idx]] if idx < len(self.landmarks_to_calculate) - 1:
_next = landmarks[landmark_names[idx + 1]] _current = landmarks[l.value]
pixel_distance = self.euclidean_distance( _nextl = self.landmarks_to_calculate[idx + 1]
_current.x * self.resized_width, _next = landmarks[_nextl.value]
_current.y * self.resized_height, pixel_distance = self.euclidean_distance(
_next.x * self.resized_width, _current.x * self.resized_width,
_next.y * self.resized_height, _current.y * self.resized_height,
) _next.x * self.resized_width,
real_distance = pixel_distance * self.pixel_to_metric_ratio() _next.y * self.resized_height)
total_distance += real_distance real_distance = pixel_distance * self.pixel_to_metric_ratio()
return total_distance table.append([l.name, _nextl.name, real_distance])
output = tabulate(
table,
headers=["Landmark 1", "Landmark 2", "Distance (cm)"],
tablefmt="grid")
print(output)
# for l in self.landmarks_to_calculate:
# real_distance = 0
# for idx, l in enumerate(self.landmarks_to_calculate):
# if idx < len(self.landmarks_to_calculate) - 1:
# _current = landmarks[l.value]
# _nextl = self.landmarks_to_calculate[idx + 1]
# _next = landmarks[_nextl.value]
# pixel_distance = self.euclidean_distance(
# _current.x * self.resized_width,
# _current.y * self.resized_height,
# _next.x * self.resized_width,
# _next.y * self.resized_height,
# )
# real_distance += pixel_distance * self.pixel_to_metric_ratio(
# )
# print(real_distance)
# self.distances[l.name] = real_distance
#
def euclidean_distance(self, x1, y1, x2, y2): def euclidean_distance(self, x1, y1, x2, y2):
distance = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) distance = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
return distance return distance
def destroy(self):
cv2.destroyAllWindows()
def display_images(self):
cv2.imshow("front_image_keypoints", self.front_image_keypoints)
cv2.imshow("side_image_keypoints", self.side_image_keypoints)
cv2.imshow("edges", self.edges)
cv2.waitKey(0)
def get_center_top_point(self, side_results): def get_center_top_point(self, side_results):
gray_image = cv2.cvtColor( gray_image = cv2.cvtColor(self.side_image_keypoints,
self.side_image_keypoints, cv2.COLOR_BGR2GRAY)
cv2.COLOR_BGR2GRAY,
)
blurred_image = cv2.GaussianBlur(gray_image, (5, 5), 0) blurred_image = cv2.GaussianBlur(gray_image, (5, 5), 0)
roi = blurred_image[ roi = blurred_image[0:int(self.side_image_resized.shape[0] / 2), :]
0 : int(self.side_image_resized.shape[0] / 2), self.edges = cv2.Canny(roi, 50, 150)
:, contours, _ = cv2.findContours(self.edges, cv2.RETR_EXTERNAL,
] cv2.CHAIN_APPROX_SIMPLE)
edges = cv2.Canny(roi, 50, 150)
contours, _ = cv2.findContours(
edges,
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE,
)
xt, yt = None, None xt, yt = None, None
topmost_point = None self.topmost_point = None
if contours: if contours:
largest_contour = max( largest_contour = max(contours, key=cv2.contourArea)
contours, self.topmost_point = tuple(
key=cv2.contourArea, largest_contour[largest_contour[:, :, 1].argmin()][0])
) xt, yt = self.topmost_point
topmost_point = tuple(largest_contour[largest_contour[:, :, 1].argmin()][0]) self.circle(self.side_image_keypoints, xt, yt)
xt, yt = topmost_point
cv2.circle(
self.side_image_keypoints,
(xt, yt),
2,
(255, 255, 0),
-1,
)
logging.warning("xt: %s", xt)
logging.warning("yt: %s", yt)
xc, yc = None, None xc, yc = None, None
landmarks = side_results.pose_landmarks.landmark landmarks = side_results.pose_landmarks.landmark
if side_results.pose_landmarks: if side_results.pose_landmarks:
left_hip = landmarks[LANDMARK_NAME_TO_INDEX["left_hip"]] left_hip = landmarks[pose.PoseLandmark.LEFT_HIP.value]
right_hip = landmarks[LANDMARK_NAME_TO_INDEX["right_hip"]] right_hip = landmarks[pose.PoseLandmark.RIGHT_HIP.value]
center_point = ( center_point = (
(left_hip.x + right_hip.x) / 2, (left_hip.x + right_hip.x) / 2,
(left_hip.y + right_hip.y) / 2, (left_hip.y + right_hip.y) / 2,
@ -331,26 +276,23 @@ class Landmarker:
int(center_point[1] * self.side_image_resized.shape[0]), int(center_point[1] * self.side_image_resized.shape[0]),
) )
xc, yc = center_point xc, yc = center_point
self.circle( logging.warning("xc: %s", xc)
self.side_image_keypoints, logging.warning("yc: %s", yc)
xc, self.circle(self.side_image_keypoints, xc, yc)
yc,
)
self.pixel_distance = self.euclidean_distance(xc, yc, xt, yt) self.pixel_distance = self.euclidean_distance(xc, yc, xt, yt)
logging.debug( logging.warning("top_center_pixel_distance: %s",
"top_center_pixel_distance: %s", self.pixel_distance)
self.pixel_distance,
)
self.pixel_height = self.pixel_distance * 2 self.pixel_height = self.pixel_distance * 2
logging.debug( logging.warning("pxl height: %s ", self.pixel_height)
"pixel height: %s ", self.distance = (self.euclidean_distance(xc, yc, xt, yt) *
self.pixel_height, self.pixel_to_metric_ratio())
)
self.distance = self.euclidean_distance(xc, yc, xt, yt) * self.pixel_to_metric_ratio()
return self.distance return self.distance
if __name__ == "__main__": l = Landmarker()
landmarker = Landmarker() try:
landmarker.run() l.run()
except:
print("error")
finally:
l.destroy()

View File

@ -1,3 +0,0 @@
[tool.black]
line-length = 120

View File

@ -1,4 +0,0 @@
mediapipe==0.10.13
tabulate==0.9.0
opencv-python-headless==4.10.0.84
pyyaml==6.0.1