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 try_load from utils.datasets import LoadStreams、 LoadImages from utils.general import check_img_size、check_requirements、non_max_classifier、apply 、scale_coords、\ xyxy2xywh、strip_optimizer、set_logging、utils.plots からのincrement_path import plot_one_box from utils.torch_utils import select_device、load_classifier、time_synchronized defdetect (save_img = False): #source:テストデータ、または画像/ビデオパスにすることができます「0」(コンピューターにはカメラが付属しています)、またはrtspなどのビデオストリームにすることができます。 です。#view_img表示/ビデオ、デフォルトはFalseかどうかの予測後、画像 #save_txt予測されたフレーム座標がtxtファイルとして保存されるかどうかにかかわらず、デフォルトはFalse です。#imgszネットワーク入力画像 ソースのサイズ、重み、view_img、save_txt、imgsz = opt.source、opt.weights、opt.view_img、opt .save_txt、opt。img_size #isnumeric ()メソッドは、文字列が数字のみで構成されているかどうかを検出します #lower()大文字は小文字に変換されます。指定された文字列 webcam = source.isnumeric()またはsourceで始まります。 extendswith( '。txt')またはsource.lower()。startswith( ( 'rtsp://'、 'rtmp://'、 'http://')) #ディレクトリ save_dir = Path(increment_path(Path(opt .project)/ opt.name、exist_ok = opt.exist_ok))#増分実行 (save_dir / 'labels' if save_txt else save_dir).mkdir(parents = True、exist_ok = True) #make dir #初期化set_logging()#Select 端末 device = select_device(opt.device) modelc.load_state_dict(torch.load(' weights / resnet101.pt '、map_location = device)[' model '])。to(device).eval()をデータローダーを 設定します half = device.type!= 'cpu'#CUDAでのみサポートされる半精度 #モデルのロード model = try_load(weights、map_location = device)#FP32モデルのロード stride = int(model.stride.max())#モデルのストライド imgsz = check_img_size(imgsz、s = stride)# 半分の場合はimg_sizeをチェック: model.half()#FP16へ #第2段階の分類子 classify =分類する 場合はFalse : modelc = load_classifier(name = 'resnet101'、n = 2)#初期化 vid_path、vid_writer = None、None #ウェブ サイトの場合:#view_img = True #cudnn.benchmark = True#一定の画像サイズの推測を高速化するためにTrueを設定 #dataset = LoadStreams(source、img_size = imgsz、stride = stride) #else :save_img =真の データセット= LoadImages(source、img_size = imgsz、stride = stride) print(dataset) #名前と色を取得 names = model.module.names if hasattr(model、 'module')else model.names colors = [[random .randint(0、255)for _ in range(3)] for _ in names] # device.type!= 'cpu'の場合に推論を実行します。 model(torch.zeros(1、3、imgsz、imgsz).to(device).type_as(next(model.parameters())))#1回実行 t0 = time.time() #img0 = cv2.imread(path ) #path〉片/视频路径#img進む行 サイズ+ pad之后的 #img0原サイズ図片 #キャップのは、画像を読み取る場合はNoneであり、ビデオを読み取る場合はビデオソースです。 〉データセット内のパス、img、im0s、vid_capの場合: img = torch.from_numpy(img).to(device) img = img.half()if half else img.float()#uint8〜fp16 / 32 img / = 255.0#0-255〜0.0-1.0 if img.ndimension()== 3: img = img.unsqueeze(0) #推論 t1 = time_synchronized() pred = model(img、augment = opt.augment)[0] #NMSを 適用する#NMSを 適用する "" " pred:順伝播の出力 conf_thres:信頼しきい値 iou_thres:iouしきい値 クラス:特定のカテゴリのみを保持するかどうか をし、enumerate(pred)でdet:#画像ごとの検出 依存しない:nmsを実行し、異なるカテゴリ間のボックスを削除するかどうかnmsの 後、予測ボックスの形式:xywh-> xyxy(左上隅と右下隅) predはリストリスト[torch.tensor]、長さはbatch_size 、各torch.tensorの形状は(num_boxes、6)、内容はbox + conf + cls "" " pred = non_max_suppression(pred、opt。 conf_thres、opt。iou_thres、classes = opt.classes、agnostic = opt.agnostic_nms) t2 = time_synchronized() #分類子の適用# 二次分類を追加します 。classifyの 場合はデフォルトでは使用されません:pred = apply_classifier(pred、modelc、img、im0s) #検出を処理する # サイトの各画像を処理する#batch_size p、s、im0、frame = path [i]、 '%g:'%i、im0s [i] .copy()、dataset.count else: ウェブ場合: > = 1 座標形式はxyxyです #getattr(dataset、 'frame'、0)获取dataset中的文字列值frame、不存在戻る回0 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)+( '' ifdataset.mode == ' image'else f'_ {frame} ')#img.txt s + ='%gx%g '%img.shape [2:]#文字列を出力 gn = torch.tensor(im0.shape)[[1、0 、1、0]]#正規化ゲインwhhh if len(det): #ボックスをimg_sizeからim0サイズに再スケールします det [:、:4] = scale_coords(img.shape [2:]、det [:、:4]、im0.shape).round() #結果を 出力し ます、-1] .unique(): n =(det [:、-1] == c).sum()#クラスごとの検出 s + = f "{n} {names [int(c)]} {' s '*(n> 1)}、 "#文字列に追加 # * xyxy、conf、clsの結果をreversed(det)に 書き込む:if save_txt:#ファイルに 書き込むxywh =(xyxy2xywh(torch.tensor(xyxy))。 view(1、4))/ gn).view(-1).tolist()#正規化されたxywh line =(cls、* xywh、conf)if opt.save_conf else(cls、* xywh)#ラベル形式 open(txt_path + '。txt'、 ' a ')as f: f.write(('%g '* len(line))。rstrip()%line +' \ n ') if save_img or view_img:#画像にbboxを追加#出力 ラベルとスコア値 label = f '{names [int(cls)]} {conf:.2f}' # カテゴリとスコアボックス情報を描画plot_one_box(xyxy、im0、label = label、color = colors [int(cls)]、line_thickness = 5) #印刷時間(推論+ NMS) print(f '{s}完了。({t2-t1:.3f} s)') # view_img: cv2。imshowの場合に結果をストリーミング(str(p)、im0) #結果を保存します(検出された画像) if save_img: if dataset.mode == 'image': cv2.imwrite(save_path、im0) else:# 'video' if vid_path!= save_path:#新しいビデオ vid_path = save_path if isinstance(vid_writer、cv2.VideoWriter): vid_writer.release()#前のビデオライターを 解放するfourcc = 'mp4v'#出力ビデオコーデック 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)) vid_writer = cv2.VideoWriter(save_path、cv2.VideoWriter_fourcc(* fourcc)、fps、(w、 ) save_txt またはsave_imgの場合はvid_writer.write(im0): s = f "\ n {len(list(save_dir.glob( 'labels / *。txt')))}ラベルを{save_dir / 'labels'}"に 保存ifsave_txt else '' print(f "結果を{に保存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 = 'yolov5s.pt'、help = 'model.pt path(s)') parser.add_argument( '-weights'、nargs = '+ '、type = str、default ='。/ runs / train / exp29 / weights / best.pt '、help =' model.pt path(s) ') parser.add_argument( ' ' 、type = str、default = 'data / images'、help = 'ソース ')#ファイル/フォルダー、ウェブカメラの場合は0 parser.add_argument('-img-size '、type = int、default = 640、help = '推論サイズ(ピクセル)') #Confidence output threshold parser.add_argument( '-conf-thres'、type = float、default = 0.25、help = 'objectconfidencethreshold') parser.add_argument( '-iou-thres'、type = float、default = 0.45、help = 'NMSのIOUしきい値') parser.add_argument( '-device'、default = ''、help = 'cuda device、つまり、0または0,1,2,3またはcpu ') parser.add_argument('-view-img '、action =' store_true '、help =' display results ') parser.add_argument('-save-txt ' 、action = 'store_true'、help = '結果を* .txtに保存') parser.add_argument( '-save-conf'、action = 'store_true'、help = '信頼性を--save-txtラベルに保存') parser.add_argument( '-augment'、action = 'store_true'、help = '拡張推論 ') parser.add_argument('-update '、action =' store_true '、help ='すべてのモデルを更新 ') parser.add_argument( '-classes'、nargs = '+'、type = int、 help = 'クラスでフィルタリング:-class 0、または--class 0 2 3 ') parser.add_argument( '-agnostic-nms'、action = 'store_true'、help = 'class-agnostic NMS') -project #重みの optおよびその他の情報を削除します parser.add_argument( '-project'、default = 'runs / detect'、help = '結果をプロジェクト/名前に保存') parser.add_argument( '-name'、default = 'exp'、help = '結果を保存to project / name ') parser.add_argument('-exist-ok '、action =' store_true '、help =' existing project / name ok、do not incremental ') opt = parser.parse_args() print(opt) check_requirements () with torch.no_grad(): if opt.update:# ['yolov5s.pt'、 'yolov5m.pt'、 'yolov5l.pt'、 'yolov5xのopt.weightsのすべてのモデルを(SourceChangeWarningを修正するために)更新します。 pt ']: detect() strip_optimizer(opt.weights) else: detect()
yolov5検出コードの詳細な説明
おすすめ
転載: blog.csdn.net/qq_16792139/article/details/114025854
ランキング