首页 > 编程语言 >单个python文件代码的车牌检测系统 使用pyqt做界面进行车牌检测,可以保存结果到excel文件

单个python文件代码的车牌检测系统 使用pyqt做界面进行车牌检测,可以保存结果到excel文件

时间:2024-06-07 14:29:34浏览次数:17  
标签:文件 img point 检测 self cv2 label 车牌 card

融合了hyperlpr3和opencv 来检测车牌

通过图片检测车牌的系统,使用了pyqt和hyperlpr3结合来进行检测,可以保存检测的结果到excel文件
 

亲自测试修改代码,运行正常并且不依赖百度网络api, 纯本地运行,融合了2个车牌检测模型,

第一个模型使用opencv 来模糊图像,然后进行边缘检测和轮廓检测,然后通过几何条件,矩形长宽,比例过滤轮廓,最后通过颜色过滤轮廓,得到车牌的轮廓区域;

第二个模型使用 vlpr 库来进行车牌检测;

然后把结果显示在左侧,并可以对结果进行输出。

我的工作是融合了两个车牌检测的模型,并且把所以的代码融合到了一个python文件,使得系统更加精简,容易修改。

# -*- coding: utf-8 -*-



# 通过图片检测车牌的系统,使用了pyqt和hyperlpr3结合来进行检测,可以保存检测的结果到excel文件


import sys, os, xlwt, time, json  #
from sys import exit, argv
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import *

from PIL import Image, ImageDraw, ImageFont
import numpy as np

import cv2
import hyperlpr3 as lpr3
# pip install hyperlpr3 -i https://pypi.tuna.tsinghua.edu.cn/simple/

import cv2 as cv

big = False

def drawRectBox(image, rect, addText, fontC):
    cv.rectangle(image, (int(round(rect[0])), int(round(rect[1]))),
                 (int(round(rect[2]) + 8), int(round(rect[3]) + 8)),
                 (0, 0, 255), 2)
    cv.rectangle(image, (int(rect[0] - 1), int(rect[1]) - 16), (int(rect[0] + 75), int(rect[1])), (0, 0, 255), -1, cv.LINE_AA)
    img = Image.fromarray(image)
    draw = ImageDraw.Draw(img)
    draw.text((int(rect[0] + 1), int(rect[1] - 16)), addText, (255, 255, 255), font=fontC)
    imagex = np.array(img)
    return imagex



# Instantiate object
catcher = lpr3.LicensePlateCatcher()


