<jupyter_start><jupyter_text>Human Posture DetectionIn this example, we show how the MAX-Human-Pose-Estimator model can be used to detect and visualize the human poses from an image. Contents of this codeWe first visualize the test image and pass it through the MAX-Human-Pose-Estimator model to get all the human poses (a group of lines for each person in a JSON format). We then visualize the detected poses to verify that the model worked as intended.<jupyter_code>import os
import traceback

from matplotlib import pyplot as plt
from utils.helpers import draw_pose, get_pose_from_file, convert_pose
from utils.train import train_svm_classifier
from utils.data import process_images, fill_empty_vector, flatten_dataset

from sklearn.preprocessing import LabelEncoder
import numpy as np
import cv2
import pandas as pd
%matplotlib inline<jupyter_output><empty_output><jupyter_text>Process images to the numpy formatTurn images stored in assets/images into numpy files stored in assets/poses.Images of the same class must be stored in their own subdirectories in the assets/images directory.The *process_images* function goes through all of the directories in the assets/images folder, processing all of the images in each folder. The *get_pose_from_file* function takes the specified image and sends it to the MAX Model for prediction. The model returns a prediction of shape [num_lines, x, y] where x and y define the Cartesian coordinates of the center of the predicted body part.The *save_pose* function takes these Cartesian predictions and saves the prediction as a numpy file. The *cartesian* parameter specifies whether or not to convert to polar coordinates. When converted to polar coordinates, the features are converted from from [x, y] to [rho, phi], a vector that points from the center of the pose to the specified coordinate.<jupyter_code>def process(cartesian=False):
    """
    Extracts features and labels from assets/images directory
    """
    features = []
    labels = []
    lines = []
    fig = plt.figure(figsize=(14,14))

    for x in os.walk(str(os.getcwd())+'/assets/images'):
        for d in x[1]:
            if d != 'test':
                print('processing images in {}'.format(d))
                for f in os.listdir(str(os.getcwd())+'/assets/images/'+d):
                    try:
                        preds, img = get_pose_from_file(f, d)
                        
                        if preds['predictions']:
                            for i in range(len(preds['predictions'])):
                                pose_lines = preds['predictions'][i]['pose_lines']
                                body_parts = preds['predictions'][i]['body_parts']
                                coordinates = np.array([[d['x'], d['y']] for d in body_parts], dtype=np.float32)
                                p = convert_pose(coordinates, cartesian=cartesian)

                                if p != []:
                                    p = fill_empty_vector(p)
                                    features.append(p)
                                    labels.append(d)
                                    lines.append(pose_lines)

                    except Exception:
                        print("Something went wrong")
                        traceback.print_exc()
                        break

    return np.array(features), labels, np.array(lines)
features, labels, lines = process_images(cartesian=True)<jupyter_output><empty_output><jupyter_text>Augment the dataAdding more data helps our model generalize a little bit. Tweak the data_size and noise_amount values to change how noisy the poses should be.<jupyter_code># take the features and labels and add noise to them until each class reaches data_size
def augment_data(features, labels, data_size=15,noise_amount=0.03):
    print('\n--- Augmenting Data ---\n')
    orig_labels_count = len(labels)
    label_frequency = np.unique(labels, return_counts=True)
    
    while sum(label_frequency[1]) < data_size * len(label_frequency[0]):
        for i in range(orig_labels_count):
            if label_frequency[1][np.where(label_frequency[0] == labels[i])] < data_size:
                feature = features[i]
                new_data = np.zeros(feature.shape,dtype=np.float32)
                
                # add noise to each body part, making sure to add the same noise to corresponding joints
                for k, part in enumerate(feature):
                    noise = np.random.normal(0, noise_amount, 2)
                    new_0 = part[0] + noise[0]
                    new_1 = part[1] + noise[1]
                    new_data[k] = [new_0, new_1]

                features = np.concatenate((features, np.expand_dims(new_data,axis=0)))
                labels.append(labels[i])
            label_frequency = np.unique(labels, return_counts=True)

    return features, labels

# OPTIMAL PARAMETERS
data_size, noise = 100, 0.05
f_aug, l_aug = augment_data(features, labels, data_size=data_size, noise_amount=noise)<jupyter_output><empty_output><jupyter_text>PCA<jupyter_code>from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

df = pd.DataFrame(columns=['Class','Nose_x','Nose_y',
    'Neck_x','Neck_y',
    'RShoulder_x','RShoulder_y',
    'RElbow_x','RElbow_y',
    'RWrist_x','RWrist_y',
    'LShoulder_x','LShoulder_y',
    'LElbow_x','LElbow_y',
    'LWrist_x','LWrist_y',
    'RHip_x','RHip_y',
    'RKnee_x','RKnee_y',
    'RAnkle_x','RAnkle_y',
    'LHip_x','LHip_y',
    'LKnee_x','LKnee_y',
    'LAnkle_x','LAnkle_y',
    'REye_x','REye_y',
    'LEye_x','LEye_y',
    'REar_x','REar_y',
    'LEar_x','LEar_y'])

df['Class'] = l_aug

for col in [name for name in df.columns if name != 'Class']:
    if '_x' in col:
        x = 0
    else:
        x = 1
    idx = (df.columns.get_loc(col)) % 19
    df[col] = f_aug[:,idx,x]
    
class_names = df['Class'].unique()
#df['Class'] = pd.factorize(df['Class'])[0] + 1

# separate features from target
feats = [name for name in df.columns if name != 'Class']

x = df.loc[:,feats].values
y = df.loc[:,['Class']].values

# standardize the features
x = StandardScaler().fit_transform(x)
pca = PCA(.95)

