UPDATE openvino
This commit is contained in:
@ -13,35 +13,49 @@ import cv2
|
|||||||
import open3d as o3d
|
import open3d as o3d
|
||||||
from Vision.tool.CameraRVC import camera
|
from Vision.tool.CameraRVC import camera
|
||||||
from Vision.yolo.yolov8_pt_seg import yolov8_segment
|
from Vision.yolo.yolov8_pt_seg import yolov8_segment
|
||||||
|
from Vision.yolo.yolov8_openvino import yolov8_segment_openvino
|
||||||
from Vision.tool.utils import find_position
|
from Vision.tool.utils import find_position
|
||||||
|
from Vision.tool.utils import class_names
|
||||||
|
import os
|
||||||
|
|
||||||
class Detection:
|
class Detection:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, use_openvino_model = False):
|
||||||
model_path = './pt_model/best.pt'
|
print(os.getcwd())
|
||||||
|
self.use_openvino_model = use_openvino_model
|
||||||
|
if self.use_openvino_model == False:
|
||||||
|
model_path = ''.join([os.getcwd(), '/model/pt/best.pt'])
|
||||||
device = 'cpu'
|
device = 'cpu'
|
||||||
self.camera_rvc = camera()
|
|
||||||
self.model = yolov8_segment()
|
self.model = yolov8_segment()
|
||||||
self.model.load_model(model_path, device)
|
self.model.load_model(model_path, device)
|
||||||
# if self.camera_rvc.caminit_isok == True:
|
else:
|
||||||
# print("RVC X Camera is opened!")
|
model_path = ''.join([os.getcwd(), '/model/openvino/bset.xml'])
|
||||||
# else:
|
device = 'CPU'
|
||||||
# print("RVC X Camera is not opened!")
|
self.model = yolov8_segment_openvino(model_path, device, conf_thres=0.3, iou_thres=0.3)
|
||||||
|
|
||||||
def get_position(self, Point_isVision=False, first_depth=False):
|
img_path = ''.join([os.getcwd(), '/model/data/test0910.png'])
|
||||||
|
point_path = ''.join([os.getcwd(), '/model/data/test0910.xyz'])
|
||||||
|
self.img = cv2.imread(img_path)
|
||||||
|
self.point = np.loadtxt(point_path).reshape((1080, 1440, 3))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_position(self, Point_isVision=True):
|
||||||
""
|
""
|
||||||
'''
|
'''
|
||||||
:param api:
|
:param api: None
|
||||||
Point_isVision: 点云可视化
|
|
||||||
first_depth: 按Z轴深度返回坐标及向量
|
|
||||||
|
|
||||||
:return: ret , img, (x,y,z), (nx, ny, nz)
|
:return: ret , img, (x,y,z), (nx, ny, nz)
|
||||||
'''
|
'''
|
||||||
ret, img, pm = self.camera_rvc.get_img_and_point_map() # 拍照,获取图像及
|
#ret, img, pm = self.camera_rvc.get_img_and_point_map() # 拍照,获取图像及
|
||||||
if self.camera_rvc.caminit_isok == True:
|
ret = 1
|
||||||
|
img = self.img
|
||||||
|
pm = self.point
|
||||||
if ret == 1:
|
if ret == 1:
|
||||||
|
if self.use_openvino_model == False:
|
||||||
flag, det_cpu, dst_img, masks, category_names = self.model.model_inference(img, 0)
|
flag, det_cpu, dst_img, masks, category_names = self.model.model_inference(img, 0)
|
||||||
|
else:
|
||||||
|
flag, det_cpu, scores, masks, category_names = self.model.segment_objects(img)
|
||||||
|
dst_img = img
|
||||||
if flag == 1:
|
if flag == 1:
|
||||||
xyz = []
|
xyz = []
|
||||||
nx_ny_nz = []
|
nx_ny_nz = []
|
||||||
@ -49,7 +63,7 @@ class Detection:
|
|||||||
Depth_Z = []
|
Depth_Z = []
|
||||||
uv = []
|
uv = []
|
||||||
seg_point = []
|
seg_point = []
|
||||||
if Point_isVision==True:
|
if Point_isVision == True:
|
||||||
pm2 = pm.copy()
|
pm2 = pm.copy()
|
||||||
pm2 = pm2.reshape(-1, 3)
|
pm2 = pm2.reshape(-1, 3)
|
||||||
pm2 = pm2[~np.isnan(pm2).all(axis=-1), :]
|
pm2 = pm2[~np.isnan(pm2).all(axis=-1), :]
|
||||||
@ -62,7 +76,10 @@ class Detection:
|
|||||||
|
|
||||||
# 画box
|
# 画box
|
||||||
box_x1, box_y1, box_x2, box_y2 = item[0:4].astype(np.int32)
|
box_x1, box_y1, box_x2, box_y2 = item[0:4].astype(np.int32)
|
||||||
|
if self.use_openvino_model == False:
|
||||||
label = category_names[int(item[5])]
|
label = category_names[int(item[5])]
|
||||||
|
else:
|
||||||
|
label = class_names[int(item[4])]
|
||||||
rand_color = (0, 255, 255)
|
rand_color = (0, 255, 255)
|
||||||
score = item[4]
|
score = item[4]
|
||||||
org = (int((box_x1 + box_x2) / 2), int((box_y1 + box_y2) / 2))
|
org = (int((box_x1 + box_x2) / 2), int((box_y1 + box_y2) / 2))
|
||||||
@ -74,9 +91,13 @@ class Detection:
|
|||||||
thickness=2)
|
thickness=2)
|
||||||
# 画mask
|
# 画mask
|
||||||
# mask = masks[i].cpu().numpy().astype(int)
|
# mask = masks[i].cpu().numpy().astype(int)
|
||||||
|
if self.use_openvino_model == False:
|
||||||
mask = masks[i].cpu().data.numpy().astype(int)
|
mask = masks[i].cpu().data.numpy().astype(int)
|
||||||
|
else:
|
||||||
|
mask = masks[i].astype(int)
|
||||||
|
mask = mask[box_y1:box_y2, box_x1:box_x2]
|
||||||
|
|
||||||
# mask = masks[i].numpy().astype(int)
|
# mask = masks[i].numpy().astype(int)
|
||||||
bbox_image = img[box_y1:box_y2, box_x1:box_x2]
|
|
||||||
h, w = box_y2 - box_y1, box_x2 - box_x1
|
h, w = box_y2 - box_y1, box_x2 - box_x1
|
||||||
mask_colored = np.zeros((h, w, 3), dtype=np.uint8)
|
mask_colored = np.zeros((h, w, 3), dtype=np.uint8)
|
||||||
mask_colored[np.where(mask)] = rand_color
|
mask_colored[np.where(mask)] = rand_color
|
||||||
@ -108,14 +129,11 @@ class Detection:
|
|||||||
# result = np.zeros_like(color_image)
|
# result = np.zeros_like(color_image)
|
||||||
select_point = []
|
select_point = []
|
||||||
for i in range(pixel_point2.shape[0]):
|
for i in range(pixel_point2.shape[0]):
|
||||||
select_point.append(pm[pixel_point2[i][0][1]+box_y1, pixel_point2[i][0][0]+box_x1])
|
select_point.append(pm[pixel_point2[i][0][1] + box_y1, pixel_point2[i][0][0] + box_x1])
|
||||||
select_point = np.array(select_point)
|
select_point = np.array(select_point)
|
||||||
pm_seg = select_point.reshape(-1, 3)
|
pm_seg = select_point.reshape(-1, 3)
|
||||||
pm_seg = pm_seg[~np.isnan(pm_seg).all(axis=-1), :] # 剔除 nan
|
pm_seg = pm_seg[~np.isnan(pm_seg).all(axis=-1), :] # 剔除 nan
|
||||||
# cv2.imshow('result', piont_result)
|
# cv2.imshow('result', piont_result)
|
||||||
if pm_seg.size < 300:
|
|
||||||
print("分割出的点云数量较少,无法拟合平面!")
|
|
||||||
continue
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
拟合平面,计算法向量
|
拟合平面,计算法向量
|
||||||
@ -126,7 +144,7 @@ class Detection:
|
|||||||
ransac_n=5,
|
ransac_n=5,
|
||||||
num_iterations=5000)
|
num_iterations=5000)
|
||||||
[a, b, c, d] = plane_model
|
[a, b, c, d] = plane_model
|
||||||
#print(f"Plane equation: {a:.2f}x + {b:.2f}y + {c:.2f}z + {d:.2f} = 0")
|
# print(f"Plane equation: {a:.2f}x + {b:.2f}y + {c:.2f}z + {d:.2f} = 0")
|
||||||
|
|
||||||
# inlier_cloud = pcd.select_by_index(inliers) # 点云可视化
|
# inlier_cloud = pcd.select_by_index(inliers) # 点云可视化
|
||||||
# inlier_cloud.paint_uniform_color([1.0, 0, 0])
|
# inlier_cloud.paint_uniform_color([1.0, 0, 0])
|
||||||
@ -155,22 +173,22 @@ class Detection:
|
|||||||
if np.isnan(point_x): # 点云值为无效值
|
if np.isnan(point_x): # 点云值为无效值
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
xyz.append([point_x*1000, point_y*1000, point_z*1000])
|
xyz.append([point_x * 1000, point_y * 1000, point_z * 1000])
|
||||||
Depth_Z.append(point_z*1000)
|
Depth_Z.append(point_z * 1000)
|
||||||
nx_ny_nz.append([a, b, c])
|
nx_ny_nz.append([a, b, c])
|
||||||
RegionalArea.append(cv2.contourArea(max_contour))
|
RegionalArea.append(cv2.contourArea(max_contour))
|
||||||
uv.append([x_rotation_center, y_rotation_center])
|
uv.append([x_rotation_center, y_rotation_center])
|
||||||
seg_point.append(pm_seg)
|
seg_point.append(pm_seg)
|
||||||
cv2.polylines(img, [box], True, (0, 255, 0), 2)
|
cv2.polylines(img, [box], True, (0, 255, 0), 2)
|
||||||
|
|
||||||
_idx = find_position(Depth_Z, RegionalArea, 100, first_depth)
|
_idx = find_position(Depth_Z, RegionalArea, 100, True)
|
||||||
|
|
||||||
if _idx == None:
|
if _idx == None:
|
||||||
return 1, img, None, None
|
return 1, img, None, None
|
||||||
else:
|
else:
|
||||||
cv2.circle(img, (uv[_idx][0], uv[_idx][1]), 30, (255, 0, 0), 20) # 标出中心点
|
cv2.circle(img, (uv[_idx][0], uv[_idx][1]), 30, (0, 0, 255), 20) # 标出中心点
|
||||||
|
|
||||||
if Point_isVision==True:
|
if Point_isVision == True:
|
||||||
pcd = o3d.geometry.PointCloud()
|
pcd = o3d.geometry.PointCloud()
|
||||||
pcd.points = o3d.utility.Vector3dVector(seg_point[_idx])
|
pcd.points = o3d.utility.Vector3dVector(seg_point[_idx])
|
||||||
plane_model, inliers = pcd.segment_plane(distance_threshold=0.01,
|
plane_model, inliers = pcd.segment_plane(distance_threshold=0.01,
|
||||||
@ -190,12 +208,7 @@ class Detection:
|
|||||||
print("RVC X Camera capture failed!")
|
print("RVC X Camera capture failed!")
|
||||||
return 0, None, None, None
|
return 0, None, None, None
|
||||||
|
|
||||||
else:
|
|
||||||
print("RVC X Camera is not opened!")
|
|
||||||
return 0, None, None, None
|
|
||||||
|
|
||||||
def release(self):
|
def release(self):
|
||||||
self.camera_rvc.release()
|
|
||||||
self.model.clear()
|
self.model.clear()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -13,17 +13,27 @@ import cv2
|
|||||||
import open3d as o3d
|
import open3d as o3d
|
||||||
from Vision.tool.CameraRVC import camera
|
from Vision.tool.CameraRVC import camera
|
||||||
from Vision.yolo.yolov8_pt_seg import yolov8_segment
|
from Vision.yolo.yolov8_pt_seg import yolov8_segment
|
||||||
|
from Vision.yolo.yolov8_openvino import yolov8_segment_openvino
|
||||||
from Vision.tool.utils import find_position
|
from Vision.tool.utils import find_position
|
||||||
|
from Vision.tool.utils import class_names
|
||||||
|
import os
|
||||||
|
|
||||||
class Detection:
|
class Detection:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, use_openvino_model = False):
|
||||||
model_path = './pt_model/best.pt'
|
self.use_openvino_model = use_openvino_model
|
||||||
|
if self.use_openvino_model == False:
|
||||||
|
model_path = ''.join([os.getcwd(), '/model/pt/best.pt'])
|
||||||
device = 'cpu'
|
device = 'cpu'
|
||||||
img_path = './pt_model/test0910.png'
|
|
||||||
point_path = './pt_model/test0910.xyz'
|
|
||||||
self.model = yolov8_segment()
|
self.model = yolov8_segment()
|
||||||
self.model.load_model(model_path, device)
|
self.model.load_model(model_path, device)
|
||||||
|
else:
|
||||||
|
model_path = ''.join([os.getcwd(), '/model/openvino/best.xml'])
|
||||||
|
device = 'CPU'
|
||||||
|
self.model = yolov8_segment_openvino(model_path, device, conf_thres=0.3, iou_thres=0.3)
|
||||||
|
|
||||||
|
img_path = ''.join([os.getcwd(), '/model/data/test0910.png'])
|
||||||
|
point_path = ''.join([os.getcwd(), '/model/data/test0910.xyz'])
|
||||||
self.img = cv2.imread(img_path)
|
self.img = cv2.imread(img_path)
|
||||||
self.point = np.loadtxt(point_path).reshape((1080, 1440, 3))
|
self.point = np.loadtxt(point_path).reshape((1080, 1440, 3))
|
||||||
|
|
||||||
@ -39,9 +49,12 @@ class Detection:
|
|||||||
ret = 1
|
ret = 1
|
||||||
img = self.img
|
img = self.img
|
||||||
pm = self.point
|
pm = self.point
|
||||||
|
|
||||||
if ret == 1:
|
if ret == 1:
|
||||||
|
if self.use_openvino_model == False:
|
||||||
flag, det_cpu, dst_img, masks, category_names = self.model.model_inference(img, 0)
|
flag, det_cpu, dst_img, masks, category_names = self.model.model_inference(img, 0)
|
||||||
|
else:
|
||||||
|
flag, det_cpu, scores, masks, category_names = self.model.segment_objects(img)
|
||||||
|
dst_img = img
|
||||||
if flag == 1:
|
if flag == 1:
|
||||||
xyz = []
|
xyz = []
|
||||||
nx_ny_nz = []
|
nx_ny_nz = []
|
||||||
@ -62,7 +75,10 @@ class Detection:
|
|||||||
|
|
||||||
# 画box
|
# 画box
|
||||||
box_x1, box_y1, box_x2, box_y2 = item[0:4].astype(np.int32)
|
box_x1, box_y1, box_x2, box_y2 = item[0:4].astype(np.int32)
|
||||||
|
if self.use_openvino_model == False:
|
||||||
label = category_names[int(item[5])]
|
label = category_names[int(item[5])]
|
||||||
|
else:
|
||||||
|
label = class_names[int(item[4])]
|
||||||
rand_color = (0, 255, 255)
|
rand_color = (0, 255, 255)
|
||||||
score = item[4]
|
score = item[4]
|
||||||
org = (int((box_x1 + box_x2) / 2), int((box_y1 + box_y2) / 2))
|
org = (int((box_x1 + box_x2) / 2), int((box_y1 + box_y2) / 2))
|
||||||
@ -74,9 +90,13 @@ class Detection:
|
|||||||
thickness=2)
|
thickness=2)
|
||||||
# 画mask
|
# 画mask
|
||||||
# mask = masks[i].cpu().numpy().astype(int)
|
# mask = masks[i].cpu().numpy().astype(int)
|
||||||
|
if self.use_openvino_model == False:
|
||||||
mask = masks[i].cpu().data.numpy().astype(int)
|
mask = masks[i].cpu().data.numpy().astype(int)
|
||||||
|
else:
|
||||||
|
mask = masks[i].astype(int)
|
||||||
|
mask = mask[box_y1:box_y2, box_x1:box_x2]
|
||||||
|
|
||||||
# mask = masks[i].numpy().astype(int)
|
# mask = masks[i].numpy().astype(int)
|
||||||
bbox_image = img[box_y1:box_y2, box_x1:box_x2]
|
|
||||||
h, w = box_y2 - box_y1, box_x2 - box_x1
|
h, w = box_y2 - box_y1, box_x2 - box_x1
|
||||||
mask_colored = np.zeros((h, w, 3), dtype=np.uint8)
|
mask_colored = np.zeros((h, w, 3), dtype=np.uint8)
|
||||||
mask_colored[np.where(mask)] = rand_color
|
mask_colored[np.where(mask)] = rand_color
|
||||||
@ -113,9 +133,7 @@ class Detection:
|
|||||||
pm_seg = select_point.reshape(-1, 3)
|
pm_seg = select_point.reshape(-1, 3)
|
||||||
pm_seg = pm_seg[~np.isnan(pm_seg).all(axis=-1), :] # 剔除 nan
|
pm_seg = pm_seg[~np.isnan(pm_seg).all(axis=-1), :] # 剔除 nan
|
||||||
# cv2.imshow('result', piont_result)
|
# cv2.imshow('result', piont_result)
|
||||||
if pm_seg.size < 300:
|
|
||||||
print("分割出的点云数量较少,无法拟合平面!")
|
|
||||||
continue
|
|
||||||
'''
|
'''
|
||||||
拟合平面,计算法向量
|
拟合平面,计算法向量
|
||||||
'''
|
'''
|
||||||
@ -167,7 +185,7 @@ class Detection:
|
|||||||
if _idx == None:
|
if _idx == None:
|
||||||
return 1, img, None, None
|
return 1, img, None, None
|
||||||
else:
|
else:
|
||||||
cv2.circle(img, (uv[_idx][0], uv[_idx][1]), 30, (255, 0, 0), 20) # 标出中心点
|
cv2.circle(img, (uv[_idx][0], uv[_idx][1]), 30, (0, 0, 255), 20) # 标出中心点
|
||||||
|
|
||||||
if Point_isVision == True:
|
if Point_isVision == True:
|
||||||
pcd = o3d.geometry.PointCloud()
|
pcd = o3d.geometry.PointCloud()
|
||||||
@ -185,6 +203,10 @@ class Detection:
|
|||||||
else:
|
else:
|
||||||
return 1, img, None, None
|
return 1, img, None, None
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("RVC X Camera capture failed!")
|
||||||
|
return 0, None, None, None
|
||||||
|
|
||||||
def release(self):
|
def release(self):
|
||||||
self.model.clear()
|
self.model.clear()
|
||||||
|
|
||||||
|
|||||||
BIN
Vision/model/openvino/best.bin
Normal file
BIN
Vision/model/openvino/best.bin
Normal file
Binary file not shown.
9457
Vision/model/openvino/best.xml
Normal file
9457
Vision/model/openvino/best.xml
Normal file
File diff suppressed because it is too large
Load Diff
14
Vision/model/openvino/metadata.yaml
Normal file
14
Vision/model/openvino/metadata.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
description: Ultralytics YOLOv8n-seg model trained on D:\work\ultralytics-main\ultralytics\cfg\datasets\coco8-seg-dy.yaml
|
||||||
|
author: Ultralytics
|
||||||
|
date: '2024-09-10T13:48:59.901222'
|
||||||
|
version: 8.2.86
|
||||||
|
license: AGPL-3.0 License (https://ultralytics.com/license)
|
||||||
|
docs: https://docs.ultralytics.com
|
||||||
|
stride: 32
|
||||||
|
task: segment
|
||||||
|
batch: 1
|
||||||
|
imgsz:
|
||||||
|
- 640
|
||||||
|
- 640
|
||||||
|
names:
|
||||||
|
0: box
|
||||||
@ -8,6 +8,9 @@
|
|||||||
@Date :2024/8/29 15:07
|
@Date :2024/8/29 15:07
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import cv2
|
||||||
|
|
||||||
def find_position(Depth_Z, RegionalArea, RegionalArea_Threshold, first_depth=True):
|
def find_position(Depth_Z, RegionalArea, RegionalArea_Threshold, first_depth=True):
|
||||||
if first_depth == True:
|
if first_depth == True:
|
||||||
sorted_id = sorted(range(len(Depth_Z)), key=lambda k: Depth_Z[k], reverse=False)
|
sorted_id = sorted(range(len(Depth_Z)), key=lambda k: Depth_Z[k], reverse=False)
|
||||||
@ -25,6 +28,157 @@ def find_position(Depth_Z, RegionalArea, RegionalArea_Threshold, first_depth=Tru
|
|||||||
if RegionalArea1[i] > RegionalArea_Threshold:
|
if RegionalArea1[i] > RegionalArea_Threshold:
|
||||||
return sorted_id[i]
|
return sorted_id[i]
|
||||||
|
|
||||||
|
class_names = ['box', 'other']
|
||||||
|
|
||||||
|
# Create a list of colors for each class where each color is a tuple of 3 integer values
|
||||||
|
rng = np.random.default_rng(3)
|
||||||
|
colors = rng.uniform(0, 255, size=(len(class_names), 3))
|
||||||
|
|
||||||
|
|
||||||
|
def nms(boxes, scores, iou_threshold):
|
||||||
|
# Sort by score
|
||||||
|
sorted_indices = np.argsort(scores)[::-1]
|
||||||
|
|
||||||
|
keep_boxes = []
|
||||||
|
while sorted_indices.size > 0:
|
||||||
|
# Pick the last box
|
||||||
|
box_id = sorted_indices[0]
|
||||||
|
keep_boxes.append(box_id)
|
||||||
|
|
||||||
|
# Compute IoU of the picked box with the rest
|
||||||
|
ious = compute_iou(boxes[box_id, :], boxes[sorted_indices[1:], :])
|
||||||
|
|
||||||
|
# Remove boxes with IoU over the threshold
|
||||||
|
keep_indices = np.where(ious < iou_threshold)[0]
|
||||||
|
|
||||||
|
# print(keep_indices.shape, sorted_indices.shape)
|
||||||
|
sorted_indices = sorted_indices[keep_indices + 1]
|
||||||
|
|
||||||
|
return keep_boxes
|
||||||
|
|
||||||
|
|
||||||
|
def compute_iou(box, boxes):
|
||||||
|
# Compute xmin, ymin, xmax, ymax for both boxes
|
||||||
|
xmin = np.maximum(box[0], boxes[:, 0])
|
||||||
|
ymin = np.maximum(box[1], boxes[:, 1])
|
||||||
|
xmax = np.minimum(box[2], boxes[:, 2])
|
||||||
|
ymax = np.minimum(box[3], boxes[:, 3])
|
||||||
|
|
||||||
|
# Compute intersection area
|
||||||
|
intersection_area = np.maximum(0, xmax - xmin) * np.maximum(0, ymax - ymin)
|
||||||
|
|
||||||
|
# Compute union area
|
||||||
|
box_area = (box[2] - box[0]) * (box[3] - box[1])
|
||||||
|
boxes_area = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])
|
||||||
|
union_area = box_area + boxes_area - intersection_area
|
||||||
|
|
||||||
|
# Compute IoU
|
||||||
|
iou = intersection_area / union_area
|
||||||
|
|
||||||
|
return iou
|
||||||
|
|
||||||
|
|
||||||
|
def xywh2xyxy(x):
|
||||||
|
# Convert bounding box (x, y, w, h) to bounding box (x1, y1, x2, y2)
|
||||||
|
y = np.copy(x)
|
||||||
|
y[..., 0] = x[..., 0] - x[..., 2] / 2
|
||||||
|
y[..., 1] = x[..., 1] - x[..., 3] / 2
|
||||||
|
y[..., 2] = x[..., 0] + x[..., 2] / 2
|
||||||
|
y[..., 3] = x[..., 1] + x[..., 3] / 2
|
||||||
|
return y
|
||||||
|
|
||||||
|
|
||||||
|
def sigmoid(x):
|
||||||
|
return 1 / (1 + np.exp(-x))
|
||||||
|
|
||||||
|
|
||||||
|
def draw_detections(image, boxes, scores, class_ids, mask_alpha=0.3, mask_maps=None):
|
||||||
|
img_height, img_width = image.shape[:2]
|
||||||
|
size = min([img_height, img_width]) * 0.0006
|
||||||
|
text_thickness = int(min([img_height, img_width]) * 0.001)
|
||||||
|
|
||||||
|
mask_img = draw_masks(image, boxes, class_ids, mask_alpha, mask_maps)
|
||||||
|
|
||||||
|
# Draw bounding boxes and labels of detections
|
||||||
|
for box, score, class_id in zip(boxes, scores, class_ids):
|
||||||
|
color = colors[class_id]
|
||||||
|
|
||||||
|
x1, y1, x2, y2 = box.astype(int)
|
||||||
|
|
||||||
|
# Draw rectangle
|
||||||
|
cv2.rectangle(mask_img, (x1, y1), (x2, y2), color, 2)
|
||||||
|
|
||||||
|
label = class_names[class_id]
|
||||||
|
caption = f'{label} {int(score * 100)}%'
|
||||||
|
(tw, th), _ = cv2.getTextSize(text=caption, fontFace=cv2.FONT_HERSHEY_SIMPLEX,
|
||||||
|
fontScale=size, thickness=text_thickness)
|
||||||
|
th = int(th * 1.2)
|
||||||
|
|
||||||
|
cv2.rectangle(mask_img, (x1, y1),
|
||||||
|
(x1 + tw, y1 - th), color, -1)
|
||||||
|
|
||||||
|
cv2.putText(mask_img, caption, (x1, y1),
|
||||||
|
cv2.FONT_HERSHEY_SIMPLEX, size, (255, 255, 255), text_thickness, cv2.LINE_AA)
|
||||||
|
|
||||||
|
return mask_img
|
||||||
|
|
||||||
|
|
||||||
|
def draw_masks(image, boxes, class_ids, mask_alpha=0.3, mask_maps=None):
|
||||||
|
mask_img = image.copy()
|
||||||
|
|
||||||
|
# Draw bounding boxes and labels of detections
|
||||||
|
for i, (box, class_id) in enumerate(zip(boxes, class_ids)):
|
||||||
|
color = colors[class_id]
|
||||||
|
|
||||||
|
x1, y1, x2, y2 = box.astype(int)
|
||||||
|
|
||||||
|
# Draw fill mask image
|
||||||
|
if mask_maps is None:
|
||||||
|
cv2.rectangle(mask_img, (x1, y1), (x2, y2), color, -1)
|
||||||
|
else:
|
||||||
|
crop_mask = mask_maps[i][y1:y2, x1:x2, np.newaxis]
|
||||||
|
crop_mask_img = mask_img[y1:y2, x1:x2]
|
||||||
|
crop_mask_img = crop_mask_img * (1 - crop_mask) + crop_mask * color
|
||||||
|
mask_img[y1:y2, x1:x2] = crop_mask_img
|
||||||
|
|
||||||
|
return cv2.addWeighted(mask_img, mask_alpha, image, 1 - mask_alpha, 0)
|
||||||
|
|
||||||
|
|
||||||
|
def draw_comparison(img1, img2, name1, name2, fontsize=2.6, text_thickness=3):
|
||||||
|
(tw, th), _ = cv2.getTextSize(text=name1, fontFace=cv2.FONT_HERSHEY_DUPLEX,
|
||||||
|
fontScale=fontsize, thickness=text_thickness)
|
||||||
|
x1 = img1.shape[1] // 3
|
||||||
|
y1 = th
|
||||||
|
offset = th // 5
|
||||||
|
cv2.rectangle(img1, (x1 - offset * 2, y1 + offset),
|
||||||
|
(x1 + tw + offset * 2, y1 - th - offset), (0, 115, 255), -1)
|
||||||
|
cv2.putText(img1, name1,
|
||||||
|
(x1, y1),
|
||||||
|
cv2.FONT_HERSHEY_DUPLEX, fontsize,
|
||||||
|
(255, 255, 255), text_thickness)
|
||||||
|
|
||||||
|
(tw, th), _ = cv2.getTextSize(text=name2, fontFace=cv2.FONT_HERSHEY_DUPLEX,
|
||||||
|
fontScale=fontsize, thickness=text_thickness)
|
||||||
|
x1 = img2.shape[1] // 3
|
||||||
|
y1 = th
|
||||||
|
offset = th // 5
|
||||||
|
cv2.rectangle(img2, (x1 - offset * 2, y1 + offset),
|
||||||
|
(x1 + tw + offset * 2, y1 - th - offset), (94, 23, 235), -1)
|
||||||
|
|
||||||
|
cv2.putText(img2, name2,
|
||||||
|
(x1, y1),
|
||||||
|
cv2.FONT_HERSHEY_DUPLEX, fontsize,
|
||||||
|
(255, 255, 255), text_thickness)
|
||||||
|
|
||||||
|
combined_img = cv2.hconcat([img1, img2])
|
||||||
|
if combined_img.shape[1] > 3840:
|
||||||
|
combined_img = cv2.resize(combined_img, (3840, 2160))
|
||||||
|
|
||||||
|
return combined_img
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
232
Vision/yolo/yolov8_openvino.py
Normal file
232
Vision/yolo/yolov8_openvino.py
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
# @Time : 2024/9/10 16:33
|
||||||
|
# @Author : hjw
|
||||||
|
# @File : yolov8_openvino.py
|
||||||
|
'''
|
||||||
|
import math
|
||||||
|
import time
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
from openvino.runtime import Core
|
||||||
|
from Vision.tool.utils import xywh2xyxy, nms, draw_detections, sigmoid
|
||||||
|
|
||||||
|
|
||||||
|
class yolov8_segment_openvino:
|
||||||
|
|
||||||
|
def __init__(self, path, device_name="CPU", conf_thres=0.7, iou_thres=0.5, num_masks=32):
|
||||||
|
self.conf_threshold = conf_thres
|
||||||
|
self.iou_threshold = iou_thres
|
||||||
|
self.num_masks = num_masks
|
||||||
|
|
||||||
|
# Initialize model
|
||||||
|
self.initialize_model(path, device_name)
|
||||||
|
|
||||||
|
def __call__(self, image):
|
||||||
|
return self.segment_objects(image)
|
||||||
|
|
||||||
|
def initialize_model(self, path, device_name):
|
||||||
|
self.core = Core()
|
||||||
|
self.net = self.core.compile_model(path, device_name=device_name)
|
||||||
|
self.ir = self.net.create_infer_request()
|
||||||
|
input_shape = self.net.inputs[0].shape
|
||||||
|
self.input_height = input_shape[2]
|
||||||
|
self.input_width = input_shape[3]
|
||||||
|
|
||||||
|
def segment_objects(self, image):
|
||||||
|
input_tensor = self.prepare_input(image)
|
||||||
|
|
||||||
|
# Perform inference on the image
|
||||||
|
outputs = self.ir.infer(input_tensor)
|
||||||
|
|
||||||
|
self.boxes, self.scores, self.class_ids, mask_pred = self.process_box_output(outputs[0])
|
||||||
|
self.mask_maps = self.process_mask_output(mask_pred, outputs[1])
|
||||||
|
self.boxes = self.boxes.tolist()
|
||||||
|
self.scores = self.scores.tolist()
|
||||||
|
for t in range(len(self.scores)):
|
||||||
|
self.boxes[t].append(self.scores[t])
|
||||||
|
|
||||||
|
self.boxes = np.array(self.boxes)
|
||||||
|
if len(self.boxes) == 0:
|
||||||
|
return 0, None, None, None, None
|
||||||
|
else:
|
||||||
|
return 1, self.boxes, self.scores, self.mask_maps, self.class_ids
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_input(self, image):
|
||||||
|
self.img_height, self.img_width = image.shape[:2]
|
||||||
|
|
||||||
|
input_img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
||||||
|
|
||||||
|
# Resize input image
|
||||||
|
input_img = cv2.resize(input_img, (self.input_width, self.input_height))
|
||||||
|
|
||||||
|
# Scale input pixel values to 0 to 1
|
||||||
|
input_img = input_img / 255.0
|
||||||
|
input_img = input_img.transpose(2, 0, 1)
|
||||||
|
input_tensor = input_img[np.newaxis, :, :, :].astype(np.float32)
|
||||||
|
|
||||||
|
return input_tensor
|
||||||
|
|
||||||
|
def process_box_output(self, box_output):
|
||||||
|
|
||||||
|
predictions = np.squeeze(box_output).T
|
||||||
|
num_classes = box_output.shape[1] - self.num_masks - 4
|
||||||
|
|
||||||
|
# Filter out object confidence scores below threshold
|
||||||
|
scores = np.max(predictions[:, 4:4+num_classes], axis=1)
|
||||||
|
predictions = predictions[scores > self.conf_threshold, :]
|
||||||
|
scores = scores[scores > self.conf_threshold]
|
||||||
|
|
||||||
|
if len(scores) == 0:
|
||||||
|
return [], [], [], np.array([])
|
||||||
|
|
||||||
|
box_predictions = predictions[..., :num_classes+4]
|
||||||
|
mask_predictions = predictions[..., num_classes+4:]
|
||||||
|
|
||||||
|
# Get the class with the highest confidence
|
||||||
|
class_ids = np.argmax(box_predictions[:, 4:], axis=1)
|
||||||
|
|
||||||
|
# Get bounding boxes for each object
|
||||||
|
boxes = self.extract_boxes(box_predictions)
|
||||||
|
|
||||||
|
# Apply non-maxima suppression to suppress weak, overlapping bounding boxes
|
||||||
|
indices = nms(boxes, scores, self.iou_threshold)
|
||||||
|
|
||||||
|
return boxes[indices], scores[indices], class_ids[indices], mask_predictions[indices]
|
||||||
|
|
||||||
|
def process_mask_output(self, mask_predictions, mask_output):
|
||||||
|
|
||||||
|
if mask_predictions.shape[0] == 0:
|
||||||
|
return []
|
||||||
|
|
||||||
|
mask_output = np.squeeze(mask_output)
|
||||||
|
|
||||||
|
# Calculate the mask maps for each box
|
||||||
|
num_mask, mask_height, mask_width = mask_output.shape # CHW
|
||||||
|
masks = sigmoid(mask_predictions @ mask_output.reshape((num_mask, -1)))
|
||||||
|
masks = masks.reshape((-1, mask_height, mask_width))
|
||||||
|
|
||||||
|
# Downscale the boxes to match the mask size
|
||||||
|
scale_boxes = self.rescale_boxes(self.boxes,
|
||||||
|
(self.img_height, self.img_width),
|
||||||
|
(mask_height, mask_width))
|
||||||
|
|
||||||
|
# For every box/mask pair, get the mask map
|
||||||
|
mask_maps = np.zeros((len(scale_boxes), self.img_height, self.img_width))
|
||||||
|
blur_size = (int(self.img_width / mask_width), int(self.img_height / mask_height))
|
||||||
|
for i in range(len(scale_boxes)):
|
||||||
|
|
||||||
|
scale_x1 = int(math.floor(scale_boxes[i][0]))
|
||||||
|
scale_y1 = int(math.floor(scale_boxes[i][1]))
|
||||||
|
scale_x2 = int(math.ceil(scale_boxes[i][2]))
|
||||||
|
scale_y2 = int(math.ceil(scale_boxes[i][3]))
|
||||||
|
|
||||||
|
x1 = int(math.floor(self.boxes[i][0]))
|
||||||
|
y1 = int(math.floor(self.boxes[i][1]))
|
||||||
|
x2 = int(math.ceil(self.boxes[i][2]))
|
||||||
|
y2 = int(math.ceil(self.boxes[i][3]))
|
||||||
|
|
||||||
|
scale_crop_mask = masks[i][scale_y1:scale_y2, scale_x1:scale_x2]
|
||||||
|
crop_mask = cv2.resize(scale_crop_mask,
|
||||||
|
(x2 - x1, y2 - y1),
|
||||||
|
interpolation=cv2.INTER_CUBIC)
|
||||||
|
|
||||||
|
crop_mask = cv2.blur(crop_mask, blur_size)
|
||||||
|
|
||||||
|
crop_mask = (crop_mask > 0.5).astype(np.uint8)
|
||||||
|
mask_maps[i, y1:y2, x1:x2] = crop_mask
|
||||||
|
return mask_maps
|
||||||
|
|
||||||
|
def extract_boxes(self, box_predictions):
|
||||||
|
# Extract boxes from predictions
|
||||||
|
boxes = box_predictions[:, :4]
|
||||||
|
|
||||||
|
# Scale boxes to original image dimensions
|
||||||
|
boxes = self.rescale_boxes(boxes,
|
||||||
|
(self.input_height, self.input_width),
|
||||||
|
(self.img_height, self.img_width))
|
||||||
|
|
||||||
|
# Convert boxes to xyxy format
|
||||||
|
boxes = xywh2xyxy(boxes)
|
||||||
|
|
||||||
|
# Check the boxes are within the image
|
||||||
|
boxes[:, 0] = np.clip(boxes[:, 0], 0, self.img_width)
|
||||||
|
boxes[:, 1] = np.clip(boxes[:, 1], 0, self.img_height)
|
||||||
|
boxes[:, 2] = np.clip(boxes[:, 2], 0, self.img_width)
|
||||||
|
boxes[:, 3] = np.clip(boxes[:, 3], 0, self.img_height)
|
||||||
|
return boxes
|
||||||
|
|
||||||
|
def draw_detections(self, image, draw_scores=True, mask_alpha=0.4):
|
||||||
|
return draw_detections(image, self.boxes, self.scores,
|
||||||
|
self.class_ids, mask_alpha)
|
||||||
|
|
||||||
|
def draw_masks(self, image, draw_scores=True, mask_alpha=0.5):
|
||||||
|
return draw_detections(image, self.boxes, self.scores,
|
||||||
|
self.class_ids, mask_alpha, mask_maps=self.mask_maps)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def rescale_boxes(boxes, input_shape, image_shape):
|
||||||
|
# Rescale boxes to original image dimensions
|
||||||
|
input_shape = np.array([input_shape[1], input_shape[0], input_shape[1], input_shape[0]])
|
||||||
|
boxes = np.divide(boxes, input_shape, dtype=np.float32)
|
||||||
|
boxes *= np.array([image_shape[1], image_shape[0], image_shape[1], image_shape[0]])
|
||||||
|
return boxes
|
||||||
|
|
||||||
|
# frame = cv2.imread('../1.png')
|
||||||
|
# # frame = cv2.resize(frame,(640,640))
|
||||||
|
# model_path = ("../runs/segment/train2/weights/last-0903_openvino_model/last-0903.xml")
|
||||||
|
# #model_path = ("../yolov8n-seg_openvino_model/yolov8n-seg.xml")
|
||||||
|
# device_name = "GPU"
|
||||||
|
# yoloseg = yolov8_segment_openvino(model_path, device_name, conf_thres=0.3, iou_thres=0.3)
|
||||||
|
#
|
||||||
|
# start = time.time()
|
||||||
|
# boxes, scores, class_ids, masks = yoloseg(frame)
|
||||||
|
# # postprocess and draw masks
|
||||||
|
# combined_img = yoloseg.draw_masks(frame)
|
||||||
|
# end = time.time()
|
||||||
|
# # show FPS
|
||||||
|
# print(end- start)
|
||||||
|
# fps = (1 / (end - start))
|
||||||
|
# fps_label = "Throughput: %.2f FPS" % fps
|
||||||
|
# cv2.putText(combined_img, fps_label, (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
|
||||||
|
# cv2.imwrite('rs2.jpg', combined_img)
|
||||||
|
# # show ALL
|
||||||
|
# cv2.imshow("YOLOv8 Segmentation OpenVINO inference Demo", combined_img)
|
||||||
|
#
|
||||||
|
# cv2.waitKey(0)
|
||||||
|
|
||||||
|
# # Initialize the VideoCapture
|
||||||
|
# cap = cv2.VideoCapture("store-aisle-detection.mp4")
|
||||||
|
# img = cv2.imread('../1.png')
|
||||||
|
# # Initialize YOLOv5 Instance Segmentator
|
||||||
|
# model_path = "yolov8n-seg.xml"
|
||||||
|
# device_name = "GPU"
|
||||||
|
# yoloseg = YOLOSeg(model_path, device_name, conf_thres=0.3, iou_thres=0.3)
|
||||||
|
|
||||||
|
# while cap.isOpened():
|
||||||
|
# # Read frame from the video
|
||||||
|
# ret, frame = cap.read()
|
||||||
|
# if not ret:
|
||||||
|
# break
|
||||||
|
# # Update object localizer
|
||||||
|
# start = time.time()
|
||||||
|
# boxes, scores, class_ids, masks = yoloseg(frame)
|
||||||
|
# # postprocess and draw masks
|
||||||
|
# combined_img = yoloseg.draw_masks(frame)
|
||||||
|
# end = time.time()
|
||||||
|
# # show FPS
|
||||||
|
# fps = (1 / (end - start))
|
||||||
|
# fps_label = "Throughput: %.2f FPS" % fps
|
||||||
|
# cv2.putText(combined_img, fps_label, (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
|
||||||
|
# # show ALL
|
||||||
|
# cv2.imshow("YOLOv8 Segmentation OpenVINO inference Demo", combined_img)
|
||||||
|
#
|
||||||
|
# # Press Any key stop
|
||||||
|
# if cv2.waitKey(1) > -1:
|
||||||
|
# print("finished by user")
|
||||||
|
# break
|
||||||
|
#
|
||||||
|
# cap.release()
|
||||||
|
# cv2.destroyAllWindows()
|
||||||
Reference in New Issue
Block a user