WalidAlHassan commited on
Commit
5494ea8
·
1 Parent(s): 6858d07
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ posmPJSTRIKE_v1.3.pt filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use a minimal Python image
2
+ FROM python:3.10-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Install required system libraries
8
+ RUN apt-get update && apt-get install -y libgl1-mesa-glx libglib2.0-0
9
+
10
+ # Install PyTorch separately to avoid timeout
11
+ RUN pip install --no-cache-dir torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
12
+
13
+ # Copy dependencies
14
+ COPY requirements.txt ./
15
+
16
+ # Install remaining dependencies
17
+ RUN pip install --no-cache-dir -r requirements.txt --timeout 100 --index-url https://pypi.tuna.tsinghua.edu.cn/simple
18
+
19
+ # Copy application code
20
+ COPY . .
21
+
22
+ # Expose the FastAPI port
23
+ EXPOSE 8000
24
+
25
+ # Run the application
26
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
27
+
base_width.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "Name": ["Width","hight"],
3
+ "focused_medium_core": [49.6,34.6],
4
+ "modular_small_core": [44.6,17.2],
5
+ "focused_modular_extra_small_core": [25.7,12.7],
6
+ "regular_modular_core": [42.9,25.5],
7
+ "reusable_pack_dispenser_core": [28.15,15.15],
8
+
9
+ "regular_modular_fns": [42.9,25.5],
10
+ "modular_small_fns": [44.8,17.1],
11
+ "focused_medium_fns": [49.6,34.6],
12
+ "reusable_pack_dispenser_fns": [28.15,15.15],
13
+ "focused_modular_extra_small_fns": [25.5,12.7]
14
+ }
distance_calculate3.ipynb ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 11,
6
+ "metadata": {},
7
+ "outputs": [
8
+ {
9
+ "name": "stdout",
10
+ "output_type": "stream",
11
+ "text": [
12
+ "\n",
13
+ "0: 384x512 1 focused_medium_core, 1 modular_small_core, 341.3ms\n",
14
+ "Speed: 1.5ms preprocess, 341.3ms inference, 1.5ms postprocess per image at shape (1, 3, 384, 512)\n"
15
+ ]
16
+ }
17
+ ],
18
+ "source": [
19
+ "import math\n",
20
+ "import cv2\n",
21
+ "import numpy as np\n",
22
+ "from ultralytics import YOLO\n",
23
+ "import json\n",
24
+ "\n",
25
+ "model = YOLO(\"posmPJSTRIKE_v1.3.pt\")\n",
26
+ "image = cv2.imread(\"1.jpeg\")\n",
27
+ "res = model(image)\n",
28
+ "\n",
29
+ "with open(\"base_width.json\", \"r\") as f:\n",
30
+ " base_width = json.load(f)"
31
+ ]
32
+ },
33
+ {
34
+ "cell_type": "code",
35
+ "execution_count": 12,
36
+ "metadata": {},
37
+ "outputs": [],
38
+ "source": [
39
+ "def find_position(objects_names_points, par_pix_cm, image):\n",
40
+ " object_positions = {}\n",
41
+ " for obj in objects_names_points:\n",
42
+ " name = list(obj.keys())[0]\n",
43
+ " points = list(obj.values())[0]\n",
44
+ "\n",
45
+ " top_distance = round((points[0][1] - 0) * par_pix_cm[name],2)\n",
46
+ " bottom_distance = round((image.shape[0] - points[3][1]) * par_pix_cm[name],2)\n",
47
+ " left_distance = round((points[0][0] - 0) * par_pix_cm[name],2)\n",
48
+ " right_distance = round((image.shape[1] - points[3][0]) * par_pix_cm[name],2)\n",
49
+ " \n",
50
+ " object_positions.update({name: {\"top\": top_distance, \"bottom\": bottom_distance, \"left\": left_distance, \"right\": right_distance}})\n",
51
+ " return object_positions\n",
52
+ "\n",
53
+ "def get_actual_distance(closest_points, par_pix_cm):\n",
54
+ " actual_results_n_distance = {}\n",
55
+ " for i in closest_points:\n",
56
+ " avg_px_cm = ((par_pix_cm[i[0]] + par_pix_cm[i[1]])/2)\n",
57
+ " actual_results_n_distance.update({i:round(closest_points[i]*avg_px_cm,2)})\n",
58
+ " return actual_results_n_distance\n",
59
+ "\n",
60
+ "def pixel_per_cm(objects_names_width_pix):\n",
61
+ " par_pix_cm = {}\n",
62
+ " for i in objects_names_width_pix:\n",
63
+ " par_pix_cm_width = base_width[i][0]/objects_names_width_pix[i][0]\n",
64
+ " par_pix_cm_hight = base_width[i][1]/objects_names_width_pix[i][1]\n",
65
+ " avg_par_pix_cm = (par_pix_cm_width + par_pix_cm_hight)/2\n",
66
+ " par_pix_cm.update({i:avg_par_pix_cm})\n",
67
+ " return par_pix_cm\n",
68
+ "\n",
69
+ "def get_points_n_names(results):\n",
70
+ " objects_names_points = []\n",
71
+ " objects_names_width_pix = {}\n",
72
+ " for box, cls in zip(results[0].boxes.xyxy, results[0].boxes.cls):\n",
73
+ " x1, y1, x2, y2 = map(int, box)\n",
74
+ " class_name = results[0].names[int(cls)]\n",
75
+ " width = x2 - x1\n",
76
+ " hight = y2 - y1\n",
77
+ " objects_names_points.append({class_name: [(x1, y1), (x2, y1), (x1, y2), (x2, y2)]})\n",
78
+ " objects_names_width_pix.update({class_name: [width, hight]})\n",
79
+ " \n",
80
+ " return objects_names_points, objects_names_width_pix\n",
81
+ "\n",
82
+ "def euclidean_distance(point1, point2):\n",
83
+ " dist_pixels = math.sqrt((point2[0] - point1[0])**2 + (point2[1] - point1[1])**2)\n",
84
+ " return dist_pixels\n",
85
+ "\n",
86
+ "def find_closest_points(lst):\n",
87
+ " closest_points = {}\n",
88
+ " \n",
89
+ " for i in range(len(lst)):\n",
90
+ " for j in range(i + 1, len(lst)):\n",
91
+ " list1 = lst[i]\n",
92
+ " list2 = lst[j]\n",
93
+ " min_distance = float('inf')\n",
94
+ " closest_objects_pair = None\n",
95
+ " \n",
96
+ " for obj1 in list1.values():\n",
97
+ " points1 = obj1\n",
98
+ " for obj2 in list2.values():\n",
99
+ " points2 = obj2\n",
100
+ " \n",
101
+ " for point1 in points1:\n",
102
+ " for point2 in points2:\n",
103
+ " distance = euclidean_distance(point1, point2)\n",
104
+ " if distance < min_distance:\n",
105
+ " min_distance = distance\n",
106
+ " closest_objects_pair = (list1.keys(), list2.keys())\n",
107
+ " \n",
108
+ " closest_points.update({(list(closest_objects_pair[0])[0],list(closest_objects_pair[1])[0]):round(min_distance, 2)})\n",
109
+ " return closest_points\n",
110
+ "\n",
111
+ "objects_names_points, objects_names_width_pix = get_points_n_names(res)\n",
112
+ "par_pix_cm = pixel_per_cm(objects_names_width_pix)\n",
113
+ "closest_points = find_closest_points(objects_names_points)\n",
114
+ "actual_distances = get_actual_distance(closest_points, par_pix_cm)\n",
115
+ "object_position = find_position(objects_names_points, par_pix_cm, image)"
116
+ ]
117
+ }
118
+ ],
119
+ "metadata": {
120
+ "kernelspec": {
121
+ "display_name": "bat",
122
+ "language": "python",
123
+ "name": "python3"
124
+ },
125
+ "language_info": {
126
+ "codemirror_mode": {
127
+ "name": "ipython",
128
+ "version": 3
129
+ },
130
+ "file_extension": ".py",
131
+ "mimetype": "text/x-python",
132
+ "name": "python",
133
+ "nbconvert_exporter": "python",
134
+ "pygments_lexer": "ipython3",
135
+ "version": "3.12.8"
136
+ }
137
+ },
138
+ "nbformat": 4,
139
+ "nbformat_minor": 2
140
+ }
main.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import requests
3
+ import numpy as np
4
+ import json
5
+ from io import BytesIO
6
+ from fastapi import FastAPI
7
+ from pydantic import BaseModel
8
+ from ultralytics import YOLO
9
+ from PIL import Image
10
+
11
+ app = FastAPI()
12
+
13
+ model = YOLO("posmPJSTRIKE_v1.3.pt")
14
+
15
+ with open("base_width.json", "r") as f:
16
+ base_width = json.load(f)
17
+
18
+ with open("name_conversion.json", "r") as f:
19
+ name_convert = json.load(f)
20
+
21
+ class ImageRequest(BaseModel):
22
+ image_url: str
23
+
24
+ def get_image_from_url(image_url):
25
+ response = requests.get(image_url)
26
+ image = Image.open(BytesIO(response.content)).convert("RGB")
27
+ return np.array(image)
28
+
29
+ def name_conversion(actual_distances,object_positions, name_convert):
30
+ actual_distances_sys = []
31
+ object_positions_sys = {}
32
+ for item in actual_distances:
33
+ actual_distances_sys.append({'object':(name_convert[list(item.values())[0][0]],name_convert[list(item.values())[0][1]]),'distances': str(list(item.values())[1]) + " cm"})
34
+
35
+ for item in object_positions:
36
+ object_positions_sys.update({name_convert[item]:{"top": str(object_positions[item]['top']) + " cm", "bottom": str(object_positions[item]['bottom']) + " cm", "left": str(object_positions[item]['left']) + " cm", "right": str(object_positions[item]['right']) + " cm"}})
37
+ return object_positions_sys, actual_distances_sys
38
+
39
+ def find_position(objects_names_points, par_pix_cm, image):
40
+ object_positions = {}
41
+ for obj in objects_names_points:
42
+ name = list(obj.keys())[0]
43
+ points = list(obj.values())[0]
44
+
45
+ top_distance = round((points[0][1] - 0) * par_pix_cm[name], 2)
46
+ bottom_distance = round((image.size[1] - points[3][1]) * par_pix_cm[name], 2)
47
+ left_distance = round((points[0][0] - 0) * par_pix_cm[name], 2)
48
+ right_distance = round((image.size[0] - points[3][0]) * par_pix_cm[name], 2)
49
+
50
+ object_positions.update({name: {"top": top_distance, "bottom": bottom_distance, "left": left_distance, "right": right_distance}})
51
+ return object_positions
52
+
53
+ def get_actual_distance(closest_points, par_pix_cm):
54
+ actual_results_n_distance = []
55
+ for i in closest_points:
56
+ avg_px_cm = ((par_pix_cm[i[0]] + par_pix_cm[i[1]]) / 2)
57
+ actual_results_n_distance.append({'object': i, 'distances': round(closest_points[i] * avg_px_cm, 2)})
58
+ return actual_results_n_distance
59
+
60
+ def pixel_per_cm(objects_names_width_pix):
61
+ par_pix_cm = {}
62
+ for i in objects_names_width_pix:
63
+ par_pix_cm_width = base_width[i][0] / objects_names_width_pix[i][0]
64
+ par_pix_cm_height = base_width[i][1] / objects_names_width_pix[i][1]
65
+ avg_par_pix_cm = (par_pix_cm_width + par_pix_cm_height) / 2
66
+ par_pix_cm.update({i: avg_par_pix_cm})
67
+ return par_pix_cm
68
+
69
+ def get_points_n_names(results):
70
+ objects_names_points = []
71
+ objects_names_width_pix = {}
72
+ for box, cls in zip(results[0].boxes.xyxy, results[0].boxes.cls):
73
+ x1, y1, x2, y2 = map(int, box)
74
+ class_name = results[0].names[int(cls)]
75
+ width = x2 - x1
76
+ height = y2 - y1
77
+ objects_names_points.append({class_name: [(x1, y1), (x2, y1), (x1, y2), (x2, y2)]})
78
+ objects_names_width_pix.update({class_name: [width, height]})
79
+
80
+ return objects_names_points, objects_names_width_pix
81
+
82
+ def euclidean_distance(point1, point2):
83
+ dist_pixels = math.sqrt((point2[0] - point1[0])**2 + (point2[1] - point1[1])**2)
84
+ return dist_pixels
85
+
86
+ def find_closest_points(lst):
87
+ closest_points = {}
88
+
89
+ for i in range(len(lst)):
90
+ for j in range(i + 1, len(lst)):
91
+ list1 = lst[i]
92
+ list2 = lst[j]
93
+ min_distance = float('inf')
94
+ closest_objects_pair = None
95
+
96
+ for obj1 in list1.values():
97
+ points1 = obj1
98
+ for obj2 in list2.values():
99
+ points2 = obj2
100
+
101
+ for point1 in points1:
102
+ for point2 in points2:
103
+ distance = euclidean_distance(point1, point2)
104
+ if distance < min_distance:
105
+ min_distance = distance
106
+ closest_objects_pair = (list1.keys(), list2.keys())
107
+
108
+ closest_points.update({(list(closest_objects_pair[0])[0], list(closest_objects_pair[1])[0]): round(min_distance, 2)})
109
+ return closest_points
110
+
111
+ @app.post("/process_image")
112
+ def process_image(request: ImageRequest):
113
+ image = get_image_from_url(request.image_url)
114
+ image = Image.fromarray(image)
115
+ size = (640, 640)
116
+ image.thumbnail(size)
117
+ image.save("image.jpg")
118
+ res = model(image)
119
+
120
+ objects_names_points, objects_names_width_pix = get_points_n_names(res)
121
+ par_pix_cm = pixel_per_cm(objects_names_width_pix)
122
+ closest_points = find_closest_points(objects_names_points)
123
+ actual_distances = get_actual_distance(closest_points, par_pix_cm)
124
+ object_positions = find_position(objects_names_points, par_pix_cm, image)
125
+
126
+ # Remove the distance between the same object
127
+ for item in actual_distances[:]:
128
+ if item['object'][0] == item['object'][1]:
129
+ actual_distances.remove(item)
130
+
131
+ # Convert the object names to the system names
132
+ object_positions_sys, actual_distances_sys = name_conversion(actual_distances,object_positions, name_convert)
133
+
134
+ return {
135
+ "object_positions": object_positions_sys,
136
+ "actual_distances": actual_distances_sys
137
+ }
name_conversion.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "pvc_base_surface_hanger_core":"PVC Base Surface Hanger Core",
3
+ "paper_base_surface_hanger_core":"Paper Base Surface Hanger Core",
4
+ "pvc_base_surface_hanger_fns":"PVC Base Surface Hanger FnS",
5
+ "paper_base_surface_hanger_fns":"Paper Base Surface Hanger FnS",
6
+ "focused_medium_core":"Focused Medium Core",
7
+ "focused_modular_extra_small_core":"Focused Modular-Extra Small Core",
8
+ "focused_modular_extra_small_fns":"Focused Modular-Extra Small FnS",
9
+ "focused_medium_fns":"Focused Medium FnS",
10
+ "modular_small_core":"Modular Small Core",
11
+ "modular_small_fns":"Modular Small FnS",
12
+ "regular_modular_core":"Regular Modular Core",
13
+ "regular_modular_fns":"Regular Modular FnS",
14
+ "reusable_pack_dispenser_core":"Reusable Pack Dispenser Core",
15
+ "reusable_pack_dispenser_fns":"Reusable Pack Dispenser FnS",
16
+ "street_kiosk_identifier_core":"Street Kiosk Identifier Core",
17
+ "street_kiosk_identifier_fns":"Street Kiosk Identifier FnS"
18
+ }
posmPJSTRIKE_v1.3.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e318caeaf1d380b927894f517d142f4176a4ad20c8706f01fd14d089e7f18980
3
+ size 144064701
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ ultralytics
2
+ torch
3
+ torchvision
4
+ torchaudio
5
+ fastapi
6
+ uvicorn
7
+ pillow
8
+ numpy
9
+ requests
10
+ pydantic