YOLOv5 is a family of object detection architectures and models pretrained on the COCO dataset, and represents Ultralytics open-source research into future vision AI methods, incorporating lessons learned and best practices evolved over thousands of hours of research and development.
1. 环境搭建 没有找到合适的板块发布,先放在这里把。刚才看了一下帖子内容被清空了?重新上传一下。传统的广告跳过做法是通过控件获取文本,根据关键字进行匹配。但是这种方法对于图片按钮和自定义控件的兼容性基本没有,所以想通过ai识别跳过按钮来实现广告跳过。大家有什么想法和建议还望不吝赐教,也环境大家加入这个项目~~ 自动广告跳过这个想法,不过由于各种原因一直没有实时。知道最近才又重新开始折腾这个东西,yolov5的安装这里就不再说明了,建议使用anaconda安装。我创建了一个conda环境可以直接下载之后通过conda安装:
如果不想使用上面的安装方法可以参考:https://blog.csdn.net/oJiWuXuan/article/details/107558286 和https://github.com/ultralytics/yolov5 按照官方指导进行安装。
2.数据准备 将手机上已经准备好的截图复制到Screenshot目录下,使用labelImg {conda 环境地址:https://anaconda.org/obaby/labelimg 可以直接导入使用},对图片进行标记。将标记后的xml文件保存到xmls目录下。 屏幕截图: labelimg标记: xml文件路径:3.构建数据集: 在根目录下创建make_text.py代码如下(以下代码基本都是拷贝自:https://blog.csdn.net/oJiWuXuan/article/details/107558286 这篇文章,表示感谢!! ):
创建voc_label.py代码如下,需要注意classes中的列别信息:
分别运行makeTxt.py和voc_label.py。
make_text.py主要是将数据集分类成训练数据集和测试数据集,默认train,val,test按照8:1:1的比例进行随机分类,运行后ImagesSets文件夹中会出现四个文件,主要是生成的训练数据集和测试数据集的图片名称,如下图。同时data目录下也会出现这四个文件,内容是训练数据集和测试数据集的图片路径。 voc_label.py主要是将图片数据集标注后的xml文件中的标注信息读取出来并写入txt文件,运行后在labels文件夹中出现所有图片数据集的标注信息,如下图: 到这里,数据资源准备就ok了。4.修改配置文件 在data目录下创建ads.yml内容如下:
修改网络参数models/yolov5s.yaml(这里取决于你使用了哪个模型就去修改对于的文件,该项目中使用的是yolov5s模型),主要修改nc参数:
train_ads.py 参数修改,主要参数解释如下。我们平时训练的话,主要用到的只有这几个参数而已:–weights,–cfg,–data,–epochs,–batch-size,–img-size,–project:
5.训练模型 环境搭建好,数据准备完毕之后就可以开始进行魔性的训练了。直接执行train_ads.py进行模型训练:
训练结束之后的文件保存在Optimizer stripped from runs/train/exp3/weights/last.pt, 14.4MB Optimizer stripped from runs/train/exp3/weights/best.pt, 14.4MB两个文件中。到这里模型训练就结束了。 在训练中,也可以随时查看每一轮次训练的结果,可利用tensorboard可视化训练过程,训练开始时会在runs/train/exp文件夹中产生一个“events.out.tfevents.1608924773.JWX.5276.0”文件,利用tensorboard打开即可查看训练日志。首先我们通过cmd进去该YOLOv5所在的项目文件夹,然后激活所用的虚拟环境,输入如下命令行:
命令行输入信息的整体显示如下所示:
到这一步后,我们就可打开 http://localhost:6006/ 网页查看每一轮次训练的结果,如图所示。6.实现检查 修改detect_ads.py中的参数主要用到的只有这几个参数:–weights,–source,–conf-thres,–project:
通过下面的命令进行检测:
检测回显:
如果不修改detect.py文件这可以通过下面的命令进行检测:
检测效果,由于样本太少,导致检测到的概率太低,为了显示出来这里把parser.add_argument('--conf-thres', type=float, default=0.1,)--conf-thres调成了0.1否则直接检测不到跳过按钮,调低之后检测到的跳过按钮有的并不是跳过按钮(后一张图)。 下图检测到的按钮是有问题的: 为了提高检测准确度,下一步会加大样本量再次训练,等待看效果吧 ~~
安卓apk开屏广告跳过按钮识别项目,地址:https://github.com/obaby/skip_ads_yolov5
obaby@mars http://www.h4ck.org.cn http://www.obaby.org.cn
参考链接: https://github.com/EvgenMeshkin/ScreenShot/blob/master/app/src/main/java/by/android/evgen/screenshot/ScreenActivity.java https://blog.csdn.net/qq_38499859/article/details/90523283 https://juejin.cn/post/6844903589127651335 https://stackoverflow.com/questions/2661536/how-to-programmatically-take-a-screenshot-on-android https://pytorch.org https://developer.nvidia.com/cuda-downloads?target_os=Windows&target_arch=x86_64&target_version=10&target_type=exe_network
conda env create user
/
my
-
environment
source activate my
-
environment
conda env create user
/
my
-
environment
source activate my
-
environment
import
os
import
random
trainval_percent
=
0.9
train_percent
=
0.9
xmlfilepath
=
'xmls'
txtsavepath
=
'Screenshots'
total_xml
=
os.listdir(xmlfilepath)
num
=
len
(total_xml)
list
=
range
(num)
tv
=
int
(num
*
trainval_percent)
tr
=
int
(tv
*
train_percent)
trainval
=
random.sample(
list
, tv)
train
=
random.sample(trainval, tr)
ftrainval
=
open
(
'data/ImageSets/trainval.txt'
,
'w'
)
ftest
=
open
(
'data/ImageSets/test.txt'
,
'w'
)
ftrain
=
open
(
'data/ImageSets/train.txt'
,
'w'
)
fval
=
open
(
'data/ImageSets/val.txt'
,
'w'
)
for
i
in
list
:
name
=
total_xml[i][:
-
4
]
+
'\n'
if
i
in
trainval:
ftrainval.write(name)
if
i
in
train:
ftrain.write(name)
else
:
fval.write(name)
else
:
ftest.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
import
os
import
random
trainval_percent
=
0.9
train_percent
=
0.9
xmlfilepath
=
'xmls'
txtsavepath
=
'Screenshots'
total_xml
=
os.listdir(xmlfilepath)
num
=
len
(total_xml)
list
=
range
(num)
tv
=
int
(num
*
trainval_percent)
tr
=
int
(tv
*
train_percent)
trainval
=
random.sample(
list
, tv)
train
=
random.sample(trainval, tr)
ftrainval
=
open
(
'data/ImageSets/trainval.txt'
,
'w'
)
ftest
=
open
(
'data/ImageSets/test.txt'
,
'w'
)
ftrain
=
open
(
'data/ImageSets/train.txt'
,
'w'
)
fval
=
open
(
'data/ImageSets/val.txt'
,
'w'
)
for
i
in
list
:
name
=
total_xml[i][:
-
4
]
+
'\n'
if
i
in
trainval:
ftrainval.write(name)
if
i
in
train:
ftrain.write(name)
else
:
fval.write(name)
else
:
ftest.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
import
xml.etree.ElementTree as ET
import
pickle
import
os
from
os
import
listdir, getcwd
from
os.path
import
join
sets
=
[
'train'
,
'test'
,
'val'
]
classes
=
[
'skip'
]
def
convert(size, box):
dw
=
1.
/
size[
0
]
dh
=
1.
/
size[
1
]
x
=
(box[
0
]
+
box[
1
])
/
2.0
y
=
(box[
2
]
+
box[
3
])
/
2.0
w
=
box[
1
]
-
box[
0
]
h
=
box[
3
]
-
box[
2
]
x
=
x
*
dw
w
=
w
*
dw
y
=
y
*
dh
h
=
h
*
dh
return
(x, y, w, h)
def
convert_annotation(image_id):
in_file
=
open
(
'train/%s.xml'
%
(image_id), encoding
=
'utf-8'
)
out_file
=
open
(
'data/labels/%s.txt'
%
(image_id),
'w'
, encoding
=
'utf-8'
)
tree
=
ET.parse(in_file)
root
=
tree.getroot()
size
=
root.find(
'size'
)
if
size !
=
None
:
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))
print
(image_id,
cls
, b)
bb
=
convert((w, h), b)
out_file.write(
str
(cls_id)
+
" "
+
" "
.join([
str
(a)
for
a
in
bb])
+
'\n'
)
wd
=
getcwd()
print
(wd)
for
image_set
in
sets:
if
not
os.path.exists(
'data/labels/'
):
os.makedirs(
'data/labels/'
)
image_ids
=
open
(
'data/ImageSets/%s.txt'
%
(image_set)).read().strip().split()
list_file
=
open
(
'data/%s.txt'
%
(image_set),
'w'
)
for
image_id
in
image_ids:
list_file.write(
'data/images/%s.jpg\n'
%
(image_id))
convert_annotation(image_id)
list_file.close()
import
xml.etree.ElementTree as ET
import
pickle
import
os
from
os
import
listdir, getcwd
from
os.path
import
join
sets
=
[
'train'
,
'test'
,
'val'
]
classes
=
[
'skip'
]
def
convert(size, box):
dw
=
1.
/
size[
0
]
dh
=
1.
/
size[
1
]
x
=
(box[
0
]
+
box[
1
])
/
2.0
y
=
(box[
2
]
+
box[
3
])
/
2.0
w
=
box[
1
]
-
box[
0
]
h
=
box[
3
]
-
box[
2
]
x
=
x
*
dw
w
=
w
*
dw
y
=
y
*
dh
h
=
h
*
dh
return
(x, y, w, h)
def
convert_annotation(image_id):
in_file
=
open
(
'train/%s.xml'
%
(image_id), encoding
=
'utf-8'
)
out_file
=
open
(
'data/labels/%s.txt'
%
(image_id),
'w'
, encoding
=
'utf-8'
)
tree
=
ET.parse(in_file)
root
=
tree.getroot()
size
=
root.find(
'size'
)
if
size !
=
None
:
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))
print
(image_id,
cls
, b)
bb
=
convert((w, h), b)
out_file.write(
str
(cls_id)
+
" "
+
" "
.join([
str
(a)
for
a
in
bb])
+
'\n'
)
wd
=
getcwd()
print
(wd)
for
image_set
in
sets:
if
not
os.path.exists(
'data/labels/'
):
os.makedirs(
'data/labels/'
)
image_ids
=
open
(
'data/ImageSets/%s.txt'
%
(image_set)).read().strip().split()
list_file
=
open
(
'data/%s.txt'
%
(image_set),
'w'
)
for
image_id
in
image_ids:
list_file.write(
'data/images/%s.jpg\n'
%
(image_id))
convert_annotation(image_id)
list_file.close()
train: data
/
train.txt
val: data
/
val.txt
test: data
/
test.txt
nc:
1
names: [
'skip'
]
train: data
/
train.txt
val: data
/
val.txt
test: data
/
test.txt
nc:
1
names: [
'skip'
]
nc:
1
depth_multiple:
0.33
width_multiple:
0.50
anchors:
-
[
10
,
13
,
16
,
30
,
33
,
23
]
-
[
30
,
61
,
62
,
45
,
59
,
119
]
-
[
116
,
90
,
156
,
198
,
373
,
326
]
backbone:
[[
-
1
,
1
, Focus, [
64
,
3
]],
[
-
1
,
1
, Conv, [
128
,
3
,
2
]],
[
-
1
,
3
, C3, [
128
]],
[
-
1
,
1
, Conv, [
256
,
3
,
2
]],
[
-
1
,
9
, C3, [
256
]],
[
-
1
,
1
, Conv, [
512
,
3
,
2
]],
[
-
1
,
9
, C3, [
512
]],
[
-
1
,
1
, Conv, [
1024
,
3
,
2
]],
[
-
1
,
1
, SPP, [
1024
, [
5
,
9
,
13
]]],
[
-
1
,
3
, C3, [
1024
,
False
]],
]
head:
[[
-
1
,
1
, Conv, [
512
,
1
,
1
]],
[
-
1
,
1
, nn.Upsample, [
None
,
2
,
'nearest'
]],
[[
-
1
,
6
],
1
, Concat, [
1
]],
[
-
1
,
3
, C3, [
512
,
False
]],
[
-
1
,
1
, Conv, [
256
,
1
,
1
]],
[
-
1
,
1
, nn.Upsample, [
None
,
2
,
'nearest'
]],
[[
-
1
,
4
],
1
, Concat, [
1
]],
[
-
1
,
3
, C3, [
256
,
False
]],
[
-
1
,
1
, Conv, [
256
,
3
,
2
]],
[[
-
1
,
14
],
1
, Concat, [
1
]],
[
-
1
,
3
, C3, [
512
,
False
]],
[
-
1
,
1
, Conv, [
512
,
3
,
2
]],
[[
-
1
,
10
],
1
, Concat, [
1
]],
[
-
1
,
3
, C3, [
1024
,
False
]],
[[
17
,
20
,
23
],
1
, Detect, [nc, anchors]],
]
nc:
1
depth_multiple:
0.33
width_multiple:
0.50
anchors:
-
[
10
,
13
,
16
,
30
,
33
,
23
]
-
[
30
,
61
,
62
,
45
,
59
,
119
]
-
[
116
,
90
,
156
,
198
,
373
,
326
]
backbone:
[[
-
1
,
1
, Focus, [
64
,
3
]],
[
-
1
,
1
, Conv, [
128
,
3
,
2
]],
[
-
1
,
3
, C3, [
128
]],
[
-
1
,
1
, Conv, [
256
,
3
,
2
]],
[
-
1
,
9
, C3, [
256
]],
[
-
1
,
1
, Conv, [
512
,
3
,
2
]],
[
-
1
,
9
, C3, [
512
]],
[
-
1
,
1
, Conv, [
1024
,
3
,
2
]],
[
-
1
,
1
, SPP, [
1024
, [
5
,
9
,
13
]]],
[
-
1
,
3
, C3, [
1024
,
False
]],
]
head:
[[
-
1
,
1
, Conv, [
512
,
1
,
1
]],
[
-
1
,
1
, nn.Upsample, [
None
,
2
,
'nearest'
]],
[[
-
1
,
6
],
1
, Concat, [
1
]],
[
-
1
,
3
, C3, [
512
,
False
]],
[
-
1
,
1
, Conv, [
256
,
1
,
1
]],
[
-
1
,
1
, nn.Upsample, [
None
,
2
,
'nearest'
]],
[[
-
1
,
4
],
1
, Concat, [
1
]],
[
-
1
,
3
, C3, [
256
,
False
]],
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-9-16 09:37
被obaby编辑
,原因: 文档内容有问题,编辑器不支持火箭