Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7,948 changes: 7,948 additions & 0 deletions .gitignore

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## 蛇足

我在bubbliiiing的代码中加入了

import os

os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"

解决了我的Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.的报错问题

同时加入了coco转voc数据集的代码。




## YOLOV5:You Only Look Once目标检测模型在pytorch当中的实现(edition v5.0 in Ultralytics)
---

Expand Down
122 changes: 122 additions & 0 deletions coco2voc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import json
from xml.dom.minidom import *
import xml.etree.ElementTree as ET
import numpy as np

#-----------------------------------------------------------#
#
# 本文件用于将coco数据集中的json文件
# 转化为voc数据集用的xml标签
#-----------------------------------------------------------#
# 美化xml文件
def pretty_xml(element, indent, newline, level=0): # elemnt为传进来的Elment类,参数indent用于缩进,newline用于换行
if element: # 判断element是否有子元素
if (element.text is None) or element.text.isspace(): # 如果element的text没有内容
element.text = newline + indent * (level + 1)
else:
element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * (level + 1)
# else: # 此处两行如果把注释去掉,Element的text也会另起一行
# element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * level
temp = list(element) # 将element转成list
for subelement in temp:
if temp.index(subelement) < (len(temp) - 1): # 如果不是list的最后一个元素,说明下一个行是同级别元素的起始,缩进应一致
subelement.tail = newline + indent * (level + 1)
else: # 如果是list的最后一个元素, 说明下一行是母元素的结束,缩进应该少一个
subelement.tail = newline + indent * level
pretty_xml(subelement, indent, newline, level=level + 1) # 对子元素进行递归操作

# 写入xml文件
def write_xml(img_name, width, height, object_dicts, save_path, folder='XJTU_dataset'):
'''
object_dict = {'name': classes[int(object_category)],
'truncated': int(truncation),
'difficult': int(occlusion),
'xmin':int(bbox_left),
'ymin':int(bbox_top),
'xmax':int(bbox_left) + int(bbox_width),
'ymax':int(bbox_top) + int(bbox_height)
}
'''
doc = Document
root = ET.Element('Annotation')
ET.SubElement(root, 'folder').text = folder
ET.SubElement(root, 'filename').text = img_name
size_node = ET.SubElement(root, 'size')
ET.SubElement(size_node, 'width').text = str(width)
ET.SubElement(size_node, 'height').text = str(height)
ET.SubElement(size_node, 'depth').text = '3'
for object_dict in object_dicts:
object_node = ET.SubElement(root, 'object')
ET.SubElement(object_node, 'name').text = object_dict['name']
ET.SubElement(object_node, 'pose').text = 'Unspecified'
ET.SubElement(object_node, 'truncated').text = str(object_dict['truncated'])
ET.SubElement(object_node, 'difficult').text = str(object_dict['difficult'])
bndbox_node = ET.SubElement(object_node, 'bndbox')
ET.SubElement(bndbox_node, 'xmin').text = str(object_dict['xmin'])
ET.SubElement(bndbox_node, 'ymin').text = str(object_dict['ymin'])
ET.SubElement(bndbox_node, 'xmax').text = str(object_dict['xmax'])
ET.SubElement(bndbox_node, 'ymax').text = str(object_dict['ymax'])

pretty_xml(root, '\t', '\n')
tree = ET.ElementTree(root)
tree.write(save_path, encoding='utf-8')

if __name__ == '__main__':
# class_names = ['road', 'car', 'motorcycle', 'person']
# f = open("../../../cow/train.json", encoding='utf-8')
f = open("cowboyoutfits/train.json", encoding='utf-8')
data = json.load(f)
annotations = data['annotations']
images = data['images']
cate = {
"87": "belt",
"1034": "sunglasses",
"131": "boot",
"318": "cowboy_hat",
"588": "jacket"
}
images_num = len(images)
# print()
bbox_infos = {}
for image in images:
print()
bbox_infos[str(image["id"])] = []

for ann in annotations:
print(ann)
image_id = ann['image_id']
bbox = ann['bbox']
bbox_x = bbox[0]
bbox_y = bbox[1]
bbox_w = bbox[2]
bbox_h = bbox[3]
class_id = ann['category_id']
object_dict = {'name': cate[str(class_id)],
'truncated': 0,
'difficult': 0,
'xmin': int(bbox_x),
'ymin': int(bbox_y),
'xmax': int(bbox_x+bbox_w),
'ymax': int(bbox_y+bbox_h)
}
print(object_dict)
bbox_infos[str(image_id)].append(object_dict)