# get principal components
principal_components = pca.fit_transform(x)
principal_df = pd.DataFrame(data = principal_components)
final_df = pd.concat([principal_df, df[['Class']]], axis=1)<jupyter_output><empty_output><jupyter_text>Plot the first two principal components so we can see how well the classes separate<jupyter_code>fig = plt.figure(figsize=(13,11))
ax = fig.add_subplot(1,1,1) 
ax.set_xlabel('Principal Component 1', fontsize = 15)
ax.set_ylabel('Principal Component 2', fontsize = 15)
ax.set_title(str('2 component PCA with data_size = {} noise = {}'.format(data_size, noise)), fontsize = 20)
targets = class_names
colors = ['aqua', 'magenta', 'navy', 'lime', 'red', 'blue', 'orange', 'yellow', 'maroon', 'coral','plum']

for target, color in zip(targets,colors):
    indicesToKeep = final_df['Class'] == target
    ax.scatter(final_df.loc[indicesToKeep, 0],
               final_df.loc[indicesToKeep, 1],
               c = color, s = 50)
    
ax.legend(targets)
ax.grid()<jupyter_output><empty_output><jupyter_text>Encode the labels to feed it into SVM.<jupyter_code>def encode_labels(labels):
    label_encoder = LabelEncoder()
    integer_encoded = label_encoder.fit_transform(labels)
    name_map = {key:val for key,val in zip(integer_encoded,labels)}
    return np.array(integer_encoded), name_map

labels_encoded, name_map = encode_labels(l_aug)<jupyter_output><empty_output><jupyter_text>Get the ideal poses for each class.<jupyter_code>def get_ideal_pose(features, labels, name_map):
    ideal_poses = {}
    for lab, name in name_map.items():
        feature_list = np.array([feats for i, feats in enumerate(features) if labels[i]==lab])
        ideal_poses[name] = np.average(feature_list, axis=0)
        
    return ideal_poses

ideal_poses = get_ideal_pose(f_aug, labels_encoded, name_map)<jupyter_output><empty_output><jupyter_text>Plot the polar coordinates for the features<jupyter_code>import matplotlib.cm as cm

for lab,name in name_map.items():
    fig = plt.figure(figsize=(10,10))
    ax = fig.add_subplot(121 + lab%2, projection='polar')
    ax.set_theta_zero_location("W")
    plt.title(str(name_map[lab]),loc='left')
    feature_list = np.array([feats for i, feats in enumerate(f_aug) if labels_encoded[i]==lab])
    for feat in feature_list:
        colors = cm.rainbow(np.linspace(0, 1, len(feat[:,0])))
        c = ax.scatter(feat[:,1],feat[:,0],cmap='hsv',alpha=0.75,c=colors)<jupyter_output><empty_output><jupyter_text>Time to train the SVM!Take the augmented data/labels that we've generated, flatten the features vector, then pass into the SVM function for training.This will create */assets/classifier.pkl* which can be loaded at any time for prediction.<jupyter_code>features_flat = flatten_dataset(f_aug)
print('augmented features shape: ', str(f_aug.shape))
print('flattened features shape: ', str(features_flat.shape))
print('encoded labels shape: ', str(labels_encoded.shape))
classifier, svm = train_svm_classifier(features_flat, labels_encoded,'assets/classifier.pkl')<jupyter_output><empty_output><jupyter_text>Test the SVM using the data in the assets/images/test folder<jupyter_code>up = 0
down = 0
for img in os.listdir(str(os.getcwd())+'/assets/images/test'):
    fig = plt.figure(figsize=(10,15))
    # visualize the pose
    plt.subplot(1,2,1)
    
    preds, frame = get_pose_from_file(img,'test')
    bgr = np.array(cv2.imread('./assets/images/test/'+img))
    pose_img = bgr[..., ::-1]
    draw_pose(preds, bgr)
    plt.imshow(pose_img)
    plt.title("The detected poses")
    
    # make predictions
    body_parts = preds['predictions'][0]['body_parts']
    coordinates = np.array([[d['x'], d['y']] for d in body_parts], dtype=np.float32)
    pose = np.array(convert_pose(coordinates, cartesian=False))
    x = flatten_dataset(np.expand_dims(fill_empty_vector(np.squeeze(pose)), axis=0))
    p = classifier.predict(x)
    prediction = name_map[p[0]]
    confidence = classifier.predict_proba(x)
    print('The prediction is {} with confidence {} %'.format(prediction, 100 * confidence[0][p[0]]))
    print('The real pose is ', img.split('.')[0])

    #Check percentage ------------------- Nihar
    inside = str(prediction) in str(img.split('.')[0])
    if inside:
        up +=1
        print("Tru Pred")
    else:
        print("False Pred")
    down +=1
    print(up,down)
    # visualize the polar plot
    ax = plt.subplot(1, 2, 2, projection='polar')
    ax.set_theta_zero_location("W")
    colors = cm.rainbow(np.linspace(0, 1, len(pose[:,0])))
    c = plt.scatter(pose[:, 1], pose[:, 0], cmap='hsv', alpha=0.75, c=colors)
    plt.show()
    
print("Test Accuracy:",up/down*100)
print(str(up) + "/" + str(down) )<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12172078517703173, 'fraction_numerical': 0.011098880939277196, 'mean_word_length': 3.3804740859783045, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '164082', 'license': 'Apache-2.0', 'n_tokens_mistral': 3583, 'n_tokens_neox': 3448, 'n_words': 895, 'path': 'HumanPoseDetection_final.ipynb', 'repo_name': 'rsatwik/Human-Pose-Detection', 'size': '10902'}