├── .gitignore
├── .idea
├── deployment.xml
├── dictionaries
│ └── z00428518.xml
├── license-plate-generator.iml
├── markdown-navigator.xml
├── markdown-navigator
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── LICENSE
├── README.md
├── __init__.py
├── augment_image.py
├── background
├── A01_N84E28_1.jpg
├── A01_N84E28_2.jpg
├── A01_NMV802_1.jpg
├── A01_NMV802_2.jpg
├── A02_NBD719_1.jpg
├── A02_NBD719_2.jpg
├── A03_A05F26_1.jpg
├── A03_A137U8_1.jpg
├── A03_A137U8_2.jpg
├── A03_A137U8_3.jpg
├── A03_A19Z80_0.jpg
├── A03_A19Z80_1.jpg
├── A03_A19Z80_2.jpg
├── A03_A19Z80_3.jpg
├── A03_A19Z80_4.jpg
├── A03_A19Z80_5.jpg
├── A03_A19Z80_7.jpg
├── A03_A19Z80_8.jpg
├── A03_A1L828_0.jpg
├── A03_A1L828_1.jpg
├── A03_A1L828_2.jpg
├── A03_A1L828_4.jpg
├── A03_A1Z726_1.jpg
├── A03_A203J1_1.jpg
├── A03_A203J1_2.jpg
├── A03_A2H337_0.jpg
├── A03_A2H337_2.jpg
├── A03_A2M801_1.jpg
├── A03_A2M801_2.jpg
├── A03_A4F288_1.jpg
├── A03_A5X098_1.jpg
├── A03_A60L48_0.jpg
├── A03_A60L48_1.jpg
├── A03_A60L48_2.jpg
├── A03_A60L48_3.jpg
├── A03_A60L48_4.jpg
├── A03_A63X72_1.jpg
├── A03_A6U922_1.jpg
├── A03_A6U922_2.jpg
├── A03_A722S6_0.jpg
├── A03_A79A95_1.jpg
├── A03_A7N292_1.jpg
├── A03_A82E65_1.jpg
├── A03_A82E65_2.jpg
├── A03_A85V02_1.jpg
├── A03_A8B389_1.jpg
├── A03_A8B389_2.jpg
├── A03_A8B389_3.jpg
├── A03_A8B389_4.jpg
├── A03_A8E322_1.jpg
├── A03_A9F208_1.jpg
├── A03_A9F208_2.jpg
├── A03_AAC595_0.jpg
├── A03_AAC595_2.jpg
├── A03_AAC595_3.jpg
├── A03_AAC595_4.jpg
├── A03_AAC595_5.jpg
├── A03_AAQ839_0.jpg
├── A03_AAQ839_1.jpg
├── A03_AAQ839_2.jpg
├── A03_AAQ839_4.jpg
├── A03_AAQ839_5.jpg
├── A03_ABF318_1.jpg
└── A03_ABF318_2.jpg
├── doc
└── 中华人民共和国机动车号牌.pdf
├── font
├── platech.ttf
└── platechar.ttf
├── generate_chars_image.py
├── generate_license_plate.py
├── generate_license_plate_number.py
├── generate_plate_template.py
├── images
├── 11.bmp
├── 12.bmp
├── army1.bmp
├── army2.bmp
├── big_new_energy.jpg
├── double_white1.bmp
├── double_white2.bmp
├── double_yellow1.bmp
├── double_yellow2.bmp
├── police1.bmp
├── police2.bmp
├── single_black1.bmp
├── single_black2.bmp
├── single_blue1.bmp
├── single_blue2.bmp
├── single_yellow1.bmp
├── single_yellow2.bmp
├── small_new_energy.jpg
├── smu.jpg
├── smu2.jpg
├── 大型新能源车牌号-示例.jpg
└── 小型新能源车牌号-示例.jpg
├── license_plate_elements.py
├── plate-recognition-models
└── multi-label-classification
│ └── caffe
│ ├── README.md
│ ├── file_tools.py
│ ├── generate_lmdb.sh
│ ├── generate_txt.py
│ ├── recognization_engine.py
│ ├── resnet18
│ ├── recognition-resnet18-deploy.prototxt
│ ├── recognition-resnet18-solver.prototxt
│ ├── recognition-resnet18-train-test.prototxt
│ └── recognition-resnet18-train.sh
│ └── resnet50
│ ├── recognition-resnet50-deploy.prototxt
│ ├── recognition-resnet50-solver.prototxt
│ ├── recognition-resnet50-train-test.prototxt
│ └── recognition-resnet50-train.sh
└── plate_images
├── single_blue
├── 00_甘A0W9U9.jpg
├── 00_皖JP7Z46.jpg
├── 01_渝R6P85G.jpg
├── 01_青AY1G55.jpg
├── 02_浙X4DZ51.jpg
├── 02_蒙XX83H0.jpg
├── 03_皖C2HW16.jpg
├── 03_蒙NLP471.jpg
├── 04_皖D785JQ.jpg
├── 04_藏H54HU0.jpg
├── 05_京X48LL5.jpg
├── 05_桂UP03K2.jpg
├── 06_渝W63CD0.jpg
├── 06_鄂U60RJ1.jpg
├── 07_蒙U17CL7.jpg
├── 07_赣S8Q147.jpg
├── 08_琼XFN464.jpg
├── 08_闽B99EB1.jpg
├── 09_甘YJ5A31.jpg
└── 09_苏JA147V.jpg
├── single_yellow
├── 00_粤YT06R0.jpg
├── 00_赣UV0B03.jpg
├── 01_宁Y6T4E9.jpg
├── 01_豫WKB412.jpg
├── 02_粤F7F635.jpg
├── 02_豫B9J2Z0.jpg
├── 03_藏F11LD1.jpg
├── 03_贵PKT044.jpg
├── 04_京F2T25S.jpg
├── 04_晋NX84E5.jpg
├── 05_吉V14Q9Q.jpg
├── 05_辽A48GP6.jpg
├── 06_宁M2L6V8.jpg
├── 06_晋E146LP.jpg
├── 07_川M41A9V.jpg
├── 07_琼S4P85Y.jpg
├── 08_粤B87S2V.jpg
├── 08_陕F54ZW9.jpg
├── 09_冀FPZ908.jpg
└── 09_吉P5DU24.jpg
└── small_new_energy
├── 00_云HD40984.jpg
├── 00_鲁CF23225.jpg
├── 01_豫QD96106.jpg
├── 01_青BFA1001.jpg
├── 02_苏KD38100.jpg
├── 02_闽ED96706.jpg
├── 03_青AFV2900.jpg
├── 03_黑QDE9515.jpg
├── 04_晋KFA4659.jpg
├── 04_琼BFA4418.jpg
├── 05_桂FFQ8217.jpg
├── 05_甘XDG6119.jpg
├── 06_云YDR7996.jpg
├── 06_辽QF15431.jpg
├── 07_桂CDQ1150.jpg
├── 07_黑VD15418.jpg
├── 08_宁YF71827.jpg
├── 08_新NDZ8091.jpg
├── 09_吉XDF3229.jpg
└── 09_津MDW4893.jpg
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
105 |
--------------------------------------------------------------------------------
/.idea/deployment.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/dictionaries/z00428518.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | caffe
5 | caffemodel
6 | prototxt
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/license-plate-generator.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/markdown-navigator.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.idea/markdown-navigator/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
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 | generate_license_plate_image
85 | vertical_tilt_transfer
86 | angle_horizontal
87 | sedd
88 | random
89 | angle_font_back
90 | seed
91 |
92 |
93 |
94 |
95 |
96 |
97 |
114 |
115 |
116 |
117 |
118 | true
119 | DEFINITION_ORDER
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 | 1555554999355
218 |
219 |
220 | 1555554999355
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 | cv2.imwrite('f.jpg', cv2.bitwise_or(cv2.bitwise_and(bak, env), img))
272 | Python
273 | CODE_FRAGMENT
274 |
275 |
276 | cv2.imwrite('e.jpg', cv2.bitwise_and(bak, env))
277 | Python
278 | CODE_FRAGMENT
279 |
280 |
281 | bak = bak.astype(np.uint8) * 255
282 | Python
283 | CODE_FRAGMENT
284 |
285 |
286 | cv2.imwrite('d.jpg', bak.astype(np.uint8) * 255)
287 | Python
288 | CODE_FRAGMENT
289 |
290 |
291 | bak[:, :, 2] = bak[:, :, 0]
292 | Python
293 | CODE_FRAGMENT
294 |
295 |
296 | bak[:, :, 1] = bak[:, :, 0]
297 | Python
298 | CODE_FRAGMENT
299 |
300 |
301 | bak[:, :, 0] &= bak[:, :, 2]
302 | Python
303 | CODE_FRAGMENT
304 |
305 |
306 | bak[:, :, 0] &= bak[:, :, 1]
307 | Python
308 | CODE_FRAGMENT
309 |
310 |
311 | bak[:, :, 0] &= bak[:, :, 0]
312 | Python
313 | CODE_FRAGMENT
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 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 郑煜伟
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 中国车牌生成
2 | @author **郑煜伟** in 2019-04-18
3 | 目前支持蓝色标准车牌,黄色标准车牌,小型新能源车牌的车牌生成。
4 | 实际的车牌示例:
5 | 
6 | 
7 | 生成的车牌示例:
8 | 
9 | 
10 |
11 | ### 文件夹目录说明
12 | 1. background: 车牌生成时,随机选取其中一张作为背景照片放置在车牌后面,类似于车头部分;
13 | 2. doc:放置了车牌号的国家规定文档;
14 | 3. font:车牌号的英文/中文字体;
15 | 4. images:各种车牌底牌(蓝色底牌等),污渍图片(图像增强使用);
16 | 5. plate_images:生成的车牌图片的存放路径。
17 | 6. plate-recognition-models:车牌识别模型
18 | - multi-label-classification:多标签分类模型,下面包含caffe和tensorflow版本;
19 |
20 | ### 程序结构说明
21 | - license_plate_elements.py: 车牌号元素,其中定义:
22 | 1. 车牌号中,不同车牌位的取值范围;
23 | 2. 不同的车牌类型。
24 | - generate_license_plate_number.py: 根据车牌类型,生成指定数量的车牌号
25 | 1. 定义不同车牌类型中,对应车牌位的取值规则;(当前只定义了标准车牌和小型新能源车牌的车牌号取值规则)
26 | 2. 从license_plate_elements.py中,读取不同车牌位的初始初值范围。
27 |
28 | - generate_chars_image.py: 指定车牌类型,根据给定的车牌号列表,生成车牌号文字图片
29 | 1. 根据实际车牌号字体大小,生成相应的中英文字符;
30 | 2. 依照车牌号不同位字符的分布规则,将生成的字符放置在对应的位置上,得到最终的车牌号文字图片。
31 | - generate_plate_template.py: 指定车牌类型,生成车牌底牌图片
32 | 1. 根据车牌类型,加载底牌图片;
33 | 2. 根据指定尺寸resize。
34 |
35 | - augment_image.py: 根据车牌类型,组合车牌底牌、车牌号图片,并进行数据增强
36 | 1. 根据车牌类型,判断车牌号图片为白字黑底 或 黑字白底;
37 | 2. 对车牌号图片、底牌,进行同样的透视视角变换,对底牌加背景;
38 | 3. 组合车牌底牌、车牌号图片
39 | 2. 对车牌图片进行剩余数据增强,包含HSV变化、高斯噪声、添加污渍。
40 |
41 | - generate_license_plate.py: 主函数,按照流程调用以上Python脚本,生成图像增强后的车牌图片
42 | 1. 生成指定类型、指定数量的车牌号;
43 | 2. 生成车牌图片;
44 | 3. 进行数据增强;
45 | 4. 保存图片。
46 |
47 | ### 生成lmdb格式数据集及模型训练
48 | 参考plate-recognition-models文件夹下README.md。
49 |
50 | ### TODO:
51 | 1. 将其他车牌类型的规则定义好,以生成其他类型的车牌;
52 | 2. 车牌底牌图片分辨率不统一,且不太标准,待改善;
53 | 3. 利用GAN进行风格迁移,使生成的车牌更加真实。
54 |
55 |
56 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on 2019/3/27
4 | File __init__.py
5 | @author:ZhengYuwei
6 | """
7 | from .generate_license_plate import LicensePlateGenerator
8 |
9 | __all__ = [
10 | '.generate_license_plate.LicensePlateGenerator',
11 | ]
12 |
13 | __version__ = '0.1.0'
14 |
15 | __description__ = '生成车牌图片数据'
16 |
--------------------------------------------------------------------------------
/augment_image.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on 2019/4/17
4 | File augment_image
5 | @author:ZhengYuwei
6 | @ref: https://github.com/huxiaoman7/mxnet-cnn-plate-recognition, @author Huxiaoman
7 | 功能:
8 | 进行图像增强:透视变换、HSV变化、添加背景、高斯噪声、添加污渍
9 | """
10 | import cv2
11 | import numpy as np
12 | import math
13 | import os
14 | import random
15 |
16 |
17 | class ImageAugmentation(object):
18 | """ 一些图像增强操作操作: 透视变换、HSV变化、添加背景、高斯噪声、污渍 """
19 |
20 | horizontal_sight_directions = ('left', 'mid', 'right')
21 | vertical_sight_directions = ('up', 'mid', 'down')
22 |
23 | def __init__(self, plate_type, template_image):
24 | """ 一些图像增强参数的默认初值初始化
25 | :param plate_type: 车牌类型,用于字符颜色修正
26 | :param template_image: 车牌底牌图片
27 | """
28 | self.plate_type = plate_type
29 | # 确定字符颜色是否应该为黑色
30 | if plate_type == 'single_blue':
31 | # 字符为白色
32 | self.is_black_char = False
33 | elif plate_type in ['single_yellow', 'small_new_energy']:
34 | # 字符为黑字
35 | self.is_black_char = True
36 | else:
37 | raise ValueError('暂时不支持该类型车牌')
38 | self.template_image = template_image
39 | # 透视变换
40 | self.angle_horizontal = 15
41 | self.angle_vertical = 15
42 | self.angle_up_down = 10
43 | self.angle_left_right = 5
44 | self.factor = 10
45 | # 色调,饱和度,亮度
46 | self.hue_keep = 0.8
47 | self.saturation_keep = 0.3
48 | self.value_keep = 0.2
49 | # 自然环境照片的路径列表
50 | self.env_data_paths = ImageAugmentation.search_file("background")
51 | # 高斯噪声level
52 | self.level = 1 + ImageAugmentation.rand_reduce(4)
53 | # 污渍
54 | self.smu = cv2.imread("images/smu.jpg")
55 |
56 | def sight_transfer(self, images, horizontal_sight_direction, vertical_sight_direction):
57 | """ 对图片进行视角变换
58 | :param images: 图片列表
59 | :param horizontal_sight_direction: 水平视角变换方向
60 | :param vertical_sight_direction: 垂直视角变换方向
61 | :return:
62 | """
63 | flag = 0
64 | img_num = len(images)
65 | # 左右视角
66 | if horizontal_sight_direction == 'left':
67 | flag += 1
68 | images[0], matrix, size = self.left_right_transfer(images[0], is_left=True)
69 | for i in range(1, img_num):
70 | images[i] = cv2.warpPerspective(images[i], matrix, size)
71 | elif horizontal_sight_direction == 'right':
72 | flag -= 1
73 | images[0], matrix, size = self.left_right_transfer(images[0], is_left=False)
74 | for i in range(1, img_num):
75 | images[i] = cv2.warpPerspective(images[i], matrix, size)
76 | else:
77 | pass
78 | # 上下视角
79 | if vertical_sight_direction == 'down':
80 | flag += 1
81 | images[0], matrix, size = self.up_down_transfer(images[0], is_down=True)
82 | for i in range(1, img_num):
83 | images[i] = cv2.warpPerspective(images[i], matrix, size)
84 | elif vertical_sight_direction == 'up':
85 | flag -= 1
86 | images[0], matrix, size = self.up_down_transfer(images[0], is_down=False)
87 | for i in range(1, img_num):
88 | images[i] = cv2.warpPerspective(images[i], matrix, size)
89 | else:
90 | pass
91 |
92 | # 左下视角 或 右上视角
93 | if abs(flag) == 2:
94 | images[0], matrix, size = self.vertical_tilt_transfer(images[0], is_left_high=True)
95 | for i in range(1, img_num):
96 | images[i] = cv2.warpPerspective(images[i], matrix, size)
97 |
98 | images[0], matrix, size = self.horizontal_tilt_transfer(images[0], is_right_tilt=True)
99 | for i in range(1, img_num):
100 | images[i] = cv2.warpPerspective(images[i], matrix, size)
101 | # 左上视角 或 右下视角
102 | elif abs(flag) == 1:
103 | images[0], matrix, size = self.vertical_tilt_transfer(images[0], is_left_high=False)
104 | for i in range(1, img_num):
105 | images[i] = cv2.warpPerspective(images[i], matrix, size)
106 |
107 | images[0], matrix, size = self.horizontal_tilt_transfer(images[0], is_right_tilt=False)
108 | for i in range(1, img_num):
109 | images[i] = cv2.warpPerspective(images[i], matrix, size)
110 | else:
111 | pass
112 |
113 | return images
114 |
115 | def up_down_transfer(self, img, is_down=True, angle=None):
116 | """ 上下视角,默认下视角
117 | :param img: 正面视角原始图片
118 | :param is_down: 是否下视角
119 | :param angle: 角度
120 | :return:
121 | """
122 | if angle is None:
123 | angle = self.rand_reduce(self.angle_up_down)
124 |
125 | shape = img.shape
126 | size_src = (shape[1], shape[0])
127 | # 源图像四个顶点坐标
128 | pts1 = np.float32([[0, 0], [0, size_src[1]], [size_src[0], 0], [size_src[0], size_src[1]]])
129 | # 计算图片进行投影倾斜后的位置
130 | interval = abs(int(math.sin((float(angle) / 180) * math.pi) * shape[0]))
131 | # 目标图像上四个顶点的坐标
132 | if is_down:
133 | pts2 = np.float32([[interval, 0], [0, size_src[1]],
134 | [size_src[0] - interval, 0], [size_src[0], size_src[1]]])
135 | else:
136 | pts2 = np.float32([[0, 0], [interval, size_src[1]],
137 | [size_src[0], 0], [size_src[0] - interval, size_src[1]]])
138 | # 获取 3x3的投影映射/透视变换 矩阵
139 | matrix = cv2.getPerspectiveTransform(pts1, pts2)
140 | dst = cv2.warpPerspective(img, matrix, size_src)
141 | return dst, matrix, size_src
142 |
143 | def left_right_transfer(self, img, is_left=True, angle=None):
144 | """ 左右视角,默认左视角
145 | :param img: 正面视角原始图片
146 | :param is_left: 是否左视角
147 | :param angle: 角度
148 | :return:
149 | """
150 | if angle is None:
151 | angle = self.angle_left_right # self.rand_reduce(self.angle_left_right)
152 |
153 | shape = img.shape
154 | size_src = (shape[1], shape[0])
155 | # 源图像四个顶点坐标
156 | pts1 = np.float32([[0, 0], [0, size_src[1]], [size_src[0], 0], [size_src[0], size_src[1]]])
157 | # 计算图片进行投影倾斜后的位置
158 | interval = abs(int(math.sin((float(angle) / 180) * math.pi) * shape[0]))
159 | # 目标图像上四个顶点的坐标
160 | if is_left:
161 | pts2 = np.float32([[0, 0], [0, size_src[1]],
162 | [size_src[0], interval], [size_src[0], size_src[1] - interval]])
163 | else:
164 | pts2 = np.float32([[0, interval], [0, size_src[1] - interval],
165 | [size_src[0], 0], [size_src[0], size_src[1]]])
166 | # 获取 3x3的投影映射/透视变换 矩阵
167 | matrix = cv2.getPerspectiveTransform(pts1, pts2)
168 | dst = cv2.warpPerspective(img, matrix, size_src)
169 | return dst, matrix, size_src
170 |
171 | def vertical_tilt_transfer(self, img, is_left_high=True):
172 | """ 添加按照指定角度进行垂直倾斜(上倾斜或下倾斜,最大倾斜角度self.angle_vertical一半)
173 | :param img: 输入图像的numpy
174 | :param is_left_high: 图片投影的倾斜角度,左边是否相对右边高
175 | """
176 | angle = self.rand_reduce(self.angle_vertical)
177 |
178 | shape = img.shape
179 | size_src = [shape[1], shape[0]]
180 | # 源图像四个顶点坐标
181 | pts1 = np.float32([[0, 0], [0, size_src[1]], [size_src[0], 0], [size_src[0], size_src[1]]])
182 |
183 | # 计算图片进行上下倾斜后的距离,及形状
184 | interval = abs(int(math.sin((float(angle) / 180) * math.pi) * shape[1]))
185 | size_target = (int(math.cos((float(angle) / 180) * math.pi) * shape[1]), shape[0] + interval)
186 | # 目标图像上四个顶点的坐标
187 | if is_left_high:
188 | pts2 = np.float32([[0, 0], [0, size_target[1] - interval],
189 | [size_target[0], interval], [size_target[0], size_target[1]]])
190 | else:
191 | pts2 = np.float32([[0, interval], [0, size_target[1]],
192 | [size_target[0], 0], [size_target[0], size_target[1] - interval]])
193 |
194 | # 获取 3x3的投影映射/透视变换 矩阵
195 | matrix = cv2.getPerspectiveTransform(pts1, pts2)
196 | dst = cv2.warpPerspective(img, matrix, size_target)
197 | return dst, matrix, size_target
198 |
199 | def horizontal_tilt_transfer(self, img, is_right_tilt=True):
200 | """ 添加按照指定角度进行水平倾斜(右倾斜或左倾斜,最大倾斜角度self.angle_horizontal一半)
201 | :param img: 输入图像的numpy
202 | :param is_right_tilt: 图片投影的倾斜方向(右倾,左倾)
203 | """
204 | angle = self.rand_reduce(self.angle_horizontal)
205 |
206 | shape = img.shape
207 | size_src = [shape[1], shape[0]]
208 | # 源图像四个顶点坐标
209 | pts1 = np.float32([[0, 0], [0, size_src[1]], [size_src[0], 0], [size_src[0], size_src[1]]])
210 |
211 | # 计算图片进行左右倾斜后的距离,及形状
212 | interval = abs(int(math.sin((float(angle) / 180) * math.pi) * shape[0]))
213 | size_target = (shape[1] + interval, int(math.cos((float(angle) / 180) * math.pi) * shape[0]))
214 | # 目标图像上四个顶点的坐标
215 | if is_right_tilt:
216 | pts2 = np.float32([[interval, 0], [0, size_target[1]],
217 | [size_target[0], 0], [size_target[0] - interval, size_target[1]]])
218 | else:
219 | pts2 = np.float32([[0, 0], [interval, size_target[1]],
220 | [size_target[0] - interval, 0], [size_target[0], size_target[1]]])
221 |
222 | # 获取 3x3的投影映射/透视变换 矩阵
223 | matrix = cv2.getPerspectiveTransform(pts1, pts2)
224 | dst = cv2.warpPerspective(img, matrix, size_target)
225 | return dst, matrix, size_target
226 |
227 | @staticmethod
228 | def rand_reduce(val):
229 | return int(np.random.random() * val)
230 |
231 | def rand_perspective_transfer(self, img, factor=None, size=None):
232 | """ 添加投影映射畸变
233 | :param img: 输入图像的numpy
234 | :param factor: 畸变的参数
235 | :param size: 图片的目标尺寸,默认维持不变
236 | """
237 | if factor is None:
238 | factor = self.factor
239 | if size is None:
240 | size = (img.shape[1], img.shape[0])
241 | shape = size
242 | # 源图像四个顶点坐标
243 | pts1 = np.float32([[0, 0], [0, shape[0]], [shape[1], 0], [shape[1], shape[0]]])
244 | # 目标图像上四个顶点的坐标
245 | pts2 = np.float32([[self.rand_reduce(factor), self.rand_reduce(factor)],
246 | [self.rand_reduce(factor), shape[0] - self.rand_reduce(factor)],
247 | [shape[1] - self.rand_reduce(factor), self.rand_reduce(factor)],
248 | [shape[1] - self.rand_reduce(factor), shape[0] - self.rand_reduce(factor)]])
249 | # 获取 3x3的投影映射/透视变换 矩阵
250 | matrix = cv2.getPerspectiveTransform(pts1, pts2)
251 | # 利用投影映射矩阵,进行透视变换
252 | dst = cv2.warpPerspective(img, matrix, size)
253 | return dst, matrix, size
254 |
255 | def rand_hsv(self, img):
256 | """ 添加饱和度光照的噪声
257 | :param img: BGR格式的图片
258 | :return 加了饱和度、光照噪声的BGR图片
259 | """
260 | hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
261 | # 色调,饱和度,亮度
262 | hsv[:, :, 0] = hsv[:, :, 0] * (self.hue_keep + np.random.random() * (1 - self.hue_keep))
263 | hsv[:, :, 1] = hsv[:, :, 1] * (self.saturation_keep + np.random.random() * (1 - self.saturation_keep))
264 | hsv[:, :, 2] = hsv[:, :, 2] * (self.value_keep + np.random.random() * (1 - self.value_keep))
265 | img = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
266 | return img
267 |
268 | def rand_environment(self, img, env_data_paths=None):
269 | """ 添加自然环境的噪声
270 | :param img: 待加噪图片
271 | :param env_data_paths: 自然环境图片路径列表
272 | """
273 | if env_data_paths is None:
274 | env_data_paths = self.env_data_paths
275 | # 随机选取环境照片
276 | index = self.rand_reduce(len(env_data_paths))
277 | env = cv2.imread(env_data_paths[index])
278 | env = cv2.resize(env, (img.shape[1], img.shape[0]))
279 | # 找到黑背景,反转为白
280 | bak = (img == 0)
281 | for i in range(bak.shape[2]):
282 | bak[:, :, 0] &= bak[:, :, i]
283 | for i in range(bak.shape[2]):
284 | bak[:, :, i] = bak[:, :, 0]
285 | bak = bak.astype(np.uint8) * 255
286 | # 环境照片用白掩码裁剪,然后与原图非黑部分合并
287 | inv = cv2.bitwise_and(bak, env)
288 | img = cv2.bitwise_or(inv, img)
289 | return img
290 |
291 | def add_gauss(self, img, level=None):
292 | """ 添加高斯模糊
293 | :param img: 待加噪图片
294 | :param level: 加噪水平
295 | """
296 | if level is None:
297 | level = self.level
298 | return cv2.blur(img, (level * 2 + 1, level * 2 + 1))
299 |
300 | def add_single_channel_noise(self, single):
301 | """ 添加高斯噪声
302 | :param single: 单一通道的图像数据
303 | """
304 | diff = 255 - single.max()
305 | noise = np.random.normal(0, 1 + self.rand_reduce(6), single.shape)
306 | noise = (noise - noise.min()) / (noise.max() - noise.min())
307 | noise = diff * noise
308 | noise = noise.astype(np.uint8)
309 | dst = single + noise
310 | return dst
311 |
312 | def add_noise(self, img):
313 | """添加噪声"""
314 | img[:, :, 0] = self.add_single_channel_noise(img[:, :, 0])
315 | img[:, :, 1] = self.add_single_channel_noise(img[:, :, 1])
316 | img[:, :, 2] = self.add_single_channel_noise(img[:, :, 2])
317 | return img
318 |
319 | def add_smudge(self, img, smu=None):
320 | """添加污渍"""
321 | if smu is None:
322 | smu = self.smu
323 | # 截取某一部分
324 | rows = self.rand_reduce(smu.shape[0] - img.shape[0])
325 | cols = self.rand_reduce(smu.shape[1] - img.shape[1])
326 | add_smu = smu[rows:rows + img.shape[0], cols:cols + img.shape[1]]
327 | img = cv2.bitwise_not(img)
328 | img = cv2.bitwise_and(add_smu, img)
329 | img = cv2.bitwise_not(img)
330 | return img
331 |
332 | @staticmethod
333 | def search_file(search_path, file_format='.jpg'):
334 | """在指定目录search_path下,递归目录搜索指定尾缀的文件
335 | :param search_path: 指定的搜索目录,如:./2018年收集的素材并已校正
336 | :param file_format: 文件尾缀,如‘.jpg’
337 | :return: 该目录下所有指定尾缀文件的路径组成的list
338 | """
339 | file_path_list = []
340 | # 获取:1.父目录绝对路径 2.所有文件夹名字(不含路径) 3.所有文件名字
341 | for root_path, dir_names, file_names in os.walk(search_path):
342 | # 收集符合条件的文件名
343 | for filename in file_names:
344 | if filename.endswith(file_format):
345 | file_path_list.append(os.path.join(root_path, filename))
346 | return file_path_list
347 |
348 | def augment(self, img, horizontal_sight_direction=None, vertical_sight_direction=None):
349 | """ 综合上面的加载操作,进行全流程加噪
350 | :param img: 待加噪图片,传进来的图片是白底黑字
351 | :param horizontal_sight_direction: 水平视角方向
352 | :param vertical_sight_direction: 垂直视角方向
353 | :return: 加噪后的图片,numpy数组
354 | """
355 | if horizontal_sight_direction is None:
356 | horizontal_sight_direction = ImageAugmentation.horizontal_sight_directions[random.randint(0, 2)]
357 | if vertical_sight_direction is None:
358 | vertical_sight_direction = ImageAugmentation.vertical_sight_directions[random.randint(0, 2)]
359 |
360 | # 转为黑底白字
361 | img = cv2.bitwise_not(img)
362 | if not self.is_black_char:
363 | img = cv2.bitwise_or(img, self.template_image)
364 | # 基于视角的变换
365 | img = self.sight_transfer([img], horizontal_sight_direction, vertical_sight_direction)
366 | img = img[0]
367 | # 加上随机透视变换,这个其实可以不用
368 | img, _, _ = self.rand_perspective_transfer(img)
369 | img = self.rand_environment(img)
370 | img = self.rand_hsv(img)
371 | else:
372 | # 对文字和底牌进行一样的透视操作
373 | img, template_image = self.sight_transfer([img, self.template_image],
374 | horizontal_sight_direction, vertical_sight_direction)
375 | img, matrix, size = self.rand_perspective_transfer(img)
376 | template_image = cv2.warpPerspective(template_image, matrix, size)
377 | # 底牌加背景
378 | template_image = self.rand_environment(template_image)
379 | # 转为白底黑字
380 | img = cv2.bitwise_not(img)
381 | # 底牌加车牌文字
382 | img = cv2.bitwise_and(img, template_image)
383 | img = self.rand_hsv(img)
384 |
385 | img = self.add_gauss(img)
386 | img = self.add_noise(img)
387 | img = self.add_smudge(img)
388 | return img
389 |
--------------------------------------------------------------------------------
/background/A01_N84E28_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A01_N84E28_1.jpg
--------------------------------------------------------------------------------
/background/A01_N84E28_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A01_N84E28_2.jpg
--------------------------------------------------------------------------------
/background/A01_NMV802_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A01_NMV802_1.jpg
--------------------------------------------------------------------------------
/background/A01_NMV802_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A01_NMV802_2.jpg
--------------------------------------------------------------------------------
/background/A02_NBD719_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A02_NBD719_1.jpg
--------------------------------------------------------------------------------
/background/A02_NBD719_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A02_NBD719_2.jpg
--------------------------------------------------------------------------------
/background/A03_A05F26_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A05F26_1.jpg
--------------------------------------------------------------------------------
/background/A03_A137U8_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A137U8_1.jpg
--------------------------------------------------------------------------------
/background/A03_A137U8_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A137U8_2.jpg
--------------------------------------------------------------------------------
/background/A03_A137U8_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A137U8_3.jpg
--------------------------------------------------------------------------------
/background/A03_A19Z80_0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A19Z80_0.jpg
--------------------------------------------------------------------------------
/background/A03_A19Z80_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A19Z80_1.jpg
--------------------------------------------------------------------------------
/background/A03_A19Z80_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A19Z80_2.jpg
--------------------------------------------------------------------------------
/background/A03_A19Z80_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A19Z80_3.jpg
--------------------------------------------------------------------------------
/background/A03_A19Z80_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A19Z80_4.jpg
--------------------------------------------------------------------------------
/background/A03_A19Z80_5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A19Z80_5.jpg
--------------------------------------------------------------------------------
/background/A03_A19Z80_7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A19Z80_7.jpg
--------------------------------------------------------------------------------
/background/A03_A19Z80_8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A19Z80_8.jpg
--------------------------------------------------------------------------------
/background/A03_A1L828_0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A1L828_0.jpg
--------------------------------------------------------------------------------
/background/A03_A1L828_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A1L828_1.jpg
--------------------------------------------------------------------------------
/background/A03_A1L828_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A1L828_2.jpg
--------------------------------------------------------------------------------
/background/A03_A1L828_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A1L828_4.jpg
--------------------------------------------------------------------------------
/background/A03_A1Z726_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A1Z726_1.jpg
--------------------------------------------------------------------------------
/background/A03_A203J1_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A203J1_1.jpg
--------------------------------------------------------------------------------
/background/A03_A203J1_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A203J1_2.jpg
--------------------------------------------------------------------------------
/background/A03_A2H337_0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A2H337_0.jpg
--------------------------------------------------------------------------------
/background/A03_A2H337_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A2H337_2.jpg
--------------------------------------------------------------------------------
/background/A03_A2M801_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A2M801_1.jpg
--------------------------------------------------------------------------------
/background/A03_A2M801_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A2M801_2.jpg
--------------------------------------------------------------------------------
/background/A03_A4F288_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A4F288_1.jpg
--------------------------------------------------------------------------------
/background/A03_A5X098_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A5X098_1.jpg
--------------------------------------------------------------------------------
/background/A03_A60L48_0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A60L48_0.jpg
--------------------------------------------------------------------------------
/background/A03_A60L48_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A60L48_1.jpg
--------------------------------------------------------------------------------
/background/A03_A60L48_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A60L48_2.jpg
--------------------------------------------------------------------------------
/background/A03_A60L48_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A60L48_3.jpg
--------------------------------------------------------------------------------
/background/A03_A60L48_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A60L48_4.jpg
--------------------------------------------------------------------------------
/background/A03_A63X72_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A63X72_1.jpg
--------------------------------------------------------------------------------
/background/A03_A6U922_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A6U922_1.jpg
--------------------------------------------------------------------------------
/background/A03_A6U922_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A6U922_2.jpg
--------------------------------------------------------------------------------
/background/A03_A722S6_0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A722S6_0.jpg
--------------------------------------------------------------------------------
/background/A03_A79A95_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A79A95_1.jpg
--------------------------------------------------------------------------------
/background/A03_A7N292_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A7N292_1.jpg
--------------------------------------------------------------------------------
/background/A03_A82E65_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A82E65_1.jpg
--------------------------------------------------------------------------------
/background/A03_A82E65_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A82E65_2.jpg
--------------------------------------------------------------------------------
/background/A03_A85V02_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A85V02_1.jpg
--------------------------------------------------------------------------------
/background/A03_A8B389_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A8B389_1.jpg
--------------------------------------------------------------------------------
/background/A03_A8B389_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A8B389_2.jpg
--------------------------------------------------------------------------------
/background/A03_A8B389_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A8B389_3.jpg
--------------------------------------------------------------------------------
/background/A03_A8B389_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A8B389_4.jpg
--------------------------------------------------------------------------------
/background/A03_A8E322_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A8E322_1.jpg
--------------------------------------------------------------------------------
/background/A03_A9F208_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A9F208_1.jpg
--------------------------------------------------------------------------------
/background/A03_A9F208_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_A9F208_2.jpg
--------------------------------------------------------------------------------
/background/A03_AAC595_0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_AAC595_0.jpg
--------------------------------------------------------------------------------
/background/A03_AAC595_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_AAC595_2.jpg
--------------------------------------------------------------------------------
/background/A03_AAC595_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_AAC595_3.jpg
--------------------------------------------------------------------------------
/background/A03_AAC595_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_AAC595_4.jpg
--------------------------------------------------------------------------------
/background/A03_AAC595_5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_AAC595_5.jpg
--------------------------------------------------------------------------------
/background/A03_AAQ839_0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_AAQ839_0.jpg
--------------------------------------------------------------------------------
/background/A03_AAQ839_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_AAQ839_1.jpg
--------------------------------------------------------------------------------
/background/A03_AAQ839_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_AAQ839_2.jpg
--------------------------------------------------------------------------------
/background/A03_AAQ839_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_AAQ839_4.jpg
--------------------------------------------------------------------------------
/background/A03_AAQ839_5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_AAQ839_5.jpg
--------------------------------------------------------------------------------
/background/A03_ABF318_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_ABF318_1.jpg
--------------------------------------------------------------------------------
/background/A03_ABF318_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/background/A03_ABF318_2.jpg
--------------------------------------------------------------------------------
/doc/中华人民共和国机动车号牌.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/doc/中华人民共和国机动车号牌.pdf
--------------------------------------------------------------------------------
/font/platech.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/font/platech.ttf
--------------------------------------------------------------------------------
/font/platechar.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/font/platechar.ttf
--------------------------------------------------------------------------------
/generate_chars_image.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on 2019/4/17
4 | File generate_chars_image
5 | @author:ZhengYuwei
6 | 功能:生成车牌号字符图像:背景为白色,字体为黑色
7 | """
8 | from PIL import Image
9 | from PIL import ImageDraw
10 | from PIL import ImageFont
11 | import numpy as np
12 | import cv2
13 |
14 |
15 | class CharsImageGenerator(object):
16 | """ 生成字符图像:背景为白色,字体为黑色 """
17 | # 数字和英文字母列表
18 | numerals = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
19 | alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
20 | 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
21 | 'U', 'V', 'W', 'X', 'Y', 'Z']
22 |
23 | def __init__(self, plate_type):
24 | """ 一些参数的初始化
25 | :param plate_type: 需要生成的车牌类型
26 | """
27 | self.plate_type = plate_type
28 | # 字符图片参数
29 | self.font_ch = ImageFont.truetype("./font/platech.ttf", 180, 0) # 中文字体格式
30 | self.font_en = ImageFont.truetype('./font/platechar.ttf', 240, 0) # 英文字体格式
31 | self.bg_color = (255, 255, 255) # 车牌背景颜色
32 | self.fg_color = (0, 0, 0) # 车牌号的字体颜色
33 |
34 | self.plate_height = 280 # 车牌高度
35 | self.left_offset = 32 # 车牌号左边第一个字符的偏移量
36 | self.height_offset = 10 # 高度方向的偏移量
37 | self.char_height = 180 # 字符高度
38 | self.chinese_original_width = 180 # 中文字符原始宽度
39 | self.english_original_width = 90 # 非中文字符原始宽度
40 | if plate_type in ['single_blue', 'single_yellow']:
41 | self.char_num = 7
42 | self.char_width = 90 # 字符校正后的宽度
43 | self.plate_width = 880 # 车牌的宽度
44 | self.char_interval = 24 # 字符间的间隔
45 | self.point_size = 20 # 第2个字符与第三个字符间有一个点,该点的尺寸
46 | elif plate_type == 'small_new_energy':
47 | self.char_num = 8
48 | self.first_char_width = 90 # 第一个字符校正后的宽度
49 | self.char_width = 86 # 其余字符校正后宽度
50 | self.plate_width = 960 # 车牌的宽度
51 | self.char_interval = 18 # 字符间的间隔
52 | self.point_size = 62 # 第2个字符与第三个字符间有一个点,该点的尺寸
53 | else:
54 | raise ValueError('目前不支持该类型车牌!')
55 |
56 | def generate_images(self, plate_nums):
57 | """ 根据车牌号列表,生成车牌号图片:背景为白色,字体为黑色
58 | :param plate_nums: 车牌号
59 | :return:
60 | """
61 | if self.plate_type in ['single_blue', 'single_yellow', ]:
62 | plate_images = self.generate_440_140_plate(plate_nums)
63 | elif self.plate_type == 'small_new_energy':
64 | plate_images = self.generate_480_140_plate(plate_nums)
65 | else:
66 | raise ValueError('该类型车牌目前功能尚未完成!')
67 |
68 | return plate_images
69 |
70 | def generate_440_140_plate(self, plate_nums):
71 | """ 生成440 * 140尺寸的7位车牌字符图片
72 | :param plate_nums:
73 | :return:
74 | """
75 | plate_images = list()
76 | for plate_num in plate_nums:
77 | # 创建空白车牌号图片
78 | img = np.array(Image.new("RGB", (self.plate_width, self.plate_height), self.bg_color))
79 | # 每个字符的x轴起始、终止位置
80 | char_width_start = self.left_offset
81 | char_width_end = char_width_start + self.char_width
82 | img[:, char_width_start:char_width_end] = self.generate_char_image(plate_num[0])
83 |
84 | char_width_start = char_width_end + self.char_interval
85 | char_width_end = char_width_start + self.char_width
86 | img[:, char_width_start:char_width_end] = self.generate_char_image(plate_num[1])
87 | # 隔开特殊间隙,继续添加车牌的后续车牌号
88 | char_width_end = char_width_end + self.point_size + self.char_interval
89 | for i in range(2, len(plate_num)):
90 | char_width_start = char_width_end + self.char_interval
91 | char_width_end = char_width_start + self.char_width
92 | img[:, char_width_start:char_width_end] = self.generate_char_image(plate_num[i])
93 |
94 | plate_images.append(img)
95 | return plate_images
96 |
97 | def generate_480_140_plate(self, plate_nums):
98 | """ 生成480 * 140尺寸的8位车牌字符图片
99 | :param plate_nums:
100 | :return:
101 | """
102 | plate_images = list()
103 | for plate_num in plate_nums:
104 | # 创建空白车牌号图片
105 | img = np.array(Image.new("RGB", (self.plate_width, self.plate_height), self.bg_color))
106 | # 第一个字符有差异,8位车牌第一个字符是45宽,后续是43宽
107 | char_width = self.char_width
108 | self.char_width = self.first_char_width
109 | # 每个字符的x轴起始、终止位置
110 | char_width_start = self.left_offset
111 | char_width_end = char_width_start + self.char_width
112 | img[:, char_width_start:char_width_end] = self.generate_char_image(plate_num[0])
113 | self.char_width = char_width
114 |
115 | char_width_start = char_width_end + self.char_interval
116 | char_width_end = char_width_start + self.char_width
117 | img[:, char_width_start:char_width_end] = self.generate_char_image(plate_num[1])
118 | # 隔开特殊间隙,继续添加车牌的后续车牌号
119 | char_width_end = char_width_end + self.point_size + self.char_interval
120 | for i in range(2, len(plate_num)):
121 | char_width_start = char_width_end + self.char_interval
122 | char_width_end = char_width_start + self.char_width
123 | img[:, char_width_start:char_width_end] = self.generate_char_image(plate_num[i])
124 |
125 | plate_images.append(img)
126 | return plate_images
127 |
128 | def generate_char_image(self, char):
129 | """ 生成字符图片
130 | :param char: 字符
131 | :return:
132 | """
133 | # 根据是否中文字符,选择生成模式
134 | if char in CharsImageGenerator.numerals or char in CharsImageGenerator.alphabet:
135 | img = self.generate_en_char_image(char)
136 | else:
137 | img = self.generate_ch_char_image(char)
138 | return img
139 |
140 | def generate_ch_char_image(self, char):
141 | """ 生成中文字符图片
142 | :param char: 待生成的中文字符
143 | """
144 | img = Image.new("RGB", (self.chinese_original_width, self.plate_height), self.bg_color)
145 | ImageDraw.Draw(img).text((0, self.height_offset), char, self.fg_color, font=self.font_ch)
146 | img = img.resize((self.char_width, self.plate_height))
147 | return np.array(img)
148 |
149 | def generate_en_char_image(self, char):
150 | """" 生成英文字符图片
151 | :param char: 待生成的英文字符
152 | """
153 | img = Image.new("RGB", (self.english_original_width, self.plate_height), self.bg_color)
154 | ImageDraw.Draw(img).text((0, self.height_offset), char, self.fg_color, font=self.font_en)
155 | img = img.resize((self.char_width, self.plate_height))
156 | return np.array(img)
157 |
--------------------------------------------------------------------------------
/generate_license_plate.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on 2019/4/17
4 | File generate_license_plate
5 | @author:ZhengYuwei
6 | 1. 产生车牌号:generate_license_plate_number
7 | 1.1 定义车牌号中每一位车牌元素:license_plate_elements
8 | 2.1 产生车牌号标签:针对特定类型的车牌,从车牌元素中选择元素组成车牌号
9 | 2 为车牌号产生车牌号图形:generate_chars_image
10 | 3. 产生车牌底牌图片:generate_plate_template
11 | 4. 加扰动元素进行数据增强,拼装底牌和车牌号图片: augment_image
12 | 4. 保存图片
13 | """
14 | import cv2
15 | import os
16 | import sys
17 | import datetime
18 | from generate_license_plate_number import LicensePlateNoGenerator
19 | from generate_chars_image import CharsImageGenerator
20 | from generate_plate_template import LicensePlateImageGenerator
21 | from augment_image import ImageAugmentation
22 |
23 |
24 | class LicensePlateGenerator(object):
25 |
26 | @staticmethod
27 | def generate_license_plate_images(plate_type, batch_size, save_path, shift_index=0):
28 | """ 生成特定数量的、指定车牌类型的车牌图片,并保存到指定目录下
29 | :param plate_type: 车牌类型
30 | :param batch_size: 车牌号数量
31 | :param save_path: txt文件根目录
32 | :param shift_index: 图片名称保存的前缀偏移量
33 | :return:
34 | """
35 | sys.stdout.write('\r>> 生成车牌号图片...')
36 | sys.stdout.flush()
37 | # 生成车牌号
38 | license_plate_no_generator = LicensePlateNoGenerator(plate_type)
39 | plate_nums = license_plate_no_generator.generate_license_plate_numbers(batch_size)
40 | # 生成车牌号图片:白底黑字
41 | chars_image_generator = CharsImageGenerator(plate_type)
42 | chars_images = chars_image_generator.generate_images(plate_nums)
43 | # 生成车牌底牌
44 | license_template_generator = LicensePlateImageGenerator(plate_type)
45 | template_image = license_template_generator.generate_template_image(chars_image_generator.plate_width,
46 | chars_image_generator.plate_height)
47 | # 数据增强及车牌字符颜色修正,并保存
48 | sys.stdout.write('\r>> 生成车牌图片...')
49 | sys.stdout.flush()
50 | augmentation = ImageAugmentation(plate_type, template_image)
51 |
52 | save_path = os.path.join(save_path, plate_type)
53 | if not os.path.exists(save_path):
54 | os.makedirs(save_path)
55 | prefix_len = 9 # 图片前缀位数,亿
56 | global plate_height
57 | plate_width = int(chars_image_generator.plate_width * plate_height / chars_image_generator.plate_height)
58 | for index, char_image in enumerate(chars_images):
59 | image_name = str(shift_index + index).zfill(prefix_len) + '_' + plate_nums[index] + '.jpg'
60 | image_path = os.path.join(save_path, image_name)
61 | image = augmentation.augment(char_image)
62 | image = cv2.resize(image, (plate_width, plate_height))
63 | cv2.imencode('.jpg', image)[1].tofile(image_path)
64 | if (index+1) % 100 == 0:
65 | sys.stdout.write('\r>> {} done...'.format(index + 1))
66 | sys.stdout.flush()
67 | return
68 |
69 |
70 | if __name__ == '__main__':
71 | plate_height = 72
72 | # 每个颜色的生成
73 | blue_batch_size = 1400
74 | yellow_batch_size = 300
75 | new_energy_batch_size = 300
76 | # 迭代次数
77 | iter_times = 10000
78 | # 保存文件夹名称
79 | file_path = os.path.join(os.getcwd(), 'plate_images')
80 | start_index = 0
81 | sys.stdout.write('{}: total {} iterations ...\n'.format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
82 | iter_times))
83 | sys.stdout.flush()
84 | for i in range(iter_times):
85 | sys.stdout.write('\r{}: iter {}...\n'.format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), i))
86 | sys.stdout.flush()
87 | LicensePlateGenerator.generate_license_plate_images('single_blue',
88 | batch_size=blue_batch_size,
89 | save_path=file_path,
90 | shift_index=start_index)
91 | start_index += blue_batch_size
92 | LicensePlateGenerator.generate_license_plate_images('single_yellow',
93 | batch_size=yellow_batch_size,
94 | save_path=file_path,
95 | shift_index=start_index)
96 | start_index += yellow_batch_size
97 | LicensePlateGenerator.generate_license_plate_images('small_new_energy',
98 | batch_size=new_energy_batch_size,
99 | save_path=file_path,
100 | shift_index=start_index)
101 | start_index += new_energy_batch_size
102 | sys.stdout.write('\r{}: done...\n'.format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), iter_times))
103 | sys.stdout.flush()
104 |
--------------------------------------------------------------------------------
/generate_license_plate_number.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on 2019/4/17
4 | File generate_license_plate_number
5 | @author:ZhengYuwei
6 | 功能:
7 | 定制不同类型车牌的车牌号规则,生成指定数量的车牌号
8 | """
9 | import numpy as np
10 | from license_plate_elements import LicensePlateElements
11 |
12 |
13 | class LicensePlateNoGenerator(object):
14 | """ 随机生成车牌号和类型 """
15 | # 数字和英文字母列表
16 | numerals = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
17 | alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
18 | 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
19 | 'U', 'V', 'W', 'X', 'Y', 'Z']
20 |
21 | def __init__(self, plate_type):
22 | """ 初始化随机生成的比例,用于后续的随机生成方法中
23 | :param plate_type: 需要生成的车牌类型
24 | """
25 | if plate_type not in LicensePlateElements.plate_type_enum.keys():
26 | print('车牌类型指定错误,请参考license_plate_elements,py里的plate_type_enum变量!')
27 | self.plate_type = None
28 | return
29 | # 车牌类型
30 | self.plate_type = plate_type
31 | # 车牌号元素对象
32 | self.elements = LicensePlateElements()
33 |
34 | def generate_license_plate_numbers(self, num):
35 | """ 生成指定数量的车牌号
36 | :param num: 数量
37 | :return: 车牌号及对应label
38 | """
39 | license_plate_numbers = None
40 | # 蓝色底牌、黄色底牌 车牌号为标准车牌规则
41 | if self.plate_type in ['single_blue', 'single_yellow']:
42 | license_plate_numbers = self.generate_standard_license_no(num)
43 | # 小型新能源车牌号规则
44 | elif self.plate_type == 'small_new_energy':
45 | license_plate_numbers = self.generate_small_new_energy_license_no(num)
46 | # 大型新能源车牌号规则
47 | elif self.plate_type == 'big_new_energy':
48 | pass
49 | # 警车车牌号规则
50 | elif self.plate_type == 'police':
51 | pass
52 | # 军区车车牌号规则
53 | elif self.plate_type == 'single_army':
54 | pass
55 | # 香港车牌号规则
56 | elif self.plate_type == 'hk':
57 | pass
58 | # 澳门车牌号规则
59 | elif self.plate_type == 'macau':
60 | pass
61 | # 黑色底牌车牌号规则
62 | elif self.plate_type == 'single_black':
63 | pass
64 | else:
65 | raise ValueError('暂时不支持该类型车牌!')
66 |
67 | return license_plate_numbers
68 |
69 | def generate_standard_license_no(self, num):
70 | """ 生成蓝色、黄色等标准规则车牌号
71 | :param num: 生成车牌的数量
72 | :return: 生成的车牌号列表
73 | """
74 | # 针对车牌的每一位,随机采样
75 | license_chars = list()
76 | for char_index in range(7):
77 | # 对应车牌位上限制的字符范围
78 | char_range = self.elements.get_chars_sorted_by_label(char_index)
79 | if char_index == 0:
80 | char_range = char_range[:31] # 第一位排除掉‘军’和‘使’
81 | elif char_index == 1:
82 | # 第二位的范围还和省份相关,这里没考虑
83 | char_range = char_range[:24] # 第二位排除数字
84 | elif char_index == 6:
85 | char_range = char_range[:34] # 第六位排除‘学’、‘警’等特殊字符
86 |
87 | license_chars.append(np.random.choice(a=char_range, size=num, replace=True))
88 |
89 | # 取每一位,组成7位车牌
90 | license_plate_numbers = [list(_) for _ in zip(*license_chars)]
91 | # 在后五位编码可以出现字母,但不能超过两个
92 | for i, lic_no in enumerate(license_plate_numbers):
93 | # 找出后5位中英文字母的位置
94 | alphabet_loc = list()
95 | for loc in range(2, 7):
96 | if lic_no[loc] in LicensePlateNoGenerator.alphabet:
97 | alphabet_loc.append(loc)
98 | # 字母数多于两个的,随机保留2个(这样会导致车牌中2位字母数的车牌比较多)
99 | if len(alphabet_loc) > 2:
100 | allow = np.random.choice(a=alphabet_loc, size=2, replace=False)
101 | alphabet_loc.remove(allow[0])
102 | alphabet_loc.remove(allow[1])
103 |
104 | # 多出来的字母,替换为数字
105 | new_nos = np.random.choice(a=LicensePlateNoGenerator.numerals, size=len(alphabet_loc), replace=True)
106 | for j, loc in enumerate(alphabet_loc):
107 | lic_no[loc] = new_nos[j]
108 |
109 | license_plate_numbers = [''.join(_) for _ in license_plate_numbers]
110 | return license_plate_numbers
111 |
112 | def generate_small_new_energy_license_no(self, num):
113 | """ 生成小型新能源车牌号
114 | :param num: 生成车牌的数量
115 | :return: 生成的车牌号列表
116 | """
117 | # 针对车牌的每一位,随机采样
118 | license_chars = list()
119 | for char_index in range(8):
120 | char_range = self.elements.get_chars_sorted_by_label(char_index)
121 | # 对应车牌位上限制的字符范围
122 | if char_index == 0:
123 | char_range = char_range[:31] # 排除掉‘军’和‘使’
124 | elif char_index == 1:
125 | # 第二位的范围还和省份相关,这里没考虑
126 | char_range = char_range[:24] # 第二位排除数字
127 | elif char_index == 2:
128 | char_range = ['D', 'F'] # 小型新能源第3位为D或F
129 | elif char_index == 3:
130 | # 该位规则符合取值范围
131 | pass
132 | else:
133 | char_range = LicensePlateNoGenerator.numerals # 小型新能源后4位必须用数值
134 |
135 | license_chars.append(np.random.choice(a=char_range, size=num, replace=True))
136 |
137 | # 取每一位,组成8位车牌
138 | license_plate_numbers = [''.join(_) for _ in zip(*license_chars)]
139 | return license_plate_numbers
140 |
--------------------------------------------------------------------------------
/generate_plate_template.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on 2019/4/17
4 | File generate_template_image
5 | @author:ZhengYuwei
6 | """
7 | import cv2
8 |
9 |
10 | class LicensePlateImageGenerator(object):
11 | """ 根据车牌类型和车牌号,生成车牌图片 """
12 | single_blue_plate_bg = './images/single_blue1.bmp'
13 | small_new_energy_plate_bg = './images/small_new_energy.jpg'
14 | single_yellow1_plate_bg = './images/single_yellow1.bmp'
15 | police1_plate_bg = './images/police1.bmp'
16 |
17 | def __init__(self, plate_type):
18 | """ 初始化定义车牌类型,以及不同类型的车牌底牌图片 """
19 | self.plate_type = plate_type
20 |
21 | if plate_type == 'single_blue':
22 | plate_image = cv2.imread(LicensePlateImageGenerator.single_blue_plate_bg)
23 | elif plate_type == 'small_new_energy':
24 | plate_image = cv2.imread(LicensePlateImageGenerator.small_new_energy_plate_bg)
25 | elif plate_type == 'single_yellow':
26 | plate_image = cv2.imread(LicensePlateImageGenerator.single_yellow1_plate_bg)
27 | elif plate_type == 'police':
28 | plate_image = cv2.imread(LicensePlateImageGenerator.police1_plate_bg)
29 | else:
30 | raise ValueError('该类型车牌目前功能尚未完成!')
31 |
32 | self.bg = plate_image
33 |
34 | def generate_template_image(self, width, height):
35 | """ 根据车牌类型,生成对应的车牌底牌
36 | :param width: 模板宽度
37 | :param height: 模板高度
38 | :return:
39 | """
40 | return cv2.resize(self.bg, (width, height))
41 |
--------------------------------------------------------------------------------
/images/11.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/11.bmp
--------------------------------------------------------------------------------
/images/12.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/12.bmp
--------------------------------------------------------------------------------
/images/army1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/army1.bmp
--------------------------------------------------------------------------------
/images/army2.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/army2.bmp
--------------------------------------------------------------------------------
/images/big_new_energy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/big_new_energy.jpg
--------------------------------------------------------------------------------
/images/double_white1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/double_white1.bmp
--------------------------------------------------------------------------------
/images/double_white2.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/double_white2.bmp
--------------------------------------------------------------------------------
/images/double_yellow1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/double_yellow1.bmp
--------------------------------------------------------------------------------
/images/double_yellow2.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/double_yellow2.bmp
--------------------------------------------------------------------------------
/images/police1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/police1.bmp
--------------------------------------------------------------------------------
/images/police2.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/police2.bmp
--------------------------------------------------------------------------------
/images/single_black1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/single_black1.bmp
--------------------------------------------------------------------------------
/images/single_black2.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/single_black2.bmp
--------------------------------------------------------------------------------
/images/single_blue1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/single_blue1.bmp
--------------------------------------------------------------------------------
/images/single_blue2.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/single_blue2.bmp
--------------------------------------------------------------------------------
/images/single_yellow1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/single_yellow1.bmp
--------------------------------------------------------------------------------
/images/single_yellow2.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/single_yellow2.bmp
--------------------------------------------------------------------------------
/images/small_new_energy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/small_new_energy.jpg
--------------------------------------------------------------------------------
/images/smu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/smu.jpg
--------------------------------------------------------------------------------
/images/smu2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/smu2.jpg
--------------------------------------------------------------------------------
/images/大型新能源车牌号-示例.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/大型新能源车牌号-示例.jpg
--------------------------------------------------------------------------------
/images/小型新能源车牌号-示例.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/images/小型新能源车牌号-示例.jpg
--------------------------------------------------------------------------------
/license_plate_elements.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on 2019/4/17
4 | File license_plate_elements
5 | @author:ZhengYuwei
6 | 功能:
7 | 定义车牌相关的元素,包括车牌中的字符和车牌类型
8 | 一般车牌字符一共7位,新能源车牌8位,故增加一个标志位,表示车牌位数
9 | plate_type_enum为车牌类型,is_exist_plate_enum标记是否存在车牌
10 | """
11 |
12 |
13 | class LicensePlateElements(object):
14 | """ 定义车牌相关的元素(车牌字符和车牌类型),以及获取元素的方法
15 | 一般车牌字符一共7位,新能源车牌8位,故增加一个标志位,表示车牌位数
16 | plate_type_enum为车牌类型,is_exist_plate_enum标记是否存在车牌
17 | """
18 |
19 | # 车牌第1位字符的取值范围及其label
20 | char1_enum = {
21 | u"京": 0, u"沪": 1, u"津": 2, u"渝": 3, u"冀": 4, u"晋": 5, u"蒙": 6, u"辽": 7, u"吉": 8, u"黑": 9,
22 | u"苏": 10, u"浙": 11, u"皖": 12, u"闽": 13, u"赣": 14, u"鲁": 15, u"豫": 16, u"鄂": 17, u"湘": 18, u"粤": 19,
23 | u"桂": 20, u"琼": 21, u"川": 22, u"贵": 23, u"云": 24, u"藏": 25, u"陕": 26, u"甘": 27, u"青": 28, u"宁": 29,
24 | u"新": 30, u"军": 31, u"使": 32,
25 | }
26 |
27 | # 车牌第2位字符的取值范围及其label
28 | char2_enum = {
29 | "A": 0, "B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, "H": 7, "J": 8, "K": 9,
30 | "L": 10, "M": 11, "N": 12, "P": 13, "Q": 14, "R": 15, "S": 16, "T": 17, "U": 18, "V": 19,
31 | "W": 20, "X": 21, "Y": 22, "Z": 23, "0": 24, "1": 25, "2": 26, "3": 27, "4": 28, "5": 29,
32 | "6": 30, "7": 31, "8": 32, "9": 33,
33 | }
34 |
35 | # 车牌第3~6位字符的取值范围及其label
36 | char3_6_enum = {
37 | "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
38 | "A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15, "G": 16, "H": 17, "J": 18, "K": 19,
39 | "L": 20, "M": 21, "N": 22, "P": 23, "Q": 24, "R": 25, "S": 26, "T": 27, "U": 28, "V": 29,
40 | "W": 30, "X": 31, "Y": 32, "Z": 33,
41 | }
42 |
43 | # 车牌第7位字符的取值范围及其label
44 | char7_enum = {
45 | "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
46 | "A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15, "G": 16, "H": 17, "J": 18, "K": 19,
47 | "L": 20, "M": 21, "N": 22, "P": 23, "Q": 24, "R": 25, "S": 26, "T": 27, "U": 28, "V": 29,
48 | "W": 30, "X": 31, "Y": 32, "Z": 33, u"学": 34, u"警": 35, u"领": 36, u"挂": 37, u"港": 38, u"澳": 39,
49 | u"使": 40,
50 | }
51 |
52 | # 车牌第8位字符的取值范围及其label
53 | char8_enum = {
54 | "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "D": 10, "F": 11,
55 | }
56 |
57 | # 不同车牌位置与车牌字符变量取值表的映射表
58 | index_to_char_label = {
59 | 0: char1_enum,
60 | 1: char2_enum,
61 | 2: char3_6_enum,
62 | 3: char3_6_enum,
63 | 4: char3_6_enum,
64 | 5: char3_6_enum,
65 | 6: char7_enum,
66 | 7: char8_enum,
67 | }
68 |
69 | # 车牌位数及其label
70 | char_number_enum = {'7': 0, '8': 1}
71 |
72 | # 车牌类型
73 | plate_type_enum = {
74 | 'single_blue': 0, 'single_yellow': 1, 'double_yellow': 2, 'police': 3, 'learner': 4,
75 | 'hk': 5, 'macau': 6, 'single_army': 7, 'double_army': 8, 'consulate': 9,
76 | 'embassy': 10, 'army_police': 11, 'double_army_police': 12, 'small_new_energy': 13, 'big_new_energy': 14,
77 | 'factory': 15, 'single_black': 16, 'other': 17,
78 | }
79 |
80 | # 车牌颜色
81 | plate_color_indices = {'blue': 0, 'yellow': 1, 'green': 2, 'white': 3, 'black': 4, 'other': 5, }
82 |
83 | # 是否存在车牌
84 | is_exist_plate_enum = {'exist': 0, 'non-exist': 1}
85 |
86 | def __init__(self):
87 | """ 初始化,通过每一位车牌字符的char_label,增加label_char的反向映射 """
88 | self.index_to_label_char = {}
89 | for index, char_label in LicensePlateElements.index_to_char_label.items():
90 | self.index_to_label_char[index] = {label: char for char, label in char_label.items()}
91 |
92 | self.label_to_type = {}
93 | for label, plate_type in LicensePlateElements.plate_type_enum.items():
94 | self.label_to_type[label] = plate_type
95 | return
96 |
97 | def get_char_label(self, index):
98 | """ 获取指定车牌位置的char-label映射
99 | :param index: 指定车牌位数
100 | :return: 指定车牌位置的char-label映射
101 | """
102 | return self.index_to_char_label.get(index, None)
103 |
104 | def get_label_char(self, index):
105 | """ 获取指定车牌位置的label-char映射
106 | :param index: 指定车牌位数
107 | :return: 指定车牌位置的label-char映射
108 | """
109 | return self.index_to_label_char.get(index, None)
110 |
111 | def get_chars_sorted_by_label(self, index):
112 | """ 获取指定车牌位置上,按label排序的字符列表
113 | :param index: 指定车牌位置
114 | :return: 字符列表
115 | """
116 | label_char = self.get_label_char(index)
117 | if label_char is None:
118 | print('Index is Out of Maximal License Plate Figures')
119 | chars = [None] * len(label_char)
120 | for index, char in label_char.items():
121 | chars[index] = char
122 | return chars
123 |
124 | def get_char(self, index, label):
125 | """ 获取指定车牌位数、标签的对应字符
126 | :param index: 指定车牌位数
127 | :param label: 指定标签
128 | :return: 车牌字符
129 | """
130 | label_char = self.index_to_label_char.get(index, None)
131 | if label_char is None:
132 | print('Index is Out of Maximal License Plate Figures')
133 | return None
134 | return label_char.get(label, None)
135 |
136 | def get_label(self, index, char):
137 | """ 获取指定车牌位数、字符的对应标签
138 | :param index: 指定车牌位置
139 | :param char: 指定字符
140 | :return: 车牌标签
141 | """
142 | char_label = self.index_to_char_label.get(index, None)
143 | if char_label is None:
144 | print('Index is Out of Maximal License Plate Figures')
145 | return None
146 | return char_label.get(char, None)
147 |
148 | def convert_to_labels(self, license_plate):
149 | """ 将车牌号转换为标签
150 | :param license_plate: 车牌号
151 | :return: 标签
152 | """
153 | labels = [None] * len(license_plate)
154 | for index, char in enumerate(license_plate):
155 | labels[index] = self.get_label(index, char)
156 | return labels
157 |
158 | def get_type_list(self):
159 | """ 获取车牌类型有序(label序)列表 """
160 | type_list = [None] * len(self.plate_type_enum)
161 | for plate_type, label in self.plate_type_enum.items():
162 | type_list[label] = plate_type
163 | return type_list
164 |
165 | def get_type(self, label):
166 | """ 根据车配类型的label,获取车牌类型
167 | :param label: 车牌类型的label
168 | :return:
169 | """
170 | return self.label_to_type[label]
171 |
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/README.md:
--------------------------------------------------------------------------------
1 | # 基于多标签模型的车牌号识别
2 |
3 | ### 文件说明:
4 | 1. resnet18文件夹:将resnet18作为基础结构,设计多标签分类模型;
5 | 1. resnet50文件夹:将resnet50作为基础结构,设计多标签分类模型;
6 | 2. file_tools.py:提供文件搜索功能,在generate_txt.py中调用;
7 | 3. generate_txt.py:读取车牌图片目录下的图片,根据图片名称中的车牌号、license_plate_elements.py中车牌号字符与标签的映射关系,生成标签txt文件(7和8位车牌的全量、训练、测试、验证集,7位车牌全量数据集,8位车牌全量数据集),每一行格式为:图片路径 char1 char2 char3 char4 char5 char6 char7 char8 is_8_char plate_color;
8 | 4. generate_lmdb.sh:根据生成的txt文件,找到图片数据,然后调用caffe中改造过的generate_imageset二进制执行文件生成lmdb格式的数据集;
9 | 5. recognization_engine.py:检测模型测试代码。
10 |
11 | ### 模型结构
12 | [Netscope Editor](http://ethereon.github.io/netscope/#/editor)
13 |
14 | ### 训练过程
15 | 1. 训练时,需要将7位车牌的第8位字符标记为-1,生成lmdb,然后在训练网络时,第8位的softmaxWithLoss层添加设置以忽略该类标签:
16 | ```
17 | loss_param{
18 | ignore_label: -1
19 | }
20 | ```
21 | 2. 训练时,记得平衡实际数据与生成的数据;
22 | 3. 车牌号的截取方式会影响模型的识别精度,所以最好是添加了检测模型检测出来的车牌;
23 |
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/file_tools.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on 2019/3/28
4 | File file_tools
5 | @author:ZhengYuwei
6 | """
7 | import os
8 | import shutil
9 | import sys
10 | import getopt
11 |
12 |
13 | class FileTools(object):
14 | """ 文件处理工具类 """
15 |
16 | @staticmethod
17 | def mkdir(new_dir):
18 | """ 建立文件夹路径 """
19 | if not os.path.exists(new_dir):
20 | os.makedirs(new_dir)
21 | return
22 |
23 | @staticmethod
24 | def search_file(search_path, file_format):
25 | """在指定目录search_path下,递归目录搜索指定尾缀的文件
26 | :param search_path: 指定的搜索目录,如:./2018年收集的素材并已校正
27 | :param file_format: 文件尾缀,如‘.txt’
28 | :return: 该目录下所有指定尾缀文件的路径组成的list
29 | """
30 | file_path_list = []
31 | # 获取:1.父目录绝对路径 2.所有文件夹名字(不含路径) 3.所有文件名字
32 | for root_path, dir_names, file_names in os.walk(search_path):
33 | # 收集符合条件的文件名
34 | for filename in file_names:
35 | if filename.endswith(file_format):
36 | file_path_list.append(os.path.join(root_path, filename))
37 | return file_path_list
38 |
39 | @staticmethod
40 | def copy_file(file_path_list, destination_file):
41 | """ 将文件列表中的文件拷贝到目的文件夹(为空,不存在则创建,存在则删除再创建)下
42 | :param file_path_list: 文件路径列表
43 | :param destination_file: 目的文件夹(为空,不存在则创建,存在则删除再创建)
44 | """
45 | # 保证目标目录为空
46 | if not os.path.exists(destination_file):
47 | os.removedirs(destination_file)
48 | os.makedirs(destination_file)
49 |
50 | # 复制文件
51 | for file_path in file_path_list:
52 | if not os.path.isfile(file_path):
53 | print("{} doesn't exist!".format(file_path))
54 | else:
55 | dst_file_name = os.path.join(destination_file, os.path.basename(file_path))
56 | # 名字重复的图片,修改名称
57 | flag = 1
58 | while os.path.isfile(dst_file_name):
59 | dst_file_name = os.path.splitext(os.path.basename(file_path))
60 | dst_file_name = dst_file_name[0] + '_' + str(flag) + '.' + dst_file_name[1]
61 | dst_file_name = os.path.join(destination_file, dst_file_name)
62 | flag += 1
63 | if flag != 1:
64 | print('filename conflict: {}'.format(os.path.basename(file_path)))
65 | shutil.copy(file_path, dst_file_name)
66 | return
67 |
68 |
69 | if __name__ == '__main__':
70 | """ 从源文件夹中,拷贝特定格式的文件,到目标文件夹(为空,不存在则创建,存在则删除再创建)中:
71 | -s --src=: 源文件夹
72 | -t --target=: 目标文件夹
73 | [-f --format=]: 可选,指定文件格式
74 | """
75 | opts, args = getopt.getopt(sys.argv[1:], 's:t:f:', ['src=', 'target=', 'format='])
76 | src_path = None
77 | target_path = None
78 | file_type = ''
79 | for key, value in opts:
80 | if key in ['-s', '--src']:
81 | src_path = value
82 | elif key in ['-t', '--target']:
83 | target_path = value
84 | elif key in ['-f', '--format']:
85 | file_type = value
86 | else:
87 | print("忽略选项 '{}'".format(key))
88 |
89 | if (src_path is None or src_path == '') or (target_path is None or target_path == ''):
90 | print("输入指令有误(e.g. python file_tools.py -s /home/a -t /home/b [-f .txt] )")
91 | elif not os.path.isdir(src_path) or not os.path.isdir(target_path):
92 | print('输入-s或-t选项为不合法(必须是存在路径)')
93 | else:
94 | print('源文件夹:{}'.format(src_path))
95 | print('目标文件夹:{}'.format(target_path))
96 | print('文件格式:{}'.format(file_type))
97 | FileTools.copy_file(FileTools.search_file(src_path, file_type), target_path)
98 |
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/generate_lmdb.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | python generate_txt.py
3 |
4 | CAFFE_ROOT=/home/zhengyuwei/software/multi_label_caffe
5 | IMAGES_DIR=/home/data_160/data3/smart_home/xiongxin-yuwei/plate_recognition/new_plate_images/
6 | LMDB_ROOT_DIR=/home/data_160/data3/smart_home/xiongxin-yuwei/plate_recognition/new_plate_lmdb/
7 |
8 | for MODE in all train test validate;
9 | do
10 | mkdir ${LMDB_ROOT_DIR}/multi_label_lmdb
11 | rm -r ${LMDB_ROOT_DIR}/multi_label_lmdb/${MODE}_lmdb
12 |
13 | LIST_FILE=${LMDB_ROOT_DIR}/multi_label_lmdb/${MODE}.txt
14 | LMDB_DIR=${LMDB_ROOT_DIR}/multi_label_lmdb/${MODE}_lmdb
15 | SHUFFLE=true
16 |
17 | RESIZE_W=144
18 | RESIZE_H=48
19 |
20 | ${CAFFE_ROOT}/build/tools/convert_imageset --encoded=true --encode_type=jpg --resize_width=${RESIZE_W} --resize_height=${RESIZE_H} --shuffle=true ${IMAGES_DIR} ${LIST_FILE} ${LMDB_DIR}
21 | #${CAFFE_ROOT}/build/tools/convert_imageset --encoded=true --encode_type=jpg --shuffle=true ${IMAGES_DIR} ${LIST_FILE} ${LMDB_DIR}
22 | done
23 |
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/generate_txt.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import os
3 | import sys
4 | import numpy as np
5 | import random
6 | import datetime
7 | from file_tools import FileTools
8 | sys.path.insert(0, '../../license-plate-generator')
9 | from license_plate_elements import LicensePlateElements
10 |
11 |
12 | # 所有车牌号图片的根目录
13 | plate_images_root_dir = '/home/data_160/data3/smart_home/xiongxin-yuwei/plate_recognition/new_plate_images/'
14 |
15 | blue_dir = [plate_images_root_dir + 'CCPD/blue', plate_images_root_dir + 'generate/blue']
16 | yellow_dir = [plate_images_root_dir + 'generate/yellow']
17 | green_dir = [plate_images_root_dir + 'generate/green', ]
18 | white_dir = []
19 | big_green_dir = []
20 | black_dir = []
21 |
22 | # 所有车牌图片路径list
23 | blue_paths = list()
24 | for path in blue_dir:
25 | print('搜索路径', path)
26 | blue_paths.extend(FileTools.search_file(path, '.jpg'))
27 |
28 | yellow_paths = list()
29 | for path in yellow_dir:
30 | print('搜索路径', path)
31 | yellow_paths.extend(FileTools.search_file(path, '.jpg'))
32 |
33 | green_paths = list()
34 | for path in green_dir:
35 | print('搜索路径', path)
36 | green_paths.extend(FileTools.search_file(path, '.jpg'))
37 |
38 | white_paths = list()
39 | for path in white_dir:
40 | print('搜索路径', path)
41 | white_paths.extend(FileTools.search_file(path, '.jpg'))
42 |
43 | # 生成标签数据(其中图片路径是相对根目录的路径)
44 | print('开始产生车牌号标签列表...')
45 | plate_nums = (len(blue_paths), len(yellow_paths), len(green_paths), len(white_paths), )
46 | print('blue, yellow, green, white:{}'.format(plate_nums))
47 | elements = LicensePlateElements()
48 | all_paths = (blue_paths, yellow_paths, green_paths, white_paths, )
49 | types = (str(elements.plate_colors['blue']), str(elements.plate_colors['yellow']),
50 | str(elements.plate_colors['green']), str(elements.plate_colors['white']), )
51 | lines = list()
52 | char8_labels = '-1'
53 | plate7_type = str(elements.char_number_enum.get('7'))
54 | plate8_type = str(elements.char_number_enum.get('8'))
55 | line = [None] * 11
56 | for path_index, paths in enumerate(all_paths):
57 | for image_index, image_path in enumerate(paths):
58 | plate_no = os.path.splitext(os.path.basename(image_path))[0].split('_')[-1] # 00000001_xxxxxxxx.jpg
59 | # print(plate_no)
60 | # relative_path char1 char2 char3 char4 char5 char6 char7 char8 char_num plate_color
61 | line[0] = image_path[len(plate_images_root_dir):]
62 | if len(plate_no) == 7:
63 | line[8] = char8_labels # 第8位标记为-1
64 | line[9] = plate7_type
65 | elif len(plate_no) == 8:
66 | line[8] = str(elements.get_label(7, plate_no[7]))
67 | line[9] = plate8_type
68 | else:
69 | print('Warn: checke ', image_path)
70 | continue
71 | for i in range(7):
72 | line[i+1] = str(elements.get_label(i, plate_no[i]))
73 | line[10] = types[path_index]
74 |
75 | lines.append([' '.join(line), '\n'])
76 | if (image_index + 1) % 10000 == 0:
77 | print('{}: {}/{} done...'.format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
78 | image_index + 1, plate_nums[path_index]))
79 |
80 | random.shuffle(lines)
81 | all_num = len(lines)
82 | # print(all_num)
83 | if not os.path.exists('multi_label_lmdb'):
84 | os.makedirs('multi_label_lmdb')
85 |
86 | print('生成全量数据标签文件...')
87 | all_txt = 'multi_label_lmdb/all.txt'
88 | with open(all_txt, 'w+') as file:
89 | for line in lines:
90 | file.writelines(line)
91 |
92 | print('生成测试数据标签文件...')
93 | test_txt = 'multi_label_lmdb/test.txt'
94 | with open(test_txt, 'w+') as file:
95 | for line in lines[:int(all_num * 0.1)]:
96 | file.writelines(line)
97 |
98 | print('生成验证数据标签文件...')
99 | validate_txt = 'multi_label_lmdb/validate.txt'
100 | with open(validate_txt, 'w+') as file:
101 | for line in lines[int(all_num * 0.1):(int(all_num * 0.1)+int(all_num * 0.1))]:
102 | file.writelines(line)
103 |
104 | print('生成训练数据标签文件...')
105 | train_txt = 'multi_label_lmdb/train.txt'
106 | with open(train_txt, 'w+') as file:
107 | for line in lines[(int(all_num * 0.1)+int(all_num * 0.1)):all_num]:
108 | file.writelines(line)
109 |
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/recognization_engine.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on 2019/03/30
4 |
5 | @author:x00472174
6 | """
7 | import sys
8 | import os
9 | import cv2
10 | import time
11 | import argparse
12 | from file_tools import FileTools
13 | import pdb
14 |
15 | sys.path.append('/home/zhengyuwei/software/quhezheng_caffe_yolov2/python')
16 | import caffe
17 |
18 |
19 | class RecognitionEngine(object):
20 | """车牌识别caffe模型测试代码"""
21 |
22 | # 车牌第1位字符的取值范围及其label
23 | char1_indices = {
24 | u"京": 0, u"沪": 1, u"津": 2, u"渝": 3, u"冀": 4, u"晋": 5, u"蒙": 6, u"辽": 7, u"吉": 8, u"黑": 9,
25 | u"苏": 10, u"浙": 11, u"皖": 12, u"闽": 13, u"赣": 14, u"鲁": 15, u"豫": 16, u"鄂": 17, u"湘": 18, u"粤": 19,
26 | u"桂": 20, u"琼": 21, u"川": 22, u"贵": 23, u"云": 24, u"藏": 25, u"陕": 26, u"甘": 27, u"青": 28, u"宁": 29,
27 | u"新": 30, u"军": 31, u"使": 32,
28 | }
29 |
30 | # 车牌第2位字符的取值范围及其label
31 | char2_indices = {
32 | "A": 0, "B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, "H": 7, "J": 8, "K": 9,
33 | "L": 10, "M": 11, "N": 12, "P": 13, "Q": 14, "R": 15, "S": 16, "T": 17, "U": 18, "V": 19,
34 | "W": 20, "X": 21, "Y": 22, "Z": 23, "0": 24, "1": 25, "2": 26, "3": 27, "4": 28, "5": 29,
35 | "6": 30, "7": 31, "8": 32, "9": 33,
36 | }
37 |
38 | # 车牌第3~6位字符的取值范围及其label
39 | char3_6_indices = {
40 | "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
41 | "A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15, "G": 16, "H": 17, "J": 18, "K": 19,
42 | "L": 20, "M": 21, "N": 22, "P": 23, "Q": 24, "R": 25, "S": 26, "T": 27, "U": 28, "V": 29,
43 | "W": 30, "X": 31, "Y": 32, "Z": 33,
44 | }
45 |
46 | # 车牌第7位字符的取值范围及其label
47 | char7_indices = {
48 | "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
49 | "A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15, "G": 16, "H": 17, "J": 18, "K": 19,
50 | "L": 20, "M": 21, "N": 22, "P": 23, "Q": 24, "R": 25, "S": 26, "T": 27, "U": 28, "V": 29,
51 | "W": 30, "X": 31, "Y": 32, "Z": 33, u"学": 34, u"警": 35, u"领": 36, u"挂": 37, u"港": 38, u"澳": 39,
52 | u"使": 40,
53 | }
54 |
55 | # 车牌第8位字符的取值范围及其label
56 | char8_indices = {
57 | "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "D": 10, "F": 11,
58 | }
59 |
60 | # 车牌号字符数
61 | char_num_indices = {"7": 0, "8": 1}
62 |
63 | # 车牌颜色
64 | plate_color_indices = {'blue': 0, 'yellow': 1, 'green': 2, 'white': 3, 'black': 4, 'other': 5, }
65 |
66 | char1_indices = {v: k for k, v in char1_indices.items()}
67 | char2_indices = {v: k for k, v in char2_indices.items()}
68 | char3_6_indices = {v: k for k, v in char3_6_indices.items()}
69 | char7_indices = {v: k for k, v in char7_indices.items()}
70 | char8_indices = {v: k for k, v in char8_indices.items()}
71 | char_num_indices = {v: k for k, v in char_num_indices.items()}
72 | plate_color_indices = {v: k for k, v in plate_color_indices.items()}
73 |
74 | def __init__(self, root_dir, caffemodel_name, prototxt_name, shape=(48, 144)):
75 | """ 初始化caffe模型
76 | :param root_dir: 模型文件所在根目录
77 | :param caffemodel_name: 模型文件名称
78 | :param prototxt_name: prototxt文件名称
79 | :param shape: 模型输入图片的尺寸
80 | """
81 | caffe.set_device(0)
82 | caffe.set_mode_gpu()
83 | self.net = caffe.Net(os.path.join(root_dir, prototxt_name),
84 | os.path.join(root_dir, caffemodel_name), caffe.TEST)
85 | self.transformer = caffe.io.Transformer({'data': self.net.blobs['data'].data.shape})
86 | self.transformer.set_transpose('data', (2, 0, 1))
87 | self.net.blobs['data'].reshape(1, 3, shape[0], shape[1])
88 |
89 | def recognize(self, plate_image):
90 | """ 进行车牌号识别
91 | :param plate_image: 车牌图片,BGR [0, 255]
92 | :return:
93 | {'char_num_prob': 车牌号位数概率, 'plate_no': 车牌号, 'confidence': 车牌号每位置信度列表,
94 | 'plate_color': 车牌底色, 'color_confidence': 车牌底色置信度}
95 | inference_time: 推理时间
96 | """
97 | if plate_image is None:
98 | return None
99 |
100 | plate_image = self.transformer.preprocess('data', plate_image)
101 | self.net.blobs['data'].data[...] = plate_image / 255
102 | start_time = time.time()
103 | self.net.forward()
104 | inference_time = time.time() - start_time
105 |
106 | # 解析模型输出:车牌号字符、位数、底色,及对应概率
107 | char1 = self.char1_indices[self.net.blobs['prob1'].data[...].argmax(1)[0]]
108 | char1_prob = self.net.blobs['prob1'].data[...].max()
109 | char2 = self.char2_indices[self.net.blobs['prob2'].data[...].argmax(1)[0]]
110 | char2_prob = self.net.blobs['prob2'].data[...].max()
111 | char3 = self.char3_6_indices[self.net.blobs['prob3'].data[...].argmax(1)[0]]
112 | char3_prob = self.net.blobs['prob3'].data[...].max()
113 | char4 = self.char3_6_indices[self.net.blobs['prob4'].data[...].argmax(1)[0]]
114 | char4_prob = self.net.blobs['prob4'].data[...].max()
115 | char5 = self.char3_6_indices[self.net.blobs['prob5'].data[...].argmax(1)[0]]
116 | char5_prob = self.net.blobs['prob5'].data[...].max()
117 | char6 = self.char3_6_indices[self.net.blobs['prob6'].data[...].argmax(1)[0]]
118 | char6_prob = self.net.blobs['prob6'].data[...].max()
119 | char7 = self.char7_indices[self.net.blobs['prob7'].data[...].argmax(1)[0]]
120 | char7_prob = self.net.blobs['prob7'].data[...].max()
121 | char8 = self.char8_indices[self.net.blobs['prob8'].data[...].argmax(1)[0]]
122 | char8_prob = self.net.blobs['prob8'].data[...].max()
123 | char_num = self.char_num_indices[self.net.blobs['char_num_prob'].data[...].argmax(1)[0]]
124 | char_num_prob = self.net.blobs['char_num_prob'].data[...].max()
125 | plate_color = self.plate_color_indices[self.net.blobs['plate_color'].data[...].argmax(1)[0]]
126 | plate_color_prob = self.net.blobs['plate_color'].data[...].max()
127 | # pdb.set_trace()
128 |
129 | # to check if the plate has 7 or 8 characters.
130 | if char_num == '7':
131 | plate = char1 + char2 + char3 + char4 + char5 + char6 + char7
132 | confidence = [char1_prob, char2_prob, char3_prob, char4_prob, char5_prob, char6_prob, char7_prob]
133 | else:
134 | plate = char1 + char2 + char3 + char4 + char5 + char6 + char7 + char8
135 | confidence = [char1_prob, char2_prob, char3_prob, char4_prob,
136 | char5_prob, char6_prob, char7_prob, char8_prob]
137 |
138 | return {'char_num_prob': char_num_prob, 'plate_no': plate, 'confidence': confidence,
139 | 'plate_color': plate_color, 'color_confidence': plate_color_prob}, inference_time
140 |
141 | def judge(self, plate_image, truth_plate_no, save_dir='', save_fail=False, save_success=False):
142 | """ 判断车牌号图片是否指定的车牌号,以及是否保存车牌图片
143 | :param plate_image: 车牌图片
144 | :param truth_plate_no: 真实车牌号
145 | :param save_dir: 图片保存路径
146 | :param save_fail: 是否保存失败图片
147 | :param save_success: 是否保存成功图片
148 | :return:
149 | bool: 车牌号图片是否指定的车牌号
150 | recognized_result: 车牌号图片识别结果
151 | recognized_time: 识别模型推理时间
152 | """
153 | if truth_plate_no[0] == '挂':
154 | new_gt_plate_no = ['桂']
155 | for plate_no_index in range(1, len(truth_plate_no)):
156 | new_gt_plate_no.append(truth_plate_no[plate_no_index])
157 | truth_plate_no = ''.join(new_gt_plate_no)
158 |
159 | recognized_result, recognized_time = self.recognize(plate_image)
160 | if truth_plate_no == recognized_result['plate_no']:
161 | if save_success:
162 | cv2.imwrite(os.path.join(save_dir, 'success/{}.jpg'.format(truth_plate_no)), plate_image)
163 | return True, recognized_result, recognized_time
164 | else:
165 | if save_fail:
166 | # 加上检测概率
167 | score = ['{:.1f}'.format(_) for _ in recognized_result['confidence']]
168 | cv2.putText(plate_image, score, (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 255, 0))
169 | cv2.imwrite(os.path.join(fail_path,
170 | 'fail/{}_{}.jpg'.format(truth_plate_no, recognized_result['plate_no'])),
171 | plate_image)
172 | return False, recognized_result, recognized_time
173 |
174 |
175 | if __name__ == '__main__':
176 | model_root_dir = '/home/data_160/data3/smart_home/xiongxin-yuwei/plate_recognition/models/resnet50/'
177 | model_name = 'lp_recognization_iter_20000.caffemodel'
178 | prototxt = 'recognition-deploy.prototxt'
179 | truth_color = 'green'
180 | recognition_engine = RecognitionEngine(model_root_dir, model_name, prototxt)
181 |
182 | images_root_dir = '/home/data_160/data3/smart_home/xiongxin-yuwei/plate_recognition/new_plate_images/'
183 | parser = argparse.ArgumentParser('Detect objects in image')
184 | parser.add_argument('--input', type=str, help='Input image',
185 | default=images_root_dir + 'fushi/green')
186 | parser.add_argument('--output', type=str, help='Output image',
187 | default=images_root_dir + 'temp2')
188 | args = parser.parse_args()
189 |
190 | if os.path.isfile(args.input):
191 | img_paths = [args.input]
192 | elif os.path.isdir(args.input):
193 | img_paths = FileTools.search_file(args.input, '.jpg')
194 | else:
195 | raise ValueError('输入路径不存在')
196 |
197 | if not os.path.exists(args.output):
198 | raise ValueError('输出路径不存在')
199 | else:
200 | success_path = os.path.join(args.output, 'success')
201 | fail_path = os.path.join(args.output, 'fail')
202 | if not os.path.exists(success_path):
203 | os.makedirs(success_path)
204 | if not os.path.exists(fail_path):
205 | os.makedirs(fail_path)
206 |
207 | inference_time_total_time = 0
208 | fail_recognize = 0
209 | success_recognize = 0
210 | fail_color = 0
211 | fail_image_paths = list()
212 | fail_color_paths = dict()
213 | i = 0
214 | total = len(img_paths)
215 | for image_path in img_paths:
216 | i += 1
217 | if i % 1000 == 0:
218 | print('{}/{} done...'.format(i, total))
219 |
220 | image = cv2.imread(image_path)
221 | if image is None:
222 | total -= 1
223 | continue
224 |
225 | gt_plate_num = os.path.splitext(os.path.basename(image_path))[0].split('_')[-1]
226 | is_success, result, temp_time = recognition_engine.judge(image, gt_plate_num, args.output)
227 | inference_time_total_time += temp_time
228 | if is_success:
229 | success_recognize += 1
230 | else:
231 | fail_image_paths.append(os.path.basename(image_path))
232 | fail_recognize += 1
233 |
234 | if result['plate_color'] != truth_color:
235 | fail_color += 1
236 | fail_color_paths[os.path.basename(image_path)] = '{}|{}'.format(result['plate_color'],
237 | result['color_confidence'])
238 |
239 | print('总检测数量:{}, 检测准确:{},'.format(total, success_recognize),
240 | ' 检测错误:{}, 颜色错误:{}'.format(fail_recognize, fail_color))
241 | print('检测时间(s):', inference_time_total_time / total)
242 | print('识别失败', fail_image_paths)
243 | print('车牌颜色错误', fail_color_paths)
244 |
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/resnet18/recognition-resnet18-deploy.prototxt:
--------------------------------------------------------------------------------
1 | name: "license-plate-recognition"
2 | # 输入层,只进行归一化
3 | layer {
4 | name: "data"
5 | type: "Input"
6 | top: "data"
7 | input_param {
8 | shape: {
9 | dim: 1
10 | dim: 3
11 | dim: 48
12 | dim: 144
13 | }
14 | }
15 | }
16 |
17 |
18 |
19 |
20 | ############################################################################
21 | #
22 | # 主要网络结构:conv + 4 * resnet18 building block + pooling + 全连接层
23 | #
24 | ############################################################################
25 | layer {
26 | bottom: "data"
27 | top: "conv1"
28 | name: "conv1"
29 | type: "Convolution"
30 | convolution_param {
31 | num_output: 64
32 | kernel_size: 3
33 | pad: 1
34 | stride: 1
35 | weight_filler {
36 | type: "msra"
37 | }
38 | bias_term: false
39 |
40 | }
41 | }
42 |
43 | layer {
44 | bottom: "conv1"
45 | top: "conv1"
46 | name: "bn_conv1"
47 | type: "BatchNorm"
48 | batch_norm_param{
49 | use_global_stats: true
50 | }
51 | }
52 |
53 | layer {
54 | bottom: "conv1"
55 | top: "conv1"
56 | name: "scale_conv1"
57 | type: "Scale"
58 | scale_param {
59 | bias_term: true
60 | }
61 | }
62 |
63 | layer {
64 | bottom: "conv1"
65 | top: "conv1"
66 | name: "conv1_relu"
67 | type: "ReLU"
68 | }
69 |
70 | layer {
71 | bottom: "conv1"
72 | top: "pool1"
73 | name: "pool1"
74 | type: "Pooling"
75 | pooling_param {
76 | kernel_size: 3
77 | stride: 2
78 | pool: MAX
79 | }
80 | }
81 |
82 | #########################################
83 | # resnet18的building block * 4
84 | #########################################
85 | layer {
86 | bottom: "pool1"
87 | top: "res2a_branch1"
88 | name: "res2a_branch1"
89 | type: "Convolution"
90 | convolution_param {
91 | num_output: 64
92 | kernel_size: 1
93 | pad: 0
94 | stride: 1
95 | weight_filler {
96 | type: "msra"
97 | }
98 | bias_term: false
99 |
100 | }
101 | }
102 |
103 | layer {
104 | bottom: "res2a_branch1"
105 | top: "res2a_branch1"
106 | name: "bn2a_branch1"
107 | type: "BatchNorm"
108 | batch_norm_param{
109 | use_global_stats: true
110 | }
111 | }
112 |
113 | layer {
114 | bottom: "res2a_branch1"
115 | top: "res2a_branch1"
116 | name: "scale2a_branch1"
117 | type: "Scale"
118 | scale_param {
119 | bias_term: true
120 | }
121 | }
122 |
123 | layer {
124 | bottom: "pool1"
125 | top: "res2a_branch2a"
126 | name: "res2a_branch2a"
127 | type: "Convolution"
128 | convolution_param {
129 | num_output: 64
130 | kernel_size: 3
131 | pad: 1
132 | stride: 1
133 | weight_filler {
134 | type: "msra"
135 | }
136 | bias_term: false
137 |
138 | }
139 | }
140 |
141 | layer {
142 | bottom: "res2a_branch2a"
143 | top: "res2a_branch2a"
144 | name: "bn2a_branch2a"
145 | type: "BatchNorm"
146 | batch_norm_param{
147 | use_global_stats: true
148 | }
149 | }
150 |
151 | layer {
152 | bottom: "res2a_branch2a"
153 | top: "res2a_branch2a"
154 | name: "scale2a_branch2a"
155 | type: "Scale"
156 | scale_param {
157 | bias_term: true
158 | }
159 | }
160 | layer {
161 | bottom: "res2a_branch2a"
162 | top: "res2a_branch2a"
163 | name: "res2a_branch2a_relu"
164 | type: "ReLU"
165 | }
166 |
167 | layer {
168 | bottom: "res2a_branch2a"
169 | top: "res2a_branch2b"
170 | name: "res2a_branch2b"
171 | type: "Convolution"
172 | convolution_param {
173 | num_output: 64
174 | kernel_size: 3
175 | pad: 1
176 | stride: 1
177 | weight_filler {
178 | type: "msra"
179 | }
180 | bias_term: false
181 |
182 | }
183 | }
184 |
185 | layer {
186 | bottom: "res2a_branch2b"
187 | top: "res2a_branch2b"
188 | name: "bn2a_branch2b"
189 | type: "BatchNorm"
190 | batch_norm_param{
191 | use_global_stats: true
192 | }
193 | }
194 |
195 | layer {
196 | bottom: "res2a_branch2b"
197 | top: "res2a_branch2b"
198 | name: "scale2a_branch2b"
199 | type: "Scale"
200 | scale_param {
201 | bias_term: true
202 | }
203 | }
204 |
205 | layer {
206 | bottom: "res2a_branch1"
207 | bottom: "res2a_branch2b"
208 | top: "res2a"
209 | name: "res2a"
210 | type: "Eltwise"
211 | eltwise_param {
212 | operation: SUM
213 | }
214 | }
215 | layer {
216 | bottom: "res2a"
217 | top: "res2a"
218 | name: "res2a_relu"
219 | type: "ReLU"
220 | }
221 |
222 | layer {
223 | bottom: "res2a"
224 | top: "res2b_branch2a"
225 | name: "res2b_branch2a"
226 | type: "Convolution"
227 | convolution_param {
228 | num_output: 64
229 | kernel_size: 3
230 | pad: 1
231 | stride: 1
232 | weight_filler {
233 | type: "msra"
234 | }
235 | bias_term: false
236 |
237 | }
238 | }
239 |
240 | layer {
241 | bottom: "res2b_branch2a"
242 | top: "res2b_branch2a"
243 | name: "bn2b_branch2a"
244 | type: "BatchNorm"
245 | batch_norm_param{
246 | use_global_stats: true
247 | }
248 | }
249 |
250 | layer {
251 | bottom: "res2b_branch2a"
252 | top: "res2b_branch2a"
253 | name: "scale2b_branch2a"
254 | type: "Scale"
255 | scale_param {
256 | bias_term: true
257 | }
258 | }
259 |
260 | layer {
261 | bottom: "res2b_branch2a"
262 | top: "res2b_branch2a"
263 | name: "res2b_branch2a_relu"
264 | type: "ReLU"
265 | }
266 |
267 | layer {
268 | bottom: "res2b_branch2a"
269 | top: "res2b_branch2b"
270 | name: "res2b_branch2b"
271 | type: "Convolution"
272 | convolution_param {
273 | num_output: 64
274 | kernel_size: 3
275 | pad: 1
276 | stride: 1
277 | weight_filler {
278 | type: "msra"
279 | }
280 | bias_term: false
281 |
282 | }
283 | }
284 |
285 | layer {
286 | bottom: "res2b_branch2b"
287 | top: "res2b_branch2b"
288 | name: "bn2b_branch2b"
289 | type: "BatchNorm"
290 | batch_norm_param{
291 | use_global_stats: true
292 | }
293 | }
294 |
295 | layer {
296 | bottom: "res2b_branch2b"
297 | top: "res2b_branch2b"
298 | name: "scale2b_branch2b"
299 | type: "Scale"
300 | scale_param {
301 | bias_term: true
302 | }
303 | }
304 |
305 | layer {
306 | bottom: "res2a"
307 | bottom: "res2b_branch2b"
308 | top: "res2b"
309 | name: "res2b"
310 | type: "Eltwise"
311 | eltwise_param {
312 | operation: SUM
313 | }
314 | }
315 |
316 | layer {
317 | bottom: "res2b"
318 | top: "res2b"
319 | name: "res2b_relu"
320 | type: "ReLU"
321 | }
322 |
323 | layer {
324 | bottom: "res2b"
325 | top: "res3a_branch1"
326 | name: "res3a_branch1"
327 | type: "Convolution"
328 | convolution_param {
329 | num_output: 128
330 | kernel_size: 1
331 | pad: 0
332 | stride: 2
333 | weight_filler {
334 | type: "msra"
335 | }
336 | bias_term: false
337 |
338 | }
339 | }
340 |
341 | layer {
342 | bottom: "res3a_branch1"
343 | top: "res3a_branch1"
344 | name: "bn3a_branch1"
345 | type: "BatchNorm"
346 | batch_norm_param{
347 | use_global_stats: true
348 | }
349 | }
350 |
351 | layer {
352 | bottom: "res3a_branch1"
353 | top: "res3a_branch1"
354 | name: "scale3a_branch1"
355 | type: "Scale"
356 | scale_param {
357 | bias_term: true
358 | }
359 | }
360 |
361 | layer {
362 | bottom: "res2b"
363 | top: "res3a_branch2a"
364 | name: "res3a_branch2a"
365 | type: "Convolution"
366 | convolution_param {
367 | num_output: 128
368 | kernel_size: 3
369 | pad: 1
370 | stride: 2
371 | weight_filler {
372 | type: "msra"
373 | }
374 | bias_term: false
375 |
376 | }
377 | }
378 |
379 | layer {
380 | bottom: "res3a_branch2a"
381 | top: "res3a_branch2a"
382 | name: "bn3a_branch2a"
383 | type: "BatchNorm"
384 | batch_norm_param{
385 | use_global_stats: true
386 | }
387 | }
388 |
389 | layer {
390 | bottom: "res3a_branch2a"
391 | top: "res3a_branch2a"
392 | name: "scale3a_branch2a"
393 | type: "Scale"
394 | scale_param {
395 | bias_term: true
396 | }
397 | }
398 |
399 | layer {
400 | bottom: "res3a_branch2a"
401 | top: "res3a_branch2a"
402 | name: "res3a_branch2a_relu"
403 | type: "ReLU"
404 | }
405 |
406 | layer {
407 | bottom: "res3a_branch2a"
408 | top: "res3a_branch2b"
409 | name: "res3a_branch2b"
410 | type: "Convolution"
411 | convolution_param {
412 | num_output: 128
413 | kernel_size: 3
414 | pad: 1
415 | stride: 1
416 | weight_filler {
417 | type: "msra"
418 | }
419 | bias_term: false
420 |
421 | }
422 | }
423 |
424 | layer {
425 | bottom: "res3a_branch2b"
426 | top: "res3a_branch2b"
427 | name: "bn3a_branch2b"
428 | type: "BatchNorm"
429 | batch_norm_param{
430 | use_global_stats: true
431 | }
432 | }
433 |
434 | layer {
435 | bottom: "res3a_branch2b"
436 | top: "res3a_branch2b"
437 | name: "scale3a_branch2b"
438 | type: "Scale"
439 | scale_param {
440 | bias_term: true
441 | }
442 | }
443 |
444 | layer {
445 | bottom: "res3a_branch1"
446 | bottom: "res3a_branch2b"
447 | top: "res3a"
448 | name: "res3a"
449 | type: "Eltwise"
450 | eltwise_param {
451 | operation: SUM
452 | }
453 | }
454 |
455 | layer {
456 | bottom: "res3a"
457 | top: "res3a"
458 | name: "res3a_relu"
459 | type: "ReLU"
460 | }
461 |
462 | layer {
463 | bottom: "res3a"
464 | top: "res3b_branch2a"
465 | name: "res3b_branch2a"
466 | type: "Convolution"
467 | convolution_param {
468 | num_output: 128
469 | kernel_size: 3
470 | pad: 1
471 | stride: 1
472 | weight_filler {
473 | type: "msra"
474 | }
475 | bias_term: false
476 |
477 | }
478 | }
479 |
480 | layer {
481 | bottom: "res3b_branch2a"
482 | top: "res3b_branch2a"
483 | name: "bn3b_branch2a"
484 | type: "BatchNorm"
485 | batch_norm_param{
486 | use_global_stats: true
487 | }
488 | }
489 |
490 | layer {
491 | bottom: "res3b_branch2a"
492 | top: "res3b_branch2a"
493 | name: "scale3b_branch2a"
494 | type: "Scale"
495 | scale_param {
496 | bias_term: true
497 | }
498 | }
499 |
500 | layer {
501 | bottom: "res3b_branch2a"
502 | top: "res3b_branch2a"
503 | name: "res3b_branch2a_relu"
504 | type: "ReLU"
505 | }
506 |
507 | layer {
508 | bottom: "res3b_branch2a"
509 | top: "res3b_branch2b"
510 | name: "res3b_branch2b"
511 | type: "Convolution"
512 | convolution_param {
513 | num_output: 128
514 | kernel_size: 3
515 | pad: 1
516 | stride: 1
517 | weight_filler {
518 | type: "msra"
519 | }
520 | bias_term: false
521 |
522 | }
523 | }
524 |
525 | layer {
526 | bottom: "res3b_branch2b"
527 | top: "res3b_branch2b"
528 | name: "bn3b_branch2b"
529 | type: "BatchNorm"
530 | batch_norm_param{
531 | use_global_stats: true
532 | }
533 | }
534 |
535 | layer {
536 | bottom: "res3b_branch2b"
537 | top: "res3b_branch2b"
538 | name: "scale3b_branch2b"
539 | type: "Scale"
540 | scale_param {
541 | bias_term: true
542 | }
543 | }
544 |
545 | layer {
546 | bottom: "res3a"
547 | bottom: "res3b_branch2b"
548 | top: "res3b"
549 | name: "res3b"
550 | type: "Eltwise"
551 | eltwise_param {
552 | operation: SUM
553 | }
554 | }
555 |
556 | layer {
557 | bottom: "res3b"
558 | top: "res3b"
559 | name: "res3b_relu"
560 | type: "ReLU"
561 | }
562 |
563 | layer {
564 | bottom: "res3b"
565 | top: "res4a_branch1"
566 | name: "res4a_branch1"
567 | type: "Convolution"
568 | convolution_param {
569 | num_output: 256
570 | kernel_size: 1
571 | pad: 0
572 | stride: 2
573 | weight_filler {
574 | type: "msra"
575 | }
576 | bias_term: false
577 |
578 | }
579 | }
580 |
581 | layer {
582 | bottom: "res4a_branch1"
583 | top: "res4a_branch1"
584 | name: "bn4a_branch1"
585 | type: "BatchNorm"
586 | batch_norm_param{
587 | use_global_stats: true
588 | }
589 | }
590 |
591 | layer {
592 | bottom: "res4a_branch1"
593 | top: "res4a_branch1"
594 | name: "scale4a_branch1"
595 | type: "Scale"
596 | scale_param {
597 | bias_term: true
598 | }
599 | }
600 |
601 | layer {
602 | bottom: "res3b"
603 | top: "res4a_branch2a"
604 | name: "res4a_branch2a"
605 | type: "Convolution"
606 | convolution_param {
607 | num_output: 256
608 | kernel_size: 3
609 | pad: 1
610 | stride: 2
611 | weight_filler {
612 | type: "msra"
613 | }
614 | bias_term: false
615 |
616 | }
617 | }
618 |
619 | layer {
620 | bottom: "res4a_branch2a"
621 | top: "res4a_branch2a"
622 | name: "bn4a_branch2a"
623 | type: "BatchNorm"
624 | batch_norm_param{
625 | use_global_stats: true
626 | }
627 | }
628 |
629 | layer {
630 | bottom: "res4a_branch2a"
631 | top: "res4a_branch2a"
632 | name: "scale4a_branch2a"
633 | type: "Scale"
634 | scale_param {
635 | bias_term: true
636 | }
637 | }
638 |
639 | layer {
640 | bottom: "res4a_branch2a"
641 | top: "res4a_branch2a"
642 | name: "res4a_branch2a_relu"
643 | type: "ReLU"
644 | }
645 |
646 | layer {
647 | bottom: "res4a_branch2a"
648 | top: "res4a_branch2b"
649 | name: "res4a_branch2b"
650 | type: "Convolution"
651 | convolution_param {
652 | num_output: 256
653 | kernel_size: 3
654 | pad: 1
655 | stride: 1
656 | weight_filler {
657 | type: "msra"
658 | }
659 | bias_term: false
660 |
661 | }
662 | }
663 |
664 | layer {
665 | bottom: "res4a_branch2b"
666 | top: "res4a_branch2b"
667 | name: "bn4a_branch2b"
668 | type: "BatchNorm"
669 | batch_norm_param{
670 | use_global_stats: true
671 | }
672 | }
673 |
674 | layer {
675 | bottom: "res4a_branch2b"
676 | top: "res4a_branch2b"
677 | name: "scale4a_branch2b"
678 | type: "Scale"
679 | scale_param {
680 | bias_term: true
681 | }
682 | }
683 |
684 | layer {
685 | bottom: "res4a_branch1"
686 | bottom: "res4a_branch2b"
687 | top: "res4a"
688 | name: "res4a"
689 | type: "Eltwise"
690 | eltwise_param {
691 | operation: SUM
692 | }
693 | }
694 |
695 | layer {
696 | bottom: "res4a"
697 | top: "res4a"
698 | name: "res4a_relu"
699 | type: "ReLU"
700 | }
701 |
702 | layer {
703 | bottom: "res4a"
704 | top: "res4b_branch2a"
705 | name: "res4b_branch2a"
706 | type: "Convolution"
707 | convolution_param {
708 | num_output: 256
709 | kernel_size: 3
710 | pad: 1
711 | stride: 1
712 | weight_filler {
713 | type: "msra"
714 | }
715 | bias_term: false
716 |
717 | }
718 | }
719 |
720 | layer {
721 | bottom: "res4b_branch2a"
722 | top: "res4b_branch2a"
723 | name: "bn4b_branch2a"
724 | type: "BatchNorm"
725 | batch_norm_param{
726 | use_global_stats: true
727 | }
728 | }
729 |
730 | layer {
731 | bottom: "res4b_branch2a"
732 | top: "res4b_branch2a"
733 | name: "scale4b_branch2a"
734 | type: "Scale"
735 | scale_param {
736 | bias_term: true
737 | }
738 | }
739 |
740 | layer {
741 | bottom: "res4b_branch2a"
742 | top: "res4b_branch2a"
743 | name: "res4b_branch2a_relu"
744 | type: "ReLU"
745 | }
746 |
747 | layer {
748 | bottom: "res4b_branch2a"
749 | top: "res4b_branch2b"
750 | name: "res4b_branch2b"
751 | type: "Convolution"
752 | convolution_param {
753 | num_output: 256
754 | kernel_size: 3
755 | pad: 1
756 | stride: 1
757 | weight_filler {
758 | type: "msra"
759 | }
760 | bias_term: false
761 |
762 | }
763 | }
764 |
765 | layer {
766 | bottom: "res4b_branch2b"
767 | top: "res4b_branch2b"
768 | name: "bn4b_branch2b"
769 | type: "BatchNorm"
770 | batch_norm_param{
771 | use_global_stats: true
772 | }
773 | }
774 |
775 | layer {
776 | bottom: "res4b_branch2b"
777 | top: "res4b_branch2b"
778 | name: "scale4b_branch2b"
779 | type: "Scale"
780 | scale_param {
781 | bias_term: true
782 | }
783 | }
784 |
785 | layer {
786 | bottom: "res4a"
787 | bottom: "res4b_branch2b"
788 | top: "res4b"
789 | name: "res4b"
790 | type: "Eltwise"
791 | eltwise_param {
792 | operation: SUM
793 | }
794 | }
795 |
796 | layer {
797 | bottom: "res4b"
798 | top: "res4b"
799 | name: "res4b_relu"
800 | type: "ReLU"
801 | }
802 |
803 | layer {
804 | bottom: "res4b"
805 | top: "res5a_branch1"
806 | name: "res5a_branch1"
807 | type: "Convolution"
808 | convolution_param {
809 | num_output: 384
810 | kernel_size: 1
811 | pad: 0
812 | stride: 2
813 | weight_filler {
814 | type: "msra"
815 | }
816 | bias_term: false
817 |
818 | }
819 | }
820 |
821 | layer {
822 | bottom: "res5a_branch1"
823 | top: "res5a_branch1"
824 | name: "bn5a_branch1"
825 | type: "BatchNorm"
826 | batch_norm_param{
827 | use_global_stats: true
828 | }
829 | }
830 |
831 | layer {
832 | bottom: "res5a_branch1"
833 | top: "res5a_branch1"
834 | name: "scale5a_branch1"
835 | type: "Scale"
836 | scale_param {
837 | bias_term: true
838 | }
839 | }
840 |
841 | layer {
842 | bottom: "res4b"
843 | top: "res5a_branch2a"
844 | name: "res5a_branch2a"
845 | type: "Convolution"
846 | convolution_param {
847 | num_output: 384
848 | kernel_size: 3
849 | pad: 1
850 | stride: 2
851 | weight_filler {
852 | type: "msra"
853 | }
854 | bias_term: false
855 |
856 | }
857 | }
858 |
859 | layer {
860 | bottom: "res5a_branch2a"
861 | top: "res5a_branch2a"
862 | name: "bn5a_branch2a"
863 | type: "BatchNorm"
864 | batch_norm_param{
865 | use_global_stats: true
866 | }
867 | }
868 |
869 | layer {
870 | bottom: "res5a_branch2a"
871 | top: "res5a_branch2a"
872 | name: "scale5a_branch2a"
873 | type: "Scale"
874 | scale_param {
875 | bias_term: true
876 | }
877 | }
878 |
879 | layer {
880 | bottom: "res5a_branch2a"
881 | top: "res5a_branch2a"
882 | name: "res5a_branch2a_relu"
883 | type: "ReLU"
884 | }
885 |
886 | layer {
887 | bottom: "res5a_branch2a"
888 | top: "res5a_branch2b"
889 | name: "res5a_branch2b"
890 | type: "Convolution"
891 | convolution_param {
892 | num_output: 384
893 | kernel_size: 3
894 | pad: 1
895 | stride: 1
896 | weight_filler {
897 | type: "msra"
898 | }
899 | bias_term: false
900 |
901 | }
902 | }
903 |
904 | layer {
905 | bottom: "res5a_branch2b"
906 | top: "res5a_branch2b"
907 | name: "bn5a_branch2b"
908 | type: "BatchNorm"
909 | batch_norm_param{
910 | use_global_stats: true
911 | }
912 | }
913 |
914 | layer {
915 | bottom: "res5a_branch2b"
916 | top: "res5a_branch2b"
917 | name: "scale5a_branch2b"
918 | type: "Scale"
919 | scale_param {
920 | bias_term: true
921 | }
922 | }
923 |
924 | layer {
925 | bottom: "res5a_branch1"
926 | bottom: "res5a_branch2b"
927 | top: "res5a"
928 | name: "res5a"
929 | type: "Eltwise"
930 | eltwise_param {
931 | operation: SUM
932 | }
933 | }
934 |
935 | layer {
936 | bottom: "res5a"
937 | top: "res5a"
938 | name: "res5a_relu"
939 | type: "ReLU"
940 | }
941 |
942 | layer {
943 | bottom: "res5a"
944 | top: "res5b_branch2a"
945 | name: "res5b_branch2a"
946 | type: "Convolution"
947 | convolution_param {
948 | num_output: 384
949 | kernel_size: 3
950 | pad: 1
951 | stride: 1
952 | weight_filler {
953 | type: "msra"
954 | }
955 | bias_term: false
956 |
957 | }
958 | }
959 |
960 | layer {
961 | bottom: "res5b_branch2a"
962 | top: "res5b_branch2a"
963 | name: "bn5b_branch2a"
964 | type: "BatchNorm"
965 | batch_norm_param{
966 | use_global_stats: true
967 | }
968 | }
969 |
970 | layer {
971 | bottom: "res5b_branch2a"
972 | top: "res5b_branch2a"
973 | name: "scale5b_branch2a"
974 | type: "Scale"
975 | scale_param {
976 | bias_term: true
977 | }
978 | }
979 |
980 | layer {
981 | bottom: "res5b_branch2a"
982 | top: "res5b_branch2a"
983 | name: "res5b_branch2a_relu"
984 | type: "ReLU"
985 | }
986 |
987 | layer {
988 | bottom: "res5b_branch2a"
989 | top: "res5b_branch2b"
990 | name: "res5b_branch2b"
991 | type: "Convolution"
992 | convolution_param {
993 | num_output: 384
994 | kernel_size: 3
995 | pad: 1
996 | stride: 1
997 | weight_filler {
998 | type: "msra"
999 | }
1000 | bias_term: false
1001 |
1002 | }
1003 | }
1004 |
1005 | layer {
1006 | bottom: "res5b_branch2b"
1007 | top: "res5b_branch2b"
1008 | name: "bn5b_branch2b"
1009 | type: "BatchNorm"
1010 | batch_norm_param{
1011 | use_global_stats: true
1012 | }
1013 | }
1014 |
1015 | layer {
1016 | bottom: "res5b_branch2b"
1017 | top: "res5b_branch2b"
1018 | name: "scale5b_branch2b"
1019 | type: "Scale"
1020 | scale_param {
1021 | bias_term: true
1022 | }
1023 | }
1024 |
1025 | layer {
1026 | bottom: "res5a"
1027 | bottom: "res5b_branch2b"
1028 | top: "res5b"
1029 | name: "res5b"
1030 | type: "Eltwise"
1031 | eltwise_param {
1032 | operation: SUM
1033 | }
1034 | }
1035 |
1036 | layer {
1037 | bottom: "res5b"
1038 | top: "res5b"
1039 | name: "res5b_relu"
1040 | type: "ReLU"
1041 | }
1042 |
1043 | #########################################
1044 | # pooling层
1045 | #########################################
1046 | layer {
1047 | bottom: "res5b"
1048 | top: "pool5"
1049 | name: "pool5"
1050 | type: "Pooling"
1051 | pooling_param {
1052 | kernel_size: 3
1053 | stride: 1
1054 | pool: AVE
1055 | }
1056 | }
1057 |
1058 | #########################################
1059 | # 全连接层
1060 | #########################################
1061 | layer {
1062 | bottom: "pool5"
1063 | top: "ip_fc"
1064 | name: "ip_fc"
1065 | type: "InnerProduct"
1066 | param {
1067 | lr_mult: 1
1068 | decay_mult: 1
1069 | }
1070 | param {
1071 | lr_mult: 2
1072 | decay_mult: 1
1073 | }
1074 | inner_product_param {
1075 | num_output: 1000
1076 | weight_filler {
1077 | type: "xavier"
1078 | }
1079 | bias_filler {
1080 | type: "constant"
1081 | value: 0
1082 | }
1083 | }
1084 | }
1085 |
1086 |
1087 |
1088 |
1089 |
1090 |
1091 |
1092 | ############################################################################
1093 | #
1094 | # 9个分支进行多标签分类预测
1095 | #
1096 | ############################################################################
1097 | #########################################
1098 | # 车牌号第1位字符
1099 | #########################################
1100 | layer {
1101 | name: "char1"
1102 | type: "InnerProduct"
1103 | bottom: "ip_fc"
1104 | top: "char1"
1105 | param {
1106 | lr_mult: 1
1107 | }
1108 | param {
1109 | lr_mult: 2
1110 | }
1111 | inner_product_param {
1112 | num_output: 33
1113 | weight_filler {
1114 | type: "xavier"
1115 | }
1116 | bias_filler {
1117 | type: "constant"
1118 | }
1119 | }
1120 | }
1121 | layer {
1122 | name: "prob1"
1123 | type: "Softmax"
1124 | bottom: "char1"
1125 | top: "prob1"
1126 | }
1127 | #########################################
1128 | # 车牌号第2位字符
1129 | #########################################
1130 | layer {
1131 | name: "char2"
1132 | type: "InnerProduct"
1133 | bottom: "ip_fc"
1134 | top: "char2"
1135 | param {
1136 | lr_mult: 1
1137 | }
1138 | param {
1139 | lr_mult: 2
1140 | }
1141 | inner_product_param {
1142 | num_output: 34
1143 | weight_filler {
1144 | type: "xavier"
1145 | }
1146 | bias_filler {
1147 | type: "constant"
1148 | }
1149 | }
1150 | }
1151 | layer {
1152 | name: "prob2"
1153 | type: "Softmax"
1154 | bottom: "char2"
1155 | top: "prob2"
1156 | }
1157 | #########################################
1158 | # 车牌号第3位字符
1159 | #########################################
1160 | layer {
1161 | name: "char3"
1162 | type: "InnerProduct"
1163 | bottom: "ip_fc"
1164 | top: "char3"
1165 | param {
1166 | lr_mult: 1
1167 | }
1168 | param {
1169 | lr_mult: 2
1170 | }
1171 | inner_product_param {
1172 | num_output: 34
1173 | weight_filler {
1174 | type: "xavier"
1175 | }
1176 | bias_filler {
1177 | type: "constant"
1178 | }
1179 | }
1180 | }
1181 | layer {
1182 | name: "prob3"
1183 | type: "Softmax"
1184 | bottom: "char3"
1185 | top: "prob3"
1186 | }
1187 | #########################################
1188 | # 车牌号第4位字符
1189 | #########################################
1190 | layer {
1191 | name: "char4"
1192 | type: "InnerProduct"
1193 | bottom: "ip_fc"
1194 | top: "char4"
1195 | param {
1196 | lr_mult: 1
1197 | }
1198 | param {
1199 | lr_mult: 2
1200 | }
1201 | inner_product_param {
1202 | num_output: 34
1203 | weight_filler {
1204 | type: "xavier"
1205 | }
1206 | bias_filler {
1207 | type: "constant"
1208 | }
1209 | }
1210 | }
1211 | layer {
1212 | name: "prob4"
1213 | type: "Softmax"
1214 | bottom: "char4"
1215 | top: "prob4"
1216 | }
1217 | #########################################
1218 | # 车牌号第5位字符
1219 | #########################################
1220 | layer {
1221 | name: "char5"
1222 | type: "InnerProduct"
1223 | bottom: "ip_fc"
1224 | top: "char5"
1225 | param {
1226 | lr_mult: 1
1227 | }
1228 | param {
1229 | lr_mult: 2
1230 | }
1231 | inner_product_param {
1232 | num_output: 34
1233 | weight_filler {
1234 | type: "xavier"
1235 | }
1236 | bias_filler {
1237 | type: "constant"
1238 | }
1239 | }
1240 | }
1241 | layer {
1242 | name: "prob5"
1243 | type: "Softmax"
1244 | bottom: "char5"
1245 | top: "prob5"
1246 | }
1247 | #########################################
1248 | # 车牌号第6位字符
1249 | #########################################
1250 | layer {
1251 | name: "char6"
1252 | type: "InnerProduct"
1253 | bottom: "ip_fc"
1254 | top: "char6"
1255 | param {
1256 | lr_mult: 1
1257 | }
1258 | param {
1259 | lr_mult: 2
1260 | }
1261 | inner_product_param {
1262 | num_output: 34
1263 | weight_filler {
1264 | type: "xavier"
1265 | }
1266 | bias_filler {
1267 | type: "constant"
1268 | }
1269 | }
1270 | }
1271 | layer {
1272 | name: "prob6"
1273 | type: "Softmax"
1274 | bottom: "char6"
1275 | top: "prob6"
1276 | }
1277 | #########################################
1278 | # 车牌号第7位字符
1279 | #########################################
1280 | layer {
1281 | name: "char7"
1282 | type: "InnerProduct"
1283 | bottom: "ip_fc"
1284 | top: "char7"
1285 | param {
1286 | lr_mult: 1
1287 | }
1288 | param {
1289 | lr_mult: 2
1290 | }
1291 | inner_product_param {
1292 | num_output: 41
1293 | weight_filler {
1294 | type: "xavier"
1295 | }
1296 | bias_filler {
1297 | type: "constant"
1298 | }
1299 | }
1300 | }
1301 | layer {
1302 | name: "prob7"
1303 | type: "Softmax"
1304 | bottom: "char7"
1305 | top: "prob7"
1306 | }
1307 | #########################################
1308 | # 车牌号第8位字符
1309 | #########################################
1310 | layer {
1311 | name: "char8"
1312 | type: "InnerProduct"
1313 | bottom: "ip_fc"
1314 | top: "char8"
1315 | param {
1316 | lr_mult: 1
1317 | }
1318 | param {
1319 | lr_mult: 2
1320 | }
1321 | inner_product_param {
1322 | num_output: 12
1323 | weight_filler {
1324 | type: "xavier"
1325 | }
1326 | bias_filler {
1327 | type: "constant"
1328 | }
1329 | }
1330 | }
1331 | layer {
1332 | name: "prob8"
1333 | type: "Softmax"
1334 | bottom: "char8"
1335 | top: "prob8"
1336 | }
1337 | #########################################
1338 | # 车牌号是字符数:7 or 8
1339 | #########################################
1340 | layer {
1341 | name: "char_num"
1342 | type: "InnerProduct"
1343 | bottom: "ip_fc"
1344 | top: "char_num"
1345 | param {
1346 | lr_mult: 1
1347 | }
1348 | param {
1349 | lr_mult: 2
1350 | }
1351 | inner_product_param {
1352 | num_output: 2
1353 | weight_filler {
1354 | type: "xavier"
1355 | }
1356 | bias_filler {
1357 | type: "constant"
1358 | }
1359 | }
1360 | }
1361 | layer {
1362 | name: "char_num_prob"
1363 | type: "Softmax"
1364 | bottom: "char_num"
1365 | top: "char_num_prob"
1366 | }
1367 | #########################################
1368 | # 车牌颜色
1369 | #########################################
1370 | layer {
1371 | name: "plate_color"
1372 | type: "InnerProduct"
1373 | bottom: "ip_fc"
1374 | top: "plate_color"
1375 | param {
1376 | lr_mult: 1
1377 | }
1378 | param {
1379 | lr_mult: 2
1380 | }
1381 | inner_product_param {
1382 | num_output: 6
1383 | weight_filler {
1384 | type: "xavier"
1385 | }
1386 | bias_filler {
1387 | type: "constant"
1388 | }
1389 | }
1390 | }
1391 | layer {
1392 | name: "plate_color_prob"
1393 | type: "Softmax"
1394 | bottom: "plate_color"
1395 | top: "plate_color_prob"
1396 | }
1397 |
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/resnet18/recognition-resnet18-solver.prototxt:
--------------------------------------------------------------------------------
1 | net: "recognition-resnet18-train-test.prototxt"
2 |
3 | # 测试需要加载测试数据,占内存,早期训练先不用
4 | #test_iter: 500 # 90315 / 40 = 2258
5 | #test_interval: 3613 # 722522 / 200 = 3613
6 | #test_initialization: false
7 | display: 200
8 | average_loss: 100
9 |
10 | #type: "RMSProp"
11 | #lr_policy: "fixed"
12 | #base_lr: 0.0001
13 | #rms_decay: 0.98
14 |
15 |
16 | type: "Adam"
17 | momentum: 0.9
18 | momentum2: 0.999
19 |
20 | lr_policy: "multifixed"
21 | stagelr: 0.001
22 | stagelr: 0.0001
23 | stagelr: 0.00001
24 | stagelr: 0.000001
25 | stagelr: 0.0000001
26 | stageiter: 3000
27 | stageiter: 6000
28 | stageiter: 9000
29 | stageiter: 12000
30 | stageiter: 15000
31 | #momentum: 0.9
32 |
33 |
34 |
35 | max_iter: 20000
36 |
37 | weight_decay: 0.0005
38 |
39 | snapshot:3000
40 | snapshot_prefix: "/home/data_160/data1/license_plate/plate_recognition/models/fushi_xin_hechang_xin_hechang_xia/lp_recognization"
41 | solver_mode: GPU
42 | snapshot_format: BINARYPROTO
43 |
44 |
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/resnet18/recognition-resnet18-train-test.prototxt:
--------------------------------------------------------------------------------
1 | name: "license-plate-recognition"
2 | # 输入层,只进行归一化
3 | layer {
4 | name: "input"
5 | type: "Data"
6 | top: "data"
7 | top: "label"
8 | include {
9 | phase: TRAIN
10 | }
11 | transform_param {
12 | scale: 0.00390625
13 | }
14 | data_param {
15 | # /home/data_160/data3/smart_home/xiongxin-yuwei/plate_recognition/new_plate_lmdb/fushi_xin/multi_label_lmdb/all_lmdb/
16 | source: "/home/data_160/data3/smart_home/xiongxin-yuwei/plate_recognition/new_plate_lmdb/fushi_xin/multi_label_lmdb/train_lmdb/"
17 | batch_size: 240
18 | backend: LMDB
19 | }
20 | }
21 | layer {
22 | name: "input"
23 | type: "Data"
24 | top: "data"
25 | top: "label"
26 | include {
27 | phase: TEST
28 | }
29 | transform_param {
30 | scale: 0.00390625
31 | }
32 | data_param {
33 | source: "/home/data_160/data3/smart_home/xiongxin-yuwei/plate_recognition/new_plate_lmdb/fushi_xin/multi_label_lmdb/validate_lmdb/"
34 | batch_size: 40
35 | backend: LMDB
36 | }
37 | }
38 | # 输入标签切割层,切割为10个label,含义见下方loss
39 | layer {
40 | name: "label_slices"
41 | type: "Slice"
42 | bottom: "label"
43 | top: "label_1"
44 | top: "label_2"
45 | top: "label_3"
46 | top: "label_4"
47 | top: "label_5"
48 | top: "label_6"
49 | top: "label_7"
50 | top: "label_8"
51 | top: "label_char_num"
52 | top: "label_plate_color"
53 | slice_param {
54 | axis: 1
55 | slice_point: 1
56 | slice_point: 2
57 | slice_point: 3
58 | slice_point: 4
59 | slice_point: 5
60 | slice_point: 6
61 | slice_point: 7
62 | slice_point: 8
63 | slice_point: 9
64 | }
65 | }
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | ############################################################################
74 | #
75 | # 主要网络结构:conv + 4 * resnet18 building block + pooling + 全连接层
76 | #
77 | ############################################################################
78 | layer {
79 | bottom: "data"
80 | top: "conv1"
81 | name: "conv1"
82 | type: "Convolution"
83 | convolution_param {
84 | num_output: 64
85 | kernel_size: 3
86 | pad: 1
87 | stride: 1
88 | weight_filler {
89 | type: "msra"
90 | }
91 | bias_term: false
92 | }
93 | }
94 |
95 | layer {
96 | bottom: "conv1"
97 | top: "conv1"
98 | name: "bn_conv1"
99 | type: "BatchNorm"
100 | batch_norm_param{
101 | use_global_stats: false
102 | moving_average_fraction: 0.95
103 | }
104 | include {
105 | phase: TRAIN
106 | }
107 | }
108 |
109 | layer {
110 | bottom: "conv1"
111 | top: "conv1"
112 | name: "bn_conv1"
113 | type: "BatchNorm"
114 | batch_norm_param{
115 | use_global_stats: true
116 | }
117 | include {
118 | phase: TEST
119 | }
120 | }
121 |
122 | layer {
123 | bottom: "conv1"
124 | top: "conv1"
125 | name: "scale_conv1"
126 | type: "Scale"
127 | scale_param {
128 | bias_term: true
129 | }
130 | }
131 |
132 | layer {
133 | bottom: "conv1"
134 | top: "conv1"
135 | name: "conv1_relu"
136 | type: "ReLU"
137 | }
138 |
139 | layer {
140 | bottom: "conv1"
141 | top: "pool1"
142 | name: "pool1"
143 | type: "Pooling"
144 | pooling_param {
145 | kernel_size: 3
146 | stride: 2
147 | pool: MAX
148 | }
149 | }
150 |
151 | #########################################
152 | # resnet18的building block * 4
153 | #########################################
154 | layer {
155 | bottom: "pool1"
156 | top: "res2a_branch1"
157 | name: "res2a_branch1"
158 | type: "Convolution"
159 | convolution_param {
160 | num_output: 64
161 | kernel_size: 1
162 | pad: 0
163 | stride: 1
164 | weight_filler {
165 | type: "msra"
166 | }
167 | bias_term: false
168 |
169 | }
170 | }
171 |
172 | layer {
173 | bottom: "res2a_branch1"
174 | top: "res2a_branch1"
175 | name: "bn2a_branch1"
176 | type: "BatchNorm"
177 | batch_norm_param{
178 | use_global_stats: false
179 | moving_average_fraction: 0.95
180 | }
181 | include {
182 | phase: TRAIN
183 | }
184 | }
185 | layer {
186 | bottom: "res2a_branch1"
187 | top: "res2a_branch1"
188 | name: "bn2a_branch1"
189 | type: "BatchNorm"
190 | batch_norm_param{
191 | use_global_stats: true
192 | }
193 | include {
194 | phase: TEST
195 | }
196 | }
197 |
198 | layer {
199 | bottom: "res2a_branch1"
200 | top: "res2a_branch1"
201 | name: "scale2a_branch1"
202 | type: "Scale"
203 | scale_param {
204 | bias_term: true
205 | }
206 | }
207 |
208 | layer {
209 | bottom: "pool1"
210 | top: "res2a_branch2a"
211 | name: "res2a_branch2a"
212 | type: "Convolution"
213 | convolution_param {
214 | num_output: 64
215 | kernel_size: 3
216 | pad: 1
217 | stride: 1
218 | weight_filler {
219 | type: "msra"
220 | }
221 | bias_term: false
222 |
223 | }
224 | }
225 |
226 | layer {
227 | bottom: "res2a_branch2a"
228 | top: "res2a_branch2a"
229 | name: "bn2a_branch2a"
230 | type: "BatchNorm"
231 | batch_norm_param{
232 | use_global_stats: false
233 | moving_average_fraction: 0.95
234 | }
235 | include {
236 | phase: TRAIN
237 | }
238 | }
239 | layer {
240 | bottom: "res2a_branch2a"
241 | top: "res2a_branch2a"
242 | name: "bn2a_branch2a"
243 | type: "BatchNorm"
244 | batch_norm_param{
245 | use_global_stats: true
246 | }
247 | include {
248 | phase: TEST
249 | }
250 | }
251 |
252 | layer {
253 | bottom: "res2a_branch2a"
254 | top: "res2a_branch2a"
255 | name: "scale2a_branch2a"
256 | type: "Scale"
257 | scale_param {
258 | bias_term: true
259 | }
260 | }
261 | layer {
262 | bottom: "res2a_branch2a"
263 | top: "res2a_branch2a"
264 | name: "res2a_branch2a_relu"
265 | type: "ReLU"
266 | }
267 |
268 | layer {
269 | bottom: "res2a_branch2a"
270 | top: "res2a_branch2b"
271 | name: "res2a_branch2b"
272 | type: "Convolution"
273 | convolution_param {
274 | num_output: 64
275 | kernel_size: 3
276 | pad: 1
277 | stride: 1
278 | weight_filler {
279 | type: "msra"
280 | }
281 | bias_term: false
282 |
283 | }
284 | }
285 |
286 | layer {
287 | bottom: "res2a_branch2b"
288 | top: "res2a_branch2b"
289 | name: "bn2a_branch2b"
290 | type: "BatchNorm"
291 | batch_norm_param{
292 | use_global_stats: false
293 | moving_average_fraction: 0.95
294 | }
295 | include {
296 | phase: TRAIN
297 | }
298 | }
299 | layer {
300 | bottom: "res2a_branch2b"
301 | top: "res2a_branch2b"
302 | name: "bn2a_branch2b"
303 | type: "BatchNorm"
304 | batch_norm_param{
305 | use_global_stats: true
306 | }
307 | include {
308 | phase: TEST
309 | }
310 | }
311 |
312 | layer {
313 | bottom: "res2a_branch2b"
314 | top: "res2a_branch2b"
315 | name: "scale2a_branch2b"
316 | type: "Scale"
317 | scale_param {
318 | bias_term: true
319 | }
320 | }
321 |
322 | layer {
323 | bottom: "res2a_branch1"
324 | bottom: "res2a_branch2b"
325 | top: "res2a"
326 | name: "res2a"
327 | type: "Eltwise"
328 | eltwise_param {
329 | operation: SUM
330 | }
331 | }
332 | layer {
333 | bottom: "res2a"
334 | top: "res2a"
335 | name: "res2a_relu"
336 | type: "ReLU"
337 | }
338 |
339 | layer {
340 | bottom: "res2a"
341 | top: "res2b_branch2a"
342 | name: "res2b_branch2a"
343 | type: "Convolution"
344 | convolution_param {
345 | num_output: 64
346 | kernel_size: 3
347 | pad: 1
348 | stride: 1
349 | weight_filler {
350 | type: "msra"
351 | }
352 | bias_term: false
353 |
354 | }
355 | }
356 |
357 | layer {
358 | bottom: "res2b_branch2a"
359 | top: "res2b_branch2a"
360 | name: "bn2b_branch2a"
361 | type: "BatchNorm"
362 | batch_norm_param{
363 | use_global_stats: false
364 | moving_average_fraction: 0.95
365 | }
366 | include {
367 | phase: TRAIN
368 | }
369 | }
370 | layer {
371 | bottom: "res2b_branch2a"
372 | top: "res2b_branch2a"
373 | name: "bn2b_branch2a"
374 | type: "BatchNorm"
375 | batch_norm_param{
376 | use_global_stats: true
377 | }
378 | include {
379 | phase: TEST
380 | }
381 | }
382 |
383 | layer {
384 | bottom: "res2b_branch2a"
385 | top: "res2b_branch2a"
386 | name: "scale2b_branch2a"
387 | type: "Scale"
388 | scale_param {
389 | bias_term: true
390 | }
391 | }
392 |
393 | layer {
394 | bottom: "res2b_branch2a"
395 | top: "res2b_branch2a"
396 | name: "res2b_branch2a_relu"
397 | type: "ReLU"
398 | }
399 |
400 | layer {
401 | bottom: "res2b_branch2a"
402 | top: "res2b_branch2b"
403 | name: "res2b_branch2b"
404 | type: "Convolution"
405 | convolution_param {
406 | num_output: 64
407 | kernel_size: 3
408 | pad: 1
409 | stride: 1
410 | weight_filler {
411 | type: "msra"
412 | }
413 | bias_term: false
414 |
415 | }
416 | }
417 |
418 | layer {
419 | bottom: "res2b_branch2b"
420 | top: "res2b_branch2b"
421 | name: "bn2b_branch2b"
422 | type: "BatchNorm"
423 | batch_norm_param{
424 | use_global_stats: false
425 | moving_average_fraction: 0.95
426 | }
427 | include {
428 | phase: TRAIN
429 | }
430 | }
431 | layer {
432 | bottom: "res2b_branch2b"
433 | top: "res2b_branch2b"
434 | name: "bn2b_branch2b"
435 | type: "BatchNorm"
436 | batch_norm_param{
437 | use_global_stats: true
438 | }
439 | include {
440 | phase: TEST
441 | }
442 | }
443 |
444 | layer {
445 | bottom: "res2b_branch2b"
446 | top: "res2b_branch2b"
447 | name: "scale2b_branch2b"
448 | type: "Scale"
449 | scale_param {
450 | bias_term: true
451 | }
452 | }
453 |
454 | layer {
455 | bottom: "res2a"
456 | bottom: "res2b_branch2b"
457 | top: "res2b"
458 | name: "res2b"
459 | type: "Eltwise"
460 | eltwise_param {
461 | operation: SUM
462 | }
463 | }
464 |
465 | layer {
466 | bottom: "res2b"
467 | top: "res2b"
468 | name: "res2b_relu"
469 | type: "ReLU"
470 | }
471 |
472 | layer {
473 | bottom: "res2b"
474 | top: "res3a_branch1"
475 | name: "res3a_branch1"
476 | type: "Convolution"
477 | convolution_param {
478 | num_output: 128
479 | kernel_size: 1
480 | pad: 0
481 | stride: 2
482 | weight_filler {
483 | type: "msra"
484 | }
485 | bias_term: false
486 |
487 | }
488 | }
489 |
490 | layer {
491 | bottom: "res3a_branch1"
492 | top: "res3a_branch1"
493 | name: "bn3a_branch1"
494 | type: "BatchNorm"
495 | batch_norm_param{
496 | use_global_stats: false
497 | moving_average_fraction: 0.95
498 | }
499 | include {
500 | phase: TRAIN
501 | }
502 | }
503 | layer {
504 | bottom: "res3a_branch1"
505 | top: "res3a_branch1"
506 | name: "bn3a_branch1"
507 | type: "BatchNorm"
508 | batch_norm_param{
509 | use_global_stats: true
510 | }
511 | include {
512 | phase: TEST
513 | }
514 | }
515 |
516 | layer {
517 | bottom: "res3a_branch1"
518 | top: "res3a_branch1"
519 | name: "scale3a_branch1"
520 | type: "Scale"
521 | scale_param {
522 | bias_term: true
523 | }
524 | }
525 |
526 | layer {
527 | bottom: "res2b"
528 | top: "res3a_branch2a"
529 | name: "res3a_branch2a"
530 | type: "Convolution"
531 | convolution_param {
532 | num_output: 128
533 | kernel_size: 3
534 | pad: 1
535 | stride: 2
536 | weight_filler {
537 | type: "msra"
538 | }
539 | bias_term: false
540 |
541 | }
542 | }
543 |
544 | layer {
545 | bottom: "res3a_branch2a"
546 | top: "res3a_branch2a"
547 | name: "bn3a_branch2a"
548 | type: "BatchNorm"
549 | batch_norm_param{
550 | use_global_stats: false
551 | moving_average_fraction: 0.95
552 | }
553 | include {
554 | phase: TRAIN
555 | }
556 | }
557 | layer {
558 | bottom: "res3a_branch2a"
559 | top: "res3a_branch2a"
560 | name: "bn3a_branch2a"
561 | type: "BatchNorm"
562 | batch_norm_param{
563 | use_global_stats: true
564 | }
565 | include {
566 | phase: TEST
567 | }
568 | }
569 |
570 | layer {
571 | bottom: "res3a_branch2a"
572 | top: "res3a_branch2a"
573 | name: "scale3a_branch2a"
574 | type: "Scale"
575 | scale_param {
576 | bias_term: true
577 | }
578 | }
579 |
580 | layer {
581 | bottom: "res3a_branch2a"
582 | top: "res3a_branch2a"
583 | name: "res3a_branch2a_relu"
584 | type: "ReLU"
585 | }
586 |
587 | layer {
588 | bottom: "res3a_branch2a"
589 | top: "res3a_branch2b"
590 | name: "res3a_branch2b"
591 | type: "Convolution"
592 | convolution_param {
593 | num_output: 128
594 | kernel_size: 3
595 | pad: 1
596 | stride: 1
597 | weight_filler {
598 | type: "msra"
599 | }
600 | bias_term: false
601 |
602 | }
603 | }
604 |
605 | layer {
606 | bottom: "res3a_branch2b"
607 | top: "res3a_branch2b"
608 | name: "bn3a_branch2b"
609 | type: "BatchNorm"
610 | batch_norm_param{
611 | use_global_stats: false
612 | moving_average_fraction: 0.95
613 | }
614 | include {
615 | phase: TRAIN
616 | }
617 | }
618 | layer {
619 | bottom: "res3a_branch2b"
620 | top: "res3a_branch2b"
621 | name: "bn3a_branch2b"
622 | type: "BatchNorm"
623 | batch_norm_param{
624 | use_global_stats: true
625 | }
626 | include {
627 | phase: TEST
628 | }
629 | }
630 |
631 | layer {
632 | bottom: "res3a_branch2b"
633 | top: "res3a_branch2b"
634 | name: "scale3a_branch2b"
635 | type: "Scale"
636 | scale_param {
637 | bias_term: true
638 | }
639 | }
640 |
641 | layer {
642 | bottom: "res3a_branch1"
643 | bottom: "res3a_branch2b"
644 | top: "res3a"
645 | name: "res3a"
646 | type: "Eltwise"
647 | eltwise_param {
648 | operation: SUM
649 | }
650 | }
651 |
652 | layer {
653 | bottom: "res3a"
654 | top: "res3a"
655 | name: "res3a_relu"
656 | type: "ReLU"
657 | }
658 |
659 | layer {
660 | bottom: "res3a"
661 | top: "res3b_branch2a"
662 | name: "res3b_branch2a"
663 | type: "Convolution"
664 | convolution_param {
665 | num_output: 128
666 | kernel_size: 3
667 | pad: 1
668 | stride: 1
669 | weight_filler {
670 | type: "msra"
671 | }
672 | bias_term: false
673 |
674 | }
675 | }
676 |
677 | layer {
678 | bottom: "res3b_branch2a"
679 | top: "res3b_branch2a"
680 | name: "bn3b_branch2a"
681 | type: "BatchNorm"
682 | batch_norm_param{
683 | use_global_stats: false
684 | moving_average_fraction: 0.95
685 | }
686 | include {
687 | phase: TRAIN
688 | }
689 | }
690 | layer {
691 | bottom: "res3b_branch2a"
692 | top: "res3b_branch2a"
693 | name: "bn3b_branch2a"
694 | type: "BatchNorm"
695 | batch_norm_param{
696 | use_global_stats: true
697 | }
698 | include {
699 | phase: TEST
700 | }
701 | }
702 |
703 | layer {
704 | bottom: "res3b_branch2a"
705 | top: "res3b_branch2a"
706 | name: "scale3b_branch2a"
707 | type: "Scale"
708 | scale_param {
709 | bias_term: true
710 | }
711 | }
712 |
713 | layer {
714 | bottom: "res3b_branch2a"
715 | top: "res3b_branch2a"
716 | name: "res3b_branch2a_relu"
717 | type: "ReLU"
718 | }
719 |
720 | layer {
721 | bottom: "res3b_branch2a"
722 | top: "res3b_branch2b"
723 | name: "res3b_branch2b"
724 | type: "Convolution"
725 | convolution_param {
726 | num_output: 128
727 | kernel_size: 3
728 | pad: 1
729 | stride: 1
730 | weight_filler {
731 | type: "msra"
732 | }
733 | bias_term: false
734 |
735 | }
736 | }
737 |
738 | layer {
739 | bottom: "res3b_branch2b"
740 | top: "res3b_branch2b"
741 | name: "bn3b_branch2b"
742 | type: "BatchNorm"
743 | batch_norm_param{
744 | use_global_stats: false
745 | moving_average_fraction: 0.95
746 | }
747 | include {
748 | phase: TRAIN
749 | }
750 | }
751 | layer {
752 | bottom: "res3b_branch2b"
753 | top: "res3b_branch2b"
754 | name: "bn3b_branch2b"
755 | type: "BatchNorm"
756 | batch_norm_param{
757 | use_global_stats: true
758 | }
759 | include {
760 | phase: TEST
761 | }
762 | }
763 |
764 | layer {
765 | bottom: "res3b_branch2b"
766 | top: "res3b_branch2b"
767 | name: "scale3b_branch2b"
768 | type: "Scale"
769 | scale_param {
770 | bias_term: true
771 | }
772 | }
773 |
774 | layer {
775 | bottom: "res3a"
776 | bottom: "res3b_branch2b"
777 | top: "res3b"
778 | name: "res3b"
779 | type: "Eltwise"
780 | eltwise_param {
781 | operation: SUM
782 | }
783 | }
784 |
785 | layer {
786 | bottom: "res3b"
787 | top: "res3b"
788 | name: "res3b_relu"
789 | type: "ReLU"
790 | }
791 |
792 | layer {
793 | bottom: "res3b"
794 | top: "res4a_branch1"
795 | name: "res4a_branch1"
796 | type: "Convolution"
797 | convolution_param {
798 | num_output: 256
799 | kernel_size: 1
800 | pad: 0
801 | stride: 2
802 | weight_filler {
803 | type: "msra"
804 | }
805 | bias_term: false
806 |
807 | }
808 | }
809 |
810 | layer {
811 | bottom: "res4a_branch1"
812 | top: "res4a_branch1"
813 | name: "bn4a_branch1"
814 | type: "BatchNorm"
815 | batch_norm_param{
816 | use_global_stats: false
817 | moving_average_fraction: 0.95
818 | }
819 | include {
820 | phase: TRAIN
821 | }
822 | }
823 | layer {
824 | bottom: "res4a_branch1"
825 | top: "res4a_branch1"
826 | name: "bn4a_branch1"
827 | type: "BatchNorm"
828 | batch_norm_param{
829 | use_global_stats: true
830 | }
831 | include {
832 | phase: TEST
833 | }
834 | }
835 |
836 | layer {
837 | bottom: "res4a_branch1"
838 | top: "res4a_branch1"
839 | name: "scale4a_branch1"
840 | type: "Scale"
841 | scale_param {
842 | bias_term: true
843 | }
844 | }
845 |
846 | layer {
847 | bottom: "res3b"
848 | top: "res4a_branch2a"
849 | name: "res4a_branch2a"
850 | type: "Convolution"
851 | convolution_param {
852 | num_output: 256
853 | kernel_size: 3
854 | pad: 1
855 | stride: 2
856 | weight_filler {
857 | type: "msra"
858 | }
859 | bias_term: false
860 |
861 | }
862 | }
863 |
864 | layer {
865 | bottom: "res4a_branch2a"
866 | top: "res4a_branch2a"
867 | name: "bn4a_branch2a"
868 | type: "BatchNorm"
869 | batch_norm_param{
870 | use_global_stats: false
871 | moving_average_fraction: 0.95
872 | }
873 | include {
874 | phase: TRAIN
875 | }
876 | }
877 | layer {
878 | bottom: "res4a_branch2a"
879 | top: "res4a_branch2a"
880 | name: "bn4a_branch2a"
881 | type: "BatchNorm"
882 | batch_norm_param{
883 | use_global_stats: true
884 | }
885 | include {
886 | phase: TEST
887 | }
888 | }
889 |
890 | layer {
891 | bottom: "res4a_branch2a"
892 | top: "res4a_branch2a"
893 | name: "scale4a_branch2a"
894 | type: "Scale"
895 | scale_param {
896 | bias_term: true
897 | }
898 | }
899 |
900 | layer {
901 | bottom: "res4a_branch2a"
902 | top: "res4a_branch2a"
903 | name: "res4a_branch2a_relu"
904 | type: "ReLU"
905 | }
906 |
907 | layer {
908 | bottom: "res4a_branch2a"
909 | top: "res4a_branch2b"
910 | name: "res4a_branch2b"
911 | type: "Convolution"
912 | convolution_param {
913 | num_output: 256
914 | kernel_size: 3
915 | pad: 1
916 | stride: 1
917 | weight_filler {
918 | type: "msra"
919 | }
920 | bias_term: false
921 |
922 | }
923 | }
924 |
925 | layer {
926 | bottom: "res4a_branch2b"
927 | top: "res4a_branch2b"
928 | name: "bn4a_branch2b"
929 | type: "BatchNorm"
930 | batch_norm_param{
931 | use_global_stats: false
932 | moving_average_fraction: 0.95
933 | }
934 | include {
935 | phase: TRAIN
936 | }
937 | }
938 | layer {
939 | bottom: "res4a_branch2b"
940 | top: "res4a_branch2b"
941 | name: "bn4a_branch2b"
942 | type: "BatchNorm"
943 | batch_norm_param{
944 | use_global_stats: true
945 | }
946 | include {
947 | phase: TEST
948 | }
949 | }
950 |
951 | layer {
952 | bottom: "res4a_branch2b"
953 | top: "res4a_branch2b"
954 | name: "scale4a_branch2b"
955 | type: "Scale"
956 | scale_param {
957 | bias_term: true
958 | }
959 | }
960 |
961 | layer {
962 | bottom: "res4a_branch1"
963 | bottom: "res4a_branch2b"
964 | top: "res4a"
965 | name: "res4a"
966 | type: "Eltwise"
967 | eltwise_param {
968 | operation: SUM
969 | }
970 | }
971 |
972 | layer {
973 | bottom: "res4a"
974 | top: "res4a"
975 | name: "res4a_relu"
976 | type: "ReLU"
977 | }
978 |
979 | layer {
980 | bottom: "res4a"
981 | top: "res4b_branch2a"
982 | name: "res4b_branch2a"
983 | type: "Convolution"
984 | convolution_param {
985 | num_output: 256
986 | kernel_size: 3
987 | pad: 1
988 | stride: 1
989 | weight_filler {
990 | type: "msra"
991 | }
992 | bias_term: false
993 |
994 | }
995 | }
996 |
997 | layer {
998 | bottom: "res4b_branch2a"
999 | top: "res4b_branch2a"
1000 | name: "bn4b_branch2a"
1001 | type: "BatchNorm"
1002 | batch_norm_param{
1003 | use_global_stats: false
1004 | moving_average_fraction: 0.95
1005 | }
1006 | include {
1007 | phase: TRAIN
1008 | }
1009 | }
1010 | layer {
1011 | bottom: "res4b_branch2a"
1012 | top: "res4b_branch2a"
1013 | name: "bn4b_branch2a"
1014 | type: "BatchNorm"
1015 | batch_norm_param{
1016 | use_global_stats: true
1017 | }
1018 | include {
1019 | phase: TEST
1020 | }
1021 | }
1022 |
1023 | layer {
1024 | bottom: "res4b_branch2a"
1025 | top: "res4b_branch2a"
1026 | name: "scale4b_branch2a"
1027 | type: "Scale"
1028 | scale_param {
1029 | bias_term: true
1030 | }
1031 | }
1032 |
1033 | layer {
1034 | bottom: "res4b_branch2a"
1035 | top: "res4b_branch2a"
1036 | name: "res4b_branch2a_relu"
1037 | type: "ReLU"
1038 | }
1039 |
1040 | layer {
1041 | bottom: "res4b_branch2a"
1042 | top: "res4b_branch2b"
1043 | name: "res4b_branch2b"
1044 | type: "Convolution"
1045 | convolution_param {
1046 | num_output: 256
1047 | kernel_size: 3
1048 | pad: 1
1049 | stride: 1
1050 | weight_filler {
1051 | type: "msra"
1052 | }
1053 | bias_term: false
1054 |
1055 | }
1056 | }
1057 |
1058 | layer {
1059 | bottom: "res4b_branch2b"
1060 | top: "res4b_branch2b"
1061 | name: "bn4b_branch2b"
1062 | type: "BatchNorm"
1063 | batch_norm_param{
1064 | use_global_stats: false
1065 | moving_average_fraction: 0.95
1066 | }
1067 | include {
1068 | phase: TRAIN
1069 | }
1070 | }
1071 | layer {
1072 | bottom: "res4b_branch2b"
1073 | top: "res4b_branch2b"
1074 | name: "bn4b_branch2b"
1075 | type: "BatchNorm"
1076 | batch_norm_param{
1077 | use_global_stats: true
1078 | }
1079 | include {
1080 | phase: TEST
1081 | }
1082 | }
1083 |
1084 | layer {
1085 | bottom: "res4b_branch2b"
1086 | top: "res4b_branch2b"
1087 | name: "scale4b_branch2b"
1088 | type: "Scale"
1089 | scale_param {
1090 | bias_term: true
1091 | }
1092 | }
1093 |
1094 | layer {
1095 | bottom: "res4a"
1096 | bottom: "res4b_branch2b"
1097 | top: "res4b"
1098 | name: "res4b"
1099 | type: "Eltwise"
1100 | eltwise_param {
1101 | operation: SUM
1102 | }
1103 | }
1104 |
1105 | layer {
1106 | bottom: "res4b"
1107 | top: "res4b"
1108 | name: "res4b_relu"
1109 | type: "ReLU"
1110 | }
1111 |
1112 | layer {
1113 | bottom: "res4b"
1114 | top: "res5a_branch1"
1115 | name: "res5a_branch1"
1116 | type: "Convolution"
1117 | convolution_param {
1118 | num_output: 384
1119 | kernel_size: 1
1120 | pad: 0
1121 | stride: 2
1122 | weight_filler {
1123 | type: "msra"
1124 | }
1125 | bias_term: false
1126 |
1127 | }
1128 | }
1129 |
1130 | layer {
1131 | bottom: "res5a_branch1"
1132 | top: "res5a_branch1"
1133 | name: "bn5a_branch1"
1134 | type: "BatchNorm"
1135 | batch_norm_param{
1136 | use_global_stats: false
1137 | moving_average_fraction: 0.95
1138 | }
1139 | include {
1140 | phase: TRAIN
1141 | }
1142 | }
1143 | layer {
1144 | bottom: "res5a_branch1"
1145 | top: "res5a_branch1"
1146 | name: "bn5a_branch1"
1147 | type: "BatchNorm"
1148 | batch_norm_param{
1149 | use_global_stats: true
1150 | }
1151 | include {
1152 | phase: TEST
1153 | }
1154 | }
1155 |
1156 | layer {
1157 | bottom: "res5a_branch1"
1158 | top: "res5a_branch1"
1159 | name: "scale5a_branch1"
1160 | type: "Scale"
1161 | scale_param {
1162 | bias_term: true
1163 | }
1164 | }
1165 |
1166 | layer {
1167 | bottom: "res4b"
1168 | top: "res5a_branch2a"
1169 | name: "res5a_branch2a"
1170 | type: "Convolution"
1171 | convolution_param {
1172 | num_output: 384
1173 | kernel_size: 3
1174 | pad: 1
1175 | stride: 2
1176 | weight_filler {
1177 | type: "msra"
1178 | }
1179 | bias_term: false
1180 |
1181 | }
1182 | }
1183 |
1184 | layer {
1185 | bottom: "res5a_branch2a"
1186 | top: "res5a_branch2a"
1187 | name: "bn5a_branch2a"
1188 | type: "BatchNorm"
1189 | batch_norm_param{
1190 | use_global_stats: false
1191 | moving_average_fraction: 0.95
1192 | }
1193 | include {
1194 | phase: TRAIN
1195 | }
1196 | }
1197 | layer {
1198 | bottom: "res5a_branch2a"
1199 | top: "res5a_branch2a"
1200 | name: "bn5a_branch2a"
1201 | type: "BatchNorm"
1202 | batch_norm_param{
1203 | use_global_stats: true
1204 | }
1205 | include {
1206 | phase: TEST
1207 | }
1208 | }
1209 |
1210 | layer {
1211 | bottom: "res5a_branch2a"
1212 | top: "res5a_branch2a"
1213 | name: "scale5a_branch2a"
1214 | type: "Scale"
1215 | scale_param {
1216 | bias_term: true
1217 | }
1218 | }
1219 |
1220 | layer {
1221 | bottom: "res5a_branch2a"
1222 | top: "res5a_branch2a"
1223 | name: "res5a_branch2a_relu"
1224 | type: "ReLU"
1225 | }
1226 |
1227 | layer {
1228 | bottom: "res5a_branch2a"
1229 | top: "res5a_branch2b"
1230 | name: "res5a_branch2b"
1231 | type: "Convolution"
1232 | convolution_param {
1233 | num_output: 384
1234 | kernel_size: 3
1235 | pad: 1
1236 | stride: 1
1237 | weight_filler {
1238 | type: "msra"
1239 | }
1240 | bias_term: false
1241 |
1242 | }
1243 | }
1244 |
1245 | layer {
1246 | bottom: "res5a_branch2b"
1247 | top: "res5a_branch2b"
1248 | name: "bn5a_branch2b"
1249 | type: "BatchNorm"
1250 | batch_norm_param{
1251 | use_global_stats: false
1252 | moving_average_fraction: 0.95
1253 | }
1254 | include {
1255 | phase: TRAIN
1256 | }
1257 | }
1258 | layer {
1259 | bottom: "res5a_branch2b"
1260 | top: "res5a_branch2b"
1261 | name: "bn5a_branch2b"
1262 | type: "BatchNorm"
1263 | batch_norm_param{
1264 | use_global_stats: true
1265 | }
1266 | include {
1267 | phase: TEST
1268 | }
1269 | }
1270 |
1271 | layer {
1272 | bottom: "res5a_branch2b"
1273 | top: "res5a_branch2b"
1274 | name: "scale5a_branch2b"
1275 | type: "Scale"
1276 | scale_param {
1277 | bias_term: true
1278 | }
1279 | }
1280 |
1281 | layer {
1282 | bottom: "res5a_branch1"
1283 | bottom: "res5a_branch2b"
1284 | top: "res5a"
1285 | name: "res5a"
1286 | type: "Eltwise"
1287 | eltwise_param {
1288 | operation: SUM
1289 | }
1290 | }
1291 |
1292 | layer {
1293 | bottom: "res5a"
1294 | top: "res5a"
1295 | name: "res5a_relu"
1296 | type: "ReLU"
1297 | }
1298 |
1299 | layer {
1300 | bottom: "res5a"
1301 | top: "res5b_branch2a"
1302 | name: "res5b_branch2a"
1303 | type: "Convolution"
1304 | convolution_param {
1305 | num_output: 384
1306 | kernel_size: 3
1307 | pad: 1
1308 | stride: 1
1309 | weight_filler {
1310 | type: "msra"
1311 | }
1312 | bias_term: false
1313 |
1314 | }
1315 | }
1316 |
1317 | layer {
1318 | bottom: "res5b_branch2a"
1319 | top: "res5b_branch2a"
1320 | name: "bn5b_branch2a"
1321 | type: "BatchNorm"
1322 | batch_norm_param{
1323 | use_global_stats: false
1324 | moving_average_fraction: 0.95
1325 | }
1326 | include {
1327 | phase: TRAIN
1328 | }
1329 | }
1330 | layer {
1331 | bottom: "res5b_branch2a"
1332 | top: "res5b_branch2a"
1333 | name: "bn5b_branch2a"
1334 | type: "BatchNorm"
1335 | batch_norm_param{
1336 | use_global_stats: true
1337 | }
1338 | include {
1339 | phase: TEST
1340 | }
1341 | }
1342 |
1343 | layer {
1344 | bottom: "res5b_branch2a"
1345 | top: "res5b_branch2a"
1346 | name: "scale5b_branch2a"
1347 | type: "Scale"
1348 | scale_param {
1349 | bias_term: true
1350 | }
1351 | }
1352 |
1353 | layer {
1354 | bottom: "res5b_branch2a"
1355 | top: "res5b_branch2a"
1356 | name: "res5b_branch2a_relu"
1357 | type: "ReLU"
1358 | }
1359 |
1360 | layer {
1361 | bottom: "res5b_branch2a"
1362 | top: "res5b_branch2b"
1363 | name: "res5b_branch2b"
1364 | type: "Convolution"
1365 | convolution_param {
1366 | num_output: 384
1367 | kernel_size: 3
1368 | pad: 1
1369 | stride: 1
1370 | weight_filler {
1371 | type: "msra"
1372 | }
1373 | bias_term: false
1374 |
1375 | }
1376 | }
1377 |
1378 | layer {
1379 | bottom: "res5b_branch2b"
1380 | top: "res5b_branch2b"
1381 | name: "bn5b_branch2b"
1382 | type: "BatchNorm"
1383 | batch_norm_param{
1384 | use_global_stats: false
1385 | moving_average_fraction: 0.95
1386 | }
1387 | include {
1388 | phase: TRAIN
1389 | }
1390 | }
1391 | layer {
1392 | bottom: "res5b_branch2b"
1393 | top: "res5b_branch2b"
1394 | name: "bn5b_branch2b"
1395 | type: "BatchNorm"
1396 | batch_norm_param{
1397 | use_global_stats: true
1398 | }
1399 | include {
1400 | phase: TEST
1401 | }
1402 | }
1403 |
1404 | layer {
1405 | bottom: "res5b_branch2b"
1406 | top: "res5b_branch2b"
1407 | name: "scale5b_branch2b"
1408 | type: "Scale"
1409 | scale_param {
1410 | bias_term: true
1411 | }
1412 | }
1413 |
1414 | layer {
1415 | bottom: "res5a"
1416 | bottom: "res5b_branch2b"
1417 | top: "res5b"
1418 | name: "res5b"
1419 | type: "Eltwise"
1420 | eltwise_param {
1421 | operation: SUM
1422 | }
1423 | }
1424 |
1425 | layer {
1426 | bottom: "res5b"
1427 | top: "res5b"
1428 | name: "res5b_relu"
1429 | type: "ReLU"
1430 | }
1431 |
1432 | #########################################
1433 | # pooling层
1434 | #########################################
1435 | layer {
1436 | bottom: "res5b"
1437 | top: "pool5"
1438 | name: "pool5"
1439 | type: "Pooling"
1440 | pooling_param {
1441 | kernel_size: 3
1442 | stride: 1
1443 | pool: AVE
1444 | }
1445 | }
1446 |
1447 | #########################################
1448 | # 全连接层
1449 | #########################################
1450 | layer {
1451 | bottom: "pool5"
1452 | top: "ip_fc"
1453 | name: "ip_fc"
1454 | type: "InnerProduct"
1455 | param {
1456 | lr_mult: 1
1457 | decay_mult: 1
1458 | }
1459 | param {
1460 | lr_mult: 2
1461 | decay_mult: 1
1462 | }
1463 | inner_product_param {
1464 | num_output: 1000
1465 | weight_filler {
1466 | type: "xavier"
1467 | }
1468 | bias_filler {
1469 | type: "constant"
1470 | value: 0
1471 | }
1472 | }
1473 | }
1474 |
1475 |
1476 |
1477 |
1478 |
1479 |
1480 |
1481 | ############################################################################
1482 | #
1483 | # 9个分支进行多标签分类预测
1484 | #
1485 | ############################################################################
1486 | #########################################
1487 | # 车牌号第1位字符
1488 | #########################################
1489 | layer {
1490 | name: "char1"
1491 | type: "InnerProduct"
1492 | bottom: "ip_fc"
1493 | top: "char1"
1494 | param {
1495 | lr_mult: 1
1496 | }
1497 | param {
1498 | lr_mult: 2
1499 | }
1500 | inner_product_param {
1501 | num_output: 33
1502 | weight_filler {
1503 | type: "xavier"
1504 | }
1505 | bias_filler {
1506 | type: "constant"
1507 | }
1508 | }
1509 | }
1510 | layer {
1511 | name: "prob1"
1512 | type: "SoftmaxWithLoss"
1513 | bottom: "char1"
1514 | bottom: "label_1"
1515 | top: "prob1"
1516 | loss_weight: 0.15
1517 | }
1518 | #########################################
1519 | # 车牌号第2位字符
1520 | #########################################
1521 | layer {
1522 | name: "char2"
1523 | type: "InnerProduct"
1524 | bottom: "ip_fc"
1525 | top: "char2"
1526 | param {
1527 | lr_mult: 1
1528 | }
1529 | param {
1530 | lr_mult: 2
1531 | }
1532 | inner_product_param {
1533 | num_output: 34
1534 | weight_filler {
1535 | type: "xavier"
1536 | }
1537 | bias_filler {
1538 | type: "constant"
1539 | }
1540 | }
1541 | }
1542 | layer {
1543 | name: "prob2"
1544 | type: "SoftmaxWithLoss"
1545 | bottom: "char2"
1546 | bottom: "label_2"
1547 | top: "prob2"
1548 | loss_weight: 0.1
1549 | }
1550 | #########################################
1551 | # 车牌号第3位字符
1552 | #########################################
1553 | layer {
1554 | name: "char3"
1555 | type: "InnerProduct"
1556 | bottom: "ip_fc"
1557 | top: "char3"
1558 | param {
1559 | lr_mult: 1
1560 | }
1561 | param {
1562 | lr_mult: 2
1563 | }
1564 | inner_product_param {
1565 | num_output: 34
1566 | weight_filler {
1567 | type: "xavier"
1568 | }
1569 | bias_filler {
1570 | type: "constant"
1571 | }
1572 | }
1573 | }
1574 | layer {
1575 | name: "prob3"
1576 | type: "SoftmaxWithLoss"
1577 | bottom: "char3"
1578 | bottom: "label_3"
1579 | top: "prob3"
1580 | loss_weight: 0.1
1581 | }
1582 | #########################################
1583 | # 车牌号第4位字符
1584 | #########################################
1585 | layer {
1586 | name: "char4"
1587 | type: "InnerProduct"
1588 | bottom: "ip_fc"
1589 | top: "char4"
1590 | param {
1591 | lr_mult: 1
1592 | }
1593 | param {
1594 | lr_mult: 2
1595 | }
1596 | inner_product_param {
1597 | num_output: 34
1598 | weight_filler {
1599 | type: "xavier"
1600 | }
1601 | bias_filler {
1602 | type: "constant"
1603 | }
1604 | }
1605 | }
1606 | layer {
1607 | name: "prob4"
1608 | type: "SoftmaxWithLoss"
1609 | bottom: "char4"
1610 | bottom: "label_4"
1611 | top: "prob4"
1612 | loss_weight: 0.1
1613 | }
1614 | #########################################
1615 | # 车牌号第5位字符
1616 | #########################################
1617 | layer {
1618 | name: "char5"
1619 | type: "InnerProduct"
1620 | bottom: "ip_fc"
1621 | top: "char5"
1622 | param {
1623 | lr_mult: 1
1624 | }
1625 | param {
1626 | lr_mult: 2
1627 | }
1628 | inner_product_param {
1629 | num_output: 34
1630 | weight_filler {
1631 | type: "xavier"
1632 | }
1633 | bias_filler {
1634 | type: "constant"
1635 | }
1636 | }
1637 | }
1638 | layer {
1639 | name: "prob5"
1640 | type: "SoftmaxWithLoss"
1641 | bottom: "char5"
1642 | bottom: "label_5"
1643 | top: "prob5"
1644 | loss_weight: 0.1
1645 | }
1646 | #########################################
1647 | # 车牌号第6位字符
1648 | #########################################
1649 | layer {
1650 | name: "char6"
1651 | type: "InnerProduct"
1652 | bottom: "ip_fc"
1653 | top: "char6"
1654 | param {
1655 | lr_mult: 1
1656 | }
1657 | param {
1658 | lr_mult: 2
1659 | }
1660 | inner_product_param {
1661 | num_output: 34
1662 | weight_filler {
1663 | type: "xavier"
1664 | }
1665 | bias_filler {
1666 | type: "constant"
1667 | }
1668 | }
1669 | }
1670 | layer {
1671 | name: "prob6"
1672 | type: "SoftmaxWithLoss"
1673 | bottom: "char6"
1674 | bottom: "label_6"
1675 | top: "prob6"
1676 | loss_weight: 0.1
1677 | }
1678 | #########################################
1679 | # 车牌号第7位字符
1680 | #########################################
1681 | layer {
1682 | name: "char7"
1683 | type: "InnerProduct"
1684 | bottom: "ip_fc"
1685 | top: "char7"
1686 | param {
1687 | lr_mult: 1
1688 | }
1689 | param {
1690 | lr_mult: 2
1691 | }
1692 | inner_product_param {
1693 | num_output: 41
1694 | weight_filler {
1695 | type: "xavier"
1696 | }
1697 | bias_filler {
1698 | type: "constant"
1699 | }
1700 | }
1701 | }
1702 | layer {
1703 | name: "prob7"
1704 | type: "SoftmaxWithLoss"
1705 | bottom: "char7"
1706 | bottom: "label_7"
1707 | top: "prob7"
1708 | loss_weight: 0.1
1709 | }
1710 | #########################################
1711 | # 车牌号第8位字符
1712 | #########################################
1713 | layer {
1714 | name: "char8"
1715 | type: "InnerProduct"
1716 | bottom: "ip_fc"
1717 | top: "char8"
1718 | param {
1719 | lr_mult: 1
1720 | }
1721 | param {
1722 | lr_mult: 2
1723 | }
1724 | inner_product_param {
1725 | num_output: 12
1726 | weight_filler {
1727 | type: "xavier"
1728 | }
1729 | bias_filler {
1730 | type: "constant"
1731 | }
1732 | }
1733 | }
1734 | layer {
1735 | name: "prob8"
1736 | type: "SoftmaxWithLoss"
1737 | bottom: "char8"
1738 | bottom: "label_8"
1739 | top: "prob8"
1740 | loss_weight: 0.1
1741 | loss_param{
1742 | ignore_label: -1
1743 | }
1744 | }
1745 | #########################################
1746 | # 车牌号是字符数:7 or 8
1747 | #########################################
1748 | layer {
1749 | name: "char_num"
1750 | type: "InnerProduct"
1751 | bottom: "ip_fc"
1752 | top: "char_num"
1753 | param {
1754 | lr_mult: 1
1755 | }
1756 | param {
1757 | lr_mult: 2
1758 | }
1759 | inner_product_param {
1760 | num_output: 2
1761 | weight_filler {
1762 | type: "xavier"
1763 | }
1764 | bias_filler {
1765 | type: "constant"
1766 | }
1767 | }
1768 | }
1769 | layer {
1770 | name: "char_num_prob"
1771 | type: "SoftmaxWithLoss"
1772 | bottom: "char_num"
1773 | bottom: "label_char_num"
1774 | top: "char_num_prob"
1775 | loss_weight: 0.1
1776 | }
1777 |
1778 | #########################################
1779 | # 车牌颜色
1780 | #########################################
1781 | layer {
1782 | name: "plate_color"
1783 | type: "InnerProduct"
1784 | bottom: "ip_fc"
1785 | top: "plate_color"
1786 | param {
1787 | lr_mult: 1
1788 | }
1789 | param {
1790 | lr_mult: 2
1791 | }
1792 | inner_product_param {
1793 | num_output: 6
1794 | weight_filler {
1795 | type: "xavier"
1796 | }
1797 | bias_filler {
1798 | type: "constant"
1799 | }
1800 | }
1801 | }
1802 | layer {
1803 | name: "plate_color_prob"
1804 | type: "SoftmaxWithLoss"
1805 | bottom: "plate_color"
1806 | bottom: "label_plate_color"
1807 | top: "plate_color_prob"
1808 | loss_weight: 0.05
1809 | }
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/resnet18/recognition-resnet18-train.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | CAFFE_HOME=/home/zhengyuwei/software/multi_label_caffe/build/
4 |
5 | SOLVER=./recognition-resnet18-solver.prototxt
6 | WEIGHTS=/home/data_160/data1/license_plate/plate_recognition/models/fushi_xin_resnet18/lp_recognization_iter_10000.solverstate
7 |
8 | $CAFFE_HOME/tools/caffe train --solver=$SOLVER --gpu=0 --snapshot=$WEIGHTS
9 |
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/resnet50/recognition-resnet50-solver.prototxt:
--------------------------------------------------------------------------------
1 | net: "recognition-resnet50-train-test.prototxt"
2 |
3 | # 测试需要加载测试数据,占内存,早期训练先不用
4 | test_iter: 1000 # 90315 / 10 = 9031
5 | test_interval: 18064 # 722522 / 40 = 18064
6 | test_initialization: false
7 | display: 200
8 | average_loss: 100
9 |
10 | #type: "RMSProp"
11 | #lr_policy: "fixed"
12 | #base_lr: 0.0001
13 | #rms_decay: 0.98
14 |
15 |
16 | type: "Adam"
17 | momentum: 0.9
18 | momentum2: 0.999
19 |
20 | lr_policy: "multifixed"
21 | stagelr: 0.001
22 | stagelr: 0.0001
23 | stagelr: 0.00001
24 | stagelr: 0.000001
25 | stagelr: 0.0000001
26 | stageiter: 3000
27 | stageiter: 6000
28 | stageiter: 9000
29 | stageiter: 12000
30 | stageiter: 15000
31 | #momentum: 0.9
32 |
33 |
34 |
35 |
36 | max_iter: 20000
37 |
38 | weight_decay: 0.00005
39 |
40 | snapshot:1000
41 | snapshot_prefix: "/home/data_160/data3/smart_home/xiongxin-yuwei/plate_recognition/models/resnet50/lp_recognization"
42 | solver_mode: GPU
43 | snapshot_format: BINARYPROTO
44 |
45 |
--------------------------------------------------------------------------------
/plate-recognition-models/multi-label-classification/caffe/resnet50/recognition-resnet50-train.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | CAFFE_HOME=/home/zhengyuwei/software/multi_label_caffe/build/
4 |
5 | SOLVER=./recognition-resnet50-solver.prototxt
6 | WEIGHTS=/home/data_160/data3/smart_home/xiongxin-yuwei/plate_recognition/models/resnet50/lp_recognization_iter_10000.caffemodel
7 |
8 | $CAFFE_HOME/tools/caffe train --solver=$SOLVER --gpu=3 #--weights=$WEIGHTS
9 |
--------------------------------------------------------------------------------
/plate_images/single_blue/00_甘A0W9U9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/00_甘A0W9U9.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/00_皖JP7Z46.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/00_皖JP7Z46.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/01_渝R6P85G.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/01_渝R6P85G.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/01_青AY1G55.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/01_青AY1G55.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/02_浙X4DZ51.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/02_浙X4DZ51.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/02_蒙XX83H0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/02_蒙XX83H0.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/03_皖C2HW16.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/03_皖C2HW16.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/03_蒙NLP471.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/03_蒙NLP471.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/04_皖D785JQ.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/04_皖D785JQ.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/04_藏H54HU0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/04_藏H54HU0.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/05_京X48LL5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/05_京X48LL5.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/05_桂UP03K2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/05_桂UP03K2.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/06_渝W63CD0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/06_渝W63CD0.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/06_鄂U60RJ1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/06_鄂U60RJ1.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/07_蒙U17CL7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/07_蒙U17CL7.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/07_赣S8Q147.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/07_赣S8Q147.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/08_琼XFN464.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/08_琼XFN464.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/08_闽B99EB1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/08_闽B99EB1.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/09_甘YJ5A31.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/09_甘YJ5A31.jpg
--------------------------------------------------------------------------------
/plate_images/single_blue/09_苏JA147V.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_blue/09_苏JA147V.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/00_粤YT06R0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/00_粤YT06R0.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/00_赣UV0B03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/00_赣UV0B03.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/01_宁Y6T4E9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/01_宁Y6T4E9.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/01_豫WKB412.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/01_豫WKB412.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/02_粤F7F635.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/02_粤F7F635.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/02_豫B9J2Z0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/02_豫B9J2Z0.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/03_藏F11LD1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/03_藏F11LD1.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/03_贵PKT044.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/03_贵PKT044.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/04_京F2T25S.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/04_京F2T25S.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/04_晋NX84E5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/04_晋NX84E5.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/05_吉V14Q9Q.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/05_吉V14Q9Q.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/05_辽A48GP6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/05_辽A48GP6.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/06_宁M2L6V8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/06_宁M2L6V8.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/06_晋E146LP.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/06_晋E146LP.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/07_川M41A9V.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/07_川M41A9V.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/07_琼S4P85Y.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/07_琼S4P85Y.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/08_粤B87S2V.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/08_粤B87S2V.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/08_陕F54ZW9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/08_陕F54ZW9.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/09_冀FPZ908.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/09_冀FPZ908.jpg
--------------------------------------------------------------------------------
/plate_images/single_yellow/09_吉P5DU24.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/single_yellow/09_吉P5DU24.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/00_云HD40984.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/00_云HD40984.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/00_鲁CF23225.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/00_鲁CF23225.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/01_豫QD96106.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/01_豫QD96106.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/01_青BFA1001.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/01_青BFA1001.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/02_苏KD38100.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/02_苏KD38100.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/02_闽ED96706.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/02_闽ED96706.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/03_青AFV2900.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/03_青AFV2900.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/03_黑QDE9515.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/03_黑QDE9515.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/04_晋KFA4659.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/04_晋KFA4659.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/04_琼BFA4418.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/04_琼BFA4418.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/05_桂FFQ8217.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/05_桂FFQ8217.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/05_甘XDG6119.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/05_甘XDG6119.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/06_云YDR7996.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/06_云YDR7996.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/06_辽QF15431.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/06_辽QF15431.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/07_桂CDQ1150.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/07_桂CDQ1150.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/07_黑VD15418.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/07_黑VD15418.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/08_宁YF71827.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/08_宁YF71827.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/08_新NDZ8091.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/08_新NDZ8091.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/09_吉XDF3229.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/09_吉XDF3229.jpg
--------------------------------------------------------------------------------
/plate_images/small_new_energy/09_津MDW4893.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zheng-yuwei/license-plate-generator/7600d36edd09e8e57aa8a5d935c6a4ed973118fa/plate_images/small_new_energy/09_津MDW4893.jpg
--------------------------------------------------------------------------------