【源码】车牌检测+QT界面+附带数据库

news2024/7/4 6:25:01

目录

  • 1、基本介绍
  • 2、基本环境
  • 3、核心代码
    • 3.1、车牌识别
    • 3.2、车牌定位
    • 3.3、车牌坐标矫正
  • 4、界面展示
    • 4.1、主界面
    • 4.2、车牌检测
    • 4.3、查询功能
  • 5、演示
  • 6、链接

1、基本介绍

 本项目采用tensorflow,opencv,pyside6和pymql编写,pyside6用来编写UI界面,进行界面展示;tensorflow用来训练模型检测字符和车牌定位;使用opencv进行边缘检测,获取车牌区域的边缘坐标和最小外接矩形4个端点坐标,再从车牌的边缘坐标中计算出和最小外接矩形4个端点,最近的点即为平行四边形车牌的四个端点,从而实现车牌的定位和矫正;pysql主要用来实现基本的数据库读写插入功能。

2、基本环境

pyside6==6.5.0
tensorflow>=2.0.0
opencv-python==4.8.1.78
pymysql==1.0.3

3、核心代码

3.1、车牌识别


#车牌识别
def cnn_predict(cnn, Lic_img):
    characters = ["京", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "皖", "闽", "赣", "鲁", "豫",
                  "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "0", "1", "2",
                  "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M",
                  "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
    Lic_pred = []
    for lic in Lic_img:
        lic_pred = cnn.predict(lic.reshape(1, 80, 240, 3))
        lic_pred = np.array(lic_pred).reshape(7, 65)
        if len(lic_pred[lic_pred >= 0.8]) >= 4:
            chars = ''
            for arg in np.argmax(lic_pred, axis=1):  # 取每行中概率值最大的arg,将其转为字符
                chars += characters[arg]
            chars = chars[0:2] + '·' + chars[2:]
            Lic_pred.append((lic, chars))  # 将车牌和识别结果一并存入Lic_pred
    return Lic_pred

3.2、车牌定位

#车牌定位
def unet_predict(unet, img_src_path):
    img_src = cv2.imdecode(np.fromfile(img_src_path, dtype=np.uint8), -1)
    # img_src=cv2.imread(img_src_path)
    if img_src.shape != (512, 512, 3):
        img_src = cv2.resize(img_src, dsize=(512, 512), interpolation=cv2.INTER_AREA)[:, :, :3]  # dsize=(宽度,高度),[:,:,:3]是防止图片为4通道图片,后续无法reshape
    img_src = img_src.reshape(1, 512, 512, 3)

    img_mask = unet.predict(img_src)  # 归一化除以255后进行预测
    img_src = img_src.reshape(512, 512, 3)  # 将原图reshape为3维
    img_mask = img_mask.reshape(512, 512, 3)  # 将预测后图片reshape为3维
    img_mask = img_mask / np.max(img_mask) * 255  # 归一化后乘以255
    img_mask[:, :, 2] = img_mask[:, :, 1] = img_mask[:, :, 0]  # 三个通道保持相同
    img_mask = img_mask.astype(np.uint8)  # 将img_mask类型转为int型

    return img_src, img_mask

3.3、车牌坐标矫正


def locate_and_correct(img_src, img_mask):
    """
    该函数通过cv2对img_mask进行边缘检测,获取车牌区域的边缘坐标(存储在contours中)和最小外接矩形4个端点坐标,

    再从车牌的边缘坐标中计算出和最小外接矩形4个端点
    最近的点即为平行四边形车牌的四个端点,从而实现车牌的定位和矫正

    img_src: 原始图片

    img_mask: 通过u_net进行图像分隔得到的二值化图片,车牌区域呈现白色,背景区域为黑色

    定位且矫正后的车牌

    """
    try: #  contours1长度为0说明未检测到车牌
        contours, hierarchy = cv2.findContours(img_mask[:, :, 0], cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    except:
        ret, contours, hierarchy = cv2.findContours(img_mask[:, :, 0], cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    if not len(contours):
        # print("未检测到车牌")
        return [], []
    else:
        Lic_img = []
        img_src_copy = img_src.copy()
        for ii, cont in enumerate(contours):
            x, y, w, h = cv2.boundingRect(cont)
            img_cut_mask = img_mask[y:y + h, x:x + w]
            # contours中除了车牌区域可能会有宽或高都是1或者2这样的小噪点,
            # 而待选车牌区域的均值应较高,且宽和高不会非常小,因此通过以下条件进行筛选
            if np.mean(img_cut_mask) >= 75 and w > 15 and h > 15:
                rect = cv2.minAreaRect(cont)  # 针对坐标点获取带方向角的最小外接矩形,中心点坐标,宽高,旋转角度
                box = cv2.boxPoints(rect).astype(np.int32)  # 获取最小外接矩形四个顶点坐标
                cont = cont.reshape(-1, 2).tolist()
                # 由于转换矩阵的两组坐标位置需要一一对应,因此需要将最小外接矩形的坐标进行排序,最终排序为[左上,左下,右上,右下]
                box = sorted(box, key=lambda xy: xy[0])  # 先按照左右进行排序,分为左侧的坐标和右侧的坐标
                box_left, box_right = box[:2], box[2:]  # 此时box的前2个是左侧的坐标,后2个是右侧的坐标
                box_left = sorted(box_left, key=lambda x: x[1])  # 再按照上下即y进行排序,此时box_left中为左上和左下两个端点坐标
                box_right = sorted(box_right, key=lambda x: x[1])  # 此时box_right中为右上和右下两个端点坐标
                box = np.array(box_left + box_right)  # [左上,左下,右上,右下]
                # print(box)
                x0, y0 = box[0][0], box[0][1]  # 这里的4个坐标即为最小外接矩形的四个坐标,接下来需获取平行(或不规则)四边形的坐标
                x1, y1 = box[1][0], box[1][1]
                x2, y2 = box[2][0], box[2][1]
                x3, y3 = box[3][0], box[3][1]
                def point_to_line_distance(X, Y):
                    if x2 - x0:
                        k_up = (y2 - y0) / (x2 - x0)  # 斜率不为无穷大
                        d_up = abs(k_up * X - Y + y2 - k_up * x2) / (k_up ** 2 + 1) ** 0.5
                    else:  # 斜率无穷大
                        d_up = abs(X - x2)
                    if x1 - x3:
                        k_down = (y1 - y3) / (x1 - x3)  # 斜率不为无穷大
                        d_down = abs(k_down * X - Y + y1 - k_down * x1) / (k_down ** 2 + 1) ** 0.5
                    else:  # 斜率无穷大
                        d_down = abs(X - x1)
                    return d_up, d_down
                d0, d1, d2, d3 = np.inf, np.inf, np.inf, np.inf
                l0, l1, l2, l3 = (x0, y0), (x1, y1), (x2, y2), (x3, y3)
                for each in cont:  # 计算cont中的坐标与矩形四个坐标的距离以及到上下两条直线的距离,对距离和进行权重的添加,成功计算选出四边形的4个顶点坐标
                    x, y = each[0], each[1]
                    dis0 = (x - x0) ** 2 + (y - y0) ** 2
                    dis1 = (x - x1) ** 2 + (y - y1) ** 2
                    dis2 = (x - x2) ** 2 + (y - y2) ** 2
                    dis3 = (x - x3) ** 2 + (y - y3) ** 2
                    d_up, d_down = point_to_line_distance(x, y)
                    weight = 0.975
                    if weight * d_up + (1 - weight) * dis0 < d0:  # 小于则更新
                        d0 = weight * d_up + (1 - weight) * dis0
                        l0 = (x, y)
                    if weight * d_down + (1 - weight) * dis1 < d1:
                        d1 = weight * d_down + (1 - weight) * dis1
                        l1 = (x, y)
                    if weight * d_up + (1 - weight) * dis2 < d2:
                        d2 = weight * d_up + (1 - weight) * dis2
                        l2 = (x, y)
                    if weight * d_down + (1 - weight) * dis3 < d3:
                        d3 = weight * d_down + (1 - weight) * dis3
                        l3 = (x, y)
                p0 = np.float32([l0, l1, l2, l3])  # 左上角,左下角,右上角,右下角,p0和p1中的坐标顺序对应,以进行转换矩阵的形成
                p1 = np.float32([(0, 0), (0, 80), (240, 0), (240, 80)])  # 我们所需的长方形
                transform_mat = cv2.getPerspectiveTransform(p0, p1)  # 构成转换矩阵
                lic = cv2.warpPerspective(img_src, transform_mat, (240, 80))  # 进行车牌矫正
                Lic_img.append(lic)
                cv2.drawContours(img_src_copy, [np.array([l0, l1, l3, l2])], -1, (0, 255, 0), 2)
    return img_src_copy, Lic_img

4、界面展示

4.1、主界面

 主界面包括停车场容量和剩余容量显示和当前时间。
请添加图片描述

4.2、车牌检测

 车牌检测与定位功能。
请添加图片描述

4.3、查询功能

按车牌查询。
请添加图片描述
所有信息记录查询
请添加图片描述

5、演示

6、链接

源码链接

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年【上海市安全员B证】考试题库及上海市安全员B证考试资料

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 上海市安全员B证考试题库是安全生产模拟考试一点通总题库中生成的一套上海市安全员B证考试资料&#xff0c;安全生产模拟考试一点通上上海市安全员B证作业手机同步练习。2023年【上海市安全员B证】考试题库及上海市安…

支出管理如何帮助企业抵御经营成本压力?

近日&#xff0c;国内中小企业协会发布最新中小企业发展指数情况&#xff0c;虽然经济持续恢复向好&#xff0c;但依然面临困难和挑战。企业经营成本压力不减&#xff0c;效益状况总体仍不乐观。 许多中小企业采取被动措施&#xff0c;想方设法削减成本。然而&#xff0c;如果…

怎样培养孩子的好习惯

好习惯是孩子成长道路上不可或缺的伴侣。那么&#xff0c;如何在孩子成长的关键时期培养他们良好的习惯呢&#xff1f;以下是几点建议&#xff1a; 一、以身作则&#xff0c;成为孩子的榜样 父母是孩子的第一任老师和榜样。要求孩子做到的事情&#xff0c;自己首先要做到。只有…

常用的系统存储过程

exec sp_databases ---列出服务器上所有的数据库信息 exec sp_help student ---查看学生表中的所有信息 exec sp_renamedb Myschool,MySchools ---更改数据库的名称 需要两个参数 一个是原来数据库的名称 一个是要改为的数据库名称 消息框显示&#xff1a;数据库 名称 MyS…

Docker——2. Docker基础

1. 常见命令 不用重复使用docker run命令&#xff0c;这是创建容器命令&#xff0c;启动容器应该是docker start&#xff1b; docker ps 查看进程运行状态&#xff1b; docker rmi 删除镜像、rm 删除容器&#xff1b; docker logs 查看日志、docker exec 执行命令进入容器内部&…

c#读取XML文件实现晶圆wafermapping显示demo计算电机坐标以便控制电机移动

c#读取XML文件实现晶圆wafermapping显示 功能&#xff1a; 1.读取XML文件&#xff0c;显示mapping图 2.在mapping视图图标移动&#xff0c;实时查看bincode,x,y索引与计算的电机坐标 3.通过设置wafer放在平台的位置x,y轴电机编码值&#xff0c;相机在wafer的中心位置&#…

jstree组件的使用详细教程,部分案例( PHP / fastAdmin )

jstree 组件的使用。 简介&#xff1a;JsTree是一个jquery的插件&#xff0c;它提交一个非常友好并且强大的交互性的树&#xff0c;并且是完全免费或开源的&#xff08;MIT 许可&#xff09;。Jstree技持Html 或 json格式的的数据&#xff0c; 或者是ajax方式的动态请求加载数…

基于ssm的汽车服务商城系统设计与实现论文

摘 要 本课题是根据用户的需要以及网络的优势建立的一个基于Vue的汽车服务商城系统&#xff0c;来更好的为用户提供服务。 本基于Vue的汽车服务商城系统应用Java技术&#xff0c;MYSQL数据库存储数据&#xff0c;基于SSMVue框架开发。在网站的整个开发过程中&#xff0c;首先对…

关于响应式布局,你需要了解的知识点

什么是响应式布局&#xff1f; 响应式布局&#xff0c;就是根据不同设备展示不同的布局&#xff0c;以免更方便用户浏览页面。 举个很简单的例子&#xff0c;我们在电脑上浏览网页&#xff0c;屏幕非常大&#xff0c;这时候可能采用的是如下图所示的布局方式。这种布局方式很宽…

[陇剑杯 2021]日志分析

[陇剑杯 2021]日志分析 题目做法及思路解析&#xff08;个人分享&#xff09; 问一&#xff1a;单位某应用程序被攻击&#xff0c;请分析日志&#xff0c;进行作答&#xff1a; 网络存在源码泄漏&#xff0c;源码文件名是_____________。(请提交带有文件后缀的文件名&…

vue项目debugger调试看不到源码

vue项目debugger调试看不到源码 引用地址&#xff1a;vue项目debugger调试看不到源码_hua_ban_yu的博客-CSDN博客_vue项目网页源代码查看不了 在开发vue项目时&#xff0c;不知为啥进行debug但是查看不到页面源代码&#xff0c;尝试过很多方法&#xff0c;最后在看到大神相关…

WSL的安装与使用 (超详细图文版安装教程)

安装与使用 Windows Subsystem for Linux - WSL 安装&#xff08;两种方式均可实现WSL的安装&#xff09;图文版安装文字版安装步骤1&#xff1a;启用 WSL 功能步骤2&#xff1a;选择并安装 Linux 发行版步骤3&#xff1a;配置和使用 WSL步骤4&#xff1a;与 Windows 的互操作性…

探索高级AJAX技术:深入研究异步请求和响应处理

大家有关于JavaScript知识点不知道可以去 &#x1f389;博客主页&#xff1a;阿猫的故乡 &#x1f389;系列专栏&#xff1a;JavaScript专题栏 &#x1f389;ajax专栏&#xff1a;ajax知识点 &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 目录…

Docker-consul容器服务自动发现与注册

什么叫微服务或者注册与发现&#xff1f; 是一种分布式管理系统&#xff0c;定位服务的方法。 在传统的架构中&#xff0c;应用程序之间直连到已知的服务。 已知的服务&#xff1a;设备提供的网络、IP地址、基于tcp/ip端口 基于现微服务部署&#xff0c;服务的动态性&#…

在MDK开发调试过程中,发现程序正常运行,但是打断点无法进入。

在MDK开发调试过程中&#xff0c;发现程序正常运行&#xff0c;但是打断点无法进入。 打断点无法进入&#xff1a; 程序无法进行&#xff1a; 查找问题&#xff1a;这些都已经配置 上面都已经配置&#xff0c;最终发现: 勾选后进入断点成功。

以csv为源 flink 创建paimon 临时表相关 join 操作

目录 概述配置关键配置测试启动 kyuubi执行配置中的命令 bug解决bug01bug02 结束 概述 目标&#xff1a;生产中有需要外部源数据做paimon的数据源&#xff0c;生成临时表&#xff0c;以使用与现有正式表做相关统计及 join 操作。 环境&#xff1a;各组件版本如下 kyuubi 1.8…

Redis 过期删除策略、内存回收策略、单线程理解

不知从何开始Redis的内存淘汰策略也开始被人问及&#xff0c;卷&#xff01;真的是太卷了。难不成要我们去阅读Redis源码吗&#xff0c;其实问题的答案&#xff0c;在Redis中的配置文件中全有&#xff0c;不需要你阅读源码、这个东西就是个老八股&#xff0c;估计问这个东西是想…

微信小程序识别小程序码并传参

一、场景 连续看到几个类似关于小程序生成二维码场景的问题&#xff0c;分销的场景和单商品购买的页面居多 二、思路 #mermaid-svg-8CjFXSzutuF1OvO8 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-8CjFXSzutuF1…

中小企业业财融合策略(2):财务赋能,如何支持业务经营?

上一文《中小企业业财融合(1):把财务从琐碎的凭证处理、核算中解放出来!》&#xff0c;我们提出了财务升级的背景以及必要性&#xff0c;本篇我们就财务赋能&#xff0c;如何支持业务经营&#xff1f;提出一些简要的看法&#xff0c;希望对大家有所帮助。 一、财务赋能&#x…

com.sun.org.apache.xerces.internal.impl.dv.util.Base64

com.sun.org.apache.xerces.internal.impl.dv.util.Base64 Access restriction: The type Base64 is not API (restriction on required library D:\Java\jdk1.8.0_341\jre\lib\rt.jar) Maven Update Project 虽然没错误了&#xff0c;但是有警告&#xff0c;好奇&#xff1f;…