首页 > 互联网 > 业界 > 正文

用PaddlePaddle进行车牌识别(一)
2018-04-12 16:09   观天下      我要评论()
字号:T|T

小伙伴们,终于到了实战部分了!今天给大家带来的项目是用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

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

1 python genPlate.py 100 ./plate_100 

显示结果:

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

参考资料:

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

作者:Charlotte77 

投稿:news@newhua.com

关键词: PaddlePaddle

责任编辑:新闻中心

我要评论

已有位网友参与评论

网站地图

牛华网

华军下载 | 牛华网 | 盒子 | pcsoft | 论坛

实用工具

关于我们 | 新闻投稿 | 软件发布 | 版权声明 | 意见建议 | 网站地图 | 友情连接 | RSS订阅 | 总编信箱 | 诚聘英才 | 联系我们

苏ICP备11016551号-2  苏公网安备 32132202000111号 本站特聘法律顾问:于国富律师

Copyright (C) 1997-2018 newhua.com 江苏奥蓝德软件有限公司 版权所有