import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
f rom os.path import join
import random
from shutil import copyfile
classes =["aeroplane","bicycle","bird","boat","bottle","bus","car","cat","chair","cow","diningtable","dog","horse","motorbike","person","pottedplant","sheep","sofa","train","tvmonitor"]
TRAIN_RATIO =70defclear_hidden_files(path):
dir_list = os.listdir(path)for i in dir_list:
abspath = os.path.join(os.path.abspath(path), i)if os.path.isfile(abspath):if i.startswith("._"):
os.remove(abspath)else:
clear_hidden_files(abspath)defconvert(size, box):
dw =1./ size[0]
dh =1./ size[1]
x =(box[0]+ box[1])/2.0
y =(box[2]+ box[3])/2.0
w = box[1]- box[0]
h = box[3]- box[2]
x = x * dw
w = w * dw
y = y * dh
h = h * dh
return(x, y, w, h)defconvert_annotation(image_id):
in_file =open('VOCdevkit/VOC2007/Annotations/%s.xml'% image_id)
out_file =open('VOCdevkit/VOC2007/YOLOLabels/%s.txt'% image_id,'w')
tree = ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
w =int(size.find('width').text)
h =int(size.find('height').text)for obj in root.iter('object'):# difficult = obj.find('difficult').text
cls = obj.find('name').text
if cls notin classes:continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
b =(float(xmlbox.find('xmin').text),float(xmlbox.find('xmax').text),float(xmlbox.find('ymin').text),float(xmlbox.find('ymax').text))
bb = convert((w, h), b)
out_file.write(str(cls_id)+" "+" ".join([str(a)for a in bb])+'\n')
in_file.close()
out_file.close()
wd = os.getcwd()
wd = os.getcwd()
data_base_dir = os.path.join(wd,"VOCdevkit/")ifnot os.path.isdir(data_base_dir):
os.mkdir(data_base_dir)
work_sapce_dir = os.path.join(data_base_dir,"VOC2007/")ifnot os.path.isdir(work_sapce_dir):
os.mkdir(work_sapce_dir)
annotation_dir = os.path.join(work_sapce_dir,"Annotations/")ifnot os.path.isdir(annotation_dir):
os.mkdir(annotation_dir)
clear_hidden_files(annotation_dir)
image_dir = os.path.join(work_sapce_dir,"JPEGImages/")ifnot os.path.isdir(image_dir):
os.mkdir(image_dir)
clear_hidden_files(image_dir)
yolo_labels_dir = os.path.join(work_sapce_dir,"YOLOLabels/")ifnot os.path.isdir(yolo_labels_dir):
os.mkdir(yolo_labels_dir)
clear_hidden_files(yolo_labels_dir)
yolov5_images_dir = os.path.join(data_base_dir,"images/")ifnot os.path.isdir(yolov5_images_dir):
os.mkdir(yolov5_images_dir)
clear_hidden_files(yolov5_images_dir)
yolov5_labels_dir = os.path.join(data_base_dir,"labels/")ifnot os.path.isdir(yolov5_labels_dir):
os.mkdir(yolov5_labels_dir)
clear_hidden_files(yolov5_labels_dir)
yolov5_images_train_dir = os.path.join(yolov5_images_dir,"train/")ifnot os.path.isdir(yolov5_images_train_dir):
os.mkdir(yolov5_images_train_dir)
clear_hidden_files(yolov5_images_train_dir)
yolov5_images_test_dir = os.path.join(yolov5_images_dir,"val/")ifnot os.path.isdir(yolov5_images_test_dir):
os.mkdir(yolov5_images_test_dir)
clear_hidden_files(yolov5_images_test_dir)
yolov5_labels_train_dir = os.path.join(yolov5_labels_dir,"train/")ifnot os.path.isdir(yolov5_labels_train_dir):
os.mkdir(yolov5_labels_train_dir)
clear_hidden_files(yolov5_labels_train_dir)
yolov5_labels_test_dir = os.path.join(yolov5_labels_dir,"val/")ifnot os.path.isdir(yolov5_labels_test_dir):
os.mkdir(yolov5_labels_test_dir)
clear_hidden_files(yolov5_labels_test_dir)
train_file =open(os.path.join(wd,"yolov7_train.txt"),'w')
test_file =open(os.path.join(wd,"yolov7_val.txt"),'w')
train_file.close()
test_file.close()
train_file =open(os.path.join(wd,"yolov7_train.txt"),'a')
test_file =open(os.path.join(wd,"yolov7_val.txt"),'a')
list_imgs = os.listdir(image_dir)# list image files
prob = random.randint(1,100)print("Probability: %d"% prob)for i inrange(0,len(list_imgs)):
path = os.path.join(image_dir, list_imgs[i])if os.path.isfile(path):
image_path = image_dir + list_imgs[i]
voc_path = list_imgs[i](nameWithoutExtention, extention)= os.path.splitext(os.path.basename(image_path))(voc_nameWithoutExtention, voc_extention)= os.path.splitext(os.path.basename(voc_path))
annotation_name = nameWithoutExtention +'.xml'
annotation_path = os.path.join(annotation_dir, annotation_name)
label_name = nameWithoutExtention +'.txt'
label_path = os.path.join(yolo_labels_dir, label_name)
prob = random.randint(1,100)print("Probability: %d"% prob)if(prob < TRAIN_RATIO):# train datasetif os.path.exists(annotation_path):
train_file.write(image_path +'\n')
convert_annotation(nameWithoutExtention)# convert label
copyfile(image_path, yolov5_images_train_dir + voc_path)
copyfile(label_path, yolov5_labels_train_dir + label_name)else:# test datasetif os.path.exists(annotation_path):
test_file.write(image_path +'\n')
convert_annotation(nameWithoutExtention)# convert label
copyfile(image_path, yolov5_images_test_dir + voc_path)
copyfile(label_path, yolov5_labels_test_dir + label_name)
train_file.close()
test_file.close()
yolov7 ap精度
defap_per_class(tp, conf, pred_cls, target_cls, v5_metric=False, plot=False, save_dir='.', names=()):""" Compute the average precision, given the recall and precision curves.
Source: https://github.com/rafaelpadilla/Object-Detection-Metrics.
# Arguments
tp: True positives (nparray, nx1 or nx10).
conf: Objectness value from 0-1 (nparray).
pred_cls: Predicted object classes (nparray).
target_cls: True object classes (nparray).
plot: Plot precision-recall curve at mAP@0.5
save_dir: Plot save directory
# Returns
The average precision as computed in py-faster-rcnn.
"""# Sort by objectness# 计算mAP 需要将tp按照conf降序排列# Sort by objectness 按conf从大到小排序 返回数据对应的索引
i = np.argsort(-conf)
tp, conf, pred_cls = tp[i], conf[i], pred_cls[i]# Find unique classes
unique_classes = np.unique(target_cls)
nc = unique_classes.shape[0]# number of classes, number of detections# Create Precision-Recall curve and compute AP for each class
px, py = np.linspace(0,1,1000),[]# for plotting
ap, p, r = np.zeros((nc, tp.shape[1])), np.zeros((nc,1000)), np.zeros((nc,1000))for ci, c inenumerate(unique_classes):
i = pred_cls == c
n_l =(target_cls == c).sum()# number of labels
n_p = i.sum()# number of predictionsif n_p ==0or n_l ==0:continueelse:# Accumulate FPs and TPs
fpc =(1- tp[i]).cumsum(0)
tpc = tp[i].cumsum(0)# Recall
recall = tpc /(n_l +1e-16)# recall curve
r[ci]= np.interp(-px,-conf[i], recall[:,0], left=0)# negative x, xp because xp decreases# Precision
precision = tpc /(tpc + fpc)# precision curve
p[ci]= np.interp(-px,-conf[i], precision[:,0], left=1)# p at pr_score# AP from recall-precision curvefor j inrange(tp.shape[1]):
ap[ci, j], mpre, mrec = compute_ap(recall[:, j], precision[:, j], v5_metric=v5_metric)if plot and j ==0:
py.append(np.interp(px, mrec, mpre))# precision at mAP@0.5# Compute F1 (harmonic mean of precision and recall)
f1 =2* p * r /(p + r +1e-16)if plot:
plot_pr_curve(px, py, ap, Path(save_dir)/'PR_curve.png', names)
plot_mc_curve(px, f1, Path(save_dir)/'F1_curve.png', names, ylabel='F1')
plot_mc_curve(px, p, Path(save_dir)/'P_curve.png', names, ylabel='Precision')
plot_mc_curve(px, r, Path(save_dir)/'R_curve.png', names, ylabel='Recall')
i = f1.mean(0).argmax()# max F1 indexreturn p[:, i], r[:, i], ap, f1[:, i], unique_classes.astype('int32')
detected.py
import argparse
import time
from pathlib import Path
import cv2
import torch
import torch.backends.cudnn as cudnn
from numpy import random
from models.experimental import attempt_load
from utils.datasets import LoadStreams, LoadImages
from utils.general import check_img_size, check_requirements, check_imshow, non_max_suppression, apply_classifier, \
scale_coords, xyxy2xywh, strip_optimizer, set_logging, increment_path
from utils.plots import plot_one_box
from utils.torch_utils import select_device, load_classifier, time_synchronized, TracedModel
defdetect(save_img=False):
source, weights, view_img, save_txt, imgsz, trace = opt.source, opt.weights, opt.view_img, opt.save_txt, opt.img_size,not opt.no_trace
save_img =not opt.nosave andnot source.endswith('.txt')# save inference images
webcam = source.isnumeric()or source.endswith('.txt')or source.lower().startswith(('rtsp://','rtmp://','http://','https://'))# Directories
save_dir = Path(increment_path(Path(opt.project)/ opt.name, exist_ok=opt.exist_ok))# increment run(save_dir /'labels'if save_txt else save_dir).mkdir(parents=True, exist_ok=True)# make dir# Initialize
set_logging()
device = select_device(opt.device)
half = device.type!='cpu'# half precision only supported on CUDA# Load model
model = attempt_load(weights, map_location=device)# load FP32 model
stride =int(model.stride.max())# model stride imgsz = check_img_size(imgsz, s=stride) # check img_sizeif trace:
model = TracedModel(model, device, opt.img_size)if half:
model.half()# to FP16# Second-stage classifier
classify =Falseif classify:
modelc = load_classifier(name='resnet101', n=2)# initialize
modelc.load_state_dict(torch.load('weights/resnet101.pt', map_location=device)['model']).to(device).eval()# Set Dataloader
vid_path, vid_writer =None,Noneif webcam:
view_img = check_imshow()
cudnn.benchmark =True# set True to speed up constant image size inference
dataset = LoadStreams(source, img_size=imgsz, stride=stride)else:
dataset = LoadImages(source, img_size=imgsz, stride=stride)# Get names and colors
names = model.module.names ifhasattr(model,'module')else model.names
colors =[[random.randint(0,255)for _ inrange(3)]for _ in names]# Run inferenceif device.type!='cpu':
model(torch.zeros(1,3, imgsz, imgsz).to(device).type_as(next(model.parameters())))# run once
old_img_w = old_img_h = imgsz
old_img_b =1
t0 = time.time()for path, img, im0s, vid_cap in dataset:
img = torch.from_numpy(img).to(device)
img = img.half()if half else img.float()# uint8 to fp16/32
img /=255.0# 0 - 255 to 0.0 - 1.0if img.ndimension()==3:
img = img.unsqueeze(0)# Warmupif device.type!='cpu'and(old_img_b != img.shape[0]or old_img_h != img.shape[2]or old_img_w != img.shape[3]):
old_img_b = img.shape[0]
old_img_h = img.shape[2]
old_img_w = img.shape[3]for i inrange(3):
model(img, augment=opt.augment)[0]# Inference
t1 = time_synchronized()with torch.no_grad():# Calculating gradients would cause a GPU memory leak
pred = model(img, augment=opt.augment)[0]
t2 = time_synchronized()# Apply NMS
pred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classes=opt.classes, agnostic=opt.agnostic_nms)
t3 = time_synchronized()# Apply Classifierif classify:
pred = apply_classifier(pred, modelc, img, im0s)# Process detectionsfor i, det inenumerate(pred):# detections per imageif webcam:# batch_size >= 1
p, s, im0, frame = path[i],'%g: '% i, im0s[i].copy(), dataset.count
else:
p, s, im0, frame = path,'', im0s,getattr(dataset,'frame',0)
p = Path(p)# to Path
save_path =str(save_dir / p.name)# img.jpg
txt_path =str(save_dir /'labels'/ p.stem)+(''if dataset.mode =='image'elsef'_{frame}')# img.txt
gn = torch.tensor(im0.shape)[[1,0,1,0]]# normalization gain whwh"""
det : tensor([[ -0.87500, 171.75000, 261.50000, 352.75000],
[361.75000, 187.37500, 494.25000, 300.50000],
[203.37500, 173.25000, 348.50000, 312.75000],
[304.50000, 184.50000, 378.50000, 282.75000],
[ -0.93750, 166.37500, 130.75000, 309.50000]], device='cuda:0')
"""iflen(det):# Rescale boxes from img_size to im0 size
det[:,:4]= scale_coords(img.shape[2:], det[:,:4], im0.shape).round()# Print resultsfor 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 resultsfor*xyxy, conf, cls inreversed(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 opt.save_conf else(cls,*xywh)# label formatwithopen(txt_path +'.txt','a')as f:
f.write(('%g '*len(line)).rstrip()% line +'\n')if save_img or view_img:# Add bbox to image
label =f'{names[int(cls)]}{conf:.2f}'
plot_one_box(xyxy, im0, label=label, color=colors[int(cls)], line_thickness=1)# Print time (inference + NMS)print(f'{s}Done. ({(1E3*(t2 - t1)):.1f}ms) Inference, ({(1E3*(t3 - t2)):.1f}ms) NMS')# Stream resultsif view_img:
cv2.imshow(str(p), im0)
cv2.waitKey(1)# 1 millisecond# Save results (image with detections)if save_img:if dataset.mode =='image':
cv2.imwrite(save_path, im0)print(f" The image with the result is saved in: {save_path}")else:# 'video' or 'stream'if vid_path != save_path:# new video
vid_path = save_path
ifisinstance(vid_writer, cv2.VideoWriter):
vid_writer.release()# release previous video writerif vid_cap:# video
fps = vid_cap.get(cv2.CAP_PROP_FPS)
w =int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h =int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))else:# stream
fps, w, h =30, im0.shape[1], im0.shape[0]
save_path +='.mp4'
vid_writer = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps,(w, h))
vid_writer.write(im0)if save_txt or save_img:
s =f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir /'labels'}"if save_txt else''#print(f"Results saved to {save_dir}{s}")print(f'Done. ({time.time()- t0:.3f}s)')if __name__ =='__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--weights', nargs='+',type=str, default='runs/train/exp10/weights/best.pt',help='model.pt path(s)')
parser.add_argument('--source',type=str, default='inference/images',help='source')# file/folder, 0 for webcam
parser.add_argument('--img-size',type=int, default=640,help='inference size (pixels)')
parser.add_argument('--conf-thres',type=float, default=0.25,help='object confidence threshold')
parser.add_argument('--iou-thres',type=float, default=0.45,help='IOU threshold for NMS')
parser.add_argument('--device', default='',help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
parser.add_argument('--view-img', action='store_true',help='display results')
parser.add_argument('--save-txt', action='store_true',help='save results to *.txt')
parser.add_argument('--save-conf', action='store_true',help='save confidences in --save-txt labels')
parser.add_argument('--nosave', action='store_true',help='do not save images/videos')
parser.add_argument('--classes', nargs='+',type=int,help='filter by class: --class 0, or --class 0 2 3')
parser.add_argument('--agnostic-nms', action='store_true',help='class-agnostic NMS')
parser.add_argument('--augment', action='store_true',help='augmented inference')
parser.add_argument('--update', action='store_true',help='update all models')
parser.add_argument('--project', default='runs/detect',help='save results to project/name')
parser.add_argument('--name', default='exp',help='save results to project/name')
parser.add_argument('--exist-ok', action='store_true',help='existing project/name ok, do not increment')
parser.add_argument('--no-trace', action='store_true',help='don`t trace model')
opt = parser.parse_args()print(opt)#check_requirements(exclude=('pycocotools', 'thop'))with torch.no_grad():if opt.update:# update all models (to fix SourceChangeWarning)for opt.weights in['yolov7.pt']:
detect()
strip_optimizer(opt.weights)else:
detect()