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

融合了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 npimport cv2
import hyperlpr3 as lpr3
# pip install hyperlpr3 -i https://pypi.tuna.tsinghua.edu.cn/simple/import cv2 as cvbig = Falsedef 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()# breakdef __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] = 0if point[1] < 0:point[1] = 0def accurate_place(self, card_img_hsv, limit1, limit2, color):row_num, col_num = card_img_hsv.shape[:2]xl = col_numxr = 0yh = 0yl = 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 = 0for 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 += 1if count > col_num_limit:if yl > i:yl = iif yh < i:yh = ifor j in range(col_num):count = 0for 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 += 1if count > row_num - row_num_limit:if xl > j:xl = jif xr < j:xr = jreturn xl, xr, yh, yl# 预处理def pretreatment(self, car_pic):if type(car_pic) == type(""):img = self.__imreadex(car_pic)else:img = car_picpic_hight, pic_width = img.shape[:2]if pic_width > self.MAX_WIDTH:resize_rate = self.MAX_WIDTH / pic_widthimg = 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 = imgimg = 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_widthwh_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 = 1else: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 = pointif low_point[1] > point[1]:low_point = pointif heigth_point[1] < point[1]:heigth_point = pointif right_point[0] < point[0]:right_point = pointif 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 = 0try:# 有转换失败的可能,原因来自于上面矫正矩形出错card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)except:print('BGR转HSV失败')card_imgs = colors = Nonereturn card_imgs, colorsif card_img_hsv is None:continuerow_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 += 1elif 35 < H <= 99 and S > 34:  # 图片分辨率调整green += 1elif 99 < H <= 124 and S > 34:  # 图片分辨率调整blue += 1if 0 < H < 180 and 0 < S < 255 and 0 < V < 46:black += 1elif 0 < H < 180 and 0 < S < 43 and 221 < V < 225:white += 1color = "no"# print('黄:{:<6}绿:{:<6}蓝:{:<6}'.format(yellow,green,blue))limit1 = limit2 = 0if yellow * 2 >= card_img_count:color = "yellow"limit1 = 11limit2 = 34  # 有的图片有色偏偏绿elif green * 2 >= card_img_count:color = "green"limit1 = 35limit2 = 99elif blue * 2 >= card_img_count:color = "blue"limit1 = 100limit2 = 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:continueneed_accurate = Falseif yl >= yh:yl = 0yh = row_numneed_accurate = Trueif xl >= xr:xl = 0xr = col_numneed_accurate = Truecard_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:continueif yl >= yh:yl = 0yh = row_numif xl >= xr:xl = 0xr = col_numcard_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, colorsPlateRecognition_example = PlateRecognition()class Ui_MainWindow(QMainWindow):def __init__(self):super().__init__()self.RowLength = 0self.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.translateMainWindow.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)  # lonloncard_imgs, colors = PlateRecognition_example.pretreatment(path)if len(colors) == 0:result['InputTime'] = time.strftime("%Y-%m-%d %H:%M:%S")result['Type'] = "蓝色牌照"result['Picture'] = imageresult['Number'] = resresult['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'] = resresult['From'] = '未知'return resultdef __show(self, result, FileName):# 显示表格self.RowLength = self.RowLength + 1if 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 == "":  # 未选择returnif 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 == "":  # 未选择文件returnprint('path',path)filename = path.split('/')[-1]# 尺寸适配size = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR).shapeif 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 bigbig = Falseself.setWindowState(Qt.WindowNoState)self.m_flag = Trueself.m_Position = event.globalPos() - self.pos()  # 获取鼠标相对窗口的位置event.accept()def mouseMoveEvent(self, QMouseEvent):global bigbig = Falseself.setWindowState(Qt.WindowNoState)self.move(QMouseEvent.globalPos() - self.m_Position)  # 更改窗口位置QMouseEvent.accept()def mouseReleaseEvent(self, QMouseEvent):global bigbig = Falseself.setWindowState(Qt.WindowNoState)self.m_flag = Falsedef mousePressEvent(self, event):global bigbig = Falseself.setWindowState(Qt.WindowNoState)self.m_flag = Trueself.m_Position = event.globalPos() - self.pos()  # 获取鼠标相对窗口的位置event.accept()def mouseMoveEvent(self, QMouseEvent):global bigbig = Falseself.setWindowState(Qt.WindowNoState)self.move(QMouseEvent.globalPos() - self.m_Position)  # 更改窗口位置QMouseEvent.accept()def mouseReleaseEvent(self, QMouseEvent):global bigbig = Falseself.setWindowState(Qt.WindowNoState)self.m_flag = Falsedef big(self):global bigprint('最大化:{}'.format(big))if not big:self.setWindowState(Qt.WindowMaximized)big = Trueelif big:self.setWindowState(Qt.WindowNoState)big = Falsedef 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_())

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

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

