基于Python深度学习的车辆车牌识别系统(PyTorch2卷积神经网络CNN+OpenCV4实现)视频教程 - 切割车牌矩阵获取车牌字符

大家好,我是java1234_小锋老师,最近写了一套基于Python深度学习的车辆车牌识别系统(PyTorch2卷积神经网络CNN+OpenCV4实现)视频教程,持续更新中,计划月底更新完,感谢支持。

视频在线地址:

https://www.bilibili.com/video/BV1BdUnBLE6N/

课程简介:

本课程采用主流的Python技术栈实现,分两套系统讲解,一套是专门讲PyTorch2卷积神经网络CNN训练模型,识别车牌,当然实现过程中还用到OpenCV实现图像格式转换,裁剪,大小缩放等。另外一套是基于前面Django+Vue通用权限系统基础上,加了车辆识别业务模型,Mysql8数据库,Django后端,Vue前端,后端集成训练好的模型,实现车牌识别。

基于Python深度学习的车辆车牌识别系统(PyTorch2卷积神经网络CNN+OpenCV4实现)视频教程 - 切割车牌矩阵获取车牌字符

前面代码我们从图像中截取了车牌矩阵,现在我们来切割车牌字符。

复制代码
复制代码
# 左右切割
def horizontal_cut_chars(plate):
    """
    该函数用于对车牌图像进行水平切割,提取字符区域。主要步骤包括:
    1. 计算每列像素点总和;
    2. 根据阈值判断字符区域起止位置;
    3. 限制字符宽度范围以过滤无效区域;
    4. 返回符合条件的字符区域坐标列表。
    """
    char_addr_list = []
    area_left, area_right, char_left, char_right = 0, 0, 0, 0
    img_w = plate.shape[1]

    # 获取车牌每列边缘像素点个数
    def getColSum(img, col):
        sum = 0
        for i in range(img.shape[0]):
            sum += round(img[i, col] / 255)
        return sum;

    sum = 0
    for col in range(img_w):
        sum += getColSum(plate, col)
    # 每列边缘像素点必须超过均值的60%才能判断属于字符区域
    col_limit = 0  # round(0.6*sum/img_w)
    # 每个字符宽度也进行限制
    charWid_limit = [round(img_w / 12), round(img_w / 5)]
    is_char_flag = False

    for i in range(img_w):
        colValue = getColSum(plate, i)
        if colValue > col_limit:
            if is_char_flag == False:
                area_right = round((i + char_right) / 2)
                area_width = area_right - area_left
                char_width = char_right - char_left
                if (area_width > charWid_limit[0]) and (area_width < charWid_limit[1]):
                    char_addr_list.append((area_left, area_right, char_width))
                char_left = i
                area_left = round((char_left + char_right) / 2)
                is_char_flag = True
        else:
            if is_char_flag == True:
                char_right = i - 1
                is_char_flag = False
    # 手动结束最后未完成的字符分割
    if area_right < char_left:
        area_right, char_right = img_w, img_w
        area_width = area_right - area_left
        char_width = char_right - char_left
        if (area_width > charWid_limit[0]) and (area_width < charWid_limit[1]):
            char_addr_list.append((area_left, area_right, char_width))
    return char_addr_list


# 获取字符
def get_chars(car_plate):
    img_h, img_w = car_plate.shape[:2]
    h_proj_list = []  # 水平投影长度列表
    h_temp_len, v_temp_len = 0, 0
    h_startIndex, h_end_index = 0, 0  # 水平投影记索引
    h_proj_limit = [0.2, 0.8]  # 车牌在水平方向得轮廓长度少于20%或多余80%过滤掉
    char_imgs = []

    """
    这段代码用于对二值化车牌图像进行水平投影分析。
    它统计每一行的白色像素数量,记录连续有效投影段,并根据比例过滤掉过短或过长的投影区域,
    最终提取出最可能包含字符的水平区域。
    """
    # 将二值化的车牌水平投影到Y轴,计算投影后的连续长度,连续投影长度可能不止一段
    h_count = [0 for i in range(img_h)]
    for row in range(img_h):
        temp_cnt = 0
        for col in range(img_w):
            if car_plate[row, col] == 255:
                temp_cnt += 1
        h_count[row] = temp_cnt
        if temp_cnt / img_w < h_proj_limit[0] or temp_cnt / img_w > h_proj_limit[1]:
            if h_temp_len != 0:
                h_end_index = row - 1
                h_proj_list.append((h_startIndex, h_end_index))
                h_temp_len = 0
            continue
        if temp_cnt > 0:
            if h_temp_len == 0:
                h_startIndex = row
                h_temp_len = 1
            else:
                h_temp_len += 1
        else:
            if h_temp_len > 0:
                h_end_index = row - 1
                h_proj_list.append((h_startIndex, h_end_index))
                h_temp_len = 0

    # 手动结束最后得水平投影长度累加
    if h_temp_len != 0:
        h_end_index = img_h - 1
        h_proj_list.append((h_startIndex, h_end_index))
    """
    这段代码的功能是:
    1. 遍历水平投影列表,找出最长的有效投影段(即字符区域)。
    2. 若该投影段高度不足图像总高度的50%,则认为未检测到有效车牌字符,直接返回空结果。
    3. 否则,截取该区域作为车牌主体部分,并调用[horizontal_cut_chars]函数进一步横向切割出每个字符的边界。
    4. 根据字符边界从原图中提取每个字符图像,缩放到统一尺寸后加入结果列表返回。
    """
    h_maxIndex, h_maxHeight = 0, 0
    for i, (start, end) in enumerate(h_proj_list):
        if h_maxHeight < (end - start):
            h_maxHeight = (end - start)
            h_maxIndex = i
    if h_maxHeight / img_h < 0.5:
        return char_imgs
    chars_top, chars_bottom = h_proj_list[h_maxIndex][0], h_proj_list[h_maxIndex][1]

    plates = car_plate[chars_top:chars_bottom + 1, :]
    cv2.imwrite('process_img/plate.jpg', plates)
    char_addr_list = horizontal_cut_chars(plates)

    for i, addr in enumerate(char_addr_list):
        char_img = car_plate[chars_top:chars_bottom + 1, addr[0]:addr[1]]
        char_img = cv2.resize(char_img, (char_w, char_h))
        char_imgs.append(char_img)
    return char_imgs


def extract_char(car_plate):
    gray_plate = cv2.cvtColor(car_plate, cv2.COLOR_BGR2GRAY)  # 转为灰度图
    ret, binary_plate = cv2.threshold(gray_plate, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)  # 二值化
    cv2.imwrite('process_img/binary_plate.jpg', gray_plate)
    print(binary_plate)
    return get_chars(binary_plate)


if __name__ == '__main__':
    car_plate_w, car_plate_h = 136, 36  # 车牌宽高
    char_w, char_h = 20, 20  # 字符宽高
    char_model_path = "char.pth"
    test_images_root = 'images/test/'  # 测试图片路径
    files = list_all_files(test_images_root)
    files.sort()

    for file in files:
        img = cv2.imread(file)  # 读取图片
        pred_img = pre_process(img)  # 预处理图片
        car_plate_list = locate_carPlate(img, pred_img)  # 车牌定位
        if len(car_plate_list) == 0:
            continue
        else:
            car_plate = car_plate_list[0]  # 获取车牌
            char_img_list = extract_char(car_plate)  # 获取车牌字符
            for id in range(len(char_img_list)):
                img_name = 'char/char-' + str(id) + '.jpg'
                cv2.imwrite(img_name, char_img_list[id])

运行后,能得到切割后的字符

相关推荐
陈文锦丫1 小时前
Boundary Difference Over Union Loss For Medical Image Segmentation
深度学习
u***28471 小时前
Python连接SQL SEVER数据库全流程
数据库·python·sql
测试19981 小时前
接口测试工具之postman详解
自动化测试·软件测试·python·测试工具·测试用例·接口测试·postman
q***57501 小时前
问题:Flask应用中的用户会话(Session)管理失效
后端·python·flask
青瓷程序设计1 小时前
海洋生物识别系统【最新版】Python+TensorFlow+Vue3+Django+人工智能+深度学习+卷积神经网络算法
人工智能·python·深度学习
小邓   ༽1 小时前
C语言课件(非常详细)
java·c语言·开发语言·python·eclipse·c#·c语言课件
~~李木子~~1 小时前
中文社交媒体情感分析实战:基于B站评论的机器学习与深度学习对比
深度学习·机器学习·媒体
闲人编程2 小时前
Django中间件开发:从请求到响应的完整处理链
python·中间件·性能优化·django·配置·codecapsule