文章目录
最近在做目标检测的任务,但是由于自己训练的损失函数不是自己想要的,但是自己的程序在训练的时候每个 E p o c h Epoch Epoch都会生成一个模型的损失数值,所以想根据这些数值自己画图。
任务1:根据 t x t txt txt文件内的数值,生成损失曲线。
t
x
t
txt
txt文件内的数据样例如下图所示:
因为我的模型训练了150次,所以这样的数据有150个,且只有一列。直接在代码里详细叙述:
#导入必须的包
import matplotlib.pyplot as plt
import numpy as np
#----------- 打开txt文件 ----------
file = open('YOLOV4.txt')
#----------- 逐行读取文件内的数据 ------------
data = file.readlines()
#----------- 根据自己的需要查看data的内容 ---------
#print(data)
'''
txt文件的数值为y轴的数据
所以x要根据y的个数有序生成
'''
#------ x轴数据有序生成150个(根据自己的横坐标范围自己修改范围) ----
x = np.arange(0,150)
#---------- 新建一个空的列表,用于存储上一步逐行读取的data ------------
y = []
#---------- 用循环的方式添加进列表 -----------
for num in data:
#------split用于将每一行数据用逗号分割成多个对象-----
#------取分割后的第0列,转换成float格式后添加到列表中-------
y.append(float(num.split(',')[0]))
#--------------- 输出图 ----------------------
#--------- 可以理解为在图上加载x和y的数据 label为关于x和y曲线的标签------------
pic = plt.plot(x,y,label='Yolov4')
#--------- x轴的小标题 -------------
plt.xlabel('Epoch')
#--------- y轴的小标题 -------------
plt.ylabel('Loss')
#--------- 整个图的标题 ----------
plt.title('yolov4-loss')
plt.legend()
plt.show()
代码关于画图的每个细节写的很详细,下面生成的折线图。
任务2- 将.txt文件转换成.xls(excel)文件
需要的同学直接复制代码,代码中注释了你需要修改的地方。
import xlwt
def txt_xls(filename, xlsname):
try:
f = open(filename, 'r', encoding='utf-8')
xls = xlwt.Workbook()
sheet = xls.add_sheet('sheet1', cell_overwrite_ok=True)
x = 0
while True:
# 按行循环,读取文本文件
line = f.readline()
if not line:
break
for i in range(len(line.split('\t'))):
item = line.split('\t')[i]
sheet.write(x, i, item)
x += 1
f.close()
# 保存xls文件
xls.save(xlsname)
except:
raise
'''
下面的地址中就是自己根据自己的需要修改的地方
为什么看上去没有路径呢?因为我是把txt文件和运行的此程序放在了同一个文件夹中
所以生成的.xls文件也在同级文件下,也就是他们在同一个文件夹中
如果你没放在一起,建议使用E://Path//...
'''
if __name__ == "__main__":
#---------- 需要转化的.txt文件 -----------
filename = "YOLOV4.txt"
#---------- 转换后的.xls文件名 -----------
xlsname = "YOLOV4.xls" # 保存及命名
txt_xls(filename, xlsname)
任务3- 将.xls(excel)文件转换成.txt文件
将 . x l s .xls .xls文件转换成 . t x t .txt .txt文件。
python
import pandas as pd
#---------- 如果你的.xls文件开了多个窗口文件(sheet1,sheet2,sheet3....)使用下面的代码 -----------
#df = pd.read_excel('YOLOV4.xls', sheet_name='Sheet1',header=None)
#---------- 如果你的.xls文件没有开多个窗口(没有sheet1,sheet2,sheet3....)试用下面的代码
data = pd.read_excel('YOLOV4.xls', sheet_name='Sheet1',header=None)
print('正在读取将.xls文件内容')
#---------- 写入txt文件,seq表示逗号分隔 --------------
data.to_csv('YOLOV4.txt', header=None, sep=',', index=False)
print('.xls文件转换成.txt文件成功')
任务4- 读取.txt文件画折线图(曲线图)
该任务算是任务一的进阶版,通过文件数据的转换,我的
.
t
x
t
.txt
.txt文件的内容不再是一列,而是两列,第一列为序号,第二列为数值,基于此种情况,读取
.
t
x
t
.txt
.txt文件,将其以折线图(曲线图)表示出来。
下图是我现在
.
t
x
t
.txt
.txt数据的图例。
可以发现和任务一数据唯一不同就是多了一列的序列号,下面的是基于任务一改进的,就是改了几行,修改后的内容以注释的形式保存。话不多说直接代码中详细介绍:
#导入必须的包
import matplotlib.pyplot as plt
import numpy as np
#----------- 打开txt文件 ----------
file = open('file2.txt')
#----------- 逐行读取文件内的数据 ------------
data = file.readlines()
#----------- 根据自己的需要查看data的内容 ---------
#print(data)
'''
txt文件的数值为y轴的数据
所以x要根据y的个数有序生成
'''
#------ x轴数据有序生成150个(根据自己的横坐标范围自己修改范围) ----
#x = np.arange(0,150)
#---------- 新建一个空的列表,用于存储上一步逐行读取的data ------------
x = []
y = []
#---------- 用循环的方式添加进列表 -----------
for num in data:
#------split用于将每一行数据用逗号分割成多个对象-----
#------x读取data数据的第一列(也就是序列号)
x.append(float(num.split(',')[0]))
#------取分割后的第0列,转换成float格式后添加到列表中-------
#------y读取data数据的第二列(也就是数值)
y.append(float(num.split(',')[1]))
#--------------- 输出图 ----------------------
#--------- 可以理解为在图上加载x和y的数据 label为关于x和y曲线的标签------------
pic = plt.plot(x,y,label='Yolov4')
#--------- x轴的小标题 -------------
plt.xlabel('Epoch')
#--------- y轴的小标题 -------------
plt.ylabel('Loss')
#--------- 整个图的标题 ----------
plt.title('yolov4-loss')
plt.legend()
plt.show()
下面是得到的折线图(曲线图),和任务一得到的一模一样。
任务5- xml格式的数据集标签文件转.txt文件
在做目标检测任务时,我们手工打的标签往往都是.xml的文件,但是对于很多的网络,标签文件都需要.txt的文件,所以需要将.xml文件转换成模型需要的.txt文件,直接下面的代码可以转换:
#------------------------------- successful ----------------------------------
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
def convert(size, box):
x_center = (box[0] + box[1]) / 2.0
y_center = (box[2] + box[3]) / 2.0
x = x_center / size[0]
y = y_center / size[1]
w = (box[1] - box[0]) / size[0]
h = (box[3] - box[2]) / size[1]
return (x, y, w, h)
def convert_annotation(xml_files_path, save_txt_files_path, classes):
xml_files = os.listdir(xml_files_path)
print(xml_files)
for xml_name in xml_files:
print(xml_name)
xml_file = open(os.path.join(xml_files_path, xml_name))
out_txt_path = os.path.join(save_txt_files_path, xml_name.split('.')[0] + '.txt')
out_txt_f = open(out_txt_path, 'w')
tree = ET.parse(xml_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 not in classes or int(difficult) == 1:
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))
# b=(xmin, xmax, ymin, ymax)
print(w, h, b)
bb = convert((w, h), b)
out_txt_f.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
if __name__ == "__main__":
# 类别 txt中会取类别索引
classes1 = ['aocao', 'cashang','huahen']
# xml标签文件路径
xml_files1 = r'E:\\pycharm\\py_shiyancode\\LYD-CGN\\xml_convert_txt\\Annotations'
# txt标签文件存储路径
save_txt_files1 = r'E:\\pycharm\\py_shiyancode\\LYD-CGN\\xml_convert_txt\\txt'
convert_annotation(xml_files1, save_txt_files1, classes1)
任务6- 读取两个.txt文件画折线图(曲线图)
由于技术有限,只能使用最笨的方式读取每个文本的数据,然后再逐个遍历文本中的内容,将其添加进入列表内,然后画图,方法不是最优的,但是结果没问题。由于我没有之前的损失函数的文件了,所以自己手动添加进入文件几个数,作为教程。
这里需要注意:
- 如果你的 t x t txt txt文本数据内只有一列,且这一列就是你要绘制图的 y y y数值,则只需要将以下代码中的 y 1 y1 y1直接读取第 0 0 0列就可以了, y 2 y2 y2也同理,读取第 0 0 0列(1默认为第2例)。至于 x x x,你只需要根据y的个数生成 1 − − l e n ( y 1 ) 1--len(y1) 1−−len(y1)的数就可以画图了。(下面就是 t x t txt txt文本数据内的内容,仅作为参考)
- 保持
y
1
y1
y1的个数与
y
2
y2
y2的个数一致,不然会超出
x
x
x坐标的范围
import matplotlib.pyplot as plt
if __name__== '__main__':
# ----------- 打开txt文件(路径一定要修改成自己的路径) ----------
file1 = open('./dataloader_experience/1.txt')
file2 = open('./dataloader_experience/2.txt')
# ----------- 逐行读取文件内的数据 ------------
data1 = file1.readlines()
data2 = file2.readlines()
# ----------- 根据自己的需要查看data的内容 ---------
# print(data)
'''
txt文件的数值为y轴的数据
所以x要根据y的个数有序生成
'''
# ------ x轴数据有序生成150个(根据自己的横坐标范围自己修改范围) ----
# x = np.arange(0,150)
# ---------- 新建一个空的列表,用于存储上一步逐行读取的data ------------
x1 = []
y1 = []
y2 = []
# ---------- 用循环的方式添加进列表 -----------
for num1 in data1:
# ------split用于将每一行数据用逗号分割成多个对象-----
# ------x读取data数据的第一列(也就是序列号)
#-------建议以float类型添加,因为得到的损失值,一般都为小数
x1.append(float(num1.split(',')[0]))
# ------取分割后的第0列,转换成float格式后添加到列表中-------
# ------y读取data数据的第二列(也就是数值)
y1.append(float(num1.split(',')[1]))
for num2 in data2:
y2.append(float(num2.split(',')[1]))
# --------------- 输出图 ----------------------
# --------- 可以理解为在图上加载x和y的数据 label为关于x和y曲线的标签------------
# 根据需求变换线的格式和颜色
plt.plot(x1, y1,label= 'yolov4_loss2')
plt.plot(x1, y2, color='red', linestyle='--',label = 'yolov4_loss1')
# --------- x轴的小标题 -------------
plt.xlabel('Epoch')
# --------- y轴的小标题 -------------
plt.ylabel('Loss')
# --------- 整个图的标题 ----------
plt.title('yolov4-loss')
plt.legend()
plt.show()
结果图如下
总结:
- 如果你的数据是 . t x t .txt .txt文件,数据只有一列,那么任务一就可以解决你的问题
- 如果你有 . x l s .xls .xls格式的文件,你可以通过任务三将其转换成 . t x t .txt .txt文件,然后通过任务一或者四解决你的问题
- 如果你将 . t x t .txt .txt文件转换成 . x l s .xls .xls文件,任务二可以解决你的问题
- 如果你将
.
x
m
l
.xml
.xml文件转换成
.
t
x
t
.txt
.txt文件,任务五可以解决你的问题
如果对您有用,不妨点个赞吧