txt_results = []
for image in images:
print(image)
image_height = image['height']
image_width = image['width']
image_id = image['id']
image_file_name = image['file_name']
object_dicts = bbox_infos[str(image_id)]
xml_file_name = image_file_name.strip('.jpg') + '.xml'
txt_results.append(image_file_name.strip('.jpg'))
# print(image_file_name, image_width, image_height, object_dicts, )
write_xml(image_file_name, image_width, image_height, object_dicts, "D:/yolov5-pytorch/cowboy_voc_xml/"+xml_file_name)

# np.savetxt()
# np.savetxt('train.txt', txt_results, fmt="%s", delimiter="\n")
# for image in images:
# print(image)
150 changes: 150 additions & 0 deletions data_analysis.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import tensorboard"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 批量用yolo将bounding box保存csv\n",
"\n",
"1.保存bounding box到csv\n",
"\n",
"2.将代码缩减成一到两个py文件\n",
"\n",
"3.将bounding box保存到json文件\n",
"\n",
"上传json文件X"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"data = {\"name\": \"Alice\", \"age\": 20, \"hobbies\": [\"reading\", \"coding\"]}\n",
"with open(\"data.json\", \"w\") as f:\n",
" json.dump(data, f)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"python使用字典操作\n",
"\n",
"https://www.runoob.com/python/python-dictionary.html"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<class 'numpy.ndarray'>\n"
]
}
],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"label, top, left, bottom, right = 'jacket 0.51',538 ,528,707,616\n",
"data=(label, top, left, bottom, right)\n",
"array = np.asarray(data).reshape(1,5)\n",
"array = np.concatenate((array,array),axis=0)\n",
"print(type(array))\n",
"test=pd.DataFrame(array,columns=['label', 'top', 'left', 'bottom', 'right'])\n",
"test.to_csv('save1.csv', index=False, sep=',')"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"image_name = 'sadfhkj.jpg'\n",
"label, top, left, bottom, right = 'jacket 0.51',538 ,528,707,616\n",
"data=(image_name,label, top, left, bottom, right)\n",
"array = np.asarray(data).reshape(1,6)\n",
"array = np.concatenate((array,array),axis=0)\n",
"# image_name = np.asarray(image_name)\n",
"# array_image_name = np.concatenate((image_name,array),axis=1)\n",
"# label, top, left, bottom, right = array\n",
"# array_image_name = image_name + array\n",
"\n",
"test=pd.DataFrame(array,columns=['image_name','label', 'top', 'left', 'bottom', 'right'])\n",
"# test=pd.DataFrame(array)\n",
"if os.path.exists('save1.csv'):\n",
" test.to_csv('save1.csv', index=False, sep=',',mode='a', header=None)\n",
" \n",
"else:\n",
" test.to_csv('save1.csv', index=False, sep=',',mode='a')"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import os\n",
"os.path.exists('save1.csv')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "pytorch_py37",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.16"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "6198aedcd0ac652a444d7ee87cdb474140afc32862f11a7cd22c6cfd8fc2757e"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
2 changes: 1 addition & 1 deletion get_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# 此处的classes_path用于指定需要测量VOC_map的类别
# 一般情况下与训练和预测所用的classes_path一致即可
#--------------------------------------------------------------------------------------#
classes_path = 'model_data/voc_classes.txt'
classes_path = 'model_data/cowboy_classes.txt'
#--------------------------------------------------------------------------------------#
# MINOVERLAP用于指定想要获得的mAP0.x,mAP0.x的意义是什么请同学们百度一下。
# 比如计算mAP0.75,可以设定MINOVERLAP = 0.75。
Expand Down
4 changes: 2 additions & 2 deletions predict.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
# 'export_onnx' 表示将模型导出为onnx,需要pytorch1.7.1以上。
# 'predict_onnx' 表示利用导出的onnx模型进行预测,相关参数的修改在yolo.py_423行左右处的YOLO_ONNX
#----------------------------------------------------------------------------------------------------------#
mode = "predict"
mode = "dir_predict"
#-------------------------------------------------------------------------#
# crop 指定了是否在单张图片预测后对目标进行截取
# count 指定了是否进行目标的计数
Expand Down Expand Up @@ -158,7 +158,7 @@
if img_name.lower().endswith(('.bmp', '.dib', '.png', '.jpg', '.jpeg', '.pbm', '.pgm', '.ppm', '.tif', '.tiff')):
image_path = os.path.join(dir_origin_path, img_name)
image = Image.open(image_path)
r_image = yolo.detect_image(image)
r_image = yolo.detect_image(image,image_name=img_name)
if not os.path.exists(dir_save_path):
os.makedirs(dir_save_path)
r_image.save(os.path.join(dir_save_path, img_name.replace(".jpg", ".png")), quality=95, subsampling=0)
Expand Down
14 changes: 8 additions & 6 deletions train.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#-------------------------------------#
import datetime
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"

import numpy as np
import torch
Expand Down Expand Up @@ -68,7 +69,7 @@
# classes_path 指向model_data下的txt,与自己训练的数据集相关
# 训练前一定要修改classes_path,使其对应自己的数据集
#---------------------------------------------------------------------#
classes_path = 'model_data/voc_classes.txt'
classes_path = 'model_data/cowboy_classes.txt'
#---------------------------------------------------------------------#
# anchors_path 代表先验框对应的txt文件,一般不修改。
# anchors_mask 用于帮助代码找到对应的先验框,一般不修改。
Expand Down Expand Up @@ -112,7 +113,7 @@
# 如果不设置model_path,pretrained = True,此时仅加载主干开始训练。
# 如果不设置model_path,pretrained = False,Freeze_Train = Fasle,此时从0开始训练,且没有冻结主干的过程。
#----------------------------------------------------------------------------------------------------------------------------#
pretrained = False
pretrained = True
#------------------------------------------------------#
# phi 所使用的YoloV5的版本。s、m、l、x
# 在除cspdarknet的其它主干中仅影响panet的大小
Expand Down Expand Up @@ -187,7 +188,7 @@
# Adam可以使用相对较小的UnFreeze_Epoch
# Unfreeze_batch_size 模型在解冻后的batch_size
#------------------------------------------------------------------#
UnFreeze_Epoch = 300
UnFreeze_Epoch = 100
Unfreeze_batch_size = 8
#------------------------------------------------------------------#
# Freeze_Train 是否进行冻结训练
Expand All @@ -202,7 +203,7 @@
# Init_lr 模型的最大学习率
# Min_lr 模型的最小学习率,默认为最大学习率的0.01
#------------------------------------------------------------------#
Init_lr = 1e-2
Init_lr = 1e-3
Min_lr = Init_lr * 0.01
#------------------------------------------------------------------#
# optimizer_type 使用到的优化器种类,可选的有adam、sgd
Expand All @@ -212,9 +213,9 @@
# weight_decay 权值衰减,可防止过拟合
# adam会导致weight_decay错误,使用adam时建议设置为0。
#------------------------------------------------------------------#
optimizer_type = "sgd"
optimizer_type = "adam"
momentum = 0.937
weight_decay = 5e-4
weight_decay = 0
#------------------------------------------------------------------#
# lr_decay_type 使用到的学习率下降方式,可选的有step、cos
#------------------------------------------------------------------#
Expand Down Expand Up @@ -418,6 +419,7 @@
# 冻结一定部分训练
#------------------------------------#
if Freeze_Train:
# print("冻结主干")
for param in model.backbone.parameters():
param.requires_grad = False

Expand Down
2 changes: 1 addition & 1 deletion voc_annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# 那么就是因为classes没有设定正确
# 仅在annotation_mode为0和2的时候有效
#-------------------------------------------------------------------#
classes_path = 'model_data/voc_classes.txt'
classes_path = 'model_data/cowboy_classes.txt'
#--------------------------------------------------------------------------------------------------------------------------------#
# trainval_percent用于指定(训练集+验证集)与测试集的比例,默认情况下 (训练集+验证集):测试集 = 9:1
# train_percent用于指定(训练集+验证集)中训练集与验证集的比例,默认情况下 训练集:验证集 = 9:1
Expand Down
Loading