Dell AI/ADS 比赛

我也是身经百战了

 

笔试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
选择题 55道 每题一分
主观题1: 15分
主观题2: 30分
共100分

一、选择题 (共55题,其中部分为多选题,已在题中提示) :
1.( B )下列哪个语句在Python中是非法的
A. x = y = z = 1
B. x = (y = z + 1)
C. x, y = y, x
D. x += y

2.( B )关于Python内存管理,下列说法错误的是
A.变量不必事先声明 B. 变量无须先创建和赋值而直接使用
C. 变量无须指定类型 D. 可以使用del释放资源

3.( B )下面哪个不是Python合法的标识符
A. int32 B. 40XL C. self D. __name__

4.( A )下列哪种说法是错误的
A. 除字典类型外,所有标准对象均可以用于布尔测试
B. 空字符串的布尔值是False
C. 空列表对象的布尔值是False
D. 值为0的任何数字对象的布尔值是False

5.( A )Python不支持的数据类型有
A. char B. int C. float D. list

6.( C )关于Python中的复数,下列说法错误的是
A. 表示复数的语法是real + image j
B. 实部和虚部都是浮点数
C. 虚部必须后缀j,且必须是小写
D. 方法conjugate返回复数的共轭复数

7.( B )关于字符串下列说法错误的是
A. 字符应该视为长度为1的字符串
B. 字符串以\0标志字符串的结束
C. 既可以用单引号,也可以用双引号创建字符串
D. 在三引号字符串中可以包含换行回车等特殊字符

8.( C )以下不能创建一个字典的语句是
A. dict1 = {}
B. dict2 = { 3 : 5 }
C. dict3 = {[1,2,3]: “uestc”}
D. dict4 = {(1,2,3): “uestc”}

9.( A )下列Python语句正确的是
A. min = x if x < y else y
B. max = x > y ? x : y
C. if (x > y) print x
D. while True : pass

10.( A )计算机中信息处理和信息储存用
A. 二进制代码 B. 十进制代码 C. 十六进制代码 D. ASCII代码

11. ( A )python源程序执行的方式
A. 编译执行 B. 解析执行 C . 直接执行 D. 边编译边执行

12.( C )Python语言语句块的标记是
A. 分号 B. 逗号 C. 缩进 D. /

13.( B ) 以下是字符转换成字节的方法是
A. decode () B. encode () C. upper() D. rstrip()

14. 多选题(B )以下是正确的字符串
A. ‘abc”ab” B. ‘abc”ab’ C. “abc”ab” D. “abc\”ab”

15.(C )“ab”+”c”*2 结果是
A . abc2 B. abcabc C. abcc D. ababcc

16.( B )以下会出现错误的是
A. ‘北京’.encode()
B. ‘北京’.decode()
C. ‘北京’.encode().decode()
D. 以上都不会错误

17.( B ) 如下:

str1 = "Runoob example....wow!!!"

str2 = "exam";

Print(str1.find(str2, 5)) 打印的结果是

A. 6 B. 7 C. 8 D. -1

18. 多选题( B ) 下面对count(),index(), find()方法描述错误的是
A. count() 方法用于统计字符串里某个字符出现的次数
B . find() 方法检测字符串中是否包含子字符串 str 如果包含子字符串返回开始的索引值,否则会报一个 异常
C . index() 方法检测字符串中是否包含子字符串 str, 如果str不在 返回-1
D. 以上都错误

19.( A )有下面的程序段
if k<=10 and k >0:
if k >5:
if k>8:
x=0
else:
x=1
else:
if k>2:
x=3
else:
x=4
其中k取那组值时 x =3 ( )
A. 3,4,5 B. 3,4 C. 5,6,7 D. 4,5

20.( D ) 以下不是python中的关键字
A. raise B. with C. import D. final

21.( D ) 调用以下函数返回的值
def myfun():
pass
A. 0 B. 出错不能运行 C. 空字符串 D. None

22. ( C )函数如下,下面那些在调用函数时会报错
def showNnumber(numbers):
for n in numbers:
print(n)
A. showNumer([2,4,5]) B. showNnumber(‘abcesf’)
C. showNnumber(3.4) D. showNumber((12,4,5))

