morefaat69 commited on
Commit
286fde8
·
verified ·
1 Parent(s): ecc01cb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +14 -62
app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  from fastapi import FastAPI, APIRouter, UploadFile, File, Request
2
  from fastapi.staticfiles import StaticFiles
3
  import shutil
@@ -5,52 +6,37 @@ import os
5
  import cv2
6
  import base64
7
  from ultralytics import YOLO
8
-
9
- # ─── Load Models ──────────────────────────────────────────────────────────────
10
- person_model = YOLO("yolov8m.pt") # n→m: أدق بكثير في كشف أشخاص صغيرة/بعيدة
11
  statue_model = YOLO("best.pt")
12
-
13
- # ─── App Setup ────────────────────────────────────────────────────────────────
14
  app = FastAPI()
15
-
16
  UPLOAD_FOLDER = "/tmp/uploads"
17
  os.makedirs(UPLOAD_FOLDER, exist_ok=True)
18
-
19
  app.mount("/uploads", StaticFiles(directory=UPLOAD_FOLDER), name="uploads")
20
-
21
- CONF_THRESHOLD = 0.40
22
-
23
  router = APIRouter()
24
-
25
-
26
  def draw_label(image, label, x1, y1, x2, y2, box_color, text_color):
27
- """ارسم الـ label فوق الـ box، ولو مفيش مكان فوق حطه تحت"""
28
  font = cv2.FONT_HERSHEY_SIMPLEX
29
  font_scale = 0.6
30
  thickness = 2
31
-
32
  (tw, th), _ = cv2.getTextSize(label, font, font_scale, thickness)
33
-
34
- # لو فيه مكان فوق الـ box
35
  if y1 - th - 8 >= 0:
36
  label_y1 = y1 - th - 8
37
  label_y2 = y1
38
  text_y = y1 - 5
39
  else:
40
- # حط الـ label جوه الـ box من فوق
41
  label_y1 = y1
42
  label_y2 = y1 + th + 8
43
  text_y = y1 + th + 3
44
-
45
  cv2.rectangle(image, (x1, label_y1), (x1 + tw + 4, label_y2), box_color, -1)
46
  cv2.putText(image, label, (x1 + 2, text_y), font, font_scale, text_color, thickness)
47
-
48
-
49
  @app.get("/")
50
  def root():
51
  return {"message": "AI API is running 🚀"}
52
-
53
-
54
  @router.post("/predict-image")
