这次主要是针对yolov3执行测试过程的代码解析,第一部分是主体train文件代码解析,第二部分是针对utils文件代码解析,第三部分是针对config文件代码解析
第一部分 针对train文件代码解析
yolov3文件代码可以在Tensorflow2.0:Yolo v3代码详解(一)找到
import cv2
import os
import shutil
import numpy as np
import tensorflow as tf
import core.utils as utils
from core.config import cfg
from core.yolov3 import YOLOv3, decode
INPUT_SIZE = 416 # 输入模型时图片的尺寸
NUM_CLASS = len(utils.read_class_names(cfg.YOLO.CLASSES)) # 类别的数目
CLASSES = utils.read_class_names(cfg.YOLO.CLASSES) # 类别的名称
# 路径名称
predicted_dir_path = '../mAP/predicted'
ground_truth_dir_path = '../mAP/ground-truth'
# 若路径下有文件,则删除
if os.path.exists(predicted_dir_path):
shutil.rmtree(predicted_dir_path)
if os.path.exists(ground_truth_dir_path):
shutil.rmtree(ground_truth_dir_path)
if os.path.exists(cfg.TEST.DECTECTED_IMAGE_PATH):
shutil.rmtree(cfg.TEST.DECTECTED_IMAGE_PATH)
# 创建路径
os.mkdir(predicted_dir_path)
os.mkdir(ground_truth_dir_path)
os.mkdir(cfg.TEST.DECTECTED_IMAGE_PATH)
# 确定模型输入
input_layer = tf.keras.layers.Input([INPUT_SIZE, INPUT_SIZE, 3])
# 确定模型输出
feature_maps = YOLOv3(input_layer)
bbox_tensors = []
for i, fm in enumerate(feature_maps):
bbox_tensor = decode(fm, i)
bbox_tensors.append(bbox_tensor)
# 构建模型
model = tf.keras.Model(input_layer, bbox_tensors)
# 加载模型参数
model.load_weights("./yolov3")
# 进行测试
with open(cfg.TEST.ANNOT_PATH, 'r') as annotation_file:
for num, line in enumerate(annotation_file): # enumerate 使得annotation_file每个元素前面加一个序号,即num
# 第一步:读取原始图片和图上标注框信息,并在指定路径下写入txt
# 去除首尾空格,以空格来间隔
annotation = line.strip().split() # split()会按照指定的符号来分割成不同个元素
image_path = annotation[0]
# 读取原始图片
image_name = image_path.split('/')[-1] # split将以/作为间隔,提取图片名称
image = cv2.imread(image_path) # cv2.imread接口读图像,读进来直接是BGR 格式数据格式在 0~255
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # cv2.cvtColor 将图像转换为RGB
# 读取原始图片上的真实标注框信息
# 方法:map将字符类型变为数值类型 list将生成器对象转换输出
bbox_data_gt = np.array([list(map(int, box.split(','))) for box in annotation[1:]])
if len(bbox_data_gt) == 0:
bboxes_gt = []
classes_gt = []
else:
bboxes_gt, classes_gt = bbox_data_gt[:, :4], bbox_data_gt[:, 4]
# 生成存储带有真实标注框的图片路径
ground_truth_path = os.path.join(ground_truth_dir_path, str(num) + '.txt') # os.path.join拼接路径名称
print('=> ground truth of %s:' % image_name)
num_bbox_gt = len(bboxes_gt) # 标注框的数量
# 将图片上真实标注框信息写入txt文件中
with open(ground_truth_path, 'w') as f:
for i in range(num_bbox_gt):
class_name = CLASSES[classes_gt[i]]
# list变量赋值技巧:将list各个元素赋值给别的变量
xmin, ymin, xmax, ymax = list(map(str, bboxes_gt[i]))
# ' '.join() 将列表里面的元素都合成一个,以空格符作为间隔 '\n'表示换行
bbox_mess = ' '.join([class_name, xmin, ymin, xmax, ymax]) + '\n'
f.write(bbox_mess)
print('\t' + str(bbox_mess).strip()) # '\t' 横向制表符
print('=> predict result of %s:' % image_name)
predict_result_path = os.path.join(predicted_dir_path, str(num) + '.txt')
image_size = image.shape[:2]
# 第二步:图像预处理
# 具体:图像比例缩放-填充-均一化
image_data = utils.image_preporcess(np.copy(image), [INPUT_SIZE, INPUT_SIZE]) # np.copy深拷贝 不会因为image改变而改变
image_data = image_data[np.newaxis, ...].astype(np.float32)
# 第三步:模型预测输出
# 方法:model.predict
# 具体:将输出进行格式转换
pred_bbox = model.predict(image_data)
pred_bbox = [tf.reshape(x, (-1, tf.shape(x)[-1])