23. ( B ) 函数如下,打印结果哪项是正确的
def chanageInt(number2):
number2 = number2+1
print("changeInt: number2= ",number2)
#调用
number1 = 2
chanageInt(number1)
print("number:",number1)
A. changeInt: number2= 3 number: 3
B. changeInt: number2= 3 number: 2
C. number: 2 changeInt: number2= 2
D. number: 2 changeInt: number2= 3

24. 多选题( CD )函数如下,下面对 strs 和 list 的值输出正确的是
def chanageList(list):
list.append(" end")
print("list",list)
#调用
strs =['1','2']
chanageList(strs)
print("strs",strs)
A. strs ['1','2'] B. list ['1','2']
C. list ['1','2',’end’] D. strs ['1','2',’end’]

25. 多选题( CD )定义类如下,下面说明错误的是
class Hello():
pass

A. 该类实例中包含__dir__()方法
B. 该类实例中包含__hash__()方法
C. 该类实例中只包含__dir__(),不包含__hash__()
D. 该类没有定义任何方法,所以该实例中没有包含任何方法

26. 多选题( AC )定义类如下:
class hello():
def showInfo(sef):
print(self.x)
A.该类不可以实例化
B. 该类可以实例化
C. 在pycharm 工具中会出现语法错误,说self没有定义
D. 该类可以实例化,并且能正常通过对象调用showInfo()

27. ( B ) 关于python类 说法错误的是
A. 类的实例方法必须创建对象后才可以调用
B. 类的实例方法必须创建对象前才可以调用
C. 类的类方法可以用对象和类名来调用
D. 类的静态属性可以用类名和对象来调用

28. ( C ) 定义类如下, 下面代码能正常执行的
class Hello():
def __init__(self,name)
self.name=name
def showInfo(self)
print(self.name)

A. h = Hello
h.showInfo()
B. h = Hello()
h.showInfo(‘张三‘)
C. h = Hello(‘张三’)
h.showInfo()
D. h = Hello(‘admin’)
showInfo

29. ( D ) 定义类如下, 以下程序能执行的结果是
class A():
def a():
print(“a”)
class B ():
def b():
print(“b”)
class C():
def c():
print(c)
class D(A,C):
def d():
print(“d”)
d = D()
d.a()
d.b()
d.d()

A. a,b,d B. a,d C. d,a D. 执行会报错

30. ( D ) 以下哪项python能正常启动
A. 拼写错误 B . 错误表达式 C. 缩进错误 D. 手动抛出异常


31. ( B ) 有关异常说法正确的是
A. 程序中抛出异常终止程序
B. 程序中抛出异常不一定终止程序
C. 拼写错误会导致程序终止
D. 缩进错误会导致程序终止

32. ( A ) 对以下程序描述错误的是
try:
#语句块1
except IndexError as i:
# 语句块2
A. 改程序对异常处理了,因此一定不会终止程序
B. 改程序对异常处理了,不一定不会因异常引发终止
C. 语句块1,如果抛出IndexError 异常,不会因为异常终止程序
D. 语句块2 不一定会执行

33. ( B ) 程序如下:
try:
number = int(input("请输入数字:"))
print("number:",number)
print("=======hello======")
except Exception as e:
# 报错错误日志
print("打印异常详情信息: ",e)
else:
print("没有异常")
finally:#关闭资源
print("finally")
print("end")
输入的是 1a 结果是
A. number: 1
打印异常详情信息: invalid literal for int() with base 10:
finally
end
B. 打印异常详情信息: invalid literal for int() with base 10:
finally
end
C. ========hello===========
打印异常详情信息: invalid literal for int() with base 10:
finally
End
D. 以上都正确

34. ( D ) 导入模块的方式错误的是
A. import mo B. from mo import *
C. import mo as m D. import m from mo



35. ( C ) 以下关于模块说法错误的是
A. 一个xx.py就是一个模块
B. 任何一个普通的xx.py文件可以作为模块导入
C. 模块文件的扩展名不一定是 .py
D. 运行时会从制定的目录搜索导入的模块,如果没有,会报错异常


