server_minimal.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. '''
  2. This file is a barebones FastAPI example that:
  3. 1. Accepts GET request, renders a HTML form at localhost:8000 allowing the user to
  4. upload a image and select YOLO model, then submit that data via POST
  5. 2. Accept POST request, run YOLO model on input image, return JSON output
  6. Works with client_minimal.py
  7. This script does not require any of the HTML templates in /templates or other code in this repo
  8. and does not involve stuff like Bootstrap, Javascript, JQuery, etc.
  9. '''
  10. from fastapi import FastAPI, Request, Form, File, UploadFile
  11. from fastapi.responses import HTMLResponse
  12. from PIL import Image
  13. from io import BytesIO
  14. import torch
  15. app = FastAPI()
  16. @app.get("/")
  17. async def home(request: Request):
  18. ''' Returns barebones HTML form allowing the user to select a file and model '''
  19. html_content = '''
  20. <form method="post" enctype="multipart/form-data">
  21. <div>
  22. <label>Upload Image</label>
  23. <input name="file" type="file" multiple>
  24. <div>
  25. <label>Select YOLO Model</label>
  26. <select name="model_name">
  27. <option>yolov5s</option>
  28. <option>yolov5m</option>
  29. <option>yolov5l</option>
  30. <option>yolov5x</option>
  31. </select>
  32. </div>
  33. </div>
  34. <button type="submit">Submit</button>
  35. </form>
  36. '''
  37. return HTMLResponse(content=html_content, status_code=200)
  38. @app.post("/")
  39. async def process_home_form(file: UploadFile = File(...),
  40. model_name: str = Form(...)):
  41. '''
  42. Requires an image file upload, model name (ex. yolov5s).
  43. Returns: json response with list of list of dicts.
  44. Each dict contains class, class_name, confidence, normalized_bbox
  45. Note: Because this is an async method, the YOLO inference is a blocking
  46. operation.
  47. '''
  48. model = torch.hub.load('ultralytics/yolov5', model_name, pretrained=True, force_reload = False)
  49. #This is how you decode + process image with PIL
  50. results = model(Image.open(BytesIO(await file.read())))
  51. #This is how you decode + process image with OpenCV + numpy
  52. #results = model(cv2.cvtColor(cv2.imdecode(np.fromstring(await file.read(), np.uint8), cv2.IMREAD_COLOR), cv2.COLOR_RGB2BGR))
  53. json_results = results_to_json(results,model)
  54. return json_results
  55. def results_to_json(results, model):
  56. ''' Helper function for process_home_form()'''
  57. return [
  58. [
  59. {
  60. "class": int(pred[5]),
  61. "class_name": model.model.names[int(pred[5])],
  62. "bbox": [int(x) for x in pred[:4].tolist()], #convert bbox results to int from float
  63. "confidence": float(pred[4]),
  64. }
  65. for pred in result
  66. ]
  67. for result in results.xyxy
  68. ]
  69. if __name__ == '__main__':
  70. import uvicorn
  71. app_str = 'server_minimal:app'
  72. uvicorn.run(app_str, host='localhost', port=8000, reload=True, workers=1)