class PlateRecognition():


    def __init__(self):
        self.MAX_WIDTH = 1000  # 原始图片最大宽度
        self.Min_Area = 2000  # 车牌区域允许最大面积
        self.PROVINCE_START = 1000

        # 省份代码保存在provinces.json中
        self.provinces = json.loads('["zh_cuan", "川", "zh_e", "鄂", "zh_gan", "赣", "zh_gan1", "甘", "zh_gui", "贵", "zh_gui1", "桂", "zh_hei", "黑", "zh_hu", "沪", "zh_ji", "冀", "zh_jin", "津", "zh_jing", "京", "zh_jl", "吉", "zh_liao", "辽", "zh_lu", "鲁", "zh_meng", "蒙", "zh_min", "闽", "zh_ning", "宁", "zh_qing", "靑", "zh_qiong", "琼", "zh_shan", "陕", "zh_su", "苏", "zh_sx", "晋", "zh_wan", "皖", "zh_xiang", "湘", "zh_xin", "新", "zh_yu", "豫", "zh_yu1", "渝", "zh_yue", "粤", "zh_yun", "云", "zh_zang", "藏", "zh_zhe", "浙"]')

        # 车牌类型保存在cardtype.json中,便于调整
        self.cardtype = json.loads('{"blue": "蓝色牌照", "green": "绿色牌照", "yellow": "黄色牌照"}')

        # 字母所代表的地区保存在Prefecture.json中,便于更新
        self.Prefecture = json.loads('{"冀": {"A": ["河北省", "石家庄市"], "B": ["河北省", "唐山市"], "C": ["河北省", "秦皇岛市"], "D": ["河北省", "邯郸市"], "E": ["河北省", "邢台市"], "F": ["河北省", "保定市"], "G": ["河北省", "张家口市"], "H": ["河北省", "承德市"], "J": ["河北省", "沧州市"], "R": ["河北省", "廊坊市"], "S": ["河北省", "沧州市"], "T": ["河北省", "衡水市"]}, "辽": {"A": ["辽宁省", "沈阳市"], "B": ["辽宁省", "大连市"], "C": ["辽宁省", "鞍山市"], "D": ["辽宁省", "抚顺市"], "E": ["辽宁省", "本溪市"], "F": ["辽宁省", "丹东市"], "G": ["辽宁省", "锦州市"], "H": ["辽宁省", "营口市"], "J": ["辽宁省", "阜新市"], "K": ["辽宁省", "辽阳市"], "L": ["辽宁省", "盘锦市"], "M": ["辽宁省", "铁岭市"], "N": ["辽宁省", "朝阳市"], "P": ["辽宁省", "葫芦岛市"]}, "皖": {"A": ["安徽省", "合肥市"], "B": ["安徽省", "芜湖市"], "C": ["安徽省", "蚌埠市"], "D": ["安徽省", "淮南市"], "E": ["安徽省", "马鞍山市"], "F": ["安徽省", "淮北市"], "G": ["安徽省", "铜陵市"], "H": ["安徽省", "安庆市"], "J": ["安徽省", "黄山市"], "K": ["安徽省", "阜阳市"], "L": ["安徽省", "宿州市"], "M": ["安徽省", "滁州市"], "N": ["安徽省", "六安市"], "P": ["安徽省", "宣城市"], "Q": ["安徽省", "巢湖市"], "R": ["安徽省", "池州市"], "S": ["安徽省", "亳州市"]}, "苏": {"A": ["江苏省", "南京市"], "B": ["江苏省", "无锡市"], "C": ["江苏省", "徐州市"], "D": ["江苏省", "常州市"], "E": ["江苏省", "苏州市"], "F": ["江苏省", "南通市"], "G": ["江苏省", "连云港市"], "H": ["江苏省", "淮安市"], "J": ["江苏省", "盐城市"], "K": ["江苏省", "扬州市"], "L": ["江苏省", "镇江市"], "M": ["江苏省", "泰州市"], "N": ["江苏省", "宿迁市"]}, "鄂": {"A": ["湖北省", "武汉市"], "B": ["湖北省", "黄石市"], "C": ["湖北省", "十堰市"], "D": ["湖北省", "荆州市"], "E": ["湖北省", "宜昌市"], "F": ["湖北省", "襄樊市"], "G": ["湖北省", "鄂州市"], "H": ["湖北省", "荆门市"], "J": ["湖北省", "黄冈市"], "K": ["湖北省", "孝感市"], "L": ["湖北省", "咸宁市"], "M": ["湖北省", "仙桃市"], "N": ["湖北省", "潜江市"], "P": ["湖北省", "神农架林区"], "Q": ["湖北省", "恩施土家族苗族自治州"], "R": ["湖北省", "天门市"], "S": ["湖北省", "随州市"]}, "晋": {"A": ["山西省", "太原市"], "B": ["山西省", "大同市"], "C": ["山西省", "阳泉市"], "D": ["山西省", "长治市"], "E": ["山西省", "晋城市"], "F": ["山西省", "朔州市"], "H": ["山西省", "忻州市"], "J": ["山西省", "吕梁市"], "K": ["山西省", "晋中市"], "L": ["山西省", "临汾市"], "M": ["山西省", "运城市"]}, "吉": {"A": ["吉林省", "长春市"], "B": ["吉林省", "吉林市"], "C": ["吉林省", "四平市"], "D": ["吉林省", "辽源市"], "E": ["吉林省", "通化市"], "F": ["吉林省", "白山市"], "G": ["吉林省", "白城市"], "H": ["吉林省", "延边朝鲜族自治州"], "J": ["吉林省", "松原市"], "K": ["吉林省", "长白朝鲜族自治县"]}, "粤": {"A": ["广东省", "广州市"], "B": ["广东省", "深圳市"], "C": ["广东省", "珠海市"], "D": ["广东省", "汕头市"], "E": ["广东省", "佛山市"], "F": ["广东省", "韶关市"], "G": ["广东省", "湛江市"], "H": ["广东省", "肇庆市"], "J": ["广东省", "江门市"], "K": ["广东省", "茂名市"], "L": ["广东省", "惠州市"], "M": ["广东省", "梅州市"], "N": ["广东省", "汕尾市"], "P": ["广东省", "河源市"], "Q": ["广东省", "阳江市"], "R": ["广东省", "清远市"], "S": ["广东省", "东莞市"], "T": ["广东省", "中山市"], "U": ["广东省", "潮州市"], "V": ["广东省", "揭阳市"], "W": ["广东省", "云浮市"], "X": ["广东省", "顺德区"], "Y": ["广东省", "南海区"], "Z": ["广东省", "港澳进入内地车辆"]}, "藏": {"A": ["西藏自治区", "拉萨市"], "B": ["西藏自治区", "昌都地区"], "C": ["西藏自治区", "山南地区"], "D": ["西藏自治区", "日喀则地区"], "E": ["西藏自治区", "那曲地区"], "F": ["西藏自治区", "阿里地区"], "G": ["西藏自治区", "林芝地区"], "H": ["西藏自治区", "驻四川省天全县车辆管理所"], "J": ["西藏自治区", "驻青海省格尔木市车辆管理所"]}, "渝": {"A": ["重庆市"], "B": ["重庆市"], "C": ["重庆市"], "F": ["重庆市"], "G": ["重庆市"], "H": ["重庆市"]}, "沪": {"A": ["上海市"], "B": ["上海市"], "C": ["上海市"], "D": ["上海市"], "R": ["上海市"]}, "豫": {"A": ["河南省", "郑州市"], "B": ["河南省", "开封市"], "C": ["河南省", "洛阳市"], "D": ["河南省", "平顶山市"], "E": ["河南省", "安阳市"], "F": ["河南省", "鹤壁市"], "G": ["河南省", "新乡市"], "H": ["河南省", "焦作市"], "J": ["河南省", "濮阳市"], "K": ["河南省", "许昌市"], "L": ["河南省", "漯河市"], "M": ["河南省", "三门峡市"], "N": ["河南省", "商丘市"], "P": ["河南省", "周口市"], "Q": ["河南省", "驻马店市"], "R": ["河南省", "南阳市"], "S": ["河南省", "信阳市"], "U": ["河南省", "济源市"]}, "黑": {"A": ["黑龙江省", "哈尔滨市"], "B": ["黑龙江省", "齐齐哈尔市"], "C": ["黑龙江省", "牡丹江市"], "D": ["黑龙江省", "佳木斯市"], "E": ["黑龙江省", "大庆市"], "F": ["黑龙江省", "伊春市"], "G": ["黑龙江省", "鸡西市"], "H": ["黑龙江省", "鹤岗市"], "J": ["黑龙江省", "双鸭山市"], "K": ["黑龙江省", "七台河市"], "L": ["黑龙江省", "松花江地区(已并入哈尔滨市,车牌未改)"], "M": ["黑龙江省", "绥化市"], "N": ["黑龙江省", "黑河市"], "P": ["黑龙江省", "大兴安岭地区"], "R": ["黑龙江省", "农垦系统"]}, "鲁": {"A": ["山东省", "济南市"], "B": ["山东省", "青岛市"], "C": ["山东省", "淄博市"], "D": ["山东省", "枣庄市"], "E": ["山东省", "东营市"], "F": ["山东省", "烟台市"], "G": ["山东省", "潍坊市"], "H": ["山东省", "济宁市"], "J": ["山东省", "泰安市"], "K": ["山东省", "威海市"], "L": ["山东省", "日照市"], "M": ["山东省", "滨州市"], "N": ["山东省", "德州市"], "P": ["山东省", "聊城市"], "Q": ["山东省", "临沂市"], "R": ["山东省", "菏泽市"], "S": ["山东省", "莱芜市"], "U": ["山东省", "青岛市"], "V": ["山东省", "潍坊市"], "Y": ["山东省", "烟台市"]}, "浙": {"A": ["浙江省", "杭州市"], "B": ["浙江省", "宁波市"], "C": ["浙江省", "温州市"], "D": ["浙江省", "绍兴市"], "E": ["浙江省", "湖州市"], "F": ["浙江省", "嘉兴市"], "G": ["浙江省", "金华市"], "H": ["浙江省", "衢州市"], "J": ["浙江省", "台州市"], "K": ["浙江省", "丽水市"], "L": ["浙江省", "舟山市"]}, "桂": {"A": ["广西省", "南宁市"], "B": ["广西省", "柳州市"], "C": ["广西省", "桂林市"], "D": ["广西省", "梧州市"], "E": ["广西省", "北海市"], "F": ["广西省", "崇左市"], "G": ["广西省", "来宾市"], "H": ["广西省", "桂林市"], "J": ["广西省", "贺州市"], "K": ["广西省", "玉林市"], "M": ["广西省", "河池市"], "N": ["广西省", "钦州市"], "P": ["广西省", "防城港市"], "R": ["广西省", "贵港市"]}, "蒙": {"A": ["内蒙古自治区", "呼和浩特市"], "B": ["内蒙古自治区", "包头市"], "C": ["内蒙古自治区", "乌海市"], "D": ["内蒙古自治区", "赤峰市"], "E": ["内蒙古自治区", "呼伦贝尔市"], "F": ["内蒙古自治区", "兴安盟"], "G": ["内蒙古自治区", "通辽市"], "H": ["内蒙古自治区", "锡林郭勒盟"], "J": ["内蒙古自治区", "乌兰察布市"], "K": ["内蒙古自治区", "鄂尔多斯市"], "L": ["内蒙古自治区", "巴彦淖尔市"], "M": ["内蒙古自治区", "阿拉善盟"]}, "闽": {"A": ["福建省", "福州市"], "B": ["福建省", "莆田市"], "C": ["福建省", "泉州市"], "D": ["福建省", "厦门市"], "E": ["福建省", "漳州市"], "F": ["福建省", "龙岩市"], "G": ["福建省", "三明市"], "H": ["福建省", "南平市"], "J": ["福建省", "宁德市"], "K": ["福建省", "省直系统"]}, "川": {"A": ["四川省", "成都市"], "B": ["四川省", "绵阳市"], "C": ["四川省", "自贡市"], "D": ["四川省", "攀枝花市"], "E": ["四川省", "泸州市"], "F": ["四川省", "德阳市"], "H": ["四川省", "广元市"], "J": ["四川省", "遂宁市"], "K": ["四川省", "内江市"], "L": ["四川省", "乐山市"], "M": ["四川省", "资阳市"], "Q": ["四川省", "宜宾市"], "R": ["四川省", "南充市"], "S": ["四川省", "达州市"], "T": ["四川省", "雅安市"], "U": ["四川省", "阿坝藏族羌族自治州"], "V": ["四川省", "甘孜藏族自治州"], "W": ["四川省", "凉山彝族自治州"], "X": ["四川省", "广安市"], "Y": ["四川省", "巴中市"], "Z": ["四川省", "眉山市"]}, "琼": {"A": ["海南省", "海口市"], "B": ["海南省", "三亚市"], "C": ["海南省", "琼海市"], "D": ["海南省", "五指山市"], "E": ["海南省", "洋浦开发区"]}, "京": {"A": ["北京市"], "B": ["北京市"], "C": ["北京市"], "D": ["北京市"], "E": ["北京市"], "F": ["北京市"], "G": ["北京市"], "H": ["北京市"], "J": ["北京市"], "K": ["北京市"], "L": ["北京市"], "M": ["北京市"], "N": ["北京市"], "P": ["北京市"], "Q": ["北京市"]}, "云": {"A": ["云南省", "昆明市"], "C": ["云南省", "昭通市"], "D": ["云南省", "曲靖市"], "E": ["云南省", "楚雄彝族自治州"], "F": ["云南省", "玉溪市"], "G": ["云南省", "红河哈尼族彝族自治州"], "H": ["云南省", "文山壮族苗族自治州"], "J": ["云南省", "思茅区"], "K": ["云南省", "西双版纳傣族自治州"], "L": ["云南省", "大理白族自治州"], "M": ["云南省", "保山市"], "N": ["云南省", "德宏傣族景颇族自治州"], "P": ["云南省", "丽江市"], "Q": ["云南省", "怒江傈僳族自治州"], "R": ["云南省", "迪庆藏族自治州"], "S": ["云南省", "临沧市"]}, "湘": {"A": ["湖南省", "长沙市"], "B": ["湖南省", "株洲市"], "C": ["湖南省", "湘潭市"], "D": ["湖南省", "衡阳市"], "E": ["湖南省", "邵阳市"], "F": ["湖南省", "岳阳市"], "G": ["湖南省", "张家界市"], "H": ["湖南省", "益阳市"], "J": ["湖南省", "常德市"], "K": ["湖南省", "娄底市"], "L": ["湖南省", "郴州市"], "M": ["湖南省", "永州市"], "N": ["湖南省", "怀化市"], "U": ["湖南省", "湘西土家族苗族自治州"]}, "新": {"A": ["新疆维吾尔自治区", "乌鲁木齐市"], "B": ["新疆维吾尔自治区", "昌吉回族自治州"], "C": ["新疆维吾尔自治区", "石河子市"], "D": ["新疆维吾尔自治区", "奎屯市"], "E": ["新疆维吾尔自治区", "博尔塔拉蒙古自治州"], "F": ["新疆维吾尔自治区", "伊犁哈萨克自治州"], "G": ["新疆维吾尔自治区", "塔城地区"], "H": ["新疆维吾尔自治区", "阿勒泰地区"], "J": ["新疆维吾尔自治区", "克拉玛依市"], "K": ["新疆维吾尔自治区", "吐鲁番地区"], "L": ["新疆维吾尔自治区", "哈密地区"], "M": ["新疆维吾尔自治区", "巴音郭愣蒙古自治州"], "N": ["新疆维吾尔自治区", "阿克苏地区"], "P": ["新疆维吾尔自治区", "克孜勒苏柯尔克孜自治州"], "Q": ["新疆维吾尔自治区", "喀什地区"], "R": ["新疆维吾尔自治区", "和田地区"]}, "赣": {"A": ["江西省", "南昌市"], "B": ["江西省", "赣州市"], "C": ["江西省", "宜春市"], "D": ["江西省", "吉安市"], "E": ["江西省", "上饶市"], "F": ["江西省", "抚州市"], "G": ["江西省", "九江市"], "H": ["江西省", "景德镇市"], "J": ["江西省", "萍乡市"], "K": ["江西省", "新余市"], "L": ["江西省", "鹰潭市"], "M": ["江西省", "南昌市"]}, "甘": {"A": ["甘肃省", "兰州市"], "B": ["甘肃省", "嘉峪关市"], "C": ["甘肃省", "金昌市"], "D": ["甘肃省", "白银市"], "E": ["甘肃省", "天水市"], "F": ["甘肃省", "酒泉市"], "G": ["甘肃省", "张掖市"], "H": ["甘肃省", "武威市"], "J": ["甘肃省", "定西市"], "K": ["甘肃省", "陇南市"], "L": ["甘肃省", "平凉市"], "M": ["甘肃省", "庆阳市"], "N": ["甘肃省", "临夏回族自治州"], "P": ["甘肃省", "甘南藏族自治州"]}, "陕": {"A": ["陕西省", "西安市"], "B": ["陕西省", "铜川市"], "C": ["陕西省", "宝鸡市"], "D": ["陕西省", "咸阳市"], "E": ["陕西省", "渭南市"], "F": ["陕西省", "汉中市"], "G": ["陕西省", "安康市"], "H": ["陕西省", "商洛市"], "J": ["陕西省", "延安市"], "K": ["陕西省", "榆林市"], "V": ["陕西省", "杨凌区"]}, "贵": {"A": ["贵族省", "贵阳市"], "B": ["贵族省", "六盘水市"], "C": ["贵族省", "遵义市"], "D": ["贵族省", "铜仁地区"], "E": ["贵族省", "黔西南布依族苗族自治州"], "F": ["贵族省", "毕节地区"], "G": ["贵族省", "安顺市"], "H": ["贵族省", "黔东南苗族侗族自治州"], "J": ["贵族省", "黔南布依族苗族自治州"]}, "青": {"A": ["青海省", "西宁市"], "B": ["青海省", "海东地区"], "C": ["青海省", "海北藏族自治州"], "D": ["青海省", "黄南藏族自治州"], "E": ["青海省", "海南藏族自治州"], "F": ["青海省", "果洛藏族自治州"], "G": ["青海省", "玉树藏族自治州"], "H": ["青海省", "海西蒙古族藏族自治州"]}, "宁": {"A": ["宁夏回族自治区", "银川市"], "B": ["宁夏回族自治区", "石嘴山市"], "C": ["宁夏回族自治区", "银南市"], "D": ["宁夏回族自治区", "固原市"], "E": ["宁夏回族自治区", "中卫市"]}, "津": {"A": ["天津市"], "B": ["天津市"], "C": ["天津市"], "D": ["天津市"], "E": ["天津市"], "F": ["天津市"], "G": ["天津市"], "H": ["天津市"]}}')

        # 车牌识别的部分参数保存在js中,便于根据图片分辨率做调整
        # f = open('config.js')
        j = json.loads('{"open":1, "blur":3, "morphologyr":4, "morphologyc":19, "col_num_limit":10, "row_num_limit":21 }')
        # for c in j["config"]:
        if j["open"]:
            self.cfg = j.copy()
            # break

    def __del__(self):
        pass

    # 读取图片文件
    def __imreadex(self, filename):
        return cv2.imdecode(np.fromfile(filename, dtype=np.uint8), cv2.IMREAD_COLOR)

    def __point_limit(self, point):
        if point[0] < 0:
            point[0] = 0
        if point[1] < 0:
            point[1] = 0


    def accurate_place(self, card_img_hsv, limit1, limit2, color):
        row_num, col_num = card_img_hsv.shape[:2]
        xl = col_num
        xr = 0
        yh = 0
        yl = row_num
        # col_num_limit = self.cfg["col_num_limit"]
        row_num_limit = self.cfg["row_num_limit"]
        col_num_limit = col_num * 0.8 if color != "green" else col_num * 0.5  # 绿色有渐变
        for i in range(row_num):
            count = 0
            for j in range(col_num):
                H = card_img_hsv.item(i, j, 0)
                S = card_img_hsv.item(i, j, 1)
                V = card_img_hsv.item(i, j, 2)
                if limit1 < H <= limit2 and 34 < S and 46 < V:
                    count += 1
            if count > col_num_limit:
                if yl > i:
                    yl = i
                if yh < i:
                    yh = i
        for j in range(col_num):
            count = 0
            for i in range(row_num):
                H = card_img_hsv.item(i, j, 0)
                S = card_img_hsv.item(i, j, 1)
                V = card_img_hsv.item(i, j, 2)
                if limit1 < H <= limit2 and 34 < S and 46 < V:
                    count += 1
            if count > row_num - row_num_limit:
                if xl > j:
                    xl = j
                if xr < j:
                    xr = j
        return xl, xr, yh, yl

    # 预处理
    def pretreatment(self, car_pic):
        if type(car_pic) == type(""):
            img = self.__imreadex(car_pic)
        else:
            img = car_pic
        pic_hight, pic_width = img.shape[:2]

        if pic_width > self.MAX_WIDTH:
            resize_rate = self.MAX_WIDTH / pic_width
            img = cv2.resize(img, (self.MAX_WIDTH, int(pic_hight * resize_rate)),
                             interpolation=cv2.INTER_AREA)  # 图片分辨率调整
        # cv2.imshow('Image', img)

        blur = self.cfg["blur"]
        # 高斯去噪
        if blur > 0:
            img = cv2.GaussianBlur(img, (blur, blur), 0)
        oldimg = img
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # cv2.imshow('GaussianBlur', img)

        kernel = np.ones((20, 20), np.uint8)
        img_opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)  # 开运算
        img_opening = cv2.addWeighted(img, 1, img_opening, -1, 0);  # 与上一次开运算结果融合
        # cv2.imshow('img_opening', img_opening)

        # 找到图像边缘
        ret, img_thresh = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)  # 二值化
        img_edge = cv2.Canny(img_thresh, 100, 200)
        # cv2.imshow('img_edge', img_edge)

        # 使用开运算和闭运算让图像边缘成为一个整体
        kernel = np.ones((self.cfg["morphologyr"], self.cfg["morphologyc"]), np.uint8)
        img_edge1 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, kernel)  # 闭运算
        img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel)  # 开运算
        # cv2.imshow('img_edge2', img_edge2)

        # cv2.imwrite('./edge2.png', img_edge2)

        # 查找图像边缘整体形成的矩形区域,可能有很多,车牌就在其中一个矩形区域中
        # image, contours, hierarchy = cv2.findContours(img_edge2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        contours, hierarchy = cv2.findContours(img_edge2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        contours = [cnt for cnt in contours if cv2.contourArea(cnt) > self.Min_Area]
        # print(contours[0])

        # 逐个排除不是车牌的矩形区域
        car_contours = []
        for cnt in contours:
            # 框选 生成最小外接矩形 返回值(中心(x,y), (宽,高), 旋转角度)
            rect = cv2.minAreaRect(cnt)
            # print('宽高:',rect[1])
            area_width, area_height = rect[1]
            # 选择宽大于高的区域
            if area_width < area_height:
                area_width, area_height = area_height, area_width
            wh_ratio = area_width / area_height
            # print('宽高比:',wh_ratio)
            # 要求矩形区域长宽比在2到5.5之间,2到5.5是车牌的长宽比,其余的矩形排除
            if wh_ratio > 2 and wh_ratio < 5.5:
                car_contours.append(rect)
                box = cv2.boxPoints(rect)
                box = np.int0(box)
            # 框出所有可能的矩形
            # oldimg = cv2.drawContours(img, [box], 0, (0, 0, 255), 2)
            # cv2.imshow("Test",oldimg )
            # print(car_contours)

        # 矩形区域可能是倾斜的矩形,需要矫正,以便使用颜色定位
        card_imgs = []
        for rect in car_contours:
            if rect[2] > -1 and rect[2] < 1:  # 创造角度,使得左、高、右、低拿到正确的值
                angle = 1
            else:
                angle = rect[2]
            rect = (rect[0], (rect[1][0] + 5, rect[1][1] + 5), angle)  # 扩大范围,避免车牌边缘被排除
            box = cv2.boxPoints(rect)
            heigth_point = right_point = [0, 0]
            left_point = low_point = [pic_width, pic_hight]
            for point in box:
                if left_point[0] > point[0]:
                    left_point = point
                if low_point[1] > point[1]:
                    low_point = point
                if heigth_point[1] < point[1]:
                    heigth_point = point
                if right_point[0] < point[0]:
                    right_point = point

            if left_point[1] <= right_point[1]:  # 正角度
                new_right_point = [right_point[0], heigth_point[1]]
                pts2 = np.float32([left_point, heigth_point, new_right_point])  # 字符只是高度需要改变
                pts1 = np.float32([left_point, heigth_point, right_point])
                M = cv2.getAffineTransform(pts1, pts2)
                dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight))
                self.__point_limit(new_right_point)
                self.__point_limit(heigth_point)
                self.__point_limit(left_point)
                card_img = dst[int(left_point[1]):int(heigth_point[1]), int(left_point[0]):int(new_right_point[0])]
                card_imgs.append(card_img)

            elif left_point[1] > right_point[1]:  # 负角度

                new_left_point = [left_point[0], heigth_point[1]]
                pts2 = np.float32([new_left_point, heigth_point, right_point])  # 字符只是高度需要改变
                pts1 = np.float32([left_point, heigth_point, right_point])
                M = cv2.getAffineTransform(pts1, pts2)
                dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight))
                self.__point_limit(right_point)
                self.__point_limit(heigth_point)
                self.__point_limit(new_left_point)
                card_img = dst[int(right_point[1]):int(heigth_point[1]), int(new_left_point[0]):int(right_point[0])]
                card_imgs.append(card_img)
        # cv2.imshow("card", card_imgs[0])

        # #____开始使用颜色定位,排除不是车牌的矩形,目前只识别蓝、绿、黄车牌
        colors = []
        for card_index, card_img in enumerate(card_imgs):
            green = yellow = blue = black = white = 0
            try:
                # 有转换失败的可能,原因来自于上面矫正矩形出错
                card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
            except:
                print('BGR转HSV失败')
                card_imgs = colors = None
                return card_imgs, colors

            if card_img_hsv is None:
                continue
            row_num, col_num = card_img_hsv.shape[:2]
            card_img_count = row_num * col_num

            # 确定车牌颜色
            for i in range(row_num):
                for j in range(col_num):
                    H = card_img_hsv.item(i, j, 0)
                    S = card_img_hsv.item(i, j, 1)
                    V = card_img_hsv.item(i, j, 2)
                    if 11 < H <= 34 and S > 34:  # 图片分辨率调整
                        yellow += 1
                    elif 35 < H <= 99 and S > 34:  # 图片分辨率调整
                        green += 1
                    elif 99 < H <= 124 and S > 34:  # 图片分辨率调整
                        blue += 1

                    if 0 < H < 180 and 0 < S < 255 and 0 < V < 46:
                        black += 1
                    elif 0 < H < 180 and 0 < S < 43 and 221 < V < 225:
                        white += 1
            color = "no"
            # print('黄:{:<6}绿:{:<6}蓝:{:<6}'.format(yellow,green,blue))

            limit1 = limit2 = 0
            if yellow * 2 >= card_img_count:
                color = "yellow"
                limit1 = 11
                limit2 = 34  # 有的图片有色偏偏绿
            elif green * 2 >= card_img_count:
                color = "green"
                limit1 = 35
                limit2 = 99
            elif blue * 2 >= card_img_count:
                color = "blue"
                limit1 = 100
                limit2 = 124  # 有的图片有色偏偏紫
            elif black + white >= card_img_count * 0.7:
                color = "bw"
            # print(color)
            colors.append(color)
            # print(blue, green, yellow, black, white, card_img_count)
            if limit1 == 0:
                continue

            # 根据车牌颜色再定位,缩小边缘非车牌边界
            xl, xr, yh, yl = self.accurate_place(card_img_hsv, limit1, limit2, color)
            if yl == yh and xl == xr:
                continue
            need_accurate = False
            if yl >= yh:
                yl = 0
                yh = row_num
                need_accurate = True
            if xl >= xr:
                xl = 0
                xr = col_num
                need_accurate = True
            card_imgs[card_index] = card_img[yl:yh, xl:xr] \
                if color != "green" or yl < (yh - yl) // 4 else card_img[yl - (yh - yl) // 4:yh, xl:xr]
            if need_accurate:  # 可能x或y方向未缩小,需要再试一次
                card_img = card_imgs[card_index]
                card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
                xl, xr, yh, yl = self.accurate_place(card_img_hsv, limit1, limit2, color)
                if yl == yh and xl == xr:
                    continue
                if yl >= yh:
                    yl = 0
                    yh = row_num
                if xl >= xr:
                    xl = 0
                    xr = col_num
            card_imgs[card_index] = card_img[yl:yh, xl:xr] \
                if color != "green" or yl < (yh - yl) // 4 else card_img[yl - (yh - yl) // 4:yh, xl:xr]
        # cv2.imshow("result", card_imgs[0])
        # cv2.imwrite('1.jpg', card_imgs[0])
        # print('颜色识别结果:' + colors[0])
        return card_imgs, colors


