add keypoint prediction model
This commit is contained in:
		
							parent
							
								
									0b98303582
								
							
						
					
					
						commit
						5268543b7a
					
				
							
								
								
									
										6
									
								
								app.py
								
								
								
								
							
							
						
						
									
										6
									
								
								app.py
								
								
								
								
							|  | @ -17,6 +17,8 @@ import openpose_gen as opg | ||||||
| from comfy_socket import get_images | from comfy_socket import get_images | ||||||
| from postprocessing import expo_shuffle_image_steps, expo_add_to_background_image, expo_postprocess_main | from postprocessing import expo_shuffle_image_steps, expo_add_to_background_image, expo_postprocess_main | ||||||
| import skeleton_lib as skel | import skeleton_lib as skel | ||||||
|  | import predict as pred | ||||||
|  | 
 | ||||||
| sys.path.append('./') | sys.path.append('./') | ||||||
| app = Flask(__name__) | app = Flask(__name__) | ||||||
| 
 | 
 | ||||||
|  | @ -79,6 +81,10 @@ def get_predicted_coordinates(coordinates: list, width: int, height: int) -> lis | ||||||
| 
 | 
 | ||||||
|     # when testing, can visualize with the method expo_save_bodypose in openpose_gen.py |     # when testing, can visualize with the method expo_save_bodypose in openpose_gen.py | ||||||
| 
 | 
 | ||||||
|  |     predicted = pred.predict_pose_keypoints(np.array(coordinates).reshape(1, 18, 3)) | ||||||
|  |     predicted[:, :, 3] = 1 | ||||||
|  |     return predicted.flatten().tolist() | ||||||
|  | 
 | ||||||
|     # for now, just mirror the coordinates and add some random deviation |     # for now, just mirror the coordinates and add some random deviation | ||||||
|     predicted_coordinates = mirror_coordinates(coordinates, width) |     predicted_coordinates = mirror_coordinates(coordinates, width) | ||||||
|     for i in range(0, len(predicted_coordinates), 3): |     for i in range(0, len(predicted_coordinates), 3): | ||||||
|  |  | ||||||
										
											Binary file not shown.
										
									
								
							|  | @ -0,0 +1,140 @@ | ||||||
|  | # import cv2 | ||||||
|  | from glob import glob | ||||||
|  | import matplotlib.pyplot as plt | ||||||
|  | import numpy as np | ||||||
|  | import os | ||||||
|  | import torch | ||||||
|  | 
 | ||||||
|  | device = 'cuda' if torch.cuda.is_available() else 'cpu' | ||||||
|  | use_amp = True | ||||||
|  | model_path = './models/loss8.517782751325285.pt' | ||||||
|  | 
 | ||||||
|  | # define helper functions | ||||||
|  | 
 | ||||||
|  | def load_dataset_from_npy(dir_path): | ||||||
|  |     npy_files = glob(os.path.join(os.path.realpath(dir_path), '*.npy')) | ||||||
|  |     return npy_files | ||||||
|  | 
 | ||||||
|  | def find_bbox(keypoints): | ||||||
|  |     keypoints_copy = keypoints | ||||||
|  |     to_delete = [] | ||||||
|  |     cnt = 0 | ||||||
|  |     for kp in keypoints_copy: | ||||||
|  |         # print(kp.shape)x | ||||||
|  |         pos = (kp[0], kp[1]) | ||||||
|  |         if (pos == (0, 0)) or (pos == (1, 0)): | ||||||
|  |             to_delete.append(cnt) | ||||||
|  |         cnt += 1 | ||||||
|  |     keypoints_copy = np.delete(keypoints_copy, to_delete, 0) | ||||||
|  |     return [min(keypoints_copy[:, 0]), max(keypoints_copy[:, 0]), min(keypoints_copy[:, 1]), max(keypoints_copy[:, 1])] | ||||||
|  | 
 | ||||||
