diff --git a/index.html b/index.html
index fb80ff3..fca4bc7 100644
--- a/index.html
+++ b/index.html
@@ -1,70 +1,156 @@
-
-
-
-
- YOLOv8 Object Detection
-
-
-
-
-
-
-
+
+
+
+
+ TomAIto
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/object_detector.py b/object_detector.py
index ac66554..8d908c9 100644
--- a/object_detector.py
+++ b/object_detector.py
@@ -1,179 +1,177 @@
-#from ultralytics import YOLO
-from flask import request, Flask, jsonify
-from waitress import serve
-from PIL import Image
-import onnxruntime as ort
-import numpy as np
-
-#my changes
-import os
-
-script_dir = os.path.dirname(os.path.abspath(__file__))
-# Change the working directory to the script's directory
-os.chdir(script_dir)
-
-yolo_classes = ["b_fully_ripened",
- "b_half_ripened",
- "b_green",
- "l_fully_ripened",
- "l_half_ripened",
- "l_green"
-]
-
-#app start
-
-app = Flask(__name__)
-
-@app.route("/")
-def root():
- """
- Site main page handler function.
- :return: Content of index.html file
- """
- with open("index.html") as file:
- return file.read()
-
-
-@app.route("/detect", methods=["POST"])
-def detect():
- """
- Handler of /detect POST endpoint
- Receives uploaded file with a name "image_file", passes it
- through YOLOv8 object detection network and returns and array
- of bounding boxes.
- :return: a JSON array of objects bounding boxes in format [[x1,y1,x2,y2,object_type,probability],..]
- """
- buf = request.files["image_file"]
- boxes, orientation = detect_objects_on_image(buf.stream)
- #print(boxes)
- #print(orientation)
- return jsonify(boxes)
-
-def detect_objects_on_image(buf):
- input, img_width, img_height = prepare_input(buf)
- output = run_model(input)
- orientation = get_orientation(buf)
- processed_output = process_output(output, img_width, img_height, orientation)
- return processed_output, orientation
-
-def prepare_input(buf):
- img = Image.open(buf)
- img_width, img_height = img.size
- img = img.resize((640, 640))
- img = img.convert("RGB")
- input = np.array(img)
- input = input.transpose(2, 0, 1)
- input = input.reshape(1, 3, 640, 640) / 255.0
- return input.astype(np.float32), img_width, img_height
-
-def run_model(input):
- model = ort.InferenceSession("best.onnx", providers=['CPUExecutionProvider'])
- outputs = model.run(["output0"], {"images":input})
- return outputs[0]
-
-def process_output(output, img_width, img_height, orientation):
- output = output[0].astype(float)
- output = output.transpose()
-
- boxes = []
- for row in output:
- prob = row[4:].max()
- if prob < 0.5:
- continue
-
- class_id = row[4:].argmax()
- label = yolo_classes[class_id]
- xc, yc, w, h = row[:4]
- x1 = (xc - w/2) / 640 * img_width
- y1 = (yc - h/2) / 640 * img_height
- x2 = (xc + w/2) / 640 * img_width
- y2 = (yc + h/2) / 640 * img_height
-
- boxes.append([x1, y1, x2, y2, label, prob])
-
- # Adjust boxes based on orientation
- adjusted_boxes = adjust_boxes_for_orientation(boxes, orientation, img_width, img_height)
-
- # Sort and apply non-max suppression as before
- adjusted_boxes.sort(key=lambda x: x[5], reverse=True)
- result = []
- while len(adjusted_boxes) > 0:
- result.append(adjusted_boxes[0])
- adjusted_boxes = [box for box in adjusted_boxes if iou(box, adjusted_boxes[0]) < 0.7]
-
- return result
-
-
-def iou(box1,box2):
- return intersection(box1,box2)/union(box1,box2)
-
-def union(box1,box2):
- box1_x1,box1_y1,box1_x2,box1_y2 = box1[:4]
- box2_x1,box2_y1,box2_x2,box2_y2 = box2[:4]
- box1_area = (box1_x2-box1_x1)*(box1_y2-box1_y1)
- box2_area = (box2_x2-box2_x1)*(box2_y2-box2_y1)
- return box1_area + box2_area - intersection(box1,box2)
-
-def intersection(box1,box2):
- box1_x1,box1_y1,box1_x2,box1_y2 = box1[:4]
- box2_x1,box2_y1,box2_x2,box2_y2 = box2[:4]
- x1 = max(box1_x1,box2_x1)
- y1 = max(box1_y1,box2_y1)
- x2 = min(box1_x2,box2_x2)
- y2 = min(box1_y2,box2_y2)
- return (x2-x1)*(y2-y1)
-
-def get_orientation(image_path):
- with Image.open(image_path) as img:
- if hasattr(img, '_getexif'):
- exif_data = img._getexif()
- if exif_data is not None:
- return exif_data.get(274, 1) # Default to normal orientation
- return 1 # Default orientation if no EXIF data
-
-def adjust_boxes_for_orientation(boxes, orientation, img_width, img_height):
- adjusted_boxes = []
- for box in boxes:
- x1, y1, x2, y2, label, prob = box
-
- # Apply transformations based on orientation
- if orientation == 3: # 180 degrees
- x1, y1, x2, y2 = img_width - x2, img_height - y2, img_width - x1, img_height - y1
- elif orientation == 6: # 270 degrees (or -90 degrees)
- x1, y1, x2, y2 = img_height - y2, x1, img_height - y1, x2
- elif orientation == 8: # 90 degrees
- x1, y1, x2, y2 = y1, img_width - x2, y2, img_width - x1
-
- adjusted_boxes.append([x1, y1, x2, y2, label, prob])
-
- return adjusted_boxes
-
-
-""" def detect_objects_on_image(buf):
- """
-""""
- Function receives an image,
- passes it through YOLOv8 neural network
- and returns an array of detected objects
- and their bounding boxes
- :param buf: Input image file stream
- :return: Array of bounding boxes in format [[x1,y1,x2,y2,object_type,probability],..]
- """
-"""""
- model = YOLO("best.pt")
- results = model.predict(Image.open(buf))
- result = results[0]
- output = []
- for box in result.boxes:
- x1, y1, x2, y2 = [
- round(x) for x in box.xyxy[0].tolist()
- ]
- class_id = box.cls[0].item()
- prob = round(box.conf[0].item(), 2)
- output.append([
- x1, y1, x2, y2, result.names[class_id], prob
- ])
- return output
-
- """
-serve(app, host='0.0.0.0', port=8080)
+#from ultralytics import YOLO
+from flask import request, Flask, jsonify
+from waitress import serve
+from PIL import Image
+import onnxruntime as ort
+import numpy as np
+import requests
+
+#my changes
+import os
+
+script_dir = os.path.dirname(os.path.abspath(__file__))
+# Change the working directory to the script's directory
+os.chdir(script_dir)
+
+yolo_classes = ["b_fully_ripened",
+ "b_half_ripened",
+ "b_green",
+ "l_fully_ripened",
+ "l_half_ripened",
+ "l_green"
+]
+
+#app start
+
+app = Flask(__name__)
+
+
+@app.route("/")
+def root():
+ """
+ Site main page handler function.
+ :return: Content of index.html file
+ """
+ with open("index.html") as file:
+ return file.read()
+
+@app.route("/detect", methods=["POST"])
+def detect():
+ buf = request.files["image_file"]
+ crop_type = request.form.get("cropType")
+ location = request.form.get("location")
+ variety = request.form.get("variety")
+ boxes, orientation = detect_objects_on_image(buf.stream)
+ # Do something with crop_type, location, and variety here (e.g., store in database)
+
+ return jsonify(boxes)
+
+
+def detect_objects_on_image(buf):
+ input, img_width, img_height = prepare_input(buf)
+ output = run_model(input)
+ orientation = get_orientation(buf)
+ processed_output = process_output(output, img_width, img_height, orientation)
+ return processed_output, orientation
+
+def prepare_input(buf):
+ img = Image.open(buf)
+ img_width, img_height = img.size
+ img = img.resize((640, 640))
+ img = img.convert("RGB")
+ input = np.array(img)
+ input = input.transpose(2, 0, 1)
+ input = input.reshape(1, 3, 640, 640) / 255.0
+ return input.astype(np.float32), img_width, img_height
+
+def run_model(input):
+ model = ort.InferenceSession("best.onnx", providers=['CPUExecutionProvider'])
+ outputs = model.run(["output0"], {"images":input})
+ return outputs[0]
+
+def process_output(output, img_width, img_height, orientation):
+ output = output[0].astype(float)
+ output = output.transpose()
+
+ boxes = []
+ for row in output:
+ prob = row[4:].max()
+ if prob < 0.5:
+ continue
+
+ class_id = row[4:].argmax()
+ label = yolo_classes[class_id]
+ xc, yc, w, h = row[:4]
+ x1 = (xc - w/2) / 640 * img_width
+ y1 = (yc - h/2) / 640 * img_height
+ x2 = (xc + w/2) / 640 * img_width
+ y2 = (yc + h/2) / 640 * img_height
+
+ boxes.append([x1, y1, x2, y2, label, prob])
+
+ # Adjust boxes based on orientation
+ adjusted_boxes = adjust_boxes_for_orientation(boxes, orientation, img_width, img_height)
+
+ # Sort and apply non-max suppression as before
+ adjusted_boxes.sort(key=lambda x: x[5], reverse=True)
+ result = []
+ while len(adjusted_boxes) > 0:
+ result.append(adjusted_boxes[0])
+ adjusted_boxes = [box for box in adjusted_boxes if iou(box, adjusted_boxes[0]) < 0.7]
+
+ return result
+
+
+def iou(box1,box2):
+ return intersection(box1,box2)/union(box1,box2)
+
+def union(box1,box2):
+ box1_x1,box1_y1,box1_x2,box1_y2 = box1[:4]
+ box2_x1,box2_y1,box2_x2,box2_y2 = box2[:4]
+ box1_area = (box1_x2-box1_x1)*(box1_y2-box1_y1)
+ box2_area = (box2_x2-box2_x1)*(box2_y2-box2_y1)
+ return box1_area + box2_area - intersection(box1,box2)
+
+def intersection(box1,box2):
+ box1_x1,box1_y1,box1_x2,box1_y2 = box1[:4]
+ box2_x1,box2_y1,box2_x2,box2_y2 = box2[:4]
+ x1 = max(box1_x1,box2_x1)
+ y1 = max(box1_y1,box2_y1)
+ x2 = min(box1_x2,box2_x2)
+ y2 = min(box1_y2,box2_y2)
+ return (x2-x1)*(y2-y1)
+
+def get_orientation(image_path):
+ with Image.open(image_path) as img:
+ if hasattr(img, '_getexif'):
+ exif_data = img._getexif()
+ if exif_data is not None:
+ return exif_data.get(274, 1) # Default to normal orientation
+ return 1 # Default orientation if no EXIF data
+
+def adjust_boxes_for_orientation(boxes, orientation, img_width, img_height):
+ adjusted_boxes = []
+ for box in boxes:
+ x1, y1, x2, y2, label, prob = box
+
+ # Apply transformations based on orientation
+ if orientation == 3: # 180 degrees
+ x1, y1, x2, y2 = img_width - x2, img_height - y2, img_width - x1, img_height - y1
+ elif orientation == 6: # 270 degrees (or -90 degrees)
+ x1, y1, x2, y2 = img_height - y2, x1, img_height - y1, x2
+ elif orientation == 8: # 90 degrees
+ x1, y1, x2, y2 = y1, img_width - x2, y2, img_width - x1
+
+ adjusted_boxes.append([x1, y1, x2, y2, label, prob])
+
+ return adjusted_boxes
+
+
+""" def detect_objects_on_image(buf):
+ """
+""""
+ Function receives an image,
+ passes it through YOLOv8 neural network
+ and returns an array of detected objects
+ and their bounding boxes
+ :param buf: Input image file stream
+ :return: Array of bounding boxes in format [[x1,y1,x2,y2,object_type,probability],..]
+ """
+"""""
+ model = YOLO("best.pt")
+ results = model.predict(Image.open(buf))
+ result = results[0]
+ output = []
+ for box in result.boxes:
+ x1, y1, x2, y2 = [
+ round(x) for x in box.xyxy[0].tolist()
+ ]
+ class_id = box.cls[0].item()
+ prob = round(box.conf[0].item(), 2)
+ output.append([
+ x1, y1, x2, y2, result.names[class_id], prob
+ ])
+ return output
+
+ """
+serve(app, host='0.0.0.0', port=8080)