源码fork自 该版本,代码注释借鉴多处,仅供个人学习记录。
YOLOv3 代码梳理
0.文件结构
- config: 配置文件,包含超参数、网络结构等信息
- data: 训练图片、训练标签等信息
- pytorchyolo:项目需要使用到的工具代码,运行代码
- weights: 权重文件
0.1 config:
├── coco.data
├── create_custom_model.sh # 创建自定义.cfg用的脚本
├── custom.data
├── yolov3-tiny.cfg # 模型定义文件
├── yolov3.cfg # 模型定义文件
0.1.1 coco.data:
coco数据的配置文件
classes= 80
train=data/coco/trainvalno5k.txt
valid=data/coco/5k.txt
names=data/coco.names
backup=backup/
eval=coco
class=80
表示类别的数量
train=data/coco/trainvalno5k.txt
valid=data/coco/5k.txt
coco数据集的训练集数据地址和验证集数据地址
backup=backup/
备份文件
eval=coco
0.1.2 create_custom_model.sh
create_custom_model.sh是用来执行自定义模型的文件,建自定义.cfg用的脚本
0.1.3 custom.data:
classes= 1 # 类别数量
train=data/custom/train.txt # 存放训练集图片地址的txt
valid=data/custom/valid.txt # 存放验证集图片地址的txt
names=data/custom/classes.names # 类别名称
0.2 data:
── coco
│ └── 5k.txt
├── coco.names
├── custom
│ ├── classes.names
│ ├── images
│ │ └── train.jpg
│ ├── labels
│ │ └── train.txt
│ ├── train.txt
│ └── valid.txt
├── get_coco_dataset.sh
└── samples
0.2.1 custom
这里的customer文件夹配合上面的custom.data,就是完整的自定义训练集的配置文件了。
images:存放训练验证图片
labels: (可通过代码将xml格式文件进行转换)存放YOLO格式的标签 其中每一个.txt对应images中一个.jpg;.txt中每一行对应一个gt框。坐标均除以原图的长宽以归一化。第一个是标签号,从0开始 中心点x坐标 中心点y坐标 标注框的宽 标注框的高。
classes.names:这里面写的是所有类别的标签,标签用换行符隔开,最后一行末尾没有换行符。类别名称的顺序与类别标号对应
train.txt: 训练数据的地址
valid.txt: 验证数据的地址
1 推理介绍
detect.py 文件
该文件的作用、推理过程:
1、配置参数。
2、加载模型。
3、加载数据。
4、推理&绘制
1.1 配置参数
parser = argparse.ArgumentParser(description="Detect objects on images.")
parser.add_argument("-m", "--model", type=str, default="config/yolov3.cfg", help="Path to model definition file (.cfg)") #网络结构
parser.add_argument("-w", "--weights", type=str, default="weights/yolov3.weights", help="Path to weights or checkpoint file (.weights or .pth)") #权重文件
parser.add_argument("-i", "--images", type=str, default="data/samples", help="Path to directory with images to inference")# 推理图片路径
parser.add_argument("-c", "--classes", type=str, default="data/coco.names", help="Path to classes label file (.names)") # 类别名称
parser.add_argument("-o", "--output", type=str, default="output", help="Path to output directory") # 输出路径
parser.add_argument("-b", "--batch_size", type=int, default=1, help="Size of each image batch")
parser.add_argument("--img_size", type=int, default=416, help="Size of each image dimension for yolo")
parser.add_argument("--n_cpu", type=int, default=0, help="Number of cpu threads to use during batch generation")
parser.add_argument("--conf_thres", type=float, default=0.5, help="Object confidence threshold") # 置信度阈值
parser.add_argument("--nms_thres", type=float, default=0.4, help="IOU threshold for non-maximum suppression") # nms阈值
args = parser.parse_args()
1.2 加载模型
进入detect_directory 开始推理
def detect_directory(...):
dataloader = _create_data_loader(img_path, batch_size, img_size, n_cpu)
model = load_model(model_path, weights_path)
img_detections, imgs = detect(model,dataloader, output_path, conf_thres,nms_thres)
_draw_and_save_output_images(img_detections, imgs, img_size, output_path, classes)
model = load_model(model_path, weights_pat 加载模型
def load_model(model_path, weights_path=None):
device = torch.device("cuda" if torch.cuda.is_available()
else "cpu") # Select device for inference
model = Darknet(model_path).to(device)
model.apply(weights_init_normal)
# If pretrained weights are specified, start from checkpoint or weight file
if weights_path:
if weights_path.endswith(".pth"):
# Load checkpoint weights
model.load_state_dict(torch.load(weights_path, map_location=device))
else:
# Load darknet weights
model.load_darknet_weights(weights_path)
return model
这里利用自定义的Darknet——一个自定义的nn.Module——来解析模型的网络结构文件(yolov3.cfg)
yolov3.cfg文件
见博客 https://editor.youkuaiyun.com/md/?articleId=131627851
Darknet类
这个类在models.py里面。该类的init方法里面,就将配置文件转化为以nn.ModuleList表示的网络结构了。
models.py ->class Darknet(nn.Modules)
class Darknet(nn.Module):
"""YOLOv3 object detection model"""
def __init__(self, config_path):
super(Darknet, self).__init__()
self.module_defs = parse_model_config(config_path)
## 使用 parse_model_config函数 解析.cfg文件,输出的是一个包含配置信息的list
self.hyperparams, self.module_list = create_modules(self.module_defs)
## 使用 create_modules函数, 输出配置信息list,得到网络的超参数hyperparams和nn.Modulelist(module_list)
self.yolo_layers =