36. ( C )关于数据的存储结构,以下选项描述正确的是
A. 数据所占的存储空间量
B. 数据在计算机中的顺序存储方式
C. 数据的逻辑结构在计算机中的表示
D. 存储在外存中的数据

37. ( D )关于线性链表的描述,以下选项中正确的是
A. 存储空间不一定连续,且前件元素一定存储在后件元素的前面
B. 存储空间必须连续,且前件元素一定存储在后件元素的前面
C. 存储空间必须连续,且各元素的存储顺序是任意的
D. 存储空间不一定连续,且各元素的存储顺序是任意的

38. ( B )在深度为 7 的满二叉树中,叶子结点的总个数是
A. 31 B. 64 C. 63 D. 32

39. ( C )关于结构化程序设计所要求的基本结构,以下选项中描述错误的是
A. 重复(循环)结构
B. 选择(分支)结构
C. goto 跳转
D. 顺序结构

40. ( B )关于面向对象的继承,以下选项中描述正确的是
A. 继承是指一组对象所具有的相似性质
B. 继承是指类之间共享属性和操作的机制
C. 继承是指各对象之间的共同性质
D. 继承是指一个对象具有另一个对象的性质

41. ( C )关于软件危机,以下选项中描述错误的是
A. 软件成本不断提高
B. 软件质量难以控制
C. 软件过程不规范
D. 软件开发生产率低

42. ( D )关于软件测试,以下选项中描述正确的是
A. 软件测试的主要目的是确定程序中错误的位置
B. 为了提高软件测试的效率,最好由程序编制者自己来完成软件的测试工作
C. 软件测试是证明软件没有错误
D. 软件测试的主要目的是发现程序中的错误

43. ( B )以下选项中用树形结构表示实体之间联系的模型是
A. 网状模型
B. 层次模型
C. 静态模型
D. 关系模型

44. ( B )设有表示学生选课的三张表,学生S(学号,姓名,性别,年龄,身份证号),课程(课号,课程名),选课SC(学号,课号,成绩),表SC的关键字(键或码)是
A. 学号,成绩
B. 学号,课号
C. 学号,姓名,成绩
D. 课号,成绩

45. ( C )设有如下关系表:
以下选项中正确地描述了关系表 R、S、T 之间关系的是
A. T=R∪S
B. T=R×S
C. T=R–S
D. T=R∩S

46. ( D )关于 Python 程序格式框架的描述,以下选项中错误的是
A. Python 语言的缩进可以采用 Tab 键实现
B. Python单层缩进代码属于之前最邻近的一行非缩进代码,多层缩进代码根据缩进关系决定所属范围
C. 判断、循环、函数等语法形式能够通过缩进包含一批Python 代码,进而表达对应的语义
D. Python 语言不采用严格的“缩进”来表明程序的格式框架

47. ( B )以下选项中不符合 Python 语言变量命名规则的是
A. I
B. 3_1
C. _AI
D. TempStr

48. ( C )以下关于 Python 字符串的描述中,错误的是
A. 字符串是字符的序列,可以按照单个字符或者字符片段进行索引
B. 字符串包括两种序号体系:正向递增和反向递减
C. Python字符串提供区间访问方式,采用 [N:M] 格式,表示字符串中从 N 到 M 的索引子字符串(包含 N 和 M)
D. 字符串是用一对双引号""或者单引号’ '括起来的零个或者多个字符

49. ( B )关于 Python 语言的注释,以下选项中描述错误的是
A. Python 语言的单行注释以#开头
B. Python 语言的单行注释以单引号 ’ 开头
C. Python 语言的多行注释以 ’ ‘’(三个单引号)开头和结尾
D. Python 语言有两种注释方式:单行注释和多行注释

50. ( B )关于 import 引用,以下选项中描述错误的是
A. 使用 import turtle 引入turtle 库
B. 可以使用 from turtle import setup 引入turtle 库
C. 使用 import turtle as t 引入 turtle 库,取别名为 t
D. import保留字用于导入模块或者模块中的对象

