Spaces:
Running
Running
import gradio as gr | |
import torch | |
from ultralytics import YOLO | |
import cv2 | |
import numpy as np | |
from math import atan2, cos, sin, sqrt, pi | |
# Images | |
torch.hub.download_url_to_file('https://github.com/lucarei/orientation-detection-robotic-grasping/assets/22428774/cefd9731-c57c-428b-b401-fd54a8bd0a95', 'highway.jpg') | |
torch.hub.download_url_to_file('https://github.com/lucarei/orientation-detection-robotic-grasping/assets/22428774/acbad76a-33f9-4028-b012-4ece5998c272', 'highway1.jpg') | |
torch.hub.download_url_to_file('https://github.com/lucarei/orientation-detection-robotic-grasping/assets/22428774/7fa95f52-3c8b-4ea0-8bca-7374792a4c55', 'small-vehicles1.jpeg') | |
def drawAxis(img, p_, q_, color, scale): | |
p = list(p_) | |
q = list(q_) | |
## [visualization1] | |
angle = atan2(p[1] - q[1], p[0] - q[0]) # angle in radians | |
hypotenuse = sqrt((p[1] - q[1]) * (p[1] - q[1]) + (p[0] - q[0]) * (p[0] - q[0])) | |
# Here we lengthen the arrow by a factor of scale | |
q[0] = p[0] - scale * hypotenuse * cos(angle) | |
q[1] = p[1] - scale * hypotenuse * sin(angle) | |
cv2.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), color, 3, cv2.LINE_AA) | |
# create the arrow hooks | |
p[0] = q[0] + 9 * cos(angle + pi / 4) | |
p[1] = q[1] + 9 * sin(angle + pi / 4) | |
cv2.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), color, 3, cv2.LINE_AA) | |
p[0] = q[0] + 9 * cos(angle - pi / 4) | |
p[1] = q[1] + 9 * sin(angle - pi / 4) | |
cv2.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), color, 3, cv2.LINE_AA) | |
## [visualization1] | |
def getOrientation(pts, img): | |
## [pca] | |
# Construct a buffer used by the pca analysis | |
sz = len(pts) | |
data_pts = np.empty((sz, 2), dtype=np.float64) | |
for i in range(data_pts.shape[0]): | |
data_pts[i,0] = pts[i,0,0] | |
data_pts[i,1] = pts[i,0,1] | |
# Perform PCA analysis | |
mean = np.empty((0)) | |
mean, eigenvectors, eigenvalues = cv2.PCACompute2(data_pts, mean) | |
# Store the center of the object | |
cntr = (int(mean[0,0]), int(mean[0,1])) | |
## [pca] | |
## [visualization] | |
# Draw the principal components | |
cv2.circle(img, cntr, 3, (255, 0, 255), 10) | |
p1 = (cntr[0] + 0.02 * eigenvectors[0,0] * eigenvalues[0,0], cntr[1] + 0.02 * eigenvectors[0,1] * eigenvalues[0,0]) | |
p2 = (cntr[0] - 0.02 * eigenvectors[1,0] * eigenvalues[1,0], cntr[1] - 0.02 * eigenvectors[1,1] * eigenvalues[1,0]) | |
drawAxis(img, cntr, p1, (255, 255, 0), 1) | |
drawAxis(img, cntr, p2, (0, 0, 255), 3) | |
angle = atan2(eigenvectors[0,1], eigenvectors[0,0]) # orientation in radians | |
## [visualization] | |
angle_deg = -(int(np.rad2deg(angle))-180) % 180 | |
# Label with the rotation angle | |
label = " Rotation Angle: " + str(int(np.rad2deg(angle))) + " degrees" | |
textbox = cv2.rectangle(img, (cntr[0], cntr[1]-25), (cntr[0] + 250, cntr[1] + 10), (255,255,255), -1) | |
cv2.putText(img, label, (cntr[0], cntr[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0), 1, cv2.LINE_AA) | |
return angle_deg | |
def yolov8_inference( | |
image: gr.inputs.Image = None, | |
model_path: gr.inputs.Dropdown = None, | |
image_size: gr.inputs.Slider = 640, | |
conf_threshold: gr.inputs.Slider = 0.25, | |
iou_threshold: gr.inputs.Slider = 0.45, | |
): | |
""" | |
YOLOv8 inference function | |
Args: | |
image: Input image | |
model_path: Path to the model | |
image_size: Image size | |
conf_threshold: Confidence threshold | |
iou_threshold: IOU threshold | |
Returns: | |
Rendered image | |
""" | |
model = YOLO(model_path) | |
model.conf = conf_threshold | |
model.iou = iou_threshold | |
#read image | |
image = cv2.imread(image) | |
#resize image (optional) | |
img_res_toshow = cv2.resize(image, None, fx= 0.5, fy= 0.5, interpolation= cv2.INTER_LINEAR) | |
height=img_res_toshow.shape[0] | |
width=img_res_toshow.shape[1] | |
dim=(width,height) | |
results = model.predict(image, imgsz=image_size, return_outputs=True) | |
#obtain BW image | |
bw=(results[0].masks.masks[0].cpu().numpy() * 255).astype("uint8") | |
#BW image with same dimention of initial image | |
bw=cv2.resize(bw, dim, interpolation = cv2.INTER_AREA) | |
img=img_res_toshow | |
contours, _ = cv2.findContours(bw, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) | |
for i, c in enumerate(contours): | |
# Calculate the area of each contour | |
area = cv2.contourArea(c) | |
# Ignore contours that are too small or too large | |
if area < 3700 or 100000 < area: | |
continue | |
# Draw each contour only for visualisation purposes | |
cv2.drawContours(img, contours, i, (0, 0, 255), 2) | |
# Find the orientation of each shape | |
print(getOrientation(c, img)) | |
return img | |
inputs = [ | |
gr.inputs.Image(type="filepath", label="Input Image"), | |
gr.inputs.Dropdown(["kadirnar/yolov8n-v8.0", "kadirnar/yolov8m-v8.0", "kadirnar/yolov8l-v8.0", "kadirnar/yolov8x-v8.0", "kadirnar/yolov8x6-v8.0"], | |
default="kadirnar/yolov8m-v8.0", label="Model"), | |
gr.inputs.Slider(minimum=320, maximum=1280, default=640, step=32, label="Image Size"), | |
gr.inputs.Slider(minimum=0.0, maximum=1.0, default=0.25, step=0.05, label="Confidence Threshold"), | |
gr.inputs.Slider(minimum=0.0, maximum=1.0, default=0.45, step=0.05, label="IOU Threshold"), | |
] | |
outputs = gr.outputs.Image(type="filepath", label="Output Image") | |
title = "Ultralytics YOLOv8: State-of-the-Art YOLO Models" | |
examples = [['highway.jpg', 'kadirnar/yolov8m-v8.0', 640, 0.25, 0.45], ['highway1.jpg', 'kadirnar/yolov8l-v8.0', 640, 0.25, 0.45], ['small-vehicles1.jpeg', 'kadirnar/yolov8x-v8.0', 1280, 0.25, 0.45]] | |
demo_app = gr.Interface( | |
fn=yolov8_inference, | |
inputs=inputs, | |
outputs=outputs, | |
title=title, | |
examples=examples, | |
cache_examples=True, | |
theme='huggingface', | |
) | |
demo_app.launch(debug=True, enable_queue=True) |