|  | def get_dist_grid(dist_ref, grid_dim=[30, 1], offsets=[0, 0]): | ||||||
|  |     dist_grid = torch.zeros([grid_dim[0], grid_dim[1], 2]).to(device) | ||||||
|  |     offsetX = torch.tensor([offsets[0], 0.0]).float().to(device) | ||||||
|  |     offsetY = torch.tensor([0.0, offsets[1]]).float().to(device) | ||||||
|  |     for i in range(grid_dim[0]): | ||||||
|  |         for j in range(grid_dim[1]): | ||||||
|  |             dist_grid[i, j, :] = dist_ref + \ | ||||||
|  |                                  offsetX * (i - int((grid_dim[0]) / 2)) + \ | ||||||
|  |                                  offsetY * (j - int((grid_dim[1]) / 2)) | ||||||
|  | 
 | ||||||
|  |     return dist_grid | ||||||
|  | 
 | ||||||
|  | def bbox_center(bbox): | ||||||
|  |     return ((bbox[0] + bbox[1])/2, (bbox[2] + bbox[3])/2) | ||||||
|  | 
 | ||||||
|  | def bbox_dists(bbox1, bbox2): | ||||||
|  |     return (np.array(bbox_center(bbox1)) - np.array(bbox_center(bbox2))) | ||||||
|  | 
 | ||||||
|  | def openpose17_colors(): | ||||||
|  |     return ['#ff0000', '#ff5500', '#ffaa00', '#ffff00', '#aaff00', '#55ff00', '#00ff00', '#00ff55', '#00ffaa', '#00ffff', '#00aaff', '#0055ff', '#0000ff', '#5500ff', '#aa00ff', '#ff00ff', '#ff00aa', '#ff0055'] | ||||||
|  | 
 | ||||||
|  | def keypoints25to18(keypoints): | ||||||
|  |     return np.delete(keypoints, [8, 19, 20, 21, 22, 23, 24], 0) | ||||||
|  | 
 | ||||||
|  | def get_keypoints_linkage(): | ||||||
|  |     return np.array([[0, 1], [1, 2], [2, 3], [3, 4], [1, 5], [5, 6], [6, 7], [1, 8], [8, 9], [9, 10], [1, 11], [11, 12], [12, 13], [0, 14], [14, 16], [0, 15], [15, 17]]) | ||||||
|  | 
 | ||||||
|  | @torch.compile | ||||||
|  | def batch_pose_confidence_mat(batch_pose_keypoints_with_confidence): | ||||||
|  |     keypoints_conf = batch_pose_keypoints_with_confidence[:, :, 2] | ||||||
|  |     confidence_mat = torch.zeros([keypoints_conf.shape[0], get_keypoints_linkage().shape[0]]).to(device) | ||||||
|  | 
 | ||||||
|  |     for i in range(get_keypoints_linkage().shape[0]): | ||||||
|  |         for j in range(keypoints_conf.shape[0]): | ||||||
|  |             if keypoints_conf[j, get_keypoints_linkage()[i, 0]] == 0 or keypoints_conf[j, get_keypoints_linkage()[i, 1]] == 0: | ||||||
|  |                 confidence_mat[j, i] = 0 | ||||||
|  |             else: | ||||||
|  |                 confidence_mat[j, i] = (keypoints_conf[j, get_keypoints_linkage()[i, 0]] + keypoints_conf[j, get_keypoints_linkage()[i, 1]]) / 2 | ||||||
|  | 
 | ||||||
|  |     return confidence_mat | ||||||
|  | 
 | ||||||
|  | @torch.compile | ||||||
|  | def pose_diff(output_pose_keypoints, target_pose_keypoints, confidence_mat): | ||||||
|  |     link_open = get_keypoints_linkage()[:, 0] | ||||||
|  |     link_end = get_keypoints_linkage()[:, 1] | ||||||
|  | 
 | ||||||
|  |     p1 = (output_pose_keypoints[:, link_open, :2] - target_pose_keypoints[:, link_open, :2]).reshape(output_pose_keypoints.shape[0], get_keypoints_linkage().shape[0], 2) | ||||||
|  |     p2 = (output_pose_keypoints[:, link_end, :2] - target_pose_keypoints[:, link_end, :2]).reshape(output_pose_keypoints.shape[0], get_keypoints_linkage().shape[0], 2) | ||||||
|  | 
 | ||||||
