First training
This commit is contained in:
@@ -27,6 +27,8 @@ class KeypointExtractor:
|
||||
|
||||
def extract_keypoints_from_video(self,
|
||||
video: str,
|
||||
normalize: bool = False,
|
||||
draw: bool = False,
|
||||
) -> pd.DataFrame:
|
||||
"""extract_keypoints_from_video this function extracts keypoints from a video and stores them in a dataframe
|
||||
|
||||
@@ -35,19 +37,24 @@ class KeypointExtractor:
|
||||
:return: dataframe with keypoints
|
||||
:rtype: pd.DataFrame
|
||||
"""
|
||||
# check if video exists
|
||||
if not os.path.exists(self.video_folder + video):
|
||||
logging.error("Video does not exist at path: " + self.video_folder + video)
|
||||
return None
|
||||
|
||||
# check if cache exists
|
||||
if not os.path.exists(self.cache_folder):
|
||||
os.makedirs(self.cache_folder)
|
||||
if not draw:
|
||||
# check if video exists
|
||||
if not os.path.exists(self.video_folder + video):
|
||||
logging.error("Video does not exist at path: " + self.video_folder + video)
|
||||
return None
|
||||
|
||||
# check if cache file exists and return
|
||||
if os.path.exists(self.cache_folder + "/" + video + ".npy"):
|
||||
# create dataframe from cache
|
||||
return pd.DataFrame(np.load(self.cache_folder + "/" + video + ".npy", allow_pickle=True), columns=self.columns)
|
||||
# check if cache exists
|
||||
if not os.path.exists(self.cache_folder):
|
||||
os.makedirs(self.cache_folder)
|
||||
|
||||
# check if cache file exists and return
|
||||
if os.path.exists(self.cache_folder + "/" + video + ".npy"):
|
||||
# create dataframe from cache
|
||||
df = pd.DataFrame(np.load(self.cache_folder + "/" + video + ".npy", allow_pickle=True), columns=self.columns)
|
||||
if normalize:
|
||||
df = self.normalize_hands(df)
|
||||
return df
|
||||
|
||||
# open video
|
||||
cap = cv2.VideoCapture(self.video_folder + video)
|
||||
@@ -56,7 +63,9 @@ class KeypointExtractor:
|
||||
|
||||
# extract frames from video so we extract 5 frames per second
|
||||
frame_rate = int(cap.get(cv2.CAP_PROP_FPS))
|
||||
frame_skip = frame_rate // 5
|
||||
frame_skip = frame_rate // 10
|
||||
|
||||
output_frames = []
|
||||
|
||||
while cap.isOpened():
|
||||
|
||||
@@ -70,7 +79,11 @@ class KeypointExtractor:
|
||||
if not success:
|
||||
break
|
||||
# extract keypoints of frame
|
||||
results = self.extract_keypoints_from_frame(image)
|
||||
if draw:
|
||||
results, draw_image = self.extract_keypoints_from_frame(image, draw=True)
|
||||
output_frames.append(draw_image)
|
||||
else:
|
||||
results = self.extract_keypoints_from_frame(image)
|
||||
|
||||
def extract_keypoints(landmarks):
|
||||
if landmarks:
|
||||
@@ -80,15 +93,23 @@ class KeypointExtractor:
|
||||
k1 = extract_keypoints(results.pose_landmarks)
|
||||
k2 = extract_keypoints(results.left_hand_landmarks)
|
||||
k3 = extract_keypoints(results.right_hand_landmarks)
|
||||
if k1 and k2 and k3:
|
||||
keypoints_df = pd.concat([keypoints_df, pd.DataFrame([k1+k2+k3], columns=self.columns)])
|
||||
|
||||
if k1 and (k2 or k3):
|
||||
data = [k1 + (k2 or [0] * 42) + (k3 or [0] * 42)]
|
||||
new_df = pd.DataFrame(data, columns=self.columns)
|
||||
keypoints_df = pd.concat([keypoints_df, new_df], ignore_index=True)
|
||||
|
||||
# close video
|
||||
cap.release()
|
||||
|
||||
# save keypoints to cache
|
||||
np.save(self.cache_folder + "/" + video + ".npy", keypoints_df.to_numpy())
|
||||
|
||||
if normalize:
|
||||
keypoints_df = self.normalize_hands(keypoints_df)
|
||||
|
||||
if draw:
|
||||
return keypoints_df, output_frames
|
||||
|
||||
return keypoints_df
|
||||
|
||||
|
||||
@@ -108,11 +129,81 @@ class KeypointExtractor:
|
||||
if draw:
|
||||
# Draw the pose annotations on the image
|
||||
draw_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
||||
self.mp_drawing.draw_landmarks(draw_image, results.face_landmarks, self.mp_holistic.FACEMESH_CONTOURS)
|
||||
# self.mp_drawing.draw_landmarks(draw_image, results.face_landmarks, self.mp_holistic.FACEMESH_CONTOURS)
|
||||
self.mp_drawing.draw_landmarks(draw_image, results.left_hand_landmarks, self.mp_holistic.HAND_CONNECTIONS)
|
||||
self.mp_drawing.draw_landmarks(draw_image, results.right_hand_landmarks, self.mp_holistic.HAND_CONNECTIONS)
|
||||
|
||||
# create bounding box around hands
|
||||
if results.left_hand_landmarks:
|
||||
x = [landmark.x for landmark in results.left_hand_landmarks.landmark]
|
||||
y = [landmark.y for landmark in results.left_hand_landmarks.landmark]
|
||||
draw_image = cv2.rectangle(draw_image, (int(min(x) * 640), int(min(y) * 480)), (int(max(x) * 640), int(max(y) * 480)), (255, 0, 0), 2)
|
||||
|
||||
if results.right_hand_landmarks:
|
||||
x = [landmark.x for landmark in results.right_hand_landmarks.landmark]
|
||||
y = [landmark.y for landmark in results.right_hand_landmarks.landmark]
|
||||
draw_image = cv2.rectangle(draw_image, (int(min(x) * 640), int(min(y) * 480)), (int(max(x) * 640), int(max(y) * 480)), (255, 0, 0), 2)
|
||||
|
||||
self.mp_drawing.draw_landmarks(draw_image, results.pose_landmarks, self.mp_holistic.POSE_CONNECTIONS)
|
||||
|
||||
return results, draw_image
|
||||
|
||||
return results
|
||||
return results
|
||||
|
||||
|
||||
def normalize_hands(self, dataframe: pd.DataFrame) -> pd.DataFrame:
|
||||
"""normalize_hand this function normalizes the hand keypoints of a dataframe
|
||||
|
||||
:param dataframe: the dataframe to normalize
|
||||
:type dataframe: pd.DataFrame
|
||||
:return: the normalized dataframe
|
||||
:rtype: pd.DataFrame
|
||||
"""
|
||||
|
||||
# normalize left hand
|
||||
dataframe = self.normalize_hand_helper(dataframe, "left_hand")
|
||||
|
||||
# normalize right hand
|
||||
dataframe = self.normalize_hand_helper(dataframe, "right_hand")
|
||||
|
||||
return dataframe
|
||||
|
||||
def normalize_hand_helper(self, dataframe: pd.DataFrame, hand: str) -> pd.DataFrame:
|
||||
"""normalize_hand_helper this function normalizes the hand keypoints of a dataframe
|
||||
|
||||
:param dataframe: the dataframe to normalize
|
||||
:type dataframe: pd.DataFrame
|
||||
:param hand: the hand to normalize
|
||||
:type hand: str
|
||||
:return: the normalized dataframe
|
||||
:rtype: pd.DataFrame
|
||||
"""
|
||||
# get all columns that belong to the hand (left hand column 66 - 107, right hand column 108 - 149)
|
||||
hand_columns = np.array([i for i in range(66 + (42 if hand == "right_hand" else 0), 108 + (42 if hand == "right_hand" else 0))])
|
||||
|
||||
# get the x, y coordinates of the hand keypoints
|
||||
hand_coords = dataframe.iloc[:, hand_columns].values.reshape(-1, 21, 2)
|
||||
|
||||
# get the min and max x, y coordinates of the hand keypoints
|
||||
min_x, min_y = np.min(hand_coords[:, :, 0], axis=1), np.min(hand_coords[:, :, 1], axis=1)
|
||||
max_x, max_y = np.max(hand_coords[:, :, 0], axis=1), np.max(hand_coords[:, :, 1], axis=1)
|
||||
|
||||
# calculate the center of the hand keypoints
|
||||
center_x, center_y = (min_x + max_x) / 2, (min_y + max_y) / 2
|
||||
|
||||
# calculate the width and height of the bounding box around the hand keypoints
|
||||
bbox_width, bbox_height = max_x - min_x, max_y - min_y
|
||||
|
||||
# repeat the center coordinates and bounding box dimensions to match the shape of hand_coords
|
||||
center_coords = np.tile(np.array([center_x, center_y]), (21, 1)).reshape(-1, 21, 2)
|
||||
bbox_dims = np.tile(np.array([bbox_width, bbox_height]), (21, 1)).reshape(-1, 21, 2)
|
||||
|
||||
if np.any(bbox_dims == 0):
|
||||
return dataframe
|
||||
# normalize the hand keypoints based on the bounding box around the hand
|
||||
norm_hand_coords = (hand_coords - center_coords) / bbox_dims
|
||||
|
||||
# flatten the normalized hand keypoints array and replace the original hand keypoints with the normalized hand keypoints in the dataframe
|
||||
dataframe.iloc[:, hand_columns] = norm_hand_coords.reshape(-1, 42)
|
||||
|
||||
return dataframe
|
||||
Reference in New Issue
Block a user