PlateRecognition_example = PlateRecognition()


class Ui_MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.RowLength = 0
        self.Data = [['文件名称', '录入时间', '车牌号码', '车牌类型', '车牌信息']]
        # self.setupUi(MainWindow())
        self.cardtype = json.loads('{"blue": "蓝色牌照", "green": "绿色牌照", "yellow": "黄色牌照"}')

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1213, 670)
        MainWindow.setFixedSize(1213, 670)  # 设置窗体固定大小
        MainWindow.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)

        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
        self.scrollArea.setGeometry(QtCore.QRect(690, 40, 511, 460))
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 500, 489))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.label_0 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        self.label_0.setGeometry(QtCore.QRect(10, 10, 111, 20))
        font = QtGui.QFont()
        font.setPointSize(11)
        self.label_0.setFont(font)
        self.label_0.setObjectName("label_0")
        self.label = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        self.label.setGeometry(QtCore.QRect(10, 40, 481, 420))
        self.label.setObjectName("label")
        self.label.setAlignment(Qt.AlignCenter)
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.scrollArea_2 = QtWidgets.QScrollArea(self.centralwidget)
        self.scrollArea_2.setGeometry(QtCore.QRect(10, 10, 671, 631))
        self.scrollArea_2.setWidgetResizable(True)
        self.scrollArea_2.setObjectName("scrollArea_2")
        self.scrollAreaWidgetContents_1 = QtWidgets.QWidget()
        self.scrollAreaWidgetContents_1.setGeometry(QtCore.QRect(0, 0, 669, 629))
        self.scrollAreaWidgetContents_1.setObjectName("scrollAreaWidgetContents_1")
        self.label_1 = QtWidgets.QLabel(self.scrollAreaWidgetContents_1)
        self.label_1.setGeometry(QtCore.QRect(10, 10, 111, 20))
        font = QtGui.QFont()
        font.setPointSize(11)
        self.label_1.setFont(font)
        self.label_1.setObjectName("label_1")
        self.tableWidget = QtWidgets.QTableWidget(self.scrollAreaWidgetContents_1)
        self.tableWidget.setGeometry(QtCore.QRect(10, 40, 651, 581))  # 581))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(5)
        self.tableWidget.setColumnWidth(0, 140)  # 设置1列的宽度
        self.tableWidget.setColumnWidth(1, 130)  # 设置2列的宽度
        self.tableWidget.setColumnWidth(2, 110)  # 设置3列的宽度
        self.tableWidget.setColumnWidth(3, 90)  # 设置4列的宽度
        self.tableWidget.setColumnWidth(4, 181)  # 设置5列的宽度
        self.tableWidget.setHorizontalHeaderLabels(["图片名称", "录入时间", "车牌号码", "车牌类型", "车牌信息"])
        self.tableWidget.setRowCount(self.RowLength)
        self.tableWidget.verticalHeader().setVisible(False)  # 隐藏垂直表头)

        b = '''
                     color:white;
                     background:#2B2B2B;
                    '''
        # self.tableWidget.setStyleSheet(b)
        # self.tableWidget.setAlternatingRowColors(True)

        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tableWidget.raise_()
        self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_1)
        self.scrollArea_3 = QtWidgets.QScrollArea(self.centralwidget)
        self.scrollArea_3.setGeometry(QtCore.QRect(690, 510, 341, 131))
        self.scrollArea_3.setWidgetResizable(True)
        self.scrollArea_3.setObjectName("scrollArea_3")
        self.scrollAreaWidgetContents_3 = QtWidgets.QWidget()
        self.scrollAreaWidgetContents_3.setGeometry(QtCore.QRect(0, 0, 339, 129))
        self.scrollAreaWidgetContents_3.setObjectName("scrollAreaWidgetContents_3")
        self.label_2 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3)
        self.label_2.setGeometry(QtCore.QRect(10, 10, 111, 20))
        font = QtGui.QFont()
        font.setPointSize(11)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.scrollAreaWidgetContents_3)
        self.label_3.setGeometry(QtCore.QRect(10, 40, 321, 81))
        self.label_3.setObjectName("label_3")
        self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3)
        self.scrollArea_4 = QtWidgets.QScrollArea(self.centralwidget)
        self.scrollArea_4.setGeometry(QtCore.QRect(1040, 510, 161, 131))
        self.scrollArea_4.setWidgetResizable(True)
        self.scrollArea_4.setObjectName("scrollArea_4")
        self.scrollAreaWidgetContents_4 = QtWidgets.QWidget()
        self.scrollAreaWidgetContents_4.setGeometry(QtCore.QRect(0, 0, 159, 129))
        self.scrollAreaWidgetContents_4.setObjectName("scrollAreaWidgetContents_4")
        self.pushButton_2 = QtWidgets.QPushButton(self.scrollAreaWidgetContents_4)
        self.pushButton_2.setGeometry(QtCore.QRect(20, 50, 121, 31))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton = QtWidgets.QPushButton(self.scrollAreaWidgetContents_4)
        self.pushButton.setGeometry(QtCore.QRect(20, 90, 121, 31))
        self.pushButton.setObjectName("pushButton")
        self.label_4 = QtWidgets.QLabel(self.scrollAreaWidgetContents_4)
        self.label_4.setGeometry(QtCore.QRect(10, 10, 111, 20))
        font = QtGui.QFont()
        font.setPointSize(11)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.scrollArea_4.setWidget(self.scrollAreaWidgetContents_4)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.pushButton.clicked.connect(self.__openimage)  # 设置点击事件
        self.pushButton.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#2B2B2B;}''')
        self.pushButton_2.clicked.connect(self.__writeFiles)  # 设置点击事件
        self.pushButton_2.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#2B2B2B;}''')
        self.retranslateUi(MainWindow)


        self.close_widget = QtWidgets.QWidget(self.centralwidget)
        self.close_widget.setGeometry(QtCore.QRect(1130, 0, 90, 50))
        self.close_widget.setObjectName("close_widget")
        self.close_layout = QGridLayout()  # 创建左侧部件的网格布局层
        self.close_widget.setLayout(self.close_layout)  # 设置左侧部件布局为网格

        self.left_close = QPushButton("")  # 关闭按钮
        self.left_close.clicked.connect(self.close)
        self.left_visit = QPushButton("")  # 空白按钮
        self.left_visit.clicked.connect(MainWindow.big)
        self.left_mini = QPushButton("")  # 最小化按钮
        self.left_mini.clicked.connect(MainWindow.mini)
        self.close_layout.addWidget(self.left_mini, 0, 0, 1, 1)
        self.close_layout.addWidget(self.left_close, 0, 2, 1, 1)
        self.close_layout.addWidget(self.left_visit, 0, 1, 1, 1)
        self.left_close.setFixedSize(15, 15)  # 设置关闭按钮的大小
        self.left_visit.setFixedSize(15, 15)  # 设置按钮大小
        self.left_mini.setFixedSize(15, 15)  # 设置最小化按钮大小
        self.left_close.setStyleSheet(
            '''QPushButton{background:#F76677;border-radius:5px;}QPushButton:hover{background:red;}''')
        self.left_visit.setStyleSheet(
            '''QPushButton{background:#F7D674;border-radius:5px;}QPushButton:hover{background:yellow;}''')
        self.left_mini.setStyleSheet(
            '''QPushButton{background:#6DDF6D;border-radius:5px;}QPushButton:hover{background:green;}''')

        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.ProjectPath = os.getcwd()  # 获取当前工程文件位置

        self.centralwidget.setStyleSheet('''
             QWidget#centralwidget{
             color:white;
             background:#222225;
             border-top:1px solid #222225;
             border-bottom:1px solid #222225;
             border-right:1px solid #222225;
             border-left:1px solid #444444;
             border-top-left-radius:10px;
             border-top-right-radius:10px;
             border-bottom-left-radius:10px;
             border-bottom-right-radius:10px;
             }
             ''')
        sc = '''
             QWidget{
             color:white;
             background:#2B2B2B;
             border-top:1px solid #222225;
             border-bottom:1px solid #222225;
             border-right:1px solid #222225;
             border-left:1px solid #444444;
             border-top-left-radius:10px;
             border-top-right-radius:10px;
             border-bottom-left-radius:10px;
             border-bottom-right-radius:10px;
             }

             '''

        self.scrollAreaWidgetContents_1.setStyleSheet('''
             QWidget{
             color:black;
             background:#2B2B2B;
             border-top:1px solid #222225;
             border-bottom:1px solid #222225;
             border-right:1px solid #222225;
             border-left:1px solid #444444;
             border-top-left-radius:10px;
             border-top-right-radius:10px;
             border-bottom-left-radius:10px;
             border-bottom-right-radius:10px;
             }
                      QListWidget{background-color:#2B2B2B;color:#222225}
         /*垂直滚动条*/
         QScrollBar:vertical{
             width:12px;
             border:1px solid #2B2B2B;
             margin:0px,0px,0px,0px;
             padding-top:0px;
             padding-bottom:0px;
         }
         QScrollBar::handle:vertical{
             width:3px;
             background:#4B4B4B;
             min-height:3;
         }
         QScrollBar::handle:vertical:hover{
             background:#3F3F3F;
             border:0px #3F3F3F;
         }
         QScrollBar::sub-line:vertical{
             width:0px;
             border-image:url(:/Res/scroll_left.png);
             subcontrol-position:left;
         }
         QScrollBar::sub-line:vertical:hover{
             height:0px;
             background:#222225;
             subcontrol-position:top;
         }
         QScrollBar::add-line:vertical{
             height:0px;
             border-image:url(:/Res/scroll_down.png);
             subcontrol-position:bottom;
         }
         QScrollBar::add-line:vertical:hover{
             height:0px;
             background:#3F3F3F;
             subcontrol-position:bottom;
         }
         QScrollBar::add-page:vertical{
             background:#2B2B2B;
         }
         QScrollBar::sub-page:vertical{
             background:#2B2B2B;
         }
         QScrollBar::up-arrow:vertical{
             border-style:outset;
             border-width:0px;
         }
         QScrollBar::down-arrow:vertical{
             border-style:outset;
             border-width:0px;
         }

         QScrollBar:horizontal{
             height:12px;
             border:1px #2B2B2B;
             margin:0px,0px,0px,0px;
             padding-left:0px;
             padding-right:0px;
         }
         QScrollBar::handle:horizontal{
             height:16px;
             background:#4B4B4B;
             min-width:20;
         }
         QScrollBar::handle:horizontal:hover{
             background:#3F3F3F;
             border:0px #3F3F3F;
         }
         QScrollBar::sub-line:horizontal{
             width:0px;
             border-image:url(:/Res/scroll_left.png);
             subcontrol-position:left;
         }
         QScrollBar::sub-line:horizontal:hover{
             width:0px;
             background:#2B2B2B;
             subcontrol-position:left;
         }
         QScrollBar::add-line:horizontal{
             width:0px;
             border-image:url(:/Res/scroll_right.png);
             subcontrol-position:right;
         }
         QScrollBar::add-line:horizontal:hover{
             width:0px;
             background::#2B2B2B;
             subcontrol-position:right;
         }
         QScrollBar::add-page:horizontal{
                    background:#2B2B2B;
         }
         QScrollBar::sub-page:horizontal{
                     background:#2B2B2B;
         }
             ''')
        self.scrollAreaWidgetContents.setStyleSheet(sc)
        self.scrollAreaWidgetContents_3.setStyleSheet(sc)
        self.scrollAreaWidgetContents_4.setStyleSheet(sc)
        b =             '''
             color:white;
             background:#2B2B2B;
            '''
        self.label_0.setStyleSheet(b)
        self.label_1.setStyleSheet(b)
        self.label_2.setStyleSheet(b)
        self.label_3.setStyleSheet(b)


        MainWindow.setWindowOpacity(0.95)  # 设置窗口透明度
        MainWindow.setAttribute(Qt.WA_TranslucentBackground)
        MainWindow.setWindowFlag(Qt.FramelessWindowHint)  # 隐藏边框


    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "车牌识别系统"))
        self.label_0.setText(_translate("MainWindow", "原始图片:"))
        self.label.setText(_translate("MainWindow", ""))
        self.label_1.setText(_translate("MainWindow", "识别结果:"))
        self.label_2.setText(_translate("MainWindow", "车牌区域:"))
        self.label_3.setText(_translate("MainWindow", ""))
        self.pushButton.setText(_translate("MainWindow", "打开文件"))
        self.pushButton_2.setText(_translate("MainWindow", "导出数据"))
        self.label_4.setText(_translate("MainWindow", "事件:"))
        self.scrollAreaWidgetContents_1.show()

    # 识别
    def __vlpr(self, path):

        # image = cv2.imread(path)
        result = {}

        image = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR)
        resu = catcher(image)
        # [['京QF60F0', 0.99931663, 0, [137, 120, 319, 177]]]
        print(resu)
        # fontC = ImageFont.truetype("./platech.ttf", 14, 0)
        fontC = ImageFont.truetype("simsun.ttc", 14, 0)
        res, confi, box = resu[0][0], resu[0][1], resu[0][3]

        # 获取地域省份信息
        # license_result = response.json()['words_result']['number']
        # result['From'] = ''.join(self.Prefecture[license_result[0]][license_result[1]])

        image = drawRectBox(image, box, res, fontC)
        # cv.imshow('Stream', image)
        # c = cv.waitKey(0)

        # PR = PlateRecognition()
        # result = PR.get_license_plate(path)  # lonlon
        card_imgs, colors = PlateRecognition_example.pretreatment(path)

        if len(colors) == 0:
            result['InputTime'] = time.strftime("%Y-%m-%d %H:%M:%S")
            result['Type'] = "蓝色牌照"
            result['Picture'] = image
            result['Number'] = res
            result['From'] = '未知'
        else:
            result['InputTime'] = time.strftime("%Y-%m-%d %H:%M:%S")
            result['Type'] = self.cardtype[colors[0]]
            result['Picture'] = card_imgs[0]
            result['Number'] = res
            result['From'] = '未知'


        return result

    def __show(self, result, FileName):
        # 显示表格
        self.RowLength = self.RowLength + 1
        if self.RowLength > 18:
            self.tableWidget.setColumnWidth(5, 157)
        self.tableWidget.setRowCount(self.RowLength)

        self.tableWidget.setItem(self.RowLength - 1, 0, QTableWidgetItem(FileName))
        self.tableWidget.setItem(self.RowLength - 1, 1, QTableWidgetItem(result['InputTime']))
        self.tableWidget.setItem(self.RowLength - 1, 2, QTableWidgetItem(result['Number']))
        self.tableWidget.setItem(self.RowLength - 1, 3, QTableWidgetItem(result['Type']))
        if result['Type'] == '蓝色牌照':
            self.tableWidget.item(self.RowLength - 1, 3).setBackground(QBrush(QColor(3, 128, 255)))
        elif result['Type'] == '绿色牌照':
            self.tableWidget.item(self.RowLength - 1, 3).setBackground(QBrush(QColor(98, 198, 148)))
        elif result['Type'] == '黄色牌照':
            self.tableWidget.item(self.RowLength - 1, 3).setBackground(QBrush(QColor(242, 202, 9)))
        self.tableWidget.setItem(self.RowLength - 1, 4, QTableWidgetItem(result['From']))

        self.tableWidget.item(self.RowLength - 1, 0).setBackground(QBrush(QColor(255, 255, 255)))
        self.tableWidget.item(self.RowLength - 1, 1).setBackground(QBrush(QColor(255, 255, 255)))
        self.tableWidget.item(self.RowLength - 1, 2).setBackground(QBrush(QColor(255, 255, 255)))
        self.tableWidget.item(self.RowLength - 1, 4).setBackground(QBrush(QColor(255, 255, 255)))

        # 显示识别到的车牌位置
        size = (int(self.label_3.width()), int(self.label_3.height()))
        shrink = cv2.resize(result['Picture'], size, interpolation=cv2.INTER_AREA)
        shrink = cv2.cvtColor(shrink, cv2.COLOR_BGR2RGB)
        self.QtImg = QtGui.QImage(shrink[:], shrink.shape[1], shrink.shape[0], shrink.shape[1] * 3,
                                  QtGui.QImage.Format_RGB888)
        self.label_3.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))

    def __writexls(self, DATA, path):
        try:
            wb = xlwt.Workbook();
            ws = wb.add_sheet('Data');
            # DATA.insert(0, ['文件名称','录入时间', '车牌号码', '车牌类型', '车牌信息'])
            for i, Data in enumerate(DATA):
                for j, data in enumerate(Data):
                    ws.write(i, j, data)
            wb.save(path)
            QMessageBox.information(None, "成功", "数据已保存!", QMessageBox.Yes)
        except:
            QMessageBox.information(None, "失败", "数据保存失败!可能因为保存的文件已经被打开", QMessageBox.Yes)

    def __writecsv(self, DATA, path):
        try:
            f = open(path, 'w')
            # DATA.insert(0, ['文件名称','录入时间', '车牌号码', '车牌类型', '车牌信息'])
            for data in DATA:
                f.write((',').join(data) + '\n')
            f.close()
            QMessageBox.information(None, "成功", "数据已保存!", QMessageBox.Yes)
        except:
            QMessageBox.information(None, "失败", "数据保存失败!可能因为保存的文件已经被打开", QMessageBox.Yes)


    def __writeFiles(self):
        path, filetype = QFileDialog.getSaveFileName(None, "另存为", self.ProjectPath,
                                                     "Excel 工作簿(*.xls);;CSV (逗号分隔)(*.csv)")
        if path == "":  # 未选择
            return
        if filetype == 'Excel 工作簿(*.xls)':
            self.__writexls(self.Data, path)
        elif filetype == 'CSV (逗号分隔)(*.csv)':
            self.__writecsv(self.Data, path)

    def __openimage(self):
        path, filetype = QFileDialog.getOpenFileName(None, "选择文件", self.ProjectPath,
                                                     "JPEG Image (*.jpg);;PNG Image (*.png);;JFIF Image (*.jfif)")  # ;;All Files (*)
        if path == "":  # 未选择文件
            return

        print('path',path)
        filename = path.split('/')[-1]

        # 尺寸适配
        size = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR).shape
        if size[0] / size[1] > 1.0907:
            w = int(size[1] * self.label.height() / size[0])
            h = self.label.height()
            jpg = QtGui.QPixmap(path).scaled(w, h)
        elif size[0] / size[1] < 1.0907:
            w = self.label.width()
            h = int((size[0] * self.label.width()) / size[1])
            jpg = QtGui.QPixmap(path).scaled(w, h)
        else:
            jpg = QtGui.QPixmap(path).scaled(self.label.width(), self.label.height())

        self.label.setPixmap(jpg)
        result = self.__vlpr(path)
        if result is not None:
            self.Data.append(
                [filename, result['InputTime'], result['Number'], result['Type'],
                 result['From']])
            self.__show(result, filename)
        else:
            QMessageBox.warning(None, "Error", "无法识别此图像!", QMessageBox.Yes)

    def close(self):
        reply = QtWidgets.QMessageBox.question(self, '提示',
                                               "是否要退出程序?\n提示:退出后将丢失所有识别数据",
                                               QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                                               QtWidgets.QMessageBox.No)
        if reply == QtWidgets.QMessageBox.Yes:
            sys.exit()
        else:
            pass



