diff --git a/.gitignore b/.gitignore index fedfb88a..3f5edbe0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,12 @@ weights/ runs/ data/widok01-11_images +data/widok01-11_labels +data/widok01-11_labels.npy .idea/ +experiments/ MY_INFO *.pyc +*.pyx +*.jpg \ No newline at end of file diff --git a/detect.py b/detect.py index 0c4b17b3..626a28f3 100644 --- a/detect.py +++ b/detect.py @@ -6,9 +6,10 @@ from utils.utils import * def detect(save_img=False): - imgsz = (320, 192) if ONNX_EXPORT else opt.img_size # (320, 192) or (416, 256) or (608, 352) for (height, width) + imgsz = (320, 192) if ONNX_EXPORT else opt.test_img_size # (320, 192) or (416, 256) or (608, 352) for (height, width) out, source, weights, half, view_img, save_txt = opt.output, opt.source, opt.weights, opt.half, opt.view_img, opt.save_txt - webcam = source == '0' or source.startswith('rtsp') or source.startswith('http') or source.endswith('.txt') + #webcam = source == '0' or source.startswith('rtsp') or source.startswith('http') or source.endswith('.txt') + webcam = False # Initialize device = torch_utils.select_device(device='cpu' if ONNX_EXPORT else opt.device) @@ -171,7 +172,7 @@ if __name__ == '__main__': parser.add_argument('--weights', type=str, default='weights/yolov3-spp-ultralytics.pt', help='weights path') parser.add_argument('--source', type=str, default='data/samples', help='source') # input file/folder, 0 for webcam parser.add_argument('--output', type=str, default='output', help='output folder') # output folder - parser.add_argument('--img-size', type=int, default=512, help='inference size (pixels)') + parser.add_argument('--test-img-size', type=int, default=512, help='inference size (pixels)') parser.add_argument('--conf-thres', type=float, default=0.3, help='object confidence threshold') parser.add_argument('--iou-thres', type=float, default=0.6, help='IOU threshold for NMS') parser.add_argument('--fourcc', type=str, default='mp4v', help='output video codec (verify ffmpeg support)') @@ -188,4 +189,4 @@ if __name__ == '__main__': print(opt) with torch.no_grad(): - detect() + detect(True) diff --git a/our_scripts/config.py b/our_scripts/config.py new file mode 100644 index 00000000..d2ca923d --- /dev/null +++ b/our_scripts/config.py @@ -0,0 +1,67 @@ +from typing import Any + +import yaml + + +class Args: + + def get_args_string(self) -> str: + string = '' + for key, value in self.__dict__.items(): + if not isinstance(value, Configuration.Train.OtherHyps) and value is not None: + if key == 'img-size': + string += f' --{key} {value.split(" ")[0]} {value.split(" ")[1]}' + elif type(value) == bool: + if value: + string += f" --{key}" + else: + continue + elif type(value) in [int, str] and value != '': + string += f' --{key} {value}' + else: + raise Exception(f"Cannot parse argument {key} {value}") + + return string + +class Configuration: + class Train(Args): + + class OtherHyps: + def __init__(self, config_file) -> None: + for key, value in config_file['train']['other-hyps'].items(): + self.__dict__[key] = value + + def __init__(self, config_file) -> None: + self.other_hyps = Configuration.Train.OtherHyps(config_file) + for key, value in config_file['train'].items(): + if key != 'other-hyps': + self.__dict__[key] = value + + class Experiments(Args): + def __init__(self, config_file) -> None: + for key, value in config_file['experiments'].items(): + self.__dict__[key] = value + + class Detect(Args): + def __init__(self, config_file) -> None: + for key, value in config_file['detect'].items(): + self.__dict__[key] = value + + class ConfussionMatrix(Args): + def __init__(self, config_file) -> None: + for key, value in config_file['confussion-matrix'].items(): + self.__dict__[key] = value + + class Bayes(Args): + def __init__(self, config_file) -> None: + for key, value in config_file['bayes'].items(): + self.__dict__[key] = value + + def __init__(self, config_path='/home/tomekb/yolov3/our_scripts/config.yml') -> None: + self.config_path = config_path + file = yaml.load(open(config_path, 'r'), Loader=yaml.Loader) + self.train = self.Train(file) + self.experiments = self.Experiments(file) + self.detect = self.Detect(file) + self.confussion_matrix = self.ConfussionMatrix(file) + self.bayes = self.Bayes(file) diff --git a/our_scripts/config.yml b/our_scripts/config.yml new file mode 100644 index 00000000..93679407 --- /dev/null +++ b/our_scripts/config.yml @@ -0,0 +1,58 @@ +train: + epochs: 2 + batch-size: 400 + cfg: ./cfg/yolov3-spp-18cls.cfg + data: ./data/widok01-11.data + multi-scale: false + img-size: '64 128' + rect: false + resume: false + nosave: false + notest: false + evolve: false + bucket: + cache-images: false + weights: /home/tomekb/yolov3/weights/yolov3-spp-ultralytics.pt + device: 1 + adam: true + single-cls: false + + # inne hiperparametry + other-hyps: + giou: 3.53 # giou loss gain + cls: 37.4 # cls loss gain + cls_pw: 1.0 # cls BCELoss positive_weight + obj: 64.3 # obj loss gain (*=img_size/320 if img_size != 320) + obj_pw: 1.0 # obj BCELoss positive_weight + iou_t: 0.20 # iou training threshold + lr0: 0.01 # initial learning rate (SGD=5E-3 Adam=5E-4) + lrf: 0.0005 # final learning rate (with cos scheduler) + momentum: 0.937 # SGD momentum + weight_decay: 0.0005 # optimizer weight decay + fl_gamma: 0.0 # focal loss gamma (efficientDet default is gamma=1.5) + hsv_h: 0.0138 # image HSV-Hue augmentation (fraction) + hsv_s: 0.678 # image HSV-Saturation augmentation (fraction) + hsv_v: 0.36 # image HSV-Value augmentation (fraction) + degrees: 0 # 1.98 * 0 # image rotation (+/- deg) + translate: 0 # 0.05 * 0 # image translation (+/- fraction) + scale: 0 #0 .05 * 0 # image scale (+/- gain) + shear: 0 # 0.641 * 0 # image shear (+/- deg) + +experiments: + dir: ./experiments +detect: + source: /home/michall/yolov3/data/widok01-11_test_labels.txt + test-img-size: 1024 + conf-thres: 0.3 + iou-thres: 0.6 + save-txt: true + classes: + agnostic-nms: + augment: +confussion-matrix: + labels-dir: ./data/widok01-11_labels +bayes: + todo: todo + + + diff --git a/our_scripts/generate-confusion-matrix.js b/our_scripts/generate-confusion-matrix.js new file mode 100644 index 00000000..312f3f77 --- /dev/null +++ b/our_scripts/generate-confusion-matrix.js @@ -0,0 +1,178 @@ +const fs = require('fs') +const path = require('path') + +const detectionsDir = process.argv[2] +const labelsDir = process.argv[3] +const namesFile = process.argv[4] +const maxDistance = process.argv[5] || 0.1 +const width = process.argv[6] || 1920 +const height = process.argv[7] || 1080 + +/* +console.log("DETECTIONS DIRECTORY:", detectionsDir) +console.log("LABELS DIRECTORY:", labelsDir) +console.log("NAMES FILE:", namesFile) +console.log("WIDTH", width) +console.log("HEIGHT", height) +//*/ + +function parseDetections(detectionData) { + return detectionData + .split('\n') + .filter(x => !!x) + .map(line => line.split(' ').map(x => +x)) + .map(a => ({ + x: (a[0] + a[2]) / ( 2 * width ), + y: (a[1] + a[3]) / ( 2 * height ), + w: (a[2] - a[0]) / width, + h: (a[3] - a[1]) / height, + c: a[4], + p: a[5] + })) +} + +function parseLabels(labelData) { + return labelData + .split('\n') + .filter(x => !!x) + .map(line => line.split(' ').map(x => +x)) + .map(a => ({ + x: a[1], + y: a[2], + w: a[3], + h: a[4], + c: a[0], + p: 1 + })) +} + +function findNearest(position, boxes) { + let dx = position.x - boxes[0].x + let dy = position.y - boxes[0].y + let bestBox = { ...boxes[0], d: Math.sqrt(dx * dx + dy * dy) } + for(let i = 1; i < boxes.length; i++) { + dx = position.x - boxes[i].x + dy = position.y - boxes[i].y + let distance = Math.sqrt(dx * dx + dy * dy) + if(distance < bestBox.d) { + bestBox = { ...boxes[i], d: distance } + } + } + return bestBox +} + +function compare(labels, detections) { + const results = {} + for(const label of labels) { + const detection = findNearest(label, detections) + if(detection.d > maxDistance) { + if(!results[label.c]) results[label.c] = {} + results[label.c]['n'] = + (results[label.c]['n'] || 0) + 1 + } else { + if(!results[label.c]) results[label.c] = {} + results[label.c][detection.c] = (results[label.c][detection.c] || 0) + 1 + } + } + for(const detection of detections) { + const label = findNearest(detection, labels) + if(label.d > maxDistance) { + results['n'] = results['n'] || {} + results['n'][detection.c] = + (results['n'][detection.c] || 0) + 1 + } + } + return results +} + +async function compareLabelsAndResults(txt) { + const detectionPath = path.resolve(detectionsDir, txt) + const basename = path.basename(txt.split('.')[0]) + const labelPath = path.resolve(labelsDir, basename+'.txt') + const [detectionData, labelData] = await Promise.all([fs.promises.readFile(detectionPath, 'utf8'), fs.promises.readFile(labelPath, 'utf8')]) + const detections = parseDetections(detectionData) + const labels = parseLabels(labelData) + + return { + basename, + result: compare(labels, detections) + } +} + +async function main() { + const names = (await fs.promises.readFile(namesFile, 'utf8')).split('\n').map(t=>t.trim()) + names.n = '?' + names.sum = 'sum' + const files = await fs.promises.readdir(detectionsDir) + const txts = files.filter(p => path.extname(p) == '.txt') + //console.log("OUTPUT TXT FILES", txts.length) + const promises = txts.map(compareLabelsAndResults) + const compareResults = await Promise.all(promises) + await fs.promises.mkdir(path.resolve(detectionsDir, 'errors')).catch(e => {}) + const summary = {} + const copyPromises = [] + for(const result of compareResults) { + let errors = [] + for(const c in result.result) { + if(!summary[c]) summary[c] = {} + for(const r in result.result[c]) { + summary[c][r] = (summary[c][r] || 0) + result.result[c][r] + if( c!=r ) errors.push([c, r, result.result[c][r]]) + } + } + if(errors.length > 0) { + copyPromises.push(fs.promises.copyFile( + path.resolve(detectionsDir, result.basename + '.jpg'), + path.resolve(detectionsDir, 'errors', result.basename + '.jpg') + )) + copyPromises.push(fs.promises.writeFile( + path.resolve(detectionsDir, 'errors', result.basename + '.tsv'), + errors.map(([c1,c2,cnt]) => [ names[c1], names[c2], cnt ].join('\t')).join('\n'), 'utf8')) + } + } + //console.log("S", summary) + let rows = Object.keys(summary).filter(k=>k!='n').sort().concat(['n']) + summary.sum = {} + for(const row of rows) { + if(!summary[row]) summary[row] = {} + const rowSum = rows.map(r => summary[row][r] || 0).reduce( (a, b) => a + b, 0) + const columnSum = rows.map(r => summary[r] && summary[r][row] || 0).reduce( (a, b) => a + b, 0) + summary[row].sum = rowSum + summary.sum[row] = columnSum + } + summaryRows = rows.concat(['sum']) + let tsvRows = [] + tsvRows.push('Count:') + tsvRows.push([' ', ...(summaryRows.map(n=>names[n]))].join('\t')) + for(const row of summaryRows) { + const summaryPart = summary[row] || {} + tsvRows.push([ names[row], ...(summaryRows.map(r => summaryPart[r]))].join('\t')) + } + + summaryRows.pop() + tsvRows.push('Fraction:') + tsvRows.push([' ', ...(summaryRows.map(n=>names[n]))].join('\t')) + for(const row of summaryRows) { + const summaryPart = summary[row] || {} + const sum = row != 'sum' ? summaryPart.sum : summary.sum[row] + tsvRows.push([ names[row], ...(summaryRows.map(r => summaryPart[r] && (summaryPart[r] / sum).toFixed(2)))].join('\t')) + } + + const allLabeled = rows.slice(0, -1).map(r => summary.sum[r]).reduce((a, b) => a + b, 0) + const allDetected = rows.slice(0, -1).map(r => summary[r].sum).reduce((a, b) => a + b, 0) + const falseNegatives = rows.slice(0, -1).map(r => summary.n[r] || 0).reduce((a, b) => a + b, 0) + const falsePositives = rows.slice(0, -1).map(r => summary[r].n || 0).reduce((a, b) => a + b, 0) + const right = rows.slice(0, -1).map(r => summary[r][r] || 0).reduce((a, b) => a + b, 0) + const mistakes = rows.slice(0, -1).map(a => rows.slice(0, -1).map(b => (a!=b && summary[a][b]) || 0).reduce((a, b) => a + b, 0)).reduce((a, b) => a + b, 0) + + console.log(`right:\t${right}\t${(right/allLabeled).toFixed(3)}`) + console.log(`false positives:\t${falsePositives}\t${(falsePositives/allLabeled).toFixed(3)}`) + console.log(`false negatives:\t${falseNegatives}\t${(falseNegatives/allLabeled).toFixed(3)}`) + console.log(`mistakes:\t${mistakes}\t${(mistakes/allLabeled).toFixed(3)}`) + console.log(`labeled:\t${allLabeled}`) + console.log(`detected:\t${allDetected}`) + + let tsv = tsvRows.join('\n') + console.log(tsv) + await Promise.all(copyPromises) +} + +main() diff --git a/our_scripts/generate_txt_from_xml.py b/our_scripts/generate_txt_from_xml.py new file mode 100644 index 00000000..0d38d0f2 --- /dev/null +++ b/our_scripts/generate_txt_from_xml.py @@ -0,0 +1,151 @@ +# - *- coding: utf- 8 - *- +import sys +import os +import re +import xml.etree.ElementTree as ET +from glob import glob +from os.path import join +from pathlib import Path + +# This should just be a folder of xmls +annotations = sys.argv[1] +# Then you have a folder of txts. +modified_annotations = sys.argv[2] + + +def convert(size, box): + dw = 1. / (size[0]) + dh = 1. / (size[1]) + x = (box[0] + box[1]) / 2.0 - 1 + y = (box[2] + box[3]) / 2.0 - 1 + w = box[1] - box[0] + h = box[3] - box[2] + x = round(x * dw, 4) + w = round(w * dw, 4) + y = round(y * dh, 4) + h = round(h * dh, 4) + return (x, y, w, h) + + +def map_class_name_to_id(class_name, xml_document, class_distribution): + if class_name in ['1. rower']: + class_distribution[0] += 1 + return 0 + elif class_name in ['2. motocykl']: + class_distribution[1] += 1 + return 1 + elif class_name in ['3. osobowy']: + class_distribution[2] += 1 + return 2 + elif class_name in ['4. osobowy pickup']: + class_distribution[3] += 1 + return 3 + elif class_name in ['5. osobowy dostawczy']: + class_distribution[4] += 1 + return 4 + elif class_name in ['6. osobowy van 7-9']: + class_distribution[5] += 1 + return 5 + elif class_name in ['7. dostawczy blaszak']: + class_distribution[6] += 1 + return 6 + elif class_name in ['8. dostawczy zabudowany']: + class_distribution[7] += 1 + return 7 + elif class_name in ['9. dostawczy pickup (w tym pomoc drog.)']: + class_distribution[8] += 1 + return 8 + elif class_name in ['10. dostawczy VAN (osobowy)']: + class_distribution[9] += 1 + return 9 + elif class_name in ['11. autobus mały 10-24']: + return -1 + elif class_name in ['12. autobus miejski']: + class_distribution[10] += 1 + return 10 + elif class_name in ['13. autobus turystyczny i inny']: + return -1 + elif class_name in ['14. ciężarowy pow. 3,5t zabudowany']: + class_distribution[11] += 1 + return 11 + elif class_name in ['15. ciężarowy pow. 3,5t otwarty (w tym duży holownik)']: + class_distribution[12] += 1 + return 12 + elif class_name in ['16. ciężarowy pow. 3,5t inny (wanna, gruszka, dźwig itp.)']: + class_distribution[13] += 1 + return 13 + elif class_name in ['17. ciężarowy z widoczną przyczepą']: + return -1 + elif class_name in ['18. ciągnik siodłowy z widoczną naczepą']: + class_distribution[14] += 1 + return 14 + elif class_name in ['19. ciągnik siodłowy bez naczepy']: + class_distribution[15] += 1 + return 15 + elif class_name in ['20. camper']: + class_distribution[15] += 1 + return -1 + elif class_name in ['22. ciągnik roliczy, koparka, spychacz']: + return -1 + elif class_name in ['23. inne pojazdy silnikowe']: + return -1 + elif class_name in ['24. przyczepa']: + class_distribution[16] += 1 + return 16 + elif class_name in ['25. BUS-karetka/policja']: + class_distribution[17] += 1 + return 17 + else: + raise Exception('Unknown Class ', xml_document, class_name) + + +def generate_txt_from_xml(): + class_distribution = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + + filepaths = glob(annotations + '*.xml') + for filepath in filepaths: + txtpath = join(modified_annotations, re.sub(r"\.xml$", ".txt", os.path.basename(filepath))) + + in_file = open(filepath, mode='r', encoding='utf-8') + + tree = ET.parse(in_file) + root = tree.getroot() + size = root.find('size') + w = int(size.find('width').text) + h = int(size.find('height').text) + + good_file = True + + for obj in root.iter('object'): + #difficult = obj.find('difficult').text + class_label = obj.find('name').text + #if int(difficult) == 1: + # raise Exception("Difficult == 1") + cls_id = map_class_name_to_id(class_label, filepath, class_distribution) + if cls_id == -1 : + good_file = False + + if not good_file : + print('File discarded.') + continue + + Path(txtpath).touch() + out_file = open(txtpath, mode='w', encoding='utf-8') + + for obj in root.iter('object'): + #difficult = obj.find('difficult').text + class_label = obj.find('name').text + #if int(difficult) == 1: + # raise Exception("Difficult == 1") + cls_id = map_class_name_to_id(class_label, filepath, class_distribution) + if cls_id != -1 : + 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') + + + print(class_distribution) + +generate_txt_from_xml() diff --git a/our_scripts/run_yolov3_process.py b/our_scripts/run_yolov3_process.py new file mode 100644 index 00000000..bbc7bc60 --- /dev/null +++ b/our_scripts/run_yolov3_process.py @@ -0,0 +1,100 @@ +import argparse +import datetime +import glob +import io +import ntpath +import os +import shutil +import subprocess + +from config import Configuration + + +def call_training_script(config): + cmd = '/home/tomekb/miniconda3/envs/conda3.7/bin/python -u /home/tomekb/yolov3/train.py ' + cmd += config.train.get_args_string() + print("_______ CALLING TRAINING SCRIPT _______") + print(cmd) + + os.chdir('..') + process = subprocess.Popen(cmd, stdout=subprocess.PIPE,shell=True) + for line in io.TextIOWrapper(process.stdout, encoding="utf-8"): # print output of training process to console + print(line) + return cmd + +def move_training_results_to_experiments_dir(config): + training_results_dir_path = os.path.join(config.experiments.dir, datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')) + print("_______ CALLING MOVING RESULTS _______") + print(f"MOVING RESUTLS TO {training_results_dir_path}") + + + os.mkdir(training_results_dir_path) + + weights_path = os.path.join(training_results_dir_path, 'best.pt') + shutil.move('/home/tomekb/yolov3/weights/best.pt', weights_path) #move best weights + + names_path = open(config.train.data).readlines()[3].split('=')[-1].rstrip() # read names path from file + names_file_name = ntpath.basename(names_path) + experiment_names_path = os.path.join(training_results_dir_path, names_file_name) + shutil.copy(names_path, experiment_names_path) # copy names to created experiment dir with training results + + tensorboard_dir = './runs' + last_modified_tensorboard_dir = max(glob.glob(os.path.join(tensorboard_dir, '*/')), key=os.path.getmtime) + shutil.move(last_modified_tensorboard_dir, os.path.join(training_results_dir_path)) #saving related tensorboard dir + + shutil.copy2(config.config_path, training_results_dir_path) #copying configuration yaml + + + #for test purposes only + shutil.copy2('/home/tomekb/yolov3/experiments/1/best.pt', training_results_dir_path) + + return weights_path, experiment_names_path, training_results_dir_path + + +def call_detection_script(config, weights_path, names_path, dir): + detect_output_dir = os.path.join(dir, 'output') + cmd = f"""/home/tomekb/miniconda3/envs/conda3.7/bin/python -u /home/tomekb/yolov3/detect.py + --cfg {config.train.cfg} + --source {config.detect.source} + --output {detect_output_dir} + --names {names_path} + --weights {weights_path} + --test-img-size {getattr(config.detect, 'test-img-size')} + --conf-thres {getattr(config.detect, 'conf-thres')} + --iou-thres {getattr(config.detect, 'iou-thres')}""" + cmd += " --save-txt" if getattr(config.detect, 'save-txt') else "" + cmd += " --agnostic-nms" if getattr(config.detect, 'agnostic-nms') else "" + cmd += " --agument" if getattr(config.detect, 'augment') else "" + cmd += f" --device {config.train.device}" if config.train.device else "" + + cmd = " ".join(cmd.split()) + + + print("_______ CALLING DETECTION SCRIPT _______") + print(cmd) + + process = subprocess.Popen(cmd, stdout=subprocess.PIPE,shell=True) + for line in io.TextIOWrapper(process.stdout, encoding="utf-8"): # print output of process to console + print(line) + return detect_output_dir + + +def call_generate_confussion_matrix(detect_output_dir, config, names_path, train_results_dir): + labels_dir = getattr(config.confussion_matrix, 'labels-dir') + + cmd = f"node ./our_scripts/generate-confusion-matrix.js {detect_output_dir} {labels_dir} {names_path} > {train_results_dir}/confussion-matrix.tsv" + process = subprocess.Popen(cmd, stdout=subprocess.PIPE,shell=True) + print("_______ CALLING CONFUSSION MATRIX SCRIPT _______") + print(cmd) + for line in io.TextIOWrapper(process.stdout, encoding="utf-8"): # print output of process to console + print(line) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + config = Configuration() + + train_cmd = call_training_script(config) + weights_path, names_path,train_results_dir = move_training_results_to_experiments_dir(config) + detect_output_dir = call_detection_script(config, weights_path, names_path,train_results_dir) + call_generate_confussion_matrix(detect_output_dir, config, names_path,train_results_dir) diff --git a/our_scripts/run_yolov3_process.sh b/our_scripts/run_yolov3_process.sh new file mode 100644 index 00000000..8c0b9cc9 --- /dev/null +++ b/our_scripts/run_yolov3_process.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +/home/tomekb/miniconda3/envs/conda3.7/bin/python -u /home/tomekb/yolov3/our_scripts/run_yolov3_process.py \ +--epochs 50 \ +--batch-size 8 \ +--cfg /cfg/yolov3-spp-18cls.cfg \ +--data ./data/widok01-11.data \ +--multi-scale \ +--img-size 512 896 \ +`# --cache-images` \ +--adam \ +--device 0 \ +`# poniżej parametry do detect.py` \ +--source /home/michall/yolov3/data/widok01-11_test_labels.txt \ +--test-img-size 1024 \ +--conf-thres 0.3 \ +--iou-thres 0.6 \ +--save-txt \ +`# poniżej parametry do generate-confussion-matrix.js` \ +--labels-dir ./data/widok01-11_labels + diff --git a/train.py b/train.py index f963fdf1..620cbf04 100644 --- a/train.py +++ b/train.py @@ -9,6 +9,8 @@ import test # import test.py to get mAP after each epoch from models import * from utils.datasets import * from utils.utils import * +from our_scripts.config import Configuration + mixed_precision = True try: # Mixed precision training https://github.com/NVIDIA/apex @@ -399,7 +401,7 @@ if __name__ == '__main__': check_git_status() opt.cfg = check_file(opt.cfg) # check file opt.data = check_file(opt.data) # check file - print(opt) + #print(opt) opt.img_size.extend([opt.img_size[-1]] * (3 - len(opt.img_size))) # extend to 3 sizes (min, max, test) device = torch_utils.select_device(opt.device, apex=mixed_precision, batch_size=opt.batch_size) if device.type == 'cpu': @@ -408,6 +410,10 @@ if __name__ == '__main__': # scale hyp['obj'] by img_size (evolved at 320) # hyp['obj'] *= opt.img_size[0] / 320. + + hyp = Configuration().train.other_hyps.__dict__ + + tb_writer = None if not opt.evolve: # Train normally print('Start Tensorboard with "tensorboard --logdir=runs", view at http://localhost:6006/') diff --git a/utils/datasets.py b/utils/datasets.py index 5811142a..b73c9e8c 100755 --- a/utils/datasets.py +++ b/utils/datasets.py @@ -44,11 +44,10 @@ def exif_size(img): class LoadImages: # for inference def __init__(self, path, img_size=416): path = str(Path(path)) # os-agnostic - files = [] - if os.path.isdir(path): - files = sorted(glob.glob(os.path.join(path, '*.*'))) - elif os.path.isfile(path): - files = [path] + files = [f.strip() for f in open(path, 'r').readlines()] + + + images = [x for x in files if os.path.splitext(x)[-1].lower() in img_formats] videos = [x for x in files if os.path.splitext(x)[-1].lower() in vid_formats]