commit e33e4ff6581b9b57f1889258f5a5733c241fcc10 Author: Akbar Rahman Date: Wed Dec 27 23:26:15 2023 +0000 initial commit diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ac34fea --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +env +.git +**/__pycache__ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f2efa5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +env +**/__pycache__ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..461c7d6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM python:3 + +ENV PYTHONUNBUFFERED=value + +WORKDIR /usr/src/app + +COPY requirements.txt ./ + +RUN pip install --no-cache-dir --extra-index-url https://download.pytorch.org/whl/cpu -r requirements.txt + +COPY src . +COPY best.pt /best.pt + +CMD [ "gunicorn", "-b 0.0.0.0:80", "app:app" ] diff --git a/best.pt b/best.pt new file mode 100644 index 0000000..a1f0aab Binary files /dev/null and b/best.pt differ diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3f7b541 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +version: '3' + +services: + alv.cx-glass: + build: . + restart: unless-stopped + ports: + - 8759:8000 diff --git a/index.html b/index.html new file mode 100644 index 0000000..ecf4d94 --- /dev/null +++ b/index.html @@ -0,0 +1,40 @@ + + +

submit an image to get started!

+
+
+ +
+ + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1447fdd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,45 @@ +blinker==1.7.0 +certifi==2022.12.7 +charset-normalizer==2.1.1 +click==8.1.7 +contourpy==1.2.0 +cycler==0.12.1 +filelock==3.9.0 +Flask==3.0.0 +fonttools==4.47.0 +fsspec==2023.4.0 +gunicorn==21.2.0 +idna==3.4 +itsdangerous==2.1.2 +Jinja2==3.1.2 +kiwisolver==1.4.5 +MarkupSafe==2.1.3 +matplotlib==3.8.2 +mpmath==1.3.0 +networkx==3.0 +numpy==1.24.1 +opencv-python-headless==4.8.1.78 +packaging==23.2 +pandas==2.1.4 +Pillow==9.3.0 +psutil==5.9.7 +py-cpuinfo==9.0.0 +pyparsing==3.1.1 +python-dateutil==2.8.2 +pytz==2023.3.post1 +PyYAML==6.0.1 +requests==2.28.1 +scipy==1.11.4 +seaborn==0.13.0 +six==1.16.0 +sympy==1.12 +thop==0.1.1.post2209072238 +torch==2.1.2+cpu +torchaudio==2.1.2+cpu +torchvision==0.16.2+cpu +tqdm==4.66.1 +typing_extensions==4.4.0 +tzdata==2023.3 +ultralytics==8.0.230 +urllib3==1.26.13 +Werkzeug==3.0.1 diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/app.py b/src/app.py new file mode 100755 index 0000000..f80be86 --- /dev/null +++ b/src/app.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 + +import os +import uuid +import json +import time +import cv2 +import queue +from pathlib import Path as P +from PIL import Image +from flask import Flask, request, send_from_directory +from flask_cors import CORS +from threading import Thread + +app = Flask(__name__) +CORS(app) + +QUEUE_STATE_IN_QUEUE = 'IN_QUEUE' +QUEUE_STATE_PROCESSING = 'PROCESSING' +QUEUE_STATE_READY = 'READY' + +q = queue.Queue(maxsize=1000) +state = {} +root = P("./q").absolute() +root.mkdir(parents=True, exist_ok=True) + + +def process(): + print("importing ultralytics") + from ultralytics import YOLO + print("creating model") + model = YOLO(os.environ.get("MODEL_PATH", "/best.pt")) + print("created model") + last = 0 + while True: + if time.time() < last + 10: + print("aa") + time.sleep(0.5) + continue + + print("BB") + + print("waiting for/getting job") + job = q.get() + filepath = root.joinpath(job) + print("got job") + state[job] = { + 'state': QUEUE_STATE_PROCESSING, + } + print(f"processing job: {job=}") + img = cv2.imread(str(filepath)) + results = model.predict(img) + + for r in results: + im_array = r.plot() + im = Image.fromarray(im_array[..., ::-1]) + im.save(str(filepath.with_suffix(".png"))) + state[job] = { + 'state': QUEUE_STATE_READY, + } + + filepath.unlink() + + +@app.route("/submit", methods=['POST']) +def render(): + id = str(uuid.uuid4()) + request.files['image'].save(root.joinpath(id)) + q.put(id) + state[id] = {'state': QUEUE_STATE_IN_QUEUE} + return json.dumps({'id': id}) + + +@app.route("/state/") +def get_state(id): + return json.dumps(state[id]) + + +@app.route("/result/") +def get_result(i): + print(root) + print(i + '.png') + return send_from_directory(root, i + '.png') + + +if __name__ == '__main__': + p = Thread(target=process) + p.start() + app.run(debug=True) + p.join()