python车牌号OCR识别(centos版)

在实际应用中,车牌号的识别(OCR)是一个非常重要的需求,尤其是在停车场管理、道路监控等场景中。本文将介绍如何在CentOS环境下,通过Docker容器,基于PaddleOCR来实现车牌号的识别。具体内容包括构建Docker镜像的步骤、相关依赖安装、Python脚本实现,以及如何运行整个车牌识别流程。

一、环境准备

我们采用CentOS作为宿主机操作系统,利用Docker容器来构建Python车牌OCR识别环境。容器化可以有效简化环境配置,避免依赖冲突。

1.1 安装Docker

首先,确保宿主机已经安装了Docker。若尚未安装,可以通过以下命令安装:

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的内容:

# 使用 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 车牌识别核心代码
# -*- 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 核心步骤说明
  1. 车牌区域提取:使用形态学操作、边缘检测等技术提取车牌区域。
  2. OCR识别:调用PaddleOCR库对车牌区域进行识别,返回车牌号。
  3. 日志与调试:将每个重要步骤记录到日志中,方便调试与监控。

三、运行车牌识别

在完成Docker镜像的构建与Python脚本编写后,我们可以通过以下命令来运行车牌识别程序:

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进行车牌区域的检测和识别,整个过程简单高效。

五、示例图

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/891990.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

antd vue 输入框高亮设置关键字

<highlight-textareaplaceholder"请输入主诉"type"textarea"v-model"formModel.mainSuit":highlightKey"schema.componentProps.highlightKey"></highlight-textarea> 参考链接原生input&#xff0c;textarea demo地址 …

网站建设为什么要选择国内服务器

选择国内服务器进行网站建设&#xff0c;对于面向国内用户的企业来说&#xff0c;是一个明智的决策。以下是一些选择国内服务器的主要原因&#xff1a; 提升用户体验&#xff1a; 网站访问速度是用户体验的关键因素之一。由于物理距离较近&#xff0c;国内服务器通常能提供更快…

Linux_进程概念详解(续)_命令行参数_环境变量_进程地址空间

本篇文章是Linux_进程概念详解的续篇&#xff0c;请先阅读Linux_进程概念详解再来阅读本篇。 命令行参数 在C / C中&#xff0c;每个程序都必须有一个main函数&#xff0c;该函数有很多的版本&#xff0c;我们最常用的就是不带参数的版本&#xff0c;也就是下面第一条语句 i…

关于 文件操作详解 笔记 (含代码解析)

文件 磁盘&#xff08;硬盘&#xff09;上的⽂件是⽂件。 程序设计中&#xff0c;我们⼀般谈的⽂件有两种&#xff1a;程序⽂件、数据⽂件&#xff08;从⽂件功能的⻆度来分类 &#xff09; 程序⽂件 程序⽂件包括源程序⽂件&#xff08;后缀为.c&#xff09;,⽬标⽂件&#…

【测试】BUG篇——BUG

bug的概念 定义&#xff1a;⼀个计算机bug指在计算机程序中存在的⼀个错误(error)、缺陷(flaw)、疏忽(mistake)或者故障(fault)&#xff0c;这些bug使程序⽆法正确的运⾏。Bug产⽣于程序的源代码或者程序设计阶段的疏忽或者错误。 准确的来说&#xff1a; 当且仅当规格说明&am…

项目_C_Ncurses_Flappy bird小游戏

Ncurses库 概述 什么是Ncurses库&#xff1a; Ncurses是一个管理应用程序在字符终端显示的函数库&#xff0c;库中提供了创建窗口界面、移动光标、产生颜色、处理键盘按键等功能。 安装Ncurses库&#xff1a; sudo apt-get install libncurses5-dev 头文件与编译&#xf…

老人桌面 1.3.5|专为老人设计的便捷实用桌面应用

老人桌面是一款专为老人设计的便捷实用桌面应用&#xff0c;具有超大字体设计&#xff0c;符合老人视力水平&#xff0c;撞色简洁的应用界面&#xff0c;拯救老人视觉体验。此外&#xff0c;还提供了常用的实用小工具&#xff0c;让老人能够轻松使用手机。 大小&#xff1a;5.…

Oracle-19g数据库的安装

简介 Oracle是一家全球领先的数据库和云解决方案提供商。他们提供了一套完整的技术和产品&#xff0c;包括数据库管理系统、企业级应用程序、人工智能和机器学习工具等。Oracle的数据库管理系统是业界最受欢迎和广泛使用的数据库之一&#xff0c;它可以管理和存储大量结构化和…

