融合了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_())