|  |     return torch.sum(torch.sum(torch.pow(p1, 2) + torch.pow(p2, 2), axis=2) * confidence_mat) / get_keypoints_linkage().shape[0] / output_pose_keypoints.shape[0] | ||||||
|  | 
 | ||||||
|  | @torch.compile | ||||||
|  | def pose_loss(outputs, batch_target_pose_keypoints_with_confidence): | ||||||
|  |     err = pose_diff(outputs, batch_target_pose_keypoints_with_confidence, batch_pose_confidence_mat(batch_target_pose_keypoints_with_confidence)) | ||||||
|  |     return torch.abs(torch.sum(err)) | ||||||
|  | 
 | ||||||
|  | @torch.compile | ||||||
|  | def zscore_normalization(data): | ||||||
|  |     return torch.std(data), torch.mean(data), (data - torch.mean(data)) / torch.std(data) | ||||||
|  |      | ||||||
|  | model = torch.nn.Sequential( | ||||||
|  |     torch.nn.Linear(36, 256), | ||||||
|  |     torch.nn.Tanh(), | ||||||
|  |     torch.nn.Dropout(0.1), | ||||||
|  |     torch.nn.Linear(256, 512), | ||||||
|  |     torch.nn.Tanh(), | ||||||
|  |     torch.nn.Dropout(0.1), | ||||||
|  |     torch.nn.Linear(512, 256), | ||||||
|  |     torch.nn.Tanh(), | ||||||
|  |     torch.nn.Dropout(0.1), | ||||||
|  |     torch.nn.Linear(256, 36) | ||||||
|  | ).to(device) | ||||||
|  | 
 | ||||||
|  | loss_fn = pose_loss #torch.nn.MSELoss() | ||||||
|  | optimizer = torch.optim.Adam(model.parameters(), lr=0.001) | ||||||
|  | scaler = torch.cuda.amp.GradScaler(enabled=use_amp) | ||||||
|  |      | ||||||
|  | checkpoint = torch.load(model_path) | ||||||
|  | model.load_state_dict(checkpoint['model']) | ||||||
|  | optimizer.load_state_dict(checkpoint['optimizer']) | ||||||
|  | scaler.load_state_dict(checkpoint['scaler']) | ||||||
|  |      | ||||||
|  | sample_data = torch.Tensor([[[-0.9695, -1.6531,  2.2570], | ||||||
|  |          [-0.9758, -1.5557,  2.5996], | ||||||
|  |          [-1.0910, -1.5669,  2.2916], | ||||||
|  |          [-1.1820, -1.3080,  2.4095], | ||||||
|  |          [-1.0606, -1.2970,  2.6237], | ||||||
|  |          [-0.8728, -1.5446,  2.4116], | ||||||
|  |          [-0.7996, -1.2856,  2.2992], | ||||||
|  |          [-0.6417, -1.3074,  2.2848], | ||||||
|  |          [-1.1578, -1.0483,  2.3292], | ||||||
|  |          [-1.2732, -0.6165,  2.3635], | ||||||
|  |          [-1.3583, -0.2720,  2.3981], | ||||||
|  |          [-1.0120, -1.0378,  2.3269], | ||||||
|  |          [-0.8237, -0.7680,  2.5688], | ||||||
|  |          [-0.7751, -0.3148,  2.4276], | ||||||
|  |          [-0.9878, -1.7177,  2.1040], | ||||||
|  |          [-0.9453, -1.7068,  1.8512], | ||||||
|  |          [-1.0184, -1.7280,  1.7790], | ||||||
|  |          [-0.9146, -1.6959,  0.9578]]]).to(device) | ||||||
|  | model.eval() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def predict_pose_keypoints(data): | ||||||
|  |     std, mean, data = zscore_normalization(data) | ||||||
|  |     data = data[:,:,:2].reshape(1, 36).to(device) | ||||||
|  |     with torch.cuda.amp.autocast(enabled=use_amp): | ||||||
|  |         outputs = model(data) | ||||||
|  |     outputs = (outputs * std + mean).reshape(18, 2).cpu().detach().numpy() | ||||||
|  |     return outputs | ||||||
		Loading…
	
		Reference in New Issue