├── .gitignore
├── .idea
├── .name
├── HWDB.iml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── README.md
├── __pycache__
└── pascal_voc_io.cpython-36.pyc
├── classify.py
├── pascal_voc_io.py
├── pascal_voc_io.pyc
├── processHWDB.py
└── sample-pics
├── 18.jpg
├── 25.jpg
├── 42.jpg
├── 5.jpg
├── test_acc.png
└── train_loss.png
/.gitignore:
--------------------------------------------------------------------------------
1 | models/
2 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | HWDB
--------------------------------------------------------------------------------
/.idea/HWDB.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.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 |
37 |
38 |
39 |
40 | label
41 | 3368
42 | prob
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 | 1528008833135
160 |
161 |
162 | 1528008833135
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### HWDB-1.1 手写汉字CNN识别模型训练
2 |
3 | ---
4 |
5 | #### 数据集
6 |
7 | 使用CASIA-HWDB1.1进行训练和测试,训练集和测试集按照4:1划分,测试集235200张,训练集940800张,
8 |
9 | 共计1,176,000张图像。该数据集由300个人手写而成,其中包含171个阿拉伯数字和特殊符号,3755类GB2312-80 level-1汉字。
10 |
11 | http://www.nlpr.ia.ac.cn/databases/handwriting/Download.html
12 |
13 | - 样例图
14 |
15 | 
16 |
17 | 
18 |
19 | 
20 |
21 | 
22 |
23 |
24 |
25 | #### 模型训练
26 |
27 | - **Finetuning from a pretrained model**
28 |
29 | 以googlenet为基础模型,进行finetuning。直接训练全部类别无法收敛时,尝试分阶段训练。
30 |
31 | 训练后的测试结果为loss-1和loss-2分支准确率为95%,loss-3分支为97%。收敛很快,以0.01为基础学习率,32的batch size,不到10000次迭代就收敛了。
32 |
33 |
34 |
35 | - **Train 'HWDB-CNN-9Layer' model**
36 |
37 | 虽然googlenet效果尚可,但是由于网络设计的历史原因,全连接层没有用avg_pooling,所以输入时需要强行把图像放大到224*224,且输入是3通道,对于字符来说有点浪费资源。决定按照论文重头撸一个轻量点的模型。
38 |
39 | 这个论文里的模型比较简单,就是很基本的结构(模型图太长,不贴了)。
40 | 加了BN(注意BN以及一些特殊层训练和deploy的区别),训练过程收敛也很快,过程图如下:
41 |
42 | 
43 |
44 |
45 |
46 | 
47 |
48 | - 前传时间及模型大小对比
49 |
50 | googlenet: 0.46ms/张,89.5MB
51 |
52 | HWDB-CNN-9Layer: 0.205ms / 张, 44.2MB
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/__pycache__/pascal_voc_io.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peterWon/CASIA-HWDB-Recognition/c8e8ea95b24c0cc340bf2d099b0dbb3105598a49/__pycache__/pascal_voc_io.cpython-36.pyc
--------------------------------------------------------------------------------
/classify.py:
--------------------------------------------------------------------------------
1 | import sys
2 | sys.path.insert(0, '/home/wz/DeepLearning/caffe_dir/easy-pvanet/caffe-fast-rcnn/python')#py2
3 | # sys.path.insert(0, '/home/wz/DeepLearning/caffe_dir/caffe/python') #py3
4 | import caffe
5 | import cv2
6 | import numpy as np
7 | import os
8 | import codecs
9 |
10 | CLASSIFIER_MODEL_FILE = '/home/wz/PycharmProjects/HWDB/model/googlenet-deploy.prototxt'
11 | CLASSIFIER_PRETRAINED = '/home/wz/PycharmProjects/HWDB/model/googlenet.caffemodel'
12 | caffe.set_mode_gpu()
13 | goolenet_classifier = caffe.Classifier(CLASSIFIER_MODEL_FILE, CLASSIFIER_PRETRAINED)
14 |
15 |
16 | with codecs.open('/home/wz/DataSets/Offline/CASIA-HWDB1.1/labelmap.txt', encoding='utf-8', mode='r') as labelfile:
17 | label_lines = labelfile.readlines()
18 | print(len(label_lines))
19 |
20 | testset = '/home/wz/DataSets/Offline/CASIA-HWDB1.1/test_all.txt'
21 | with open(testset, 'r') as testfile:
22 | lines = testfile.readlines()
23 | for line in lines[:10]:
24 | IMAGE_FILE = os.path.join('/home/wz/DataSets/Offline/CASIA-HWDB1.1/IMG_CLS/', line.split(' ')[0])
25 | show = cv2.imread(IMAGE_FILE, cv2.IMREAD_COLOR)
26 | input_array = np.zeros(shape = (show.shape[0], show.shape[1], 3), dtype=np.float)
27 | input_array[:, :, :] = show
28 | input_array[:, :, 0] -= 104.0
29 | input_array[:, :, 1] -= 117.0
30 | input_array[:, :, 2] -= 123.0
31 |
32 | prediction = goolenet_classifier.predict([input_array])[0]
33 | top_1_index = prediction.argmax()
34 | print(label_lines[top_1_index])
--------------------------------------------------------------------------------
/pascal_voc_io.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf8 -*-
3 | #import _init_path
4 | import sys
5 | from xml.etree import ElementTree
6 | from xml.etree.ElementTree import Element, SubElement
7 | from lxml import etree
8 | import codecs
9 |
10 | XML_EXT = '.xml'
11 |
12 |
13 | class PascalVocWriter:
14 |
15 | def __init__(self, foldername, filename, imgSize, databaseSrc='Unknown', localImgPath=None):
16 | self.foldername = foldername
17 | self.filename = filename
18 | self.databaseSrc = databaseSrc
19 | self.imgSize = imgSize
20 | self.boxlist = []
21 | self.localImgPath = localImgPath
22 | self.verified = False
23 |
24 | def renameFileName(self,filename):
25 | self.filename = filename
26 |
27 | def prettify(self, elem):
28 | """
29 | Return a pretty-printed XML string for the Element.
30 | """
31 | rough_string = ElementTree.tostring(elem, 'utf-8')
32 | root = etree.fromstring(rough_string)
33 | return etree.tostring(root, pretty_print=True)
34 |
35 | def genXML(self):
36 | """
37 | Return XML root
38 | """
39 | # Check conditions
40 | if self.filename is None or \
41 | self.foldername is None or \
42 | self.imgSize is None:
43 | return None
44 |
45 | top = Element('annotation')
46 | top.set('verified', 'yes' if self.verified else 'no')
47 |
48 | folder = SubElement(top, 'folder')
49 | folder.text = self.foldername
50 |
51 | filename = SubElement(top, 'filename')
52 | filename.text = self.filename
53 |
54 | localImgPath = SubElement(top, 'path')
55 | localImgPath.text = self.localImgPath
56 |
57 | source = SubElement(top, 'source')
58 | database = SubElement(source, 'database')
59 | database.text = self.databaseSrc
60 |
61 | size_part = SubElement(top, 'size')
62 | width = SubElement(size_part, 'width')
63 | height = SubElement(size_part, 'height')
64 | depth = SubElement(size_part, 'depth')
65 | width.text = str(self.imgSize[1])
66 | height.text = str(self.imgSize[0])
67 | if len(self.imgSize) == 3:
68 | depth.text = str(self.imgSize[2])
69 | else:
70 | depth.text = '1'
71 |
72 | segmented = SubElement(top, 'segmented')
73 | segmented.text = '0'
74 | return top
75 |
76 | def addBndBox(self, xmin, ymin, xmax, ymax, name):
77 | bndbox = {'xmin': xmin, 'ymin': ymin, 'xmax': xmax, 'ymax': ymax}
78 | bndbox['name'] = name
79 | xmin = max(0, xmin)
80 | ymin = max(0, ymin)
81 | xmax = min(xmax, self.imgSize[1] - 1)
82 | ymax = min(ymax, self.imgSize[0] - 1)
83 |
84 | # 判断是否box是否是边界处的狭长box
85 | if abs((xmax - xmin) * 1.0 / (ymax - ymin)) < 0.25 and (xmin < 0.1 * self.imgSize[1] or xmax > 0.9 * self.imgSize[1]):
86 | return None
87 | if abs((xmax - xmin) * 1.0 / (ymax - ymin)) > 4 and (ymin < 0.1 * self.imgSize[0] or ymax > 0.9 * self.imgSize[0]):
88 | return None
89 |
90 | self.boxlist.append(bndbox)
91 |
92 | def appendObjects(self, top):
93 | for each_object in self.boxlist:
94 | object_item = SubElement(top, 'object')
95 | name = SubElement(object_item, 'name')
96 | try:
97 | name.text = unicode(each_object['name'])
98 | except NameError:
99 | # Py3: NameError: name 'unicode' is not defined
100 | name.text = each_object['name']
101 | pose = SubElement(object_item, 'pose')
102 | pose.text = "Unspecified"
103 | truncated = SubElement(object_item, 'truncated')
104 | truncated.text = "0"
105 | difficult = SubElement(object_item, 'difficult')
106 | difficult.text = "0"
107 | bndbox = SubElement(object_item, 'bndbox')
108 | xmin = SubElement(bndbox, 'xmin')
109 | xmin.text = str(each_object['xmin'])
110 | ymin = SubElement(bndbox, 'ymin')
111 | ymin.text = str(each_object['ymin'])
112 | xmax = SubElement(bndbox, 'xmax')
113 | xmax.text = str(each_object['xmax'])
114 | ymax = SubElement(bndbox, 'ymax')
115 | ymax.text = str(each_object['ymax'])
116 |
117 | def save(self, targetFile=None):
118 | root = self.genXML()
119 | self.appendObjects(root)
120 | out_file = None
121 | if targetFile is None:
122 | out_file = codecs.open(
123 | self.filename + XML_EXT, 'w', encoding='utf-8')
124 | else:
125 | out_file = codecs.open(targetFile, 'w', encoding='utf-8')
126 |
127 | prettifyResult = self.prettify(root)
128 | out_file.write(prettifyResult.decode('utf8'))
129 | out_file.close()
130 |
131 |
132 | class PascalVocReader:
133 | def __init__(self, filepath):
134 | # shapes type:
135 | # [labbel, [(x1,y1), (x2,y2), (x3,y3), (x4,y4)], color, color]
136 | self.shapes = []
137 | self.filepath = filepath
138 | self.verified = False
139 | self.width = 0
140 | self.height = 0
141 |
142 | self.parseXML()
143 |
144 | def getShapes(self):
145 | return self.shapes
146 |
147 | def addShape(self, label, bndbox):
148 | xmin = int(bndbox.find('xmin').text)
149 | ymin = int(bndbox.find('ymin').text)
150 | xmax = int(bndbox.find('xmax').text)
151 | ymax = int(bndbox.find('ymax').text)
152 | points = [(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]
153 | self.shapes.append((label, points, None, None))
154 |
155 | def parseXML(self):
156 | assert self.filepath.endswith('.xml'), "Unsupport file format"
157 | parser = etree.XMLParser(encoding='utf-8')
158 | xmltree = ElementTree.parse(self.filepath, parser=parser).getroot()
159 | filename = xmltree.find('filename').text
160 | try:
161 | verified = xmltree.attrib['verified']
162 | if verified == 'yes':
163 | self.verified = True
164 | except KeyError:
165 | self.verified = False
166 |
167 | size = xmltree.find('size')
168 | self.width = int(size.find('width').text)
169 | self.height = int(size.find('height').text)
170 | for object_iter in xmltree.findall('object'):
171 | bndbox = object_iter.find("bndbox")
172 | #wz, check if bbox out of range.
173 | '''
174 | xmin = int(bndbox.find('xmin').text)
175 | ymin = int(bndbox.find('ymin').text)
176 | xmax = int(bndbox.find('xmax').text)
177 | ymax = int(bndbox.find('ymax').text)
178 | if ymin < 0 or ymax > height or xmin < 0 or xmax > width:
179 | self.hasExceedBoundingBBox = True
180 | '''
181 |
182 | label = object_iter.find('name').text
183 | self.addShape(label, bndbox)
184 | return True
185 |
186 |
--------------------------------------------------------------------------------
/pascal_voc_io.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peterWon/CASIA-HWDB-Recognition/c8e8ea95b24c0cc340bf2d099b0dbb3105598a49/pascal_voc_io.pyc
--------------------------------------------------------------------------------
/processHWDB.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import codecs
3 |
4 | import struct
5 | import numpy as np
6 | import cv2
7 | import os
8 | import random
9 | from pascal_voc_io import *
10 |
11 | def transform_labelmap_to_utf8(src_path, src_encode, dst_path, dst_encode = 'utf-8'):
12 | '''
13 | :param src_path: source file path.
14 | :param src_encode: source file encoding.
15 | :param dst_path: destination file path.
16 | :param dst_encode: destination file encoding.
17 | :return:
18 | '''
19 | with codecs.open(src_path, mode='r', encoding=src_encode) as infile:
20 | lines = infile.readlines()
21 | with codecs.open(dst_path, mode='w', encoding=dst_encode) as outfile:
22 | outfile.writelines(lines)
23 | print('Transform encodings done!')
24 |
25 | def decode_GNT_to_imgs(gnt):
26 | '''
27 | :param gnt: a writer's encoded ground truth file.
28 | :return: samples list, each sample with format (charname, img)
29 | '''
30 | samples = []
31 | with codecs.open(gnt, mode='rb') as fin:
32 | while(True):
33 | left_cache = fin.read(4)
34 | if len(left_cache) < 4:
35 | break
36 | sample_size = struct.unpack("I", left_cache)[0]
37 | tag_code = str(fin.read(2), 'gbk')
38 | width = struct.unpack("H", fin.read(2))[0]
39 | height = struct.unpack("H", fin.read(2))[0]
40 |
41 | img = np.zeros(shape=[height, width], dtype=np.uint8)
42 | for r in range(height):
43 | for c in range(width):
44 | img[r, c] = struct.unpack("B", fin.read(1))[0]
45 | if width*height + 10 != sample_size:
46 | break
47 | samples.append((tag_code[0], img))
48 |
49 | return samples
50 |
51 | def decode_DGR_to_imgs_and_vocxml(dgr):
52 | '''
53 | :param dgr: a writer's encoded ground truth file.
54 | :return: samples list, each sample with format (charname, img)
55 | '''
56 | doc_img, voc_xml = None, None
57 | with codecs.open(dgr, mode='rb') as fin:
58 | while(True):
59 | left_cache = fin.read(4)
60 | if len(left_cache) < 4:
61 | break
62 |
63 | #FILE HEAFER
64 | size_of_header = struct.unpack("I", left_cache)[0]
65 | format_code = fin.read(8)
66 | illus_len = size_of_header - 36
67 | illus = fin.read(illus_len)
68 | if sys.version_info < (3, 0, 0):
69 | code_type = fin.read(20).decode('ASCII')
70 | else:
71 | code_type = str(fin.read(20), 'ASCII')
72 |
73 | code_len = struct.unpack("h", fin.read(2))[0]
74 | bits_per_pix = struct.unpack("h", fin.read(2))[0]
75 |
76 | if bits_per_pix == 1:
77 | break
78 |
79 | #Image Records (concatenated)
80 | height = struct.unpack("I", fin.read(4))[0]
81 | width = struct.unpack("I", fin.read(4))[0]
82 | doc_img = np.zeros(shape=[height, width], dtype=np.uint8) + 255
83 |
84 | voc_xml = PascalVocWriter(os.path.dirname(dgr), os.path.split(dgr)[-1][:-4] + '.jpg', doc_img.shape)
85 |
86 | # Line Records (concatenated)
87 | line_num = struct.unpack("I", fin.read(4))[0]
88 | for i in range(line_num):
89 | # Character Records (concatenated)
90 | word_num = struct.unpack("I", fin.read(4))[0]
91 | for j in range(word_num):
92 | tmp_code = fin.read(code_len)
93 | try:
94 | if sys.version_info < (3, 0, 0):
95 | label = tmp_code.decode('gbk')[0]
96 | else:
97 | label = str(tmp_code, ('gbk'))[0]
98 | except:
99 | label = u'Unknown'
100 |
101 | top = struct.unpack("H", fin.read(2))[0]
102 | left = struct.unpack("H", fin.read(2))[0]
103 | char_height = struct.unpack("H", fin.read(2))[0]
104 | char_width = struct.unpack("H", fin.read(2))[0]
105 | tmp_img = np.zeros(shape=[char_height, char_width], dtype=np.uint8)
106 |
107 | #Image data
108 | for r in range(char_height):
109 | for c in range(char_width):
110 | tmp_img[r, c] = struct.unpack("B", fin.read(1))[0]
111 | doc_img[top:top+char_height, left:left+char_width] = tmp_img
112 | voc_xml.addBndBox(left, top, left + char_width, top+char_height, label)
113 |
114 | return doc_img, voc_xml
115 |
116 | def init_save_dir(labelmap, save_root):
117 | '''
118 | initialize saveing dirs. save time in process.
119 | :param labelmap:
120 | :param save_root:
121 | :return:
122 | '''
123 | with open(labelmap, 'r') as infile:
124 | for line in infile.readlines():
125 | if line[0] == '.':
126 | os.mkdir(os.path.join(save_root, 'dot'))
127 | elif line[0] == '/':
128 | os.mkdir(os.path.join(save_root, 'slash'))
129 | else:
130 | os.mkdir(os.path.join(save_root, line[0]))
131 |
132 |
133 | def gen_train_test_sets(img_root_dir, labelmap, train_index, test_index, subsetnum = None):
134 | samples_train = []
135 | samples_test = []
136 | labels = []
137 | subdirs = os.listdir(img_root_dir)
138 | subdirs.sort()
139 |
140 | if subsetnum is None:
141 | subsetnum = len(subdirs)
142 |
143 | for id, folder in enumerate(subdirs[:subsetnum]):
144 | imgs = os.listdir(os.path.join(img_root_dir, folder))
145 | for iid, img in enumerate(imgs):
146 | if iid < 0.8 * len(imgs):
147 | samples_train.append(folder + '/' + img + ' ' + str(id))
148 | else:
149 | samples_test.append(folder + '/' + img + ' ' + str(id))
150 | # labels.append(folder+','+str(id))
151 | labels.append(folder)
152 |
153 | random.shuffle(samples_train)
154 | random.shuffle(samples_test)
155 | with open(train_index, 'w') as trainset:
156 | for sample in samples_train:
157 | trainset.writelines(sample+'\n')
158 |
159 | with open(test_index, 'w') as testset:
160 | for sample in samples_test:
161 | testset.writelines(sample+'\n')
162 |
163 | with open(labelmap, 'w') as labelfile:
164 | for label in labels:
165 | labelfile.writelines(str(label)+'\n')
166 |
167 |
168 | def decode_HWDB_subset_v1(gnt_root_dir, img_save_dir, labelmap_ori):
169 | '''
170 | 解析并保存HWDB-1的gnt格式数据到对应类别的图像文件夹
171 | :param gnt_root_dir:
172 | :param img_save_dir:
173 | :param labelmap_ori: 原始字码表(若是gbk编码的,需要先利用transform_labelmap_to_utf8
174 | 转换到utf-8编码), 其中的‘.’和‘/’尚未以dot和slash表示
175 | :return:
176 | '''
177 | #初始化保存文件夹,节省处理时间
178 | init_save_dir(labelmap_ori, img_save_dir)
179 |
180 | index_dict = {}
181 | for gnt in os.listdir(gnt_root_dir):
182 | gnt_path = os.path.join(gnt_root_dir, gnt)
183 | samples = decode_GNT_to_imgs(gnt_path)
184 | for sample in samples:
185 | char_name = sample[0]
186 | if char_name == '.': char_name = 'dot' #避免文件夹路径冲突
187 | if char_name == '/': char_name = 'slash' #避免文件夹路径冲突
188 | if not char_name in index_dict: index_dict.update({char_name: 0})
189 | else: index_dict[char_name] += 1
190 | cv2.imwrite(os.path.join(img_save_dir, char_name, str(index_dict[char_name]) + '.jpg'), sample[1])
191 | print('processed gnt file %s.' % gnt)
192 |
193 |
194 | def decode_HWDB_subset_v2(dgr_data_dir, img_save_dir, xml_writing_dir):
195 | '''
196 | 解析并保存HWDB-v2的dgr格式数据到图像和相应的VOC格式的xml文件
197 | :param dgr_data_dir:
198 | :param img_save_dir:
199 | :param xml_writing_dir:
200 | :return:
201 | '''
202 | dgrs = os.listdir(dgr_data_dir)
203 | for dgr in dgrs:
204 | doc_img, voc_xml = decode_DGR_to_imgs_and_vocxml(os.path.join(dgr_data_dir, dgr))
205 | cv2.imwrite(os.path.join(img_save_dir, dgr[:-4] + '.jpg'), doc_img)
206 | voc_xml.save(xml_writing_dir + "/" + dgr[:-4] + XML_EXT)
207 | print('Processed file %s.' % dgr)
208 |
209 |
210 | if __name__ == '__main__':
211 | #gen_train_test_sets('/home/wz/DataSets/Offline/CASIA-HWDB1.1/IMG_CLS',
212 | # '/home/wz/DataSets/Offline/CASIA-HWDB1.1/labelmap_200.txt',
213 | # '/home/wz/DataSets/Offline/CASIA-HWDB1.1/trainval_200.txt',
214 | # '/home/wz/DataSets/Offline/CASIA-HWDB1.1/test_200.txt', 200)
215 |
216 | decode_HWDB_subset_v2('/home/wz/DataSets/Offline/CASIA-HWDB2.2/Train_Dgr',
217 | '/home/wz/DataSets/Offline/CASIA-HWDB2.2/DOC_IMG/TRAIN',
218 | '/home/wz/DataSets/Offline/CASIA-HWDB2.2/DOC_IMG/TRAIN_XML')
--------------------------------------------------------------------------------
/sample-pics/18.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peterWon/CASIA-HWDB-Recognition/c8e8ea95b24c0cc340bf2d099b0dbb3105598a49/sample-pics/18.jpg
--------------------------------------------------------------------------------
/sample-pics/25.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peterWon/CASIA-HWDB-Recognition/c8e8ea95b24c0cc340bf2d099b0dbb3105598a49/sample-pics/25.jpg
--------------------------------------------------------------------------------
/sample-pics/42.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peterWon/CASIA-HWDB-Recognition/c8e8ea95b24c0cc340bf2d099b0dbb3105598a49/sample-pics/42.jpg
--------------------------------------------------------------------------------
/sample-pics/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peterWon/CASIA-HWDB-Recognition/c8e8ea95b24c0cc340bf2d099b0dbb3105598a49/sample-pics/5.jpg
--------------------------------------------------------------------------------
/sample-pics/test_acc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peterWon/CASIA-HWDB-Recognition/c8e8ea95b24c0cc340bf2d099b0dbb3105598a49/sample-pics/test_acc.png
--------------------------------------------------------------------------------
/sample-pics/train_loss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peterWon/CASIA-HWDB-Recognition/c8e8ea95b24c0cc340bf2d099b0dbb3105598a49/sample-pics/train_loss.png
--------------------------------------------------------------------------------