yolov2训练ICDAR2011数据集

首先下载数据集train-textloc.zip

其groundtruth文件如下所示:

158,128,412,182,"Footpath"
442,128,501,170,"To"
393,198,488,240,"and"
63,200,363,242,"Colchester"
71,271,383,313,"Greenstead"

ground truth 文件格式为:xmin, ymin, xmax, ymax, label。同时,要注意,这里的坐标系是如下摆放: 

将此txt文件转换成voc xml文件的代码:

icdar2voc.py

 1 #! /usr/bin/python
 2 #-*-coding:utf8-*-
 3 
 4 import os, sys
 5 import glob
 6 from PIL import Image
 7 
 8 # ICDAR 图像存储位置
 9 src_img_dir = "train-textloc"
10 # ICDAR 图像的 ground truth 的 txt 文件存放位置
11 src_txt_dir = "train-textloc"
12 
13 img_Lists = glob.glob(src_img_dir + '/*.jpg')
14 
15 img_basenames = [] # e.g. 100.jpg
16 for item in img_Lists:
17     img_basenames.append(os.path.basename(item))
18 
19 img_names = [] # e.g. 100
20 for item in img_basenames:
21     temp1, temp2 = os.path.splitext(item)
22     img_names.append(temp1)
23 
24 for img in img_names:
25     im = Image.open((src_img_dir + '/' + img + '.jpg'))
26     width, height = im.size
27 
28     # open the crospronding txt file
29     gt = open(src_txt_dir + '/gt_' + img + '.txt').read().splitlines()
30 
31     # write in xml file
32     #os.mknod(src_txt_dir + '/' + img + '.xml')
33     xml_file = open((src_txt_dir + '/' + img + '.xml'), 'w')
34     xml_file.write('<annotation>\n')
35     xml_file.write('    <folder>VOC2007</folder>\n')
36     xml_file.write('    <filename>' + str(img) + '.jpg' + '</filename>\n')
37     xml_file.write('    <size>\n')
38     xml_file.write('        <width>' + str(width) + '</width>\n')
39     xml_file.write('        <height>' + str(height) + '</height>\n')
40     xml_file.write('        <depth>3</depth>\n')
41     xml_file.write('    </size>\n')
42 
43     # write the region of text on xml file
44     for img_each_label in gt:
45         spt = img_each_label.split(',')
46         xml_file.write('    <object>\n')
47         xml_file.write('        <name>text</name>\n')
48         xml_file.write('        <pose>Unspecified</pose>\n')
49         xml_file.write('        <truncated>0</truncated>\n')
50         xml_file.write('        <difficult>0</difficult>\n')
51         xml_file.write('        <bndbox>\n')
52         xml_file.write('            <xmin>' + str(spt[0]) + '</xmin>\n')
53         xml_file.write('            <ymin>' + str(spt[1]) + '</ymin>\n')
54         xml_file.write('            <xmax>' + str(spt[2]) + '</xmax>\n')
55         xml_file.write('            <ymax>' + str(spt[3]) + '</ymax>\n')
56         xml_file.write('        </bndbox>\n')
57         xml_file.write('    </object>\n')
58 
59     xml_file.write('</annotation>')
View Code

再将xml文件转换成yolo的txt格式:

voc_label.py

 1 import xml.etree.ElementTree as ET
 2 import pickle
 3 import os
 4 from os import listdir, getcwd
 5 from os.path import join
 6 
 7 
 8 classes = ["text"]
 9 
10 
11 def convert(size, box):
12     dw = 1./size[0]
13     dh = 1./size[1]
14     x = (box[0] + box[1])/2.0
15     y = (box[2] + box[3])/2.0
16     w = box[1] - box[0]
17     h = box[3] - box[2]
18     x = x*dw
19     w = w*dw
20     y = y*dh
21     h = h*dh
22     return (x,y,w,h)
23 
24 for i in range(100,329):
25     in_file = open('train-textloc/%d.xml'% i )
26     out_file = open('train-textloc/%d.txt'% i , 'w')
27     tree=ET.parse(in_file)
28     root = tree.getroot()
29     size = root.find('size')
30     w = int(size.find('width').text)
31     h = int(size.find('height').text)
32 
33     for obj in root.iter('object'):
34         difficult = obj.find('difficult').text
35         cls = obj.find('name').text
36         if cls not in classes or int(difficult) == 1:
37             continue
38         cls_id = classes.index(cls)
39         xmlbox = obj.find('bndbox')
40         b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
41         bb = convert((w,h), b)
42         out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
View Code

下面开始修改yolo的配置:

把20类改成1类

  1. cfg/voc.data文件中:

    • classes 改成1。
    • names=data/voc.names。
    • voc.names里只写一行 text 即可。
  2. cfg/yolo_voc.cfg文件中 :

    • 【region】层中 classes 改成1。
    • 【region】层上方第一个【convolution】层,其中的filters值要进行修改,改成(classes+ coords+ 1)* (NUM) ,我的情况中:(1+4+1)* 5=30,我把filters 的值改成了30。
    • 修改filters的建议来源自(https://groups.google.com/forum/#!topic/darknet/B4rSpOo84yg),我修改了之后一切正常。
  3. src/yolo.c 文件中 :(经指正,步骤3,4是yolo1的内容,使用yolo_v2的话可以不用更改)

    • 位置大约第14行左右改成:char *voc_names={“text”},原来里面有20类的名字,我改成了唯一1类的名字。
    • 位置大约第328行左右,修改draw_detection这个函数最后一个参数:20改成1。这个函数用于把系统检测出的框给画出来,并把画完框的图片传回第一个参数im中,用于保存和显示。
    • 位置大约第361行左右,demo函数中,倒数第三个参数我把20改成了1,虽然不知道有没有用,反正对结果没什么影响。
  4. src/yolo_kernels.cu 文件中 :(经指正,步骤3,4是yolo1的内容,使用yolo_v2的话可以不用更改)

    • 位置第62行,draw_detection这个函数最后一个参数20改成1。
  5. scripts/voc_label.py 文件中(这个应该没用的) :

    • 位置第9行改成:classes=[“text”],因为我只有一类。

建立一个文件夹,里面JPEGImages里放入所有的图片,labels里放入所有的标签,系统会自动识别。

然后生成train.txt

list.py

1 # -*- coding: utf-8 -*-
2 import os
3 fw = open('train.txt','w')
4 files = os.listdir('/home/mingyu_ding/darknet/voc/Table/JPEGImages')
5 for f in files:
6     file = '/home/mingyu_ding/darknet/voc/Table/JPEGImages' + os.sep + f
7     print >> fw, file
View Code

就可以开始训练了,系统默认会迭代45000次。 

nohup ./darknet detector train cfg/voc.data cfg/yolo-voc.cfg darknet19_448.conv.23 > log.txt &

当然迭代次数是可以修改的,应该是在cfg/yolo_voc.cfg修改max_batches的值就行。

没训练完就可以测试啦

./darknet detector test cfg/voc.data cfg/yolo-voc.cfg backup/yolo-voc_5000.weights ../Downloads/1.jpg

参考链接:http://blog.csdn.net/hysteric314/article/details/54097845

结果如下:

 

后来又训练了京东的参数图数据。

图是自己下载的,重命名后用labelimg进行标注,之后用voc_label.py修改成标签数据即可。

rename.py

 1 import os
 2 from os.path import join
 3 
 4 files = os.listdir('imageset')
 5 i = 0
 6 for f in files:
 7     i += 1
 8     print os.path.join(os.getcwd() + os.sep + 'imageset' , f)
 9     print os.getcwd() + os.sep  + 'imageset' + os.sep + '%d.jpg' % i
10     os.rename(os.path.join(os.getcwd() + os.sep + 'imageset' , f), os.getcwd() + os.sep  + 'imageset' + os.sep + '%d.jpg' % i)
View Code

训练办法和上面一模一样'

结果如下图:

想要输出预测框的位置的话

修改 image.c 后重新 make 就可以了

1 printf("left:%d right:%d top:%d bot:%d\n",left,right,top,bot);
View Code

修改 detector.c 后 make 可以切割出想要的位置,如下图所示。

在函数draw_detections() 前面修改就可以

 1         int i;
 2     int j = 1;
 3         for(i = 0; i < l.w*l.h*l.n; ++i){
 4             int class = max_index(probs[i], l.classes);
 5             float prob = probs[i][class];
 6             if(prob > thresh){
 7         box b = boxes[i];
 8         int left  = (b.x-b.w/2.)*im.w;
 9         int right = (b.x+b.w/2.)*im.w;
10         int top   = (b.y-b.h/2.)*im.h;
11         int bot   = (b.y+b.h/2.)*im.h;
12         if(left < 0) left = 0;
13         if(right > im.w-1) right = im.w-1;
14         if(top < 0) top = 0;
15         if(bot > im.h-1) bot = im.h-1;
16         int width = right - left;
17                 int height = bot - top;
18         IplImage* src = cvLoadImage(input,-1);
19         CvSize size = cvSize(width, height);
20                 //printf("%d,%d",src->depth,src->nChannels);
21         IplImage* roi = cvCreateImage(size,src->depth,src->nChannels);
22         CvRect box = cvRect(left, top, size.width, size.height);
23         cvSetImageROI(src,box);
24         cvCopy(src,roi,NULL);
25         //cvNamedWindow("pic",CV_WINDOW_AUTOSIZE);
26         //cvShowImage("pic",src);
27         char name[4] = "cut";
28         char name1[5] = ".jpg";
29         char newname[100];
30         sprintf(newname,"%s%d_%.0f%s",name,j,100*prob,name1);
31         //printf("%s\n",newname);
32         j++;
33         cvSaveImage(newname,roi,0);
34         //cvWaitKey(0); 
35         //cvDestoryWindow("pic");
36         cvReleaseImage(&src);
37         cvReleaseImage(&roi);
38         //printf("left:%d right:%d top:%d bot:%d\n",left,right,top,bot);
39             }
40         };
View Code

 

下一步就是识别出参数框里的文字了,需要数据集和标签的可以联系我。

sudo apt-get install tesseract-ocr

sudo apt-get install tesseract-ocr-chi-sim

tesseract cut1_93.jpg out -l eng+chi_sim

out.txt 就可以看了

posted on 2017-03-21 20:00  Satchmo丶  阅读(3348)  评论(27编辑  收藏  举报