Hussein El-Hadidy commited on
Commit
ef22c1c
·
1 Parent(s): 8ed1da1

Updated Burns

Browse files
Files changed (3) hide show
  1. SkinBurns_Classification.py +4 -19
  2. app.py +10 -129
  3. svm_model.pkl +2 -2
SkinBurns_Classification.py CHANGED
@@ -129,24 +129,9 @@ def FullFeautures(pathF):
129
 
130
  fv = []
131
 
132
- # split color histogram into two halves and extend
133
- _cl = len(ch)
134
- fv.extend(ch[:_cl//2])
135
- fv.extend(ch[_cl//2:])
136
-
137
- # split LBP histogram into two halves and extend
138
- _ll = len(lbph)
139
- fv.extend(lbph[:_ll//2])
140
- fv.extend(lbph[_ll//2:])
141
-
142
- # split GLCM features into two halves and extend
143
- _gl = len(glc)
144
- fv.extend(glc[:_gl//2])
145
- fv.extend(glc[_gl//2:])
146
-
147
- # split Hu moments into two halves and extend
148
- _hl = len(hu)
149
- fv.extend(hu[:_hl//2])
150
- fv.extend(hu[_hl//2:])
151
 
152
  return _np.array(fv)
 
129
 
130
  fv = []
131
 
132
+ fv.extend(ch)
133
+ fv.extend(lbph)
134
+ fv.extend(glc)
135
+ fv.extend(hu)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
 
137
  return _np.array(fv)
app.py CHANGED
@@ -44,8 +44,8 @@ import signal
44
 
45
  app = FastAPI()
46
 
47
- SCREENSHOTS_DIR = "screenshots" # Folder containing screenshots to upload
48
- OUTPUT_DIR = "Output" # Folder containing the .mp4 video and graph .png
49
  UPLOAD_DIR = "uploads"
50
  os.makedirs(UPLOAD_DIR, exist_ok=True)
51
 
@@ -59,7 +59,7 @@ except Exception as e:
59
 
60
 
61
 
62
- # Cloudinary config
63
  cloudinary.config(
64
  cloud_name = "darumyfpl",
65
  api_key = "493972437417214",
@@ -75,30 +75,21 @@ def greet_json():
75
  @app.post("/predict_burn")
76
  async def predict_burn(file: UploadFile = File(...)):
77
  try:
78
- # Save the uploaded file temporarily
79
  temp_file_path = f"temp_{file.filename}"
80
  with open(temp_file_path, "wb") as temp_file:
81
  temp_file.write(await file.read())
82
 
 
83
 
84
- # Load the saved SVM model
85
- with open('svm_model.pkl', 'rb') as model_file:
86
- loaded_svm = pickle.load(model_file)
87
-
88
- # Extract features from the uploaded image
89
  features = FullFeautures(temp_file_path)
90
 
91
- # Remove the temporary file
92
  os.remove(temp_file_path)
93
 
94
  if features is None:
95
  return JSONResponse(content={"error": "Failed to extract features from the image."}, status_code=400)
96
 
97
- # Reshape features to match the SVM model's expected input
98
- features = features.reshape(1, -1)
99
-
100
- # Predict the class
101
- prediction = loaded_svm.predict(features)
102
  prediction_label = "Burn" if prediction[0] == 1 else "No Burn"
103
 
104
  if prediction[0] == 1:
@@ -118,22 +109,18 @@ async def predict_burn(file: UploadFile = File(...)):
118
  @app.post("/segment_burn")
119
  async def segment_burn_endpoint(reference: UploadFile = File(...), patient: UploadFile = File(...)):
120
  try:
121
- # Save the reference image temporarily
122
  reference_path = f"temp_ref_{reference.filename}"
123
  reference_bytes = await reference.read()
124
  with open(reference_path, "wb") as ref_file:
125
  ref_file.write(reference_bytes)
126
 
127
- # Save the patient image temporarily
128
  patient_path = f"temp_patient_{patient.filename}"
129
  patient_bytes = await patient.read()
130
  with open(patient_path, "wb") as pat_file:
131
  pat_file.write(patient_bytes)
132
 
133
- # Call the segmentation logic
134
  burn_crop_clean, burn_crop_debug = segment_burn(patient_path, reference_path)
135
 
136
- # Save the cropped outputs
137
  burn_crop_clean_path = f"temp_burn_crop_clean_{uuid.uuid4()}.png"
138
  burn_crop_debug_path = f"temp_burn_crop_debug_{uuid.uuid4()}.png"
139
 
@@ -141,13 +128,10 @@ async def segment_burn_endpoint(reference: UploadFile = File(...), patient: Uplo
141
  plt.imsave(burn_crop_clean_path, burn_crop_clean)
142
  plt.imsave(burn_crop_debug_path, burn_crop_debug)
143
 
144
- # Upload to Cloudinary
145
  crop_clean_upload = cloudinary.uploader.upload(burn_crop_clean_path, public_id=f"ref_{reference.filename}")
146
  crop_debug_upload = cloudinary.uploader.upload(burn_crop_debug_path, public_id=f"pat_{patient.filename}")
147
  crop_clean_url = crop_clean_upload["secure_url"]
148
  crop_debug_url = crop_debug_upload["secure_url"]
149
-
150
- # Clean up temp files
151
 
152
  os.remove(burn_crop_clean_path)
153
  os.remove(burn_crop_debug_path)
@@ -165,18 +149,14 @@ async def segment_burn_endpoint(reference: UploadFile = File(...), patient: Uplo
165
  @app.post("/classify-ecg")
166
  async def classify_ecg_endpoint(file: UploadFile = File(...)):
167
  model = joblib.load('voting_classifier.pkl')
168
- # Load the model
169
 
170
  try:
171
- # Save the uploaded file temporarily
172
  temp_file_path = f"temp_{file.filename}"
173
  with open(temp_file_path, "wb") as temp_file:
174
  temp_file.write(await file.read())
175
 
176
- # Call the ECG classification function
177
  result = classify_ecg(temp_file_path, model, debug=True, is_pdf=True)
178
 
179
- # Remove the temporary file
180
  os.remove(temp_file_path)
181
 
182
  return {"result": result}
@@ -220,14 +200,11 @@ async def diagnose_ecg(file: UploadFile = File(...)):
220
 
221
 
222
  def clean_warning_name(filename: str) -> str:
223
- """
224
- Remove frame index and underscores from filename base
225
- E.g. "posture_001.png" -> "posture"
226
- """
227
  name, _ = os.path.splitext(filename)
228
- # Remove trailing underscore + digits
229
  cleaned = re.sub(r'_\d+$', '', name)
230
- # Remove all underscores in the name for description
231
  cleaned_desc = cleaned.replace('_', ' ')
232
  return cleaned, cleaned_desc
233
 
@@ -253,27 +230,22 @@ async def process_video(file: UploadFile = File(...)):
253
  if os.path.isfile(file_path):
254
  os.remove(file_path)
255
 
256
- # Save uploaded video file
257
  video_path = os.path.join(UPLOAD_DIR, file.filename)
258
  with open(video_path, "wb") as buffer:
259
  shutil.copyfileobj(file.file, buffer)
260
 
261
  print(f"\n[API] CPR Analysis Started on {video_path}")
262
 
263
- # Prepare output paths for the analyzer
264
  video_output_path = os.path.join(OUTPUT_DIR, "Myoutput.mp4")
265
  plot_output_path = os.path.join(OUTPUT_DIR, "Myoutput.png")
266
 
267
- # Initialize analyzer with input video and output paths
268
  start_time = time.time()
269
  analyzer = OfflineAnalyzer(video_path, video_output_path, plot_output_path, requested_fps=30)
270
 
271
- # Run the analysis (choose your method)
272
  chunks = analyzer.run_analysis_video()
273
 
274
- warnings = [] # Start empty list
275
 
276
- # Upload screenshots and build warnings list with descriptions and URLs
277
  if os.path.exists(SCREENSHOTS_DIR):
278
  for filename in os.listdir(SCREENSHOTS_DIR):
279
  if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
@@ -333,97 +305,6 @@ async def process_video(file: UploadFile = File(...)):
333
  })
334
 
335
 
336
- # @app.websocket("/ws/process_video")
337
- # async def websocket_process_video(websocket: WebSocket):
338
-
339
- # await websocket.accept()
340
-
341
- # frame_buffer = []
342
- # frame_limit = 50
343
- # frame_size = (640, 480) # Adjust if needed
344
- # fps = 30 # Adjust if needed
345
- # loop = asyncio.get_event_loop()
346
-
347
- # # Progress reporting during analysis
348
- # async def progress_callback(data):
349
- # await websocket.send_text(json.dumps(data))
350
-
351
- # def sync_callback(data):
352
- # asyncio.run_coroutine_threadsafe(progress_callback(data), loop)
353
-
354
- # def save_frames_to_video(frames, path):
355
- # out = cv2.VideoWriter(path, cv2.VideoWriter_fourcc(*'mp4v'), fps, frame_size)
356
- # for frame in frames:
357
- # resized = cv2.resize(frame, frame_size)
358
- # out.write(resized)
359
- # out.release()
360
-
361
- # def run_analysis_on_buffer(frames):
362
- # try:
363
- # tmp_path = "temp_video.mp4"
364
- # save_frames_to_video(frames, tmp_path)
365
-
366
- # # Notify: video saved
367
- # asyncio.run_coroutine_threadsafe(
368
- # websocket.send_text(json.dumps({
369
- # "status": "info",
370
- # "message": "Video saved. Starting CPR analysis..."
371
- # })),
372
- # loop
373
- # )
374
-
375
- # # Run analysis
376
- # analyzer = CPRAnalyzer(video_path=tmp_path)
377
- # analyzer.run_analysis(progress_callback=sync_callback)
378
-
379
- # except Exception as e:
380
- # asyncio.run_coroutine_threadsafe(
381
- # websocket.send_text(json.dumps({"error": str(e)})),
382
- # loop
383
- # )
384
-
385
- # try:
386
- # while True:
387
- # data: bytes = await websocket.receive_bytes()
388
- # np_arr = np.frombuffer(data, np.uint8)
389
- # frame = cv2.imdecode(np_arr, cv2.IMREAD_COLOR)
390
- # if frame is None:
391
- # continue
392
-
393
- # frame_buffer.append(frame)
394
- # print(f"Frame added to buffer: {len(frame_buffer)}")
395
-
396
- # if len(frame_buffer) == frame_limit:
397
- # # Notify Flutter that we're switching to processing
398
- # await websocket.send_text(json.dumps({
399
- # "status": "ready",
400
- # "message": "Prepare Right CPR: First 150 frames received. Starting processing."
401
- # }))
402
-
403
- # # Copy and clear buffer
404
- # buffer_copy = frame_buffer[:]
405
- # frame_buffer.clear()
406
-
407
- # # Launch background processing
408
- # executor = concurrent.futures.ThreadPoolExecutor()
409
- # loop.run_in_executor(executor, run_analysis_on_buffer, buffer_copy)
410
- # else:
411
- # # Tell Flutter to send the next frame
412
- # await websocket.send_text(json.dumps({
413
- # "status": "continue",
414
- # "message": f"Frame {len(frame_buffer)} received. Send next."
415
- # }))
416
-
417
- # except WebSocketDisconnect:
418
- # print("Client disconnected")
419
-
420
- # except Exception as e:
421
- # await websocket.send_text(json.dumps({"error": str(e)}))
422
-
423
- # finally:
424
- # cv2.destroyAllWindows()
425
-
426
-
427
  logger = logging.getLogger("cpr_logger")
428
  clients = set()
429
  analyzer_thread = None
 
44
 
45
  app = FastAPI()
46
 
47
+ SCREENSHOTS_DIR = "screenshots"
48
+ OUTPUT_DIR = "Output"
49
  UPLOAD_DIR = "uploads"
50
  os.makedirs(UPLOAD_DIR, exist_ok=True)
51
 
 
59
 
60
 
61
 
62
+ # Cloudinary config
63
  cloudinary.config(
64
  cloud_name = "darumyfpl",
65
  api_key = "493972437417214",
 
75
  @app.post("/predict_burn")
76
  async def predict_burn(file: UploadFile = File(...)):
77
  try:
 
78
  temp_file_path = f"temp_{file.filename}"
79
  with open(temp_file_path, "wb") as temp_file:
80
  temp_file.write(await file.read())
81
 
82
+ loaded_svm = joblib.load('svm_model.pkl')
83
 
84
+ print("SVM model loaded successfully")
 
 
 
 
85
  features = FullFeautures(temp_file_path)
86
 
 
87
  os.remove(temp_file_path)
88
 
89
  if features is None:
90
  return JSONResponse(content={"error": "Failed to extract features from the image."}, status_code=400)
91
 
92
+ prediction = loaded_svm.predict(features.reshape(1, -1))
 
 
 
 
93
  prediction_label = "Burn" if prediction[0] == 1 else "No Burn"
94
 
95
  if prediction[0] == 1:
 
109
  @app.post("/segment_burn")
110
  async def segment_burn_endpoint(reference: UploadFile = File(...), patient: UploadFile = File(...)):
111
  try:
 
112
  reference_path = f"temp_ref_{reference.filename}"
113
  reference_bytes = await reference.read()
114
  with open(reference_path, "wb") as ref_file:
115
  ref_file.write(reference_bytes)
116
 
 
117
  patient_path = f"temp_patient_{patient.filename}"
118
  patient_bytes = await patient.read()
119
  with open(patient_path, "wb") as pat_file:
120
  pat_file.write(patient_bytes)
121
 
 
122
  burn_crop_clean, burn_crop_debug = segment_burn(patient_path, reference_path)
123
 
 
124
  burn_crop_clean_path = f"temp_burn_crop_clean_{uuid.uuid4()}.png"
125
  burn_crop_debug_path = f"temp_burn_crop_debug_{uuid.uuid4()}.png"
126
 
 
128
  plt.imsave(burn_crop_clean_path, burn_crop_clean)
129
  plt.imsave(burn_crop_debug_path, burn_crop_debug)
130
 
 
131
  crop_clean_upload = cloudinary.uploader.upload(burn_crop_clean_path, public_id=f"ref_{reference.filename}")
132
  crop_debug_upload = cloudinary.uploader.upload(burn_crop_debug_path, public_id=f"pat_{patient.filename}")
133
  crop_clean_url = crop_clean_upload["secure_url"]
134
  crop_debug_url = crop_debug_upload["secure_url"]
 
 
135
 
136
  os.remove(burn_crop_clean_path)
137
  os.remove(burn_crop_debug_path)
 
149
  @app.post("/classify-ecg")
150
  async def classify_ecg_endpoint(file: UploadFile = File(...)):
151
  model = joblib.load('voting_classifier.pkl')
 
152
 
153
  try:
 
154
  temp_file_path = f"temp_{file.filename}"
155
  with open(temp_file_path, "wb") as temp_file:
156
  temp_file.write(await file.read())
157
 
 
158
  result = classify_ecg(temp_file_path, model, debug=True, is_pdf=True)
159
 
 
160
  os.remove(temp_file_path)
161
 
162
  return {"result": result}
 
200
 
201
 
202
  def clean_warning_name(filename: str) -> str:
203
+
 
 
 
204
  name, _ = os.path.splitext(filename)
205
+
206
  cleaned = re.sub(r'_\d+$', '', name)
207
+
208
  cleaned_desc = cleaned.replace('_', ' ')
209
  return cleaned, cleaned_desc
210
 
 
230
  if os.path.isfile(file_path):
231
  os.remove(file_path)
232
 
 
233
  video_path = os.path.join(UPLOAD_DIR, file.filename)
234
  with open(video_path, "wb") as buffer:
235
  shutil.copyfileobj(file.file, buffer)
236
 
237
  print(f"\n[API] CPR Analysis Started on {video_path}")
238
 
 
239
  video_output_path = os.path.join(OUTPUT_DIR, "Myoutput.mp4")
240
  plot_output_path = os.path.join(OUTPUT_DIR, "Myoutput.png")
241
 
 
242
  start_time = time.time()
243
  analyzer = OfflineAnalyzer(video_path, video_output_path, plot_output_path, requested_fps=30)
244
 
 
245
  chunks = analyzer.run_analysis_video()
246
 
247
+ warnings = []
248
 
 
249
  if os.path.exists(SCREENSHOTS_DIR):
250
  for filename in os.listdir(SCREENSHOTS_DIR):
251
  if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
 
305
  })
306
 
307
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  logger = logging.getLogger("cpr_logger")
309
  clients = set()
310
  analyzer_thread = None
svm_model.pkl CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:acf55c90d6a4067d1a83c0e15764fb47b0197a1f2cfa2abccb580260eff0316a
3
- size 337615
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2fefa4a94a2c6b329e1b5cfe0f61959489ed5d582835cf0c44a141eca980acbf
3
+ size 503059