def centroidError(): centroid1 = Body25.getCentroid(keypoint1) centroid2 = Body25.getCentroid(keypoint2) dist = Ut.distance(centroid1 / frame, centroid2 / frame, ignore_zero_vector=True) if np.isnan(dist): return np.inf return dist
def __calculateError(self, keypoint1, keypoint2): min_x1, min_y1, max_x1, max_y1 = Body25.getFrameCoordinates(keypoint1) min_x2, min_y2, max_x2, max_y2 = Body25.getFrameCoordinates(keypoint2) width1 = max_x1 - min_x1 width2 = max_x2 - min_x2 height1 = max_y1 - min_y1 height2 = max_y2 - min_y2 total_area1 = width1 * height1 total_area2 = width2 * height2 frame = np.full(shape=Body25.Keypoint.getCoordinatesShape(), fill_value=np.inf) frame[Body25.Keypoint.X.value] = self.__frame_width frame[Body25.Keypoint.Y.value] = self.__frame_height def distanceError(): sum_dist = 0 num = 0 for part in Body25.Parts: coord1 = Body25.getCoordinates(keypoint1, part) coord2 = Body25.getCoordinates(keypoint2, part) dist = Ut.distance(coord1 / frame, coord2 / frame, ignore_zero_vector=True) if np.isnan(dist): continue else: sum_dist += dist num += 1 if num == 0: return np.inf else: return sum_dist / num def centroidError(): centroid1 = Body25.getCentroid(keypoint1) centroid2 = Body25.getCentroid(keypoint2) dist = Ut.distance(centroid1 / frame, centroid2 / frame, ignore_zero_vector=True) if np.isnan(dist): return np.inf return dist def areaError(): return abs(total_area1 - total_area2) / max(total_area1, total_area2) def overlapError(): width = min(max_x1, max_x2) - max(min_x1, min_x2) height = min(max_y1, max_y2) - max(min_y1, min_y2) overlapped_area = width * height if abs(width) > width1 or abs(width) > width2 or \ abs(height) > height1 or abs(height) > height2 or \ abs(overlapped_area) > total_area1 or abs(overlapped_area) > total_area2: return np.inf return 1 - overlapped_area / (total_area1 + total_area2) errors = [distanceError(), centroidError(), areaError(), overlapError()] weight = [15, 3, 1, 3] return np.dot(errors, weight) / sum(weight)
def distanceError(): sum_dist = 0 num = 0 for part in Body25.Parts: coord1 = Body25.getCoordinates(keypoint1, part) coord2 = Body25.getCoordinates(keypoint2, part) dist = Ut.distance(coord1 / frame, coord2 / frame, ignore_zero_vector=True) if np.isnan(dist): continue else: sum_dist += dist num += 1 if num == 0: return np.inf else: return sum_dist / num
def predictPoseBody25(keypoint, logger=None): """ @param log_file: The path of log file @param keypoint: 3D array, 25 keypoints x 3 (x, y, score) @return: """ keypoint = np.array(keypoint) Neck = Body25.getCoordinates(keypoint, Body25.Parts.NECK) MidHip = Body25.getCoordinates(keypoint, Body25.Parts.MID_HIP) RHip = Body25.getCoordinates(keypoint, Body25.Parts.R_HIP) RKnee = Body25.getCoordinates(keypoint, Body25.Parts.R_KNEE) RAnkle = Body25.getCoordinates(keypoint, Body25.Parts.R_ANKLE) LHip = Body25.getCoordinates(keypoint, Body25.Parts.L_HIP) LKnee = Body25.getCoordinates(keypoint, Body25.Parts.L_KNEE) LAnkle = Body25.getCoordinates(keypoint, Body25.Parts.L_ANKLE) # define vectors of body parts MidHip_Neck = Ut.pointToVector(MidHip, Neck, ignore_zero_vector=True) MidHip_RKnee = Ut.pointToVector(MidHip, RKnee, ignore_zero_vector=True) MidHip_LKnee = Ut.pointToVector(MidHip, LKnee, ignore_zero_vector=True) RKnee_RHip = Ut.pointToVector(RKnee, RHip, ignore_zero_vector=True) RKnee_RAnkle = Ut.pointToVector(RKnee, RAnkle, ignore_zero_vector=True) LKnee_LHip = Ut.pointToVector(LKnee, LHip, ignore_zero_vector=True) LKnee_LAnkle = Ut.pointToVector(LKnee, LAnkle, ignore_zero_vector=True) # find angle in radians between body parts RBody_hip_angle = Ut.angleBetween(MidHip_Neck, -RKnee_RHip) RKnee_hip_angle = Ut.angleBetween(MidHip_Neck, MidHip_RKnee) RKnee_angle = Ut.angleBetween(RKnee_RHip, RKnee_RAnkle) LBody_hip_angle = Ut.angleBetween(MidHip_Neck, -LKnee_LHip) LKnee_hip_angle = Ut.angleBetween(MidHip_Neck, MidHip_LKnee) LKnee_angle = Ut.angleBetween(LKnee_LHip, LKnee_LAnkle) # find the score of sitting scores = PoseClassifier.Scores(logger) scores.RBody_hip_score = PoseClassifier.__angleScore(RBody_hip_angle) scores.RKnee_hip_score = PoseClassifier.__angleScore(RKnee_hip_angle) scores.RKnee_score = PoseClassifier.__angleScore(RKnee_angle) scores.LBody_hip_score = PoseClassifier.__angleScore(LBody_hip_angle) scores.LKnee_hip_score = PoseClassifier.__angleScore(LKnee_hip_angle) scores.LKnee_score = PoseClassifier.__angleScore(LKnee_angle) # find final score scores.left_score = PoseClassifier.__finalScore( [scores.LBody_hip_score, scores.LKnee_score, scores.LKnee_hip_score], (1, 1, 2)) scores.right_score = PoseClassifier.__finalScore( [scores.RBody_hip_score, scores.RKnee_score, scores.RKnee_hip_score], (1, 1, 2)) scores.print() if logger is not None: scores.log() # Comparing left and right score return PoseClassifier.__determinePose(scores.left_score, scores.right_score)
def outputIndividualPoseToImage(image, text, keypoint): font = cv2.FONT_HERSHEY_SIMPLEX font_scale = 0.5 font_thickness = 2 (text_width, text_height) = cv2.getTextSize(text, font, font_scale, font_thickness)[0] position = Body25.getCentroid(keypoint, to_int=True) position[0] -= text_width // 2 box = ((position[0] - 2, position[1] + 2), (position[0] + text_width + 2, position[1] - text_height - 2)) cv2.rectangle(image, box[0], box[1], (0, 0, 0), cv2.FILLED) cv2.putText(image, text, tuple(position), font, font_scale, (255, 255, 0), font_thickness)
def predictPoseModel(keypoint, logger=None): keypoint = Body25.normalizeKeypoint(keypoint) poses = {pose: 0 for pose in PoseClassifier.Pose} for model in PoseClassifier.__model.getModels(): pose_prediction = model.predict(np.array([keypoint])) for i in range(len(pose_prediction[0])): poses[PoseClassifier.Pose(i)] += pose_prediction[0][i] print(poses) if logger is not None: logger.info(str(poses)) return max(poses, key=poses.get)
def outputIndividualIdToImage(image, id, keypoint): font = cv2.FONT_HERSHEY_SIMPLEX font_scale = 0.5 font_thickness = 2 text = "ID: " + str(id) text_width, text_height = cv2.getTextSize(text, font, font_scale, font_thickness)[0] min_x, min_y, max_x, max_y = Body25.getFrameCoordinates(keypoint, to_int=True) box_coordinates = ((min_x - 5, min_y - text_height - 10), (max_x + 5, max_y + 5)) org = (min_x, min_y - 5) # text_box_coordinates = ((org[0] - 2, org[1] + 2), (org[0] + text_width + 2, org[1] - text_height - 2)) cv2.rectangle(image, box_coordinates[0], box_coordinates[1], (0, 255, 0), 2) # cv2.rectangle(image, text_box_coordinates[0], text_box_coordinates[1], (0, 0, 0), cv2.FILLED) cv2.putText(image, text, org, font, font_scale, (0, 255, 0), font_thickness)
def generateDatasetFromDirectory(directory, pose, export_path, start=0, end=None, logger=None, df=None, config=False): path = export_path.split('.') extension = path[-1] export_path = '.'.join(path[:-1]) if df is None: try: df = pd.read_pickle(export_path + ".pkl") except Exception as e: df = pd.DataFrame([], columns=columns) else: df.columns = columns dir_path = os.path.abspath(directory) config_path = os.path.join(dir_path, "generate_dataset_config.json") try: file_names = sorted(os.listdir(dir_path)) if config is True: config_dict = dict() try: with open(config_path, 'r') as openfile: config_dict = json.load(openfile) openfile.close() except Exception as e: pass for file_name in file_names: if file_name not in config_dict: config_dict[file_name] = False if end is None: end = len(file_names) - 1 pose_estimator = PoseEstimator(face=False, hand=False) for i, file_name in enumerate(file_names, start=1): fp = FilePath(dir_path + "\\" + file_name) try: if int(fp.getFileName()) < start or int( fp.getFileName()) > end: print(file_name + " is not in range\n") continue except Exception as e: continue if config is True: if config_dict[file_name] is True: print(file_name + " has already been processed\n") continue imageToProcess = cv2.imread(fp.getAbsPath()) if imageToProcess is None: continue print("Processing " + file_name) if logger is not None: logger.info("Processing " + file_name) pose_estimator.processImage(imageToProcess) output = pose_estimator.getPoseKeypoints() person = 1 for keypoint in output: score = Body25.getAverageScore(keypoint) if score < 0.5: body_pose = "UNKNOWN" else: body_pose = pose df = df.append( { columns[0]: keypoint, columns[1]: Body25.normalizeKeypoint(keypoint), columns[2]: body_pose, columns[3]: file_name, columns[4]: score }, ignore_index=True) print("Person " + str(person) + ": " + body_pose) if logger is not None: logger.info("Person " + str(person) + ": " + body_pose) person += 1 if config is True: config_dict[file_name] = True print(file_name + " Done") print(str(df['POSE'].value_counts()) + "\n") if logger is not None: logger.info(file_name + " Done") logger.info(str(df['POSE'].value_counts()) + "\n") if i % 5 == 0: df.to_pickle(export_path + ".pkl", protocol=4) print(export_path + ".pkl Saved") if logger is not None: logger.info(export_path + ".pkl Saved") if config is True: with open(config_path, "w") as outfile: json.dump(config_dict, outfile, sort_keys=True) outfile.close() except Exception as e: if logger is not None: logger.error(e) print(e) df.to_pickle(export_path + ".pkl", protocol=4) df.to_csv(export_path + "." + extension, index=False, header=True) if config is True: with open(config_path, "w") as outfile: json.dump(config_dict, outfile, sort_keys=True) outfile.close() print(export_path + ".pkl Saved") print(export_path + "." + extension + " Saved" + "\n") print("Done") print(df['POSE'].value_counts()) if logger is not None: logger.info(export_path + ".pkl Saved") logger.info(export_path + "." + extension + " Saved" + "\n") logger.info("Done") logger.info(df['POSE'].value_counts())