未来智库 > 新闻资讯 > 用PaddlePaddle进行车牌识别一

      小伙伴们,终于到了实战部分了!今天给大家带来的项目是用PaddlePaddle进行车牌识别。车牌识别其实属于比较常见的图像识别的项目了,目前也属于比较成熟的应用,大多数老牌厂家能做到准确率99%+。传统的方法需要对图像进行多次预处理再用机器学习的分类算法进行分类识别,然而深度学习发展起来以后,我们可以通过用CNN来进行端对端的车牌识别。任何模型的训练都离不开数据,在车牌识别中,除了晚上能下载到的一些包含车牌的数据是不够的,本篇文章的主要目的是教大家如何批量生成车牌。
      生成车牌数据
      1.定义车牌数据所需字符
      车牌中包括省份简称、大写英文字母和数字,我们首先定义需要的字符和字典,方便后面使用
      
      1 index = {"京": 0, "沪": 1, "津": 2, "渝": 3, "冀": 4, "晋": 5, "蒙": 6, "辽": 7, "吉": 8, "黑": 9, "苏": 10, "浙": 11, "皖": 12,
      2 "闽": 13, "赣": 14, "鲁": 15, "豫": 16, "鄂": 17, "湘": 18, "粤": 19, "桂": 20, "琼": 21, "川": 22, "贵": 23, "云": 24,
      3 "藏": 25, "陕": 26, "甘": 27, "青": 28, "宁": 29, "新": 30, "0": 31, "1": 32, "2": 33, "3": 34, "4": 35, "5": 36,
      4 "6": 37, "7": 38, "8": 39, "9": 40, "A": 41, "B": 42, "C": 43, "D": 44, "E": 45, "F": 46, "G": 47, "H": 48,
      5 "J": 49, "K": 50, "L": 51, "M": 52, "N": 53, "P": 54, "Q": 55, "R": 56, "S": 57, "T": 58, "U": 59, "V": 60,
      6 "W": 61, "X": 62, "Y": 63, "Z": 64};
      7
      8 chars = ["京", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "皖", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂",
      9 "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A",
      10 "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X",
      11 "Y", "Z"
      12 ];
      
      
      2.生成中英文字符
      
      1 def GenCh(f,val):
      2 """
      3 生成中文字符
      4 """
      5 img=Image.new("RGB", (45,70),(255,255,255))
      6 draw = ImageDraw.Draw(img)
      7 draw.text((0, 3),val,(0,0,0),font=f)
      8 img = img.resize((23,70))
      9 A = np.array(img)
      10 return A
      11
      12 def GenCh1(f,val):
      13 """
      14 生成英文字符
      15 """
      16 img=Image.new("RGB", (23,70),(255,255,255))
      17 draw = ImageDraw.Draw(img)
      18 draw.text((0, 2),val.decode('utf-8'),(0,0,0),font=f)
      19 A = np.array(img)
      20 return A
      
      
      3.对数据添加各种噪音和畸变,模糊处理
      
      1 def AddSmudginess(img, Smu):
      2 rows = r(Smu.shape[0] - 50)
      3 cols = r(Smu.shape[1] - 50)
      4 adder = Smu[rows:rows + 50, cols:cols + 50];
      5 adder = cv2.resize(adder, (50, 50));
      6 #adder = cv2.bitwise_not(adder)
      7 img = cv2.resize(img,(50,50))
      8 img = cv2.bitwise_not(img)
      9 img = cv2.bitwise_and(adder, img)
      10 img = cv2.bitwise_not(img)
      11 return img
      12
      13
      14 def rot(img,angel,shape,max_angel):
      15 """
      16 添加放射畸变
      17 img 输入图像
      18 factor 畸变的参数
      19 size 为图片的目标尺寸
      20 """
      21 size_o = [shape[1],shape[0]]
      22 size = (shape[1]+ int(shape[0]*cos((float(max_angel )/180) * 3.14)),shape[0])
      23 interval = abs( int( sin((float(angel) /180) * 3.14)* shape[0]));
      24 pts1 = np.float32([[0,0],[0,size_o[1]],[size_o[0],0],[size_o[0],size_o[1]]])
      25 if(angel>0):
      26 pts2 = np.float32([[interval,0],[0,size[1] ],[size[0],0 ],[size[0]-interval,size_o[1]]])
      27 else:
      28 pts2 = np.float32([[0,0],[interval,size[1] ],[size[0]-interval,0 ],[size[0],size_o[1]]])
      29 M = cv2.getPerspectiveTransform(pts1,pts2);
      30 dst = cv2.warpPerspective(img,M,size);
      31 return dst
      32
      33
      34 def rotRandrom(img, factor, size):
      35 """
      36 添加透视畸变
      37 """
      38 shape = size;
      39 pts1 = np.float32([[0, 0], [0, shape[0]], [shape[1], 0], [shape[1], shape[0]]])
      40 pts2 = np.float32([[r(factor), r(factor)], [ r(factor), shape[0] - r(factor)], [shape[1] - r(factor), r(factor)],
      41 [shape[1] - r(factor), shape[0] - r(factor)]])
      42 M = cv2.getPerspectiveTransform(pts1, pts2);
      43 dst = cv2.warpPerspective(img, M, size);
      44 return dst
      45
      46 def tfactor(img):
      47 """
      48 添加饱和度光照的噪声
      49 """
      50 hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV);
      51 hsv[:,:,0] = hsv[:,:,0]*(0.8+ np.random.random()*0.2);
      52 hsv[:,:,1] = hsv[:,:,1]*(0.3+ np.random.random()*0.7);
      53 hsv[:,:,2] = hsv[:,:,2]*(0.2+ np.random.random()*0.8);
      54
      55 img = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR);
      56 return img
      57
      58 def random_envirment(img,data_set):
      59 """
      60 添加自然环境的噪声
      61 """
      62 index=r(len(data_set))
      63 env = cv2.imread(data_set[index])
      64 env = cv2.resize(env,(img.shape[1],img.shape[0]))
      65 bak = (img==0);
      66 bak = bak.astype(np.uint8)*255;
      67 inv = cv2.bitwise_and(bak,env)
      68 img = cv2.bitwise_or(inv,img)
      69 return img
      70
      71 def AddGauss(img, level):
      72 """
      73 添加高斯模糊
      74 """
      75 return cv2.blur(img, (level * 2 + 1, level * 2 + 1));
      76
      77 def r(val):
      78 return int(np.random.random() * val)
      79
      80 def AddNoiseSingleChannel(single):
      81 """
      82 添加高斯噪声
      83 """
      84 diff = 255-single.max();
      85 noise = np.random.normal(0,1+r(6),single.shape);
      86 noise = (noise - noise.min())/(noise.max()-noise.min())
      87 noise= diff*noise;
      88 noise= noise.astype(np.uint8)
      89 dst = single + noise
      90 return dst
      91
      92 def addNoise(img,sdev = 0.5,avg=10):
      93 img[:,:,0] = AddNoiseSingleChannel(img[:,:,0]);
      94 img[:,:,1] = AddNoiseSingleChannel(img[:,:,1]);
      95 img[:,:,2] = AddNoiseSingleChannel(img[:,:,2]);
      96 return img
      
      
      4.加入背景图片,生成车牌字符串list和label,并存为图片格式,批量生成。
      
      1 class GenPlate:
      2
      3 def __init__(self,fontCh,fontEng,NoPlates):
      4 self.fontC = ImageFont.truetype(fontCh,43,0);
      5 self.fontE = ImageFont.truetype(fontEng,60,0);
      6 self.img=np.array(Image.new("RGB", (226,70),(255,255,255)))
      7 self.bg = cv2.resize(cv2.imread("./images/template.bmp"),(226,70));
      8 self.smu = cv2.imread("./images/smu2.jpg");
      9 self.noplates_path = [];
      10 for parent,parent_folder,filenames in os.walk(NoPlates):
      11 for filename in filenames:
      12 path = parent+"/"+filename;
      13 self.noplates_path.append(path);
      14
      15
      16 def draw(self,val):
      17 offset= 2 ;
      18 self.img[0:70,offset+8:offset+8+23]= GenCh(self.fontC,val[0]);
      19 self.img[0:70,offset+8+23+6:offset+8+23+6+23]= GenCh1(self.fontE,val[1]);
      20 for i in range(5):
      21 base = offset+8+23+6+23+17 +i*23 + i*6 ;
      22 self.img[0:70, base : base+23]= GenCh1(self.fontE,val[i+2]);
      23 return self.img
      24
      25 def generate(self,text):
      26 if len(text) == 9:
      27 fg = self.draw(text.decode(encoding="utf-8"));
      28 fg = cv2.bitwise_not(fg);
      29 com = cv2.bitwise_or(fg,self.bg);
      30 com = rot(com,r(60)-30,com.shape,30);
      31 com = rotRandrom(com,10,(com.shape[1],com.shape[0]));
      32 com = tfactor(com)
      33 com = random_envirment(com,self.noplates_path);
      34 com = AddGauss(com, 1+r(4));
      35 com = addNoise(com);
      36 return com
      37
      38 def genPlateString(self,pos,val):
      39 '''
      40 生成车牌String,存为图片
      41 生成车牌list,存为label
      42 '''
      43 plateStr = "";
      44 plateList=[]
      45 box = [0,0,0,0,0,0,0];
      46 if(pos!=-1):
      47 box[pos]=1;
      48 for unit,cpos in zip(box,range(len(box))):
      49 if unit == 1:
      50 plateStr += val
      51 #print plateStr
      52 plateList.append(val)
      53 else:
      54 if cpos == 0:
      55 plateStr += chars[r(31)]
      56 plateList.append(plateStr)
      57 elif cpos == 1:
      58 plateStr += chars[41+r(24)]
      59 plateList.append(plateStr)
      60 else:
      61 plateStr += chars[31 + r(34)]
      62 plateList.append(plateStr)
      63 plate = [plateList[0]]
      64 b = [plateList[i][-1] for i in range(len(plateList))]
      65 plate.extend(b[1:7])
      66 return plateStr,plate
      67
      68 # 将生成的车牌图片写入文件夹,对应的label写入label.txt
      69 def genBatch(self, batchSize,pos,charRange, outputPath,size):
      70 if (not os.path.exists(outputPath)):
      71 os.mkdir(outputPath)
      72 outfile = open('label.txt','w')
      73 for i in xrange(batchSize):
      74 plateStr,plate = G.genPlateString(-1,-1)
      75 print plateStr,plate
      76 img = G.generate(plateStr);
      77 img = cv2.resize(img,size);
      78 cv2.imwrite(outputPath + "/" + str(i).zfill(2) + ".jpg", img);
      79 outfile.write(str(plate)+"\n")
      80 G = GenPlate("./font/platech.ttf",'./font/platechar.ttf',"./NoPlates")
      
      完整代码:
      View Code
      运行时加生成数量和保存路径即可,如:
      1python genPlate.py 100 ./plate_100
      显示结果:
      
      上图即为生成的车牌数据,有清晰的有模糊的,有比较方正的,也有一些比较倾斜,生成完大量的车牌样张后就可以进行车牌识别了。下一小节将会讲如何用端对端的CNN进行车牌识别,不需要通过传统的ocr先对字符进行分割处理后再识别。
      参考资料:
      1.原来做的车牌识别项目:https://github.com/huxiaoman7/mxnet-cnn-plate-recognition
      作者:Charlotte77
转载请注明来源。原文地址:https://www.7428.cn/vipzj15370/
 与本篇相关的热门内容: