接上篇车牌识别系列,Tensorflow生成车牌数据(一),实际上上篇生成的数据仅仅是一个字符串序列,加上对应的label,使用Pygame或者其他库生成图片后,并不具备真实感觉的车牌。考虑到实际车牌拍照出来的效果,我们必须添加些环境噪声,模糊处理,畸变等,让最终生成的车牌看起来更加接近真实图片拍下来的效果。并且加入背景图片,生成车牌字符串list和label,存为图片格式,批量生成。

先来看看效果:

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

源码如下:

#coding=utf-8
""" genPlate.py:生成随机车牌
"""__author__ = "Huxiaoman&Gavin"
__copyright__ = "Copyright (c) 2018 "import PIL
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw
import cv2
import numpy as np
import os
from math import *
import sysindex = {"京": 0, "沪": 1, "津": 2, "渝": 3, "冀": 4, "晋": 5, "蒙": 6, "辽": 7, "吉": 8, "黑": 9, "苏": 10, "浙": 11, "皖": 12,"闽": 13, "赣": 14, "鲁": 15, "豫": 16, "鄂": 17, "湘": 18, "粤": 19, "桂": 20, "琼": 21, "川": 22, "贵": 23, "云": 24,"藏": 25, "陕": 26, "甘": 27, "青": 28, "宁": 29, "新": 30, "0": 31, "1": 32, "2": 33, "3": 34, "4": 35, "5": 36,"6": 37, "7": 38, "8": 39, "9": 40, "A": 41, "B": 42, "C": 43, "D": 44, "E": 45, "F": 46, "G": 47, "H": 48,"J": 49, "K": 50, "L": 51, "M": 52, "N": 53, "P": 54, "Q": 55, "R": 56, "S": 57, "T": 58, "U": 59, "V": 60,"W": 61, "X": 62, "Y": 63, "Z": 64}chars = ["京", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "皖", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂","琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A","B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X","Y", "Z"]def AddSmudginess(img, Smu):rows = r(Smu.shape[0] - 50)cols = r(Smu.shape[1] - 50)adder = Smu[rows:rows + 50, cols:cols + 50]adder = cv2.resize(adder, (50, 50))#adder = cv2.bitwise_not(adder)img = cv2.resize(img,(50,50))img = cv2.bitwise_not(img)img = cv2.bitwise_and(adder, img)img = cv2.bitwise_not(img)return imgdef rot(img,angel,shape,max_angel):"""添加透视畸变"""size_o = [shape[1],shape[0]]size = (shape[1]+ int(shape[0]*cos((float(max_angel )/180) * 3.14)),shape[0])interval = abs( int( sin((float(angel) /180) * 3.14)* shape[0]))pts1 = np.float32([[0,0],[0,size_o[1]],[size_o[0],0],[size_o[0],size_o[1]]])if(angel>0):pts2 = np.float32([[interval,0],[0,size[1]  ],[size[0],0  ],[size[0]-interval,size_o[1]]])else:pts2 = np.float32([[0,0],[interval,size[1]  ],[size[0]-interval,0  ],[size[0],size_o[1]]])M  = cv2.getPerspectiveTransform(pts1,pts2)dst = cv2.warpPerspective(img,M,size)return dstdef rotRandrom(img, factor, size):"""添加放射畸变img 输入图像factor 畸变的参数size 为图片的目标尺寸"""shape = sizepts1 = np.float32([[0, 0], [0, shape[0]], [shape[1], 0], [shape[1], shape[0]]])pts2 = np.float32([[r(factor), r(factor)], [ r(factor), shape[0] - r(factor)], [shape[1] - r(factor),  r(factor)],[shape[1] - r(factor), shape[0] - r(factor)]])M = cv2.getPerspectiveTransform(pts1, pts2)dst = cv2.warpPerspective(img, M, size)return dstdef tfactor(img):"""添加饱和度光照的噪声"""hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)hsv[:,:,0] = hsv[:,:,0]*(0.8+ np.random.random()*0.2)hsv[:,:,1] = hsv[:,:,1]*(0.3+ np.random.random()*0.7)hsv[:,:,2] = hsv[:,:,2]*(0.2+ np.random.random()*0.8)img = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR)return imgdef random_envirment(img,data_set):"""添加自然环境的噪声    """index=r(len(data_set))env = cv2.imread(data_set[index])env = cv2.resize(env,(img.shape[1],img.shape[0]))bak = (img==0)bak = bak.astype(np.uint8)*255inv = cv2.bitwise_and(bak,env)img = cv2.bitwise_or(inv,img)return imgdef GenCh(f,val):"""生成中文字符"""img=Image.new("RGB", (45,70),(255,255,255))draw = ImageDraw.Draw(img)draw.text((0, 3),val,(0,0,0),font=f)img =  img.resize((23,70))A = np.array(img)return Adef GenCh1(f,val):"""生成英文字符"""img=Image.new("RGB", (23,70),(255,255,255))draw = ImageDraw.Draw(img)draw.text((0, 2),val,(0,0,0),font=f) # val.decode('utf-8')A = np.array(img)return Adef AddGauss(img, level):"""添加高斯模糊""" return cv2.blur(img, (level * 2 + 1, level * 2 + 1))def r(val):return int(np.random.random() * val)def AddNoiseSingleChannel(single):"""添加高斯噪声"""diff = 255-single.max()noise = np.random.normal(0,1+r(6),single.shape)noise = (noise - noise.min())/(noise.max()-noise.min())noise= diff*noisenoise= noise.astype(np.uint8)dst = single + noisereturn dstdef addNoise(img,sdev = 0.5,avg=10):img[:,:,0] =  AddNoiseSingleChannel(img[:,:,0])img[:,:,1] =  AddNoiseSingleChannel(img[:,:,1])img[:,:,2] =  AddNoiseSingleChannel(img[:,:,2])return imgclass GenPlate:def __init__(self,fontCh,fontEng,NoPlates):self.fontC =  ImageFont.truetype(fontCh,43,0)self.fontE =  ImageFont.truetype(fontEng,60,0)self.img=np.array(Image.new("RGB", (226,70),(255,255,255)))self.bg  = cv2.resize(cv2.imread("./images/template.bmp"),(226,70))self.smu = cv2.imread("./images/smu2.jpg")self.noplates_path = []for parent,parent_folder,filenames in os.walk(NoPlates):for filename in filenames:path = parent+"/"+filenameself.noplates_path.append(path)def draw(self,val):offset= 2self.img[0:70,offset+8:offset+8+23]= GenCh(self.fontC,val[0])self.img[0:70,offset+8+23+6:offset+8+23+6+23]= GenCh1(self.fontE,val[1])for i in range(5):base = offset+8+23+6+23+17 +i*23 + i*6self.img[0:70, base  : base+23]= GenCh1(self.fontE,val[i+2])return self.imgdef generate(self,text):if len(text) == 7:fg = self.draw(text) #.decode(encoding="utf-8")fg = cv2.bitwise_not(fg)com = cv2.bitwise_or(fg,self.bg)com = rot(com,r(60)-30,com.shape,30)com = rotRandrom(com,10,(com.shape[1],com.shape[0]))com = tfactor(com)com = random_envirment(com,self.noplates_path)com = AddGauss(com, 1+r(4))com = addNoise(com)return comdef genPlateString(self,pos,val):'''生成车牌String,存为图片生成车牌list,存为label'''plateStr = ""plateList=[]box = [0,0,0,0,0,0,0]if(pos!=-1):box[pos]=1for unit,cpos in zip(box,range(len(box))):if unit == 1:plateStr += val#print plateStrplateList.append(val)else:if cpos == 0:plateStr += chars[r(31)]plateList.append(plateStr)elif cpos == 1:plateStr += chars[41+r(24)]plateList.append(plateStr)else:plateStr += chars[31 + r(34)]plateList.append(plateStr)plate = [plateList[0]]b = [plateList[i][-1] for i in range(len(plateList))]plate.extend(b[1:7])return plateStr,plate# 将生成的车牌图片写入文件夹,对应的label写入label.txtdef genBatch(self, batchSize,pos,charRange, outputPath,size):if (not os.path.exists(outputPath)):os.mkdir(outputPath)outfile = open('label.txt','w')for i in range(batchSize):plateStr,plate = G.genPlateString(-1,-1)print(plateStr,plate)# print('len of %s:%d' %(plateStr,len(plateStr)))img =  G.generate(plateStr)img = cv2.resize(img,size)cv2.imwrite(outputPath + "/" + str(i).zfill(2) + ".jpg", img)outfile.write(str(plate)+"\n")G = GenPlate("./font/platech.ttf",'./font/platechar.ttf',"./NoPlates")if __name__=='__main__':G.genBatch(int(sys.argv[1]),2,range(31,65),sys.argv[2],(272,72))

参考github:https://github.com/huxiaoman7/mxnet-cnn-plate-recognition

车牌识别系列(二)生成具有真实感的(realistic)车牌数据相关推荐

  1. android图像识别二次开发包,车牌识别一体机二次开发包sdk详细介绍

    原标题:车牌识别一体机二次开发包sdk详细介绍 无论是车辆管理系统,洗车房,二手车交易,汽车4S店,称重系统还是考勤系统均能和易泊完美结合. 通过易泊车牌识别一体机抓拍识别车牌号码,将识别的车牌信息传 ...

  2. python-opencv实战:车牌识别(二):字符分割与保存

    上一篇文章内容为车牌定位,这篇文章从原理及代码角度分析如何分割字符. 文章目录 一. 分割字符的目的 二. 分割字符原理: 三. 代码 四. 代码分析 一. 分割字符的目的 定位车牌仅仅是为了找出其车 ...

  3. NVIDIA中文车牌识别系列-1” 在Jetson上用DeepStream识别中文车牌

    前言 这是NVIDIA在2021年初公布的一个开源项目,用NVIDA Jetson设备上的DeepStream视频分析套件实现"车牌识别"的功能,这是个实用性非常高的应用,能应用在 ...

  4. 车牌识别之二:字符分割

    车牌识别大概步骤可分为:车牌定位,字符分割,字符识别三个步骤. 细分点可以有以下几个步骤: (1)将图片灰度化与二值化 (2)去噪,然后切割成一个一个的字符 (3)提取每一个字符的特征,生成特征矢量或 ...

  5. 深度学习之视频人脸识别系列二:人脸检测与对齐

    作者 | 东田应子 [磐创AI导读]本文是深度学习之视频人脸识别系列的第二篇文章,介绍人脸检测与对齐的相关算法.欢迎大家关注我们的公众号:磐创AI. 一.人脸检测与关键点检测 问题描述: 人脸检测解决 ...

  6. 在ARM-Linux下实现车牌识别(二)------车牌识别

    你好!这里是风筝的博客, 欢迎和我一起交流. 之前说到,把车牌区域提前出来后,就可以着手识别程序了.先使用SVM判断是不是车牌.这里为了提高运行速度,板子资源有限,程序里我把svm训练部分注释掉了,假 ...

  7. 基于C++(QT)的车牌识别实现——二值化处理

    文章目录 拟采用的技术路线 车牌图片打开 图片二值化 窗口UI实现 拟采用的技术路线 本次设计计划以最快的速度实现一个清晰车牌的识别,后续再增加识别精确度,故采取以下技术路线本篇文章主要讲述图像二值化 ...

  8. 有关 车牌识别(二、Linux嵌入式系统代码)

    二.Linux嵌入式系统代码 参考  https://blog.csdn.net/qq_36449541/article/details/80206477 原先的开发者是在友善之臂的平台上(好像cpu ...

  9. 基于Python opencv实现车牌识别及二维码条形码识别系统 附完整源码

    完整代码:https://download.csdn.net/download/qq_38735017/87416699 原理简介 车牌字符识别使用的算法是 opencv 的 SVM opencv 的 ...

最新文章

  1. python是最好的语言 永远二十岁_Python是世界上最好的语言吗?
  2. 掌握ASP.NET技术之捷径
  3. java基础提升篇:Java 序列化的高级认识
  4. VTK:Qt之RenderWindowUISingleInheritance
  5. java怎么更改id名_java - 尽管ID已更改为_id,但列'_id'不存在
  6. mysql 命令 g_MySQL命令行的几个用法
  7. UVA 10895——Matrix Transpose
  8. shell编程之awk
  9. GCC的缺陷,由匿名对象引起的内存泄漏
  10. 考试一个程序员,1f=0.1
  11. vs2019 无法打开包括文件:“SDKDDKVer.h”: No such file or directory的另外一种解决思路
  12. 想知道电脑上怎么压缩图片?用这3个方法实现快速压缩
  13. 计算机不能正常开机怎么处理,电脑不能正常启动的原因和处理步骤
  14. 在北京租房 舒舍的租客素质怎么样?
  15. JAva继承编写自行车例子,java – Freemarker中的继承/实例检查
  16. android学习笔记之——获取SD卡及手机ROM容量
  17. 总结一下刚刚参加了今日头条的线上前端笔试
  18. csp试题1:称检测点查询
  19. 碉堡了,一个专注于效率的开源编程语言
  20. Java进阶:File类

热门文章

  1. 关于学校edu邮箱登录第三方邮件客户端(例如Outlook、Foxmail、QQ邮箱、邮件App等)的注意事项
  2. LabVIEW串口仪器控制
  3. linux的第一个内核,Linus Torvalds启动了第一个RC版本的Linux内核4.15
  4. 计算机网怎样连接网络连接不上,网络连接不上,详细教您电脑网络连接不上怎么解决...
  5. Java序列中如果有些字段不想被序列化,怎么办
  6. 天了噜!《闪耀暖暖》居然是一群男程序员做的!
  7. 小程序源码:端午送粽子祝福微信小程序源码下载支持打赏模式带背景音乐
  8. 区块链网络的价值是啥?
  9. 电脑黑屏只有鼠标箭头怎么修复 电脑开机黑屏的修复办法
  10. 关于前端会用到的一些技术栈