# 重写MainWindow类
class MainWindow(QtWidgets.QMainWindow):

    def closeEvent(self, event):
        reply = QtWidgets.QMessageBox.question(self, '提示',
                                               "是否要退出程序?\n提示:退出后将丢失所有识别数据",
                                               QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                                               QtWidgets.QMessageBox.No)
        if reply == QtWidgets.QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def mousePressEvent(self, event):
        global big
        big = False
        self.setWindowState(Qt.WindowNoState)
        self.m_flag = True
        self.m_Position = event.globalPos() - self.pos()  # 获取鼠标相对窗口的位置
        event.accept()

    def mouseMoveEvent(self, QMouseEvent):
        global big
        big = False
        self.setWindowState(Qt.WindowNoState)
        self.move(QMouseEvent.globalPos() - self.m_Position)  # 更改窗口位置
        QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        global big
        big = False
        self.setWindowState(Qt.WindowNoState)
        self.m_flag = False

    def mousePressEvent(self, event):
        global big
        big = False
        self.setWindowState(Qt.WindowNoState)
        self.m_flag = True
        self.m_Position = event.globalPos() - self.pos()  # 获取鼠标相对窗口的位置
        event.accept()

    def mouseMoveEvent(self, QMouseEvent):
        global big
        big = False
        self.setWindowState(Qt.WindowNoState)
        self.move(QMouseEvent.globalPos() - self.m_Position)  # 更改窗口位置
        QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        global big
        big = False
        self.setWindowState(Qt.WindowNoState)
        self.m_flag = False

    def big(self):
        global big
        print('最大化:{}'.format(big))
        if not big:
            self.setWindowState(Qt.WindowMaximized)
            big = True
        elif big:
            self.setWindowState(Qt.WindowNoState)
            big = False

    def mini(self):

        self.showMinimized()




