一 安装anaconda
首先安装anaconda,网址https://mirrors.bfsu.edu.cn/anaconda/archive/上,选择x86_64的exe文件,建议安装在c盘,且目录中最好不要有中文(以后可能有麻烦),另外可以直接addpath,对于不想麻烦搞环境变量的同学推荐。
安装教程:(24条消息) Anaconda超详细安装教程(Windows环境下)_windows安装conda_菜鸟1号!!的博客-CSDN博客
二 下载pycharm,新建项目,使用conda环境,他会自动给你创一个conda环境,位置可以不用改,但建议python版本不要太高,38-36比较适合,因为后面opencv可能由于python版本太高而匹配不上。
三 环境下载太慢,可以翻墙软件或者添加清华源通道:
#添加镜像源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/pro
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
#显示检索路径
conda config --set show_channel_urls yes
#显示镜像通道
conda config --show channels
感觉部分包下载还是很慢,感兴趣的可以再搜搜
四 conda安装环境问题
opencv-python下载问题
有可能会出现下载不下来的问题,这时候就需要去下wel文件,放到scrips下,并把目录移到这里执行pip install命令,注意下载版本匹配Links for opencv-python (tsinghua.edu.cn)。
pytorch-cuda下载
因为默认安装要求的pytorch并不是cuda版本的,无法调用gpu,执行命令:python 分隔import torch分隔torch.cuda.is_available()可以看cuda可不可用,可用的话cuda一般编号为0,需要在train.py文件中将参数device默认空改为0。
pytorch安装建议去官网执行cuda命令或者pip命令,PyTorch,都试试。
五 运行debug
numpy版本太高问题
他会报错没有int格式或者greater函数有问题,可以尝试将int改为int_,并将numpy中summary.py中386行的greater函数去掉dtype参数,因为我们比较的是float类型。
编码问题
可能是遇到的第一个问题了,python用的gbk编码,而windows上用的是utf-8,我们需要在train.py第一行添加:
import _locale
_locale._getdefaultlocale = (lambda *args: ['zh_CN', 'utf8'])
yolo7.pt找不到
我们从GitHub上下载的是yolov7.pt,需要在train.py中加个‘v'
device无效,不一致
这个去网上找找,改两行代码就行,都有现成的,复制粘贴就行。
找不到训练集labels
这个问题就是我们的数据集没整好,我在train.py中传入的是默认的coco,yaml文件,用记事本打开,修改训练集,验证集,测试集路径,但注意,我们的路径是图片,那我们的txt标签怎么识别呢,其实,我们的数据集结构应该是这样的:data-images-train//val//test,在data目录下再建一个labels,即data-labels-train//val//test,注意labels不可更改名称,要不然很可能识别不到。
六 数据集制作
上一步已经做好了目录结构,我们需要往里面添加图片和标签,我用的labelimg,标签都是xml,而我们需要用txt格式的,于是需要转换,网上随便找一个代码就行,还有能按比例自动分割数据集的,我在这只写一个,亲测有效:
import _locale
_locale._getdefaultlocale = (lambda *args: ['zh_CN', 'utf8'])
import os
import json
import argparse
import sys
import shutil
from lxml import etree
from tqdm import tqdm
category_set = set()
image_set = set()
bbox_nums = 0
def parse_xml_to_dict(xml):
"""
将xml文件解析成字典形式,参考tensorflow的recursive_parse_xml_to_dict
Args:
xml: xml tree obtained by parsing XML file contents using lxml.etree
Returns:
Python dictionary holding XML contents.
"""
if len(xml) == 0: # 遍历到底层,直接返回tag对应的信息
return {xml.tag: xml.text}
result = {}
for child in xml:
child_result = parse_xml_to_dict(child) # 递归遍历标签信息
if child.tag != 'object':
result[child.tag] = child_result[child.tag]
else:
if child.tag not in result: # 因为object可能有多个,所以需要放入列表里
result[child.tag] = []
result[child.tag].append(child_result[child.tag])
return {xml.tag: result}
def write_classIndices(category_set):
class_indices = dict((k, v) for v, k in enumerate(category_set))
json_str = json.dumps(dict((val, key) for key, val in class_indices.items()), indent=4)
with open('class_indices.json', 'w') as json_file:
json_file.write(json_str)
def xyxy2xywhn(bbox, size):
bbox = list(map(float, bbox))
size = list(map(float, size))
xc = (bbox[0] + (bbox[2] - bbox[0]) / 2.) / size[0]
yc = (bbox[1] + (bbox[3] - bbox[1]) / 2.) / size[1]
wn = (bbox[2] - bbox[0]) / size[0]
hn = (bbox[3] - bbox[1]) / size[1]
return (xc, yc, wn, hn)
def parser_info(info: dict, only_cat=True, class_indices=None):
filename = info['annotation']['filename']
image_set.add(filename)
objects = []
width = int(info['annotation']['size']['width'])
height = int(info['annotation']['size']['height'])
for obj in info['annotation']['object']:
obj_name = obj['name']
category_set.add(obj_name)
if only_cat:
continue
xmin = int(obj['bndbox']['xmin'])
ymin = int(obj['bndbox']['ymin'])
xmax = int(obj['bndbox']['xmax'])
ymax = int(obj['bndbox']['ymax'])
bbox = xyxy2xywhn((xmin, ymin, xmax, ymax), (width, height))
if class_indices is not None:
obj_category = class_indices[obj_name]
object = [obj_category, bbox]
objects.append(object)
return filename, objects
def parseXmlFilse(voc_dir, save_dir):
assert os.path.exists(voc_dir), "ERROR {} does not exists".format(voc_dir)
if os.path.exists(save_dir):
shutil.rmtree(save_dir)
os.makedirs(save_dir)
xml_files = [os.path.join(voc_dir, i) for i in os.listdir(voc_dir) if os.path.splitext(i)[-1] == '.xml']
for xml_file in xml_files:
with open(xml_file) as fid:
xml_str = fid.read()
xml = etree.fromstring(xml_str)
info_dict = parse_xml_to_dict(xml)
parser_info(info_dict, only_cat=True)
with open(save_dir + "/classes.txt", 'w') as classes_file:
for cat in sorted(category_set):
classes_file.write("{}\n".format(cat))
class_indices = dict((v, k) for k, v in enumerate(sorted(category_set)))
xml_files = tqdm(xml_files)
for xml_file in xml_files:
with open(xml_file) as fid:
xml_str = fid.read()
xml = etree.fromstring(xml_str)
info_dict = parse_xml_to_dict(xml)
filename, objects = parser_info(info_dict, only_cat=False, class_indices=class_indices)
if len(objects) != 0:
global bbox_nums
bbox_nums += len(objects)
with open(save_dir + "/" + filename.split(".")[0] + ".txt", 'w') as f:
for obj in objects:
f.write(
"{} {:.5f} {:.5f} {:.5f} {:.5f}\n".format(obj[0], obj[1][0], obj[1][1], obj[1][2], obj[1][3]))
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--voc-dir', type=str, default='C:/Users/杀杀杀/Desktop/labels/test')
parser.add_argument('--save-dir', type=str, default='C:/Users/杀杀杀/Desktop/labels/yolotrain')
opt = parser.parse_args()
if len(sys.argv) > 1:
print(opt)
parseXmlFilse(**vars(opt))
print("image nums: {}".format(len(image_set)))
print("category nums: {}".format(len(category_set)))
print("bbox nums: {}".format(bbox_nums))
else:
voc_dir = 'C:/Users/杀杀杀/Desktop/labels/test'
save_dir = 'C:/Users/杀杀杀/Desktop/labels/yolotrain'
parseXmlFilse(voc_dir, save_dir)
print("image nums: {}".format(len(image_set)))
print("category nums: {}".format(len(category_set)))
print("bbox nums: {}".format(bbox_nums))
只需要修改路径即可,这个也是我从网上抄的,抄的谁的忘记了。
好了,最后祝愿大家最后运行都是这样子的: