ehsanhon commited on
Commit
537321d
·
verified ·
1 Parent(s): a0c24e5

Upload 3 files

Browse files

test docker file

Files changed (3) hide show
  1. Dockerfile +20 -0
  2. app.py +290 -0
  3. requirements.txt +0 -0
Dockerfile ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use a lightweight Python image
2
+ FROM python:3.9-slim
3
+
4
+ # Set the working directory
5
+ WORKDIR /app
6
+
7
+ # Copy dependency list first (for Docker caching)
8
+ COPY requirements.txt requirements.txt
9
+
10
+ # Install dependencies
11
+ RUN pip install --no-cache-dir -r requirements.txt
12
+
13
+ # Copy the rest of the app files
14
+ COPY . .
15
+
16
+ # Expose the port your Flask app runs on
17
+ EXPOSE 7860
18
+
19
+ # Run the app
20
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, send_file
2
+ from flask_ngrok import run_with_ngrok
3
+ from io import BytesIO
4
+ import mimetypes
5
+ import cv2
6
+ import numpy as np
7
+ import mediapipe as mp
8
+ import math
9
+
10
+ def calculate_angle(point1, point2, point3):
11
+ """
12
+ Calculates the angle at point2 formed by the lines connecting it to point1 and point3.
13
+
14
+ Args:
15
+ point1 (tuple): Coordinates (x, y) of the first point.
16
+ point2 (tuple): Coordinates (x, y) of the vertex (the point where the angle is).
17
+ point3 (tuple): Coordinates (x, y) of the third point.
18
+
19
+ Returns:
20
+ float: The angle in degrees.
21
+ """
22
+ x1, y1 = point1
23
+ x2, y2 = point2
24
+ x3, y3 = point3
25
+
26
+ # Calculate vectors
27
+ vector1 = (x1 - x2, y1 - y2)
28
+ vector2 = (x3 - x2, y3 - y2)
29
+
30
+ # Calculate dot product
31
+ dot_product = vector1[0] * vector2[0] + vector1[1] * vector2[1]
32
+
33
+ # Calculate magnitudes (lengths) of the vectors
34
+ magnitude1 = math.sqrt(vector1[0]**2 + vector1[1]**2)
35
+ magnitude2 = math.sqrt(vector2[0]**2 + vector2[1]**2)
36
+
37
+ # Calculate cosine of the angle
38
+ if magnitude1 == 0 or magnitude2 == 0:
39
+ return 0.0 # Handle cases where points are the same
40
+ cos_theta = dot_product / (magnitude1 * magnitude2)
41
+
42
+ # Ensure cos_theta is within the valid range [-1, 1] due to potential floating-point errors
43
+ cos_theta = max(-1.0, min(1.0, cos_theta))
44
+
45
+ # Calculate the angle in radians and convert to degrees
46
+ angle_radians = math.acos(cos_theta)
47
+ angle_degrees = math.degrees(angle_radians)
48
+
49
+ return angle_degrees
50
+
51
+ # Function to extract the coordinates of a landmark
52
+ def get_landmark_coordinates(landmarks, landmark_id):
53
+ try:
54
+ x = landmarks.landmark[landmark_id].x
55
+ y = landmarks.landmark[landmark_id].y
56
+ x=x/1
57
+ y=y/1
58
+ return np.array([x, y])
59
+ except:
60
+ return np.array([0, 0]) # Return [0, 0] if landmark is not detected
61
+
62
+ mp_pose = mp.solutions.pose
63
+ pose = mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5)
64
+ mp_drawing = mp.solutions.drawing_utils
65
+
66
+ def calculate_angles_landmarks(landmarks):
67
+ # Left side angles
68
+ left_shoulder = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.LEFT_SHOULDER)
69
+ left_elbow = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.LEFT_ELBOW)
70
+ left_wrist = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.LEFT_WRIST)
71
+ #
72
+ right_shoulder = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.RIGHT_SHOULDER)
73
+ right_elbow = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.RIGHT_ELBOW)
74
+ right_wrist = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.RIGHT_WRIST)
75
+ #
76
+ left_hip = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.LEFT_HIP)
77
+ left_knee = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.LEFT_KNEE)
78
+ #
79
+ right_hip = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.RIGHT_HIP)
80
+ right_knee = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.RIGHT_KNEE)
81
+ #
82
+ left_ankle = get_landmark_coordinates(landmarks,mp_pose.PoseLandmark.LEFT_ANKLE)
83
+ right_ankle = get_landmark_coordinates(landmarks,mp_pose.PoseLandmark.RIGHT_ANKLE)
84
+ #
85
+
86
+ if np.any(left_shoulder) and np.any(left_elbow) and np.any(left_wrist):
87
+ left_elbow_angle = calculate_angle(left_shoulder, left_elbow, left_wrist)
88
+ else: left_elbow_angle = 0
89
+
90
+ if np.any(left_shoulder) and np.any(left_hip) and np.any(left_knee):
91
+ left_hip_angle = calculate_angle(left_shoulder, left_hip, left_knee)
92
+ else: left_hip_angle = 0
93
+
94
+ if np.any(right_shoulder) and np.any(right_elbow) and np.any(right_wrist):
95
+ right_elbow_angle = calculate_angle(right_shoulder, right_elbow, right_wrist)
96
+ else: right_elbow_angle = 0
97
+
98
+ if np.any(right_shoulder) and np.any(right_hip) and np.any(right_knee):
99
+ right_hip_angle = calculate_angle(right_shoulder, right_hip, right_knee)
100
+ else: right_hip_angle = 0
101
+
102
+ if np.any(right_knee) and np.any(right_ankle) and np.any(right_hip):
103
+ right_knee_angle = calculate_angle(right_knee, right_ankle, right_hip)
104
+ else: right_knee_angle = 0
105
+
106
+ if np.any(left_knee) and np.any(left_ankle) and np.any(left_hip):
107
+ left_knee_angle = calculate_angle(left_knee, left_ankle, left_hip)
108
+ else: left_knee_angle = 0
109
+
110
+
111
+ # Additional angles (e.g., shoulders, knees, etc.)
112
+ head0 = 0
113
+ num = 0
114
+ head = get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.NOSE)
115
+ if not np.array_equal(head, head0): num += 1
116
+ head0 = head
117
+
118
+ head += get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.RIGHT_EYE)
119
+ if (head[0]==head0[0]) & (head[1]==head0[1]): num += 1
120
+ head0 = head
121
+
122
+ head += get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.LEFT_EYE)
123
+ if (head[0]==head0[0]) & (head[1]==head0[1]): num += 1
124
+ head0 = head
125
+
126
+ head += get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.RIGHT_EAR)
127
+ if (head[0]==head0[0]) & (head[1]==head0[1]): num += 1
128
+ head0 = head
129
+
130
+ head += get_landmark_coordinates(landmarks, mp_pose.PoseLandmark.LEFT_EAR)
131
+ if (head[0]==head0[0]) & (head[1]==head0[1]): num += 1
132
+ head0 = head
133
+
134
+ head /= num
135
+
136
+ if np.any(head) and np.any(left_shoulder) and np.any(left_elbow):
137
+ left_arm_angle = calculate_angle(head, left_shoulder, left_elbow)
138
+ else:
139
+ left_arm_angle = 0
140
+
141
+ if np.any(head) and np.any(right_shoulder) and np.any(right_elbow):
142
+ right_arm_angle = calculate_angle(head, right_shoulder, right_elbow)
143
+ else:
144
+ right_arm_angle = 0
145
+
146
+ if np.any(head) and np.any(left_shoulder) and np.any(left_hip):
147
+ left_back_angle = calculate_angle(head, left_shoulder, left_hip)
148
+ else:
149
+ left_back_angle = 0
150
+
151
+ if np.any(head) and np.any(right_shoulder) and np.any(right_hip):
152
+ right_back_angle = calculate_angle(head, right_shoulder, right_hip)
153
+ else:
154
+ right_back_angle = 0
155
+ ###############
156
+ angles = {
157
+ "left_elbow_angle": left_elbow_angle,
158
+ "left_hip_angle": left_hip_angle,
159
+ "right_elbow_angle": right_elbow_angle,
160
+ "right_hip_angle": right_hip_angle,
161
+ "left_arm_angle": left_arm_angle,
162
+ "right_arm_angle": right_arm_angle,
163
+ "left_back_angle": left_back_angle,
164
+ "right_back_angle": right_back_angle,
165
+ "left_knee_angle": left_knee_angle,
166
+ "right_knee_angle": right_knee_angle
167
+ }
168
+
169
+ locations={
170
+ "left_shoulder":left_shoulder,
171
+ "left_elbow":left_elbow,
172
+ "left_wrist":left_wrist,
173
+ "right_shoulder":right_shoulder,
174
+ "right_elbow":right_elbow,
175
+ "right_wrist":right_wrist,
176
+
177
+ "head":head,
178
+
179
+ "left_hip":left_hip,
180
+ "left_knee":left_knee,
181
+ "left_ankle":left_ankle,
182
+
183
+ "right_hip":right_hip,
184
+ "right_knee":right_knee,
185
+ "right_ankle":right_ankle
186
+ }
187
+ return angles,locations
188
+
189
+ # Function to calculate the angles for both left and right sides and overlay on image
190
+ def calculate_and_display_angles(image_path, return_angles=False):
191
+ mp_pose = mp.solutions.pose
192
+ pose = mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5)
193
+
194
+ image = cv2.imread(image_path)
195
+ image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
196
+
197
+ # Get pose landmarks
198
+ results = pose.process(image_rgb)
199
+
200
+ if results.pose_landmarks:
201
+ # landmarks = results.pose_landmarks
202
+ ########
203
+ ang , locs = calculate_angles_landmarks(results.pose_landmarks)
204
+
205
+ #if only angles needed
206
+ if return_angles:
207
+ return ang
208
+
209
+ # Draw the pose landmarks on the image
210
+ mp_drawing = mp.solutions.drawing_utils
211
+ mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
212
+
213
+ # Display the angle values at corresponding locations
214
+ def overlay_angle(angle, location, color=(0, 255, 0)):
215
+ # Coordinates are normalized, scale them to the image size
216
+ x = int(location[0] * image.shape[1])
217
+ y = int(location[1] * image.shape[0])
218
+ cv2.putText(image, f'{angle:.2f}', (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.3, color, 1)
219
+
220
+ # Overlay angles on the image
221
+ if np.any(ang['left_elbow_angle']!=0):
222
+ overlay_angle(ang['left_elbow_angle'], locs['left_elbow'], (0, 255, 0)) # Left elbow angle
223
+ if np.any(ang['right_elbow_angle']!=0):
224
+ overlay_angle(ang['right_elbow_angle'], locs['right_elbow'], (0, 255, 0)) # Right elbow angle
225
+ if np.any(ang['left_hip_angle']!=0):
226
+ overlay_angle(ang['left_hip_angle'], locs['left_hip'], (0, 255, 0)) # Left hip angle
227
+ if np.any(ang['right_hip_angle']!=0):
228
+ overlay_angle(ang['right_hip_angle'], locs['right_hip'], (0, 255, 0)) # Right hip angle
229
+ if np.any(ang['left_arm_angle']!=0):
230
+ overlay_angle(ang['left_arm_angle'], (locs['left_shoulder']
231
+ + locs['left_elbow'])/2, (0, 255, 0)) # Left arm angle
232
+ if np.any(ang['right_arm_angle']!=0):
233
+ overlay_angle(ang['right_arm_angle'], (locs['right_shoulder']
234
+ + locs['right_elbow'])/2, (0, 255, 0))
235
+ if np.any(ang['left_back_angle']!=0):
236
+ overlay_angle(ang['left_back_angle'], locs['left_shoulder'], (0, 255, 0)) # Left back angle
237
+ if np.any(ang['right_back_angle']!=0):
238
+ overlay_angle(ang['right_back_angle'], locs['right_shoulder'], (0, 255, 0)) # Right back angle
239
+
240
+ if np.any(ang['left_knee_angle']!=0):
241
+ overlay_angle(ang['left_knee_angle'], locs['left_knee'], (0, 255, 0)) # Left knee angle
242
+
243
+ if np.any(ang['right_knee_angle']!=0):
244
+ overlay_angle(ang['right_knee_angle'], locs['right_knee'], (0, 255, 0)) # Right knee angle
245
+
246
+ # Return the image with the overlayed angles
247
+ return image
248
+ else:
249
+ return None
250
+ ###
251
+
252
+
253
+
254
+
255
+ ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
256
+ def allowed_file(filename):
257
+ return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
258
+ app = Flask(__name__)
259
+ run_with_ngrok(app) # This will use ngrok for the server
260
+
261
+ @app.route('/')
262
+ def hello():
263
+ return 'Hello, World!'
264
+
265
+ @app.route('/1', methods=['POST'])
266
+ def upload_file():
267
+ if 'image' not in request.files:
268
+ return {"message": "No file part"}, 400
269
+ file = request.files['image']
270
+ if file.filename == '':
271
+ return {"message": "No selected file"}, 400
272
+
273
+ # send file with angles on image or just angles
274
+ if file and allowed_file(file.filename):
275
+ try:
276
+ file.seek(0)
277
+ mime_type, _ = mimetypes.guess_type(file.filename)
278
+
279
+ return send_file(
280
+ BytesIO(file.read()), mimetype=mime_type,
281
+ as_attachment=False, download_name=file.filename
282
+ )
283
+
284
+ except Exception as e:
285
+ return {"message": f"Error processing file: {str(e)}"}, 500
286
+ return {"message": "File not allowed"}, 400
287
+
288
+
289
+ if __name__ == '__main__':
290
+ app.run()
requirements.txt ADDED
Binary file (8.63 kB). View file