├── 27ec20a9ca6e33e2cfba29448ee4a136.png ├── 2a714c6f485a27e17916c8524fe217b0.png ├── 32742c4b561dbea289d82adc0353a2a0.png ├── 9404a0ee55390dd4627a65eff02e1201.png ├── 9532a53b9bd70fdab0f1d1817f8bfa61.png ├── LPR.py ├── README.md ├── SimpleRecognizePlateByE2E.py ├── c9ce3bd7d9ea735c4670147fa2bdb25f.png ├── chars_u_京_u_沪_u_津_u_.py ├── detectPlateRough.py ├── finemappingVertical.py ├── for_j_plate_in_enume.py ├── for_pstr_confidence_.py ├── import_HyperLPRLite_.py ├── model_finemapping.py ├── model_seq_rec.py └── recognizeOne.py /27ec20a9ca6e33e2cfba29448ee4a136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/real-time-license-plate-recognition-opencv-python/a607e887da9b8d39c9070965087de70b7ae08f9d/27ec20a9ca6e33e2cfba29448ee4a136.png -------------------------------------------------------------------------------- /2a714c6f485a27e17916c8524fe217b0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/real-time-license-plate-recognition-opencv-python/a607e887da9b8d39c9070965087de70b7ae08f9d/2a714c6f485a27e17916c8524fe217b0.png -------------------------------------------------------------------------------- /32742c4b561dbea289d82adc0353a2a0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/real-time-license-plate-recognition-opencv-python/a607e887da9b8d39c9070965087de70b7ae08f9d/32742c4b561dbea289d82adc0353a2a0.png -------------------------------------------------------------------------------- /9404a0ee55390dd4627a65eff02e1201.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/real-time-license-plate-recognition-opencv-python/a607e887da9b8d39c9070965087de70b7ae08f9d/9404a0ee55390dd4627a65eff02e1201.png -------------------------------------------------------------------------------- /9532a53b9bd70fdab0f1d1817f8bfa61.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/real-time-license-plate-recognition-opencv-python/a607e887da9b8d39c9070965087de70b7ae08f9d/9532a53b9bd70fdab0f1d1817f8bfa61.png -------------------------------------------------------------------------------- /LPR.py: -------------------------------------------------------------------------------- 1 | 2 | class LPR(): 3 | def __init__(self,model_detection,model_finemapping,model_seq_rec): 4 | self.watch_cascade = cv2.CascadeClassifier(model_detection) 5 | self.modelFineMapping = self.model_finemapping() 6 | self.modelFineMapping.load_weights(model_finemapping) 7 | self.modelSeqRec = self.model_seq_rec(model_seq_rec) 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 1.研究背景 2 | 近年来,智能交通系统(ITS)在我国应用日益广泛。作为ITS重要组成部分的自动车牌识别系统在交通流量检测、交通诱导控制、违章车辆监控等方面有着广泛的应用,是确保道路安全畅通的重要手段,也为统计有关资料,为管理者决策提供有效数字依据的重要途径。由于一般的识别系统单幅图像的检测时间较长,达不到实时的要求,从而限制了这种系统在某些方面的应用,比如不停车监控、收费等。而且,即使在固定的地方使用,也必须埋设地感线圈等触发装置,施工及维护都有一定的困难。因此,发展基于视频图像的快速准确的车牌识别系统,具有广阔的发展前景和巨大的经济价值。 3 | 4 | # 2.支持图片识别: 5 | ![3.png](9404a0ee55390dd4627a65eff02e1201.png) 6 | 7 | 8 | # 3.支持视频识别: 9 | ![2.png](c9ce3bd7d9ea735c4670147fa2bdb25f.png) 10 | 11 | 12 | # 4.支持实时识别: 13 | 14 | ![4.png](9532a53b9bd70fdab0f1d1817f8bfa61.png) 15 | 16 | # 5.视频演示: 17 | [Python基于OpenCV的视频车牌识别(源码&教程)上半篇_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV11G4y1q7WB/?vd_source=bc9aec86d164b67a7004b996143742dc) 18 | [实时视频流车牌识别(源码)下半篇_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1qP4y1d7QP?spm_id_from=333.999.0.0&vd_source=bc9aec86d164b67a7004b996143742dc) 19 | 20 | # 6.实现原理: 21 | [参考博客提出的如下可调用函数](https://afdian.net/item?plan_id=80488aa85cd611edb70952540025c377) 22 | 入口文件 demo.py(部分): 23 | ``` 24 | import HyperLPRLite as pr 25 | import cv2 26 | import numpy as np 27 | grr = cv2.imread("images_rec/2_.jpg") 28 | model = pr.LPR("model/cascade.xml","model/model12.h5","model/ocr_plate_all_gru.h5") 29 | for pstr,confidence,rect in model.SimpleRecognizePlateByE2E(grr): 30 | if confidence>0.7: 31 | image = drawRectBox(grr, rect, pstr+" "+str(round(confidence,3))) 32 | print "plate_str:" 33 | print pstr 34 | print "plate_confidence" 35 | print confidence 36 | 37 | cv2.imshow("image",image) 38 | cv2.waitKey(0) 39 | ``` 40 | (1) opencv2的imread函数导入图片, 返回的是Mat类型。 41 | 42 | (2) HyperLPRLiite.py中的LPR类构造函数导入model, 参数就是训练好的三个模型文件,名字分别是: 43 | - model/cascade.xml 44 | - model/model12.h5 45 | - model/ocr_plate_all_gru.h5 46 | #### HyperLPRLite.py: 47 | ``` 48 | class LPR(): 49 | def __init__(self,model_detection,model_finemapping,model_seq_rec): 50 | self.watch_cascade = cv2.CascadeClassifier(model_detection) 51 | self.modelFineMapping = self.model_finemapping() 52 | self.modelFineMapping.load_weights(model_finemapping) 53 | self.modelSeqRec = self.model_seq_rec(model_seq_rec) 54 | ``` 55 | (3)参数 model_detection 就是文件 model/cascade.xml 56 | 用到了 opencv2的CascadeClassifier()函数 57 | cv2.CascadeClassifier() 58 | 参数输入.xml或者.yaml文件,表示加载模型 59 | 一种基于Haar特征的级联分类器用于物体检测的模型 60 | #### model.SImpleRecognizePlateByE2E()函数: 61 | ``` 62 | for pstr,confidence,rect in model.SimpleRecognizePlateByE2E(grr): 63 | if confidence>0.7: 64 | image = drawRectBox(grr, rect, pstr+" "+str(round(confidence,3))) 65 | print "plate_str:" 66 | print pstr 67 | print "plate_confidence" 68 | print confidence 69 | ``` 70 | 输入为一个Mat类型的图片 71 | 输出为识别的车牌字符串,以及confidence可信度, 72 | 定义在 HyperLPRLite.py: 73 | ``` 74 | def SimpleRecognizePlateByE2E(self,image): 75 | images = self.detectPlateRough(image,image.shape[0],top_bottom_padding_rate=0.1) 76 | res_set = [] 77 | for j,plate in enumerate(images): 78 | plate, rect =plate 79 | image_rgb,rect_refine = self.finemappingVertical(plate,rect) 80 | res,confidence = self.recognizeOne(image_rgb) 81 | res_set.append([res,confidence,rect_refine]) 82 | return res_set 83 | ``` 84 | 其中又用到detectPlateRough()函数 85 | 86 | [该博客有详细说明detectPlateRough函数](https://mbd.pub/o/bread/Y5aakp1r) 87 | 是返回图像中所有车牌的边框在图片中的bbox 88 | 返回的是一个表示车牌区域坐标边框的list 89 | 90 | for循环中,对于每个识别出来的车牌用到filemappingVertical()函数 91 | #### detectPlateRough函数 92 | ``` 93 | def detectPlateRough(self,image_gray,resize_h = 720,en_scale =1.08 ,top_bottom_padding_rate = 0.05): 94 | if top_bottom_padding_rate>0.2: 95 | print("error:top_bottom_padding_rate > 0.2:",top_bottom_padding_rate) 96 | exit(1) 97 | height = image_gray.shape[0] 98 | padding = int(height*top_bottom_padding_rate) 99 | scale = image_gray.shape[1]/float(image_gray.shape[0]) 100 | image = cv2.resize(image_gray, (int(scale*resize_h), resize_h)) 101 | image_color_cropped = image[padding:resize_h-padding,0:image_gray.shape[1]] 102 | image_gray = cv2.cvtColor(image_color_cropped,cv2.COLOR_RGB2GRAY) 103 | watches = self.watch_cascade.detectMultiScale(image_gray, en_scale, 2, minSize=(36, 9),maxSize=(36*40, 9*40)) 104 | cropped_images = [] 105 | for (x, y, w, h) in watches: 106 | x -= w * 0.14 107 | w += w * 0.28 108 | y -= h * 0.15 109 | h += h * 0.3 110 | cropped = self.cropImage(image_color_cropped, (int(x), int(y), int(w), int(h))) 111 | cropped_images.append([cropped,[x, y+padding, w, h]]) 112 | return cropped_images 113 | ``` 114 | 输入参数: 115 | image_gray: 一个rgb图像,Mat类型 116 | resize_h: 重新设定的图像大小 117 | top_bottom_padding_rate: 表示要裁剪掉图片的上下部占比 118 | 119 | 这个函数实现的处理: 120 | 1.resize图像大小,cv2.resize函数,按照原来图像比例 121 | 2.裁剪图片,根据输入的top_bottom_padding_rate如果是0.1,那么上面裁剪掉0.1*height,下面也裁剪掉0.1*height 122 | 3.将图像从rgb转化为灰度 cv2.cvtColor函数,cv2.COLOR_RGB2GRAY 123 | 4.根据前面的cv2.CascadeClassifier()物体检测模型(3),输入image_gray灰度图像,边框可识别的最小size,最大size,输出得到车牌在图像中的offset,也就是边框左上角坐标( x, y )以及边框高度( h )和宽度( w ) 124 | 5.对得到的车牌边框的bbox进行扩大,也就是宽度左右各扩大0.14倍,高度上下各扩大0.15倍。 125 | 6.返回图片中所有识别出来的车牌边框bbox,这个list作为返回结果。 126 | 127 | #### filemappingVertical函数 128 | ``` 129 | def finemappingVertical(self,image,rect): 130 | resized = cv2.resize(image,(66,16)) 131 | resized = resized.astype(np.float)/255 132 | res_raw= (np.array([resized]))[0] 133 | res =res_raw*image.shape[1] 134 | res = res.astype(np.int) 135 | H,T = res 136 | H-=3 137 | if H<0: 138 | H=0 139 | T+=2; 140 | if T>= image.shape[1]-1: 141 | T= image.shape[1]-1 142 | rect[2] -= rect[2]*(1-res_raw[1] + res_raw[0]) 143 | rect[0]+=res[0] 144 | image = image[:,H:T+2] 145 | image = cv2.resize(image, (int(136), int(36))) 146 | return image,rect 147 | ``` 148 | 输入参数: 149 | 裁剪的车牌区域图像(Mat类型),rect也是裁剪的车牌部分的图像(Mat类型) 150 | 151 | 实现处理: 152 | 1.将原来车牌图像resize大小:66*16*3 153 | 2.将原来灰度图颜色通道[0, 255]转化为float类型[0,1] 154 | 3.将输入66*16(float),输入进模型进行测试self.modelFineMapping.predict 155 | 156 | #### modelFineMapping模型 157 | ``` 158 | class LPR(): 159 | def __init__(self,model_detection,model_finemapping,model_seq_rec): 160 | self.watch_cascade = cv2.CascadeClassifier(model_detection) 161 | self.modelFineMapping = self.model_finemapping() 162 | self.modelFineMapping.load_weights(model_finemapping) 163 | self.modelSeqRec = self.model_seq_rec(model_seq_rec) 164 | ``` 165 | #### model_finemapping()函数 166 | ``` 167 | def model_finemapping(self): 168 | input = Input(shape=[16, 66, 3]) # change this shape to [None,None,3] to enable arbitraty shape input 169 | x = Conv2D(10, (3, 3), strides=1, padding='valid', name='conv1')(input) 170 | x = Activation("relu", name='relu1')(x) 171 | x = MaxPool2D(pool_size=2)(x) 172 | x = Conv2D(16, (3, 3), strides=1, padding='valid', name='conv2')(x) 173 | x = Activation("relu", name='relu2')(x) 174 | x = Conv2D(32, (3, 3), strides=1, padding='valid', name='conv3')(x) 175 | x = Activation("relu", name='relu3')(x) 176 | x = Flatten()(x) 177 | output = Dense(2,name = "dense")(x) 178 | output = Activation("relu", name='relu4')(output) 179 | model = Model([input], [output]) 180 | return model 181 | ``` 182 | keras网络模型:对车牌的左右边界进行回归 183 | 通过modelFineMapping.loadweights()函数加载模型文件 184 | 通过modelFineMapping.predict输出网络结果 185 | 186 | 输入:16*66*3 tensor 187 | 输出:长度为2的tensor 188 | #### recognizeOne函数 189 | 对于每个车牌区域的for循环中,经过fineMappingVertical处理后输入到recognizeOne函数,进行识别 190 | ``` 191 | for j,plate in enumerate(images): 192 | plate, rect =plate 193 | image_rgb,rect_refine = self.finemappingVertical(plate,rect) 194 | res,confidence = self.recognizeOne(image_rgb) 195 | res_set.append([res,confidence,rect_refine]) 196 | ``` 197 | #### recognizeOne() 198 | ``` 199 | def recognizeOne(self,src): 200 | x_tempx = src 201 | x_temp = cv2.resize(x_tempx,( 164,48)) 202 | x_temp = x_temp.transpose(1, 0, 2) 203 | y_pred = self.modelSeqRec.predict(np.array([x_temp])) 204 | y_pred = y_pred[:,2:,:] 205 | return self.fastdecode(y_pred) 206 | ``` 207 | 1.将前面的(136, 36)图像resize成(164, 48) 208 | 2.将图像转置,输入 209 | 210 | #### model_sec_rec函数 211 | ``` 212 | def model_seq_rec(self,model_path): 213 | width, height, n_len, n_class = 164, 48, 7, len(chars)+ 1 214 | rnn_size = 256 215 | input_tensor = Input((164, 48, 3)) 216 | x = input_tensor 217 | base_conv = 32 218 | for i in range(3): 219 | x = Conv2D(base_conv * (2 ** (i)), (3, 3))(x) 220 | x = BatchNormalization()(x) 221 | x = Activation('relu')(x) 222 | x = MaxPooling2D(pool_size=(2, 2))(x) 223 | conv_shape = x.get_shape() 224 | x = Reshape(target_shape=(int(conv_shape[1]), int(conv_shape[2] * conv_shape[3])))(x) 225 | x = Dense(32)(x) 226 | x = BatchNormalization()(x) 227 | x = Activation('relu')(x) 228 | gru_1 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru1')(x) 229 | gru_1b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru1_b')(x) 230 | gru1_merged = add([gru_1, gru_1b]) 231 | gru_2 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru2')(gru1_merged) 232 | gru_2b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru2_b')(gru1_merged) 233 | x = concatenate([gru_2, gru_2b]) 234 | x = Dropout(0.25)(x) 235 | x = Dense(n_class, kernel_initializer='he_normal', activation='softmax')(x) 236 | base_model = Model(inputs=input_tensor, outputs=x) 237 | base_model.load_weights(model_path) 238 | return base_model 239 | ``` 240 | model_path为模型weights文件路径 241 | ocr部分的网络模型(keras模型) 242 | 输入层:164*48*3的tensor 243 | 输出层:长度为7 的tensor,类别有len(chars)+1种 244 | chars: 245 | ``` 246 | chars = [u"京", u"沪", u"津", u"渝", u"冀", u"晋", u"蒙", u"辽", u"吉", u"黑", u"苏", u"浙", u"皖", u"闽", u"赣", u"鲁", u"豫", u"鄂", u"湘", u"粤", u"桂", 247 | u"琼", u"川", u"贵", u"云", u"藏", u"陕", u"甘", u"青", u"宁", u"新", u"0", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"A", 248 | u"B", u"C", u"D", u"E", u"F", u"G", u"H", u"J", u"K", u"L", u"M", u"N", u"P", u"Q", u"R", u"S", u"T", u"U", u"V", u"W", u"X", 249 | u"Y", u"Z",u"港",u"学",u"使",u"警",u"澳",u"挂",u"军",u"北",u"南",u"广",u"沈",u"兰",u"成",u"济",u"海",u"民",u"航",u"空" 250 | ] 251 | ``` 252 | 网络结构是三层卷积神经网络(CNN),以及四层内控循环单元(GRU)组成 253 | # 7.标注好的车牌数据集(文末链接提供下载): 254 | ![6.png](2a714c6f485a27e17916c8524fe217b0.png) 255 | 256 | ![7.png](32742c4b561dbea289d82adc0353a2a0.png) 257 | 258 | # 8.系统整合: 259 | 260 | 下图[源码&环境部署视频教程&数据集&自定义UI界面](https://s.xiaocichang.com/s/72c576) 261 | ![5.png](27ec20a9ca6e33e2cfba29448ee4a136.png) 262 | 参考博客[《Python基于OpenCV的实时视频流车牌识别(源码&教程)》](https://mbd.pub/o/qunma/work) 263 | 264 | 265 | # 9.参考文献: 266 | *** 267 | [1]周亮,刘云.一种基于数学形态学的汽车牌照提取算法[J].电脑知识与技术(学术交流).2007,(3).826-827. 268 | [2]管庶安.按综合特征实现车牌快速定位[J].计算机应用与软件.2005,(6).63-64. 269 | [3]吴大勇,魏平,侯朝桢,等.一种车牌图像中的字符快速分割与识别方法[J].计算机工程与应用.2002,(3).232-233. 270 | [4]柴治,陶青川,余艳梅,等.一种快速实用的车牌字符识别方法[J].四川大学学报(自然科学版).2002,(3).465-468. 271 | [5]张引,潘云鹤.彩色汽车图象牌照定位新方法[J].中国图象图形学报A辑.2001,(4).374-377. 272 | [6]魏武,张起森,王明俊,等.一种基于模板匹配的车牌识别方法[J].中国公路学报.2001,(1).104-106. 273 | [7]曹迪铭,宣国荣.牌照字符分割中的区域分裂与合并[J].计算机工程.2000,(10).18-20,43. 274 | [8]张炜,王庆,赵荣椿.汽车牌照的实时识别[J].信号处理.2000,(4).372-375. 275 | [9]沈会良,李志能.基于CCD的汽车牌照自动识别系统[J].光电工程.2000,(4).60-63,71. 276 | [10]是湘全,何苑凌,蔡孟波.遗传算法在车牌定位中的应用[J].公路交通科技.2000,(2).33-36. 277 | [11]蒋冰蕾.美国智能公共交通领域发展近况[J].国外城市规划.1999,(1).9-13. 278 | [12]刘效静,成瑜.汽车牌照自动识别技术研究[J].南京航空航天大学学报.1998,(5).106-109. 279 | [13]赵雪春,戚飞虎.基于彩色分割的车牌自动识别技术[J].上海交通大学学报.1998,(10).6-11. 280 | [14]谢磊.智能交通系统中的视频处理技术研究[D].2006 281 | [15]姚宇良.汽车牌照识别系统及其在智能卡口中的应用[D].2004 282 | [16]梁栋.智能交通系统中车牌定位的研究[D].2002 283 | [17]黄国胜.基于神经网络的实时车牌定位与识别系统研究[D].2002 284 | [18]马俊莉.车牌字符识别算法的研究[D].2002 285 | [19]Lienhart R.,Wernicke A..Localizing and segmenting text in images and videos[J].IEEE Transactions on Circuits & Systems for Video Technology.2002,12(4). 286 | 287 | 288 | 289 | --- 290 | #### 如果您需要更详细的【源码和环境部署教程】,除了通过【系统整合】小节的链接获取之外,还可以通过邮箱以下途径获取: 291 | #### 1.请先在GitHub上为该项目点赞(Star),编辑一封邮件,附上点赞的截图、项目的中文描述概述(About)以及您的用途需求,发送到我们的邮箱 292 | #### sharecode@yeah.net 293 | #### 2.我们收到邮件后会定期根据邮件的接收顺序将【完整源码和环境部署教程】发送到您的邮箱。 294 | #### 【免责声明】本文来源于用户投稿,如果侵犯任何第三方的合法权益,可通过邮箱联系删除。 -------------------------------------------------------------------------------- /SimpleRecognizePlateByE2E.py: -------------------------------------------------------------------------------- 1 | 2 | def SimpleRecognizePlateByE2E(self,image): 3 | images = self.detectPlateRough(image,image.shape[0],top_bottom_padding_rate=0.1) 4 | res_set = [] 5 | for j,plate in enumerate(images): 6 | plate, rect =plate 7 | image_rgb,rect_refine = self.finemappingVertical(plate,rect) 8 | res,confidence = self.recognizeOne(image_rgb) 9 | res_set.append([res,confidence,rect_refine]) 10 | return res_set 11 | -------------------------------------------------------------------------------- /c9ce3bd7d9ea735c4670147fa2bdb25f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/real-time-license-plate-recognition-opencv-python/a607e887da9b8d39c9070965087de70b7ae08f9d/c9ce3bd7d9ea735c4670147fa2bdb25f.png -------------------------------------------------------------------------------- /chars_u_京_u_沪_u_津_u_.py: -------------------------------------------------------------------------------- 1 | 2 | chars = [u"京", u"沪", u"津", u"渝", u"冀", u"晋", u"蒙", u"辽", u"吉", u"黑", u"苏", u"浙", u"皖", u"闽", u"赣", u"鲁", u"豫", u"鄂", u"湘", u"粤", u"桂", 3 | u"琼", u"川", u"贵", u"云", u"藏", u"陕", u"甘", u"青", u"宁", u"新", u"0", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"A", 4 | u"B", u"C", u"D", u"E", u"F", u"G", u"H", u"J", u"K", u"L", u"M", u"N", u"P", u"Q", u"R", u"S", u"T", u"U", u"V", u"W", u"X", 5 | u"Y", u"Z",u"港",u"学",u"使",u"警",u"澳",u"挂",u"军",u"北",u"南",u"广",u"沈",u"兰",u"成",u"济",u"海",u"民",u"航",u"空" 6 | ] 7 | -------------------------------------------------------------------------------- /detectPlateRough.py: -------------------------------------------------------------------------------- 1 | 2 | def detectPlateRough(self,image_gray,resize_h = 720,en_scale =1.08 ,top_bottom_padding_rate = 0.05): 3 | if top_bottom_padding_rate>0.2: 4 | print("error:top_bottom_padding_rate > 0.2:",top_bottom_padding_rate) 5 | exit(1) 6 | height = image_gray.shape[0] 7 | padding = int(height*top_bottom_padding_rate) 8 | scale = image_gray.shape[1]/float(image_gray.shape[0]) 9 | image = cv2.resize(image_gray, (int(scale*resize_h), resize_h)) 10 | image_color_cropped = image[padding:resize_h-padding,0:image_gray.shape[1]] 11 | image_gray = cv2.cvtColor(image_color_cropped,cv2.COLOR_RGB2GRAY) 12 | watches = self.watch_cascade.detectMultiScale(image_gray, en_scale, 2, minSize=(36, 9),maxSize=(36*40, 9*40)) 13 | cropped_images = [] 14 | for (x, y, w, h) in watches: 15 | x -= w * 0.14 16 | w += w * 0.28 17 | y -= h * 0.15 18 | h += h * 0.3 19 | cropped = self.cropImage(image_color_cropped, (int(x), int(y), int(w), int(h))) 20 | cropped_images.append([cropped,[x, y+padding, w, h]]) 21 | return cropped_images 22 | -------------------------------------------------------------------------------- /finemappingVertical.py: -------------------------------------------------------------------------------- 1 | 2 | def finemappingVertical(self,image,rect): 3 | resized = cv2.resize(image,(66,16)) 4 | resized = resized.astype(np.float)/255 5 | res_raw= (np.array([resized]))[0] 6 | res =res_raw*image.shape[1] 7 | res = res.astype(np.int) 8 | H,T = res 9 | H-=3 10 | if H<0: 11 | H=0 12 | T+=2; 13 | if T>= image.shape[1]-1: 14 | T= image.shape[1]-1 15 | rect[2] -= rect[2]*(1-res_raw[1] + res_raw[0]) 16 | rect[0]+=res[0] 17 | image = image[:,H:T+2] 18 | image = cv2.resize(image, (int(136), int(36))) 19 | return image,rect 20 | -------------------------------------------------------------------------------- /for_j_plate_in_enume.py: -------------------------------------------------------------------------------- 1 | 2 | for j,plate in enumerate(images): 3 | plate, rect =plate 4 | image_rgb,rect_refine = self.finemappingVertical(plate,rect) 5 | res,confidence = self.recognizeOne(image_rgb) 6 | res_set.append([res,confidence,rect_refine]) 7 | -------------------------------------------------------------------------------- /for_pstr_confidence_.py: -------------------------------------------------------------------------------- 1 | 2 | for pstr,confidence,rect in model.SimpleRecognizePlateByE2E(grr): 3 | if confidence>0.7: 4 | image = drawRectBox(grr, rect, pstr+" "+str(round(confidence,3))) 5 | print "plate_str:" 6 | print pstr 7 | print "plate_confidence" 8 | print confidence 9 | -------------------------------------------------------------------------------- /import_HyperLPRLite_.py: -------------------------------------------------------------------------------- 1 | 2 | import HyperLPRLite as pr 3 | import cv2 4 | import numpy as np 5 | grr = cv2.imread("images_rec/2_.jpg") 6 | model = pr.LPR("model/cascade.xml","model/model12.h5","model/ocr_plate_all_gru.h5") 7 | for pstr,confidence,rect in model.SimpleRecognizePlateByE2E(grr): 8 | if confidence>0.7: 9 | image = drawRectBox(grr, rect, pstr+" "+str(round(confidence,3))) 10 | print "plate_str:" 11 | print pstr 12 | print "plate_confidence" 13 | print confidence 14 | 15 | cv2.imshow("image",image) 16 | cv2.waitKey(0) 17 | -------------------------------------------------------------------------------- /model_finemapping.py: -------------------------------------------------------------------------------- 1 | 2 | def model_finemapping(self): 3 | input = Input(shape=[16, 66, 3]) # change this shape to [None,None,3] to enable arbitraty shape input 4 | x = Conv2D(10, (3, 3), strides=1, padding='valid', name='conv1')(input) 5 | x = Activation("relu", name='relu1')(x) 6 | x = MaxPool2D(pool_size=2)(x) 7 | x = Conv2D(16, (3, 3), strides=1, padding='valid', name='conv2')(x) 8 | x = Activation("relu", name='relu2')(x) 9 | x = Conv2D(32, (3, 3), strides=1, padding='valid', name='conv3')(x) 10 | x = Activation("relu", name='relu3')(x) 11 | x = Flatten()(x) 12 | output = Dense(2,name = "dense")(x) 13 | output = Activation("relu", name='relu4')(output) 14 | model = Model([input], [output]) 15 | return model 16 | -------------------------------------------------------------------------------- /model_seq_rec.py: -------------------------------------------------------------------------------- 1 | 2 | def model_seq_rec(self,model_path): 3 | width, height, n_len, n_class = 164, 48, 7, len(chars)+ 1 4 | rnn_size = 256 5 | input_tensor = Input((164, 48, 3)) 6 | x = input_tensor 7 | base_conv = 32 8 | for i in range(3): 9 | x = Conv2D(base_conv * (2 ** (i)), (3, 3))(x) 10 | x = BatchNormalization()(x) 11 | x = Activation('relu')(x) 12 | x = MaxPooling2D(pool_size=(2, 2))(x) 13 | conv_shape = x.get_shape() 14 | x = Reshape(target_shape=(int(conv_shape[1]), int(conv_shape[2] * conv_shape[3])))(x) 15 | x = Dense(32)(x) 16 | x = BatchNormalization()(x) 17 | x = Activation('relu')(x) 18 | gru_1 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru1')(x) 19 | gru_1b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru1_b')(x) 20 | gru1_merged = add([gru_1, gru_1b]) 21 | gru_2 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru2')(gru1_merged) 22 | gru_2b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru2_b')(gru1_merged) 23 | x = concatenate([gru_2, gru_2b]) 24 | x = Dropout(0.25)(x) 25 | x = Dense(n_class, kernel_initializer='he_normal', activation='softmax')(x) 26 | base_model = Model(inputs=input_tensor, outputs=x) 27 | base_model.load_weights(model_path) 28 | return base_model 29 | -------------------------------------------------------------------------------- /recognizeOne.py: -------------------------------------------------------------------------------- 1 | 2 | def recognizeOne(self,src): 3 | x_tempx = src 4 | x_temp = cv2.resize(x_tempx,( 164,48)) 5 | x_temp = x_temp.transpose(1, 0, 2) 6 | y_pred = self.modelSeqRec.predict(np.array([x_temp])) 7 | y_pred = y_pred[:,2:,:] 8 | return self.fastdecode(y_pred) 9 | --------------------------------------------------------------------------------