深度学习文章8:YOLO_v3训练过程
8.YOLO_v3训练过程
(写在每篇深度学习文章系列的前面,该系列的文章是我2019年做毕设时的步骤总结,是能实现的,不和其他很多博客一样瞎糊弄人浪费时间。写下这些文章一方面为了方便后来者,一方面也为了自己以后的步骤复现等。
另外,如果我给的那些参考帖子看不了了,可以到我的博客下载区那里去下载对应的压缩文件,我把里面所有的链接网页都截了长图,所以不用担心我给的参考帖子链接失效。
其次,如果我给的参考链接侵犯了该链接博主的权益,烦请告知,必当第一时间删掉。由于本人参考帖子较多,如果侵犯了请原谅,我会删掉。也谢谢各位在路上帮助过我的,谢谢了。
还有就是,如果积分太高了,请告诉我怎么把积分降低,我也不太清楚怎么弄,积分会随着下载次数增加逐渐增加。你知道的话怎么降的话可以留言给我。
emm, 最后的最后,如果你觉得这篇博文有用,请点个赞哩,感谢!~~)
(博客下载区:https://download.csdn.net/download/lininggggggg/11224791
或者在下载区搜索名字:8.YOLO_v3训练过程.zip–深度学习文章8)
正文
一.跑出官方例程
https://blog.csdn.net/neo_qiye/article/details/84782199
https://www.jianshu.com/p/3943be47fe84
https://blog.csdn.net/plSong_CSDN/article/details/85108256(可识别橙子,高,见文件夹keras-yolo3-master4)
二.训练自己的数据集
https://blog.csdn.net/IronMastiff/article/details/79940118 (不太好)
https://blog.csdn.net/plSong_CSDN/article/details/85194719
https://blog.csdn.net/mingqi1996/article/details/83343289#训练
https://blog.csdn.net/lly1122334/article/details/89019891
https://blog.csdn.net/mingqi1996/article/details/83343289#commentsedit
三.显示loss和map等的数值函数
https://blog.csdn.net/yudiemiaomiao/article/details/72469135
https://blog.csdn.net/plSong_CSDN/article/details/89502117 !!!(超级重要)
https://blog.csdn.net/qq_34199326/article/details/84109828 (边框)
四.下面是完整步骤。(还有第五点,不要忘了)
(1)跑出官方例程方法一(仅仅会跑出官方例程,其余不会)
https://www.jianshu.com/p/3943be47fe84
https://blog.csdn.net/neo_qiye/article/details/84782199
第一步,下载yolo_v3代码和权值文件yolov3.weights,具体网址见下
○1yolo_v3代码为:
https://github.com/xiaochus/YOLOv3 或者 https://github.com/ZhangChuann/go_elife
**○2权值文件yolov3.weights为:**https://pjreddie.com/media/files/yolov3.weights 或者
链接: https://pan.baidu.com/s/1QZTjhc6yAoqs2KJWj-Y2gA 提取码: 9ndy
第二步,将yolo_v3代码文件解压,然后把权值文件yolov3.weights复制到yolo_v3代码文件的目录下E:\GraduationProject\Data\go_elife-master\AI_Demo\yolo_v3;
然后,用黑框编译器cd到该目录下,然后输入下面的指令:
python yad2k.py cfg/yolo.cfg yolov3.weights data/yolo.h5
(注意,如果最后出现提示无法画图的话,输入conda install pydot,然后安装完成后再编译一遍应该就可以了。)
转换结束的画面是
第三步,继续在黑框编译器输入python demo.py,如果在第一步的○1选的是第一个链接的话,不出意外应该会出现摄像头识别画面。
【注意,参考博文里说可能会提示错误(但我没遇到过):TypeError: float() argument must be a string or a number, not ‘dict’,我在文件yad2k.py里加了如下两句话,可以运行:
print(model.summary())
model.save(’{}’.format(output_path))
print(‘Saved Keras model to {}’.format(output_path))
#test model file is aviable add by me
del model # deletes the existing model
model = keras.models.load_model(output_path) 】
第四步,根据不同的要求在demo.py文件的最后面添加代码段,即在下面的代码段后面添加另外的代码段:
(其中待测试的图片放在目录go_elife-master\AI_Demo\yolo_v3\images\test下)
(其中待测试的视频放在目录go_elife-master\AI_Demo\yolo_v3\videos\test下)
if name == ‘main’:
yolo = YOLO(0.6, 0.5)
file = ‘data/coco_classes.txt’
all_classes = get_classes(file)
○1测试几张图片的代码
# detect images in test floder.
# 下面是测试图片用的
for (root, dirs, files) in os.walk('images/test'):
if files:
for f in files:
print(f)
path = os.path.join(root, f)
image = cv2.imread(path)
image = detect_image(image, yolo, all_classes)
cv2.imwrite('images/res/' + f, image)
○2测试视频的代码
# detect videos one at a time in videos/test folder
# 下面是测试视频用的
video = '1.mp4'
detect_video(video, yolo, all_classes)
○3测试摄像头的代码
# 下面是测试摄像头用的
video = ''
detect_video(video, yolo, all_classes)
第五步,自此,基本上官方例程就算走完一遍了。
(2)跑出官方例程方法二
相关文章例程:https://blog.csdn.net/plSong_CSDN/article/details/85108256 和
https://blog.csdn.net/mingqi1996/article/details/83343289#先图片测试一下
第一步,下载keras-yolo3-master.zip。
方法1是自己之前已经下载了,就110KB大小;
方法2是上面几行的相关例程的第二个链接中的 “1.下载“ 这个下面的网址:
https://github.com/qqwweee/keras-yolo3
第二步,下载权值文件yolov3.weights。
这个文件和(1)跑出官方例程方法一中的那个文件是同一个,可以互用。然后把这个权值文件yolov3.weights文件放在目录E:\GraduationProject\Data\keras-yolo3-master4下。
第三步,由于yolov3.weights权值文件tf不识别,需要进行转化,所以在黑框编译器中
(1)cd到对应weight文件目录下
(2)转化:
python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5
(注意,如果最后出现提示无法画图的话,输入conda install pydot,然后安装完成后再编译一遍应该就可以了。)
转换结束的画面是
第四步,用pycharm打开该项目工程文件,设置Settings为自己的虚拟环境。
然后,将E:\GraduationProject\Data\keras-yolo3-master5\model_data目录下的新生成的yolo.h5复制后重命名为yolo_weights.h5。
第五步,打开yolo.py文件,在该文件的最后添加下面的代码:
○1检测单张图片的代码
# 添加的
def detect_img(yolo, img_path='test.png'):
image = Image.open(img_path)
import time
t1 = time.time()
r_image = yolo.detect_image(image)
print('time: {}'.format(time.time() - t1))
r_image.show()
yolo.close_session()
if __name__ == '__main__':
# 检测单张图片
detect_img(YOLO(), img_path='1.jpg') # 检测输入图片的路径
然后根据添加的代码的最后一行的路径放上相应的名称的图片,如上面的代码所对应的图片应该放在目录E:\GraduationProject\Data\keras-yolo3-master4下,命名为1.jpg。
○2检测视频的代码
# 添加的
def detect_img(yolo, img_path='test.png'):
image = Image.open(img_path)
import time
t1 = time.time()
r_image = yolo.detect_image(image)
print('time: {}'.format(time.time() - t1))
r_image.show()
yolo.close_session()
if __name__ == '__main__':
# # 检测单张图片
# detect_img(YOLO(), img_path='1.jpg') # 检测输入图片的路径
# 检测视频
video_path = '12.mp4'
detect_video(YOLO(), video_path, output_path="")
然后根据添加的代码的最后一行的路径放上相应的名称的视频,如上面的代码所对应的视频应该放在目录E:\GraduationProject\Data\keras-yolo3-master4下,命名为12.mp4。
○3检测摄像头的代码
此处改两处:
第一处:改了detect_video函数的代码,主要改了其之前不能开摄像头的问题,所以其实这个代码更好,能适应检测图片、视频和摄像头三种要求,而之前的代码只能适应前两种要求。
注意:其中第一处的更改是将下面的172-174行的代码
改为下面的177-185的代码段。
其中整个更改后的detect_video函数代码如下:
def detect_video(yolo, video, output_path=""):
import cv2
video_path = os.path.join(video)
if (os.path.exists(video_path) and video != ''):
vid = cv2.VideoCapture(video_path)
else:
vid = cv2.VideoCapture(0)
video = 'your_camera.mp4'
if not vid.isOpened():
raise IOError("Couldn't open webcam or video")
video_FourCC = int(vid.get(cv2.CAP_PROP_FOURCC))
video_fps = vid.get(cv2.CAP_PROP_FPS)
video_size = (int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)),
int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT)))
isOutput = True if output_path != "" else False
if isOutput:
print("!!! TYPE:", type(output_path), type(video_FourCC), type(video_fps), type(video_size))
out = cv2.VideoWriter(output_path, video_FourCC, video_fps, video_size)
accum_time = 0
curr_fps = 0
fps = "FPS: ??"
prev_time = timer()
while True:
return_value, frame = vid.read()
image = Image.fromarray(frame)
image = yolo.detect_image(image)
result = np.asarray(image)
curr_time = timer()
exec_time = curr_time - prev_time
prev_time = curr_time
accum_time = accum_time + exec_time
curr_fps = curr_fps + 1
if accum_time > 1:
accum_time = accum_time - 1
fps = "FPS: " + str(curr_fps)
curr_fps = 0
cv2.putText(result, text=fps, org=(3, 15), fontFace=cv2.FONT_HERSHEY_SIMPLEX,
fontScale=0.50, color=(255, 0, 0), thickness=2)
cv2.namedWindow("result", cv2.WINDOW_NORMAL)
cv2.imshow("result", result)
if isOutput:
out.write(result)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
yolo.close_session()
第二处:更改了最后面的代码,改为摄像头的代码
# 添加的
def detect_img(yolo, img_path='test.png'):
image = Image.open(img_path)
import time
t1 = time.time()
r_image = yolo.detect_image(image)
print('time: {}'.format(time.time() - t1))
r_image.show()
yolo.close_session()
if __name__ == '__main__':
# # 检测单张图片
# detect_img(YOLO(), img_path='1.jpg') # 检测输入图片的路径
# # 检测视频
# video = '12.mp4'
# detect_video(YOLO(), video, output_path="")
# 检测摄像头
video = ''
detect_video(YOLO(), video, output_path="")
第六步,自此,基本上官方例程就算走完一遍了。
(3)更改官方例程,使其只显示一类识别,即橙子的识别。
步骤的前四步和(2)跑出官方例程方法二 的一模一样。
然后是第五步,更改显示识别的类别为只识别orange这一种种类。修改官方例程为只有一类的改法可以参考帖子https://blog.csdn.net/lly1122334/article/details/89019891
(注意:这种方法是针对Python Keras下的YOLOv3:修改yolo.py第135行,在它那里添加如下代码即可:
代码段即下面所示:
# Just detect orange
if predicted_class != 'orange':
continue
。。。。。。)
到此为止可以说是已经能够实现使用官方例程但只实现其中的一类orange的效果了。
不过,此时的代码只能识别图片和视频,不能识别摄像头,如果想要能识别摄像头的话,可以参考(2)跑出官方例程方法二的(○3检测摄像头的代码)进行,一模一样。
第六步,自此,使用官方例程但只实现其中的一类orange的效果基本已经实现。
(4)训练自己的模型
参考例程https://blog.csdn.net/plSong_CSDN/article/details/85194719
和 https://blog.csdn.net/mingqi1996/article/details/83343289#commentsedit (同帖子4)
步骤的前四步和(2)跑出官方例程方法二 的一模一样。
然后是第五步,准备自己的数据集,先新建下图红框所示的空文件夹(其实和之前的SSD的做法一模一样),但最上一级是VOCdevkit,因为这样可以不用修改下面程序的路径。
第六步,将自己所有的图片拷贝到文件目录为
”……\keras-yolo3-master\VOCdevkit\VOC2007\JPEGImages“下,最好都是jpg格式(必须最好)
第七步,数据打标签
复制SSD之前下载的labelImg-master文件到keras-yolo3-master\VOCdevkit\VOC2007目录下,用黑框编译器cd到labelImg-master文件目录下,然后输入python labelImg.py
指令即可打开标注工具。更具体的操作步骤见之前的SSD的相关操作。
然后,将标注好的图片生成的xml文件全复制到目录为…VOC2007\Annotations下。
再然后,将之前的SSD下载的python文件create_txt.py复制到\VOCdevkit\VOC2007目录下(其中,create_txt.py文件应该在之前SSD文件的VOCdevkit\VOC2007目录下)。
接着,运行该create_txt.py文件,不出意外的话应该在VOC2007\ImageSets\Main”文件夹下会自动生成test.txt、train.txt、trainval.txt、val.txt文件。
第八步,将VOC2007生成的txt文件格式转换为yolo版本能够识别的文件编写txt的格式。
首先,打开主目录下的voc_annotation.py文件,进行如下图红框中所示的修改,将classes类别改为自己需要识别的类别。
然后修改完之后点击进行运行该文件可以生成yolo文件:生成的三个以“2007_”打头的txt文件,手动删掉“2007_”。(我的话是将这三个txt文件全复制一遍后将复制的文件重命名时去掉“2007_”)。
第九步,修改参数文件yolo3.cfg文件
首先,打开参数文件yolo3.cfg文件,搜索”yolo“这个字样,一共有三处。在其前后找到下面的三处地方进行修改,所以一共需要修改9个地方。
其中,修改的规则格式是:
filters: 3*(5+len(classes));我的类别classes是橙子来着(只识别橙子这一类)
classes: len(classes) = 1; 我的类别classes是橙子这一类,所以长度为1
random: 改为0;这个好像是设置性能,具体不知道。
最后的修改效果之一见下图:
第十步,修改model_data
修改“……\keras-yolo3-master\model_data”目录下的“coco_classes.txt、voc_classes.txt”这两个文件,将自己类别填入进去(具体什么功能不清楚)。
第十一步,开始训练
首先,在主目录下新建两级文件夹,目录为“\keras-yolo3-master\logs\000”,该目录用来存放自己训练完成的新模型,即权重文件。
接着,如果电脑性能不太好,可以在train.py文件下搜索batch_size(一共有两个),然后将其改小,比如改为2(但结果训练出来后loss=nan的错误,有人说是因为不能设置太小!!!)
然后,在其前后几行可以发现有epochs=***的代码(epochs应该是指训练步数之类的意思)(一共有两个,与batch_size相互对应;其中,第一个epochs小一点,第二个epochs大一点,个人认为应该是前面一个小的如果训练效果不好的话,会启动后面一个大的继续训练)。可以改为50和100等。
(补充:(这一条没实践过,但应该是对的。)val_split = 0.1:如果只用十几张图片测试模型时,建议划分比大点,否则本来分到验证集就不多,乘以0.1后不到1就会没有验证集,导致验证集loss计算报错。)
然后,运行train.py将其运行即可。结果应该会在keras-yolo3-master3\logs\000目录下生成权重文件trained_weights_final.h5以及一些中间模型。
第十二步,测试
将训练结束后的存放在目录E:\GraduationProject\Data\keras-yolo3-master3\logs\000下的权重文件trained_weights_final.h5复制后重命名为“yolo.h5”,然后复制到目录为E:\GraduationProject\Data\keras-yolo3-master3\model_data的目录下。
(注意,如果其中没训练完成的话,也可以选择其中中间的训练模型,然后将其重命名为“yolo.h5”即可,如下图所示,但由于我这次训练的模型的步数少所以没中间模型)
然后,在主目录下放置要测试的图片或视频,然后按照(2)跑出官方例程方法二的(○3检测摄像头的代码)这个步骤进行操作即可。
然后就运行yolo.py文件即可进行测试识别自己 模型训练出来的橙子。
第十三步,自此,自己训练yolo_v3模型的橙子识别到此完成结束。
五.修改代码使得程序能够保存测试的文件
○1测试图片的话修改yolo.py最后的代码为
即添加上下两行代码,中间一行原本就有的。
####
outdir="E:\GraduationProject\Data\keras-yolo3-master5/test"
r_image = yolo.detect_image(image)
r_image.save(os.path.join(outdir, os.path.basename(img_path)))
####
○2测试视频的话,现在还没完成。
上一篇: Pytorch可视化训练过程
下一篇: MySQL使用存储过程插入一百万条数据