在实际应用中,车牌号的识别(OCR)是一个非常重要的需求,尤其是在停车场管理、道路监控等场景中。本文将介绍如何在CentOS环境下,通过Docker容器,基于PaddleOCR来实现车牌号的识别。具体内容包括构建Docker镜像的步骤、相关依赖安装、Python脚本实现,以及如何运行整个车牌识别流程。
一、环境准备
我们采用CentOS作为宿主机操作系统,利用Docker容器来构建Python车牌OCR识别环境。容器化可以有效简化环境配置,避免依赖冲突。
1.1 安装Docker
首先,确保宿主机已经安装了Docker。若尚未安装,可以通过以下命令安装:
bash
yum update -y
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io -y
systemctl start docker
systemctl enable docker
1.2 编写Dockerfile
为了简化依赖的安装,我们基于Ubuntu 22.04
来构建镜像。下面是Dockerfile的内容:
Dockerfile
# 使用 Ubuntu 22.04 作为基础镜像
FROM ubuntu:22.04
# 设置时区为上海
ENV TZ=Asia/Shanghai
RUN apt-get update && apt-get install -y tzdata && \
ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata
# 安装 Python3 和所需的依赖
RUN apt-get update && \
apt-get install -y \
python3 \
python3-pip \
python3-opencv \
libglib2.0-0 \
git && \
rm -rf /var/lib/apt/lists/*
# 升级 pip
RUN pip3 install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/
# 安装 paddleocr、paddlepaddle 和 matplotlib
RUN pip3 install paddleocr paddlepaddle matplotlib -i https://mirrors.aliyun.com/pypi/simple/
# 设置工作目录
WORKDIR /app
# 复制当前目录到容器的 /app 目录
COPY . /app
此Dockerfile基于Ubuntu 22.04
,并安装了Python3、PaddleOCR、PaddlePaddle和OpenCV等依赖。这些依赖都是车牌识别所必需的,安装过程中我们使用了阿里云的镜像源来加快速度。
二、车牌OCR识别Python脚本
接下来,我们编写车牌OCR识别的Python脚本。核心流程包括图像的预处理、车牌区域提取、PaddleOCR模型的加载与识别。
2.1 车牌识别核心代码
python
# -*- coding: utf-8 -*-
import cv2
from paddleocr import PaddleOCR
import os
from matplotlib import pyplot as plt
import argparse
import logging
import matplotlib
# 使用 Agg 后端用于无显示的情况
matplotlib.use('Agg')
# 设置日志记录
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def Morph_Distinguish(img):
""" 使用形态学操作提取车牌区域 """
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
# 图像增强:对比度增强和边缘检测
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (17, 17))
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, kernel)
# Sobel算子进行边缘提取
y = cv2.Sobel(tophat, cv2.CV_16S, 1, 0)
absY = cv2.convertScaleAbs(y)
# 自适应阈值处理
ret, binary = cv2.threshold(absY, 75, 255, cv2.THRESH_BINARY)
# 形态学操作(开闭操作去噪)
kernel_open = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 15))
opened = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel_open)
kernel_close = cv2.getStructuringElement(cv2.MORPH_RECT, (41, 15))
closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel_close)
# 水平和垂直膨胀与腐蚀操作
kernel_x = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 7))
kernel_y = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 11))
dilate_x = cv2.dilate(closed, kernel_x)
erode_y = cv2.erode(dilate_x, kernel_y)
# 继续形态学操作以突出车牌
kernel_plate = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 9))
plate_area = cv2.dilate(erode_y, kernel_plate)
# 提取轮廓
contours, _ = cv2.findContours(plate_area, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
img_copy = img.copy()
cv2.drawContours(img_copy, contours, -1, (255, 0, 255), 2)
# 遍历找到可能的车牌区域
for contour in contours:
area = cv2.contourArea(contour)
x, y, w, h = cv2.boundingRect(contour)
# 车牌宽高比范围和面积阈值调整
if h * 2 < w < h * 6 and area > 1500:
ROI = img[y:y + h, x:x + w]
logging.info(f"找到车牌区域,位置: x={x}, y={y}, w={w}, h={h}")
return ROI
logging.warning("未能提取到车牌区域")
return None
def main(image_path):
""" 主函数:读取图像、预处理、OCR识别 """
# PaddleOCR初始化
ocr = PaddleOCR(use_angle_cls=False, use_gpu=False, lang="ch", show_log=False)
# 读取图片
img = cv2.imread(image_path)
if img is None:
logging.error(f"无法读取图片: {image_path}")
return
# 调整图像尺寸
img_resized = cv2.resize(img, (int(img.shape[1] * 0.5), int(img.shape[0] * 0.5)))
# 获取车牌区域
plate_img = Morph_Distinguish(img_resized)
if plate_img is None:
logging.error("没有提取到车牌区域")
return
# 保存车牌图像用于调试
plt.imshow(plate_img), plt.axis('off'), plt.title("车牌区域")
plt.savefig("detected_plate.png")
# OCR 识别车牌
ocr_results = ocr.ocr(plate_img, cls=False)
if ocr_results:
for line in ocr_results:
number_plate = line[-1][-1][0]
logging.info(f"车牌号: {number_plate}")
print(f"车牌号:{number_plate}")
else:
logging.warning("OCR 识别失败,未能找到有效车牌")
if __name__ == '__main__':
# 使用argparse解析命令行参数
parser = argparse.ArgumentParser(description="车牌识别程序")
parser.add_argument('image_path', type=str, help='输入图片的路径')
args = parser.parse_args()
# 运行主程序
main(args.image_path)
2.2 核心步骤说明
- 车牌区域提取:使用形态学操作、边缘检测等技术提取车牌区域。
- OCR识别:调用PaddleOCR库对车牌区域进行识别,返回车牌号。
- 日志与调试:将每个重要步骤记录到日志中,方便调试与监控。
三、运行车牌识别
在完成Docker镜像的构建与Python脚本编写后,我们可以通过以下命令来运行车牌识别程序:
bash
docker run --rm \
-v /www/wwwroot/ocr_py:/app \
-v /www/cosfs/api-business:/images \
-v /www/cosfs/paddleocr_models:/root/.paddleocr \
plate_recognition \
python3 /app/main.py /images/20241009/1728455029333.jpg
/www/wwwroot/ocr_py:/app
将当前代码挂载到容器的/app
目录。/www/cosfs/api-business:/images
挂载包含待识别车牌图片的路径。- `/www/cosfs/paddleocr_models:/root/.p
addleocr` 挂载PaddleOCR的模型文件路径。
运行完成后,程序会自动识别图片中的车牌号,并输出结果。
四、总结
本文介绍了如何在CentOS环境下,使用Docker容器搭建Python车牌号OCR识别系统。通过PaddleOCR进行车牌区域的检测和识别,整个过程简单高效。
五、示例图