界面耻辱纪念堂--可视元素03

更多的迹象表明&#xff0c;关于在程序里使用新的动态界面元素&#xff0c;微软的态度是不确定的&#xff0c;其中一个是仅仅需要对比一下Office97 里的“Coolbars”和“标准工具条”。Coolbar 按钮直到用户指针通过的时候才成为按钮&#xff08;否则是平的&#xff09;。 工具…

SpringBoot Data JPA基本使用

一、项目起步 1.1 pom配置 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency><dependency><groupId>org.springframework.boot</groupId><…

Android终端GB28181音视频实时回传设计探讨

技术背景 好多开发者&#xff0c;在调研Android平台GB28181实时回传的时候&#xff0c;对这块整体的流程&#xff0c;没有个整体的了解&#xff0c;本文以大牛直播SDK的SmartGBD设计开发为例&#xff0c;聊下如何在Android终端实现GB28181音视频数据实时回传。 技术实现 Andr…

光伏仿真系统在光伏项目开发中有哪些应用场景?

光伏仿真系统在光伏项目开发中的应用场景广泛&#xff0c;涵盖了从项目规划、设计优化到运维管理的全过程。 一、项目规划与选址 1、气象模拟与评估 光伏仿真系统能够基于历史气象数据和先进的预测模型&#xff0c;模拟不同地理位置、不同季节和时间段的光照强度、温度、湿度…

【学术论文投稿】Java入门:零基础小白也能轻松掌握的全攻略

【IEEE | 往届见刊1个月检索 | 国际双会场】第四届智能电力与系统国际学术会议(ICIPS 2024)_艾思科蓝_学术一站式服务平台 更多学术论文投稿请看&#xff1a;https://ais.cn/u/nuyAF3 目录 【IEEE | 往届见刊1个月检索 | 国际双会场】第四届智能电力与系统国际学术会议(ICIPS…

『网络游戏』三端增加数据.dll替换【32】三端

修改服务器脚本&#xff1a;DBMgr 增加数据库 修改客户端脚本&#xff1a;MainCityWnd.cs 拖拽绑定 查看服务端PlayerData调用的协议位置 在客户端中替换 之后客户端就可以调用服务端新增的数据了

Elasticsearch Ingest Pipelines

1. 前言 在将第三方数据源的数据导入到Elasticsearch中时&#xff0c;原始数据长什么样&#xff0c;索引后的文档就是什么样。文档数据结构不统一&#xff0c;导致后续数据分析时变得麻烦&#xff0c;以往需要额外写一个中间程序来读取原始数据&#xff0c;转换加工后再写入到…

Linux下Docker方式Jenkins安装和配置

一、下载&安装 Jenkins官方Docker仓库地址&#xff1a;https://hub.docker.com/r/jenkins/jenkins 从官网上可以看到&#xff0c;当前最新的稳定版本是 jenkins/jenkins:lts-jdk17。建议下在新的&#xff0c;后面依赖下不来 所以&#xff0c;我们这里&#xff0c;执行doc…

智绘城市地图:使用百度地图 API 实现智能定位

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

测网速小程序,纯前端

搜索&#xff1a;证寸照制作 源码介绍: 测网速小程序源码&#xff0c;是一款纯前端无需服务器的测网速小程序&#xff0c;依赖百度开发者中心js接口&#xff0c;真正的永久使用的小工具源码&#xff0c;很实用&#xff0c;可以单独运行&#xff0c;测网速很流畅~ 合法域名: ht…

深入理解 pnpm(Performant NPM) 的实现原理及其与 npm 的区别

深入理解 pnpm 的实现原理及其与 npm 的区别 在 JavaScript 生态系统中&#xff0c;包管理器是开发者日常工作中不可或缺的工具。npm&#xff08;Node Package Manager&#xff09;作为 Node.js 的默认包管理器&#xff0c;已经广泛应用于各种项目中。然而&#xff0c;随着项目…

力扣之接雨水(42)

刷题不在多&#xff0c;而在精。 这道题号称字节的保洁阿姨都能做出的。 方法一&#xff1a;动态规划 下面这幅图简直封神&#xff0c;看了下图我才做出来的。 两个方向遍历&#xff0c;然后取相同覆盖值-原始值&#xff08;heigth数组&#xff09; 这种方法更好理解。但是也有…