Python案例如何实现车牌识别?

wen python案例 2

本文目录导读:

Python案例如何实现车牌识别?

  1. 环境准备
  2. 车牌识别完整案例
  3. 使用深度学习的方法(更准确)
  4. 快速测试脚本
  5. 优化建议
  6. 使用说明

我来介绍一个基于OpenCV和Tesseract的车牌识别Python实现方案。

环境准备

# 安装必要的库
pip install opencv-python
pip install pytesseract
pip install numpy
pip install matplotlib

车牌识别完整案例

import cv2
import numpy as np
import pytesseract
import re
from matplotlib import pyplot as plt
class LicensePlateRecognizer:
    def __init__(self):
        # 配置Tesseract路径(Windows用户需要)
        # pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
        pass
    def load_image(self, image_path):
        """加载图像"""
        img = cv2.imread(image_path)
        if img is None:
            raise ValueError("无法加载图像")
        return img
    def preprocess_image(self, img):
        """图像预处理"""
        # 转换为灰度图
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # 高斯模糊去噪
        blurred = cv2.GaussianBlur(gray, (5, 5), 0)
        # 自适应阈值处理
        adaptive_thresh = cv2.adaptiveThreshold(
            blurred, 255, 
            cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
            cv2.THRESH_BINARY_INV, 11, 2
        )
        return adaptive_thresh
    def find_license_plate_contour(self, processed_img, original_img):
        """查找车牌轮廓"""
        # 形态学操作
        kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (17, 3))
        morph_img = cv2.morphologyEx(processed_img, cv2.MORPH_CLOSE, kernel)
        # 查找轮廓
        contours, _ = cv2.findContours(
            morph_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
        )
        # 筛选车牌候选区域
        license_plate_candidates = []
        for contour in contours:
            # 计算轮廓面积
            area = cv2.contourArea(contour)
            if area < 1000:  # 过滤小区域
                continue
            # 获取外接矩形
            x, y, w, h = cv2.boundingRect(contour)
            aspect_ratio = w / float(h)
            # 车牌宽高比通常在2:1到5:1之间
            if 2.0 < aspect_ratio < 5.0:
                # 提取候选区域
                license_plate = original_img[y:y+h, x:x+w]
                license_plate_candidates.append({
                    'contour': contour,
                    'rect': (x, y, w, h),
                    'image': license_plate
                })
        return license_plate_candidates
    def enhance_license_plate(self, roi):
        """增强车牌区域图像质量"""
        # 转换为灰度
        gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
        # 直方图均衡化
        equalized = cv2.equalizeHist(gray)
        # 二值化处理
        _, binary = cv2.threshold(equalized, 0, 255, 
                                  cv2.THRESH_BINARY + cv2.THRESH_OTSU)
        # 去噪
        denoised = cv2.medianBlur(binary, 3)
        return denoised
    def recognize_characters(self, plate_img):
        """识别车牌字符"""
        try:
            # 增强图像
            enhanced_plate = self.enhance_license_plate(plate_img)
            # 使用Tesseract进行OCR识别
            # 配置识别参数
            config = '--psm 7 -c tessedit_char_whitelist=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
            text = pytesseract.image_to_string(enhanced_plate, config=config)
            # 清理识别结果
            text = ''.join(text.split()).upper()
            # 使用正则表达式提取有效的车牌号
            license_pattern = r'[A-Z]{1,2}[A-Z0-9]{5,6}'
            match = re.search(license_pattern, text)
            if match:
                return match.group()
            return text
        except Exception as e:
            print(f"字符识别失败: {e}")
            return ""
    def visualize_results(self, original_img, candidates, recognized_plate):
        """可视化识别结果"""
        # 复制原图
        result_img = original_img.copy()
        # 绘制所有候选区域
        for candidate in candidates:
            x, y, w, h = candidate['rect']
            cv2.rectangle(result_img, (x, y), (x+w, y+h), (0, 255, 0), 2)
        # 显示结果
        plt.figure(figsize=(12, 4))
        plt.subplot(1, 3, 1)
        plt.imshow(cv2.cvtColor(original_img, cv2.COLOR_BGR2RGB))
        plt.title('原始图像')
        plt.axis('off')
        plt.subplot(1, 3, 2)
        plt.imshow(cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB))
        plt.title('检测结果')
        plt.axis('off')
        # 显示识别的车牌
        if recognized_plate:
            plt.subplot(1, 3, 3)
            plt.text(0.5, 0.5, f"车牌号: {recognized_plate}", 
                    fontsize=14, ha='center', va='center')
            plt.title('识别结果')
            plt.axis('off')
        plt.tight_layout()
        plt.show()
    def recognize(self, image_path):
        """完成车牌识别主流程"""
        try:
            # 1. 加载图像
            original_img = self.load_image(image_path)
            # 2. 预处理
            processed_img = self.preprocess_image(original_img)
            # 3. 查找车牌区域
            license_plate_candidates = self.find_license_plate_contour(
                processed_img, original_img
            )
            if not license_plate_candidates:
                print("未检测到车牌区域")
                return None
            # 4. 识别字符
            best_plate = None
            max_confidence = 0
            for candidate in license_plate_candidates:
                plate_img = candidate['image']
                recognized_text = self.recognize_characters(plate_img)
                if recognized_text:
                    # 简单的置信度评估(可以根据实际需求优化)
                    confidence = len(recognized_text)
                    if confidence > max_confidence:
                        max_confidence = confidence
                        best_plate = recognized_text
                        candidate['recognized'] = True
            # 5. 可视化结果
            self.visualize_results(original_img, license_plate_candidates, best_plate)
            if best_plate:
                print(f"识别到的车牌号: {best_plate}")
                return best_plate
            else:
                print("无法识别车牌")
                return None
        except Exception as e:
            print(f"车牌识别失败: {e}")
            return None
