├── .gitattributes
├── .idea
├── Visdom.py
├── misc.xml
├── modules.xml
├── workspace.xml
└── 验证码识别.iml
├── README.md
├── Visdom.py
├── __pycache__
├── Visdom.cpython-36.pyc
├── Visdom.cpython-37.pyc
├── dataset.cpython-36.pyc
├── dataset.cpython-37.pyc
├── model.cpython-36.pyc
├── model.cpython-37.pyc
├── parameters.cpython-36.pyc
├── parameters.cpython-37.pyc
├── train.cpython-36.pyc
└── train.cpython-37.pyc
├── dataset.py
├── generate_captcha.py
├── image
├── 2019-2-24-1.jpg
├── 2019-2-24-2.jpg
└── 2019-2-24-3.jpg
├── main.py
├── model.py
├── parameters.py
├── result.txt
├── train.py
├── try.py
├── userTest.py
└── userTest
├── 03Dy.jpg
├── 0Up4.jpg
├── 1N3H.jpg
├── 1q6I.jpg
├── 21qi.jpg
├── 25ou.jpg
├── 2Q5Z.jpg
├── 2V0V.jpg
├── 2isH.jpg
├── 369y.jpg
├── 37mN.jpg
├── 3C7o.jpg
├── 3v1s.jpg
├── 40EF.jpg
├── 424J.jpg
├── 4H0M.jpg
├── 4r22.jpg
├── 51SS.jpg
├── 5TT7.jpg
├── 6Ebr.jpg
├── 6SoF.jpg
├── 6wrC.jpg
├── 73Mn.jpg
├── 7K49.jpg
├── 7lCo.jpg
├── 8Qnf.jpg
├── 8g65.jpg
├── 90za.jpg
├── 98Z6.jpg
├── 99Y1.jpg
├── 9IWI.jpg
├── 9Q7C.jpg
├── 9U68.jpg
├── 9hT8.jpg
├── 9v3k.jpg
├── AD3L.jpg
├── AUsx.jpg
├── AfDA.jpg
├── Al2e.jpg
├── B3Zw.jpg
├── EB4y.jpg
├── EJ6I.jpg
├── FPV3.jpg
├── FyTd.jpg
├── HIXA.jpg
├── I4lc.jpg
├── Jl8U.jpg
├── L48g.jpg
├── LVY8.jpg
├── MMX7.jpg
├── Ma8b.jpg
├── N8jq.jpg
├── NKkP.jpg
├── Nd0w.jpg
├── QPt5.jpg
├── R63h.jpg
├── R69f.jpg
├── UcKh.jpg
├── UebN.jpg
├── Vj0l.jpg
├── VqjQ.jpg
├── W8w5.jpg
├── Y9eR.jpg
├── YCoh.jpg
├── Yhr7.jpg
├── YuPd.jpg
├── Z0tv.jpg
├── ZEEk.jpg
├── ZMwH.jpg
├── bD4z.jpg
├── bubr.jpg
├── d5cn.jpg
├── dc1g.jpg
├── f05t.jpg
├── fY5e.jpg
├── g186.jpg
├── gNDs.jpg
├── gnL3.jpg
├── h5xA.jpg
├── hP33.jpg
├── j85X.jpg
├── jIn8.jpg
├── k63p.jpg
├── kf2m.jpg
├── lA7T.jpg
├── lfRO.jpg
├── lh06.jpg
├── noWT.jpg
├── nv37.jpg
├── u5gf.jpg
├── uJY1.jpg
├── urwM.jpg
├── v5b6.jpg
├── vCO5.jpg
├── vZ88.jpg
├── w7Nx.jpg
├── yECc.jpg
├── yU32.jpg
├── yt0J.jpg
└── z259.jpg
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.idea/Visdom.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/.idea/Visdom.py
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.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 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
117 |
118 |
119 |
120 | int
121 | 248
122 | 4
123 | 1
124 | testSize
125 | print
126 | norm
127 | bat
128 |
129 |
130 | int
131 | chr
132 | tensorLength
133 | charLength
134 | batchSize
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | true
158 | DEFINITION_ORDER
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 | 1548406601162
318 |
319 |
320 | 1548406601162
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 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
--------------------------------------------------------------------------------
/.idea/验证码识别.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pytorch实现验证码识别
2 |
3 | ### 前言
4 |
5 | 这几天主要在熟悉pyTorch,俗话说:“人生苦短,我用pyTorch”,在从TensorFlow转到pytorch之后,除了“爽”以外,我实在找不到其他形容词,简洁的语法,明了的封装,加上大大降低的debug难度,我从此入了pyTorch的坑。
6 |
7 | 为了熟悉pyTorch,我最近做了几个小项目,今天分享给大家的是一个非常有用的入门级项目——验证码识别。
8 |
9 |
10 |
11 | ### 前期准备
12 |
13 | - core i7 的笔记本
14 | - 一个 GTX 1080ti 的显卡
15 | - 装上pytorch的cpu和GPU版本
16 |
17 |
18 |
19 | ### 项目目的
20 |
21 | 使用pytorch训练一个深度学习的模型来实现验证码的自动识别,其中验证码由python包cpatcha生成,其样子如下:
22 |
23 | 
24 |
25 | 可以看出,该验证码识别难度较大,扭曲较为严重,如果能在该数据集上实现较高的识别率,那么其他简单的数字+字母的验证码不在话下。
26 |
27 |
28 |
29 | ### 数据生成
30 |
31 | 我使用captcha生成了训练集和测试集,其中训练集包含大约200万张图片,测试集包含一万张图片,生成代码如下:
32 |
33 | ```python
34 | def get_string():
35 | string = ""
36 | for i in range(4):
37 | select = rd.randint(1, 3)
38 | if select == 1:
39 | index = rd.randint(0, 9)
40 | string += nums[index]
41 | elif select == 2:
42 | index = rd.randint(0, 25)
43 | string += lower_char[index]
44 | else:
45 | index = rd.randint(0, 25)
46 | string += upper_char[index]
47 | return string
48 |
49 |
50 | def get_captcha(num, path):
51 | font_sizes = [x for x in range(40, 45)]
52 | for i in range(num):
53 | print(i)
54 | imc = ImageCaptcha(get_width(), get_height(), font_sizes=font_sizes)
55 | name = get_string()
56 | image = imc.generate_image(name)
57 | image.save(path + name + ".jpg")
58 |
59 |
60 | if __name__ == '__main__':
61 | get_captcha(900000, "../data/captcha/train/")
62 | ```
63 |
64 |
65 |
66 | ### 网络定义
67 |
68 | 网络前部是卷积与池化层,网络中部是全连接层,网络最后为四个全连接层,得到四个输出,分别对应验证码中的四个数字,其定义如下:
69 |
70 | ```python
71 | class CaptchaNet(nn.Module):
72 | def __init__(self):
73 | super(CaptchaNet, self).__init__()
74 | self.conv1 = nn.Conv2d(3, 5, 5)
75 | self.conv2 = nn.Conv2d(5, 10, 5)
76 | self.conv3 = nn.Conv2d(10, 16, 6)
77 | self.fc1 = nn.Linear(4 * 12 * 16, 512)
78 | self.fc2 = nn.Linear(512, 256)
79 | self.fc3 = nn.Linear(256, 128)
80 | # 这是四个用于输出四个字符的线性层
81 | self.fc41 = nn.Linear(128, 62)
82 | self.fc42 = nn.Linear(128, 62)
83 | self.fc43 = nn.Linear(128, 62)
84 | self.fc44 = nn.Linear(128, 62)
85 |
86 | def forward(self, x):
87 | # 输入为3*128*64,经过第一层为5*62*30
88 | x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
89 | # 输出形状10*29*13
90 | x = F.max_pool2d(F.relu(self.conv2(x)), (2, 2))
91 | # 输出形状16*12*4
92 | x = F.max_pool2d(F.relu(self.conv3(x)), (2, 2))
93 | # print(x.size())
94 | x = x.view(-1, 768)
95 | x = self.fc1(x)
96 | x = F.relu(x)
97 | x = self.fc2(x)
98 | x = F.relu(x)
99 | x = self.fc3(x)
100 | x = F.relu(x)
101 | x1 = self.fc41(x)
102 | x2 = self.fc42(x)
103 | x3 = self.fc43(x)
104 | x4 = self.fc44(x)
105 | return x1, x2, x3, x4
106 | ```
107 |
108 | 后来使用ResNet进行改进模型,其网络结构如下
109 |
110 | ```python
111 | class ResidualBlock(nn.Module):
112 | def __init__(self, inchannel, outchannel, stride=1):
113 | super(ResidualBlock, self).__init__()
114 | self.left = nn.Sequential(
115 | nn.Conv2d(inchannel, outchannel, kernel_size=3, stride=stride, padding=1, bias=False),
116 | nn.BatchNorm2d(outchannel, track_running_stats=True),
117 | nn.ReLU(inplace=True),
118 | nn.Conv2d(outchannel, outchannel, kernel_size=3, stride=1, padding=1, bias=False),
119 | nn.BatchNorm2d(outchannel, track_running_stats=True)
120 | )
121 | self.shortcut = nn.Sequential()
122 | if stride != 1 or inchannel != outchannel:
123 | self.shortcut = nn.Sequential(
124 | nn.Conv2d(inchannel, outchannel, kernel_size=1, stride=stride, bias=False),
125 | nn.BatchNorm2d(outchannel, track_running_stats=True)
126 | )
127 |
128 | def forward(self, x):
129 | out = self.left(x)
130 | out += self.shortcut(x)
131 | out = F.relu(out)
132 | return out
133 |
134 |
135 | class ResNet(nn.Module):
136 | def __init__(self, ResidualBlock, num_classes=62):
137 | super(ResNet, self).__init__()
138 | self.inchannel = 64
139 | self.conv1 = nn.Sequential(
140 | nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False),
141 | nn.BatchNorm2d(64, track_running_stats=True),
142 | nn.ReLU(),
143 | )
144 | self.layer1 = self.make_layer(ResidualBlock, 64, 2, stride=1)
145 | self.layer2 = self.make_layer(ResidualBlock, 128, 2, stride=2)
146 | self.layer3 = self.make_layer(ResidualBlock, 256, 2, stride=2)
147 | self.layer4 = self.make_layer(ResidualBlock, 512, 2, stride=2)
148 | self.fc1 = nn.Linear(512, num_classes)
149 | self.fc2 = nn.Linear(512, num_classes)
150 | self.fc3 = nn.Linear(512, num_classes)
151 | self.fc4 = nn.Linear(512, num_classes)
152 |
153 | def make_layer(self, block, channels, num_blocks, stride):
154 | strides = [stride] + [1] * (num_blocks - 1) # strides=[1,1]
155 | layers = []
156 | for stride in strides:
157 | layers.append(block(self.inchannel, channels, stride))
158 | self.inchannel = channels
159 | return nn.Sequential(*layers)
160 |
161 | def forward(self, x):
162 | x = self.conv1(x)
163 | x = self.layer1(x)
164 | x = self.layer2(x)
165 | x = self.layer3(x)
166 | x = self.layer4(x)
167 | x = F.avg_pool2d(x, 4)
168 | x = x.view(-1, 512)
169 | y1 = self.fc1(x)
170 | y2 = self.fc2(x)
171 | y3 = self.fc3(x)
172 | y4 = self.fc4(x)
173 | return y1, y2, y3, y4
174 | ```
175 |
176 | 在ResNet下,正确率可以超过90%。
177 |
178 |
179 |
180 | ### 训练结果
181 |
182 | 在20万张图片训练情况下,可以达到35%的准确率。
183 |
184 | 在200万张图片训练情况下,可以达到55%——60%的准确率。
185 |
186 | 如果继续加深网络层数,以及扩展训练集数目,根据估算,在1000万训练集情况下,可以达到90%以上的准确率。
187 |
188 | 
189 |
190 |
191 |
192 | ### 测试
193 |
194 | 手写一个100张图片的数据集进行测试,可以发现如下规律:
195 |
196 | 
197 |
198 | - 确实可以达到近50%的准确率,对于这种较为难以辨认的验证码而言,效果已经不错
199 | - 错误很多都是较为相近的字母或者数字,例如
200 | - s -> 5
201 | - o -> 0
202 | - E -> B
203 |
204 |
205 |
206 | ### 使用方法
207 |
208 | - python main.py 可以对模型进行训练
209 | - python userTest.py 可以对userTest文件下下的图片进行辨认
210 |
211 | - python generate_captcha.py 可以生成验证码
--------------------------------------------------------------------------------
/Visdom.py:
--------------------------------------------------------------------------------
1 | import visdom
2 | import time
3 | import numpy as np
4 |
5 |
6 | class Visualizer(object):
7 | def __init__(self, env='default', **kwargs):
8 | self.vis = visdom.Visdom(env=env, **kwargs)
9 | self.index = {}
10 |
11 | def plot_many_stack(self, d):
12 | '''
13 | self.plot('loss',1.00)
14 | '''
15 | name = list(d.keys())
16 | name_total = " ".join(name)
17 | x = self.index.get(name_total, 0)
18 | val = list(d.values())
19 | if len(val) == 1:
20 | y = np.array(val)
21 | else:
22 | y = np.array(val).reshape(-1, len(val))
23 | # print(x)
24 | self.vis.line(Y=y, X=np.ones(y.shape) * x,
25 | win=str(name_total), # unicode
26 | opts=dict(legend=name,
27 | title=name_total),
28 | update=None if x == 0 else 'append'
29 | )
30 | self.index[name_total] = x + 1
--------------------------------------------------------------------------------
/__pycache__/Visdom.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/__pycache__/Visdom.cpython-36.pyc
--------------------------------------------------------------------------------
/__pycache__/Visdom.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/__pycache__/Visdom.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/dataset.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/__pycache__/dataset.cpython-36.pyc
--------------------------------------------------------------------------------
/__pycache__/dataset.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/__pycache__/dataset.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/model.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/__pycache__/model.cpython-36.pyc
--------------------------------------------------------------------------------
/__pycache__/model.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/__pycache__/model.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/parameters.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/__pycache__/parameters.cpython-36.pyc
--------------------------------------------------------------------------------
/__pycache__/parameters.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/__pycache__/parameters.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/train.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/__pycache__/train.cpython-36.pyc
--------------------------------------------------------------------------------
/__pycache__/train.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/__pycache__/train.cpython-37.pyc
--------------------------------------------------------------------------------
/dataset.py:
--------------------------------------------------------------------------------
1 | import os
2 | from PIL import Image
3 | from torch.utils import data
4 | import numpy as np
5 | from torchvision import transforms as T
6 | from parameters import *
7 | import torch as t
8 |
9 | nums = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
10 | lower_char = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
11 | 'v', 'w', 'x', 'y', 'z']
12 | upper_char = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
13 | 'V', 'W', 'X', 'Y', 'Z']
14 |
15 |
16 | def StrtoLabel(Str):
17 | # print(Str)
18 | label = []
19 | for i in range(0, charNumber):
20 | if Str[i] >= '0' and Str[i] <= '9':
21 | label.append(ord(Str[i]) - ord('0'))
22 | elif Str[i] >= 'a' and Str[i] <= 'z':
23 | label.append(ord(Str[i]) - ord('a') + 10)
24 | else:
25 | label.append(ord(Str[i]) - ord('A') + 36)
26 | return label
27 |
28 |
29 | def LabeltoStr(Label):
30 | Str = ""
31 | for i in Label:
32 | if i <= 9:
33 | Str += chr(ord('0') + i)
34 | elif i <= 35:
35 | Str += chr(ord('a') + i - 10)
36 | else:
37 | Str += chr(ord('A') + i - 36)
38 | return Str
39 |
40 |
41 | class Captcha(data.Dataset):
42 | def __init__(self, root, train=True):
43 | self.imgsPath = [os.path.join(root, img) for img in os.listdir(root)]
44 | self.transform = T.Compose([
45 | T.Resize((ImageHeight, ImageWidth)),
46 | T.ToTensor(),
47 | T.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
48 | ])
49 |
50 | def __getitem__(self, index):
51 | imgPath = self.imgsPath[index]
52 | # print(imgPath)
53 | label = imgPath.split("/")[-1].split(".")[0]
54 | # print(label)
55 | labelTensor = t.Tensor(StrtoLabel(label))
56 | data = Image.open(imgPath)
57 | # print(data.size)
58 | data = self.transform(data)
59 | # print(data.shape)
60 | return data, labelTensor
61 |
62 | def __len__(self):
63 | return len(self.imgsPath)
64 |
65 |
66 | if __name__ == '__main__':
67 | trainDataset = Captcha(trainRoot, train=True)
68 | # print(trainDataset.__getitem__(1000))
69 | # data = Image.open("./训练数据集\\ZzN3.jpg")
70 | # data.show()
71 | # trainDataset.__getitem__(4224)
72 | # labelTensor = t.zeros(tensorLength)
73 | labelTensor = StrtoLabel("34Tt")
74 | print(labelTensor)
75 | print(LabeltoStr(labelTensor))
76 |
--------------------------------------------------------------------------------
/generate_captcha.py:
--------------------------------------------------------------------------------
1 | from captcha.image import ImageCaptcha
2 | import random as rd
3 |
4 | # 该文件用于随机生成大量的验证码
5 | nums = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
6 | lower_char = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
7 | 'v', 'w', 'x', 'y', 'z']
8 | upper_char = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
9 | 'V', 'W', 'X', 'Y', 'Z']
10 |
11 |
12 | def get_width():
13 | return int(100 + 40 * rd.random())
14 |
15 |
16 | def get_height():
17 | return int(45 + 20 * rd.random())
18 |
19 |
20 | def get_string():
21 | string = ""
22 | for i in range(4):
23 | select = rd.randint(1, 3)
24 | if select == 1:
25 | index = rd.randint(0, 9)
26 | string += nums[index]
27 | elif select == 2:
28 | index = rd.randint(0, 25)
29 | string += lower_char[index]
30 | else:
31 | index = rd.randint(0, 25)
32 | string += upper_char[index]
33 | return string
34 |
35 |
36 | def get_captcha(num, path):
37 | font_sizes = [x for x in range(40, 45)]
38 | for i in range(num):
39 | print(i)
40 | imc = ImageCaptcha(get_width(), get_height(), font_sizes=font_sizes)
41 | name = get_string()
42 | image = imc.generate_image(name)
43 | image.save(path + name + ".jpg")
44 |
45 |
46 | if __name__ == '__main__':
47 | get_captcha(900, "./userTest/")
48 |
--------------------------------------------------------------------------------
/image/2019-2-24-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/image/2019-2-24-1.jpg
--------------------------------------------------------------------------------
/image/2019-2-24-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/image/2019-2-24-2.jpg
--------------------------------------------------------------------------------
/image/2019-2-24-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/image/2019-2-24-3.jpg
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | from parameters import *
2 | from model import *
3 | from train import *
4 |
5 | if __name__ == '__main__':
6 | net = ResNet(ResidualBlock)
7 | net.loadIfExist()
8 | # print(net.named_parameters())
9 | train(net)
10 |
--------------------------------------------------------------------------------
/model.py:
--------------------------------------------------------------------------------
1 | from parameters import *
2 | import torch as t
3 | from torch import nn
4 | import torch.nn.functional as F
5 | import os
6 |
7 |
8 | class ResidualBlock(nn.Module):
9 | def __init__(self, inchannel, outchannel, stride=1):
10 | super(ResidualBlock, self).__init__()
11 | self.left = nn.Sequential(
12 | nn.Conv2d(inchannel, outchannel, kernel_size=3, stride=stride, padding=1, bias=False),
13 | nn.BatchNorm2d(outchannel, track_running_stats=True),
14 | nn.ReLU(inplace=True),
15 | nn.Conv2d(outchannel, outchannel, kernel_size=3, stride=1, padding=1, bias=False),
16 | nn.BatchNorm2d(outchannel, track_running_stats=True)
17 | )
18 | self.shortcut = nn.Sequential()
19 | if stride != 1 or inchannel != outchannel:
20 | self.shortcut = nn.Sequential(
21 | nn.Conv2d(inchannel, outchannel, kernel_size=1, stride=stride, bias=False),
22 | nn.BatchNorm2d(outchannel, track_running_stats=True)
23 | )
24 |
25 | def forward(self, x):
26 | out = self.left(x)
27 | out += self.shortcut(x)
28 | out = F.relu(out)
29 | return out
30 |
31 |
32 | class ResNet(nn.Module):
33 | def __init__(self, ResidualBlock, num_classes=62):
34 | super(ResNet, self).__init__()
35 | self.inchannel = 64
36 | self.conv1 = nn.Sequential(
37 | nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False),
38 | nn.BatchNorm2d(64, track_running_stats=True),
39 | nn.ReLU(),
40 | )
41 | self.layer1 = self.make_layer(ResidualBlock, 64, 2, stride=1)
42 | self.layer2 = self.make_layer(ResidualBlock, 128, 2, stride=2)
43 | self.layer3 = self.make_layer(ResidualBlock, 256, 2, stride=2)
44 | self.layer4 = self.make_layer(ResidualBlock, 512, 2, stride=2)
45 | self.fc1 = nn.Linear(512, num_classes)
46 | self.fc2 = nn.Linear(512, num_classes)
47 | self.fc3 = nn.Linear(512, num_classes)
48 | self.fc4 = nn.Linear(512, num_classes)
49 |
50 | def make_layer(self, block, channels, num_blocks, stride):
51 | strides = [stride] + [1] * (num_blocks - 1) # strides=[1,1]
52 | layers = []
53 | for stride in strides:
54 | layers.append(block(self.inchannel, channels, stride))
55 | self.inchannel = channels
56 | return nn.Sequential(*layers)
57 |
58 | def forward(self, x):
59 | x = self.conv1(x)
60 | x = self.layer1(x)
61 | x = self.layer2(x)
62 | x = self.layer3(x)
63 | x = self.layer4(x)
64 | x = F.avg_pool2d(x, 4)
65 | x = x.view(-1, 512)
66 | y1 = self.fc1(x)
67 | y2 = self.fc2(x)
68 | y3 = self.fc3(x)
69 | y4 = self.fc4(x)
70 | return y1, y2, y3, y4
71 |
72 | def save(self, circle):
73 | name = "../model/captcha/resNet" + str(circle) + ".pth"
74 | t.save(self.state_dict(), name)
75 | name2 = "../model/captcha/resNet_new.pth"
76 | t.save(self.state_dict(), name2)
77 |
78 | def loadIfExist(self):
79 | fileList = os.listdir("../model/captcha/")
80 | # print(fileList)
81 | if "resNet_new.pth" in fileList:
82 | name = "../model/captcha/resNet_new.pth"
83 | self.load_state_dict(t.load(name))
84 | print("the latest model has been load")
85 |
86 |
87 | class CaptchaNet(nn.Module):
88 | def __init__(self):
89 | super(CaptchaNet, self).__init__()
90 | self.conv1 = nn.Conv2d(3, 5, 5)
91 | self.conv2 = nn.Conv2d(5, 10, 5)
92 | self.conv3 = nn.Conv2d(10, 16, 6)
93 | self.fc1 = nn.Linear(4 * 12 * 16, 512)
94 | # 这是四个用于输出四个字符的线性层
95 | self.fc2 = nn.Linear(512, 256)
96 | self.fc3 = nn.Linear(256, 128)
97 | self.fc41 = nn.Linear(128, 62)
98 | self.fc42 = nn.Linear(128, 62)
99 | self.fc43 = nn.Linear(128, 62)
100 | self.fc44 = nn.Linear(128, 62)
101 |
102 | def forward(self, x):
103 | # 输入为3*128*64,经过第一层为5*62*30
104 | x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
105 | # 输出形状10*29*13
106 | x = F.max_pool2d(F.relu(self.conv2(x)), (2, 2))
107 | # 输出形状16*12*4
108 | x = F.max_pool2d(F.relu(self.conv3(x)), (2, 2))
109 | # print(x.size())
110 | x = x.view(-1, 768)
111 | x = self.fc1(x)
112 | x = F.relu(x)
113 | x = self.fc2(x)
114 | x = F.relu(x)
115 | x = self.fc3(x)
116 | x = F.relu(x)
117 | x1 = F.softmax(self.fc41(x), dim=1)
118 | x2 = F.softmax(self.fc42(x), dim=1)
119 | x3 = F.softmax(self.fc43(x), dim=1)
120 | x4 = F.softmax(self.fc44(x), dim=1)
121 | return x1, x2, x3, x4
122 |
123 | def save(self, circle):
124 | name = "../model/captcha/net" + str(circle) + ".pth"
125 | t.save(self.state_dict(), name)
126 | name2 = "../model/captcha/net_new.pth"
127 | t.save(self.state_dict(), name2)
128 |
129 | def loadIfExist(self):
130 | fileList = os.listdir("../model/captcha/")
131 | # print(fileList)
132 | if "net_new.pth" in fileList:
133 | name = "../model/captcha/net_new.pth"
134 | self.load_state_dict(t.load(name))
135 | print("the latest model has been load")
136 |
--------------------------------------------------------------------------------
/parameters.py:
--------------------------------------------------------------------------------
1 | trainRoot = "./训练数据集"
2 | testRoot = "./测试数据集"
3 |
4 | # 不可修改的参数
5 | tensorLength = 248
6 | charLength = 62
7 | charNumber = 4
8 | ImageWidth = 32
9 | ImageHeight = 32
10 |
11 | # 可修改的参数
12 | learningRate = 1e-3
13 | totalEpoch = 200
14 | batchSize = 128
15 | printCircle = 10
16 | testCircle = 100
17 | testNum = 6
18 | saveCircle = 200
19 |
--------------------------------------------------------------------------------
/train.py:
--------------------------------------------------------------------------------
1 | from parameters import *
2 | import torch as t
3 | from torch import optim
4 | from torch import nn
5 | from dataset import *
6 | from torch.utils.data import DataLoader
7 | import tqdm
8 | from Visdom import *
9 | from torchnet import meter
10 |
11 |
12 |
13 | def train(model):
14 | avgLoss = 0.0
15 | if t.cuda.is_available():
16 | model = model.cuda()
17 | trainDataset = Captcha("../data/captcha/train/", train=True)
18 | testDataset = Captcha("../data/captcha/test/", train=False)
19 | trainDataLoader = DataLoader(trainDataset, batch_size=batchSize,
20 | shuffle=True, num_workers=4)
21 | testDataLoader = DataLoader(testDataset, batch_size=batchSize,
22 | shuffle=True, num_workers=4)
23 | criterion = nn.CrossEntropyLoss()
24 | optimizer = optim.Adam(model.parameters(), lr=learningRate)
25 | vis = Visualizer(env = "ResCaptcha")
26 | loss_meter = meter.AverageValueMeter()
27 | for epoch in range(totalEpoch):
28 | for circle, input in tqdm.tqdm(enumerate(trainDataLoader, 0)):
29 | x, label = input
30 | if t.cuda.is_available():
31 | x = x.cuda()
32 | label = label.cuda()
33 | label = label.long()
34 | label1, label2, label3, label4 = label[:, 0], label[:, 1], label[:, 2], label[:, 3]
35 | # print(label1,label2,label3,label4)
36 | optimizer.zero_grad()
37 | y1, y2, y3, y4 = model(x)
38 | # print(y1.shape, y2.shape, y3.shape, y4.shape)
39 | loss1, loss2, loss3, loss4 = criterion(y1, label1), criterion(y2, label2) \
40 | , criterion(y3, label3), criterion(y4, label4)
41 | loss = loss1 + loss2 + loss3 + loss4
42 | loss_meter.add(loss.item())
43 | # print(loss)
44 | avgLoss += loss.item()
45 | loss.backward()
46 | optimizer.step()
47 | if circle % printCircle == 1:
48 | print("after %d circle,the train loss is %.5f" %
49 | (circle, avgLoss / printCircle))
50 | writeFile("after %d circle,the train loss is %.5f" %
51 | (circle, avgLoss / printCircle))
52 | vis.plot_many_stack({"train_loss": avgLoss})
53 | avgLoss = 0
54 | if circle % testCircle == 1:
55 | accuracy = test(model, testDataLoader)
56 | vis.plot_many_stack({"test_acc":accuracy})
57 | if circle % saveCircle == 1:
58 | model.save(str(epoch)+"_"+str(saveCircle))
59 |
60 |
61 | def test(model, testDataLoader):
62 | totalNum = testNum * batchSize
63 | rightNum = 0
64 | for circle, input in enumerate(testDataLoader, 0):
65 | if circle >= testNum:
66 | break
67 | x, label = input
68 | label = label.long()
69 | if t.cuda.is_available():
70 | x = x.cuda()
71 | label = label.cuda()
72 | y1, y2, y3, y4 = model(x)
73 | y1, y2, y3, y4 = y1.topk(1, dim=1)[1].view(batchSize, 1), y2.topk(1, dim=1)[1].view(batchSize, 1), \
74 | y3.topk(1, dim=1)[1].view(batchSize, 1), y4.topk(1, dim=1)[1].view(batchSize, 1)
75 | y = t.cat((y1, y2, y3, y4), dim=1)
76 | diff = (y != label)
77 | diff = diff.sum(1)
78 | diff = (diff != 0)
79 | res = diff.sum(0).item()
80 | rightNum += (batchSize - res)
81 | print("the accuracy of test set is %s" % (str(float(rightNum) / float(totalNum))))
82 | writeFile("the accuracy of test set is %s" % (str(float(rightNum) / float(totalNum))))
83 | return float(rightNum) / float(totalNum)
84 |
85 |
86 | def writeFile(str):
87 | file = open("result.txt", "a+")
88 | file.write(str)
89 | file.write("\n\n")
90 | file.flush()
91 | file.close()
92 |
--------------------------------------------------------------------------------
/try.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | def test(model, testDataLoader):
4 | x, label = input
5 | label = label.long()
6 | y1, y2, y3, y4 = model(x)
7 | y1, y2, y3, y4 = y1.topk(1, dim=1)[1].view(testSize, 1), y2.topk(1, dim=1)[1].view(testSize, 1), \
8 | y3.topk(1, dim=1)[1].view(testSize, 1), y4.topk(1, dim=1)[1].view(testSize, 1)
9 | y = t.cat((y1, y2, y3, y4), dim=1)
10 | diff = (y != label)
11 | diff = diff.sum(1)
12 | diff = (diff != 0)
13 | res = diff.sum(0)[0]
14 | print("the accuracy of test set is %s" % (str(float(rightNum) / float(totalNum))))
15 |
16 | fileList = os.listdir("../model/captcha/")
17 | print(fileList)
18 |
--------------------------------------------------------------------------------
/userTest.py:
--------------------------------------------------------------------------------
1 | from model import *
2 | from dataset import *
3 | from train import *
4 |
5 |
6 | def userTest(model, dataLoader):
7 | totalNum = 0
8 | rightNum = 0
9 | for circle, input in enumerate(dataLoader, 0):
10 | if circle >= 200:
11 | break
12 | totalNum += 1
13 | x, label = input
14 | if t.cuda.is_available():
15 | x = x.cuda()
16 | label = label.cuda()
17 | realLabel = LabeltoStr([label[0][0], label[0][1], label[0][2], label[0][3]])
18 | # print(label,realLabel)
19 | y1, y2, y3, y4 = model(x)
20 | y1, y2, y3, y4 = y1.topk(1, dim=1)[1].view(1, 1), y2.topk(1, dim=1)[1].view(1, 1), \
21 | y3.topk(1, dim=1)[1].view(1, 1), y4.topk(1, dim=1)[1].view(1, 1)
22 | y = t.cat((y1, y2, y3, y4), dim=1)
23 | # print(x,label,y)
24 | decLabel = LabeltoStr([y[0][0], y[0][1], y[0][2], y[0][3]])
25 | print("real: %s -> %s , %s" % (realLabel, decLabel, str(realLabel == decLabel)))
26 | if realLabel == decLabel:
27 | rightNum += 1
28 | print("\n total %s, right %s" % (totalNum, rightNum))
29 |
30 | if __name__ == '__main__':
31 | model = ResNet(ResidualBlock)
32 | model.eval()
33 | model.loadIfExist()
34 | if t.cuda.is_available():
35 | model = model.cuda()
36 | userTestDataset = Captcha("./userTest/", train=True)
37 | userTestDataLoader = DataLoader(userTestDataset, batch_size=1,
38 | shuffle=True, num_workers=1)
39 | userTest(model, userTestDataLoader)
40 |
--------------------------------------------------------------------------------
/userTest/03Dy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/03Dy.jpg
--------------------------------------------------------------------------------
/userTest/0Up4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/0Up4.jpg
--------------------------------------------------------------------------------
/userTest/1N3H.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/1N3H.jpg
--------------------------------------------------------------------------------
/userTest/1q6I.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/1q6I.jpg
--------------------------------------------------------------------------------
/userTest/21qi.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/21qi.jpg
--------------------------------------------------------------------------------
/userTest/25ou.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/25ou.jpg
--------------------------------------------------------------------------------
/userTest/2Q5Z.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/2Q5Z.jpg
--------------------------------------------------------------------------------
/userTest/2V0V.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/2V0V.jpg
--------------------------------------------------------------------------------
/userTest/2isH.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/2isH.jpg
--------------------------------------------------------------------------------
/userTest/369y.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/369y.jpg
--------------------------------------------------------------------------------
/userTest/37mN.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/37mN.jpg
--------------------------------------------------------------------------------
/userTest/3C7o.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/3C7o.jpg
--------------------------------------------------------------------------------
/userTest/3v1s.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/3v1s.jpg
--------------------------------------------------------------------------------
/userTest/40EF.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/40EF.jpg
--------------------------------------------------------------------------------
/userTest/424J.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/424J.jpg
--------------------------------------------------------------------------------
/userTest/4H0M.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/4H0M.jpg
--------------------------------------------------------------------------------
/userTest/4r22.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/4r22.jpg
--------------------------------------------------------------------------------
/userTest/51SS.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/51SS.jpg
--------------------------------------------------------------------------------
/userTest/5TT7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/5TT7.jpg
--------------------------------------------------------------------------------
/userTest/6Ebr.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/6Ebr.jpg
--------------------------------------------------------------------------------
/userTest/6SoF.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/6SoF.jpg
--------------------------------------------------------------------------------
/userTest/6wrC.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/6wrC.jpg
--------------------------------------------------------------------------------
/userTest/73Mn.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/73Mn.jpg
--------------------------------------------------------------------------------
/userTest/7K49.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/7K49.jpg
--------------------------------------------------------------------------------
/userTest/7lCo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/7lCo.jpg
--------------------------------------------------------------------------------
/userTest/8Qnf.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/8Qnf.jpg
--------------------------------------------------------------------------------
/userTest/8g65.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/8g65.jpg
--------------------------------------------------------------------------------
/userTest/90za.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/90za.jpg
--------------------------------------------------------------------------------
/userTest/98Z6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/98Z6.jpg
--------------------------------------------------------------------------------
/userTest/99Y1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/99Y1.jpg
--------------------------------------------------------------------------------
/userTest/9IWI.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/9IWI.jpg
--------------------------------------------------------------------------------
/userTest/9Q7C.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/9Q7C.jpg
--------------------------------------------------------------------------------
/userTest/9U68.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/9U68.jpg
--------------------------------------------------------------------------------
/userTest/9hT8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/9hT8.jpg
--------------------------------------------------------------------------------
/userTest/9v3k.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/9v3k.jpg
--------------------------------------------------------------------------------
/userTest/AD3L.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/AD3L.jpg
--------------------------------------------------------------------------------
/userTest/AUsx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/AUsx.jpg
--------------------------------------------------------------------------------
/userTest/AfDA.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/AfDA.jpg
--------------------------------------------------------------------------------
/userTest/Al2e.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/Al2e.jpg
--------------------------------------------------------------------------------
/userTest/B3Zw.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/B3Zw.jpg
--------------------------------------------------------------------------------
/userTest/EB4y.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/EB4y.jpg
--------------------------------------------------------------------------------
/userTest/EJ6I.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/EJ6I.jpg
--------------------------------------------------------------------------------
/userTest/FPV3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/FPV3.jpg
--------------------------------------------------------------------------------
/userTest/FyTd.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/FyTd.jpg
--------------------------------------------------------------------------------
/userTest/HIXA.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/HIXA.jpg
--------------------------------------------------------------------------------
/userTest/I4lc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/I4lc.jpg
--------------------------------------------------------------------------------
/userTest/Jl8U.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/Jl8U.jpg
--------------------------------------------------------------------------------
/userTest/L48g.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/L48g.jpg
--------------------------------------------------------------------------------
/userTest/LVY8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/LVY8.jpg
--------------------------------------------------------------------------------
/userTest/MMX7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/MMX7.jpg
--------------------------------------------------------------------------------
/userTest/Ma8b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/Ma8b.jpg
--------------------------------------------------------------------------------
/userTest/N8jq.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/N8jq.jpg
--------------------------------------------------------------------------------
/userTest/NKkP.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/NKkP.jpg
--------------------------------------------------------------------------------
/userTest/Nd0w.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/Nd0w.jpg
--------------------------------------------------------------------------------
/userTest/QPt5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/QPt5.jpg
--------------------------------------------------------------------------------
/userTest/R63h.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/R63h.jpg
--------------------------------------------------------------------------------
/userTest/R69f.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/R69f.jpg
--------------------------------------------------------------------------------
/userTest/UcKh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/UcKh.jpg
--------------------------------------------------------------------------------
/userTest/UebN.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/UebN.jpg
--------------------------------------------------------------------------------
/userTest/Vj0l.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/Vj0l.jpg
--------------------------------------------------------------------------------
/userTest/VqjQ.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/VqjQ.jpg
--------------------------------------------------------------------------------
/userTest/W8w5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/W8w5.jpg
--------------------------------------------------------------------------------
/userTest/Y9eR.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/Y9eR.jpg
--------------------------------------------------------------------------------
/userTest/YCoh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/YCoh.jpg
--------------------------------------------------------------------------------
/userTest/Yhr7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/Yhr7.jpg
--------------------------------------------------------------------------------
/userTest/YuPd.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/YuPd.jpg
--------------------------------------------------------------------------------
/userTest/Z0tv.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/Z0tv.jpg
--------------------------------------------------------------------------------
/userTest/ZEEk.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/ZEEk.jpg
--------------------------------------------------------------------------------
/userTest/ZMwH.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/ZMwH.jpg
--------------------------------------------------------------------------------
/userTest/bD4z.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/bD4z.jpg
--------------------------------------------------------------------------------
/userTest/bubr.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/bubr.jpg
--------------------------------------------------------------------------------
/userTest/d5cn.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/d5cn.jpg
--------------------------------------------------------------------------------
/userTest/dc1g.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/dc1g.jpg
--------------------------------------------------------------------------------
/userTest/f05t.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/f05t.jpg
--------------------------------------------------------------------------------
/userTest/fY5e.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/fY5e.jpg
--------------------------------------------------------------------------------
/userTest/g186.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/g186.jpg
--------------------------------------------------------------------------------
/userTest/gNDs.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/gNDs.jpg
--------------------------------------------------------------------------------
/userTest/gnL3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/gnL3.jpg
--------------------------------------------------------------------------------
/userTest/h5xA.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/h5xA.jpg
--------------------------------------------------------------------------------
/userTest/hP33.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/hP33.jpg
--------------------------------------------------------------------------------
/userTest/j85X.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/j85X.jpg
--------------------------------------------------------------------------------
/userTest/jIn8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/jIn8.jpg
--------------------------------------------------------------------------------
/userTest/k63p.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/k63p.jpg
--------------------------------------------------------------------------------
/userTest/kf2m.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/kf2m.jpg
--------------------------------------------------------------------------------
/userTest/lA7T.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/lA7T.jpg
--------------------------------------------------------------------------------
/userTest/lfRO.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/lfRO.jpg
--------------------------------------------------------------------------------
/userTest/lh06.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/lh06.jpg
--------------------------------------------------------------------------------
/userTest/noWT.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/noWT.jpg
--------------------------------------------------------------------------------
/userTest/nv37.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/nv37.jpg
--------------------------------------------------------------------------------
/userTest/u5gf.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/u5gf.jpg
--------------------------------------------------------------------------------
/userTest/uJY1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/uJY1.jpg
--------------------------------------------------------------------------------
/userTest/urwM.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/urwM.jpg
--------------------------------------------------------------------------------
/userTest/v5b6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/v5b6.jpg
--------------------------------------------------------------------------------
/userTest/vCO5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/vCO5.jpg
--------------------------------------------------------------------------------
/userTest/vZ88.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/vZ88.jpg
--------------------------------------------------------------------------------
/userTest/w7Nx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/w7Nx.jpg
--------------------------------------------------------------------------------
/userTest/yECc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/yECc.jpg
--------------------------------------------------------------------------------
/userTest/yU32.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/yU32.jpg
--------------------------------------------------------------------------------
/userTest/yt0J.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/yt0J.jpg
--------------------------------------------------------------------------------
/userTest/z259.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braveryCHR/CNN_captcha/3165617616ee0891128863463fa17e4a5ee5c89c/userTest/z259.jpg
--------------------------------------------------------------------------------