55
  async def predict_image(
56
  request: Request,
@@ -58,43 +44,27 @@ async def predict_image(
58
  ):
59
  safe_filename = file.filename.replace(" ", "_")
60
  file_path = os.path.join(UPLOAD_FOLDER, safe_filename)
61
-
62
  with open(file_path, "wb") as buffer:
63
  shutil.copyfileobj(file.file, buffer)
64
-
65
  image = cv2.imread(file_path)
66
-
67
  if image is None:
68
  return {"error": "Invalid image"}
69
-
70
  detections = []
71
  person_count = 0
72
  statue_count = 0
73
-
74
- # ── Person Detection ──────────────────────────────────────────────────────
75
- person_results = person_model(
76
- file_path,
77
- imgsz=1280, # تكبير دقة المعالجة الداخلية → يكشف أشخاص أصغر/أبعد
78
- conf=CONF_THRESHOLD,
79
- iou=0.45, # يمنع لغي boxes متقاربة بالغلط (أشخاص جنب بعض)
80
- max_det=300 # يسمح باكتشاف عدد أكبر من الأشخاص بدل القطع عند حد معين
81
- )
82
-
83
  for box in person_results[0].boxes:
84
  cls_id = int(box.cls)
85
  if cls_id != 0:
86
  continue
87
-
88
  conf = float(box.conf)
89
  if conf < CONF_THRESHOLD:
90
  continue
91
-
92
  x1, y1, x2, y2 = map(int, box.xyxy[0])
93
-
94
  cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
95
  draw_label(image, f"Person {conf:.2f}", x1, y1, x2, y2,
96
  box_color=(0, 255, 0), text_color=(0, 0, 0))
97
-
98
  detections.append({
99
  "type": "person",
100
  "name": "Person",
@@ -102,30 +72,18 @@ async def predict_image(
102
  "bbox": [x1, y1, x2, y2]
103
  })
104
  person_count += 1
105
-
106
- # ── Statue Detection ──────────────────────────────────────────────────────
107
- statue_results = statue_model(
108
- file_path,
109
- imgsz=1280,
110
- conf=CONF_THRESHOLD,
111
- iou=0.45,
112
- max_det=300
113
- )
114
-
115
  for box in statue_results[0].boxes:
116
  conf = float(box.conf)
117
  if conf < CONF_THRESHOLD:
118
  continue
119
-
120
  cls_id = int(box.cls)
121
  statue_name = statue_results[0].names[cls_id]
122
-
123
  x1, y1, x2, y2 = map(int, box.xyxy[0])
124
-
125
  cv2.rectangle(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
126
  draw_label(image, f"{statue_name} {conf:.2f}", x1, y1, x2, y2,
127
  box_color=(0, 0, 255), text_color=(255, 255, 255))
128
-
129
  detections.append({
130
  "type": "statue",
131
  "name": statue_name,
@@ -133,17 +91,13 @@ async def predict_image(
133
  "bbox": [x1, y1, x2, y2]
134
  })
135
  statue_count += 1
136
-
137
- # ── Save Output Image ─────────────────────────────────────────────────────
138
  output_filename = f"output_{safe_filename}"
139
  output_path = os.path.join(UPLOAD_FOLDER, output_filename)
140
  cv2.imwrite(output_path, image)
141
-
142
  with open(output_path, "rb") as img_file:
143
  image_base64 = base64.b64encode(img_file.read()).decode("utf-8")
144
-
145
  image_url = f"{request.base_url}uploads/{output_filename}"
146
-
147
  return {
148
  "total_count": len(detections),
149
  "persons": person_count,
@@ -152,6 +106,4 @@ async def predict_image(
152
  "output_image_base64": f"data:image/jpeg;base64,{image_base64}",
153
  "detections": detections
154
  }
155
-
156
-
157
- app.include_router(router)
 
1
+
2
  from fastapi import FastAPI, APIRouter, UploadFile, File, Request
3
  from fastapi.staticfiles import StaticFiles
4
  import shutil
 
6
  import cv2
7
  import base64
8
  from ultralytics import YOLO
9
+ # ─── Load Models
10
+ person_model = YOLO("yolov8n.pt")
 
11
  statue_model = YOLO("best.pt")
12
+ # ─── App Setup
 
13
  app = FastAPI()
 
14
  UPLOAD_FOLDER = "/tmp/uploads"
15
  os.makedirs(UPLOAD_FOLDER, exist_ok=True)
 
16
  app.mount("/uploads", StaticFiles(directory=UPLOAD_FOLDER), name="uploads")
17
+ CONF_THRESHOLD = 0.30
 
 
18
  router = APIRouter()
 
 
19
  def draw_label(image, label, x1, y1, x2, y2, box_color, text_color):
20
+
21
  font = cv2.FONT_HERSHEY_SIMPLEX
22
  font_scale = 0.6
23
  thickness = 2
 
24
  (tw, th), _ = cv2.getTextSize(label, font, font_scale, thickness)
25
+
 
26
  if y1 - th - 8 >= 0:
27
  label_y1 = y1 - th - 8
28
  label_y2 = y1
29
  text_y = y1 - 5
30
  else:
31
+
32
  label_y1 = y1
33
  label_y2 = y1 + th + 8
34
  text_y = y1 + th + 3
 
35
  cv2.rectangle(image, (x1, label_y1), (x1 + tw + 4, label_y2), box_color, -1)
36
  cv2.putText(image, label, (x1 + 2, text_y), font, font_scale, text_color, thickness)
 
 
37
  @app.get("/")
38
  def root():
39
  return {"message": "AI API is running 🚀"}
 
 
40
  @router.post("/predict-image")
41
  async def predict_image(
42
  request: Request,
 
44
  ):
45
  safe_filename = file.filename.replace(" ", "_")
46
  file_path = os.path.join(UPLOAD_FOLDER, safe_filename)
 
47
  with open(file_path, "wb") as buffer:
48
  shutil.copyfileobj(file.file, buffer)
 
49
  image = cv2.imread(file_path)
 
50
  if image is None:
51
  return {"error": "Invalid image"}
 
52
  detections = []
53
  person_count = 0
54
  statue_count = 0
55
+ # ── Person Detection
56
+ person_results = person_model(file_path)
 
 
 
 
 
 
 
 
57
  for box in person_results[0].boxes:
58
  cls_id = int(box.cls)
59
  if cls_id != 0:
60
  continue
 
61
  conf = float(box.conf)
62
  if conf < CONF_THRESHOLD:
63
  continue
 
64
  x1, y1, x2, y2 = map(int, box.xyxy[0])
 
65
  cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
66
  draw_label(image, f"Person {conf:.2f}", x1, y1, x2, y2,
67
  box_color=(0, 255, 0), text_color=(0, 0, 0))
 
68
  detections.append({
69
  "type": "person",
70
  "name": "Person",
 
72
  "bbox": [x1, y1, x2, y2]
73
  })
74
  person_count += 1
75
+ # ── Statue Detection
76
+ statue_results = statue_model(file_path)
 
 
 
 
 
 
 
 
77
  for box in statue_results[0].boxes:
78
  conf = float(box.conf)
79
  if conf < CONF_THRESHOLD:
80
  continue
 
81
  cls_id = int(box.cls)
82
  statue_name = statue_results[0].names[cls_id]
 
83
  x1, y1, x2, y2 = map(int, box.xyxy[0])
 
84
  cv2.rectangle(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
85
  draw_label(image, f"{statue_name} {conf:.2f}", x1, y1, x2, y2,
86
  box_color=(0, 0, 255), text_color=(255, 255, 255))
 
87
  detections.append({
88
  "type": "statue",
89
  "name": statue_name,
 
91
  "bbox": [x1, y1, x2, y2]
92
  })
93
  statue_count += 1
94
+ # ── Save Output Image
 
95
  output_filename = f"output_{safe_filename}"
96
  output_path = os.path.join(UPLOAD_FOLDER, output_filename)
97
  cv2.imwrite(output_path, image)
 
98
  with open(output_path, "rb") as img_file:
99
  image_base64 = base64.b64encode(img_file.read()).decode("utf-8")
 
100
  image_url = f"{request.base_url}uploads/{output_filename}"
 
101
  return {
102
  "total_count": len(detections),
103
  "persons": person_count,
 
106
  "output_image_base64": f"data:image/jpeg;base64,{image_base64}",
107
  "detections": detections
108
  }
109
+ app.include_router(router)