这篇文章就不设 vip 可见了,如果有条件请打个赏给孩子买份饭吃吧,谢谢大嘎!
Python pytorch yolov5 google colab 口罩佩戴检测
colab 上的训练在这里
目前有用的网络视频流地址:伊拉克电视台
rtmp://ns8.indexforce.com/home/mystream
https://vd2.bdstatic.com/mda-kbitdw1fp321irs1/v1-cae/sc/mda-kbitdw1fp321irs1.mp4?v_from_s=hkapp-haokan-suzhou&auth_key=1647140033-0-0-5b3b43f203e8f57d4a2e34627da9f137&bcevod_channel=searchbox_feed&pd=1&cd=0&pt=3&logid=1432873267&vid=2466983731079509186&abtest=100815_2-17451_2&klogid=1432873267%20#%20%E5%BA%94%E8%AF%A5%E5%9C%A8%E7%95%8C%E9%9D%A2%E5%90%AF%E5%8A%A8%E7%9A%84%E6%97%B6%E5%80%99%E5%B0%B1%E5%B0%86%E6%A8%A1%E5%9E%8B%E5%8A%A0%E8%BD%BD%E5%87%BA%E6%9D%A5%EF%BC%8C%E8%AE%BE%E7%BD%AEtmp%E7%9A%84%E7%9B%AE%E5%BD%95%E6%9D%A5%E6%94%BE%E4%B8%AD%E9%97%B4%E7%9A%84%E5%A4%84%E7%90%86%E7%BB%93%E6%9E%9C
这可能是最后一次训练了
训练结果参考另一篇的 exp27
本来以为还要重新训练过的,但是改了一下两个阈值发现效果不错,置信度改成 0.5,iou 改成 0.3 左右。这样可以把一些把手当成鼻子背景当成口罩 and 一些一张脸多个框的框给过滤掉,因为这次训练本身就把清楚的人头都能标到 0.9+的置信度,所以置信度阈值其实还可以再提高一些,因为有些背景还是会有大概 0.79 会被识别成口罩。其实可以多加一些环境的负样本,比如手或是一些模糊背景进去再训练,但是本人比较懒,加上手机拍摄照片的格式还得转换成 jpg,且 mac 不能通过修改扩展名来改变格式。。。所以训练暂时告一段落。
2022.4.22 在 colab 上从 0 开始训练 100 轮
!nvidia-smi
import torch
torch.__version__
!pip3 install torchvision
import os
from google.colab import drive
drive.mount('/content/drive')
path = "/content/drive/My Drive"
os.chdir(path)
os.listdir(path)
%cd yolov5
!python train.py --data data/data.yaml --cfg models/yolov5s.yaml --weights '' --epochs 100 --batch-size 64
忘记改 Detect 的 thickness 和关闭置信度显示了,所以人多的图有点乱。
!python detect.py --source ../mask4/train/images --weights 'runs/train/exp23/weights/best.pt'
原文前言
- 训练日志在另一篇中。
- Mac 上,首先读取子目录会有隐藏的.DS_store文件,在终端运行删除这些。
find ./ -name ".DS_Store" -depth -exec rm {} \;
- 查找了永久不再生成这个文件的指令,重启后好像并没有用。。所以每次创文件夹还得删一次。
原文
- 查找了永久不再生成这个文件的指令,重启后好像并没有用。。所以每次创文件夹还得删一次。
- mac 上右键文件按住 option 会出现将此文件拷贝为文件路径可以直接复制文件路径。
labelimg 重新标注时报错超过 index 范围
- labelImg 的使用注意
- 修改数据框后再点下一张的时候 Python 直接退出,报错index 超出 list,查看 classes 发现少了一个类,加回去后才能上下查看图片。解决:“修改安装路径下data文件夹下的默认predefined_classes.txt,将其中的类删除换成自己的类”
- 上面的问题之前是解决了的,但是后来又去修改时还是会报错,不知道是不是只是 mac 的问题,就是我后面想要修改时,如果只在一张图上修改一个标签,那么 classes 的文件就会只出现这一个标签,如果在一张图中修改了两种标签,那么标签的名字会按顺序写入 classes,所以解决方法就是找一张图按顺序添加两个标签,再删掉就行了。(因为我只有两个类,太多的话就 gg 只能第一次就要标注好咯)
代码
# find ./ -name ".DS_Store" -depth -exec rm {} \;
import numpy as np
import cv2
import os
from tqdm import tqdm
label=np.zeros( (6) )
data_=np.zeros((6,512,512))
array_img = []
def image(path):
print("-" * 50)
print("训练集读取")
'''读取路径下所有子文件夹中的图片并存入list'''
train = []
dir_counter = 0
x=0
i=0
h=-1
for child_dir in os.listdir(path):
child_path = os.path.join(path, child_dir)
h += 1
for dir_image in tqdm(os.listdir(child_path)):
img = cv2.imread(child_path + "//" + dir_image, cv2.IMREAD_COLOR) # 斜杆\改成/
#cv2.namedWindow("Image")
# cv2.imshow("Image", img)
img=cv2.resize(img,(512,512))
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#灰度处理
data=np.zeros((512,512))
data[0:img.shape[0],0:img.shape[1]] = img
data_[i, :, :] = data[0:512, 0:512]
label[x] = h
i += 1
x += 1
dir_counter += 1
train.append(label)
train.append(data_)
return train
image('/Users/sinkarsenic/Downloads/mask/val/mask/test')
print('data_')
print(data_)
print('label')
print(label)
删完隐藏文件后还是报错,改了参数啥的 也没变好,debug发现是图片没读出来,刚好看到这篇文章给了我启发。
关于 NoneType : object has no attribute shape
把斜杆\改成/就可以了
但是这一段只是打印出标签并没有创建…
所以
mac使用python脚本快捷键创建txt文本
学会了 mac 的自动化操作
发现这段代码可以加点自己写的
def createtext():
path_name = os.getcwd()
#path_name = raw_input()
path_name += '/'
text_name = '新文本_' # + str(random.randint(0, 65536))
completeName = path_name + text_name + ".txt"
file1 = open(completeName , "w")
init_text = "Hello world!"
file1.write(init_text)
file1.close()
file_name("/Users/sinkarsenic/Downloads/mask/val/mask/test/nomask")
批量生成YOLO 格式标签
<object-class> <x> <y> <width> <height>
x,y是目标的中心坐标,width,height是目标的宽和高。
这些坐标是通过归一化的,其中x,width是使用原图的width进行归一化;
而y,height是使用原图的height进行归一化。
创建txt 的时候要获取图片名称,把.jpg去掉发现还有个空的数据,不去掉发现又是那个 dsstore!
于是加了个 if 判断处理后的文件长度,排除掉空的再生成 txt。
def file_name(file_dir):
for root, dirs, files in os.walk(file_dir):
#print(root) #当前目录路径
#print(dirs) #当前路径下所有子目录
for file in files:
file = file.split('.')[0]
if len(file)!=0:
path_name = root
path_name += '/'
text_name = file
completeName = path_name + text_name + ".txt"
file1 = open(completeName, "w")
init_text = "0 0.500952 0.501429 0.998095 0.997143"# 整张图片
file1.write(init_text)
file1.close()
print(len(file)) #当前路径下所有非目录子文件
批量给图片改名字加前缀
- 源代码是加前缀就行了,但我发现我的数据集原名字有点长,干脆都改成数字。
import os
import sys
path = "/Users/sinkarsenic/Downloads/mask/val/mask/test/nomask"
postfix = ".jpg" #只改后缀为这个的
mark = 'm_' #'nm_' # 前缀名
def add_prefix_files():
oldnames = os.listdir(path)
index = 0
for oldname in oldnames:
if oldname!=sys.argv[0]:
#if oldname.endswith(postfix):如果文件夹中只有图片得注释掉不然只会修改固定后缀的图片
os.rename(os.path.join(path,oldname),os.path.join(path,mark + str(index) + '.jpg'))
print(oldname,"has been renamed successfully! New name is: ",mark+str(index) + '.jpg')
index=index+1
本来以为要卡一会,没想到 600 多图片转眼就重命名完了。
批量在 txt 内容前面加上标签数字 0 和 1
def add_mark():
with open('/Users/sinkarsenic/Downloads/mask/val/mask/test/nomask/m_0.txt', 'r+') as f:
content = f.read()
f.seek(0, 0)
f.write('0'+" "+content)
- 然后发现我已经打好标签了全都是 0,现在需要的是修改第一个数字而不是加数字。。。
批量将数据集 txt 中的第一个数字替换
def replace_mark():
if __name__ == '__main__':
txt_list = glob.glob("/Users/sinkarsenic/Downloads/mask/test/test/*.txt")
for txt_item in txt_list:
with open(txt_item) as f:
lines = f.readlines()
with open(txt_item, 'w') as f:
for line in lines:
line_split = line.strip().split()
line_split[0] = '1' #替换的数字
f.write(
line_split[0] + ' ' +
line_split[1] + " " +
line_split[2] + " " +
line_split[3] + " " +
line_split[4]+'\n')
pass
replace_mark()
然后只修改带有 m_前缀的文件名加一个 if
if mark not in os.path.split(txt_item)[1]:
(attention:not in 是包括 classes.txt 的)
批量将 voc 数据集改成 yolo 格式
- 网上找的代码好像有点错误…有些框会丢失,所以干脆自己写个自动点击代码,在 labelimg 上直接自己点。
- 写无限循环的时候千万千万千万要设个条件 break…因为 mac 系统还不知道怎么通过键盘输入来暂停,而且鼠标不在 pycharm 上按也没用…只能算下大概要点多少次设个 break…之前没设的两次真是费了老大劲才关闭(还好只设了间隔 0.5 秒手速快还是能关的…)mac 这玩意连休眠再启动它都还在点的…
import pyautogui
import time
import cv2
#time.sleep(4)
x, y = pyautogui.position()
print(x, y)
next = (42,274)
change = (42,446)
save = (42,393)
other = (193,239)
i = 0
while 1:
i = i+1
pyautogui.leftClick(other)
time.sleep(0.1)
pyautogui.leftClick(change)
time.sleep(0.1)
pyautogui.leftClick(save)
time.sleep(0.1)
pyautogui.leftClick(next)
if i == 680:
break
- 用 labelImg 把 xml 转成 txt 后,xml 和 txt 在同一个文件夹,于是又写代码批量将 xml 文件删掉。
import os
filename = "/Users/sinkarsenic/Downloads/mask_detect/archive/annotations"
for root, dirs, files in os.walk(filename):
#print(root) #当前目录路径
#print(dirs) #当前路径下所有子目录
for file in files:
post = file.split('.')[1]
prefix = file.split('.')[0]
if post=="xml":
#print(prefix)
delete_path = os.path.join(filename, prefix + ".xml")
#print(delete_path)
os.remove(delete_path)
将爬取的文件夹中的所有文件夹内容批量拷贝到一个文件夹中
- 下载的一个数据集中有很多个以名字命名的文件夹,每个文件夹里有几张图片,想把所有图片都整在一起。
#将爬取的文件夹中的所有文件夹内容批量拷贝到一个文件夹中
import shutil
import os
copypath = "/Users/sinkarsenic/Downloads/mask_detect/mask3/without_mask"
movepath1 = "/Users/sinkarsenic/Downloads/mask_detect/mask3/without"
for root, dirs, files in os.walk(copypath, topdown=False):
for name in files:
# print(os.path.join(root, name))
filepath=os.path.join(root, name) #文件存放路径
movepath = os.path.join(movepath1, name) # movepath:指定移动文件夹
shutil.copyfile(filepath,movepath)
YOLOv5 在 colab 上
人脸检测负样本下载可能得科学上
- 修改 train.py 中的weights(pt)和 data(yaml )
- 基于官网的预训练模型继续训练
- Colab运行YOLOv5
$ python train.py --img 640 --batch 16 --epochs 300 --data ../orange-detection1/data.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt
- 基于训练得到的best.pt模型继续训练
$ python train.py --img 640 --batch 16 --epochs 300 --data ../orange-detection1/data.yaml --cfg models/yolov5s.yaml --weights best.pt
my
!python train.py --data data/data.yaml --cfg models/yolov5s.yaml --weights 'runs/train/exp18/weights/best.pt' --epochs 100 --batch-size 64
中断训练后通过设置 resume 继续训练
- colab训练太久会断开,没钱升级 pro。
!python train.py --data data/data.yaml --cfg models/yolov5s.yaml
–weights ‘runs/train/exp11/weights/best.pt’ --epochs 150 --batch-size 64
Yolov5如何在训练意外中断后接续训练
PyTorch三种保存方法 模型保存和继续训练的完整例程
How to prevent Google Colab from disconnecting ?
pytorch 保存模型
best_model = '/models/yolov5s.yaml'
PATH = './runs/train/exp5/weights/best.pth'
torch.save(best_model, PATH)
发现这个PyTorch实现断点继续训练
detect
- 测试
执行成功后,会显示检测结果保存路径,并在保存路径(yolov5s/runs/detect)下查看检测图片的结果。
python detect.py --weight weights/best.pt --source ../orange-detection1/test/images/图片名
my
!python detect.py --source ../mask/valid/images --weights 'runs/train/exp13/weights/best.pt'
Yolov3模型没有框的解决方案之——提高训练模型的置信度
深度学习中“过拟合”的产生原因和解决方法
YOLOv5 参数介绍
准确率(Precision)、召回率(Recall)以及F值(F-Measure)
理解准确率,精准率,召回率,真正率,假正率,ROC/AUC
使用WBF来提升目标检测性能
基于YOLOV4的人脸口罩佩戴检测(全过程知乎)
一些项目的参考
可视化界面
自留一下,省的爆改后找不到原代码了
'''
***上传图片***
'''
def upload_img(self):
# 选择录像文件进行读取
global result_path
global origin_path
fileName, fileType = QFileDialog.getOpenFileName(self, 'Choose file', '', '*.jpg *.png *.tif *.jpeg')
if fileName:
suffix = fileName.split(".")[-1]
origin_path = osp.join("/Users/sinkarsenic/PycharmProjects/mask_detect/images/origin", "tmp_upload.jpg") #暂时统一 + suffix
result_path = osp.join("/Users/sinkarsenic/PycharmProjects/mask_detect/images/tmp", "tmp_upload.jpg")
shutil.copy(fileName, origin_path)
# 应该调整一下图片的大小,然后统一放在一起
im0 = cv2.imread(origin_path)
# resize_scale = 1 #self.output_size / im0.shape[0]
# im0 = cv2.resize(im0, (0, 0), fx=resize_scale, fy=resize_scale)
# cv2.imwrite(result_path, im0)
#self.right_img.setPixmap(QPixmap("images/tmp/single_result.jpg"))
self.img2predict = fileName
self.left_img.setPixmap(QPixmap(origin_path))
# 上传图片之后右侧的图片重置,
self.right_img.setPixmap(QPixmap("/Users/sinkarsenic/PycharmProjects/mask_detect/images/UI/right.jpeg")) # 改路径
def detect_img(self):
os.system('python /Users/sinkarsenic/PycharmProjects/mask_detect/detect.py')
self.left_img.setPixmap(QPixmap(origin_path))
self.right_img.setPixmap(QPixmap(result_path))
- 1.如果是大的图片,界面上显示的图片不完整。
完整版
# -*- coding: utf-8 -*-
# 再整个输入 url 下载视频检测
# https://vd2.bdstatic.com/mda-kbitdw1fp321irs1/v1-cae/sc/mda-kbitdw1fp321irs1.mp4?v_from_s=hkapp-haokan-suzhou&auth_key=1647140033-0-0-5b3b43f203e8f57d4a2e34627da9f137&bcevod_channel=searchbox_feed&pd=1&cd=0&pt=3&logid=1432873267&vid=2466983731079509186&abtest=100815_2-17451_2&klogid=1432873267
# 应该在界面启动的时候就将模型加载出来,设置tmp的目录来放中间的处理结果
import shutil
import PyQt5.QtCore
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import threading
import argparse
import os
import sys
from pathlib import Path
import cv2
import torch
import torch.backends.cudnn as cudnn
import os.path as osp
import detect
FILE = Path(__file__).resolve()
ROOT = FILE.parents[0] # YOLOv5 root directory : /Users/sinkarsenic/PycharmProjects/mask_detect
if str(ROOT) not in sys.path:
sys.path.append(str(ROOT)) # add ROOT to PATH
ROOT = Path(os.path.relpath(ROOT, Path.cwd())) # relative
from models.common import DetectMultiBackend
from utils.datasets import IMG_FORMATS, VID_FORMATS, LoadImages, LoadStreams
from utils.general import (LOGGER, check_file, check_img_size, check_imshow, check_requirements, colorstr,
increment_path<