├── .gitignore ├── CRNN ├── cfg.py ├── dataset.py ├── img │ ├── 0.jpg │ ├── 1.jpg │ ├── 10.jpg │ ├── 11.jpg │ ├── 12.jpg │ ├── 13.jpg │ ├── 14.jpg │ ├── 15.jpg │ ├── 16.jpg │ ├── 17.jpg │ ├── 18.jpg │ ├── 19.jpg │ ├── 2.jpg │ ├── 20.jpg │ ├── 21.jpg │ ├── 22.jpg │ ├── 23.jpg │ ├── 24.jpg │ ├── 25.jpg │ ├── 26.jpg │ ├── 27.jpg │ ├── 28.jpg │ ├── 29.jpg │ ├── 3.jpg │ ├── 30.jpg │ ├── 31.jpg │ ├── 32.jpg │ ├── 33.jpg │ ├── 34.jpg │ ├── 35.jpg │ ├── 36.jpg │ ├── 37.jpg │ ├── 38.jpg │ ├── 39.jpg │ ├── 4.jpg │ ├── 40.jpg │ ├── 41.jpg │ ├── 42.jpg │ ├── 43.jpg │ ├── 44.jpg │ ├── 45.jpg │ ├── 46.jpg │ ├── 47.jpg │ ├── 48.jpg │ ├── 49.jpg │ ├── 5.jpg │ ├── 50.jpg │ ├── 51.jpg │ ├── 52.jpg │ ├── 53.jpg │ ├── 54.jpg │ ├── 55.jpg │ ├── 56.jpg │ ├── 57.jpg │ ├── 58.jpg │ ├── 59.jpg │ ├── 6.jpg │ ├── 60.jpg │ ├── 61.jpg │ ├── 62.jpg │ ├── 63.jpg │ ├── 64.jpg │ ├── 65.jpg │ ├── 66.jpg │ ├── 67.jpg │ ├── 68.jpg │ ├── 69.jpg │ ├── 7.jpg │ ├── 70.jpg │ ├── 71.jpg │ ├── 72.jpg │ ├── 73.jpg │ ├── 74.jpg │ ├── 75.jpg │ ├── 76.jpg │ ├── 77.jpg │ ├── 78.jpg │ ├── 79.jpg │ ├── 8.jpg │ ├── 80.jpg │ ├── 81.jpg │ ├── 82.jpg │ ├── 83.jpg │ ├── 84.jpg │ ├── 85.jpg │ ├── 86.jpg │ ├── 87.jpg │ ├── 88.jpg │ ├── 89.jpg │ ├── 9.jpg │ ├── 90.jpg │ ├── 91.jpg │ ├── 92.jpg │ ├── 93.jpg │ ├── 94.jpg │ └── 95.jpg ├── model.py ├── train.py └── util │ └── util.py ├── EAST ├── advanced_east.py ├── cfg.py ├── data_generator.py ├── label.py ├── losses.py ├── network.py ├── nms.py ├── predict.py └── preprocess.py └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | */__pycache__ 3 | .ipynb_checkpoints 4 | *.h5 5 | *.hdf5 6 | *.json 7 | *.pb 8 | *.pbtxt 9 | *.yml 10 | *.ckpt 11 | .idea 12 | me.md 13 | data 14 | gen_data 15 | *.txt 16 | EAST/*.jpg 17 | EAST/DF_zh 18 | EAST/row 19 | *.pth 20 | data_generator_my -------------------------------------------------------------------------------- /CRNN/cfg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | ''' 4 | @author: tianxiaomo 5 | @license: (C) Apache. 6 | @contact: huguanghao520@gmail.com 7 | @software: 8 | @file: cfg.py 9 | @time: 2019/1/7 15:56 10 | @desc: 11 | ''' 12 | import time 13 | def getTimeStr(): 14 | return time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) 15 | 16 | 17 | model = 'CRNN' 18 | checkpoint = None 19 | char_path = './util/char_gb2312.txt' 20 | 21 | model_weights_path = 'checkpoints/weights_%s.{epoch:03d}-{val_loss:.3f}-{val_acc:.3f}.h5' % model 22 | tensorboard_dir = './logs/%s_%s' % (model,getTimeStr()) 23 | 24 | with open(char_path, 'r', encoding='utf-8') as file: 25 | char_dict = {num: char.strip() for num, char in enumerate(file.readlines())} 26 | lexicon_len = len(char_dict) 27 | 28 | gpu = 3 29 | 30 | num_classes = lexicon_len 31 | 32 | img_w, img_h,img_c = 640, 32, 3 33 | 34 | # data parameter 35 | from easydict import EasyDict as edict 36 | data_para =edict({'img_w':None, 37 | 'img_h':32, 38 | 'img_c':3, 39 | 'vertical':True, 40 | 'background_path':'/img/', 41 | 'font_path':'./fonts/' 42 | }) 43 | 44 | # Network parameters 45 | train_batch_size = 96 46 | val_batch_size = 128 47 | 48 | downsample_factor = 4 49 | max_text_len = 9 50 | 51 | locked_layers = False 52 | 53 | patience = 6 # earlystop 54 | lr = 0.0005 #learn rate 55 | train_steps = 10 56 | val_steps = 5 57 | epoch_num = 100 58 | 59 | img = 'img1' 60 | -------------------------------------------------------------------------------- /CRNN/dataset.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | ''' 4 | @author: tianxiaomo 5 | @license: (C) Apache. 6 | @contact: huguanghao520@gmail.com 7 | @software: 8 | @file: dataset.py 9 | @time: 2019/1/7 22:10 10 | @desc: 11 | ''' 12 | import numpy as np 13 | from keras.utils import Sequence 14 | 15 | from data_generator.generator import gen_data 16 | import cfg 17 | 18 | class DATA_V_Sequence(Sequence): 19 | def __init__(self,train=True,img_w=cfg.img_w,img_h=cfg.img_h,img_c=cfg.img_c): 20 | if train == False: 21 | self.batch_size = cfg.val_batch_size 22 | else: 23 | self.batch_size = cfg.train_batch_size 24 | self.img_w = img_w 25 | self.img_h = img_h 26 | self.img_c = img_c 27 | 28 | with open(cfg.char_path, 'r', encoding='utf-8') as file: 29 | self.char_dict = {num: char.strip() for num, char in enumerate(file.readlines())} 30 | self.num_dict = {char: num for num, char in self.char_dict.items()} 31 | self.lexicon_len = len(self.char_dict) 32 | 33 | def __len__(self): 34 | return self.batch_size 35 | 36 | def __getitem__(self, item): 37 | maxlabellen = self.img_w//8 38 | images = np.zeros([self.batch_size, self.img_h, self.img_w, self.img_c]) 39 | labels = np.zeros([self.batch_size, maxlabellen], dtype=np.int32) 40 | input_length = np.zeros([self.batch_size, 1], dtype=np.int32) 41 | label_length = np.zeros([self.batch_size, 1]) 42 | 43 | for i in range(self.batch_size): 44 | img, text = gen_data(cfg.data_para) 45 | img = np.asarray(img) 46 | _,w,_ = img.shape 47 | l = (cfg.img_w - w) // 2 48 | r = cfg.img_w - w - l 49 | # img = np.pad(img,((0,0),(l,r),(0,0)),'edge') 50 | img = np.pad(img, ((0, 0), (l, r), (0, 0)), 'constant',constant_values=(0,0)) 51 | images[i] = img 52 | label = [] 53 | for j in text: 54 | try: 55 | num = self.num_dict.get(j) 56 | if num is None: 57 | num = 0 58 | label.append(num) 59 | except Exception: 60 | label.append(0) 61 | 62 | label_len = len(label) 63 | 64 | try: 65 | labels[i, :label_len] = label 66 | except TypeError: 67 | print(label) 68 | input_length[i] = self.img_w // 4 + 1 69 | label_length[i] = label_len 70 | 71 | inputs = {'input_image': images, 72 | 'the_labels': labels, 73 | 'input_length': input_length, 74 | 'label_length': label_length, 75 | } 76 | outputs = {'ctc': np.zeros([self.batch_size])} 77 | 78 | return inputs, outputs 79 | 80 | 81 | if __name__ == '__main__': 82 | # for i in range(100): 83 | # x,y = data_gen() 84 | a = DATA_V_Sequence() 85 | a.__getitem__(6) 86 | 87 | -------------------------------------------------------------------------------- /CRNN/img/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/0.jpg -------------------------------------------------------------------------------- /CRNN/img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/1.jpg -------------------------------------------------------------------------------- /CRNN/img/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/10.jpg -------------------------------------------------------------------------------- /CRNN/img/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/11.jpg -------------------------------------------------------------------------------- /CRNN/img/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/12.jpg -------------------------------------------------------------------------------- /CRNN/img/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/13.jpg -------------------------------------------------------------------------------- /CRNN/img/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/14.jpg -------------------------------------------------------------------------------- /CRNN/img/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/15.jpg -------------------------------------------------------------------------------- /CRNN/img/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/16.jpg -------------------------------------------------------------------------------- /CRNN/img/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/17.jpg -------------------------------------------------------------------------------- /CRNN/img/18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/18.jpg -------------------------------------------------------------------------------- /CRNN/img/19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/19.jpg -------------------------------------------------------------------------------- /CRNN/img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/2.jpg -------------------------------------------------------------------------------- /CRNN/img/20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/20.jpg -------------------------------------------------------------------------------- /CRNN/img/21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/21.jpg -------------------------------------------------------------------------------- /CRNN/img/22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/22.jpg -------------------------------------------------------------------------------- /CRNN/img/23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/23.jpg -------------------------------------------------------------------------------- /CRNN/img/24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/24.jpg -------------------------------------------------------------------------------- /CRNN/img/25.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/25.jpg -------------------------------------------------------------------------------- /CRNN/img/26.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/26.jpg -------------------------------------------------------------------------------- /CRNN/img/27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/27.jpg -------------------------------------------------------------------------------- /CRNN/img/28.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/28.jpg -------------------------------------------------------------------------------- /CRNN/img/29.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/29.jpg -------------------------------------------------------------------------------- /CRNN/img/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/3.jpg -------------------------------------------------------------------------------- /CRNN/img/30.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/30.jpg -------------------------------------------------------------------------------- /CRNN/img/31.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/31.jpg -------------------------------------------------------------------------------- /CRNN/img/32.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/32.jpg -------------------------------------------------------------------------------- /CRNN/img/33.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/33.jpg -------------------------------------------------------------------------------- /CRNN/img/34.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/34.jpg -------------------------------------------------------------------------------- /CRNN/img/35.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/35.jpg -------------------------------------------------------------------------------- /CRNN/img/36.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/36.jpg -------------------------------------------------------------------------------- /CRNN/img/37.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/37.jpg -------------------------------------------------------------------------------- /CRNN/img/38.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/38.jpg -------------------------------------------------------------------------------- /CRNN/img/39.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/39.jpg -------------------------------------------------------------------------------- /CRNN/img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/4.jpg -------------------------------------------------------------------------------- /CRNN/img/40.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/40.jpg -------------------------------------------------------------------------------- /CRNN/img/41.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/41.jpg -------------------------------------------------------------------------------- /CRNN/img/42.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/42.jpg -------------------------------------------------------------------------------- /CRNN/img/43.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/43.jpg -------------------------------------------------------------------------------- /CRNN/img/44.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/44.jpg -------------------------------------------------------------------------------- /CRNN/img/45.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/45.jpg -------------------------------------------------------------------------------- /CRNN/img/46.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/46.jpg -------------------------------------------------------------------------------- /CRNN/img/47.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/47.jpg -------------------------------------------------------------------------------- /CRNN/img/48.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/48.jpg -------------------------------------------------------------------------------- /CRNN/img/49.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/49.jpg -------------------------------------------------------------------------------- /CRNN/img/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/5.jpg -------------------------------------------------------------------------------- /CRNN/img/50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/50.jpg -------------------------------------------------------------------------------- /CRNN/img/51.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/51.jpg -------------------------------------------------------------------------------- /CRNN/img/52.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/52.jpg -------------------------------------------------------------------------------- /CRNN/img/53.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/53.jpg -------------------------------------------------------------------------------- /CRNN/img/54.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/54.jpg -------------------------------------------------------------------------------- /CRNN/img/55.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/55.jpg -------------------------------------------------------------------------------- /CRNN/img/56.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/56.jpg -------------------------------------------------------------------------------- /CRNN/img/57.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/57.jpg -------------------------------------------------------------------------------- /CRNN/img/58.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/58.jpg -------------------------------------------------------------------------------- /CRNN/img/59.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/59.jpg -------------------------------------------------------------------------------- /CRNN/img/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/6.jpg -------------------------------------------------------------------------------- /CRNN/img/60.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/60.jpg -------------------------------------------------------------------------------- /CRNN/img/61.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/61.jpg -------------------------------------------------------------------------------- /CRNN/img/62.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/62.jpg -------------------------------------------------------------------------------- /CRNN/img/63.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/63.jpg -------------------------------------------------------------------------------- /CRNN/img/64.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/64.jpg -------------------------------------------------------------------------------- /CRNN/img/65.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/65.jpg -------------------------------------------------------------------------------- /CRNN/img/66.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/66.jpg -------------------------------------------------------------------------------- /CRNN/img/67.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/67.jpg -------------------------------------------------------------------------------- /CRNN/img/68.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/68.jpg -------------------------------------------------------------------------------- /CRNN/img/69.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/69.jpg -------------------------------------------------------------------------------- /CRNN/img/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/7.jpg -------------------------------------------------------------------------------- /CRNN/img/70.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/70.jpg -------------------------------------------------------------------------------- /CRNN/img/71.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/71.jpg -------------------------------------------------------------------------------- /CRNN/img/72.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/72.jpg -------------------------------------------------------------------------------- /CRNN/img/73.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/73.jpg -------------------------------------------------------------------------------- /CRNN/img/74.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/74.jpg -------------------------------------------------------------------------------- /CRNN/img/75.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/75.jpg -------------------------------------------------------------------------------- /CRNN/img/76.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/76.jpg -------------------------------------------------------------------------------- /CRNN/img/77.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/77.jpg -------------------------------------------------------------------------------- /CRNN/img/78.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/78.jpg -------------------------------------------------------------------------------- /CRNN/img/79.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/79.jpg -------------------------------------------------------------------------------- /CRNN/img/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/8.jpg -------------------------------------------------------------------------------- /CRNN/img/80.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/80.jpg -------------------------------------------------------------------------------- /CRNN/img/81.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/81.jpg -------------------------------------------------------------------------------- /CRNN/img/82.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/82.jpg -------------------------------------------------------------------------------- /CRNN/img/83.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/83.jpg -------------------------------------------------------------------------------- /CRNN/img/84.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/84.jpg -------------------------------------------------------------------------------- /CRNN/img/85.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/85.jpg -------------------------------------------------------------------------------- /CRNN/img/86.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/86.jpg -------------------------------------------------------------------------------- /CRNN/img/87.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/87.jpg -------------------------------------------------------------------------------- /CRNN/img/88.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/88.jpg -------------------------------------------------------------------------------- /CRNN/img/89.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/89.jpg -------------------------------------------------------------------------------- /CRNN/img/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/9.jpg -------------------------------------------------------------------------------- /CRNN/img/90.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/90.jpg -------------------------------------------------------------------------------- /CRNN/img/91.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/91.jpg -------------------------------------------------------------------------------- /CRNN/img/92.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/92.jpg -------------------------------------------------------------------------------- /CRNN/img/93.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/93.jpg -------------------------------------------------------------------------------- /CRNN/img/94.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/94.jpg -------------------------------------------------------------------------------- /CRNN/img/95.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianxiaomo/Cultural_Inheritance-Recognizing_Chinese_Calligraphy_in_Multiple_Scenarios/adc083ede70998217616d73e3525b0a3d4d324a5/CRNN/img/95.jpg -------------------------------------------------------------------------------- /CRNN/model.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | ''' 4 | @author: tianxiaomo 5 | @license: (C) Apache. 6 | @contact: huguanghao520@gmail.com 7 | @software: 8 | @file: model.py 9 | @time: 2019/1/7 15:59 10 | @desc: 11 | ''' 12 | from keras import layers 13 | from keras import backend 14 | from keras.backend import transpose 15 | from keras.layers import * 16 | # from keras.backend impor 17 | from keras import Model 18 | from keras.applications import DenseNet121 19 | import tensorflow as tf 20 | 21 | import cfg 22 | 23 | # Total params: 12,147,637 24 | # Trainable params: 12,145,077 25 | # Non-trainable params: 2,560 26 | class CRNN: 27 | ''' 28 | CRNN : CNN(vgg16) + RNN(BLSTM) + CTC 29 | ''' 30 | def __init__(self, 31 | weight=None, 32 | num=cfg.num_classes, 33 | img_w=cfg.img_w, 34 | img_h=cfg.img_h, 35 | img_c=cfg.img_c): 36 | 37 | self.input_img = Input(name='input_image',shape=(img_h,img_w,img_c),dtype='float32') 38 | self.num = num 39 | model = self.build_model() 40 | if weight: 41 | print(weight) 42 | model.load_weights(weight) 43 | self.model = model 44 | 45 | def build_model(self): 46 | 47 | x = Conv2D(64, (3, 3),activation='relu',padding='same',name='block1_conv1')(self.input_img) 48 | x = MaxPooling2D(2, strides=2, name='block1_pool')(x) # 64x16x64 49 | 50 | x = Conv2D(128, (3, 3),activation='relu',padding='same',name='block2_conv1')(x) 51 | x = MaxPooling2D(2, strides=2, name='block2_pool')(x) # 128x8x32 52 | 53 | x = Conv2D(256, (3, 3),activation='relu',padding='same',name='block3_conv1')(x) 54 | x = BatchNormalization()(x) 55 | x = Conv2D(256, (3, 3),activation='relu',padding='same',name='block3_conv2')(x) 56 | x = MaxPooling2D(2, strides=(2,1), name='block3_pool')(x) 57 | x = convolutional.ZeroPadding2D(padding=(0, 1))(x) # 256x4x16 58 | 59 | x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x) 60 | x = BatchNormalization()(x) 61 | x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x) 62 | x = MaxPooling2D(2, strides=(2,1), name='block4_pool')(x) 63 | x = convolutional.ZeroPadding2D(padding=(0, 1))(x) # 512x2x42 64 | 65 | x = Conv2D(512, (2, 2), activation='relu',name='block5_conv1')(x) 66 | x = BatchNormalization()(x) # 512x1x41 67 | 68 | bn,h,w,c = x.get_shape().as_list() 69 | 70 | x = Reshape((w,c),input_shape=(h,w,c))(x) 71 | 72 | #==============================================RNN===============================================# 73 | x = Bidirectional(LSTM(256,input_shape=(None, 256),return_sequences=True),name='bilstm_1')(x) 74 | x = Dense(256,activation='linear',name='fc_1')(x) 75 | x = Bidirectional(LSTM(256,input_shape=(None, 256),return_sequences=True,name='bilstm_2'))(x) 76 | x = Dense(self.num,activation='softmax',name='output')(x) 77 | 78 | return Model(inputs=self.input_img,outputs=x) 79 | 80 | -------------------------------------------------------------------------------- /CRNN/train.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | ''' 4 | @author: tianxiaomo 5 | @license: (C) Apache. 6 | @contact: huguanghao520@gmail.com 7 | @software: 8 | @file: train.py 9 | @time: 2019/1/7 21:40 10 | @desc: 11 | ''' 12 | import keras.backend as K 13 | from keras.models import Model,load_model 14 | from keras.layers import Lambda,Input 15 | from keras.optimizers import adam,Nadam,Adam 16 | from keras.callbacks import EarlyStopping,ModelCheckpoint,TensorBoard 17 | 18 | import cfg 19 | from model import CRNN 20 | from dataset import DATA_V_Sequence 21 | from util.util import gpuConfig 22 | 23 | gpuConfig(cfg.gpu) 24 | 25 | def train(net): 26 | opt = Adam(lr=cfg.lr,decay=0.0001) 27 | 28 | train_data_seq = DATA_V_Sequence() 29 | val_data_seq = DATA_V_Sequence(train=False) 30 | 31 | labels = Input(name='the_labels', shape=[None], dtype='float32') 32 | input_length = Input(name='input_length', shape=[1], dtype='int64') 33 | label_length = Input(name='label_length', shape=[1], dtype='int64') 34 | # Keras doesn't currently support loss funcs with extra parameters 35 | # so CTC loss is implemented in a lambda layer 36 | def ctc_lambda_func(args): 37 | y_pred, labels, input_length, label_length = args 38 | return K.ctc_batch_cost(labels, y_pred, input_length, label_length) 39 | 40 | y_pred = net.output 41 | loss_out = Lambda(ctc_lambda_func, output_shape=(1,), name='ctc')([y_pred, labels, input_length, label_length]) 42 | model = Model(inputs=[net.input, labels, input_length, label_length], outputs=loss_out) 43 | model.compile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer=opt,metrics=['accuracy']) 44 | 45 | earlystopping = EarlyStopping(monitor='val_loss',mode='min',patience=cfg.patience) 46 | checkpoint = ModelCheckpoint(cfg.model_weights_path,verbose=1,save_best_only=True,save_weights_only=True) 47 | tensorbord = TensorBoard(cfg.tensorboard_dir) 48 | callbacks = [earlystopping,checkpoint,tensorbord] 49 | 50 | model.fit_generator(generator=train_data_seq, 51 | steps_per_epoch=cfg.train_steps, 52 | epochs = cfg.epoch_num, 53 | validation_data = val_data_seq, 54 | validation_steps = cfg.val_steps, 55 | callbacks=callbacks, 56 | workers = 32, 57 | # use_multiprocessing = True 58 | max_queue_size=10, 59 | ) 60 | 61 | 62 | if __name__ == '__main__': 63 | 64 | for i in dir(cfg): 65 | if i != 'char_dict': 66 | print(i, eval('cfg.' + i)) 67 | 68 | model = None 69 | if cfg.model == 'CRNN': 70 | model = CRNN(cfg.checkpoint).model 71 | else: 72 | print('%s is not define!!!' % cfg.model) 73 | train(model) -------------------------------------------------------------------------------- /CRNN/util/util.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | ''' 4 | @author: tianxiaomo 5 | @license: (C) Apache. 6 | @contact: huguanghao520@gmail.com 7 | @software: 8 | @file: util.py 9 | @time: 2019/1/9 14:42 10 | @desc: 11 | ''' 12 | import tensorflow as tf 13 | import keras.backend.tensorflow_backend as KTF 14 | import os 15 | import time 16 | 17 | def getTimeStr(): 18 | return time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) 19 | 20 | def gpuConfig(gpu_num): 21 | import tensorflow as tf 22 | import keras.backend.tensorflow_backend as KTF 23 | import os 24 | if gpu_num is not None: 25 | if isinstance(gpu_num, (list, tuple)): 26 | gpu_num = ','.join(str(i) for i in gpu_num) 27 | os.environ['CUDA_VISIBLE_DEVICES'] = str(gpu_num) 28 | 29 | config = tf.ConfigProto() 30 | config.gpu_options.allow_growth = True 31 | 32 | sess = tf.Session(config=config) 33 | KTF.set_session(sess) 34 | print('GPU config done!') 35 | else: 36 | print('Use CPU!') 37 | # if cfg.gpu != None: 38 | # # gpuConfig(cfg.gpu) -------------------------------------------------------------------------------- /EAST/advanced_east.py: -------------------------------------------------------------------------------- 1 | # import pudb; pu.db 2 | 3 | import os 4 | from keras.callbacks import EarlyStopping, ModelCheckpoint 5 | from keras.optimizers import Adam,Nadam 6 | 7 | import cfg 8 | from network import East,PixelLink 9 | from losses import quad_loss 10 | from data_generator import gen 11 | import tensorflow as tf 12 | import keras.backend as K 13 | from keras.utils import multi_gpu_model 14 | 15 | # num_cores = 1 16 | # GPU = 2 17 | # CPU = 1 18 | # if GPU: 19 | # num_GPU = 1 20 | # num_CPU = 1 21 | # if CPU: 22 | # num_CPU = 1 23 | # num_GPU = 0 24 | # 25 | # config = tf.ConfigProto(intra_op_parallelism_threads=num_cores,\ 26 | # inter_op_parallelism_threads=num_cores, allow_soft_placement=True,\ 27 | # device_count = {'CPU' : num_CPU, 'GPU' : num_GPU}) 28 | # session = tf.Session(config=config) 29 | # K.set_session(session) 30 | 31 | def gpu_config(gpu_num): 32 | import tensorflow as tf 33 | import keras.backend.tensorflow_backend as KTF 34 | import os 35 | if isinstance(gpu_num, (list, tuple)): 36 | gpu_num = ','.join(str(i) for i in gpu_num) 37 | os.environ['CUDA_VISIBLE_DEVICES'] = str(gpu_num) 38 | 39 | config = tf.ConfigProto() 40 | config.gpu_options.allow_growth = True 41 | 42 | sess = tf.Session(config=config) 43 | KTF.set_session(sess) 44 | print('GPU config done!') 45 | 46 | if cfg.gpu != None: 47 | gpu_config(cfg.gpu) 48 | 49 | 50 | def iou(y_true,y_pred): 51 | logits = y_pred[:, :, :, :1] 52 | labels = y_true[:, :, :, :1] 53 | predicts = tf.nn.sigmoid(logits) 54 | 55 | return tf.metrics.mean_iou(labels,predicts,num_classes=2) 56 | 57 | def iou_loss_core(y_true, y_pred, smooth=1): 58 | y_pred = y_pred[:, :, :, :1] 59 | y_true = y_true[:, :, :, :1] 60 | y_pred = tf.nn.sigmoid(y_pred) 61 | intersection = K.sum(K.abs(y_true * y_pred), axis=-1) 62 | union = K.sum(y_true,-1) + K.sum(y_pred,-1) - intersection 63 | iou = (intersection + smooth) / ( union + smooth) 64 | return iou 65 | 66 | east = East() 67 | east_network = east.east_network() 68 | east_network.summary() 69 | 70 | east_network_m = multi_gpu_model(east_network, gpus=4) 71 | 72 | east_network_m.compile(loss=quad_loss, optimizer=Nadam(lr=cfg.lr), 73 | # clipvalue=cfg.clipvalue, 74 | # decay=cfg.decay), 75 | metrics=[iou_loss_core]) 76 | 77 | if cfg.load_weight and os.path.exists(cfg.load_weight): 78 | east_network_m.load_weights(cfg.load_weight) 79 | 80 | east_network.fit_generator(generator=gen(), 81 | steps_per_epoch=cfg.steps_per_epoch, 82 | epochs=cfg.epoch_num, 83 | validation_data=gen(is_val=True), 84 | validation_steps=cfg.validation_steps, 85 | verbose=1, 86 | initial_epoch=cfg.initial_epoch, 87 | callbacks=[EarlyStopping(patience=cfg.patience, verbose=1), 88 | ModelCheckpoint(filepath=cfg.checkpoint_path, 89 | save_best_only=True, 90 | save_weights_only=True, 91 | verbose=1)]) 92 | 93 | # east_network.save(cfg.saved_model_file_path) 94 | east_network.save_weights(cfg.saved_model_weights_file_path) 95 | -------------------------------------------------------------------------------- /EAST/cfg.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | train_task_id = 'ICDAR2015T640' 4 | initial_epoch = 0 5 | epoch_num = 24 6 | lr = 1e-4 7 | decay = 5e-4 8 | # clipvalue = 0.5 # default 0.5, 0 means no clip 9 | patience = 5 10 | load_weights = True 11 | lambda_inside_score_loss = 4.0 12 | lambda_side_vertex_code_loss = 1.0 13 | lambda_side_vertex_coord_loss = 1.0 14 | 15 | total_img = 60000 16 | validation_split_ratio = 0.1 17 | max_train_img_size = int(train_task_id[-3:]) 18 | max_predict_img_size = int(train_task_id[-3:]) # 2400 19 | assert max_train_img_size in [256, 384, 512, 640, 736], \ 20 | 'max_train_img_size must in [256, 384, 512, 640, 736]' 21 | if max_train_img_size == 256: 22 | batch_size = 8 23 | elif max_train_img_size == 384: 24 | batch_size = 4 25 | elif max_train_img_size == 512: 26 | batch_size = 2 27 | else: 28 | batch_size = 8 29 | steps_per_epoch = 50000 // batch_size 30 | validation_steps = 10000 // batch_size 31 | 32 | # data_dir = '/home/huguanghao2/Data/DF_zh/train_dataset_char/' 33 | data_dir = '/home/huguanghao2/Data/DF_zh/train_dataset_char/' 34 | #=====================================================================# 35 | 36 | origin_image_dir_name = 'train_Image/' 37 | origin_txt_dir_name = 'train_lable.csv' 38 | 39 | origin_val_image_dir_name = 'verify_Image/' 40 | origin_val_txt_dir_name = 'verify_lable.csv' 41 | 42 | origin_test_image_dir_name = '../test_dataset_char/' 43 | origin_test_txt_dir_name = 'verify_lable.csv' 44 | 45 | #======================================================================# 46 | 47 | train_image_dir_name = 'images_%s/' % train_task_id 48 | train_label_dir_name = 'labels_%s/' % train_task_id 49 | 50 | val_image_dir_name = 'images_%s/' % train_task_id 51 | val_label_dir_name = 'labels_%s/' % train_task_id 52 | 53 | test_image_dir_name = 'images_test_%s/' % train_task_id 54 | test_label_dir_name = 'labels_test_%s/' % train_task_id 55 | 56 | #======================================================================# 57 | 58 | show_gt_image_dir_name = 'show_gt_images_%s/' % train_task_id 59 | show_act_image_dir_name = 'show_act_images_%s/' % train_task_id 60 | 61 | gen_origin_img = True 62 | draw_gt_quad = True 63 | draw_act_quad = True 64 | 65 | val_fname = 'val_%s.txt' % train_task_id 66 | train_fname = 'train_%s.txt' % train_task_id 67 | # in paper it's 0.3, maybe to large to this problem 68 | shrink_ratio = 0.2 69 | # pixels between 0.2 and 0.6 are side pixels 70 | shrink_side_ratio = 0.6 71 | epsilon = 1e-4 72 | 73 | num_channels = 3 74 | feature_layers_range = range(5, 1, -1) 75 | # feature_layers_range = range(3, 0, -1) 76 | feature_layers_num = len(feature_layers_range) 77 | # pixel_size = 4 78 | pixel_size = 2 ** feature_layers_range[-1] 79 | locked_layers = False 80 | 81 | if not os.path.exists('model'): 82 | os.mkdir('model') 83 | if not os.path.exists('saved_model'): 84 | os.mkdir('saved_model') 85 | 86 | checkpoint_path = 'checkpoints/weights_%s.{epoch:03d}-{val_loss:.3f}.h5' \ 87 | % train_task_id 88 | 89 | load_weight = 'checkpoints/weights_ICDAR2015T640.001-0.587.h5' 90 | 91 | saved_model_weights_file_path = 'saved_models/east_model_weights_%s.h5'\ 92 | % train_task_id 93 | 94 | pixel_threshold = 0.7 95 | side_vertex_pixel_threshold = 0.9 96 | trunc_threshold = 0.1 97 | predict_cut_text_line = False 98 | predict_write2txt = True 99 | 100 | gpu = 1 -------------------------------------------------------------------------------- /EAST/data_generator.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | from keras.preprocessing import image 4 | from keras.applications.vgg16 import preprocess_input 5 | 6 | import cfg 7 | 8 | 9 | def gen(batch_size=cfg.batch_size, is_val=False): 10 | img_h, img_w = cfg.max_train_img_size, cfg.max_train_img_size 11 | x = np.zeros((batch_size, img_h, img_w, cfg.num_channels), dtype=np.float32) 12 | pixel_num_h = img_h // cfg.pixel_size 13 | pixel_num_w = img_w // cfg.pixel_size 14 | y = np.zeros((batch_size, pixel_num_h, pixel_num_w, 7), dtype=np.float32) 15 | if is_val: 16 | with open(os.path.join(cfg.data_dir, cfg.val_fname), 'r') as f_val: 17 | f_list = f_val.readlines() 18 | else: 19 | with open(os.path.join(cfg.data_dir, cfg.train_fname), 'r') as f_train: 20 | f_list = f_train.readlines() 21 | while True: 22 | for i in range(batch_size): 23 | # random gen an image name 24 | random_img = np.random.choice(f_list) 25 | img_filename = str(random_img).strip().split(',')[0] 26 | # load img and img anno 27 | img_path = os.path.join(cfg.data_dir, 28 | cfg.train_image_dir_name, 29 | img_filename) 30 | img = image.load_img(img_path) 31 | img = image.img_to_array(img) 32 | x[i] = preprocess_input(img, mode='tf') 33 | gt_file = os.path.join(cfg.data_dir, 34 | cfg.train_label_dir_name, 35 | img_filename[:-4] + '_gt.npy') 36 | y[i] = np.load(gt_file) 37 | yield x, y 38 | -------------------------------------------------------------------------------- /EAST/label.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from PIL import Image, ImageDraw 4 | from tqdm import tqdm 5 | from EAST import cfg 6 | 7 | 8 | def point_inside_of_quad(px, py, quad_xy_list, p_min, p_max): 9 | if (p_min[0] <= px <= p_max[0]) and (p_min[1] <= py <= p_max[1]): 10 | xy_list = np.zeros((4, 2)) 11 | xy_list[:3, :] = quad_xy_list[1:4, :] - quad_xy_list[:3, :] 12 | xy_list[3] = quad_xy_list[0, :] - quad_xy_list[3, :] 13 | yx_list = np.zeros((4, 2)) 14 | yx_list[:, :] = quad_xy_list[:, -1:-3:-1] 15 | a = xy_list * ([py, px] - yx_list) 16 | b = a[:, 0] - a[:, 1] 17 | if np.amin(b) >= 0 or np.amax(b) <= 0: 18 | return True 19 | else: 20 | return False 21 | else: 22 | return False 23 | 24 | 25 | def point_inside_of_nth_quad(px, py, xy_list, shrink_1, long_edge): 26 | nth = -1 27 | vs = [[[0, 0, 3, 3, 0], [1, 1, 2, 2, 1]], 28 | [[0, 0, 1, 1, 0], [2, 2, 3, 3, 2]]] 29 | for ith in range(2): 30 | quad_xy_list = np.concatenate(( 31 | np.reshape(xy_list[vs[long_edge][ith][0]], (1, 2)), 32 | np.reshape(shrink_1[vs[long_edge][ith][1]], (1, 2)), 33 | np.reshape(shrink_1[vs[long_edge][ith][2]], (1, 2)), 34 | np.reshape(xy_list[vs[long_edge][ith][3]], (1, 2))), axis=0) 35 | p_min = np.amin(quad_xy_list, axis=0) 36 | p_max = np.amax(quad_xy_list, axis=0) 37 | if point_inside_of_quad(px, py, quad_xy_list, p_min, p_max): 38 | if nth == -1: 39 | nth = ith 40 | else: 41 | nth = -1 42 | break 43 | return nth 44 | 45 | 46 | def shrink(xy_list, ratio=cfg.shrink_ratio): 47 | if ratio == 0.0: 48 | return xy_list, xy_list 49 | diff_1to3 = xy_list[:3, :] - xy_list[1:4, :] 50 | diff_4 = xy_list[3:4, :] - xy_list[0:1, :] 51 | diff = np.concatenate((diff_1to3, diff_4), axis=0) 52 | dis = np.sqrt(np.sum(np.square(diff), axis=-1)) 53 | # determine which are long or short edges 54 | long_edge = int(np.argmax(np.sum(np.reshape(dis, (2, 2)), axis=0))) 55 | short_edge = 1 - long_edge 56 | # cal r length array 57 | r = [np.minimum(dis[i], dis[(i + 1) % 4]) for i in range(4)] 58 | # cal theta array 59 | diff_abs = np.abs(diff) 60 | diff_abs[:, 0] += cfg.epsilon 61 | theta = np.arctan(diff_abs[:, 1] / diff_abs[:, 0]) 62 | # shrink two long edges 63 | temp_new_xy_list = np.copy(xy_list) 64 | shrink_edge(xy_list, temp_new_xy_list, long_edge, r, theta, ratio) 65 | shrink_edge(xy_list, temp_new_xy_list, long_edge + 2, r, theta, ratio) 66 | # shrink two short edges 67 | new_xy_list = np.copy(temp_new_xy_list) 68 | shrink_edge(temp_new_xy_list, new_xy_list, short_edge, r, theta, ratio) 69 | shrink_edge(temp_new_xy_list, new_xy_list, short_edge + 2, r, theta, ratio) 70 | return temp_new_xy_list, new_xy_list, long_edge 71 | 72 | 73 | def shrink_edge(xy_list, new_xy_list, edge, r, theta, ratio=cfg.shrink_ratio): 74 | if ratio == 0.0: 75 | return 76 | start_point = edge 77 | end_point = (edge + 1) % 4 78 | long_start_sign_x = np.sign( 79 | xy_list[end_point, 0] - xy_list[start_point, 0]) 80 | new_xy_list[start_point, 0] = \ 81 | xy_list[start_point, 0] + \ 82 | long_start_sign_x * ratio * r[start_point] * np.cos(theta[start_point]) 83 | long_start_sign_y = np.sign( 84 | xy_list[end_point, 1] - xy_list[start_point, 1]) 85 | new_xy_list[start_point, 1] = \ 86 | xy_list[start_point, 1] + \ 87 | long_start_sign_y * ratio * r[start_point] * np.sin(theta[start_point]) 88 | # long edge one, end point 89 | long_end_sign_x = -1 * long_start_sign_x 90 | new_xy_list[end_point, 0] = \ 91 | xy_list[end_point, 0] + \ 92 | long_end_sign_x * ratio * r[end_point] * np.cos(theta[start_point]) 93 | long_end_sign_y = -1 * long_start_sign_y 94 | new_xy_list[end_point, 1] = \ 95 | xy_list[end_point, 1] + \ 96 | long_end_sign_y * ratio * r[end_point] * np.sin(theta[start_point]) 97 | 98 | 99 | def process_label(data_dir=cfg.data_dir): 100 | print(cfg.train_task_id) 101 | # with open(os.path.join(data_dir, cfg.train_fname), 'r') as f_val: 102 | # f_list = f_val.readlines() 103 | with open(os.path.join(data_dir, cfg.train_fname), 'r') as f_train: 104 | f_list =f_train.readlines() 105 | for line in tqdm(f_list): 106 | line_cols = str(line).strip().split(',') 107 | img_name, width, height = \ 108 | line_cols[0].strip(), int(line_cols[1].strip()), \ 109 | int(line_cols[2].strip()) 110 | gt = np.zeros((height // cfg.pixel_size, width // cfg.pixel_size, 7)) 111 | train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) 112 | xy_list_array = np.load(os.path.join(train_label_dir, 113 | img_name[:-4] + '.npy')) 114 | train_image_dir = os.path.join(data_dir, cfg.train_image_dir_name) 115 | with Image.open(os.path.join(train_image_dir, img_name)) as im: 116 | draw = ImageDraw.Draw(im) 117 | for xy_list in xy_list_array: 118 | _, shrink_xy_list, _ = shrink(xy_list, cfg.shrink_ratio) 119 | shrink_1, _, long_edge = shrink(xy_list, cfg.shrink_side_ratio) 120 | p_min = np.amin(shrink_xy_list, axis=0) 121 | p_max = np.amax(shrink_xy_list, axis=0) 122 | # floor of the float 123 | ji_min = (p_min / cfg.pixel_size - 0.5).astype(int) - 1 124 | # +1 for ceil of the float and +1 for include the end 125 | ji_max = (p_max / cfg.pixel_size - 0.5).astype(int) + 3 126 | imin = np.maximum(0, ji_min[1]) 127 | imax = np.minimum(height // cfg.pixel_size, ji_max[1]) 128 | jmin = np.maximum(0, ji_min[0]) 129 | jmax = np.minimum(width // cfg.pixel_size, ji_max[0]) 130 | for i in range(imin, imax): 131 | for j in range(jmin, jmax): 132 | px = (j + 0.5) * cfg.pixel_size 133 | py = (i + 0.5) * cfg.pixel_size 134 | if point_inside_of_quad(px, py, 135 | shrink_xy_list, p_min, p_max): 136 | gt[i, j, 0] = 1 137 | line_width, line_color = 1, 'red' 138 | ith = point_inside_of_nth_quad(px, py, 139 | xy_list, 140 | shrink_1, 141 | long_edge) 142 | vs = [[[3, 0], [1, 2]], [[0, 1], [2, 3]]] 143 | if ith in range(2): 144 | gt[i, j, 1] = 1 145 | if ith == 0: 146 | line_width, line_color = 2, 'yellow' 147 | else: 148 | line_width, line_color = 2, 'green' 149 | gt[i, j, 2:3] = ith 150 | gt[i, j, 3:5] = \ 151 | xy_list[vs[long_edge][ith][0]] - [px, py] 152 | gt[i, j, 5:] = \ 153 | xy_list[vs[long_edge][ith][1]] - [px, py] 154 | draw.line([(px - 0.5 * cfg.pixel_size, 155 | py - 0.5 * cfg.pixel_size), 156 | (px + 0.5 * cfg.pixel_size, 157 | py - 0.5 * cfg.pixel_size), 158 | (px + 0.5 * cfg.pixel_size, 159 | py + 0.5 * cfg.pixel_size), 160 | (px - 0.5 * cfg.pixel_size, 161 | py + 0.5 * cfg.pixel_size), 162 | (px - 0.5 * cfg.pixel_size, 163 | py - 0.5 * cfg.pixel_size)], 164 | width=line_width, fill=line_color) 165 | act_image_dir = os.path.join(cfg.data_dir, 166 | cfg.show_act_image_dir_name) 167 | if cfg.draw_act_quad: 168 | im.save(os.path.join(act_image_dir, img_name)) 169 | train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) 170 | np.save(os.path.join(train_label_dir, 171 | img_name[:-4] + '_gt.npy'), gt) 172 | 173 | 174 | if __name__ == '__main__': 175 | # process_label() 176 | import multiprocessing as mlp 177 | from multiprocessing import Pool 178 | 179 | with open(os.path.join(cfg.data_dir, cfg.train_fname), 'r') as f_train: 180 | f_list = f_train.readlines() 181 | # 任务数量 182 | num = len(f_list) 183 | data_dir = cfg.data_dir 184 | # 子任务 185 | def task(f_list,a, b): 186 | for line in tqdm(f_list[a:b]): 187 | line_cols = str(line).strip().split(',') 188 | img_name, width, height = \ 189 | line_cols[0].strip(), int(line_cols[1].strip()), \ 190 | int(line_cols[2].strip()) 191 | gt = np.zeros((height // cfg.pixel_size, width // cfg.pixel_size, 7)) 192 | train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) 193 | xy_list_array = np.load(os.path.join(train_label_dir, 194 | img_name[:-4] + '.npy')) 195 | train_image_dir = os.path.join(data_dir, cfg.train_image_dir_name) 196 | with Image.open(os.path.join(train_image_dir, img_name)) as im: 197 | draw = ImageDraw.Draw(im) 198 | for xy_list in xy_list_array: 199 | _, shrink_xy_list, _ = shrink(xy_list, cfg.shrink_ratio) 200 | shrink_1, _, long_edge = shrink(xy_list, cfg.shrink_side_ratio) 201 | p_min = np.amin(shrink_xy_list, axis=0) 202 | p_max = np.amax(shrink_xy_list, axis=0) 203 | # floor of the float 204 | ji_min = (p_min / cfg.pixel_size - 0.5).astype(int) - 1 205 | # +1 for ceil of the float and +1 for include the end 206 | ji_max = (p_max / cfg.pixel_size - 0.5).astype(int) + 3 207 | imin = np.maximum(0, ji_min[1]) 208 | imax = np.minimum(height // cfg.pixel_size, ji_max[1]) 209 | jmin = np.maximum(0, ji_min[0]) 210 | jmax = np.minimum(width // cfg.pixel_size, ji_max[0]) 211 | for i in range(imin, imax): 212 | for j in range(jmin, jmax): 213 | px = (j + 0.5) * cfg.pixel_size 214 | py = (i + 0.5) * cfg.pixel_size 215 | if point_inside_of_quad(px, py, 216 | shrink_xy_list, p_min, p_max): 217 | gt[i, j, 0] = 1 218 | line_width, line_color = 1, 'red' 219 | ith = point_inside_of_nth_quad(px, py, 220 | xy_list, 221 | shrink_1, 222 | long_edge) 223 | vs = [[[3, 0], [1, 2]], [[0, 1], [2, 3]]] 224 | if ith in range(2): 225 | gt[i, j, 1] = 1 226 | if ith == 0: 227 | line_width, line_color = 2, 'yellow' 228 | else: 229 | line_width, line_color = 2, 'green' 230 | gt[i, j, 2:3] = ith 231 | gt[i, j, 3:5] = \ 232 | xy_list[vs[long_edge][ith][0]] - [px, py] 233 | gt[i, j, 5:] = \ 234 | xy_list[vs[long_edge][ith][1]] - [px, py] 235 | draw.line([(px - 0.5 * cfg.pixel_size, 236 | py - 0.5 * cfg.pixel_size), 237 | (px + 0.5 * cfg.pixel_size, 238 | py - 0.5 * cfg.pixel_size), 239 | (px + 0.5 * cfg.pixel_size, 240 | py + 0.5 * cfg.pixel_size), 241 | (px - 0.5 * cfg.pixel_size, 242 | py + 0.5 * cfg.pixel_size), 243 | (px - 0.5 * cfg.pixel_size, 244 | py - 0.5 * cfg.pixel_size)], 245 | width=line_width, fill=line_color) 246 | act_image_dir = os.path.join(cfg.data_dir, 247 | cfg.show_act_image_dir_name) 248 | if cfg.draw_act_quad: 249 | im.save(os.path.join(act_image_dir, img_name)) 250 | train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) 251 | np.save(os.path.join(train_label_dir, 252 | img_name[:-4] + '_gt.npy'), gt) 253 | return 0 254 | 255 | # 线程池 256 | p = Pool() 257 | n_cpu = mlp.cpu_count() 258 | split = num // n_cpu 259 | res = [] 260 | for i in range(n_cpu): 261 | a = split * i 262 | if i == n_cpu - 1: 263 | b = num 264 | else: 265 | b = split * (i + 1) 266 | res.append(p.apply_async(task, args=(f_list,a, b))) 267 | 268 | for r in res: 269 | print(r.get()) 270 | 271 | p.close() 272 | p.join() -------------------------------------------------------------------------------- /EAST/losses.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | 3 | import cfg 4 | 5 | 6 | def quad_loss(y_true, y_pred): 7 | # loss for inside_score 8 | logits = y_pred[:, :, :, :1] 9 | labels = y_true[:, :, :, :1] 10 | # balance positive and negative samples in an image 11 | beta = 1 - tf.reduce_mean(labels) 12 | # first apply sigmoid activation 13 | predicts = tf.nn.sigmoid(logits) 14 | # log +epsilon for stable cal 15 | inside_score_loss = tf.reduce_mean( 16 | -1 * (beta * labels * tf.log(predicts + cfg.epsilon) + 17 | (1 - beta) * (1 - labels) * tf.log(1 - predicts + cfg.epsilon))) 18 | inside_score_loss *= cfg.lambda_inside_score_loss 19 | 20 | # loss for side_vertex_code 21 | vertex_logits = y_pred[:, :, :, 1:3] 22 | vertex_labels = y_true[:, :, :, 1:3] 23 | vertex_beta = 1 - (tf.reduce_mean(y_true[:, :, :, 1:2]) 24 | / (tf.reduce_mean(labels) + cfg.epsilon)) 25 | vertex_predicts = tf.nn.sigmoid(vertex_logits) 26 | pos = -1 * vertex_beta * vertex_labels * tf.log(vertex_predicts + 27 | cfg.epsilon) 28 | neg = -1 * (1 - vertex_beta) * (1 - vertex_labels) * tf.log( 29 | 1 - vertex_predicts + cfg.epsilon) 30 | positive_weights = tf.cast(tf.equal(y_true[:, :, :, 0], 1), tf.float32) 31 | side_vertex_code_loss = \ 32 | tf.reduce_sum(tf.reduce_sum(pos + neg, axis=-1) * positive_weights) / ( 33 | tf.reduce_sum(positive_weights) + cfg.epsilon) 34 | side_vertex_code_loss *= cfg.lambda_side_vertex_code_loss 35 | 36 | # loss for side_vertex_coord delta 37 | g_hat = y_pred[:, :, :, 3:] 38 | g_true = y_true[:, :, :, 3:] 39 | vertex_weights = tf.cast(tf.equal(y_true[:, :, :, 1], 1), tf.float32) 40 | pixel_wise_smooth_l1norm = smooth_l1_loss(g_hat, g_true, vertex_weights) 41 | side_vertex_coord_loss = tf.reduce_sum(pixel_wise_smooth_l1norm) / ( 42 | tf.reduce_sum(vertex_weights) + cfg.epsilon) 43 | side_vertex_coord_loss *= cfg.lambda_side_vertex_coord_loss 44 | return inside_score_loss + side_vertex_code_loss + side_vertex_coord_loss 45 | 46 | 47 | def smooth_l1_loss(prediction_tensor, target_tensor, weights): 48 | n_q = tf.reshape(quad_norm(target_tensor), tf.shape(weights)) 49 | diff = prediction_tensor - target_tensor 50 | abs_diff = tf.abs(diff) 51 | abs_diff_lt_1 = tf.less(abs_diff, 1) 52 | pixel_wise_smooth_l1norm = (tf.reduce_sum( 53 | tf.where(abs_diff_lt_1, 0.5 * tf.square(abs_diff), abs_diff - 0.5), 54 | axis=-1) / n_q) * weights 55 | return pixel_wise_smooth_l1norm 56 | 57 | 58 | def quad_norm(g_true): 59 | shape = tf.shape(g_true) 60 | delta_xy_matrix = tf.reshape(g_true, [-1, 2, 2]) 61 | diff = delta_xy_matrix[:, 0:1, :] - delta_xy_matrix[:, 1:2, :] 62 | square = tf.square(diff) 63 | distance = tf.sqrt(tf.reduce_sum(square, axis=-1)) 64 | distance *= 4.0 65 | distance += cfg.epsilon 66 | return tf.reshape(distance, shape[:-1]) 67 | -------------------------------------------------------------------------------- /EAST/network.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | from keras import Input, Model 3 | from keras.applications.vgg16 import VGG16 4 | from keras.applications.resnet50 import ResNet50 5 | from keras.layers import Concatenate, Conv2D, UpSampling2D, BatchNormalization,add 6 | 7 | import cv2 8 | import numpy as np 9 | 10 | import cfg 11 | 12 | """ 13 | input_shape=(img.height, img.width, 3), height and width must scaled by 32. 14 | So images's height and width need to be pre-processed to the nearest num that 15 | scaled by 32.And the annotations xy need to be scaled by the same ratio 16 | as height and width respectively. 17 | """ 18 | import tensorflow as tf 19 | from keras import backend as K 20 | num_cores = 1 21 | GPU = 0 22 | CPU = 1 23 | if GPU: 24 | num_GPU = 1 25 | num_CPU = 1 26 | if CPU: 27 | num_CPU = 1 28 | num_GPU = 0 29 | 30 | config = tf.ConfigProto(intra_op_parallelism_threads=num_cores,\ 31 | inter_op_parallelism_threads=num_cores, allow_soft_placement=True,\ 32 | device_count = {'CPU' : num_CPU, 'GPU' : num_GPU}) 33 | session = tf.Session(config=config) 34 | K.set_session(session) 35 | 36 | 37 | class East: 38 | 39 | def __init__(self): 40 | self.input_img = Input(name='input_img', 41 | shape=(None, None, cfg.num_channels), 42 | dtype='float32') 43 | vgg16 = VGG16(input_tensor=self.input_img, 44 | # weights='imagenet', 45 | include_top=False) 46 | if cfg.locked_layers: 47 | # locked first two conv layers 48 | locked_layers = [vgg16.get_layer('block1_conv1'), 49 | vgg16.get_layer('block1_conv2')] 50 | for layer in locked_layers: 51 | layer.trainable = False 52 | self.f = [vgg16.get_layer('block%d_pool' % i).output 53 | for i in cfg.feature_layers_range] 54 | self.f.insert(0, None) 55 | self.diff = cfg.feature_layers_range[0] - cfg.feature_layers_num 56 | 57 | def g(self, i): 58 | # i+diff in cfg.feature_layers_range 59 | assert i + self.diff in cfg.feature_layers_range, \ 60 | ('i=%d+diff=%d not in ' % (i, self.diff)) + \ 61 | str(cfg.feature_layers_range) 62 | if i == cfg.feature_layers_num: 63 | bn = BatchNormalization()(self.h(i)) 64 | return Conv2D(32, 3, activation='relu', padding='same')(bn) 65 | else: 66 | return UpSampling2D((2, 2))(self.h(i)) 67 | 68 | def h(self, i): 69 | # i+diff in cfg.feature_layers_range 70 | assert i + self.diff in cfg.feature_layers_range, \ 71 | ('i=%d+diff=%d not in ' % (i, self.diff)) + \ 72 | str(cfg.feature_layers_range) 73 | if i == 1: 74 | return self.f[i] 75 | else: 76 | concat = Concatenate(axis=-1)([self.g(i - 1), self.f[i]]) 77 | bn1 = BatchNormalization()(concat) 78 | conv_1 = Conv2D(128 // 2 ** (i - 2), 1, 79 | activation='relu', padding='same',)(bn1) 80 | bn2 = BatchNormalization()(conv_1) 81 | conv_3 = Conv2D(128 // 2 ** (i - 2), 3, 82 | activation='relu', padding='same',)(bn2) 83 | return conv_3 84 | 85 | def east_network(self): 86 | before_output = self.g(cfg.feature_layers_num) 87 | inside_score = Conv2D(1, 1, padding='same', name='inside_score' 88 | )(before_output) 89 | side_v_code = Conv2D(2, 1, padding='same', name='side_vertex_code' 90 | )(before_output) 91 | side_v_coord = Conv2D(4, 1, padding='same', name='side_vertex_coord' 92 | )(before_output) 93 | east_detect = Concatenate(axis=-1, 94 | name='east_detect')([inside_score, 95 | side_v_code, 96 | side_v_coord]) 97 | return Model(inputs=self.input_img, outputs=east_detect) 98 | 99 | 100 | from keras.layers.core import Layer 101 | 102 | class GetBox(Layer): 103 | 104 | def __init__(self, **kwargs): 105 | # self.output_dim = output_shape 106 | super(GetBox, self).__init__(**kwargs) 107 | 108 | def build(self, input_shape): 109 | None 110 | 111 | def call(self, x): 112 | 113 | _,contours, hierarchy = cv2.findContours(x, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 114 | def draw_min_rect_circle(cnts): 115 | rects = [] 116 | for cnt in cnts: 117 | min_rect = cv2.minAreaRect(cnt) 118 | min_rect = np.int0(cv2.boxPoints(min_rect)) 119 | rects.append(min_rect) 120 | return rects 121 | return draw_min_rect_circle(contours) 122 | 123 | def compute_output_shape(self, input_shape): 124 | return (input_shape[0],4,None) 125 | 126 | 127 | class MyEast: 128 | 129 | def __init__(self): 130 | self.input_img = Input(name='input_img', 131 | shape=(None, None, cfg.num_channels), 132 | dtype='float32') 133 | vgg16 = VGG16(input_tensor=self.input_img, 134 | # weights='imagenet', 135 | include_top=False) 136 | if cfg.locked_layers: 137 | # locked first two conv layers 138 | locked_layers = [vgg16.get_layer('block1_conv1'), 139 | vgg16.get_layer('block1_conv2')] 140 | for layer in locked_layers: 141 | layer.trainable = False 142 | self.f = [vgg16.get_layer('block%d_pool' % i).output 143 | for i in cfg.feature_layers_range] 144 | self.f.insert(0, None) 145 | self.diff = cfg.feature_layers_range[0] - cfg.feature_layers_num 146 | 147 | def g(self, i): 148 | # i+diff in cfg.feature_layers_range 149 | assert i + self.diff in cfg.feature_layers_range, \ 150 | ('i=%d+diff=%d not in ' % (i, self.diff)) + \ 151 | str(cfg.feature_layers_range) 152 | if i == cfg.feature_layers_num: 153 | bn = BatchNormalization()(self.h(i)) 154 | return Conv2D(32, 3, activation='relu', padding='same')(bn) 155 | else: 156 | return UpSampling2D((2, 2))(self.h(i)) 157 | 158 | def h(self, i): 159 | # i+diff in cfg.feature_layers_range 160 | assert i + self.diff in cfg.feature_layers_range, \ 161 | ('i=%d+diff=%d not in ' % (i, self.diff)) + \ 162 | str(cfg.feature_layers_range) 163 | if i == 1: 164 | return self.f[i] 165 | else: 166 | concat = Concatenate(axis=-1)([self.g(i - 1), self.f[i]]) 167 | bn1 = BatchNormalization()(concat) 168 | conv_1 = Conv2D(128 // 2 ** (i - 2), 1, 169 | activation='relu', padding='same',)(bn1) 170 | bn2 = BatchNormalization()(conv_1) 171 | conv_3 = Conv2D(128 // 2 ** (i - 2), 3, 172 | activation='relu', padding='same',)(bn2) 173 | return conv_3 174 | 175 | def east_network(self): 176 | before_output = self.g(cfg.feature_layers_num) 177 | inside_score = Conv2D(1, 1, padding='same', name='inside_score' 178 | )(before_output) 179 | side_v_code = Conv2D(2, 1, padding='same', name='side_vertex_code' 180 | )(before_output) 181 | side_v_coord = Conv2D(4, 1, padding='same', name='side_vertex_coord' 182 | )(before_output) 183 | 184 | box = GetBox()(inside_score) 185 | 186 | east_detect = Concatenate(axis=-1, 187 | name='east_detect')([inside_score, 188 | side_v_code, 189 | side_v_coord, 190 | box]) 191 | return Model(inputs=self.input_img, outputs=east_detect) 192 | 193 | def get_box(self,score): 194 | 195 | # tf.findContours() 196 | 197 | _,contours, hierarchy = cv2.findContours(score, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 198 | 199 | def draw_min_rect_circle(cnts): 200 | rects = [] 201 | for cnt in cnts: 202 | min_rect = cv2.minAreaRect(cnt) 203 | min_rect = np.int0(cv2.boxPoints(min_rect)) 204 | rects.append(min_rect) 205 | return rects 206 | 207 | return draw_min_rect_circle(contours) 208 | 209 | 210 | class ResEast: 211 | 212 | def __init__(self): 213 | self.input_img = Input(name='input_img', 214 | shape=(None, None, cfg.num_channels), 215 | dtype='float32') 216 | Res = ResNet50(input_tensor=self.input_img, 217 | # weights='imagenet', 218 | include_top=False) 219 | if cfg.locked_layers: 220 | # locked first two conv layers 221 | locked_layers = [Res.get_layer('block1_conv1'), 222 | Res.get_layer('block1_conv2')] 223 | for layer in locked_layers: 224 | layer.trainable = False 225 | self.f = [Res.get_layer('block%d_pool' % i).output 226 | for i in cfg.feature_layers_range] 227 | self.f.insert(0, None) 228 | self.diff = cfg.feature_layers_range[0] - cfg.feature_layers_num 229 | 230 | def g(self, i): 231 | # i+diff in cfg.feature_layers_range 232 | assert i + self.diff in cfg.feature_layers_range, \ 233 | ('i=%d+diff=%d not in ' % (i, self.diff)) + \ 234 | str(cfg.feature_layers_range) 235 | if i == cfg.feature_layers_num: 236 | bn = BatchNormalization()(self.h(i)) 237 | return Conv2D(32, 3, activation='relu', padding='same')(bn) 238 | else: 239 | return UpSampling2D((2, 2))(self.h(i)) 240 | 241 | def h(self, i): 242 | # i+diff in cfg.feature_layers_range 243 | assert i + self.diff in cfg.feature_layers_range, \ 244 | ('i=%d+diff=%d not in ' % (i, self.diff)) + \ 245 | str(cfg.feature_layers_range) 246 | if i == 1: 247 | return self.f[i] 248 | else: 249 | concat = Concatenate(axis=-1)([self.g(i - 1), self.f[i]]) 250 | bn1 = BatchNormalization()(concat) 251 | conv_1 = Conv2D(128 // 2 ** (i - 2), 1, 252 | activation='relu', padding='same',)(bn1) 253 | bn2 = BatchNormalization()(conv_1) 254 | conv_3 = Conv2D(128 // 2 ** (i - 2), 3, 255 | activation='relu', padding='same',)(bn2) 256 | return conv_3 257 | 258 | def east_network(self): 259 | before_output = self.g(cfg.feature_layers_num) 260 | inside_score = Conv2D(1, 1, padding='same', name='inside_score' 261 | )(before_output) 262 | side_v_code = Conv2D(2, 1, padding='same', name='side_vertex_code' 263 | )(before_output) 264 | side_v_coord = Conv2D(4, 1, padding='same', name='side_vertex_coord' 265 | )(before_output) 266 | east_detect = Concatenate(axis=-1, 267 | name='east_detect')([inside_score, 268 | side_v_code, 269 | side_v_coord]) 270 | return Model(inputs=self.input_img, outputs=east_detect) 271 | 272 | 273 | from keras.engine.topology import Layer 274 | import tensorflow as tf 275 | 276 | class Resize(Layer): 277 | 278 | def __init__(self, output_shape, **kwargs): 279 | self.output_dim = output_shape 280 | super(Resize, self).__init__(**kwargs) 281 | 282 | def build(self, input_shape): 283 | None 284 | 285 | def call(self, x): 286 | return tf.image.resize_images(x,self.output_dim) 287 | 288 | def compute_output_shape(self, input_shape): 289 | return (input_shape[0], self.output_dim[0],self.output_dim[1],input_shape[-1]) 290 | 291 | 292 | class PixelLink: 293 | 294 | def __init__(self): 295 | self.input_img = Input(name='input_img', 296 | shape=(640,640,cfg.num_channels), 297 | dtype='float32') 298 | vgg16 = VGG16(input_tensor=self.input_img, 299 | # weights=None, 300 | include_top=False) 301 | if cfg.locked_layers: 302 | # locked first two conv layers 303 | locked_layers = [vgg16.get_layer('block1_conv1'), 304 | vgg16.get_layer('block1_conv2')] 305 | for layer in locked_layers: 306 | layer.trainable = False 307 | self.f = [] 308 | self.f.append(vgg16.get_layer('block2_conv2').output) 309 | self.f.append(vgg16.get_layer('block3_conv3').output) 310 | self.f.append(vgg16.get_layer('block4_conv3').output) 311 | self.f.append(vgg16.get_layer('block5_conv3').output) 312 | self.f.insert(0, None) 313 | self.f.insert(0, None) 314 | 315 | def upsample(self,x,target,init=False): 316 | target_shape = list(target._keras_shape[1:-1]) 317 | upscored = Resize(target_shape)(x) 318 | if init: 319 | return upscored 320 | else: 321 | return add([upscored,target]) 322 | 323 | def east_network(self): 324 | block2 = self.f[2] # 1/2 325 | block3 = self.f[3] # 1/4 326 | block4 = self.f[4] # 1/8 327 | block5 = self.f[5] # 1/16 328 | 329 | fc1 = Conv2D(512, (3, 3),activation='relu',padding='same',name='fc1')(block5) 330 | fc2 = Conv2D(512, (3, 3),activation='relu',padding='same',name='fc2')(fc1) 331 | 332 | # -------------------------------------------------------------# 333 | 334 | link1 = Conv2D(1, (1, 1),activation='relu',padding='same',name='link1')(fc2) 335 | 336 | link2 = Conv2D(1, (1, 1),activation='relu',padding='same',name='link2')(block5) 337 | link = self.upsample(link1,link2,init=True) # 1/16 338 | 339 | link3 = Conv2D(1, (1, 1),activation='relu',padding='same',name='link3')(block4) 340 | link = self.upsample(link,link3) # 1/8 341 | 342 | link4 = Conv2D(1, (1, 1),activation='relu',padding='same',name='link4')(block3) 343 | link = self.upsample(link,link4) # 1/4 344 | 345 | #-------------------------------------------------------------# 346 | 347 | cls1 = Conv2D(2, (1, 1), activation='relu', padding='same', name='cls1')(fc2) 348 | 349 | cls2 = Conv2D(2, (1, 1), activation='relu', padding='same', name='cls2')(block5) 350 | cls = self.upsample(cls1,cls2,init=True) 351 | 352 | cls3 = Conv2D(2, (1, 1), activation='relu', padding='same', name='cls3')(block4) 353 | cls = self.upsample(cls,cls3) 354 | 355 | cls4 = Conv2D(2, (1, 1), activation='relu', padding='same', name='cls4')(block3) 356 | cls = self.upsample(cls,cls4) 357 | 358 | # -------------------------------------------------------------# 359 | 360 | coord1 = Conv2D(4, (1, 1), activation='relu', padding='same', name='coord1')(fc2) 361 | 362 | coord2 = Conv2D(4, (1, 1), activation='relu', padding='same', name='coord2')(block5) 363 | coord = self.upsample(coord1,coord2,init=True) 364 | 365 | coord3 = Conv2D(4, (1, 1), activation='relu', padding='same', name='coord3')(block4) 366 | coord = self.upsample(coord,coord3) 367 | 368 | coord4 = Conv2D(4, (1, 1), activation='relu', padding='same', name='coord4')(block3) 369 | coord = self.upsample(coord,coord4) 370 | 371 | pixel_detect = Concatenate(axis=-1,name='pixellink_detect')([cls,link,coord]) 372 | return Model(inputs=self.input_img, outputs=pixel_detect) 373 | 374 | 375 | if __name__ == '__main__': 376 | east = MyEast() 377 | east_network = east.east_network() 378 | east_network.summary() 379 | -------------------------------------------------------------------------------- /EAST/nms.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import numpy as np 3 | 4 | import cfg 5 | 6 | 7 | def should_merge(region, i, j): 8 | neighbor = {(i, j - 1)} 9 | return not region.isdisjoint(neighbor) 10 | 11 | 12 | def region_neighbor(region_set): 13 | region_pixels = np.array(list(region_set)) 14 | j_min = np.amin(region_pixels, axis=0)[1] - 1 15 | j_max = np.amax(region_pixels, axis=0)[1] + 1 16 | i_m = np.amin(region_pixels, axis=0)[0] + 1 17 | region_pixels[:, 0] += 1 18 | neighbor = {(region_pixels[n, 0], region_pixels[n, 1]) for n in 19 | range(len(region_pixels))} 20 | neighbor.add((i_m, j_min)) 21 | neighbor.add((i_m, j_max)) 22 | return neighbor 23 | 24 | 25 | def region_group(region_list): 26 | S = [i for i in range(len(region_list))] 27 | D = [] 28 | while len(S) > 0: 29 | m = S.pop(0) 30 | if len(S) == 0: 31 | # S has only one element, put it to D 32 | D.append([m]) 33 | else: 34 | D.append(rec_region_merge(region_list, m, S)) 35 | return D 36 | 37 | 38 | def rec_region_merge(region_list, m, S): 39 | rows = [m] 40 | tmp = [] 41 | for n in S: 42 | if not region_neighbor(region_list[m]).isdisjoint(region_list[n]) or \ 43 | not region_neighbor(region_list[n]).isdisjoint(region_list[m]): 44 | # 第m与n相交 45 | tmp.append(n) 46 | for d in tmp: 47 | S.remove(d) 48 | for e in tmp: 49 | rows.extend(rec_region_merge(region_list, e, S)) 50 | return rows 51 | 52 | 53 | def nms(predict, activation_pixels, threshold=cfg.side_vertex_pixel_threshold): 54 | region_list = [] 55 | for i, j in zip(activation_pixels[0], activation_pixels[1]): 56 | merge = False 57 | for k in range(len(region_list)): 58 | if should_merge(region_list[k], i, j): 59 | region_list[k].add((i, j)) 60 | merge = True 61 | # 重叠文本区域处理,存在和多个区域邻接的pixels,先都merge试试 62 | # break 63 | if not merge: 64 | region_list.append({(i, j)}) 65 | D = region_group(region_list) 66 | quad_list = np.zeros((len(D), 4, 2)) 67 | score_list = np.zeros((len(D), 4)) 68 | for group, g_th in zip(D, range(len(D))): 69 | total_score = np.zeros((4, 2)) 70 | for row in group: 71 | for ij in region_list[row]: 72 | score = predict[ij[0], ij[1], 1] 73 | if score >= threshold: 74 | ith_score = predict[ij[0], ij[1], 2:3] 75 | if not (cfg.trunc_threshold <= ith_score < 1 - 76 | cfg.trunc_threshold): 77 | ith = int(np.around(ith_score)) 78 | total_score[ith * 2:(ith + 1) * 2] += score 79 | px = (ij[1] + 0.5) * cfg.pixel_size 80 | py = (ij[0] + 0.5) * cfg.pixel_size 81 | p_v = [px, py] + np.reshape(predict[ij[0], ij[1], 3:7], 82 | (2, 2)) 83 | quad_list[g_th, ith * 2:(ith + 1) * 2] += score * p_v 84 | score_list[g_th] = total_score[:, 0] 85 | quad_list[g_th] /= (total_score + cfg.epsilon) 86 | return score_list, quad_list 87 | -------------------------------------------------------------------------------- /EAST/predict.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import numpy as np 4 | from PIL import Image, ImageDraw 5 | from keras.preprocessing import image 6 | from keras.applications.vgg16 import preprocess_input 7 | 8 | import cfg 9 | from label import point_inside_of_quad 10 | from network import East 11 | from preprocess import resize_image 12 | from nms import nms 13 | 14 | import tensorflow as tf 15 | from keras import backend as K 16 | 17 | num_cores = 1 18 | GPU = 0 19 | CPU = 1 20 | if GPU: 21 | num_GPU = 1 22 | num_CPU = 1 23 | if CPU: 24 | num_CPU = 1 25 | num_GPU = 0 26 | 27 | config = tf.ConfigProto(intra_op_parallelism_threads=num_cores,\ 28 | inter_op_parallelism_threads=num_cores, allow_soft_placement=True,\ 29 | device_count = {'CPU' : num_CPU, 'GPU' : num_GPU}) 30 | session = tf.Session(config=config) 31 | K.set_session(session) 32 | 33 | def sigmoid(x): 34 | """`y = 1 / (1 + exp(-x))`""" 35 | return 1 / (1 + np.exp(-x)) 36 | 37 | 38 | def cut_text_line(geo, scale_ratio_w, scale_ratio_h, im_array, img_path, s): 39 | geo /= [scale_ratio_w, scale_ratio_h] 40 | p_min = np.amin(geo, axis=0) 41 | p_max = np.amax(geo, axis=0) 42 | min_xy = p_min.astype(int) 43 | max_xy = p_max.astype(int) + 2 44 | sub_im_arr = im_array[min_xy[1]:max_xy[1], min_xy[0]:max_xy[0], :].copy() 45 | for m in range(min_xy[1], max_xy[1]): 46 | for n in range(min_xy[0], max_xy[0]): 47 | if not point_inside_of_quad(n, m, geo, p_min, p_max): 48 | sub_im_arr[m - min_xy[1], n - min_xy[0], :] = 255 49 | sub_im = image.array_to_img(sub_im_arr, scale=False) 50 | sub_im.save(img_path + '_subim%d.jpg' % s) 51 | 52 | 53 | def predict(east_detect, img_path, pixel_threshold, quiet=False): 54 | img = image.load_img(img_path) 55 | d_wight, d_height = resize_image(img, cfg.max_predict_img_size) 56 | img = img.resize((d_wight, d_height), Image.NEAREST).convert('RGB') 57 | img = image.img_to_array(img) 58 | img = preprocess_input(img, mode='tf') 59 | x = np.expand_dims(img, axis=0) 60 | y = east_detect.predict(x) 61 | 62 | y = np.squeeze(y, axis=0) 63 | y[:, :, :3] = sigmoid(y[:, :, :3]) 64 | cond = np.greater_equal(y[:, :, 0], pixel_threshold) 65 | activation_pixels = np.where(cond) 66 | quad_scores, quad_after_nms = nms(y, activation_pixels) 67 | with Image.open(img_path) as im: 68 | im_array = image.img_to_array(im.convert('RGB')) 69 | d_wight, d_height = resize_image(im, cfg.max_predict_img_size) 70 | scale_ratio_w = d_wight / im.width 71 | scale_ratio_h = d_height / im.height 72 | im = im.resize((d_wight, d_height), Image.NEAREST).convert('RGB') 73 | quad_im = im.copy() 74 | draw = ImageDraw.Draw(im) 75 | for i, j in zip(activation_pixels[0], activation_pixels[1]): 76 | px = (j + 0.5) * cfg.pixel_size 77 | py = (i + 0.5) * cfg.pixel_size 78 | line_width, line_color = 1, 'red' 79 | if y[i, j, 1] >= cfg.side_vertex_pixel_threshold: 80 | if y[i, j, 2] < cfg.trunc_threshold: 81 | line_width, line_color = 2, 'yellow' 82 | elif y[i, j, 2] >= 1 - cfg.trunc_threshold: 83 | line_width, line_color = 2, 'green' 84 | draw.line([(px - 0.5 * cfg.pixel_size, py - 0.5 * cfg.pixel_size), 85 | (px + 0.5 * cfg.pixel_size, py - 0.5 * cfg.pixel_size), 86 | (px + 0.5 * cfg.pixel_size, py + 0.5 * cfg.pixel_size), 87 | (px - 0.5 * cfg.pixel_size, py + 0.5 * cfg.pixel_size), 88 | (px - 0.5 * cfg.pixel_size, py - 0.5 * cfg.pixel_size)], 89 | width=line_width, fill=line_color) 90 | im.save(img_path + '_act.jpg') 91 | quad_draw = ImageDraw.Draw(quad_im) 92 | txt_items = [] 93 | for score, geo, s in zip(quad_scores, quad_after_nms, 94 | range(len(quad_scores))): 95 | if np.amin(score) > 0: 96 | quad_draw.line([tuple(geo[0]), 97 | tuple(geo[1]), 98 | tuple(geo[2]), 99 | tuple(geo[3]), 100 | tuple(geo[0])], width=2, fill='red') 101 | if cfg.predict_cut_text_line: 102 | cut_text_line(geo, scale_ratio_w, scale_ratio_h, im_array, 103 | img_path, s) 104 | rescaled_geo = geo / [scale_ratio_w, scale_ratio_h] 105 | rescaled_geo_list = np.reshape(rescaled_geo, (8,)).tolist() 106 | txt_item = ','.join(map(str, rescaled_geo_list)) 107 | txt_items.append(txt_item + '\n') 108 | elif not quiet: 109 | print('quad invalid with vertex num less then 4.') 110 | quad_im.save(img_path + '_predict.jpg') 111 | if cfg.predict_write2txt and len(txt_items) > 0: 112 | with open(img_path[:-4] + '.txt', 'w') as f_txt: 113 | f_txt.writelines(txt_items) 114 | 115 | 116 | def predict_txt(east_detect, img_path, txt_path, pixel_threshold, quiet=False): 117 | img = image.load_img(img_path) 118 | d_wight, d_height = resize_image(img, cfg.max_predict_img_size) 119 | scale_ratio_w = d_wight / img.width 120 | scale_ratio_h = d_height / img.height 121 | img = img.resize((d_wight, d_height), Image.NEAREST).convert('RGB') 122 | img = image.img_to_array(img) 123 | img = preprocess_input(img, mode='tf') 124 | x = np.expand_dims(img, axis=0) 125 | y = east_detect.predict(x) 126 | 127 | y = np.squeeze(y, axis=0) 128 | y[:, :, :3] = sigmoid(y[:, :, :3]) 129 | cond = np.greater_equal(y[:, :, 0], pixel_threshold) 130 | activation_pixels = np.where(cond) 131 | quad_scores, quad_after_nms = nms(y, activation_pixels) 132 | 133 | txt_items = [] 134 | for score, geo in zip(quad_scores, quad_after_nms): 135 | if np.amin(score) > 0: 136 | rescaled_geo = geo / [scale_ratio_w, scale_ratio_h] 137 | rescaled_geo_list = np.reshape(rescaled_geo, (8,)).tolist() 138 | txt_item = ','.join(map(str, rescaled_geo_list)) 139 | txt_items.append(txt_item + '\n') 140 | elif not quiet: 141 | print('quad invalid with vertex num less then 4.') 142 | if cfg.predict_write2txt and len(txt_items) > 0: 143 | with open(txt_path, 'w') as f_txt: 144 | f_txt.writelines(txt_items) 145 | 146 | def parse_args(): 147 | parser = argparse.ArgumentParser() 148 | parser.add_argument('--path', '-p', 149 | default='demo/012.png', 150 | help='image path') 151 | parser.add_argument('--threshold', '-t', 152 | default=cfg.pixel_threshold, 153 | help='pixel activation threshold') 154 | return parser.parse_args() 155 | 156 | 157 | if __name__ == '__main__': 158 | args = parse_args() 159 | # img_path = args.path 160 | img_path = 'test/img_calligraphy_88334_bg.jpg' 161 | # threshold = float(args.threshold) 162 | threshold = 0.7 163 | print(img_path, threshold) 164 | 165 | east = East() 166 | east_detect = east.east_network() 167 | east_detect.load_weights("checkpoints/single_gpu.h5") 168 | 169 | 170 | import os 171 | imgs = os.listdir('DF_zh') 172 | for i in imgs: 173 | predict(east_detect,'DF_zh/'+i,0.7) 174 | -------------------------------------------------------------------------------- /EAST/preprocess.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from PIL import Image, ImageDraw 3 | import os 4 | import random 5 | from tqdm import tqdm 6 | 7 | import EAST.cfg as cfg 8 | from EAST.label import shrink 9 | import pandas as pd 10 | 11 | 12 | def batch_reorder_vertexes(xy_list_array): 13 | reorder_xy_list_array = np.zeros_like(xy_list_array) 14 | for xy_list, i in zip(xy_list_array, range(len(xy_list_array))): 15 | reorder_xy_list_array[i] = reorder_vertexes(xy_list) 16 | return reorder_xy_list_array 17 | 18 | 19 | def reorder_vertexes(xy_list): 20 | reorder_xy_list = np.zeros_like(xy_list) 21 | # determine the first point with the smallest x, 22 | # if two has same x, choose that with smallest y, 23 | ordered = np.argsort(xy_list, axis=0) 24 | xmin1_index = ordered[0, 0] 25 | xmin2_index = ordered[1, 0] 26 | if xy_list[xmin1_index, 0] == xy_list[xmin2_index, 0]: 27 | if xy_list[xmin1_index, 1] <= xy_list[xmin2_index, 1]: 28 | reorder_xy_list[0] = xy_list[xmin1_index] 29 | first_v = xmin1_index 30 | else: 31 | reorder_xy_list[0] = xy_list[xmin2_index] 32 | first_v = xmin2_index 33 | else: 34 | reorder_xy_list[0] = xy_list[xmin1_index] 35 | first_v = xmin1_index 36 | # connect the first point to others, the third point on the other side of 37 | # the line with the middle slope 38 | others = list(range(4)) 39 | others.remove(first_v) 40 | k = np.zeros((len(others),)) 41 | for index, i in zip(others, range(len(others))): 42 | k[i] = (xy_list[index, 1] - xy_list[first_v, 1]) \ 43 | / (xy_list[index, 0] - xy_list[first_v, 0] + cfg.epsilon) 44 | k_mid = np.argsort(k)[1] 45 | third_v = others[k_mid] 46 | reorder_xy_list[2] = xy_list[third_v] 47 | # determine the second point which on the bigger side of the middle line 48 | others.remove(third_v) 49 | b_mid = xy_list[first_v, 1] - k[k_mid] * xy_list[first_v, 0] 50 | second_v, fourth_v = 0, 0 51 | for index, i in zip(others, range(len(others))): 52 | # delta = y - (k * x + b) 53 | delta_y = xy_list[index, 1] - (k[k_mid] * xy_list[index, 0] + b_mid) 54 | if delta_y > 0: 55 | second_v = index 56 | else: 57 | fourth_v = index 58 | reorder_xy_list[1] = xy_list[second_v] 59 | reorder_xy_list[3] = xy_list[fourth_v] 60 | # compare slope of 13 and 24, determine the final order 61 | k13 = k[k_mid] 62 | k24 = (xy_list[second_v, 1] - xy_list[fourth_v, 1]) / ( 63 | xy_list[second_v, 0] - xy_list[fourth_v, 0] + cfg.epsilon) 64 | if k13 < k24: 65 | tmp_x, tmp_y = reorder_xy_list[3, 0], reorder_xy_list[3, 1] 66 | for i in range(2, -1, -1): 67 | reorder_xy_list[i + 1] = reorder_xy_list[i] 68 | reorder_xy_list[0, 0], reorder_xy_list[0, 1] = tmp_x, tmp_y 69 | return reorder_xy_list 70 | 71 | 72 | def resize_image(im, max_img_size=cfg.max_train_img_size): 73 | im_width = np.minimum(im.width, max_img_size) 74 | if im_width == max_img_size < im.width: 75 | im_height = int((im_width / im.width) * im.height) 76 | else: 77 | im_height = im.height 78 | o_height = np.minimum(im_height, max_img_size) 79 | if o_height == max_img_size < im_height: 80 | o_width = int((o_height / im_height) * im_width) 81 | else: 82 | o_width = im_width 83 | d_wight = o_width - (o_width % 32) 84 | d_height = o_height - (o_height % 32) 85 | return d_wight, d_height 86 | 87 | 88 | def preprocess(): 89 | print(cfg.train_task_id) 90 | data_dir = cfg.data_dir 91 | # 92 | origin_image_dir = os.path.join(data_dir, cfg.origin_image_dir_name) 93 | origin_txt_dir = os.path.join(data_dir, cfg.origin_txt_dir_name) 94 | 95 | origin_val_image_dir = os.path.join(data_dir, cfg.origin_val_image_dir_name) 96 | origin_val_txt_dir = os.path.join(data_dir, cfg.origin_val_txt_dir_name) 97 | 98 | origin_test_image_dir = os.path.join(data_dir, cfg.origin_test_image_dir_name) 99 | origin_test_txt_dir=os.path.join(data_dir, cfg.origin_test_txt_dir_name) 100 | # 101 | train_image_dir = os.path.join(data_dir, cfg.train_image_dir_name) 102 | train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) 103 | 104 | val_image_dir = os.path.join(data_dir, cfg.val_image_dir_name) 105 | val_label_dir = os.path.join(data_dir, cfg.val_label_dir_name) 106 | 107 | test_image_dir = os.path.join(data_dir, cfg.test_image_dir_name) 108 | test_label_dir = os.path.join(data_dir, cfg.test_label_dir_name) 109 | 110 | 111 | if not os.path.exists(train_image_dir): 112 | os.mkdir(train_image_dir) 113 | if not os.path.exists(train_label_dir): 114 | os.mkdir(train_label_dir) 115 | 116 | draw_gt_quad = cfg.draw_gt_quad 117 | 118 | if draw_gt_quad: 119 | show_gt_image_dir = os.path.join(data_dir, cfg.show_gt_image_dir_name) 120 | if not os.path.exists(show_gt_image_dir): 121 | os.mkdir(show_gt_image_dir) 122 | show_act_image_dir = os.path.join(cfg.data_dir, cfg.show_act_image_dir_name) 123 | if not os.path.exists(show_act_image_dir): 124 | os.mkdir(show_act_image_dir) 125 | 126 | #==================================Train===============================================# 127 | # 128 | # label = pd.read_csv(origin_txt_dir) 129 | # 130 | # o_img_list = os.listdir(origin_image_dir) 131 | # print('found %d origin images.' % len(o_img_list)) 132 | # train_val_set = [] 133 | # for o_img_fname in tqdm(o_img_list): 134 | # with Image.open(os.path.join(origin_image_dir, o_img_fname)) as im: 135 | # # d_wight, d_height = resize_image(im) 136 | # d_wight, d_height = cfg.max_train_img_size, cfg.max_train_img_size 137 | # scale_ratio_w = d_wight / im.width 138 | # scale_ratio_h = d_height / im.height 139 | # im = im.resize((d_wight, d_height), Image.NEAREST).convert('RGB') 140 | # show_gt_im = im.copy() 141 | # # draw on the img 142 | # draw = ImageDraw.Draw(show_gt_im) 143 | # # with open(os.path.join(origin_txt_dir,'gt_'+o_img_fname[:-4] + '.txt'), 'r',encoding='utf-8-sig') as f: 144 | # # anno_list = f.readlines() 145 | # 146 | # txt = label[label['FileName'] == o_img_fname] 147 | # 148 | # anno_list = txt.get_values() 149 | # xy_list_array = np.zeros((len(anno_list), 4, 2)) 150 | # for anno, i in zip(anno_list, range(len(anno_list))): 151 | # anno_colums = anno[1:9] 152 | # anno_array = np.array(anno_colums) 153 | # xy_list = np.reshape(anno_array[:8].astype(float), (4, 2)) 154 | # xy_list[:, 0] = xy_list[:, 0] * scale_ratio_w 155 | # xy_list[:, 1] = xy_list[:, 1] * scale_ratio_h 156 | # xy_list = reorder_vertexes(xy_list) 157 | # xy_list_array[i] = xy_list 158 | # _, shrink_xy_list, _ = shrink(xy_list, cfg.shrink_ratio) 159 | # shrink_1, _, long_edge = shrink(xy_list, cfg.shrink_side_ratio) 160 | # if draw_gt_quad: 161 | # draw.line([tuple(xy_list[0]), tuple(xy_list[1]), 162 | # tuple(xy_list[2]), tuple(xy_list[3]), 163 | # tuple(xy_list[0]) 164 | # ], 165 | # width=2, fill='green') 166 | # draw.line([tuple(shrink_xy_list[0]), 167 | # tuple(shrink_xy_list[1]), 168 | # tuple(shrink_xy_list[2]), 169 | # tuple(shrink_xy_list[3]), 170 | # tuple(shrink_xy_list[0]) 171 | # ], 172 | # width=2, fill='blue') 173 | # vs = [[[0, 0, 3, 3, 0], [1, 1, 2, 2, 1]], 174 | # [[0, 0, 1, 1, 0], [2, 2, 3, 3, 2]]] 175 | # for q_th in range(2): 176 | # draw.line([tuple(xy_list[vs[long_edge][q_th][0]]), 177 | # tuple(shrink_1[vs[long_edge][q_th][1]]), 178 | # tuple(shrink_1[vs[long_edge][q_th][2]]), 179 | # tuple(xy_list[vs[long_edge][q_th][3]]), 180 | # tuple(xy_list[vs[long_edge][q_th][4]])], 181 | # width=3, fill='yellow') 182 | # if cfg.gen_origin_img: 183 | # im.save(os.path.join(train_image_dir, 'train_' + o_img_fname)) 184 | # np.save(os.path.join( 185 | # train_label_dir, 186 | # 'train_' + o_img_fname[:-4] + '.npy'), 187 | # xy_list_array) 188 | # if draw_gt_quad: 189 | # show_gt_im.save(os.path.join(show_gt_image_dir, o_img_fname)) 190 | # train_val_set.append('{},{},{}\n'.format('train_'+o_img_fname, 191 | # d_wight, 192 | # d_height)) 193 | # 194 | # #==================================Val================================================# 195 | # 196 | # label = pd.read_csv(origin_val_txt_dir) 197 | # 198 | # o_img_list = os.listdir(origin_val_image_dir) 199 | # print('found %d origin images.' % len(o_img_list)) 200 | # for o_img_fname in tqdm(o_img_list): 201 | # with Image.open(os.path.join(origin_val_image_dir, o_img_fname)) as im: 202 | # # d_wight, d_height = resize_image(im) 203 | # d_wight, d_height = cfg.max_train_img_size, cfg.max_train_img_size 204 | # scale_ratio_w = d_wight / im.width 205 | # scale_ratio_h = d_height / im.height 206 | # im = im.resize((d_wight, d_height), Image.NEAREST).convert('RGB') 207 | # show_gt_im = im.copy() 208 | # # draw on the img 209 | # draw = ImageDraw.Draw(show_gt_im) 210 | # # with open(os.path.join(origin_txt_dir,'gt_'+o_img_fname[:-4] + '.txt'), 'r',encoding='utf-8-sig') as f: 211 | # # anno_list = f.readlines() 212 | # 213 | # txt = label[label['FileName'] == o_img_fname] 214 | # 215 | # anno_list = txt.get_values() 216 | # xy_list_array = np.zeros((len(anno_list), 4, 2)) 217 | # for anno, i in zip(anno_list, range(len(anno_list))): 218 | # anno_colums = anno[1:9] 219 | # anno_array = np.array(anno_colums) 220 | # xy_list = np.reshape(anno_array[:8].astype(float), (4, 2)) 221 | # xy_list[:, 0] = xy_list[:, 0] * scale_ratio_w 222 | # xy_list[:, 1] = xy_list[:, 1] * scale_ratio_h 223 | # xy_list = reorder_vertexes(xy_list) 224 | # xy_list_array[i] = xy_list 225 | # _, shrink_xy_list, _ = shrink(xy_list, cfg.shrink_ratio) 226 | # shrink_1, _, long_edge = shrink(xy_list, cfg.shrink_side_ratio) 227 | # if draw_gt_quad: 228 | # draw.line([tuple(xy_list[0]), tuple(xy_list[1]), 229 | # tuple(xy_list[2]), tuple(xy_list[3]), 230 | # tuple(xy_list[0]) 231 | # ], 232 | # width=2, fill='green') 233 | # draw.line([tuple(shrink_xy_list[0]), 234 | # tuple(shrink_xy_list[1]), 235 | # tuple(shrink_xy_list[2]), 236 | # tuple(shrink_xy_list[3]), 237 | # tuple(shrink_xy_list[0]) 238 | # ], 239 | # width=2, fill='blue') 240 | # vs = [[[0, 0, 3, 3, 0], [1, 1, 2, 2, 1]], 241 | # [[0, 0, 1, 1, 0], [2, 2, 3, 3, 2]]] 242 | # for q_th in range(2): 243 | # draw.line([tuple(xy_list[vs[long_edge][q_th][0]]), 244 | # tuple(shrink_1[vs[long_edge][q_th][1]]), 245 | # tuple(shrink_1[vs[long_edge][q_th][2]]), 246 | # tuple(xy_list[vs[long_edge][q_th][3]]), 247 | # tuple(xy_list[vs[long_edge][q_th][4]])], 248 | # width=3, fill='yellow') 249 | # if cfg.gen_origin_img: 250 | # im.save(os.path.join(val_image_dir, 'val_' + o_img_fname)) 251 | # np.save(os.path.join( 252 | # val_label_dir, 253 | # 'val_' + o_img_fname[:-4] + '.npy'), 254 | # xy_list_array) 255 | # if draw_gt_quad: 256 | # show_gt_im.save(os.path.join(show_gt_image_dir, o_img_fname)) 257 | # train_val_set.append('{},{},{}\n'.format('val_'+o_img_fname, 258 | # d_wight, 259 | # d_height)) 260 | # 261 | 262 | #================================Test===================================================# 263 | 264 | label = pd.read_csv(origin_test_txt_dir) 265 | 266 | o_test_img_list = os.listdir(origin_test_image_dir) 267 | print('found %d origin images.' % len(o_test_img_list)) 268 | test_set = [] 269 | for o_img_fname in tqdm(o_test_img_list): 270 | with Image.open(os.path.join(origin_test_image_dir, o_img_fname)) as im: 271 | # d_wight, d_height = resize_image(im) 272 | d_wight, d_height = cfg.max_train_img_size, cfg.max_train_img_size 273 | scale_ratio_w = d_wight / im.width 274 | scale_ratio_h = d_height / im.height 275 | im = im.resize((d_wight, d_height), Image.NEAREST).convert('RGB') 276 | show_gt_im = im.copy() 277 | # draw on the img 278 | draw = ImageDraw.Draw(show_gt_im) 279 | # with open(os.path.join(origin_test_txt_dir,'gt_'+o_img_fname[:-4] + '.txt'), 'r',encoding='utf-8-sig') as f: 280 | # anno_list = f.readlines() 281 | 282 | txt = label[label['FileName'] == o_img_fname] 283 | anno_list = txt.get_values() 284 | 285 | xy_list_array = np.zeros((len(anno_list), 4, 2)) 286 | for anno, i in zip(anno_list, range(len(anno_list))): 287 | 288 | # anno_colums = anno.strip().split(',') 289 | 290 | anno_colums = anno[1:9] 291 | 292 | anno_array = np.array(anno_colums) 293 | xy_list = np.reshape(anno_array[:8].astype(float), (4, 2)) 294 | xy_list[:, 0] = xy_list[:, 0] * scale_ratio_w 295 | xy_list[:, 1] = xy_list[:, 1] * scale_ratio_h 296 | xy_list = reorder_vertexes(xy_list) 297 | xy_list_array[i] = xy_list 298 | _, shrink_xy_list, _ = shrink(xy_list, cfg.shrink_ratio) 299 | shrink_1, _, long_edge = shrink(xy_list, cfg.shrink_side_ratio) 300 | if draw_gt_quad: 301 | draw.line([tuple(xy_list[0]), tuple(xy_list[1]), 302 | tuple(xy_list[2]), tuple(xy_list[3]), 303 | tuple(xy_list[0]) 304 | ], 305 | width=2, fill='green') 306 | draw.line([tuple(shrink_xy_list[0]), 307 | tuple(shrink_xy_list[1]), 308 | tuple(shrink_xy_list[2]), 309 | tuple(shrink_xy_list[3]), 310 | tuple(shrink_xy_list[0]) 311 | ], 312 | width=2, fill='blue') 313 | vs = [[[0, 0, 3, 3, 0], [1, 1, 2, 2, 1]], 314 | [[0, 0, 1, 1, 0], [2, 2, 3, 3, 2]]] 315 | for q_th in range(2): 316 | draw.line([tuple(xy_list[vs[long_edge][q_th][0]]), 317 | tuple(shrink_1[vs[long_edge][q_th][1]]), 318 | tuple(shrink_1[vs[long_edge][q_th][2]]), 319 | tuple(xy_list[vs[long_edge][q_th][3]]), 320 | tuple(xy_list[vs[long_edge][q_th][4]])], 321 | width=3, fill='yellow') 322 | if cfg.gen_origin_img: 323 | im.save(os.path.join(test_image_dir, 'test_'+o_img_fname)) 324 | np.save(os.path.join( 325 | test_label_dir, 326 | 'test_'+o_img_fname[:-4] + '.npy'), 327 | xy_list_array) 328 | if draw_gt_quad: 329 | show_gt_im.save(os.path.join(show_gt_image_dir, o_img_fname)) 330 | test_set.append('{},{},{}\n'.format('test_'+o_img_fname, 331 | d_wight, 332 | d_height)) 333 | 334 | train_img_list = os.listdir(train_image_dir) 335 | print('found %d train images.' % len(train_img_list)) 336 | train_label_list = os.listdir(train_label_dir) 337 | print('found %d train labels.' % len(train_label_list)) 338 | 339 | # random.shuffle(train_val_set) 340 | # val_count = int(cfg.validation_split_ratio * len(train_val_set)) 341 | # 342 | # with open(os.path.join(data_dir, cfg.val_fname), 'w') as f_val: 343 | # f_val.writelines(test_set) 344 | # 345 | # with open(os.path.join(data_dir, cfg.train_fname), 'w') as f_train: 346 | # f_train.writelines(train_val_set) 347 | 348 | if __name__ == '__main__': 349 | preprocess() 350 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## 文化传承—汉字书法多场景识别(Cultural Inheritance – Recognizing Chinese Calligraphy in Multiple Scenarios)-Baseline 2 | 3 | [Competition URL](https://www.datafountain.cn/competitions/334/details) 4 | 5 | 使用[East](http://link.zhihu.com/?target=https%3A//arxiv.org/pdf/1704.03155.pdf)定位,[crnn](https://arxiv.org/abs/1507.05717)识别文字 6 | 7 | ## East 8 | 9 | 参考[AdvancedEASR](https://github.com/huoyijie/AdvancedEAST) 10 | 11 | ## CRNN 12 | 13 | pytorch模型在训练的过程中发现不收敛,且无法本地调试,遂修改为keras版本模型,但由于keras后端使用tensorflow,输入的图片的大小必须一致,不可以动态调整,所以采用了一个比较折中的办法,把图片设置的较大,使用 14 | ```angular2html 15 | img = np.pad(img, ((0, 0), (l, r), (0, 0)), 'constant',constant_values=(0,0)) 16 | ``` 17 | 18 | train了两天的效果 19 | 20 | ![image](CRNN/img/0.jpg) 21 | [',', '相', '从', '孝', '王', '台', '。', '细', '雨'] 22 | 23 | ![image](CRNN/img/1.jpg) 24 | ['、', '低'] 25 | 26 | ![image](CRNN/img/2.jpg) 27 | ['变'] 28 | 29 | ![image](CRNN/img/5.jpg) 30 | ['告', ',', '灌', '预', '彦', '兼', ',', '票', '脚', '冷'] 31 | 32 | ![image](CRNN/img/14.jpg) 33 | ['明', '代', '天', '险', '飞', '藤'] 34 | 35 | ![image](CRNN/img/15.jpg) 36 | ['岛', '降', '祥', '时', ',', '证', '陆', '地', '种'] 37 | 38 | ![image](CRNN/img/16.jpg) 39 | ['令', '贾', '取'] 40 | 41 | ![image](CRNN/img/17.jpg) 42 | ['武'] 43 | 44 | ![image](CRNN/img/18.jpg) 45 | ['京', '成'] 46 | 47 | ![image](CRNN/img/19.jpg) 48 | ['世', '间', '李', '论', '。', '准', '星'] 49 | 50 | ![image](CRNN/img/20.jpg) 51 | ['承', '公', '*', '烟', '、', '自', '属', '、', '、'] 52 | 53 | ![image](CRNN/img/21.jpg) 54 | ['西', '“', '添', '瑞', '鲜', '酸'] 55 | 56 | ![image](CRNN/img/4.jpg) 57 | ['性', '显', '英', '豪', ',', '挖', '塔', '的', '搬'] 58 | --------------------------------------------------------------------------------