摘要在车牌检测与识别任务中CCPDChinese City Parking Dataset是国内最常用、最具代表性的公开数据集之一。它既可以用于车牌检测也可以用于车牌字符识别甚至可以进一步支撑端到端车牌识别系统的训练与评估。CCPD 的一个显著特点是大量标注信息被直接编码在图片文件名中这使得数据预处理流程与常规的 XML/JSON 标注数据集有明显不同。官方仓库将 CCPD 描述为面向车牌检测与识别的大规模数据集并说明了文件名中的字段含义与评价方式。本文将从数据集本身出发系统介绍 CCPD 2019 与 2020 的特点并结合一份完整的 Python 脚本详细说明如何将原始 CCPD 数据转换为两类更便于训练的工程数据YOLO 检测数据 与 OCR 识别数据。这种“双路线输出”的处理方式适合同时建设车牌检测与车牌识别两个模块也适合作为后续端到端系统的基础数据准备方案。CCPD 数据集简介1.1 CCPD 是什么CCPD全称 Chinese City Parking Dataset最初由 ECCV 2018 相关工作公开用于支持车牌检测与识别任务的研究。官方仓库明确说明该数据集用于 license plate detection and recognition并配有论文、基线代码以及测试说明。与很多常见视觉数据集不同CCPD 的标注并不主要依赖单独的标注文件而是把如下信息嵌入到了图片文件名中车牌在整张图中的面积占比水平与垂直倾斜角外接框坐标四个角点坐标车牌字符索引亮度信息模糊度信息这意味着只要掌握了 CCPD 文件名规则就可以从图片本身恢复出检测与识别所需的大部分监督信息。官方 README 和 MindOCR 的数据文档都明确提到CCPD 的注释信息嵌在文件名中1.2 CCPD 2019 的特点CCPD 官方仓库在 2019 年 3 月更新说明中提到数据集在该版本进行了更新整体规模超过 30 万张图像同时标注更加精细、子集难度更高。官方还说明CCPD-Base 主要用于 train/val 划分而 DB、Blur、FN、Rotate、Tilt、Challenge 等子集主要被用作测试集。从工程角度看CCPD 2019 适合用于以下任务普通蓝牌车牌检测普通蓝牌车牌 OCR 识别检测识别联合实验模糊、倾斜、旋转等困难场景鲁棒性评估MindOCR 的文档中也给出了 CCPD 2019 的目录结构示例说明其通常由多个子目录构成例如 ccpd_base、ccpd_blur 等同时配有 splits 目录用于训练/验证/测试划分。2. CCPD 文件名规则解析2.1 文件名格式概览官方 README 给出了一个典型 CCPD 图片文件名示例并指出该名称可被拆分为 7 个字段每个字段对应一种标注信息。典型格式如下area-tilt-bbox-vertices-plate-brightness-blur.jpg也就是说一张图片的文件名中通常包含车牌面积占整图比例水平与垂直倾斜度外接框左上与右下坐标四个角点坐标车牌字符索引亮度模糊度对于绝大多数训练与转换任务最关键的是第 4 段和第 5 段第 4 段四点坐标用于检测标注和透视裁剪第 5 段字符索引用于恢复真实车牌号2.2 字符索引的含义CCPD 并不是直接把 浙A12345 这样的文本写进文件名而是使用索引编码。官方 README 给出了三组关键字符表provincesalphabetsads并说明车牌由 省份简称 字母 5 位字母数字 构成最后一个字符 O 是字母 O不是数字 0。本文数据处理脚本的目标这份脚本的设计目标非常明确将原始 CCPD 数据一次转换为两套训练数据。第一套是 YOLO4 检测数据用于训练车牌定位模型第二套是 OCR 识别数据用于训练车牌文本识别模型。也就是说脚本不是只为一个任务服务而是同时满足检测模型的数据需求OCR 模型的数据需求代码整体结构说明脚本主要由以下几个部分组成字符映射表定义车牌字符解码函数四点坐标解析与排序函数透视矫正函数YOLO 标注生成函数单张图片处理函数整个子集的批量处理函数YAML 配置写入函数主入口函数下面逐一分析这些模块的作用。5. 字符映射表设计脚本最开始定义了三组数组PROVINCES ALPHABETS ADS它们分别用于恢复车牌不同位置的字符5.1 PROVINCES该数组表示车牌的首字符即省份简称例如皖沪津渝京粤新还额外包含了 警、学 和 O其中 O 作为异常或占位场景下的兜底字符。5.2 ALPHABETS该数组表示车牌第 2 位的大写字母通常不包含 I 和 O而是包含 A-Z 中车牌规则允许的字母集合。5.3 ADS该数组表示车牌后续位置可能出现的字符包含大写字母数字O它覆盖了车牌后五位中可能出现的所有符号。6. 车牌文本恢复decode_plate函数defdecode_plate(plate_idx_str):nums[int(x)forxinplate_idx_str.split(_)]iflen(nums)2:returnplate[]p0nums[0]plate.append(PROVINCES[p0]if0p0len(PROVINCES)elseO)p1nums[1]plate.append(ALPHABETS[p1]if0p1len(ALPHABETS)elseO)forxinnums[2:]:plate.append(ADS[x]if0xlen(ADS)elseO)return.join(plate)这个函数负责把 CCPD 文件名中的“索引串”恢复成真正的车牌文本。例如一个文件名片段可能包含这样的编码0_0_22_27_27_33_16它并不是可读的车牌号而是一串整数索引。函数的处理逻辑是1.第一个数字从 PROVINCES 中取值2.第二个数字从 ALPHABETS 中取值3.后续数字从 ADS 中取值拼接成最终字符串输出结果最终可能变成皖A12345这是 OCR 标签生成的前提也是后续识别任务的监督信号来源。7. 角点解析parse_vertices函数defparse_vertices(vertices_str):pts[]foriteminvertices_str.split(_):x,ymap(int,item.split())pts.append([x,y])returnpts它负责把文件名中的四点坐标字符串解析成点集。CCPD 文件名中的四点通常写成x1y1_x2y2_x3y3_x4y4经过解析后会得到[[x1,y1],[x2,y2],[x3,y3],[x4,y4]]这组点数据后续有两个核心用途生成检测标注进行透视矫正8. 四点排序order_points四点透视变换之前最重要的一步就是统一点的顺序。函数deforder_points(pts):ptsnp.array(pts,dtypenp.float32)spts.sum(axis1)diffnp.diff(pts,axis1)tlpts[np.argmin(s)]brpts[np.argmax(s)]trpts[np.argmin(diff)]blpts[np.argmax(diff)]returnnp.array([tl,tr,br,bl],dtypenp.float32)通过点坐标的和与差来推断四个顶点的位置并统一排列为左上 tl右上 tr右下 br左下 bl这样做的目的是为了避免点顺序混乱导致透视矩阵计算错误。这个函数虽然短但实际上非常关键因为车牌透视矫正的质量在很大程度上取决于这一步是否正确。9. 透视裁剪four_point_transform函数deffour_point_transform(image,pts):rectorder_points(pts)(tl,tr,br,bl)rect widthAnp.linalg.norm(br-bl)widthBnp.linalg.norm(tr-tl)maxWidthmax(int(widthA),int(widthB),1)heightAnp.linalg.norm(tr-br)heightBnp.linalg.norm(tl-bl)maxHeightmax(int(heightA),int(heightB),1)dstnp.array([[0,0],[maxWidth-1,0],[maxWidth-1,maxHeight-1],[0,maxHeight-1]],dtypenp.float32)Mcv2.getPerspectiveTransform(rect,dst)warpedcv2.warpPerspective(image,M,(maxWidth,maxHeight))returnwarped其作用是把原图中的斜车牌、透视变形车牌拉正为相对规整的车牌小图。处理逻辑是1.对四点排序2.根据四点估算目标宽高3.构造目标矩形4.计算透视变换矩阵使用 cv2.warpPerspective 生成校正后的车牌图这一步直接决定了 OCR 数据的质量。为什么必须做透视矫正因为车牌在真实场景中常常存在水平倾斜垂直倾斜近大远小侧拍透视如果直接裁切外接框而不校正角点OCR 识别模型会承担更多几何畸变压力。相反提前把车牌拉正有助于模型更专注于字符本身。10. 生成 YOLO 多边形标注polygon_label_from_points函数defpolygon_label_from_points(pts,img_w,img_h,cls_id0):rectorder_points(pts)vals[str(cls_id)]forx,yinrect:xnmin(max(x/img_w,0.0),1.0)ynmin(max(y/img_h,0.0),1.0)vals.append(f{xn:.6f})vals.append(f{yn:.6f})return .join(vals)这个函数的作用是把四点坐标转换成适合检测模型训练的标签格式。具体做法是对四点排序根据图像宽高进行归一化输出一行多边形标注数据输出格式为class_id x1 y1 x2 y2 x3 y3 x4 y4图片收集collect_images函数defcollect_images(folder):files[]forextin[*.jpg,*.jpeg,*.png,*.bmp]:files.extend(glob.glob(os.path.join(folder,ext)))returnfiles它会扫描目录下常见图像扩展名jpgjpegpngbmp这样做的好处是兼容不同来源、不同扩展名的数据而不是只依赖某一种固定后缀。12. 单张图片的完整处理流程process_one_image整个脚本最核心的部分是defprocess_one_image(img_path,split_name,output_dir,ocr_list_file):img_namePath(img_path).name stemPath(img_path).stem# CCPD 文件名:# area-tilt-bbox-vertices-plate-brightness-blur.jpgpartsstem.split(-)iflen(parts)5:print(f[WARN] 文件名不符合 CCPD 规则跳过:{img_path})returnvertices_strparts[3]plate_idx_strparts[4]try:ptsparse_vertices(vertices_str)plate_textdecode_plate(plate_idx_str)exceptExceptionase:print(f[WARN] 解析失败跳过:{img_path}, err{e})returnimgcv2.imread(img_path)ifimgisNone:print(f[WARN] 读取失败:{img_path})returnh,wimg.shape[:2]# YOLO4yolo_img_diros.path.join(output_dir,yolo4,images,split_name)yolo_lab_diros.path.join(output_dir,yolo4,labels,split_name)ensure_dir(yolo_img_dir)ensure_dir(yolo_lab_dir)dst_img_pathos.path.join(yolo_img_dir,img_name)dst_lab_pathos.path.join(yolo_lab_dir,stem.txt)shutil.copy2(img_path,dst_img_path)yolo_linepolygon_label_from_points(pts,w,h,cls_id0)withopen(dst_lab_path,w,encodingutf-8)asf:f.write(yolo_line\n)# OCRocr_img_diros.path.join(output_dir,ocr,images,split_name)ocr_lab_diros.path.join(output_dir,ocr,labels,split_name)ensure_dir(ocr_img_dir)ensure_dir(ocr_lab_dir)ocr_img_pathos.path.join(ocr_img_dir,stem.jpg)ocr_lab_pathos.path.join(ocr_lab_dir,stem.txt)try:cropfour_point_transform(img,pts)exceptExceptionase:print(f[WARN] 透视裁切失败跳过OCR:{img_path}, err{e})cropNoneifcropisnotNoneandcrop.size0:cv2.imwrite(ocr_img_path,crop)withopen(ocr_lab_path,w,encodingutf-8)asf:f.write(plate_text\n)ocr_list_file.write(f{os.path.abspath(ocr_img_path)}\t{plate_text}\n)else:print(f[WARN] OCR crop为空:{img_path})13.主函数defmain():root_dirK:/CCPD2020/CCPD2019output_dirK:/CCPD2020/output_ccpd2019split_dirs{ccpd_base:os.path.join(root_dir,ccpd_base),}forsplit_name,src_dirinsplit_dirs.items():ifnotos.path.isdir(src_dir):print(f[ERROR] 目录不存在:{src_dir})returnprocess_split(ccpd_base,split_dirs[ccpd_base],output_dir)# process_split(val, split_dirs[val], output_dir)# process_split(test, split_dirs[test], output_dir)write_yaml(output_dir)print([INFO] 全部转换完成)print(f[INFO] YOLO4 数据:{os.path.join(output_dir,yolo4)})print(f[INFO] OCR 数据:{os.path.join(output_dir,ocr)})我这里只处理了ccpd_base数据集。如果后续希望处理更多子集例如ccpd_blurccpd_rotateccpd_tiltccpd_challenge只需要在 split_dirs 中继续补充对应目录即可。14.总结我这里用了车牌的四点左边来训练数据因为我觉得四点的效果在倾斜数据上更好一点。完整代码工程https://download.csdn.net/download/weixin_45776000/92749315如果想自己训练处理数据ccpd数据集链接: https://pan.baidu.com/s/1dh-8L544DTglReIFH3rtiQ?pwdhfhy 提取码: hfhy里面有ccpd原始数据和我自己处理好的整合过的ocr数据集(ccpd_base)
CCPD 2019 / CCPD 2020 数据集简介与工程化处理实践
摘要在车牌检测与识别任务中CCPDChinese City Parking Dataset是国内最常用、最具代表性的公开数据集之一。它既可以用于车牌检测也可以用于车牌字符识别甚至可以进一步支撑端到端车牌识别系统的训练与评估。CCPD 的一个显著特点是大量标注信息被直接编码在图片文件名中这使得数据预处理流程与常规的 XML/JSON 标注数据集有明显不同。官方仓库将 CCPD 描述为面向车牌检测与识别的大规模数据集并说明了文件名中的字段含义与评价方式。本文将从数据集本身出发系统介绍 CCPD 2019 与 2020 的特点并结合一份完整的 Python 脚本详细说明如何将原始 CCPD 数据转换为两类更便于训练的工程数据YOLO 检测数据 与 OCR 识别数据。这种“双路线输出”的处理方式适合同时建设车牌检测与车牌识别两个模块也适合作为后续端到端系统的基础数据准备方案。CCPD 数据集简介1.1 CCPD 是什么CCPD全称 Chinese City Parking Dataset最初由 ECCV 2018 相关工作公开用于支持车牌检测与识别任务的研究。官方仓库明确说明该数据集用于 license plate detection and recognition并配有论文、基线代码以及测试说明。与很多常见视觉数据集不同CCPD 的标注并不主要依赖单独的标注文件而是把如下信息嵌入到了图片文件名中车牌在整张图中的面积占比水平与垂直倾斜角外接框坐标四个角点坐标车牌字符索引亮度信息模糊度信息这意味着只要掌握了 CCPD 文件名规则就可以从图片本身恢复出检测与识别所需的大部分监督信息。官方 README 和 MindOCR 的数据文档都明确提到CCPD 的注释信息嵌在文件名中1.2 CCPD 2019 的特点CCPD 官方仓库在 2019 年 3 月更新说明中提到数据集在该版本进行了更新整体规模超过 30 万张图像同时标注更加精细、子集难度更高。官方还说明CCPD-Base 主要用于 train/val 划分而 DB、Blur、FN、Rotate、Tilt、Challenge 等子集主要被用作测试集。从工程角度看CCPD 2019 适合用于以下任务普通蓝牌车牌检测普通蓝牌车牌 OCR 识别检测识别联合实验模糊、倾斜、旋转等困难场景鲁棒性评估MindOCR 的文档中也给出了 CCPD 2019 的目录结构示例说明其通常由多个子目录构成例如 ccpd_base、ccpd_blur 等同时配有 splits 目录用于训练/验证/测试划分。2. CCPD 文件名规则解析2.1 文件名格式概览官方 README 给出了一个典型 CCPD 图片文件名示例并指出该名称可被拆分为 7 个字段每个字段对应一种标注信息。典型格式如下area-tilt-bbox-vertices-plate-brightness-blur.jpg也就是说一张图片的文件名中通常包含车牌面积占整图比例水平与垂直倾斜度外接框左上与右下坐标四个角点坐标车牌字符索引亮度模糊度对于绝大多数训练与转换任务最关键的是第 4 段和第 5 段第 4 段四点坐标用于检测标注和透视裁剪第 5 段字符索引用于恢复真实车牌号2.2 字符索引的含义CCPD 并不是直接把 浙A12345 这样的文本写进文件名而是使用索引编码。官方 README 给出了三组关键字符表provincesalphabetsads并说明车牌由 省份简称 字母 5 位字母数字 构成最后一个字符 O 是字母 O不是数字 0。本文数据处理脚本的目标这份脚本的设计目标非常明确将原始 CCPD 数据一次转换为两套训练数据。第一套是 YOLO4 检测数据用于训练车牌定位模型第二套是 OCR 识别数据用于训练车牌文本识别模型。也就是说脚本不是只为一个任务服务而是同时满足检测模型的数据需求OCR 模型的数据需求代码整体结构说明脚本主要由以下几个部分组成字符映射表定义车牌字符解码函数四点坐标解析与排序函数透视矫正函数YOLO 标注生成函数单张图片处理函数整个子集的批量处理函数YAML 配置写入函数主入口函数下面逐一分析这些模块的作用。5. 字符映射表设计脚本最开始定义了三组数组PROVINCES ALPHABETS ADS它们分别用于恢复车牌不同位置的字符5.1 PROVINCES该数组表示车牌的首字符即省份简称例如皖沪津渝京粤新还额外包含了 警、学 和 O其中 O 作为异常或占位场景下的兜底字符。5.2 ALPHABETS该数组表示车牌第 2 位的大写字母通常不包含 I 和 O而是包含 A-Z 中车牌规则允许的字母集合。5.3 ADS该数组表示车牌后续位置可能出现的字符包含大写字母数字O它覆盖了车牌后五位中可能出现的所有符号。6. 车牌文本恢复decode_plate函数defdecode_plate(plate_idx_str):nums[int(x)forxinplate_idx_str.split(_)]iflen(nums)2:returnplate[]p0nums[0]plate.append(PROVINCES[p0]if0p0len(PROVINCES)elseO)p1nums[1]plate.append(ALPHABETS[p1]if0p1len(ALPHABETS)elseO)forxinnums[2:]:plate.append(ADS[x]if0xlen(ADS)elseO)return.join(plate)这个函数负责把 CCPD 文件名中的“索引串”恢复成真正的车牌文本。例如一个文件名片段可能包含这样的编码0_0_22_27_27_33_16它并不是可读的车牌号而是一串整数索引。函数的处理逻辑是1.第一个数字从 PROVINCES 中取值2.第二个数字从 ALPHABETS 中取值3.后续数字从 ADS 中取值拼接成最终字符串输出结果最终可能变成皖A12345这是 OCR 标签生成的前提也是后续识别任务的监督信号来源。7. 角点解析parse_vertices函数defparse_vertices(vertices_str):pts[]foriteminvertices_str.split(_):x,ymap(int,item.split())pts.append([x,y])returnpts它负责把文件名中的四点坐标字符串解析成点集。CCPD 文件名中的四点通常写成x1y1_x2y2_x3y3_x4y4经过解析后会得到[[x1,y1],[x2,y2],[x3,y3],[x4,y4]]这组点数据后续有两个核心用途生成检测标注进行透视矫正8. 四点排序order_points四点透视变换之前最重要的一步就是统一点的顺序。函数deforder_points(pts):ptsnp.array(pts,dtypenp.float32)spts.sum(axis1)diffnp.diff(pts,axis1)tlpts[np.argmin(s)]brpts[np.argmax(s)]trpts[np.argmin(diff)]blpts[np.argmax(diff)]returnnp.array([tl,tr,br,bl],dtypenp.float32)通过点坐标的和与差来推断四个顶点的位置并统一排列为左上 tl右上 tr右下 br左下 bl这样做的目的是为了避免点顺序混乱导致透视矩阵计算错误。这个函数虽然短但实际上非常关键因为车牌透视矫正的质量在很大程度上取决于这一步是否正确。9. 透视裁剪four_point_transform函数deffour_point_transform(image,pts):rectorder_points(pts)(tl,tr,br,bl)rect widthAnp.linalg.norm(br-bl)widthBnp.linalg.norm(tr-tl)maxWidthmax(int(widthA),int(widthB),1)heightAnp.linalg.norm(tr-br)heightBnp.linalg.norm(tl-bl)maxHeightmax(int(heightA),int(heightB),1)dstnp.array([[0,0],[maxWidth-1,0],[maxWidth-1,maxHeight-1],[0,maxHeight-1]],dtypenp.float32)Mcv2.getPerspectiveTransform(rect,dst)warpedcv2.warpPerspective(image,M,(maxWidth,maxHeight))returnwarped其作用是把原图中的斜车牌、透视变形车牌拉正为相对规整的车牌小图。处理逻辑是1.对四点排序2.根据四点估算目标宽高3.构造目标矩形4.计算透视变换矩阵使用 cv2.warpPerspective 生成校正后的车牌图这一步直接决定了 OCR 数据的质量。为什么必须做透视矫正因为车牌在真实场景中常常存在水平倾斜垂直倾斜近大远小侧拍透视如果直接裁切外接框而不校正角点OCR 识别模型会承担更多几何畸变压力。相反提前把车牌拉正有助于模型更专注于字符本身。10. 生成 YOLO 多边形标注polygon_label_from_points函数defpolygon_label_from_points(pts,img_w,img_h,cls_id0):rectorder_points(pts)vals[str(cls_id)]forx,yinrect:xnmin(max(x/img_w,0.0),1.0)ynmin(max(y/img_h,0.0),1.0)vals.append(f{xn:.6f})vals.append(f{yn:.6f})return .join(vals)这个函数的作用是把四点坐标转换成适合检测模型训练的标签格式。具体做法是对四点排序根据图像宽高进行归一化输出一行多边形标注数据输出格式为class_id x1 y1 x2 y2 x3 y3 x4 y4图片收集collect_images函数defcollect_images(folder):files[]forextin[*.jpg,*.jpeg,*.png,*.bmp]:files.extend(glob.glob(os.path.join(folder,ext)))returnfiles它会扫描目录下常见图像扩展名jpgjpegpngbmp这样做的好处是兼容不同来源、不同扩展名的数据而不是只依赖某一种固定后缀。12. 单张图片的完整处理流程process_one_image整个脚本最核心的部分是defprocess_one_image(img_path,split_name,output_dir,ocr_list_file):img_namePath(img_path).name stemPath(img_path).stem# CCPD 文件名:# area-tilt-bbox-vertices-plate-brightness-blur.jpgpartsstem.split(-)iflen(parts)5:print(f[WARN] 文件名不符合 CCPD 规则跳过:{img_path})returnvertices_strparts[3]plate_idx_strparts[4]try:ptsparse_vertices(vertices_str)plate_textdecode_plate(plate_idx_str)exceptExceptionase:print(f[WARN] 解析失败跳过:{img_path}, err{e})returnimgcv2.imread(img_path)ifimgisNone:print(f[WARN] 读取失败:{img_path})returnh,wimg.shape[:2]# YOLO4yolo_img_diros.path.join(output_dir,yolo4,images,split_name)yolo_lab_diros.path.join(output_dir,yolo4,labels,split_name)ensure_dir(yolo_img_dir)ensure_dir(yolo_lab_dir)dst_img_pathos.path.join(yolo_img_dir,img_name)dst_lab_pathos.path.join(yolo_lab_dir,stem.txt)shutil.copy2(img_path,dst_img_path)yolo_linepolygon_label_from_points(pts,w,h,cls_id0)withopen(dst_lab_path,w,encodingutf-8)asf:f.write(yolo_line\n)# OCRocr_img_diros.path.join(output_dir,ocr,images,split_name)ocr_lab_diros.path.join(output_dir,ocr,labels,split_name)ensure_dir(ocr_img_dir)ensure_dir(ocr_lab_dir)ocr_img_pathos.path.join(ocr_img_dir,stem.jpg)ocr_lab_pathos.path.join(ocr_lab_dir,stem.txt)try:cropfour_point_transform(img,pts)exceptExceptionase:print(f[WARN] 透视裁切失败跳过OCR:{img_path}, err{e})cropNoneifcropisnotNoneandcrop.size0:cv2.imwrite(ocr_img_path,crop)withopen(ocr_lab_path,w,encodingutf-8)asf:f.write(plate_text\n)ocr_list_file.write(f{os.path.abspath(ocr_img_path)}\t{plate_text}\n)else:print(f[WARN] OCR crop为空:{img_path})13.主函数defmain():root_dirK:/CCPD2020/CCPD2019output_dirK:/CCPD2020/output_ccpd2019split_dirs{ccpd_base:os.path.join(root_dir,ccpd_base),}forsplit_name,src_dirinsplit_dirs.items():ifnotos.path.isdir(src_dir):print(f[ERROR] 目录不存在:{src_dir})returnprocess_split(ccpd_base,split_dirs[ccpd_base],output_dir)# process_split(val, split_dirs[val], output_dir)# process_split(test, split_dirs[test], output_dir)write_yaml(output_dir)print([INFO] 全部转换完成)print(f[INFO] YOLO4 数据:{os.path.join(output_dir,yolo4)})print(f[INFO] OCR 数据:{os.path.join(output_dir,ocr)})我这里只处理了ccpd_base数据集。如果后续希望处理更多子集例如ccpd_blurccpd_rotateccpd_tiltccpd_challenge只需要在 split_dirs 中继续补充对应目录即可。14.总结我这里用了车牌的四点左边来训练数据因为我觉得四点的效果在倾斜数据上更好一点。完整代码工程https://download.csdn.net/download/weixin_45776000/92749315如果想自己训练处理数据ccpd数据集链接: https://pan.baidu.com/s/1dh-8L544DTglReIFH3rtiQ?pwdhfhy 提取码: hfhy里面有ccpd原始数据和我自己处理好的整合过的ocr数据集(ccpd_base)