{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"objc[21249]: Class CaptureDelegate is implemented in both /Users/fuixlabsdev1/Programming/PP/graduation-thesis/env/lib/python3.8/site-packages/mediapipe/.dylibs/libopencv_videoio.3.4.16.dylib (0x111188860) and /Users/fuixlabsdev1/Programming/PP/graduation-thesis/env/lib/python3.8/site-packages/cv2/cv2.abi3.so (0x15eece480). One of the two will be used. Which one is undefined.\n",
"objc[21249]: Class CVWindow is implemented in both /Users/fuixlabsdev1/Programming/PP/graduation-thesis/env/lib/python3.8/site-packages/mediapipe/.dylibs/libopencv_highgui.3.4.16.dylib (0x107550a68) and /Users/fuixlabsdev1/Programming/PP/graduation-thesis/env/lib/python3.8/site-packages/cv2/cv2.abi3.so (0x15eece4d0). One of the two will be used. Which one is undefined.\n",
"objc[21249]: Class CVView is implemented in both /Users/fuixlabsdev1/Programming/PP/graduation-thesis/env/lib/python3.8/site-packages/mediapipe/.dylibs/libopencv_highgui.3.4.16.dylib (0x107550a90) and /Users/fuixlabsdev1/Programming/PP/graduation-thesis/env/lib/python3.8/site-packages/cv2/cv2.abi3.so (0x15eece4f8). One of the two will be used. Which one is undefined.\n",
"objc[21249]: Class CVSlider is implemented in both /Users/fuixlabsdev1/Programming/PP/graduation-thesis/env/lib/python3.8/site-packages/mediapipe/.dylibs/libopencv_highgui.3.4.16.dylib (0x107550ab8) and /Users/fuixlabsdev1/Programming/PP/graduation-thesis/env/lib/python3.8/site-packages/cv2/cv2.abi3.so (0x15eece520). One of the two will be used. Which one is undefined.\n"
]
}
],
"source": [
"import mediapipe as mp\n",
"import cv2\n",
"import numpy as np\n",
"import pandas as pd\n",
"import traceback\n",
"import pickle\n",
"\n",
"import warnings\n",
"warnings.filterwarnings('ignore')\n",
"\n",
"# Drawing helpers\n",
"mp_drawing = mp.solutions.drawing_utils\n",
"mp_pose = mp.solutions.pose"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Setup important landmarks and functions"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# Determine important landmarks for lunge\n",
"IMPORTANT_LMS = [\n",
" \"NOSE\",\n",
" \"LEFT_SHOULDER\",\n",
" \"RIGHT_SHOULDER\",\n",
" \"LEFT_HIP\",\n",
" \"RIGHT_HIP\",\n",
" \"LEFT_KNEE\",\n",
" \"RIGHT_KNEE\",\n",
" \"LEFT_ANKLE\",\n",
" \"RIGHT_ANKLE\",\n",
" \"LEFT_HEEL\",\n",
" \"RIGHT_HEEL\",\n",
" \"LEFT_FOOT_INDEX\",\n",
" \"RIGHT_FOOT_INDEX\",\n",
"]\n",
"\n",
"# Generate all columns of the data frame\n",
"\n",
"HEADERS = [\"label\"] # Label column\n",
"\n",
"for lm in IMPORTANT_LMS:\n",
" HEADERS += [f\"{lm.lower()}_x\", f\"{lm.lower()}_y\", f\"{lm.lower()}_z\", f\"{lm.lower()}_v\"]"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def extract_important_keypoints(results) -> list:\n",
" '''\n",
" Extract important keypoints from mediapipe pose detection\n",
" '''\n",
" landmarks = results.pose_landmarks.landmark\n",
"\n",
" data = []\n",
" for lm in IMPORTANT_LMS:\n",
" keypoint = landmarks[mp_pose.PoseLandmark[lm].value]\n",
" data.append([keypoint.x, keypoint.y, keypoint.z, keypoint.visibility])\n",
" \n",
" return np.array(data).flatten().tolist()\n",
"\n",
"\n",
"def rescale_frame(frame, percent=50):\n",
" '''\n",
" Rescale a frame to a certain percentage compare to its original frame\n",
" '''\n",
" width = int(frame.shape[1] * percent/ 100)\n",
" height = int(frame.shape[0] * percent/ 100)\n",
" dim = (width, height)\n",
" return cv2.resize(frame, dim, interpolation =cv2.INTER_AREA)\n",
"\n",
"\n",
"def calculate_angle(point1: list, point2: list, point3: list) -> float:\n",
" '''\n",
" Calculate the angle between 3 points\n",
" Unit of the angle will be in Degree\n",
" '''\n",
" point1 = np.array(point1)\n",
" point2 = np.array(point2)\n",
" point3 = np.array(point3)\n",
"\n",
" # Calculate algo\n",
" angleInRad = np.arctan2(point3[1] - point2[1], point3[0] - point2[0]) - np.arctan2(point1[1] - point2[1], point1[0] - point2[0])\n",
" angleInDeg = np.abs(angleInRad * 180.0 / np.pi)\n",
"\n",
" angleInDeg = angleInDeg if angleInDeg <= 180 else 360 - angleInDeg\n",
" return angleInDeg\n",
" \n",
"\n",
"def analyze_knee_angle(\n",
" mp_results, stage: str, angle_thresholds: list, draw_to_image: tuple = None\n",
"):\n",
" \"\"\"\n",
" Calculate angle of each knee while performer at the DOWN position\n",
"\n",
" Return result explanation:\n",
" error: True if at least 1 error\n",
" right\n",
" error: True if an error is on the right knee\n",
" angle: Right knee angle\n",
" left\n",
" error: True if an error is on the left knee\n",
" angle: Left knee angle\n",
" \"\"\"\n",
" results = {\n",
" \"error\": None,\n",
" \"right\": {\"error\": None, \"angle\": None},\n",
" \"left\": {\"error\": None, \"angle\": None},\n",
" }\n",
"\n",
" landmarks = mp_results.pose_landmarks.landmark\n",
"\n",
" # Calculate right knee angle\n",
" right_hip = [\n",
" landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].x,\n",
" landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].y,\n",
" ]\n",
" right_knee = [\n",
" landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value].x,\n",
" landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value].y,\n",
" ]\n",
" right_ankle = [\n",
" landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value].x,\n",
" landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value].y,\n",
" ]\n",
" results[\"right\"][\"angle\"] = calculate_angle(right_hip, right_knee, right_ankle)\n",
"\n",
" # Calculate left knee angle\n",
" left_hip = [\n",
" landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].x,\n",
" landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].y,\n",
" ]\n",
" left_knee = [\n",
" landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].x,\n",
" landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].y,\n",
" ]\n",
" left_ankle = [\n",
" landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].x,\n",
" landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].y,\n",
" ]\n",
" results[\"left\"][\"angle\"] = calculate_angle(left_hip, left_knee, left_ankle)\n",
"\n",
" # Draw to image\n",
" if draw_to_image is not None and stage != \"down\":\n",
" (image, video_dimensions) = draw_to_image\n",
"\n",
" # Visualize angles\n",
" cv2.putText(\n",
" image,\n",
" str(int(results[\"right\"][\"angle\"])),\n",
" tuple(np.multiply(right_knee, video_dimensions).astype(int)),\n",
" cv2.FONT_HERSHEY_COMPLEX,\n",
" 0.5,\n",
" (255, 255, 255),\n",
" 1,\n",
" cv2.LINE_AA,\n",
" )\n",
" cv2.putText(\n",
" image,\n",
" str(int(results[\"left\"][\"angle\"])),\n",
" tuple(np.multiply(left_knee, video_dimensions).astype(int)),\n",
" cv2.FONT_HERSHEY_COMPLEX,\n",
" 0.5,\n",
" (255, 255, 255),\n",
" 1,\n",
" cv2.LINE_AA,\n",
" )\n",
"\n",
" if stage != \"down\":\n",
" return results\n",
"\n",
" # Evaluation\n",
" results[\"error\"] = False\n",
"\n",
" if angle_thresholds[0] <= results[\"right\"][\"angle\"] <= angle_thresholds[1]:\n",
" results[\"right\"][\"error\"] = False\n",
" else:\n",
" results[\"right\"][\"error\"] = True\n",
" results[\"error\"] = True\n",
"\n",
" if angle_thresholds[0] <= results[\"left\"][\"angle\"] <= angle_thresholds[1]:\n",
" results[\"left\"][\"error\"] = False\n",
" else:\n",
" results[\"left\"][\"error\"] = True\n",
" results[\"error\"] = True\n",
"\n",
" # Draw to image\n",
" if draw_to_image is not None:\n",
" (image, video_dimensions) = draw_to_image\n",
"\n",
" right_color = (255, 255, 255) if not results[\"right\"][\"error\"] else (0, 0, 255)\n",
" left_color = (255, 255, 255) if not results[\"left\"][\"error\"] else (0, 0, 255)\n",
"\n",
" right_font_scale = 0.5 if not results[\"right\"][\"error\"] else 1\n",
" left_font_scale = 0.5 if not results[\"left\"][\"error\"] else 1\n",
"\n",
" right_thickness = 1 if not results[\"right\"][\"error\"] else 2\n",
" left_thickness = 1 if not results[\"left\"][\"error\"] else 2\n",
"\n",
" # Visualize angles\n",
" cv2.putText(\n",
" image,\n",
" str(int(results[\"right\"][\"angle\"])),\n",
" tuple(np.multiply(right_knee, video_dimensions).astype(int)),\n",
" cv2.FONT_HERSHEY_COMPLEX,\n",
" right_font_scale,\n",
" right_color,\n",
" right_thickness,\n",
" cv2.LINE_AA,\n",
" )\n",
" cv2.putText(\n",
" image,\n",
" str(int(results[\"left\"][\"angle\"])),\n",
" tuple(np.multiply(left_knee, video_dimensions).astype(int)),\n",
" cv2.FONT_HERSHEY_COMPLEX,\n",
" left_font_scale,\n",
" left_color,\n",
" left_thickness,\n",
" cv2.LINE_AA,\n",
" )\n",
"\n",
" return results"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Constants"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"VIDEO_PATH1 = \"../data/lunge/lunge_test_3.mp4\"\n",
"VIDEO_PATH2 = \"../data/lunge/lunge_test_5.mp4\""
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"with open(\"./model/input_scaler.pkl\", \"rb\") as f:\n",
" input_scaler = pickle.load(f)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Detection with Sklearn Models"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# Load model\n",
"with open(\"./model/sklearn/stage_SVC_model.pkl\", \"rb\") as f:\n",
" stage_sklearn_model = pickle.load(f)\n",
"\n",
"with open(\"./model/sklearn/err_LR_model.pkl\", \"rb\") as f:\n",
" err_sklearn_model = pickle.load(f)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: Created TensorFlow Lite XNNPACK delegate for CPU.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n"
]
}
],
"source": [
"cap = cv2.VideoCapture(VIDEO_PATH1)\n",
"current_stage = \"\"\n",
"counter = 0\n",
"\n",
"prediction_probability_threshold = 0.8\n",
"ANGLE_THRESHOLDS = [60, 135]\n",
"\n",
"knee_over_toe = False\n",
"\n",
"with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5) as pose:\n",
" while cap.isOpened():\n",
" ret, image = cap.read()\n",
"\n",
" if not ret:\n",
" break\n",
"\n",
" # Reduce size of a frame\n",
" image = rescale_frame(image, 50)\n",
" video_dimensions = [image.shape[1], image.shape[0]]\n",
"\n",
" # Recolor image from BGR to RGB for mediapipe\n",
" image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
" image.flags.writeable = False\n",
"\n",
" results = pose.process(image)\n",
"\n",
" if not results.pose_landmarks:\n",
" print(\"No human found\")\n",
" continue\n",
"\n",
" # Recolor image from BGR to RGB for mediapipe\n",
" image.flags.writeable = True\n",
" image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)\n",
"\n",
" # Draw landmarks and connections\n",
" mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS, mp_drawing.DrawingSpec(color=(244, 117, 66), thickness=2, circle_radius=2), mp_drawing.DrawingSpec(color=(245, 66, 230), thickness=2, circle_radius=1))\n",
"\n",
" # Make detection\n",
" try:\n",
" # Extract keypoints from frame for the input\n",
" row = extract_important_keypoints(results)\n",
" X = pd.DataFrame([row], columns=HEADERS[1:])\n",
" X = pd.DataFrame(input_scaler.transform(X))\n",
"\n",
" # Make prediction and its probability\n",
" stage_predicted_class = stage_sklearn_model.predict(X)[0]\n",
" stage_prediction_probabilities = stage_sklearn_model.predict_proba(X)[0]\n",
" stage_prediction_probability = round(stage_prediction_probabilities[stage_prediction_probabilities.argmax()], 2)\n",
"\n",
" # Evaluate model prediction\n",
" if stage_predicted_class == \"I\" and stage_prediction_probability >= prediction_probability_threshold:\n",
" current_stage = \"init\"\n",
" elif stage_predicted_class == \"M\" and stage_prediction_probability >= prediction_probability_threshold: \n",
" current_stage = \"mid\"\n",
" elif stage_predicted_class == \"D\" and stage_prediction_probability >= prediction_probability_threshold:\n",
" if current_stage in [\"mid\", \"init\"]:\n",
" counter += 1\n",
" \n",
" current_stage = \"down\"\n",
" \n",
" # Error detection\n",
" # Knee angle\n",
" analyze_knee_angle(mp_results=results, stage=current_stage, angle_thresholds=ANGLE_THRESHOLDS, draw_to_image=(image, video_dimensions))\n",
"\n",
" # Knee over toe\n",
" err_predicted_class = err_prediction_probabilities = err_prediction_probability = None\n",
" if current_stage == \"down\":\n",
" err_predicted_class = err_sklearn_model.predict(X)[0]\n",
" err_prediction_probabilities = err_sklearn_model.predict_proba(X)[0]\n",
" err_prediction_probability = round(err_prediction_probabilities[err_prediction_probabilities.argmax()], 2)\n",
" \n",
" \n",
" # Visualization\n",
" # Status box\n",
" cv2.rectangle(image, (0, 0), (800, 45), (245, 117, 16), -1)\n",
"\n",
" # Display stage prediction\n",
" cv2.putText(image, \"STAGE\", (15, 12), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)\n",
" cv2.putText(image, str(stage_prediction_probability), (10, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)\n",
" cv2.putText(image, current_stage, (50, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)\n",
"\n",
" # Display error prediction\n",
" cv2.putText(image, \"K_O_T\", (200, 12), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)\n",
" cv2.putText(image, str(err_prediction_probability), (195, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)\n",
" cv2.putText(image, str(err_predicted_class), (245, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)\n",
"\n",
" # Display Counter\n",
" cv2.putText(image, \"COUNTER\", (110, 12), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)\n",
" cv2.putText(image, str(counter), (110, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)\n",
"\n",
" except Exception as e:\n",
" print(f\"Error: {e}\")\n",
" traceback.print_exc()\n",
" break\n",
" \n",
" cv2.imshow(\"CV2\", image)\n",
" \n",
" # Press Q to close cv2 window\n",
" if cv2.waitKey(1) & 0xFF == ord('q'):\n",
" break\n",
"\n",
" cap.release()\n",
" cv2.destroyAllWindows()\n",
"\n",
" # (Optional)Fix bugs cannot close windows in MacOS (https://stackoverflow.com/questions/6116564/destroywindow-does-not-close-window-on-mac-using-python-and-opencv)\n",
" for i in range (1, 5):\n",
" cv2.waitKey(1)\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Detection with deep learning model"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"# Load model\n",
"with open(\"./model/dp/err_lunge_dp.pkl\", \"rb\") as f:\n",
" err_deep_learning_model = pickle.load(f)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n",
"No human found\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"2022-11-22 15:17:20.031325: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.\n"
]
},
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mThe Kernel crashed while executing code in the the current cell or a previous cell. Please review the code in the cell(s) to identify a possible cause of the failure. Click here for more info. View Jupyter log for further details."
]
}
],
"source": [
"cap = cv2.VideoCapture(VIDEO_PATH1)\n",
"current_stage = \"\"\n",
"counter = 0\n",
"\n",
"prediction_probability_threshold = 0.8\n",
"ANGLE_THRESHOLDS = [60, 135]\n",
"\n",
"knee_over_toe = False\n",
"\n",
"with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5) as pose:\n",
" while cap.isOpened():\n",
" ret, image = cap.read()\n",
"\n",
" if not ret:\n",
" break\n",
"\n",
" # Reduce size of a frame\n",
" image = rescale_frame(image, 50)\n",
" video_dimensions = [image.shape[1], image.shape[0]]\n",
"\n",
" # Recolor image from BGR to RGB for mediapipe\n",
" image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
" image.flags.writeable = False\n",
"\n",
" results = pose.process(image)\n",
"\n",
" if not results.pose_landmarks:\n",
" print(\"No human found\")\n",
" continue\n",
"\n",
" # Recolor image from BGR to RGB for mediapipe\n",
" image.flags.writeable = True\n",
" image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)\n",
"\n",
" # Draw landmarks and connections\n",
" mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS, mp_drawing.DrawingSpec(color=(244, 117, 66), thickness=2, circle_radius=2), mp_drawing.DrawingSpec(color=(245, 66, 230), thickness=2, circle_radius=1))\n",
"\n",
" # Make detection\n",
" try:\n",
" # Extract keypoints from frame for the input\n",
" row = extract_important_keypoints(results)\n",
" X = pd.DataFrame([row], columns=HEADERS[1:])\n",
" X = pd.DataFrame(input_scaler.transform(X))\n",
"\n",
" # Make prediction and its probability\n",
" stage_predicted_class = stage_sklearn_model.predict(X)[0]\n",
" stage_prediction_probabilities = stage_sklearn_model.predict_proba(X)[0]\n",
" stage_prediction_probability = round(stage_prediction_probabilities[stage_prediction_probabilities.argmax()], 2)\n",
"\n",
" # Evaluate model prediction\n",
" if stage_predicted_class == \"I\" and stage_prediction_probability >= prediction_probability_threshold:\n",
" current_stage = \"init\"\n",
" elif stage_predicted_class == \"M\" and stage_prediction_probability >= prediction_probability_threshold: \n",
" current_stage = \"mid\"\n",
" elif stage_predicted_class == \"D\" and stage_prediction_probability >= prediction_probability_threshold:\n",
" if current_stage == \"mid\":\n",
" counter += 1\n",
" \n",
" current_stage = \"down\"\n",
" \n",
" # Error detection\n",
" # Knee angle\n",
" analyze_knee_angle(mp_results=results, stage=current_stage, angle_thresholds=ANGLE_THRESHOLDS, draw_to_image=(image, video_dimensions))\n",
"\n",
" # Knee over toe\n",
" err_predicted_class = err_prediction_probabilities = err_prediction_probability = None\n",
" if current_stage == \"down\":\n",
" err_prediction = err_deep_learning_model.predict(X, verbose=False)\n",
" err_predicted_class = np.argmax(err_prediction, axis=1)[0]\n",
" err_prediction_probability = round(max(err_prediction.tolist()[0]), 2)\n",
"\n",
" err_predicted_class = \"C\" if err_predicted_class == 1 else \"L\"\n",
" \n",
" \n",
" # Visualization\n",
" # Status box\n",
" cv2.rectangle(image, (0, 0), (800, 45), (245, 117, 16), -1)\n",
"\n",
" # Display stage prediction\n",
" cv2.putText(image, \"STAGE\", (15, 12), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)\n",
" cv2.putText(image, str(stage_prediction_probability), (10, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)\n",
" cv2.putText(image, current_stage, (50, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)\n",
"\n",
" # Display error prediction\n",
" cv2.putText(image, \"K_O_T\", (200, 12), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)\n",
" cv2.putText(image, str(err_prediction_probability), (195, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)\n",
" cv2.putText(image, str(err_predicted_class), (245, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)\n",
"\n",
" # Display Counter\n",
" cv2.putText(image, \"COUNTER\", (110, 12), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)\n",
" cv2.putText(image, str(counter), (110, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)\n",
"\n",
" except Exception as e:\n",
" print(f\"Error: {e}\")\n",
" traceback.print_exc()\n",
" break\n",
" \n",
" cv2.imshow(\"CV2\", image)\n",
" \n",
" # Press Q to close cv2 window\n",
" if cv2.waitKey(1) & 0xFF == ord('q'):\n",
" break\n",
"\n",
" cap.release()\n",
" cv2.destroyAllWindows()\n",
"\n",
" # (Optional)Fix bugs cannot close windows in MacOS (https://stackoverflow.com/questions/6116564/destroywindow-does-not-close-window-on-mac-using-python-and-opencv)\n",
" for i in range (1, 5):\n",
" cv2.waitKey(1)\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Conclusion\n",
"\n",
"- For stage detection:\n",
" - Best Sklearn model: KNN\n",
"- For error detection:\n",
" - Best Sklearn model: LR\n",
" - Both models are correct most of the time"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.8.13 (conda)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.13"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "9260f401923fb5c4108c543a7d176de9733d378b3752e49535ad7c43c2271b65"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}