# 使用示例
def main():
    # 创建识别器实例
    recognizer = LicensePlateRecognizer()
    # 识别车牌(请替换为实际图像路径)
    result = recognizer.recognize('car_license_plate.jpg')
    if result:
        print(f"成功识别车牌: {result}")
    else:
        print("车牌识别失败")
if __name__ == "__main__":
    main()

使用深度学习的方法(更准确)

import cv2
import numpy as np
from tensorflow import keras
import matplotlib.pyplot as plt
class AdvancedLicensePlateRecognizer:
    def __init__(self):
        # 加载预训练的深度学习模型(这里需要你先训练或下载模型)
        # self.model = keras.models.load_model('license_plate_model.h5')
        pass
    def detect_plate_deep_learning(self, image):
        """使用深度学习检测车牌(示例结构)"""
        # 这里需要实现你的深度学习模型推理
        # 可以使用YOLO、SSD等目标检测模型
        pass
    def recognize_characters_cnn(self, plate_img):
        """使用CNN识别字符(示例结构)"""
        # 字符分割和识别
        # 可以使用CNN+LSTM+CTC的网络结构
        pass
# 简化的车牌字符分割与识别
def segment_characters(plate_img):
    """分割车牌字符"""
    # 转换为灰度
    gray = cv2.cvtColor(plate_img, cv2.COLOR_BGR2GRAY)
    # 二值化
    _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    # 查找轮廓
    contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 筛选字符轮廓
    char_contours = []
    for contour in contours:
        x, y, w, h = cv2.boundingRect(contour)
        if h > 30 and w > 15:  # 根据实际图像调整
            char_contours.append((x, y, w, h))
    # 按x坐标排序
    char_contours = sorted(char_contours, key=lambda x: x[0])
    # 提取字符图像
    char_images = []
    for x, y, w, h in char_contours:
        char = binary[y:y+h, x:x+w]
        # 调整为统一大小
        char = cv2.resize(char, (28, 28))
        char_images.append(char)
    return char_images

快速测试脚本

import cv2
import sys
def quick_test(image_path):
    """快速测试车牌识别"""
    recognizer = LicensePlateRecognizer()
    result = recognizer.recognize(image_path)
    if result:
        print(f"车牌号: {result}")
    else:
        print("识别失败")
# 命令行使用
if __name__ == "__main__":
    if len(sys.argv) > 1:
        quick_test(sys.argv[1])
    else:
        print("请提供图像路径")

优化建议

1 提高准确率的方法

# 1. 图像增强
def enhance_plate_image(plate_img):
    # 自适应直方图均衡化
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
    enhanced = clahe.apply(plate_img)
    return enhanced
# 2. 角度校正
def deskew_plate(plate_img):
    # 检测倾斜角度并进行校正
    coords = np.column_stack(np.where(plate_img > 0))
    angle = cv2.minAreaRect(coords)[-1]
    if angle < -45:
        angle = 90 + angle
    # 旋转校正
    (h, w) = plate_img.shape[:2]
    center = (w // 2, h // 2)
    M = cv2.getRotationMatrix2D(center, angle, 1.0)
    rotated = cv2.warpAffine(plate_img, M, (w, h))
    return rotated

2 自定义训练模型

# 如果需要训练自己的OCR模型
def train_custom_ocr(training_data_path):
    """
    训练自定义的OCR模型
    可以使用TensorFlow或PyTorch框架
    """
    # 实现你的训练逻辑
    pass

使用说明

  1. 安装依赖:确保安装了OpenCV、Tesseract等必要库
  2. 准备图像:选择清晰的车牌图像
  3. 运行代码:调用recognize()方法
  4. 查看结果:程序会显示原始图像、检测结果和识别出的车牌号

这个实现适用于大多数标准车牌识别场景,对于特殊场景(如角度大、光照不均等),建议使用深度学习模型提高准确率。

抱歉,评论功能暂时关闭!