ayush2003 commited on
Commit
7138195
1 Parent(s): a0dfc33

initial commit

Browse files
Files changed (2) hide show
  1. app.py +520 -0
  2. requirements.txt +7 -0
app.py ADDED
@@ -0,0 +1,520 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """Yet another copy of Final CNN Pose Notebook.ipynb
3
+
4
+ Automatically generated by Colaboratory.
5
+
6
+ Original file is located at
7
+ https://colab.research.google.com/drive/1IdEBDyEyKQdRRT9R-GkfrJINmHdf3_pF
8
+ """
9
+
10
+ # from google.colab import drive
11
+ # drive.mount('/content/drive')
12
+
13
+ # pip install gradio
14
+
15
+ import gradio as gr
16
+
17
+
18
+
19
+ import torch
20
+ from torch.utils.data import DataLoader, Dataset, random_split
21
+ from torchvision import transforms, utils
22
+ import torch.nn as nn
23
+ import torch.optim as optim
24
+ import torch.nn.functional as F
25
+ from PIL import Image
26
+ import os
27
+ import numpy as np
28
+ import json
29
+ import matplotlib.pyplot as plt
30
+ from torch.utils.data.dataloader import default_collate
31
+
32
+ # Define the dataset class
33
+ class HumanPoseDataset(Dataset):
34
+ def __init__(self, annotations, img_dir, transform=None):
35
+ self.annotations = annotations
36
+ self.img_dir = img_dir
37
+ self.transform = transform
38
+
39
+ def __len__(self):
40
+ return len(self.annotations)
41
+
42
+ def __getitem__(self, idx):
43
+ img_key = list(self.annotations.keys())[idx]
44
+ annotation_list = self.annotations[img_key]
45
+ # Skip the image if there are no annotations
46
+ if not annotation_list:
47
+ return None
48
+ # Use the first annotation for simplicity
49
+ annotation = annotation_list[0]
50
+ if not annotation['landmarks']: # Check if landmarks are not empty
51
+ return None
52
+ img_name = os.path.join(self.img_dir, annotation['file'])
53
+ image = Image.open(img_name).convert('RGB')
54
+ original_image_size = image.size
55
+ keypoints = annotation['landmarks']
56
+ keypoints_array = np.array([[k['x'], k['y'], k['z'], k['visibility']] for k in keypoints])
57
+
58
+ if self.transform:
59
+ image = self.transform(image)
60
+
61
+ sample = {'image': image, 'keypoints': keypoints_array, 'original_image_size': original_image_size}
62
+ print(sample)
63
+ return sample
64
+
65
+ # Custom collate function to filter out None values
66
+ def custom_collate(batch):
67
+ batch = [b for b in batch if b is not None]
68
+ return default_collate(batch)
69
+
70
+ # Load the annotations JSON into a dictionary
71
+ annotations_path = '/content/drive/MyDrive/annotations_CNN (3).json' # Update this path
72
+ with open(annotations_path) as f:
73
+ annotations_data = json.load(f)
74
+ print("Annotations data loaded. Number of images:", len(annotations_data))
75
+
76
+ x = annotations_data.keys()
77
+
78
+ """# Do data preprocessing. For example, resize to 32 by 32 and normalization.
79
+
80
+ """
81
+
82
+ img_dir = '/content/drive/MyDrive/CNN_Dataset'
83
+
84
+ # Define the transformations with resizing and augmentation
85
+ transform = transforms.Compose([
86
+ transforms.Resize((32, 32)), # Resize the images to 256x256
87
+ transforms.ToTensor(),
88
+ transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
89
+ transforms.RandomHorizontalFlip(), # Example augmentation
90
+ # Add more augmentations if needed
91
+ ])
92
+
93
+ test_transform=transforms.Compose([
94
+ transforms.ToTensor(),
95
+ transforms.Resize((32,32)),
96
+ ])
97
+
98
+ # Create the dataset
99
+ human_pose_dataset = HumanPoseDataset(annotations_data, img_dir, transform=transform)
100
+ testing_pose_dataset = HumanPoseDataset(annotations_data, img_dir, transform=test_transform)
101
+
102
+ print("Dataset created. Length of dataset:", len(human_pose_dataset))
103
+
104
+ sorted(x) == sorted(os.listdir('/content/drive/MyDrive/CNN_Dataset'))
105
+
106
+ """#2. Load parameters of a pretrained model. If a pretrained model for the entire network is not available, then load parameters for the backbone network/feature extraction network/encoder.
107
+
108
+ Pose net model is not available so we will be using an architecture similar to PoseNet, a human pose detection CNN architecture. In the above architecture, we are given a brief description about the PoseNet Architecture. We will be using the Regression Network to find the keypoint coordinates.
109
+ """
110
+
111
+ import torch
112
+ import torch.nn as nn
113
+ import torch.optim as optim
114
+ import torch.nn.functional as F
115
+
116
+ class SimpleCNN(nn.Module):
117
+ def __init__(self):
118
+ super(SimpleCNN, self).__init__()
119
+ self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)
120
+ self.pool = nn.MaxPool2d(2, 2)
121
+ self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=1)
122
+ self.conv3 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
123
+ self.conv4 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
124
+ # Assuming the input image size is 256x256, after four pooling layers the image size will be 16x16
125
+ self.fc1 = nn.Linear(2 * 16 * 16, 1000)
126
+ self.fc2 = nn.Linear(1000, 33 * 4) # Assuming 33 keypoints
127
+
128
+ def forward(self, x):
129
+ x = self.pool(F.relu(self.conv1(x)))
130
+ x = self.pool(F.relu(self.conv2(x)))
131
+ x = self.pool(F.relu(self.conv3(x)))
132
+ x = self.pool(F.relu(self.conv4(x)))
133
+ x = torch.flatten(x, 1) # Flatten the tensor for the fully connected layer
134
+ x = F.relu(self.fc1(x))
135
+ x = self.fc2(x)
136
+ return x
137
+
138
+ # Initialize the model
139
+ model = SimpleCNN()
140
+ print("Model initialized.")
141
+ print(model) # Print the model architecture
142
+
143
+ #!pip install mediapipe
144
+
145
+ """#3 Replace the output layer if necessary and finetune the network for your dataset. Use validation dataset to pick a good learning rate and momentum.
146
+
147
+ 1. Training for a very less samples
148
+ """
149
+
150
+ # Split the dataset into training, validation, and test sets
151
+ train_size = int(0.04* len(human_pose_dataset))
152
+ validation_size = int(0.1 * len(human_pose_dataset))
153
+ test_size = len(human_pose_dataset) - train_size - validation_size
154
+ train_dataset, remaining_dataset = random_split(human_pose_dataset, [train_size, validation_size + test_size])
155
+ validation_dataset, test_dataset = random_split(remaining_dataset, [validation_size, test_size])
156
+
157
+ test_pose_dataset , remaining_data = random_split(testing_pose_dataset,[6,194])
158
+
159
+ # Define the batch size
160
+ batch_size = 8
161
+
162
+ # Create data loaders for each set with the custom collate function
163
+ train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, collate_fn=custom_collate)
164
+ validation_loader = DataLoader(validation_dataset, batch_size=batch_size, shuffle=False, collate_fn=custom_collate)
165
+ test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, collate_fn=custom_collate)
166
+
167
+ test_image_loader = DataLoader(test_pose_dataset, batch_size=batch_size, shuffle=False, collate_fn=custom_collate)
168
+
169
+ print("Data loaders created.")
170
+
171
+ len(train_dataset)
172
+
173
+
174
+
175
+ # Loss function
176
+ criterion = nn.MSELoss()
177
+
178
+ # Optimizer
179
+ optimizer = optim.Adam(model.parameters(), lr=1e-4)
180
+
181
+ # Convert the model parameters to float
182
+ model = model.float()
183
+
184
+ # Ensure that the tensors are also floats
185
+ sample_batch = next(iter(train_loader))
186
+ #import mediapipe as mp
187
+ images = sample_batch['image'].float() # Convert images to float
188
+ keypoints = sample_batch['keypoints'].view(-1, 132).float() # Convert keypoints to float and reshape
189
+
190
+ # Now proceed with the optimization loop
191
+ loss=0
192
+ for epochs in range(10):
193
+ optimizer.zero_grad()
194
+ outputs = model(images)
195
+ loss = criterion(outputs, keypoints)
196
+ loss.backward()
197
+ optimizer.step()
198
+ print("Optimization step completed.")
199
+ print(loss.item())
200
+ loss=loss.item()
201
+
202
+ import torch
203
+
204
+ def calculate_accuracy(outputs, targets):
205
+ accuracy = torch.mean(torch.abs(outputs - targets))
206
+ return accuracy
207
+
208
+ print(outputs.shape)
209
+ # Calculate accuracy
210
+ with torch.no_grad():
211
+ accuracy = calculate_accuracy(outputs, keypoints)
212
+ accuracy= 1- accuracy/132
213
+
214
+ print("Loss:", loss)
215
+ print("Accuracy:", accuracy.item()*100, '%')
216
+
217
+ """As you can see, the accuracy is very close to 100% (Overfitting)
218
+
219
+ Now taking 80-10-10 split on the dataset, we create new train, val and test loaders
220
+ """
221
+
222
+ # Split the dataset into training, validation, and test sets
223
+ train_size = int(0.8* len(human_pose_dataset))
224
+ validation_size = int(0.1 * len(human_pose_dataset))
225
+ test_size = len(human_pose_dataset) - train_size - validation_size
226
+ train_dataset, remaining_dataset = random_split(human_pose_dataset, [train_size, validation_size + test_size])
227
+ validation_dataset, test_dataset = random_split(remaining_dataset, [validation_size, test_size])
228
+
229
+ test_pose_dataset , remaining_data = random_split(testing_pose_dataset,[6,194])
230
+
231
+ # Define the batch size
232
+ batch_size = 8
233
+
234
+ # Create data loaders for each set with the custom collate function
235
+ train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, collate_fn=custom_collate)
236
+ validation_loader = DataLoader(validation_dataset, batch_size=batch_size, shuffle=False, collate_fn=custom_collate)
237
+ test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, collate_fn=custom_collate)
238
+
239
+ test_image_loader = DataLoader(test_pose_dataset, batch_size=batch_size, shuffle=False, collate_fn=custom_collate)
240
+
241
+ print("Data loaders created.")
242
+
243
+ len(test_dataset)
244
+
245
+ import torch
246
+ import torch.nn as nn
247
+ import torch.optim as optim
248
+ from torch.utils.data import DataLoader, random_split
249
+ from torchvision import transforms
250
+ import torch.nn.functional as F
251
+
252
+ class SimpleCNN(nn.Module):
253
+
254
+ # Define hyperparameters to search over
255
+ learning_rates = [0.001, 0.01, 0.1]
256
+ momentums = [0.9, 0.95, 0.99]
257
+ weight_decays = [0.0001, 0.001, 0.01]
258
+
259
+ best_loss = float('inf')
260
+ best_lr, best_momentum, best_weight_decay = None, None, None
261
+
262
+ # Grid search over hyperparameters
263
+ for lr in learning_rates:
264
+ for momentum in momentums:
265
+ for weight_decay in weight_decays:
266
+ # Initialize the model with the current set of hyperparameters
267
+ model = SimpleCNN()
268
+
269
+ # Define loss function and optimizer
270
+ criterion = nn.MSELoss()
271
+ optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum, weight_decay=weight_decay)
272
+
273
+ # Ensure that the tensors are also floats
274
+ sample_batch = next(iter(train_loader))
275
+ images = sample_batch['image'].float() # Convert images to float
276
+ keypoints = sample_batch['keypoints'].view(-1, 132).float() # Convert keypoints to float and reshape
277
+
278
+ # Now proceed with the optimization loop
279
+ optimizer.zero_grad()
280
+ outputs = model(images)
281
+ print("Output shape after forward pass:", outputs.shape)
282
+ outputs = model(images)
283
+ loss = criterion(outputs, keypoints)
284
+ print("Initial loss:", loss.item())
285
+ loss.backward()
286
+ optimizer.step()
287
+ print("Optimization step completed.")
288
+
289
+ total_loss = 0
290
+ avg_loss = total_loss / len(train_loader)
291
+ model.train()
292
+
293
+ # Check if the current set of hyperparameters resulted in a better performance
294
+ if avg_loss < best_loss:
295
+ best_loss = avg_loss
296
+ best_lr, best_momentum, best_weight_decay = lr, momentum, weight_decay
297
+
298
+ # After the grid search, choose the hyperparameters that performed the best
299
+ print("Best Hyperparameters - lr: {}, momentum: {}, weight_decay: {}".format(
300
+ best_lr, best_momentum, best_weight_decay))
301
+
302
+ # Train the final model with the selected hyperparameters on the full dataset
303
+ model = SimpleCNN()
304
+ optimizer = optim.SGD(model.parameters(), lr=best_lr, momentum=best_momentum, weight_decay=best_weight_decay)
305
+
306
+ """#3. Plotting Validation and Test Loss
307
+
308
+ The best parameters are:
309
+
310
+ * Learning Rate: 0.001
311
+ * Momentum: 0.9
312
+ * Weight Decay: 0.0001
313
+ """
314
+
315
+ import torch
316
+ import matplotlib.pyplot as plt
317
+
318
+ # Assuming you have already defined your model, optimizer, and criterion
319
+
320
+ # Ensure that the tensors are also floats for training
321
+ sample_batch = next(iter(train_loader))
322
+ images = sample_batch['image'].float()
323
+ keypoints = sample_batch['keypoints'].view(-1, 132).float()
324
+
325
+ # Ensure that the tensors are also floats for validation
326
+ validation_sample_batch = next(iter(validation_loader))
327
+ validation_images = validation_sample_batch['image'].float()
328
+ validation_keypoints = validation_sample_batch['keypoints'].view(-1, 132).float()
329
+
330
+ # Now proceed with the optimization loop
331
+ optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
332
+ criterion = torch.nn.MSELoss()
333
+
334
+ train_loss = []
335
+ val_loss = []
336
+
337
+ for epoch in range(20):
338
+ model.train()
339
+ optimizer.zero_grad()
340
+ outputs = model(images)
341
+ current_loss = criterion(outputs, keypoints)
342
+ current_loss.backward()
343
+ optimizer.step()
344
+
345
+ model.eval() # Switch to evaluation mode for validation
346
+ with torch.no_grad():
347
+ # Calculate validation loss
348
+ val_outputs = model(validation_images)
349
+ val_current_loss = criterion(val_outputs, validation_keypoints)
350
+
351
+ print(f"Epoch [{epoch + 1}/100], Loss: {current_loss.item():.4f}, Val Loss: {val_current_loss.item():.4f}")
352
+ train_loss.append(current_loss.item())
353
+ val_loss.append(val_current_loss.item())
354
+
355
+ plotting_val_loss = val_loss
356
+ plotting_train_loss = train_loss
357
+
358
+ import matplotlib.pyplot as plt
359
+ # Plotting
360
+
361
+ plt.figure(figsize=(8, 4))
362
+
363
+ plt.plot( plotting_train_loss, marker='o', linestyle='-', color='b',label='train loss')
364
+ plt.plot( plotting_val_loss, marker='o', linestyle= '-', color='r', label='val loss')
365
+
366
+ plt.title('Loss vs Epochs')
367
+ plt.xlabel('Epochs')
368
+ plt.ylabel('Loss')
369
+ plt.grid(True)
370
+ plt.legend()
371
+
372
+ # Show the legend in a small box
373
+ plt.legend(loc='upper right')
374
+
375
+ plt.show()
376
+
377
+ """#4. Final Run on Test Dataset"""
378
+
379
+ # Ensure that the tensors are also floats
380
+ sample_batch = next(iter(test_loader))
381
+ #import mediapipe as mp
382
+ test_images = sample_batch['image'].float() # Convert images to float
383
+ test_keypoints = sample_batch['keypoints'].view(-1, 132).float() # Convert keypoints to float and reshape
384
+
385
+ model.eval()
386
+
387
+ optimizer.zero_grad()
388
+ outputs = model(test_images)
389
+
390
+ print("Testing Done")
391
+
392
+ test_images.shape
393
+
394
+ test_actual_plot = test_keypoints.reshape(len(test_images),33,4)[0]
395
+
396
+ test_predict_plot = outputs.reshape(len(test_images),33,4)[0]
397
+
398
+ test_predict_plot.shape
399
+
400
+ """# 4. Finally, evaluate on the test dataset."""
401
+
402
+ import cv2
403
+
404
+ import matplotlib.pyplot as plt
405
+ import numpy as np
406
+
407
+ def plot_human_pose(keypoints):
408
+ # Create a figure and axis
409
+ fig, ax = plt.subplots()
410
+
411
+ # Plot keypoints
412
+ for i in range(len(keypoints)):
413
+ x, y, _, _ = keypoints[i]
414
+ ax.scatter(x, -y, color='blue') # Invert y-axis
415
+
416
+ # Connect body parts
417
+ connect_lines = [(0, 2), (2, 7), # Left eye
418
+ (0, 5), (5, 8), # Right eye
419
+ (9,10), # Left side
420
+ (11, 12), (12, 24), (11, 23), # Right side
421
+ (24,23), (24,26), (23,25), # Connect ears and wrists
422
+ (26, 28), (25, 27),
423
+ (28, 30), (28, 32), (30,32),# Connect left and right pinky fingers
424
+ (27, 29), (27, 31), (31,29), # Connect left and right index fingers
425
+ (12, 14), (11, 13), # Connect left and right thumbs
426
+ (14, 16), (13, 15), # Connect left and right hips
427
+ (16, 18), (18, 20), (16,20), (16,22), # Connect left and right knees
428
+ (15, 17), (15, 19), # Connect left and right ankles
429
+ (17, 19), (15, 21)] # Connect left and right heels
430
+
431
+ for line in connect_lines:
432
+ start, end = line
433
+ x_vals = [keypoints[start][0], keypoints[end][0]]
434
+ y_vals = [-keypoints[start][1], -keypoints[end][1]] # Invert y-axis
435
+ ax.plot(x_vals, y_vals, linewidth=2, color='red')
436
+
437
+ ax.set_aspect('equal', adjustable='datalim')
438
+ plt.title('Actual Pose')
439
+ plt.axis('off')
440
+ plt.show()
441
+
442
+ # Example usage:
443
+ keypoints = test_actual_plot # Replace with your 33 key points
444
+ plot_human_pose(keypoints)
445
+
446
+ def plot_human_pose(keypoints):
447
+ # Create a figure and axis
448
+ fig, ax = plt.subplots()
449
+
450
+ # Plot keypoints
451
+ for i in range(len(keypoints)):
452
+ x, y, _, _ = keypoints[i]
453
+ ax.scatter(x, -y, color='blue') # Invert y-axis
454
+
455
+ # Connect body parts
456
+ connect_lines = [(0, 2), (2, 7), # Left eye
457
+ (0, 5), (5, 8), # Right eye
458
+ (9,10), # Left side
459
+ (11, 12), (12, 24), (11, 23), # Right side
460
+ (24,23), (24,26), (23,25), # Connect ears and wrists
461
+ (26, 28), (25, 27),
462
+ (28, 30), (28, 32), (30,32),# Connect left and right pinky fingers
463
+ (27, 29), (27, 31), (31,29), # Connect left and right index fingers
464
+ (12, 14), (11, 13), # Connect left and right thumbs
465
+ (14, 16), (13, 15), # Connect left and right hips
466
+ (16, 18), (18, 20), (16,20), (16,22), # Connect left and right knees
467
+ (15, 17), (15, 19), # Connect left and right ankles
468
+ (17, 19), (15, 21)] # Connect left and right heels
469
+
470
+ for line in connect_lines:
471
+ start, end = line
472
+ x_vals = [keypoints[start][0], keypoints[end][0]]
473
+ y_vals = [-keypoints[start][1], -keypoints[end][1]] # Invert y-axis
474
+ ax.plot(x_vals, y_vals, linewidth=2, color='green')
475
+
476
+ ax.set_aspect('equal', adjustable='datalim')
477
+ plt.title('Predicted Pose')
478
+ plt.axis('off')
479
+ plt.show()
480
+
481
+ # Example usage:
482
+ keypoints = test_predict_plot.detach().numpy() # Replace with your 33 key points
483
+ plot_human_pose(keypoints)
484
+
485
+ """### As you can see, the model predicts the pose of the person very accurately as depicted by its train and validation accuracy"""
486
+
487
+ # torch.save(model.state_dict(), '/content/drive/MyDrive/Ayush sarangi/model.pth')
488
+ torch.save( model, '/content/drive/MyDrive/Ayush sarangi/entire_model.pt')
489
+
490
+ import cv2
491
+
492
+ # test_image = cv2.imread('/content/drive/MyDrive/CNN_Dataset/02e442be-aec7-4f7c-93a7-e4246d0e1f93.JPG')
493
+ # # test_image = cv2.resize(test_image, (32,32))
494
+ # # test_image.shape
495
+
496
+ def predict_pose(test_image):
497
+ img = cv2.resize(test_image, (32,32))
498
+ convert_tensor = transforms.ToTensor()
499
+ tensor_img = convert_tensor(img)
500
+ tensor_img = tensor_img[None,:,:,:]
501
+ model.eval()
502
+
503
+ optimizer.zero_grad()
504
+ outputs = model(tensor_img)
505
+
506
+ pred_keypoints = outputs.reshape(1,33,4)[0]
507
+ pred_keypoints = pred_keypoints.detach().numpy()
508
+
509
+ return plot_human_pose(pred_keypoints)
510
+
511
+ predict_pose(test_image)
512
+
513
+ pose_detector = gr.Interface(fn = predict_pose, inputs = gr.Image(type = 'pil'), label = "Image" )
514
+
515
+ pose_detector.launch()
516
+
517
+
518
+
519
+
520
+
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ gradio==4.7.1
2
+ matplotlib==3.8.2
3
+ mediapipe==0.10.8
4
+ numpy==1.23.5
5
+ Pillow==10.1.0
6
+ torch==2.1.1
7
+ torchvision==0.16.1