sgbyg 发表于 2024-6-2 16:37

Python做的车牌识别

本帖最后由 sgbyg 于 2024-6-2 16:51 编辑

import cv2
import numpy as np
import glob


def get_plate(image_):
    global plate
    rawImage = image_.copy()
    # 去噪处理
    image_ = cv2.GaussianBlur(image_, (3, 3), 0)
    # 色彩空间转换
    image_ = cv2.cvtColor(image_, cv2.COLOR_BGR2GRAY)
    # Sobel算子
    Sobel_x = cv2.Sobel(image_, cv2.CV_16S, 1, 0)
    absX = cv2.convertScaleAbs(Sobel_x)
    image_ = absX
    # 阈值处理
    ret, image_ = cv2.threshold(image_, 0, 255, cv2.THRESH_OTSU)
    # 闭运算 先膨胀后腐蚀 车牌各个字符是分散的 让车牌构成一体
    kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (17, 5))
    image_ = cv2.morphologyEx(image_, cv2.MORPH_CLOSE, kernelX)
    # 开运算 先腐蚀后膨胀 去除噪声
    kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 19))
    image_ = cv2.morphologyEx(image_, cv2.MORPH_OPEN, kernelY)
    # 中值滤波 去除噪声
    image_ = cv2.medianBlur(image_, 15)
    # 查找轮廓
    contours, w1 = cv2.findContours(image_, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # 逐个遍历 将宽度>3倍高度的轮廓确定为车牌
    for item in contours:
      rect = cv2.boundingRect(item)
      x = rect
      y = rect
      weight = rect
      height = rect
      if weight > (height * 3):
            plate = rawImage
    return plate


def preprocessor(image_):
    # 图像去噪灰度处理
    image_ = cv2.GaussianBlur(image_, (3, 3), 0)
    # 色彩空间转换
    gray_image = cv2.cvtColor(image_, cv2.COLOR_RGB2GRAY)
    # 阈值处理
    ret, image_ = cv2.threshold(gray_image, 0, 255, cv2.THRESH_OTSU)
    # 膨胀处理 让一个字构成一个整体
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
    image_ = cv2.dilate(image_, kernel)
    return image_


def split_plate(image_):
    # 查找轮廓,各个字符的轮廓
    contours, hierarchy = cv2.findContours(image_, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    words = []
    # 遍历所有轮廓
    for item in contours:
      rect = cv2.boundingRect(item)
      words.append(rect)
    # 按照x轴坐标值排序(自左向右排序)
    words = sorted(words, key=lambda s: s, reverse=False)
    # 用word存放左上角起始点及长宽值
    plateChars = []
    for word in words:
      # 筛选字符的轮廓(高宽比在1.5-8之间,宽度大于3)
      if (word > (word * 1.5)) and (word < (word * 8)) and (word > 3):
            plateChar = image_:word + word, word:word + word]
            plateChars.append(plateChar)
    return plateChars


template_dict = {0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9',
               10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F', 16: 'G', 17: 'H',
               18: 'J', 19: 'K', 20: 'L', 21: 'M', 22: 'N', 23: 'P', 24: 'Q', 25: 'R',
               26: 'S', 27: 'T', 28: 'U', 29: 'V', 30: 'W', 31: 'X', 32: 'Y', 33: 'Z',
               34: '京', 35: '津', 36: '冀', 37: '晋', 38: '蒙', 39: '辽', 40: '吉', 41: '黑',
               42: '沪', 43: '苏', 44: '浙', 45: '皖', 46: '闽', 47: '赣', 48: '鲁', 49: '豫',
               50: '鄂', 51: '湘', 52: '粤', 53: '桂', 54: '琼', 55: '渝', 56: '川', 57: '贵',
               58: '云', 59: '藏', 60: '陕', 61: '甘', 62: '青', 63: '宁', 64: '新',
               65: '港', 66: '澳', 67: '台'}


def get_characters():
    c = []
    for i_ in range(0, 67):
      words = []
      words.extend(glob.glob(f'template/{template_dict.get(i_)}/*.*'))
      c.append(words)
    return c


def get_match_value(template, image_):
    # 读取模板图像
    templateImage = cv2.imdecode(np.fromfile(template, dtype=np.uint8), 1)
    # 模板图像色彩空间转换 BGR-->灰度
    templateImage = cv2.cvtColor(templateImage, cv2.COLOR_BGR2GRAY)
    # 模板图像阈值处理 灰度-->二值
    ret, templateImage = cv2.threshold(templateImage, 0, 255, cv2.THRESH_OTSU)
    # 获取待识别图像的尺寸
    height, width = image_.shape
    # 将模板图像调整为与待识别图像尺寸一致
    templateImage = cv2.resize(templateImage, (width, height))
    # 计算模板图像、待识别图像的模板匹配值
    result = cv2.matchTemplate(image_, templateImage, cv2.TM_CCOEFF)
    # 将计算结果返回
    return result


def match_chars(plates, chars_):
    # 存储所有的识别结果
    results_ = []
    # 逐个遍历要识别的字符
    for i_ in plates:
      # 最佳匹配
      best_match = []
      # words 对应的是每一个字符
      for words in chars_:
            match = []
            for word in words:
                result = get_match_value(word, i_)
                match.append(result)
            best_match.append(max(match))
      i_ = best_match.index(max(best_match))
      r = template_dict
      results_.append(r)
    return results_


if __name__ == '__main__':
    # 读取原始图像
    image = cv2.imread("test_img.jpg")
    # 获取车牌
    image = get_plate(image)
    # 预处理
    image = preprocessor(image)
    # 分割车牌 将每个字符独立出来
    plate_chars = split_plate(image)

    # 获取所有模板文件
    chars = get_characters()
    # 使用模板chars逐个识别字符集plates
    results = match_chars(plate_chars, chars)
    # 将列表转换为字符串并输出识别结果
    print("".join(results))



附件解压密码为 52pj

Liebesfreud 发表于 2024-6-3 09:21

让我想起之前做的课设就是车牌识别系统,当时不想做在网上一搜,什么类型的车牌识别系统都有,有点感慨{:301_980:}

cooltnt 发表于 2024-7-15 16:34

本帖最后由 cooltnt 于 2024-7-15 16:42 编辑

案例自带的test_img.jpg可以识别,但是网上找了一张稍微模糊点的图片,找不到车牌轮廓,下面这里不符合,导致plate为未定义
if weight > (height * 3):
            plate = rawImage

life9999 发表于 2024-6-2 18:35

识别成功率多少,能99.99%吗

cjy2323 发表于 2024-6-3 09:00

xjlyg 发表于 2024-6-2 16:53
有大门口抬杆代码吗

我也想知道,小区空那么多车位,都不让进

cat- 发表于 2024-6-2 16:46


project.7z中的main.pyj 空文件

shojnhv 发表于 2024-6-2 16:46

谢谢楼主,学习一下

sgbyg 发表于 2024-6-2 16:48

cat- 发表于 2024-6-2 16:46
project.7z中的main.pyj 空文件

代码已经在帖子里了

xjlyg 发表于 2024-6-2 16:53

有大门口抬杆代码吗

Networktest2022 发表于 2024-6-2 17:04

PY简化这么多

ZhjhJZ 发表于 2024-6-2 17:32

Python还能做这个!厉害{:1_921:}

天空宫阙 发表于 2024-6-2 17:53

找到候选框再识别的方案不多见了,不知道准确率咋样?

long88888888 发表于 2024-6-2 18:36

厉害,学习了
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: Python做的车牌识别