Tantawi commited on
Commit
65cb21e
·
verified ·
1 Parent(s): 9de57c4

Upload 3 files

Browse files
Files changed (3) hide show
  1. efficientnetv2s.h5 +3 -0
  2. main.py +121 -0
  3. requirements.txt +6 -0
efficientnetv2s.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c2da0b93a32a2f206e8e437f4a516720bcda36693b9f5f054e5387a701131119
3
+ size 247255104
main.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, UploadFile, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from fastapi.responses import JSONResponse
4
+ import tensorflow as tf
5
+ import numpy as np
6
+ from PIL import Image
7
+ import os
8
+ import uuid
9
+ import tempfile
10
+
11
+ app = FastAPI(
12
+ title="Medical Image Classification API",
13
+ description="AI-powered medical image classification service",
14
+ version="1.0.0"
15
+ )
16
+
17
+ app.add_middleware(
18
+ CORSMiddleware,
19
+ allow_origins=["*"],
20
+ allow_credentials=True,
21
+ allow_methods=["*"],
22
+ allow_headers=["*"],
23
+ )
24
+
25
+ model = None
26
+ class_names = {
27
+ 0: "AKIEC", # Actinic keratoses and intraepithelial carcinoma
28
+ 1: "BCC", # Basal cell carcinoma
29
+ 2: "BKL", # Benign keratosis-like lesions
30
+ 3: "DF", # Dermatofibroma
31
+ 4: "MEL", # Melanoma
32
+ 5: "NV", # Melanocytic nevi
33
+ 6: "VASC" # Vascular lesions
34
+ }
35
+ full_names = {
36
+ "AKIEC": "Actinic keratoses and intraepithelial carcinoma",
37
+ "BCC": "Basal cell carcinoma",
38
+ "BKL": "Benign keratosis-like lesions",
39
+ "DF": "Dermatofibroma",
40
+ "MEL": "Melanoma",
41
+ "NV": "Melanocytic nevi",
42
+ "VASC": "Vascular lesions"
43
+ }
44
+ UPLOAD_DIR = tempfile.mkdtemp()
45
+
46
+ def load_model():
47
+ global model
48
+ model_path = "efficientnetv2s.h5"
49
+ if not os.path.exists(model_path):
50
+ raise FileNotFoundError(f"Model file not found: {model_path}")
51
+ model = tf.keras.models.load_model(model_path)
52
+ return model
53
+
54
+ def predict_image(image_path):
55
+ global model
56
+ if model is None:
57
+ model = load_model()
58
+ img = Image.open(image_path).convert('RGB')
59
+ img = img.resize((224, 224))
60
+ img_array = np.array(img)
61
+ img_array = np.expand_dims(img_array, axis=0)
62
+ img_array = img_array.astype(np.float32) / 255.0
63
+ predictions = model.predict(img_array)
64
+ predicted_class = np.argmax(predictions[0])
65
+ confidence = float(predictions[0][predicted_class])
66
+ class_code = class_names[predicted_class]
67
+ class_full_name = full_names[class_code]
68
+ all_predictions = []
69
+ for i, prob in enumerate(predictions[0]):
70
+ all_predictions.append({
71
+ "label": class_names[i],
72
+ "confidence": float(prob)
73
+ })
74
+ all_predictions.sort(key=lambda x: x["confidence"], reverse=True)
75
+ return class_full_name, confidence, all_predictions
76
+
77
+ @app.get("/health")
78
+ async def health_check():
79
+ return {"status": "healthy", "service": "medical-image-classifier"}
80
+
81
+ @app.post("/api/classify")
82
+ async def classify_image_api(file: UploadFile = File(...)):
83
+ try:
84
+ if not file.content_type or not file.content_type.startswith('image/'):
85
+ raise HTTPException(status_code=400, detail="File must be an image")
86
+ unique_filename = f"{uuid.uuid4().hex}_{file.filename}"
87
+ file_path = os.path.join(UPLOAD_DIR, unique_filename)
88
+ with open(file_path, "wb") as buffer:
89
+ content = await file.read()
90
+ buffer.write(content)
91
+ label, confidence, all_predictions = predict_image(file_path)
92
+ os.remove(file_path)
93
+ formatted_predictions = []
94
+ for pred in all_predictions:
95
+ formatted_predictions.append({
96
+ "label": pred["label"],
97
+ "confidence": float(pred["confidence"]),
98
+ "confidence_percent": f"{pred['confidence'] * 100:.2f}%"
99
+ })
100
+ return JSONResponse(
101
+ status_code=200,
102
+ content={
103
+ "success": True,
104
+ "prediction": {
105
+ "top_prediction": {
106
+ "label": label,
107
+ "confidence": float(confidence),
108
+ "confidence_percent": f"{confidence * 100:.2f}%"
109
+ },
110
+ "all_predictions": formatted_predictions
111
+ }
112
+ }
113
+ )
114
+ except Exception as e:
115
+ if 'file_path' in locals() and os.path.exists(file_path):
116
+ os.remove(file_path)
117
+ raise HTTPException(status_code=500, detail=f"Classification failed: {str(e)}")
118
+
119
+ if __name__ == "__main__":
120
+ import uvicorn
121
+ uvicorn.run(app, host="0.0.0.0", port=8003)
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ fastapi==0.104.1
2
+ uvicorn[standard]==0.24.0
3
+ tensorflow==2.10.0
4
+ numpy==1.21.6
5
+ Pillow==9.4.0
6
+ python-multipart==0.0.5