51. ( B )下面代码的输出结果是
x = 12.34 print(type(x))
A. <class ‘int’>
B. <class ‘float’>
C. <class ‘bool’>
D. <class ‘complex’>

52. ( C )关于 Python 的复数类型,以下选项中描述错误的是
A 复数的虚数部分通过后缀“J”或者“j”来表示
B 对于复数 z,可以用 z.real 获得它的实数部分
C 对于复数 z,可以用z.imag 获得它的实数部分
D 复数类型表示数学中的复数

53. ( A )关于 Python 字符串,以下选项中描述错误的是
A. 可以使用 datatype() 测试字符串的类型
B. 输出带有引号的字符串,可以使用转义字符\
C. 字符串是一个字符序列,字符串中的编号叫“索引”
D. 字符串可以保存在变量中,也可以单独存在

54. ( D )关于 Python 的分支结构,以下选项中描述错误的是
A. 分支结构使用 if 保留字
B. Python 中 if-else 语句用来形成二分支结构
C. Python 中 if-elif-else语句描述多分支结构
D. 分支结构可以向已经执行过的语句部分跳转

55. ( C )关于程序的异常处理,以下选项中描述错误的是
A. 程序异常发生经过妥善处理可以继续执行
B. 异常语句可以与 else 和 finally 保留字配合使用
C. 编程语言中的异常和错误是完全相同的概念
D. Python 通过 try、except 等保留字提供异常处理功能


二、 主观题 (共2题) :

1. 一个数如果恰好等于它的因子之和,这个数就称为“完数”,例如, 6 的因子为 1、 2、 3,而 6=1+2+3,因此 6 是“完数”。编程序找出 1000 之内的所有完数。

6 是完数 对应的因子是: [1, 2, 3]
28 是完数 对应的因子是: [1, 2, 4, 7, 14]
496 是完数 对应的因子是: [1, 2, 4, 8, 16, 31, 62, 124, 248]

number = 1001
list = [1]
sum = 0
for i in range(2, number):
for j in range(2, i):
if i % j == 0:
if j not in list: # 判断列表中是否有重复值
list.append(j)
for k in list: # 循环计算因子的和
sum += k
if sum == i:
print(i ,"是完数", "对应的因子是:", list)

list = [1]
sum = 0

2. 因为智能设备的沟通门槛变低,骚扰电话也随之多了起来。同时智能手机时代,手机的定制性大大加强,也为解决这类的问题提供了技术空间。请帮忙设计相应算法,可以从一个已知的骚扰电话库中在内存中建立相应号码库,并且支持快速检验一个来电是不是骚扰电话,要求如下:
1)描述这个库的初始化过程和查询过程。
2)设计一个搜索算法,要求:
时间复杂度最优。
空间复杂度合理。

算法主要思路:采用哈希查找算法,加上连续数字段模糊匹配减小时间和空间复杂度。
哈希表就是一种以键-值(key-indexed) 存储数据的结构,只要输入待查找的值即key,即可查找到其对应的值。
初始化过程:所有的电话号码(键)都是整数,那么就可以使用一个简单的无序数组来实现:将键作为索引,值即为其对应的值,这样就可以快速访问任意键的值。
算法流程:
1)用给定的哈希函数构造哈希表;
2)根据选择的冲突处理方法解决地址冲突;常见的解决冲突的方法:拉链法和线性探测法。
3)在哈希表的基础上执行哈希查找。

复杂度分析

单纯论查找复杂度:对于无冲突的Hash表而言,查找复杂度为O(1)

提取码:82jy

面试

  • 自我介绍
  • 专业相关
  • 有没有AI比赛经历
  • 有没有做过自动驾驶的项目
  • 如何理解深度学习
  • 深度学习和机器学习的联系与区别
  • CNN 是什么
  • CNN 有哪些层
  • RNN 是什么
  • 有监督学习和无监督学习
  • 现有网络可以改进的方向
  • 模型深度越深越好吗(容限)
  • 输入数据(标签)改进方向(数据清洗)
  • yolo全程(you only look once)
  • you only look once 怎么实现的
  • 简述 yolov3 以及和 v1 v2 区别
  • 与yolo对应的一个算法
  • RCNN 池化改进方向
  • FastRCNN 改进在哪
  • 写过什么模型网络以及调参经历

 

