<jupyter_start><jupyter_text>Computer Vision push ups counterIn this project I have combined two techniques to construct a simple computer vision technique to count the number of push ups, pull ups or squats from a video.  Creating the validation and train data generators, from the directories.<jupyter_code>import tensorflow as tf
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import distutils

train_datagen = ImageDataGenerator(
    rescale=1./255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
    './data/train',
    target_size=(64, 64),
    color_mode="rgb",
    batch_size=16,
    class_mode='categorical',
    shuffle=True,
    seed=42)

validation_generator = test_datagen.flow_from_directory(
    './data/validation',
    target_size=(64, 64),
    batch_size=1,
    class_mode='categorical')<jupyter_output>Found 376 images belonging to 3 classes.
Found 84 images belonging to 3 classes.<jupyter_text>Model<jupyter_code>def create_model():
  model = tf.keras.models.Sequential()
  model.add(tf.keras.Input(shape=(64,64,3)))
  #model.add(tf.keras.layers.BatchNormalization())
  model.add(tf.keras.layers.Conv2D(6, (3, 3), padding='same', activation='relu'))
  model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))
  
  model.add(tf.keras.layers.Conv2D(16, (3,3), padding='same', activation='relu'))
  model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))

  #model.add(tf.keras.layers.BatchNormalization())
  model.add(tf.keras.layers.Conv2D(32, (3,3), padding='same', activation='relu'))
  model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2,2)))

  #model.add(tf.keras.layers.BatchNormalization())
  model.add(tf.keras.layers.Conv2D(64, (3,3), padding='same', activation='relu'))
  model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2,2)))  

  model.add(tf.keras.layers.Dropout(0.25))

  model.add(tf.keras.layers.Flatten())
  model.add(tf.keras.layers.Dense(512))
  model.add(tf.keras.layers.Activation('relu'))
  model.add(tf.keras.layers.Dropout(0.5))
  model.add(tf.keras.layers.Dense(128))
  model.add(tf.keras.layers.Activation('relu'))
  model.add(tf.keras.layers.Dropout(0.5))
  model.add(tf.keras.layers.Dense(64))
  model.add(tf.keras.layers.Dropout(0.5))
  model.add(tf.keras.layers.Dense(3))
  model.add(tf.keras.layers.Activation('softmax'))
  return model<jupyter_output><empty_output><jupyter_text>Initializing the model and training<jupyter_code>model = create_model()
model.compile(
      optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),
      loss='categorical_crossentropy',
      metrics=['categorical_accuracy'])

model.fit(
    train_generator,
    epochs=10,
    validation_data=validation_generator,
    validation_freq=1
)

model.save('model.h5', overwrite=True)<jupyter_output>Epoch 1/10
24/24 [==============================] - 13s 536ms/step - loss: 0.9943 - categorical_accuracy: 0.4016 - val_loss: 0.7613 - val_categorical_accuracy: 0.5238
Epoch 2/10
24/24 [==============================] - 13s 543ms/step - loss: 0.8253 - categorical_accuracy: 0.6995 - val_loss: 0.7210 - val_categorical_accuracy: 0.7500
Epoch 3/10
24/24 [==============================] - 13s 550ms/step - loss: 0.6235 - categorical_accuracy: 0.7766 - val_loss: 0.6164 - val_categorical_accuracy: 0.8095
Epoch 4/10
24/24 [==============================] - 14s 566ms/step - loss: 0.5352 - categorical_accuracy: 0.8059 - val_loss: 0.4083 - val_categorical_accuracy: 0.8333
Epoch 5/10
24/24 [==============================] - 13s 523ms/step - loss: 0.5674 - categorical_accuracy: 0.7606 - val_loss: 0.4435 - val_categorical_accuracy: 0.8095
Epoch 6/10
24/24 [==============================] - 12s 511ms/step - loss: 0.4443 - categorical_accuracy: 0.8138 - val_loss: 0.3677 - val_categorical_accuracy: 0.869[...]<jupyter_text>Loading the model<jupyter_code>model = tf.keras.models.load_model('model.h5')<jupyter_output><empty_output><jupyter_text>Loading and generating a new video with the repetitions<jupyter_code>import cv2
import numpy as np
cap = cv2.VideoCapture("test_video.mov")

fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
out = cv2.VideoWriter('output_count.avi',fourcc, 20.0,(int(cap.get(3)),int(cap.get(4))))

ret, frame1 = cap.read()
prvs = cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[...,1] = 255
i= 0
prediction_str = ""
repetitions = 0
up = 0
down = 0
no_move = 0
current_move = 0
initial = -1
while(cap.isOpened()):
    i+=1
    
    ret, frame2 = cap.read()
    if not(ret): break
    next = cv2.cvtColor(frame2,cv2.COLOR_BGR2GRAY)

    flow = cv2.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)

    

    mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])
    hsv[...,0] = ang*180/np.pi/2
    hsv[...,2] = cv2.normalize(mag,None,0,255,cv2.NORM_MINMAX)
    rgb = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR)

    image = cv2.resize(rgb, (64, 64))
    image = image.reshape((1,) + image.shape)
    image = image/255.0
    prediction = np.argmax(model.predict(image), axis=-1)[0]
    
    if prediction == 0:
        down +=1 
        if down == 3:
          if initial == -1:
            initial = 0
          if current_move == 2:
            repetitions+=1
          current_move = 0
        elif down > 0:
          up = 0
          no_move = 0
    elif prediction == 2:
        up += 1
        if up == 3 and initial != -1:
          current_move = 2
        elif up > 1:
          down = 0 
          no_move = 0
    else:
        no_move += 1
        if no_move == 15:
          current_move = 1
        elif no_move > 10:
          up = 0
          down = 0 
    font                   = cv2.FONT_HERSHEY_SIMPLEX
    bottomLeftCornerOfText = (10,400)
    fontScale              = 1
    fontColor              = (255,255,255)
    lineType               = 5
    cv2.putText(frame2, "Repetitions: "+ str(repetitions),bottomLeftCornerOfText,font, fontScale,fontColor,lineType)
    out.write(frame2)
    prvs = next

print("Video Generated")
out.release()
cap.release()
cv2.destroyAllWindows()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.16792786990822733, 'fraction_numerical': 0.06585090967638062, 'mean_word_length': 3.695389266817838, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '580605', 'license': 'MIT', 'n_tokens_mistral': 2543, 'n_tokens_neox': 2274, 'n_words': 407, 'path': 'exercise_predictor.ipynb', 'repo_name': 'a-i-r-1/Deep-Learning-Push-Up-Counter', 'size': '6211'}