博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【深度学习系列】用PaddlePaddle进行车牌识别(一)
阅读量:6334 次
发布时间:2019-06-22

本文共 17061 字,大约阅读时间需要 56 分钟。

  小伙伴们,终于到了实战部分了!今天给大家带来的项目是用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 A11 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 img12 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 dst32 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 dst45 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 img57 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 img70 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 + noise90     return dst91 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.img24     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 com37 38     def genPlateString(self,pos,val):39         '''40     生成车牌String,存为图片41         生成车牌list,存为label42         '''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 += val51                 #print plateStr52                 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,plate67 68     # 将生成的车牌图片写入文件夹,对应的label写入label.txt69     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,plate76         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")

  完整代码:

1 #coding=utf-8  2 """   3    genPlate.py:生成随机车牌  4 """  5   6 __author__ = "Huxiaoman"  7 __copyright__ = "Copyright (c) 2017 "  8   9 import PIL 10 from PIL import ImageFont 11 from PIL import Image 12 from PIL import ImageDraw 13 import cv2; 14 import numpy as np; 15 import os; 16 from math import * 17 import sys 18  19  20 index = {
"京": 0, "沪": 1, "津": 2, "渝": 3, "冀": 4, "晋": 5, "蒙": 6, "辽": 7, "吉": 8, "黑": 9, "苏": 10, "浙": 11, "皖": 12, 21 "闽": 13, "赣": 14, "鲁": 15, "豫": 16, "鄂": 17, "湘": 18, "粤": 19, "桂": 20, "琼": 21, "川": 22, "贵": 23, "云": 24, 22 "藏": 25, "陕": 26, "甘": 27, "青": 28, "宁": 29, "新": 30, "0": 31, "1": 32, "2": 33, "3": 34, "4": 35, "5": 36, 23 "6": 37, "7": 38, "8": 39, "9": 40, "A": 41, "B": 42, "C": 43, "D": 44, "E": 45, "F": 46, "G": 47, "H": 48, 24 "J": 49, "K": 50, "L": 51, "M": 52, "N": 53, "P": 54, "Q": 55, "R": 56, "S": 57, "T": 58, "U": 59, "V": 60, 25 "W": 61, "X": 62, "Y": 63, "Z": 64}; 26 27 chars = ["京", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "皖", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", 28 "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", 29 "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", 30 "Y", "Z" 31 ]; 32 33 def AddSmudginess(img, Smu): 34 rows = r(Smu.shape[0] - 50) 35 cols = r(Smu.shape[1] - 50) 36 adder = Smu[rows:rows + 50, cols:cols + 50]; 37 adder = cv2.resize(adder, (50, 50)); 38 #adder = cv2.bitwise_not(adder) 39 img = cv2.resize(img,(50,50)) 40 img = cv2.bitwise_not(img) 41 img = cv2.bitwise_and(adder, img) 42 img = cv2.bitwise_not(img) 43 return img 44 45 def rot(img,angel,shape,max_angel): 46 """ 47 添加放射畸变 48 img 输入图像 49 factor 畸变的参数 50 size 为图片的目标尺寸 51 """ 52 size_o = [shape[1],shape[0]] 53 size = (shape[1]+ int(shape[0]*cos((float(max_angel )/180) * 3.14)),shape[0]) 54 interval = abs( int( sin((float(angel) /180) * 3.14)* shape[0])); 55 pts1 = np.float32([[0,0],[0,size_o[1]],[size_o[0],0],[size_o[0],size_o[1]]]) 56 if(angel>0): 57 pts2 = np.float32([[interval,0],[0,size[1] ],[size[0],0 ],[size[0]-interval,size_o[1]]]) 58 else: 59 pts2 = np.float32([[0,0],[interval,size[1] ],[size[0]-interval,0 ],[size[0],size_o[1]]]) 60 M = cv2.getPerspectiveTransform(pts1,pts2); 61 dst = cv2.warpPerspective(img,M,size); 62 return dst 63 64 def rotRandrom(img, factor, size): 65 """ 66 添加透视畸变 67 """ 68 shape = size; 69 pts1 = np.float32([[0, 0], [0, shape[0]], [shape[1], 0], [shape[1], shape[0]]]) 70 pts2 = np.float32([[r(factor), r(factor)], [ r(factor), shape[0] - r(factor)], [shape[1] - r(factor), r(factor)], 71 [shape[1] - r(factor), shape[0] - r(factor)]]) 72 M = cv2.getPerspectiveTransform(pts1, pts2); 73 dst = cv2.warpPerspective(img, M, size); 74 return dst 75 76 def tfactor(img): 77 """ 78 添加饱和度光照的噪声 79 """ 80 hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV); 81 hsv[:,:,0] = hsv[:,:,0]*(0.8+ np.random.random()*0.2); 82 hsv[:,:,1] = hsv[:,:,1]*(0.3+ np.random.random()*0.7); 83 hsv[:,:,2] = hsv[:,:,2]*(0.2+ np.random.random()*0.8); 84 85 img = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR); 86 return img 87 88 def random_envirment(img,data_set): 89 """ 90 添加自然环境的噪声 91 """ 92 index=r(len(data_set)) 93 env = cv2.imread(data_set[index]) 94 env = cv2.resize(env,(img.shape[1],img.shape[0])) 95 bak = (img==0); 96 bak = bak.astype(np.uint8)*255; 97 inv = cv2.bitwise_and(bak,env) 98 img = cv2.bitwise_or(inv,img) 99 return img100 101 def GenCh(f,val):102 """103 生成中文字符104 """105 img=Image.new("RGB", (45,70),(255,255,255))106 draw = ImageDraw.Draw(img)107 draw.text((0, 3),val,(0,0,0),font=f)108 img = img.resize((23,70))109 A = np.array(img)110 return A111 112 def GenCh1(f,val):113 """114 生成英文字符115 """116 img=Image.new("RGB", (23,70),(255,255,255))117 draw = ImageDraw.Draw(img)118 draw.text((0, 2),val.decode('utf-8'),(0,0,0),font=f)119 A = np.array(img)120 return A121 122 def AddGauss(img, level):123 """124 添加高斯模糊125 """ 126 return cv2.blur(img, (level * 2 + 1, level * 2 + 1));127 128 def r(val):129 return int(np.random.random() * val)130 131 def AddNoiseSingleChannel(single):132 """133 添加高斯噪声134 """135 diff = 255-single.max();136 noise = np.random.normal(0,1+r(6),single.shape);137 noise = (noise - noise.min())/(noise.max()-noise.min())138 noise= diff*noise;139 noise= noise.astype(np.uint8)140 dst = single + noise141 return dst142 143 def addNoise(img,sdev = 0.5,avg=10):144 img[:,:,0] = AddNoiseSingleChannel(img[:,:,0]);145 img[:,:,1] = AddNoiseSingleChannel(img[:,:,1]);146 img[:,:,2] = AddNoiseSingleChannel(img[:,:,2]);147 return img148 149 150 class GenPlate:151 152 def __init__(self,fontCh,fontEng,NoPlates):153 self.fontC = ImageFont.truetype(fontCh,43,0);154 self.fontE = ImageFont.truetype(fontEng,60,0);155 self.img=np.array(Image.new("RGB", (226,70),(255,255,255)))156 self.bg = cv2.resize(cv2.imread("./images/template.bmp"),(226,70));157 self.smu = cv2.imread("./images/smu2.jpg");158 self.noplates_path = [];159 for parent,parent_folder,filenames in os.walk(NoPlates):160 for filename in filenames:161 path = parent+"/"+filename;162 self.noplates_path.append(path);163 164 165 def draw(self,val):166 offset= 2 ;167 self.img[0:70,offset+8:offset+8+23]= GenCh(self.fontC,val[0]);168 self.img[0:70,offset+8+23+6:offset+8+23+6+23]= GenCh1(self.fontE,val[1]);169 for i in range(5):170 base = offset+8+23+6+23+17 +i*23 + i*6 ;171 self.img[0:70, base : base+23]= GenCh1(self.fontE,val[i+2]);172 return self.img173 174 def generate(self,text):175 if len(text) == 9:176 fg = self.draw(text.decode(encoding="utf-8"));177 fg = cv2.bitwise_not(fg);178 com = cv2.bitwise_or(fg,self.bg);179 com = rot(com,r(60)-30,com.shape,30);180 com = rotRandrom(com,10,(com.shape[1],com.shape[0]));181 com = tfactor(com)182 com = random_envirment(com,self.noplates_path);183 com = AddGauss(com, 1+r(4));184 com = addNoise(com);185 return com186 187 def genPlateString(self,pos,val):188 '''189 生成车牌String,存为图片190 生成车牌list,存为label191 '''192 plateStr = "";193 plateList=[]194 box = [0,0,0,0,0,0,0];195 if(pos!=-1):196 box[pos]=1;197 for unit,cpos in zip(box,range(len(box))):198 if unit == 1:199 plateStr += val200 #print plateStr201 plateList.append(val)202 else:203 if cpos == 0:204 plateStr += chars[r(31)]205 plateList.append(plateStr)206 elif cpos == 1:207 plateStr += chars[41+r(24)]208 plateList.append(plateStr)209 else:210 plateStr += chars[31 + r(34)]211 plateList.append(plateStr)212 plate = [plateList[0]]213 b = [plateList[i][-1] for i in range(len(plateList))]214 plate.extend(b[1:7])215 return plateStr,plate216 217 # 将生成的车牌图片写入文件夹,对应的label写入label.txt218 def genBatch(self, batchSize,pos,charRange, outputPath,size):219 if (not os.path.exists(outputPath)):220 os.mkdir(outputPath)221 outfile = open('label.txt','w')222 for i in xrange(batchSize):223 plateStr,plate = G.genPlateString(-1,-1)224 print plateStr,plate225 img = G.generate(plateStr);226 img = cv2.resize(img,size);227 cv2.imwrite(outputPath + "/" + str(i).zfill(2) + ".jpg", img);228 outfile.write(str(plate)+"\n")229 G = GenPlate("./font/platech.ttf",'./font/platechar.ttf',"./NoPlates")230 #G.genBatch(100,2,range(31,65),"./plate_100",(272,72))231 232 if __name__=='__main__':233 G.genBatch(int(sys.argv[1]),2,range(31,65),sys.argv[2],(272,72))
View Code

  运行时加生成数量和保存路径即可,如:

 1 python genPlate.py 100 ./plate_100 

  显示结果:

 

  上图即为生成的车牌数据,有清晰的有模糊的,有比较方正的,也有一些比较倾斜,生成完大量的车牌样张后就可以进行车牌识别了。下一小节将会讲如何用端对端的CNN进行车牌识别,不需要通过传统的ocr先对字符进行分割处理后再识别。

 

参考资料:

1.原来做的车牌识别项目:https://github.com/huxiaoman7/mxnet-cnn-plate-recognition 

转载地址:http://fdioa.baihongyu.com/

你可能感兴趣的文章
Business Contact Mnanager for Outlook2010
查看>>
9种用户体验设计的状态是必须知道的(五)
查看>>
解决WIN7下组播问题
查看>>
陈松松:视频营销成交率低,这三个因素没到位
查看>>
vmware nat模式原理探究,实现虚拟机跨网段管理
查看>>
JavaSE 学习参考:集合运算
查看>>
【Signals and Systems】 SYLLABUS
查看>>
RH135-2-command-line-interface
查看>>
浅谈OS
查看>>
mac下开启docker API远程调用
查看>>
tar 命令的详解
查看>>
Cisco路由器安全配置
查看>>
第十次作业
查看>>
给定一个字符串s,返回去掉子串"mi"后的字符串。
查看>>
Nginx 外的另一选择,轻量级开源 Web 服务器 Tengine 发布新版本
查看>>
Wrod中超链接的一些技巧
查看>>
我的友情链接
查看>>
IP_VFR-4-FRAG_TABLE_OVERFLOW【cisco设备报错】碎片***
查看>>
Codeforces Round #256 (Div. 2) D. Multiplication Table 【二分】
查看>>
ARM汇编指令格式
查看>>