复试

 

题目:交通标志识别

  根据单独提供的原始图像数据集设计一个完整的交通标志(限速、取消限速)检测工作流。你需要标记数据,选择一个合适的模型,调整参数进行训练,并验证你训练模型的结果
限速/取消限速标识

 

环境

  • 平台硬件:工作站
  • 操作系统:windows10、Ubuntu18.04
  • GPU型号:NVIDIA GeForce RTX 3090 24GB
  • 开发语言:python3.7
  • 深度学习框架:PyTorch 1.7.0
  • 训练集大小:828
  • 测试集大小:100
  • 验证集大小:227
  • 训练出模型的时长:0.561h
  • 推理100张图片时长:1.434s
  • 是否有模型对比:模型仅13.7Mb,轻量,速度快于yolov3、EFFicientDet,精度由于场景单一都很高

 

实验步骤

  1. 数据集筛选:将赛题所给的数据集进行筛选,人工删除交通标识模糊、扭曲、以及溢出图片边界的低价值图像,最后从1774张图片中筛选出1055张
  2. 图像标注:使用labelimg将筛选出的图像进行标注,标注分 limit 和 nonlimit 两类,得到对应的xml标记文件
  3. 标注格式转换:使用tools/xmltotxt.py脚本,将xml标记文件转换成yolo所需要的txt标注格式文件
  4. 数据集整理:dataa/images/train 下存放828张训练集图像 dataa/images/val 下存放227张验证集图像 dataa/labels/train 下存放训练集对应的标注文件 dataa/labels/val 下存放验证集对应的标注文件 注:训练集和验证集图像由人工从多个场景中按比例筛选分类; 测试集图像由最后在整个数据集中随机挑选100张
  5. 编写yaml数据配置文件:见于dataa/custom.yaml
  6. 模型选择与构建:本项目基于yolov5s修改,是因为yolov5s网络小、速度快,能满足交通标志检测的实时性需求。
    Yolov5s 网络架构
  7. 输入图像缩放与填充:将输入图像缩放为640640,能最大程度上利用原始图像(640480)的有效信息
  8. 网络Backbone:Focus结构中切片操作;主干网络中设计CSP结构
  9. 网络Neck: FPN+PAN
  10. 网络输出层:采用GIOU_Loss作为Bounding box 的损失函数;加权NMS非极大值抑制
  11. 环境配置:安装requirements.txt中库包,注:3090 pytorch对应版本为1.7.0
  12. 预训练模型:使用 yolov5s.pt
  13. 超参数设置:batch size 设置为32,此时对应的GPU训练内存约为7G;以及根据实际情况修改其他超参数
  14. 训练:运行 train.py, 得到结果和训练后的权重文件 best.pt

 

实验结果

  1. 训练结果:记录于runs/train/exp,下面展示部分训练结果
  1. 测试生成的模型:使用得到的best.py权重文件,运行detect.py,测试100张图片,总共用时1.434s,单张图片推断仅需8ms
  1. 测试结果:测试结果位于runs/detect/exp3,部分测试结果如下
  1. 模型可视化:将best.pt转换成onnx格式,再利用netron可视化,高清图见 best.onnx.png/svg

interface.py 编写

按照比赛要求接口的测试脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import argparse
import time
from pathlib import Path

import cv2
import torch
import torch.backends.cudnn as cudnn

from models.experimental import attempt_load
from utils.datasets import LoadStreams, LoadImages
from utils.general import check_img_size, check_requirements, check_imshow, non_max_suppression, apply_classifier, \
scale_coords, xyxy2xywh, strip_optimizer, set_logging, increment_path, save_one_box
from utils.plots import colors, plot_one_box
from utils.torch_utils import select_device, load_classifier, time_synchronized

sign = {
nonlimit: 'cancel'
}

def inference(opt):
source, weights, view_img, save_txt, imgsz = opt.source, opt.weights, opt.view_img, opt.save_txt, opt.img_size
save_img = not opt.nosave and not source.endswith('.txt') # save inference images
webcam = source.isnumeric() or source.endswith('.txt') or source.lower().startswith(
('rtsp://', 'rtmp://', 'http://', 'https://'))

# Directories
save_dir = increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok) # increment run
(save_dir / 'labels' if save_txt else save_dir).mkdir(parents=True, exist_ok=True) # make dir

# Initialize
set_logging()
device = select_device(opt.device)
half = device.type != 'cpu' # half precision only supported on CUDA

# Load model
model = attempt_load(weights, map_location=device) # load FP32 model
stride = int(model.stride.max()) # model stride
imgsz = check_img_size(imgsz, s=stride) # check img_size
names = model.module.names if hasattr(model, 'module') else model.names # get class names
if half:
model.half() # to FP16

# Second-stage classifier
classify = False
if classify:
modelc = load_classifier(name='resnet101', n=2) # initialize
modelc.load_state_dict(torch.load('weights/resnet101.pt', map_location=device)['model']).to(device).eval()

# Set Dataloader
vid_path, vid_writer = None, None
if webcam:
view_img = check_imshow()
cudnn.benchmark = True # set True to speed up constant image size inference
dataset = LoadStreams(source, img_size=imgsz, stride=stride)
else:
dataset = LoadImages(source, img_size=imgsz, stride=stride)

# Run inference
if device.type != 'cpu':
model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters()))) # run once
t0 = time.time()
for path, img, im0s, vid_cap in dataset:
img = torch.from_numpy(img).to(device)
img = img.half() if half else img.float() # uint8 to fp16/32
img /= 255.0 # 0 - 255 to 0.0 - 1.0
if img.ndimension() == 3:
img = img.unsqueeze(0)

# Inference
t1 = time_synchronized()
pred = model(img, augment=opt.augment)[0]

# Apply NMS
pred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classes=opt.classes, agnostic=opt.agnostic_nms)
t2 = time_synchronized()

# Apply Classifier
if classify:
pred = apply_classifier(pred, modelc, img, im0s)

# Process detections
for i, det in enumerate(pred): # detections per image
if webcam: # batch_size >= 1
p, s, im0, frame = path[i], f'{i}: ', im0s[i].copy(), dataset.count
else:
p, s, im0, frame = path, '', im0s.copy(), getattr(dataset, 'frame', 0)

p = Path(p) # to Path
save_path = str(save_dir / p.name) # img.jpg
txt_path = str(save_dir / 'labels' / p.stem) + ('' if dataset.mode == 'image' else f'_{frame}') # img.txt
s += '%gx%g ' % img.shape[2:] # print string
gn = torch.tensor(im0.shape)[[1, 0, 1, 0]] # normalization gain whwh
if len(det):
# Rescale boxes from img_size to im0 size
det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()

# Print results
for c in det[:, -1].unique():
n = (det[:, -1] == c).sum() # detections per class
s += f"{n} {names[int(c)]}{'s' * (n > 1)}, " # add to string

# Write results
for *xyxy, conf, cls in reversed(det):
if save_txt: # Write to file
xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywh
line = (cls, *xywh, conf) if opt.save_conf else (cls, *xywh) # label format
with open(txt_path + '.txt', 'a') as f:
f.write(('%g ' * len(line)).rstrip() % line + '\n')

