尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

车牌模拟生成器:Python3.8+Opencv代码实现与商业应用前景(C#、python 开发包SDK)

车牌模拟生成器:Python3.8+Opencv代码实现与商业应用前景(C#、python 开发包SDK) 车牌模拟生成器Python代码实现与商业应用前景引言在智慧城市建设和汽车行业数字化浪潮中车牌作为车辆的唯一标识其相关技术应用正变得越来越重要。今天我们将介绍一个基于Python的车牌模拟生成器探讨其技术实现、功能特点以及潜在的商业价值。【注意】在线生成随机或自定义的中国车牌支持多种车牌类型和样式仅用于模型数据测试、车牌识别系统的演示效果等切勿用于商业用途和不合法用途否则自己将承担相关责任与本工具无关。【需要的素材】1、需要各个省市的简称由于用到了opencv建议将图片和具体的车牌号做个映射关系【效果图】映射关系文件 font_mappings.txt云yunnan 京beijing 冀hebei 晋shanxi 蒙neimenggu 辽liaoning 吉jilin 黑heilongjiang 沪shanghai 苏jiangsu 浙zhejiang 皖anhui 闽fujian 赣jiangxi 鲁shandong 豫henan 鄂hubei 湘hunan 粤guangdong 桂guangxi 琼hainan 渝chongqing 川sichuan 贵guizhou 藏xizang 陕shanxi_s 甘gansu 青qinghai 宁ningxia 新xinjiang 津tianjin 港gang 澳ao 使shi 领ling 学xue 警jing 挂gua需求分析车牌模拟生成在多个领域有着广泛的应用需求软件开发与测试​智能交通系统、停车场管理系统需要大量车牌数据进行测试教育培训​驾校、交通法规培训需要示例车牌进行教学演示影视制作​影视剧中需要符合规定的虚拟车牌避免侵权问数据分析​交通流量模拟、城市规划需要车牌数据支持功能特点我们的车牌模拟生成器具备以下核心功能1. 符合中国车牌标准支持普通蓝牌和新能源绿牌两种格式遵循中国车牌编号规则排除易混淆字母(O/I)省份简称符合国家标准2. 灵活生成模式可指定生成特定类型车牌支持完全随机生成模式生成数量可自定义扩展3. 高度可定制化代码结构清晰易于扩展其他类型车牌生成规则可调整满足不同场景需求代码结构清晰易于扩展其他类型车牌由于服务端是python这里给出的是部分核心逻辑代码需要自己搭建。【核心代码实现流程参考】import random import string class LicensePlateGenerator: 车牌生成器类 def __init__(self): # 省份简称列表 self.provinces [ 京, 津, 冀, 晋, 蒙, 辽, 吉, 黑, 沪, 苏, 浙, 皖, 闽, 赣, 鲁, 豫, 鄂, 湘, 粤, 桂, 琼, 渝, 川, 贵, 云, 藏, 陕, 甘, 青, 宁, 新 ] # 车牌字母列表排除O和I self.letters [c for c in string.ascii_uppercase if c not in [O, I]] def generate_plate(self, plate_typeNone, provinceNone): 生成车牌号码 :param plate_type: 车牌类型normal普通/new_energy新能源 :param province: 指定省份简称 :return: 车牌号码字符串 # 确定省份 if province and province in self.provinces: province_char province else: province_char random.choice(self.provinces) # 确定车牌类型 if plate_type is None: plate_type random.choice([normal, new_energy]) # 生成普通车牌 if plate_type normal: return self._generate_normal_plate(province_char) # 生成新能源车牌 elif plate_type new_energy: return self._generate_new_energy_plate(province_char) def _generate_normal_plate(self, province): 生成普通蓝牌 plate province random.choice(self.letters) # 生成5位序号 for _ in range(5): if random.random() 0.3: plate random.choice(self.letters) else: plate random.choice(string.digits) return plate def _generate_new_energy_plate(self, province): 生成新能源绿牌 plate province random.choice(self.letters) plate random.choice([D, F]) # D纯电, F混动 plate .join(random.choices(string.digits, k5)) return plate # 使用示例 if __name__ __main__: generator LicensePlateGenerator() # 生成10个随机车牌 print(随机车牌示例:) for i in range(10): plate_type random.choice([normal, new_energy]) plate generator.generate_plate(plate_type) print(f{i1}. {普通车牌 if plate_type normal else 新能源车牌}: {plate}) # 生成特定省份车牌 print(\n北京车牌示例:) for i in range(3): print(f{i1}. {generator.generate_plate(normal, 京)})【生成车牌、计算数字边框等算法】# -*- coding: utf-8 -*- import numpy as np import cv2, os, argparse from glob import glob from tqdm import tqdm from plate_number import random_select, generate_plate_number_white, generate_plate_number_yellow_xue from plate_number import generate_plate_number_black_gangao, generate_plate_number_black_shi, generate_plate_number_black_ling from plate_number import generate_plate_number_blue, generate_plate_number_yellow_gua from plate_number import letters, digits # 加载中文字符到英文文件名的映射 def load_font_mappings(): mappings {} try: with open(font_mappings.txt, r, encodingutf-8) as f: for line in f: if in line: cn, en line.strip().split(, 1) mappings[cn] en except Exception as e: print(f警告: 无法加载字体映射文件错误: {e}) return mappings # 中文到英文的映射 CHINESE_TO_ENGLISH load_font_mappings() # 英文到中文的反向映射 ENGLISH_TO_CHINESE {v: k for k, v in CHINESE_TO_ENGLISH.items()} def get_location_data(length7, split_id1, height140): 获取车牌号码在底牌中的位置 length: 车牌字符数7或者87为普通车牌、8为新能源车牌 split_id: 分割空隙 height: 车牌高度对应单层和双层车牌 # 字符位置 location_xy np.zeros((length, 4), dtypenp.int32) # 单层车牌高度 if height 140: # 单层车牌y轴坐标固定 location_xy[:, 1] 25 location_xy[:, 3] 115 # 螺栓间隔 step_split 34 if length 7 else 49 # 字符间隔 step_font 12 if length 7 else 9 # 字符宽度 width_font 45 for i in range(length): if i 0: location_xy[i, 0] 15 elif i split_id: location_xy[i, 0] location_xy[i - 1, 2] step_split else: location_xy[i, 0] location_xy[i - 1, 2] step_font # 新能源车牌 if length 8 and i 0: width_font 43 location_xy[i, 2] location_xy[i, 0] width_font else: # 双层车牌第一层 location_xy[0, :] [110, 15, 190, 75] location_xy[1, :] [250, 15, 330, 75] # 第二层 width_font 65 step_font 15 for i in range(2, length): location_xy[i, 1] 90 location_xy[i, 3] 200 if i 2: location_xy[i, 0] 27 else: location_xy[i, 0] location_xy[i - 1, 2] step_font location_xy[i, 2] location_xy[i, 0] width_font return location_xy # 字符贴上底板 def copy_to_image_multi(img, font_img, bbox, bg_color, is_red): x1, y1, x2, y2 bbox font_img cv2.resize(font_img, (x2 - x1, y2 - y1)) img_crop img[y1: y2, x1: x2, :] if is_red: img_crop[font_img 200, :] [0, 0, 255] elif blue in bg_color or black in bg_color: img_crop[font_img 200, :] [255, 255, 255] else: img_crop[font_img 200, :] [0, 0, 0] return img class MultiPlateGenerator: def __init__(self, adr_plate_model, adr_font): # 车牌底板路径 self.adr_plate_model adr_plate_model # 车牌字符路径 # 如果存在英文目录则使用英文目录 self.adr_font font_model_english if os.path.exists(font_model_english) else adr_font # 车牌字符图片预存处理 self.font_imgs {} # 获取所有jpg文件 font_filenames [] for root, dirs, files in os.walk(self.adr_font): for file in files: if file.lower().endswith(.jpg): font_filenames.append(os.path.join(root, file)) for font_filename in font_filenames: # 尝试读取文件如果失败则跳过 try: font_img cv2.imread(font_filename, cv2.IMREAD_GRAYSCALE) if font_img is None: continue if 140 in font_filename: font_img cv2.resize(font_img, (45, 90)) elif 220 in font_filename: font_img cv2.resize(font_img, (65, 110)) elif font_filename.split(_)[-1].split(.)[0] in letters digits: font_img cv2.resize(font_img, (43, 90)) # 获取文件名作为key basename os.path.basename(font_filename).split(.)[0] # 保存原始文件名映射 self.font_imgs[basename] font_img # 对于英文文件名我们也建立到中文字符的映射 for en, cn in ENGLISH_TO_CHINESE.items(): if en in basename: # 构建中文文件名格式的key parts basename.split(_) for i, part in enumerate(parts): if part en: parts[i] cn chinese_key _.join(parts) self.font_imgs[chinese_key] font_img break except Exception as e: print(f警告: 无法读取或处理文件 {font_filename}, 错误: {e}) continue # 字符位置 self.location_xys {} for i in [7, 8]: for j in [1, 2, 4]: for k in [140, 220]: self.location_xys[{}_{}_{}.format(i, j, k)] \ get_location_data(lengthi, split_idj, heightk) # 获取字符位置 def get_location_multi(self, plate_number, height140): length len(plate_number) if 警 in plate_number: split_id 1 elif 使 in plate_number: split_id 4 else: split_id 2 return self.location_xys[{}_{}_{}.format(length, split_id, height)] # 随机生成车牌号码获取底板颜色、单双层 def generate_plate_number(self): rate np.random.random(1) if rate 0.4: # 蓝牌 plate_number generate_plate_number_blue(lengthrandom_select([7, 8])) else: # 白牌、黄牌教练车、黄牌挂车、黑色港澳、黑色使、领馆 generate_plate_number_funcs [generate_plate_number_white, generate_plate_number_yellow_xue, generate_plate_number_yellow_gua, generate_plate_number_black_gangao, generate_plate_number_black_shi, generate_plate_number_black_ling] plate_number random_select(generate_plate_number_funcs)() # 车牌底板颜色 bg_color random_select([blue] [yellow]) if len(plate_number) 8: bg_color random_select([green_car] * 10 [green_truck]) elif len(set(plate_number) set([使, 领, 港, 澳])) 0: bg_color black elif 警 in plate_number or plate_number[0] in letters: bg_color white elif len(set(plate_number) set([学, 挂])) 0: bg_color yellow is_double random_select([False] [True] * 3) if 使 in plate_number: bg_color black_shi if 挂 in plate_number: # 挂车双层 is_double True elif len(set(plate_number) set([使, 领, 港, 澳, 学, 警])) 0 \ or len(plate_number) 8 or bg_color blue: # 使领港澳学警、新能源、蓝色都是单层 is_double False # special首字符为字母、单层则是军车 if plate_number[0] in letters and not is_double: bg_color white_army return plate_number, bg_color, is_double # 随机生成车牌图片 def generate_plate(self, enhanceFalse): plate_number, bg_color, is_double self.generate_plate_number() height 220 if is_double else 140 # 获取底板图片 # print(plate_number, height, bg_color, is_double) number_xy self.get_location_multi(plate_number, height) # 读取底板图片确保中文文件名正确处理 plate_model_path os.path.join(self.adr_plate_model, {}_{}.PNG.format(bg_color, height)) img_plate_model cv2.imread(plate_model_path) if img_plate_model is None: print(f警告: 无法读取底板图片 {plate_model_path}) # 使用默认蓝色底板图片作为备选 default_path os.path.join(self.adr_plate_model, blue_140.PNG) img_plate_model cv2.imread(default_path) if img_plate_model is None: raise FileNotFoundError(f无法读取默认底板图片 {default_path}) img_plate_model cv2.resize(img_plate_model, (440 if len(plate_number) 7 else 480, height)) for i in range(len(plate_number)): if len(plate_number) 8: # 新能源 key green_{}.format(plate_number[i]) # 如果找不到中文key尝试使用英文key if key not in self.font_imgs: # 检查字符是否是中文字符如果是则转换为英文 char plate_number[i] if char in CHINESE_TO_ENGLISH: en_char CHINESE_TO_ENGLISH[char] key green_{}.format(en_char) font_img self.font_imgs[key] else: if {}_{}.format(height, plate_number[i]) in self.font_imgs: key {}_{}.format(height, plate_number[i]) # 如果找不到中文key尝试使用英文key if key not in self.font_imgs: # 检查字符是否是中文字符如果是则转换为英文 char plate_number[i] if char in CHINESE_TO_ENGLISH: en_char CHINESE_TO_ENGLISH[char] key {}_{}.format(height, en_char) font_img self.font_imgs[key] else: # 双层车牌字体库 if i 2: key 220_up_{}.format(plate_number[i]) # 如果找不到中文key尝试使用英文key if key not in self.font_imgs: # 检查字符是否是中文字符如果是则转换为英文 char plate_number[i] if char in CHINESE_TO_ENGLISH: en_char CHINESE_TO_ENGLISH[char] key 220_up_{}.format(en_char) font_img self.font_imgs[key] else: key 220_down_{}.format(plate_number[i]) # 如果找不到中文key尝试使用英文key if key not in self.font_imgs: # 检查字符是否是中文字符如果是则转换为英文 char plate_number[i] if char in CHINESE_TO_ENGLISH: en_char CHINESE_TO_ENGLISH[char] key 220_down_{}.format(en_char) font_img self.font_imgs[key] # 字符是否红色 if (i 0 and plate_number[0] in letters) or plate_number[i] in [警, 使, 领]: is_red True elif i 1 and plate_number[0] in letters and np.random.random(1) 0.5: # second letter of army plate is_red True else: is_red False if enhance: k np.random.randint(1, 6) kernel np.ones((k, k), np.uint8) if np.random.random(1) 0.5: font_img np.copy(cv2.erode(font_img, kernel, iterations1)) else: font_img np.copy(cv2.dilate(font_img, kernel, iterations1)) # 贴上底板 img_plate_model copy_to_image_multi(img_plate_model, font_img, number_xy[i, :], bg_color, is_red) img_plate_model cv2.blur(img_plate_model, (3, 3)) return img_plate_model, number_xy, plate_number, bg_color, is_double def generate_plate_special(self, plate_number, bg_color, is_double, enhanceFalse): 生成特定号码、颜色车牌 :param plate_number: 车牌号码 :param bg_color: 背景颜色black/black_shi使领馆/blue/green_car新能源轿车/green_truck新能源卡车/white/white_army军队/yellow :param is_double: 是否双层 :param enhance: 图像增强 :return: 车牌图 height 220 if is_double else 140 # print(plate_number, height, bg_color, is_double) number_xy self.get_location_multi(plate_number, height) img_plate_model cv2.imread(os.path.join(self.adr_plate_model, {}_{}.PNG.format(bg_color, height))) img_plate_model cv2.resize(img_plate_model, (440 if len(plate_number) 7 else 480, height)) for i in range(len(plate_number)): if len(plate_number) 8: # 新能源 key green_{}.format(plate_number[i]) # 如果找不到中文key尝试使用英文key if key not in self.font_imgs: # 检查字符是否是中文字符如果是则转换为英文 char plate_number[i] if char in CHINESE_TO_ENGLISH: en_char CHINESE_TO_ENGLISH[char] key green_{}.format(en_char) font_img self.font_imgs[key] else: if {}_{}.format(height, plate_number[i]) in self.font_imgs: key {}_{}.format(height, plate_number[i]) # 如果找不到中文key尝试使用英文key if key not in self.font_imgs: # 检查字符是否是中文字符如果是则转换为英文 char plate_number[i] if char in CHINESE_TO_ENGLISH: en_char CHINESE_TO_ENGLISH[char] key {}_{}.format(height, en_char) font_img self.font_imgs[key] else: if i 2: key 220_up_{}.format(plate_number[i]) # 如果找不到中文key尝试使用英文key if key not in self.font_imgs: # 检查字符是否是中文字符如果是则转换为英文 char plate_number[i] if char in CHINESE_TO_ENGLISH: en_char CHINESE_TO_ENGLISH[char] key 220_up_{}.format(en_char) font_img self.font_imgs[key] else: key 220_down_{}.format(plate_number[i]) # 如果找不到中文key尝试使用英文key if key not in self.font_imgs: # 检查字符是否是中文字符如果是则转换为英文 char plate_number[i] if char in CHINESE_TO_ENGLISH: en_char CHINESE_TO_ENGLISH[char] key 220_down_{}.format(en_char) font_img self.font_imgs[key] if (i 0 and plate_number[0] in letters) or plate_number[i] in [警, 使, 领]: is_red True elif i 1 and plate_number[0] in letters and np.random.random(1) 0.5: # second letter of army plate is_red True else: is_red False if enhance: k np.random.randint(1, 6) kernel np.ones((k, k), np.uint8) if np.random.random(1) 0.5: font_img np.copy(cv2.erode(font_img, kernel, iterations1)) else: font_img np.copy(cv2.dilate(font_img, kernel, iterations1)) img_plate_model copy_to_image_multi(img_plate_model, font_img, number_xy[i, :], bg_color, is_red) # is_double double if is_double else single img_plate_model cv2.blur(img_plate_model, (3, 3)) return img_plate_model def parse_args(): parser argparse.ArgumentParser(description中国车牌生成器) parser.add_argument(--number, default10, typeint, help生成车牌数量) parser.add_argument(--save-adr, defaultmulti_val, help车牌保存路径) args parser.parse_args() return args def mkdir(path): try: os.makedirs(path) except: pass if __name__ __main__: args parse_args() print(args) # 随机生成车牌 print(save in {}.format(args.save_adr)) mkdir(args.save_adr) generator MultiPlateGenerator(plate_model, font_model) for i in tqdm(range(args.number)): img, number_xy, gt_plate_number, bg_color, is_double generator.generate_plate() # 使用cv2.imencode和open函数来正确处理中文文件名 save_path os.path.join(args.save_adr, {}_{}_{}.jpg.format(gt_plate_number, bg_color, is_double)) try: # 将图像编码为JPEG格式 success, encoded_img cv2.imencode(.jpg, img) if success: # 使用open函数以二进制写入模式保存文件 with open(save_path, wb) as f: f.write(encoded_img.tobytes()) else: print(f警告: 无法编码图像 {save_path}) except Exception as e: print(f警告: 无法保存图像 {save_path}, 错误: {e})商业应用前景1. 软件开发服务为智能交通系统提供测试数据生成服务向停车场管理系统开发商提供车牌模拟解决方案为驾考系统提供虚拟车牌生成功能2. 数据服务业务向研究机构提供交通模拟数据为城市规划部门提供车辆流量预测数据支持向广告公司提供区域车辆分布分析数据3. 教育培训应用开发交通法规教学工具为驾校提供理论考试模拟系统制作交通安全教育材料4. 增值服务扩展添加车牌识别验证功能开发车牌样式自定义功能增加多国车牌生成支持技术拓展方向1、增加图像生成功能​将车牌文本转换为真实车牌图像​2、添加验证算法​验证生成的车牌是否符合编码规则3、支持更多车牌类型​扩展至武警车牌、领事馆车牌等特殊类型4、​开发API接口​提供Web服务供第三方调用车牌模拟生成器虽是一个小型工具但其应用场景广泛商业价值可观。【最后注意】在线生成随机或自定义的中国车牌支持多种车牌类型和样式仅用于模型数据测试、演示效果等切勿用于商业用途和不合法用途否则自己将承担相关责任与本工具无关。工具截图可以自己开发一个提供下载地址通过网盘分享的文件网盘中是编译好的可以运行的exe车牌模拟生成demo链接: https://pan.baidu.com/s/1WBzzd3qNpD8m837wqfgVBA?pwdtgp4 提取码: tgp4生成的蓝牌、绿牌、黑、白、黄牌如下模拟生成效果感谢您的阅读和支持欢迎点赞拍砖
返回列表