相关文章

2024年【起重机司机(限桥式起重机)】考试试卷及起重机司机(限桥式起重机)证考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【起重机司机(限桥式起重机)】考试试卷及起重机司机(限桥式起重机)证考试&#xff0c;包含起重机司机(限桥式起重机)考试试卷答案和解析及起重机司机(限桥式起重机)证考试练习。安全生产模拟考试一点通结合国家…

音视频开发17 FFmpeg 音频解码- 将 aac 解码成 pcm

这一节&#xff0c;接 音视频开发12 FFmpeg 解复用详情分析&#xff0c;前面我们已经对一个 MP4文件&#xff0c;或者 FLV文件&#xff0c;或者TS文件进行了 解复用&#xff0c;解出来的 视频是H264,音频是AAC&#xff0c;那么接下来就要对H264和AAC进行处理&#xff0c;这一节…

WebAPI AOP方式 异常方式

》》 自定义异常处理特性 using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web; using System.Web.Http.Filters;namespace WebApplication11 {/// <summary>/// 异常处理特性/// </sum…

005.FashionMNIST数据集简介

一、FashionMNIST数据集简介 FashionMNIST数据集&#xff0c;作为经典的MNIST数据集的现代替代品的数据集&#xff0c;是衣物分类数据集&#xff0c;由Zalando&#xff08;一家德国的在线时尚零售商&#xff09;发布。 FashionMNIST数据集和MNIST相比。图片尺寸相同&#xff0c…

混凝土结构中最小配筋率45ft/fy怎么来的?

文章目录 0. 背景1. 原理解析2. 总结 0. 背景 上学的时候就对混凝土结构规范中关于最小配筋率“ 45 f t / f y 45f_t/f_y 45ft​/fy​”的表述很好奇&#xff0c;今天终于看到解释了。原文来自这里&#xff0c;喜欢的可以关注原作者。 按照原作者的说法&#xff0c;本文的解释…

I P协议

IPv4首部 4个字节的32 bit值以下面的次序传输&#xff1a;首先是 0&#xff5e;7 bit&#xff0c;其次8&#xff5e;15 bit&#xff0c;然后1 6&#xff5e;23 bit&#xff0c;最后是24~31 bit。这种传输次序称作 big endian字节序。由于TCP/IP首部中所有的二进制整数在网络中传…

简单聊聊大数据分析的方法有什么

大数据分析是指对规模巨大的数据集合进行的分析过程。 这些数据集合通常具有以下几个特点&#xff0c;可以概括为5个V&#xff1a; 1.数据量大&#xff08;Volume&#xff09;&#xff1a;大数据分析处理的数据量巨大&#xff0c;远远超出了传统数据处理软件的能力范围。 2.…

攻防世界testre做法(考点:base58)

在做这道题目之前&#xff0c;我们先来简单了解一下base64加密和base58加密&#xff0c;先来说一些预备知识&#xff0c;bit为1个位&#xff0c;即一个0或1&#xff0c;八个位组成一个字节&#xff0c;即八个二进制数。 base64编码原理&#xff1a;1&#xff0c;在使用base64加…

走进 Apache 世界的另一扇大门

引言 作为热爱技术的你&#xff0c;是否也羡慕 Apache PMC 或者 Committer&#xff0c;此篇文章渣渣皮带你迈出如何成为技术大牛的第一步。 当然我现在还是一枚小小的 code contributor&#xff0c;在成为 committer 的路上还在奋力打码中&#xff0c;写这篇文章也是为大家有…

Windows搭建apache网站

1、官网下载安装包&#xff0c;注意下载服务器对应操作系统的安装包&#xff08;此案例为64位操作系统&#xff09; Apache VS17 binaries and modules downloadFor (business) webmasters, developers and home-users who want running always up to date Windows VS17 binar…

【机器学习】机器学习与智能交通在智慧城市中的融合应用与性能优化新探索

文章目录 引言机器学习与智能交通的基本概念机器学习概述监督学习无监督学习强化学习 智能交通概述交通流量预测交通拥堵管理智能信号控制智能停车管理 机器学习与智能交通的融合应用实时交通数据分析数据预处理特征工程 交通流量预测与优化模型训练模型评估 智能信号控制与优化…

pycharm安装openai报错

解决方案&#xff1a; Rust官网:http://rust-lang.org 下载安装包&#xff0c;下载后如下 双击这个exe文件 提示需要安装visual studio选择1进行安装即可。安装完成后会自动进行下一步 选择1进行安装 默认安装到C:\Users\用户名文件夹下 验证是否安装成功 由于这两个文件夹占…

k8s:实现一个pod两个容器

# 制作两个容器的镜像 通过以下Dockerfile创建一个镜像 cd /chz/install/docker vim Dockerfile <<<< 内容如下&#xff1a; FROM centosRUN sed -i -e "s|mirrorlist|#mirrorlist|g" /etc/yum.repos.d/CentOS-* RUN sed -i -e "s|#baseurlhttp:/…

Spring Boot框架基础

文章目录 1 Spring Boot概述2 Spring Boot入门2.1 项目搭建2.2 入门程序 3 数据请求与响应3.1 数据请求3.2 数据响应 4 分层解耦4.1 三层架构4.2 控制反转4.3 依赖注入 5 参考资料 1 Spring Boot概述 Spring是Java EE编程领域的一个轻量级开源框架&#xff0c;是为了解决企业级…

Python 机器学习 基础 之 处理文本数据 【处理文本数据/用字符串表示数据类型/将文本数据表示为词袋】的简单说明

Python 机器学习 基础 之 处理文本数据 【处理文本数据/用字符串表示数据类型/将文本数据表示为词袋】的简单说明 目录 Python 机器学习 基础 之 处理文本数据 【处理文本数据/用字符串表示数据类型/将文本数据表示为词袋】的简单说明 一、简单介绍 二、处理文本数据 三、用…

IDEA2023.1.4配置springboot项目

新建“Spring Initializr”项目 勾选以下三个依赖项即可。 springboot分为代码层、资源层和测试层。 代码层 根目录&#xff1a;src/main/java 入口启动类及程序的开发目录。在这个目录下进行业务开发、创建实体层、控制器层、数据连接层等。 资源层 根目录&#xff1a;src…

喜讯!云起无垠入选《LLM驱动数字安全2024—AI安全系列报告》

近日&#xff0c;国内领先的数字化领域第三方服务机构数世咨询&#xff0c;发布了《LLM驱动数字安全2024—AI安全系列报告》。该报告深入统计分析了国内在LLM研发或应用方面具有实力的数字安全供应商&#xff0c;并通过报告和雷达图的形式&#xff0c;直观展示了这些供应商在数…

vue2的form利用插槽修改错误提示UI

1. 需求 很多时候我们使用el-form想修改下错误提示的UI&#xff0c;比如table中使用form校验这类场景下错误提示的UI调整就非常重要。 2. 了解文档 Form-Item Scoped Slot name说明error自定义表单校验信息的显示方式&#xff0c;参数为 { error } 3.实际使用 html里使用…

抽象,自定义函数,递归

6.1懒惰是一种美德 如果你 在一个地方编写了一些代码&#xff0c;但需要在另一个地方再次使用&#xff0c;该如何办呢&#xff1f; 假设你编写了一段代码&#xff0c;它计算一些斐波那契数&#xff08;一种数列&#xff0c;其中每个数都是前两个数的和&#xff09;。 现在的…

笔记96:前馈控制 + 航向误差

1. 回顾 对于一个 系统而言&#xff0c;结构可以画作&#xff1a; 如果采用 这样的控制策略&#xff0c;结构可以画作&#xff1a;&#xff08;这就是LQR控制&#xff09; 使用LQR控制器&#xff0c;可以通过公式 和 构建一个完美的负反馈系统&#xff1b; a a 但是有上…