if save_img or opt.save_crop or view_img: # Add bbox to image
c = int(cls) # integer class
label = None if opt.hide_labels else (names[c] if opt.hide_conf else f'{names[c]} {conf:.2f}')
plot_one_box(xyxy, im0, label=label, color=colors(c, True), line_thickness=opt.line_thickness)
if opt.save_crop:
save_one_box(xyxy, im0s, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg', BGR=True)

# Print time (inference + NMS)
print(f'{s}Done. ({t2 - t1:.3f}s)')

# Stream results
if view_img:
cv2.imshow(str(p), im0)
cv2.waitKey(1) # 1 millisecond

# Save results (image with detections)
if save_img:
if dataset.mode == 'image':
cv2.imwrite(save_path, im0)
else: # 'video' or 'stream'
if vid_path != save_path: # new video
vid_path = save_path
if isinstance(vid_writer, cv2.VideoWriter):
vid_writer.release() # release previous video writer
if vid_cap: # video
fps = vid_cap.get(cv2.CAP_PROP_FPS)
w = int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
else: # stream
fps, w, h = 30, im0.shape[1], im0.shape[0]
save_path += '.mp4'
vid_writer = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
vid_writer.write(im0)

if save_txt or save_img:
s = f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir / 'labels'}" if save_txt else ''
print(f"Results saved to {save_dir}{s}")

print(f'Done. ({time.time() - t0:.3f}s)')


if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--weights', nargs='+', type=str, default='best.pt', help='model.pt path(s)')
parser.add_argument('--source', type=str, default='data/images', help='source') # file/folder, 0 for webcam
parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
parser.add_argument('--conf-thres', type=float, default=0.25, help='object confidence threshold')
parser.add_argument('--iou-thres', type=float, default=0.45, help='IOU threshold for NMS')
parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
parser.add_argument('--view-img', action='store_true', help='display results')
parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
parser.add_argument('--save-crop', action='store_true', help='save cropped prediction boxes')
parser.add_argument('--nosave', action='store_true', help='do not save images/videos')
parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')
parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
parser.add_argument('--augment', action='store_true', help='augmented inference')
parser.add_argument('--update', action='store_true', help='update all models')
parser.add_argument('--project', default='runs/detect', help='save results to project/name')
parser.add_argument('--name', default='exp', help='save results to project/name')
parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)')
parser.add_argument('--hide-labels', default=False, action='store_true', help='hide labels')
parser.add_argument('--hide-conf', default=False, action='store_true', help='hide confidences')
opt = parser.parse_args()
print(opt)
check_requirements(exclude=('tensorboard', 'pycocotools', 'thop'))

with torch.no_grad():
if opt.update: # update all models (to fix SourceChangeWarning)
for opt.weights in ['yolov5s.pt', 'yolov5m.pt', 'yolov5l.pt', 'yolov5x.pt']:
inference(opt=opt)
strip_optimizer(opt.weights)
else:
inference(opt=opt)


##需要补充按照要求格式的txt文件部分##

 

决赛

决赛流程

  • 复试通过后六强,进入决赛
  • 5月26日- 28日,线下集训(上海市杨浦区)。主要内容为小车组装,代码修改、测试、训练等
  • 5月29日上午模拟路考,下午方案陈述考试(占总成绩50%)
  • 5月30日,真实道路考试

 

硬件选择

  • 硬件选择计分规则:方案上采用NX主控会减分、采用多摄会加分、使用景深和激光雷达模组有加分、使用较大麦轮会扣分、使用增强版动力电机模组加分、使用增强版车架加分
  • 多目方案的选取:单目、双目、三目视觉原始图像如下所示。经过测试,对于赛道这种场景单一的情况,其实单目效果最好,但为了方案分数,采用裁剪拼接的三目方案。
    单目
    双目
    三目
    最终三目方案
  • 未采用景深和激光雷达模组,主要是因为其主要探测距离和障碍物,在纯视觉已经有很好效果的基础上不是很必要,且调试时间不够。
  • 采用较小车架,是权衡加减分以及机动性(转弯)的结果
  • 最终硬件结果

 

算法与软件

  • 在给出的基础架构上修改,交通标志识别部分算法,无法融合进框架,索性放弃,在训练上做文章(过拟合)
  • 具体框架文件丢失!找不到了!
  • 部分,提取码:6666
  • 训练:将自主训练的模型与预训练模型以及之前效果较好的模型混合训练,可以取得更好的效果,训练时间上5分钟左右是过拟合的最好状态
  • 关于限速的训练,修改手柄油门等参数:

结果

 

小比赛还是有黑幕不规范的地方