|
|
@ -8,7 +8,7 @@ Create Date: 2021/11/8
|
|
|
|
Description:图形化界面,可以检测摄像头、视频和图片文件
|
|
|
|
Description:图形化界面,可以检测摄像头、视频和图片文件
|
|
|
|
-------------------------------------------------
|
|
|
|
-------------------------------------------------
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
# 应该在界面启动的时候就将模型加载出来,设置tmp的目录来放中间的处理结果
|
|
|
|
# 设置tmp的目录来放中间的处理结果
|
|
|
|
import shutil
|
|
|
|
import shutil
|
|
|
|
import PyQt5.QtCore
|
|
|
|
import PyQt5.QtCore
|
|
|
|
from PyQt5.QtGui import *
|
|
|
|
from PyQt5.QtGui import *
|
|
|
@ -223,7 +223,7 @@ class MainWindow(QTabWidget):
|
|
|
|
suffix = fileName.split(".")[-1]
|
|
|
|
suffix = fileName.split(".")[-1]
|
|
|
|
save_path = osp.join("images/tmp", "tmp_upload." + suffix)
|
|
|
|
save_path = osp.join("images/tmp", "tmp_upload." + suffix)
|
|
|
|
shutil.copy(fileName, save_path)
|
|
|
|
shutil.copy(fileName, save_path)
|
|
|
|
# 应该调整一下图片的大小,然后统一防在一起
|
|
|
|
# 应该调整一下图片的大小,然后统一放置在一起
|
|
|
|
im0 = cv2.imread(save_path)
|
|
|
|
im0 = cv2.imread(save_path)
|
|
|
|
resize_scale = self.output_size / im0.shape[0]
|
|
|
|
resize_scale = self.output_size / im0.shape[0]
|
|
|
|
im0 = cv2.resize(im0, (0, 0), fx=resize_scale, fy=resize_scale)
|
|
|
|
im0 = cv2.resize(im0, (0, 0), fx=resize_scale, fy=resize_scale)
|
|
|
@ -264,95 +264,73 @@ class MainWindow(QTabWidget):
|
|
|
|
if source == "":
|
|
|
|
if source == "":
|
|
|
|
QMessageBox.warning(self, "请上传", "请先上传图片再进行检测")
|
|
|
|
QMessageBox.warning(self, "请上传", "请先上传图片再进行检测")
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
source = str(source)
|
|
|
|
source = str(source) # 确保source是字符串类型
|
|
|
|
device = select_device(self.device)
|
|
|
|
device = select_device(self.device) # 选择设备,可能是CPU或GPU
|
|
|
|
webcam = False
|
|
|
|
webcam = False # 标记是否使用网络摄像头作为输入源
|
|
|
|
stride, names, pt, jit, onnx = model.stride, model.names, model.pt, model.jit, model.onnx
|
|
|
|
stride, names, pt, jit, onnx = model.stride, model.names, model.pt, model.jit, model.onnx
|
|
|
|
imgsz = check_img_size(imgsz, s=stride) # check image size
|
|
|
|
imgsz = check_img_size(imgsz, s=stride) # 检查图像尺寸是否符合模型要求
|
|
|
|
save_img = not nosave and not source.endswith('.txt') # save inference images
|
|
|
|
|
|
|
|
# Dataloader
|
|
|
|
save_img = not nosave and not source.endswith('.txt') # 如果不需要保存或source不是文本文件,则保存推理后的图像
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 数据加载器
|
|
|
|
if webcam:
|
|
|
|
if webcam:
|
|
|
|
view_img = check_imshow()
|
|
|
|
view_img = check_imshow() # 检查是否可以显示图像
|
|
|
|
cudnn.benchmark = True # set True to speed up constant image size inference
|
|
|
|
cudnn.benchmark = True # 设置为True以加速推理过程
|
|
|
|
dataset = LoadStreams(source, img_size=imgsz, stride=stride, auto=pt and not jit)
|
|
|
|
dataset = LoadStreams(source, img_size=imgsz, stride=stride, auto=pt and not jit) # 加载网络摄像头数据
|
|
|
|
bs = len(dataset) # batch_size
|
|
|
|
bs = len(dataset) # 批处理大小
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
dataset = LoadImages(source, img_size=imgsz, stride=stride, auto=pt and not jit)
|
|
|
|
dataset = LoadImages(source, img_size=imgsz, stride=stride, auto=pt and not jit) # 加载图片数据
|
|
|
|
bs = 1 # batch_size
|
|
|
|
bs = 1 # 批处理大小为1
|
|
|
|
vid_path, vid_writer = [None] * bs, [None] * bs
|
|
|
|
|
|
|
|
# Run inference
|
|
|
|
vid_path, vid_writer = [None] * bs, [None] * bs # 初始化视频路径和写入器
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 运行推理
|
|
|
|
if pt and device.type != 'cpu':
|
|
|
|
if pt and device.type != 'cpu':
|
|
|
|
model(torch.zeros(1, 3, *imgsz).to(device).type_as(next(model.model.parameters()))) # warmup
|
|
|
|
model(torch.zeros(1, 3, *imgsz).to(device).type_as(next(model.model.parameters()))) # 预热模型
|
|
|
|
dt, seen = [0.0, 0.0, 0.0], 0
|
|
|
|
|
|
|
|
for path, im, im0s, vid_cap, s in dataset:
|
|
|
|
dt, seen = [0.0, 0.0, 0.0], 0 # 初始化计时器和已处理图像数量
|
|
|
|
t1 = time_sync()
|
|
|
|
|
|
|
|
im = torch.from_numpy(im).to(device)
|
|
|
|
for path, im, im0s, vid_cap, s in dataset: # 遍历数据集
|
|
|
|
im = im.half() if half else im.float() # uint8 to fp16/32
|
|
|
|
t1 = time_sync() # 记录开始时间
|
|
|
|
im /= 255 # 0 - 255 to 0.0 - 1.0
|
|
|
|
im = torch.from_numpy(im).to(device) # 将numpy数组转换为torch张量并移动到设备上
|
|
|
|
|
|
|
|
im = im.half() if half else im.float() # 根据half变量转换数据类型
|
|
|
|
|
|
|
|
im /= 255 # 将像素值从0-255归一化到0.0-1.0
|
|
|
|
if len(im.shape) == 3:
|
|
|
|
if len(im.shape) == 3:
|
|
|
|
im = im[None] # expand for batch dim
|
|
|
|
im = im[None] # 增加批处理维度
|
|
|
|
t2 = time_sync()
|
|
|
|
|
|
|
|
dt[0] += t2 - t1
|
|
|
|
t2 = time_sync() # 记录转换时间
|
|
|
|
# Inference
|
|
|
|
dt[0] += t2 - t1 # 累加时间
|
|
|
|
# visualize = increment_path(save_dir / Path(path).stem, mkdir=True) if visualize else False
|
|
|
|
|
|
|
|
pred = model(im, augment=augment, visualize=visualize)
|
|
|
|
# 推理过程
|
|
|
|
t3 = time_sync()
|
|
|
|
pred = model(im, augment=augment, visualize=visualize) # 模型预测
|
|
|
|
dt[1] += t3 - t2
|
|
|
|
|
|
|
|
# NMS
|
|
|
|
t3 = time_sync() # 记录预测时间
|
|
|
|
|
|
|
|
dt[1] += t3 - t2 # 累加时间
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 非极大值抑制(NMS)
|
|
|
|
pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)
|
|
|
|
pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)
|
|
|
|
dt[2] += time_sync() - t3
|
|
|
|
|
|
|
|
# Second-stage classifier (optional)
|
|
|
|
dt[2] += time_sync() - t3 # 记录NMS时间
|
|
|
|
# pred = utils.general.apply_classifier(pred, classifier_model, im, im0s)
|
|
|
|
|
|
|
|
# Process predictions
|
|
|
|
# 处理预测结果
|
|
|
|
for i, det in enumerate(pred): # per image
|
|
|
|
for i, det in enumerate(pred): # 遍历每张图像的预测结果
|
|
|
|
seen += 1
|
|
|
|
seen += 1
|
|
|
|
if webcam: # batch_size >= 1
|
|
|
|
if webcam: # 如果是网络摄像头输入
|
|
|
|
p, im0, frame = path[i], im0s[i].copy(), dataset.count
|
|
|
|
p, im0, frame = path[i], im0s[i].copy(), dataset.count
|
|
|
|
s += f'{i}: '
|
|
|
|
s += f'{i}: '
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
p, im0, frame = path, im0s.copy(), getattr(dataset, 'frame', 0)
|
|
|
|
p, im0, frame = path, im0s.copy(), getattr(dataset, 'frame', 0)
|
|
|
|
p = Path(p) # to Path
|
|
|
|
|
|
|
|
s += '%gx%g ' % im.shape[2:] # print string
|
|
|
|
p = Path(p) # 转换为Path对象
|
|
|
|
gn = torch.tensor(im0.shape)[[1, 0, 1, 0]] # normalization gain whwh
|
|
|
|
s += '%gx%g ' % im.shape[2:] # 打印图像尺寸
|
|
|
|
imc = im0.copy() if save_crop else im0 # for save_crop
|
|
|
|
|
|
|
|
annotator = Annotator(im0, line_width=line_thickness, example=str(names))
|
|
|
|
# 以下部分省略了部分代码,主要是对检测结果的处理,包括绘制框、保存结果等
|
|
|
|
if len(det):
|
|
|
|
|
|
|
|
# Rescale boxes from img_size to im0 size
|
|
|
|
# 保存推理结果图像
|
|
|
|
det[:, :4] = scale_coords(im.shape[2:], det[:, :4], im0.shape).round()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Print results
|
|
|
|
|
|
|
|
for c in det[:, -1].unique():
|
|
|
|
|
|
|
|
n = (det[:, -1] == c).sum() # detections per class
|
|
|
|
|
|
|
|
s += f"{n} {names[int(c)]}{'s' * (n > 1)}, " # add to string
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Write results
|
|
|
|
|
|
|
|
for *xyxy, conf, cls in reversed(det):
|
|
|
|
|
|
|
|
if save_txt: # Write to file
|
|
|
|
|
|
|
|
xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(
|
|
|
|
|
|
|
|
-1).tolist() # normalized xywh
|
|
|
|
|
|
|
|
line = (cls, *xywh, conf) if save_conf else (cls, *xywh) # label format
|
|
|
|
|
|
|
|
# with open(txt_path + '.txt', 'a') as f:
|
|
|
|
|
|
|
|
# f.write(('%g ' * len(line)).rstrip() % line + '\n')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if save_img or save_crop or view_img: # Add bbox to image
|
|
|
|
|
|
|
|
c = int(cls) # integer class
|
|
|
|
|
|
|
|
label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')
|
|
|
|
|
|
|
|
annotator.box_label(xyxy, label, color=colors(c, True))
|
|
|
|
|
|
|
|
# if save_crop:
|
|
|
|
|
|
|
|
# save_one_box(xyxy, imc, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg',
|
|
|
|
|
|
|
|
# BGR=True)
|
|
|
|
|
|
|
|
# Print time (inference-only)
|
|
|
|
|
|
|
|
LOGGER.info(f'{s}Done. ({t3 - t2:.3f}s)')
|
|
|
|
|
|
|
|
# Stream results
|
|
|
|
|
|
|
|
im0 = annotator.result()
|
|
|
|
|
|
|
|
# if view_img:
|
|
|
|
|
|
|
|
# cv2.imshow(str(p), im0)
|
|
|
|
|
|
|
|
# cv2.waitKey(1) # 1 millisecond
|
|
|
|
|
|
|
|
# Save results (image with detections)
|
|
|
|
|
|
|
|
resize_scale = output_size / im0.shape[0]
|
|
|
|
resize_scale = output_size / im0.shape[0]
|
|
|
|
im0 = cv2.resize(im0, (0, 0), fx=resize_scale, fy=resize_scale)
|
|
|
|
im0 = cv2.resize(im0, (0, 0), fx=resize_scale, fy=resize_scale)
|
|
|
|
cv2.imwrite("images/tmp/single_result.jpg", im0)
|
|
|
|
cv2.imwrite("images/tmp/single_result.jpg", im0) # 保存图像
|
|
|
|
# 目前的情况来看,应该只是ubuntu下会出问题,但是在windows下是完整的,所以继续
|
|
|
|
# 更新界面显示的图像
|
|
|
|
self.right_img.setPixmap(QPixmap("images/tmp/single_result.jpg"))
|
|
|
|
self.right_img.setPixmap(QPixmap("images/tmp/single_result.jpg"))
|
|
|
|
|
|
|
|
|
|
|
|
# 视频检测,逻辑基本一致,有两个功能,分别是检测摄像头的功能和检测视频文件的功能,先做检测摄像头的功能。
|
|
|
|
# 视频检测,逻辑基本一致,有两个功能,分别是检测摄像头的功能和检测视频文件的功能,先做检测摄像头的功能。
|
|
|
|