You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

HyperLPRLite.py 6.9 kB

7 years ago
7 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #coding=utf-8
  2. import cv2
  3. import numpy as np
  4. from keras import backend as K
  5. from keras.models import *
  6. from keras.layers import *
  7. chars = [u"京", u"沪", u"津", u"渝", u"冀", u"晋", u"蒙", u"辽", u"吉", u"黑", u"苏", u"浙", u"皖", u"闽", u"赣", u"鲁", u"豫", u"鄂", u"湘", u"粤", u"桂",
  8. 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",
  9. 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",
  10. u"Y", u"Z",u"港",u"学",u"使",u"警",u"澳",u"挂",u"军",u"北",u"南",u"广",u"沈",u"兰",u"成",u"济",u"海",u"民",u"航",u"空"
  11. ]
  12. class LPR():
  13. def __init__(self,model_detection,model_finemapping,model_seq_rec):
  14. self.watch_cascade = cv2.CascadeClassifier(model_detection)
  15. self.modelFineMapping = self.model_finemapping()
  16. self.modelFineMapping.load_weights(model_finemapping)
  17. self.modelSeqRec = self.model_seq_rec(model_seq_rec)
  18. def computeSafeRegion(self,shape,bounding_rect):
  19. top = bounding_rect[1] # y
  20. bottom = bounding_rect[1] + bounding_rect[3] # y + h
  21. left = bounding_rect[0] # x
  22. right = bounding_rect[0] + bounding_rect[2] # x + w
  23. min_top = 0
  24. max_bottom = shape[0]
  25. min_left = 0
  26. max_right = shape[1]
  27. if top < min_top:
  28. top = min_top
  29. if left < min_left:
  30. left = min_left
  31. if bottom > max_bottom:
  32. bottom = max_bottom
  33. if right > max_right:
  34. right = max_right
  35. return [left,top,right-left,bottom-top]
  36. def cropImage(self,image,rect):
  37. x, y, w, h = self.computeSafeRegion(image.shape,rect)
  38. return image[y:y+h,x:x+w]
  39. def detectPlateRough(self,image_gray,resize_h = 720,en_scale =1.08 ,top_bottom_padding_rate = 0.05):
  40. if top_bottom_padding_rate>0.2:
  41. print("error:top_bottom_padding_rate > 0.2:",top_bottom_padding_rate)
  42. exit(1)
  43. height = image_gray.shape[0]
  44. padding = int(height*top_bottom_padding_rate)
  45. scale = image_gray.shape[1]/float(image_gray.shape[0])
  46. image = cv2.resize(image_gray, (int(scale*resize_h), resize_h))
  47. image_color_cropped = image[padding:resize_h-padding,0:image_gray.shape[1]]
  48. image_gray = cv2.cvtColor(image_color_cropped,cv2.COLOR_RGB2GRAY)
  49. watches = self.watch_cascade.detectMultiScale(image_gray, en_scale, 2, minSize=(36, 9),maxSize=(36*40, 9*40))
  50. cropped_images = []
  51. for (x, y, w, h) in watches:
  52. x -= w * 0.14
  53. w += w * 0.28
  54. y -= h * 0.15
  55. h += h * 0.3
  56. cropped = self.cropImage(image_color_cropped, (int(x), int(y), int(w), int(h)))
  57. cropped_images.append([cropped,[x, y+padding, w, h]])
  58. return cropped_images
  59. def fastdecode(self,y_pred):
  60. results = ""
  61. confidence = 0.0
  62. table_pred = y_pred.reshape(-1, len(chars)+1)
  63. res = table_pred.argmax(axis=1)
  64. for i,one in enumerate(res):
  65. if one<len(chars) and (i==0 or (one!=res[i-1])):
  66. results+= chars[one]
  67. confidence+=table_pred[i][one]
  68. confidence/= len(results)
  69. return results,confidence
  70. def model_seq_rec(self,model_path):
  71. width, height, n_len, n_class = 164, 48, 7, len(chars)+ 1
  72. rnn_size = 256
  73. input_tensor = Input((164, 48, 3))
  74. x = input_tensor
  75. base_conv = 32
  76. for i in range(3):
  77. x = Conv2D(base_conv * (2 ** (i)), (3, 3))(x)
  78. x = BatchNormalization()(x)
  79. x = Activation('relu')(x)
  80. x = MaxPooling2D(pool_size=(2, 2))(x)
  81. conv_shape = x.get_shape()
  82. x = Reshape(target_shape=(int(conv_shape[1]), int(conv_shape[2] * conv_shape[3])))(x)
  83. x = Dense(32)(x)
  84. x = BatchNormalization()(x)
  85. x = Activation('relu')(x)
  86. gru_1 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru1')(x)
  87. gru_1b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru1_b')(x)
  88. gru1_merged = add([gru_1, gru_1b])
  89. gru_2 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru2')(gru1_merged)
  90. gru_2b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru2_b')(gru1_merged)
  91. x = concatenate([gru_2, gru_2b])
  92. x = Dropout(0.25)(x)
  93. x = Dense(n_class, kernel_initializer='he_normal', activation='softmax')(x)
  94. base_model = Model(inputs=input_tensor, outputs=x)
  95. base_model.load_weights(model_path)
  96. return base_model
  97. def model_finemapping(self):
  98. input = Input(shape=[16, 66, 3]) # change this shape to [None,None,3] to enable arbitraty shape input
  99. x = Conv2D(10, (3, 3), strides=1, padding='valid', name='conv1')(input)
  100. x = Activation("relu", name='relu1')(x)
  101. x = MaxPool2D(pool_size=2)(x)
  102. x = Conv2D(16, (3, 3), strides=1, padding='valid', name='conv2')(x)
  103. x = Activation("relu", name='relu2')(x)
  104. x = Conv2D(32, (3, 3), strides=1, padding='valid', name='conv3')(x)
  105. x = Activation("relu", name='relu3')(x)
  106. x = Flatten()(x)
  107. output = Dense(2,name = "dense")(x)
  108. output = Activation("relu", name='relu4')(output)
  109. model = Model([input], [output])
  110. return model
  111. def finemappingVertical(self,image,rect):
  112. resized = cv2.resize(image,(66,16))
  113. resized = resized.astype(np.float)/255
  114. res_raw= self.modelFineMapping.predict(np.array([resized]))[0]
  115. res =res_raw*image.shape[1]
  116. res = res.astype(np.int)
  117. H,T = res
  118. H-=3
  119. if H<0:
  120. H=0
  121. T+=2;
  122. if T>= image.shape[1]-1:
  123. T= image.shape[1]-1
  124. rect[2] -= rect[2]*(1-res_raw[1] + res_raw[0])
  125. rect[0]+=res[0]
  126. image = image[:,H:T+2]
  127. image = cv2.resize(image, (int(136), int(36)))
  128. return image,rect
  129. def recognizeOne(self,src):
  130. x_tempx = src
  131. x_temp = cv2.resize(x_tempx,( 164,48))
  132. x_temp = x_temp.transpose(1, 0, 2)
  133. y_pred = self.modelSeqRec.predict(np.array([x_temp]))
  134. y_pred = y_pred[:,2:,:]
  135. return self.fastdecode(y_pred)
  136. def SimpleRecognizePlateByE2E(self,image):
  137. images = self.detectPlateRough(image,image.shape[0],top_bottom_padding_rate=0.1)
  138. res_set = []
  139. for j,plate in enumerate(images):
  140. plate, rect =plate
  141. image_rgb,rect_refine = self.finemappingVertical(plate,rect)
  142. res,confidence = self.recognizeOne(image_rgb)
  143. res_set.append([res,confidence,rect_refine])
  144. return res_set