Spaces:
Sleeping
Sleeping
Denny Lulak commited on
Commit ·
d7832c5
1
Parent(s): 66e269f
Fix
Browse files- app.py +24 -10
- inference.py +2 -1
- requirements.txt +2 -1
app.py
CHANGED
|
@@ -1,10 +1,8 @@
|
|
| 1 |
-
# app.py
|
| 2 |
from fastapi import FastAPI, File, UploadFile, HTTPException
|
| 3 |
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
| 4 |
import numpy as np
|
| 5 |
import cv2
|
| 6 |
-
from inference import ObjectDetector
|
| 7 |
-
from typing import List
|
| 8 |
|
| 9 |
# Configuration
|
| 10 |
MODEL_ONNX_PATH = "model.onnx"
|
|
@@ -30,22 +28,38 @@ app.add_middleware(
|
|
| 30 |
allow_headers=["*"],
|
| 31 |
)
|
| 32 |
|
| 33 |
-
@app.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
async def detect_objects(file: UploadFile = File(...)):
|
| 35 |
try:
|
|
|
|
| 36 |
if not file.content_type.startswith("image/"):
|
| 37 |
-
raise HTTPException(400, "
|
| 38 |
|
|
|
|
| 39 |
image_data = await file.read()
|
| 40 |
image = cv2.imdecode(np.frombuffer(image_data, np.uint8), cv2.IMREAD_COLOR)
|
| 41 |
-
|
| 42 |
if image is None:
|
| 43 |
raise HTTPException(400, "Invalid image data")
|
| 44 |
|
|
|
|
| 45 |
detections = detector.predict(image)
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
-
except HTTPException
|
| 49 |
-
raise
|
| 50 |
except Exception as e:
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from fastapi import FastAPI, File, UploadFile, HTTPException
|
| 2 |
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
+
from inference import ObjectDetector
|
| 4 |
import numpy as np
|
| 5 |
import cv2
|
|
|
|
|
|
|
| 6 |
|
| 7 |
# Configuration
|
| 8 |
MODEL_ONNX_PATH = "model.onnx"
|
|
|
|
| 28 |
allow_headers=["*"],
|
| 29 |
)
|
| 30 |
|
| 31 |
+
@app.get("/")
|
| 32 |
+
def health_check():
|
| 33 |
+
return {"status": "OK", "model": "Object Detection API"}
|
| 34 |
+
|
| 35 |
+
@app.post("/detect")
|
| 36 |
async def detect_objects(file: UploadFile = File(...)):
|
| 37 |
try:
|
| 38 |
+
# Validate input
|
| 39 |
if not file.content_type.startswith("image/"):
|
| 40 |
+
raise HTTPException(400, "File must be an image")
|
| 41 |
|
| 42 |
+
# Read and decode image
|
| 43 |
image_data = await file.read()
|
| 44 |
image = cv2.imdecode(np.frombuffer(image_data, np.uint8), cv2.IMREAD_COLOR)
|
|
|
|
| 45 |
if image is None:
|
| 46 |
raise HTTPException(400, "Invalid image data")
|
| 47 |
|
| 48 |
+
# Perform detection
|
| 49 |
detections = detector.predict(image)
|
| 50 |
+
|
| 51 |
+
return {
|
| 52 |
+
"status": "success",
|
| 53 |
+
"detections": detections,
|
| 54 |
+
"count": len(detections)
|
| 55 |
+
}
|
| 56 |
|
| 57 |
+
except HTTPException:
|
| 58 |
+
raise
|
| 59 |
except Exception as e:
|
| 60 |
+
raise HTTPException(500, f"Processing error: {str(e)}")
|
| 61 |
+
|
| 62 |
+
# For Hugging Face Spaces
|
| 63 |
+
if __name__ == "__main__":
|
| 64 |
+
import uvicorn
|
| 65 |
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
inference.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
# inference.py
|
| 2 |
import numpy as np
|
| 3 |
import cv2
|
| 4 |
import onnxruntime as ort
|
|
@@ -34,6 +33,7 @@ class ObjectDetector:
|
|
| 34 |
intersection_area = np.maximum(0, xmax - xmin) * np.maximum(0, ymax - ymin)
|
| 35 |
box_area = (box[2] - box[0]) * (box[3] - box[1])
|
| 36 |
boxes_area = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])
|
|
|
|
| 37 |
return intersection_area / (box_area + boxes_area - intersection_area + 1e-6)
|
| 38 |
|
| 39 |
@staticmethod
|
|
@@ -107,6 +107,7 @@ class ObjectDetector:
|
|
| 107 |
} for i in indices]
|
| 108 |
|
| 109 |
def predict(self, image: np.ndarray) -> List[Dict]:
|
|
|
|
| 110 |
input_tensor, scale, padding = self.preprocess(image)
|
| 111 |
outputs = self.session.run(None, {"images": input_tensor})
|
| 112 |
return self.postprocess(outputs[0], image.shape[:2], scale, padding)
|
|
|
|
|
|
|
| 1 |
import numpy as np
|
| 2 |
import cv2
|
| 3 |
import onnxruntime as ort
|
|
|
|
| 33 |
intersection_area = np.maximum(0, xmax - xmin) * np.maximum(0, ymax - ymin)
|
| 34 |
box_area = (box[2] - box[0]) * (box[3] - box[1])
|
| 35 |
boxes_area = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])
|
| 36 |
+
|
| 37 |
return intersection_area / (box_area + boxes_area - intersection_area + 1e-6)
|
| 38 |
|
| 39 |
@staticmethod
|
|
|
|
| 107 |
} for i in indices]
|
| 108 |
|
| 109 |
def predict(self, image: np.ndarray) -> List[Dict]:
|
| 110 |
+
"""Main prediction method"""
|
| 111 |
input_tensor, scale, padding = self.preprocess(image)
|
| 112 |
outputs = self.session.run(None, {"images": input_tensor})
|
| 113 |
return self.postprocess(outputs[0], image.shape[:2], scale, padding)
|
requirements.txt
CHANGED
|
@@ -5,4 +5,5 @@ onnxruntime-gpu
|
|
| 5 |
opencv-python
|
| 6 |
Pillow
|
| 7 |
torch
|
| 8 |
-
ultralytics
|
|
|
|
|
|
| 5 |
opencv-python
|
| 6 |
Pillow
|
| 7 |
torch
|
| 8 |
+
ultralytics
|
| 9 |
+
python-multipart
|