if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    MainWindow = MainWindow()  # QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

标签:文件,img,point,检测,self,cv2,label,车牌,card
From: https://blog.csdn.net/a394467238/article/details/139316450

相关文章

  • 请求结束后删除文件
    fromflaskimportFlask,send_from_directoryimportosimportatexitapp=Flask(__name__)#假设这是你的文件高亮处理类classFileHighlighter:def__init__(self,file_path,chunk_id_list):self.file_path=file_pathself.chunk_id_list=......
  • 【护网必备】最新Struts2全版本漏洞检测工具
    基本介绍大家好,我是ABC_123。在2016年时,很多Java编写的应用网站都是基于Struts2框架研发的,因而Struts2的各个版本的漏洞非常多,当时为了方便安全测试人员快速寻找Struts2漏洞,于是ABC_123尽可能把这款工具写的简单容易上手,哪怕对Struts2漏洞完全不懂的新手,也能快速找到Struts2漏......
  • 在Linux中,有哪些系统日志文件?
    在Linux系统中,系统日志文件是记录系统操作、运行状态、错误信息以及安全事件等的重要文件。以下是Linux中常见的系统日志文件及其简要描述:系统日志(SystemLogs):这些日志记录了系统整体运行情况、错误信息等。常见的系统日志文件包括/var/log/messages、/var/log/syslog等。这......
  • 地下水勘察评价 地下水GB/T14848全项检测
    地下水检测地下水检测是指对地面以下岩石空隙中的水,地下水面以下饱和含水层中的水,各项化学指标进行检测分类,地下水是水资源的重要组成部分。地下水水量比较稳定,水质也好。地下水水质检测主要针对农田灌溉用水、工矿及城市用水。地下水等级划分为求合理地开发地下水水资源,防......
  • 木质家具板材甲醛释放量检测 木制家具含水率检测
    木质家具板材甲醛释放量检测木制家具含水率检测甲醛是一种无色,有强烈刺激型气味的气体。对人体健康有负面影响,长期接触低剂量的甲醛会引起慢性呼吸道疾病、女性月经紊乱、妊娠综合征,引起新生儿体质降低、染色体异常、甚至鼻咽癌,甲醛的危害还表现在它能凝固蛋白质,可使人......
  • anaconda环境 使用PyInstaller打包,运行exe文件出现导入_ssl错误
    使用PyInstaller打包后运行exe文件出现错误NameError:name'ssl'isnotdefined。观察PyInstaller打包程序输出,发现找不到DLL文件的警报,查看对应环境下的DLLs文件夹发现导入ssl的DLL文件缺失。查阅资料发现由于anaconda环境DLL文件错误存放在lib文件夹下面,致使PyInstaller打包......
  • 如何在 Windows 10/11 上恢复不在回收站中的永久删除文件夹?
    经验丰富的Windows用户将使用Windows备份和还原或文件历史记录来恢复不在回收站中的已删除文件夹。这些工具确实有助于Windows文件夹恢复,但并不总是有效。现在,许多专用的Windows数据恢复软件和免费解决方案都可以取代它们,从而为Windows用户提供了一种成功有效地恢复永久删......
  • 怎么发送超大文件?困扰已久的邮件大附件发送问题解决了!
    邮件是日常中使用最多的文件流转工具,特别是对于企业内部的员工间、及企业与企业间的业务开展,数据和文件的发送、业务留痕大多都基于邮箱展开。邮箱的普遍使用给用户基于邮箱进行业务沟通提供了前提,其中,Outlook邮箱是使用最广泛的邮箱之一。这使得邮箱成为一种最常用的通讯工具,但......
  • 从零手写实现 nginx-09-compress http 文件压缩
    前言大家好,我是老马。很高兴遇到你。我们为java开发者实现了java版本的nginxhttps://github.com/houbb/nginx4j如果你想知道servlet如何处理的,可以参考我的另一个项目:手写从零实现简易版tomcatminicat手写nginx系列如果你对nginx原理感兴趣,可以阅读:从零......
  • 公检法部门保密网文件导出,这样做才是真正的安全又便捷
    公检法是司法机关的核心组成,也是社会管理的重要组成,公检法部门的业务中涉及大量的居民数据、个人隐私、司法案件等信息,因此,数据的安全性至关重要。根据我国法律要求,同时基于对数据的保护需要,我国的公检法机关在网络建设上,大都采用物理隔离的方式,将内部网络与互联网隔开。但在日......