preface
Today, when I went out of the community, I found that the parking lever did not respond, and then I called someone to open it for me! Later, through the process of chatting with property personnel, the original license plate can not be recognized. I think it’s broken! This is not a small matter, I said with the property, in the evening I give you good! Property little sister insisted to give me to apply for a bonus, no way, take the bonus please property little sister to eat!
The body of the
Develop an automatic license plate recognition system with Python PyQt5!
First, let’s take a look at the final realization of the license plate recognition system renderings:
Below, we begin to introduce how to realize this automatic license plate recognition system.
I. Design of core functions
In general, we should first carry out the UI interface construction design, according to the license plate recognition system function screen layout layout; Secondly, the main functions of our license plate recognition system are vehicle picture reading and recognition display, license plate ROI area acquisition and license plate recognition result output display.
For the result output display, we mainly include reading picture name, reading input time, license plate number recognition, license plate color recognition, license plate location recognition. Finally, we can export the data information of the license plate recognition system to local storage.
After disassembling the requirements, the core functions can be roughly sorted out as follows:
UI design layout layout
-
Identification information is displayed in the left area, including picture name, reading time, license plate number, license plate color and location information
-
The right side can be divided into three areas. The top area contains window minimize, maximize, and close functions. The middle area shows reading vehicle pictures; The bottom area contains the license plate display area, picture reading, license plate information storage function
-
License plate recognition
- The license plate area is extracted and output by reading pictures
- Automatic license plate recognition result output
-
License plate information display storage
- Display all kinds of information of license plate according to the result of automatic recognition
- Store the vehicle license plate recognition information
Two, implementation steps
1. UI design and layout
According to the license plate recognition needs to function, first
UI Layout Design
We will use it again this time
pyqt5
. The core design code is as follows:
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) # 隐藏垂直表头)
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.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) # 隐藏边框
# author:CSDN-Dragon少年
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()
Copy the code
The UI implementation is as follows:
2. License plate recognition
Next we need to implement two core functions, including fetch
License plate ROI area
and
Automatic license plate recognition
Function.
Region extraction of license plate ROI:
According to the read vehicle picture, preprocessing license plate ROI area extraction, mainly through Opencv image processing related knowledge points to complete. It mainly includes image denoising, binarization, edge contour extraction, rectangular area correction, blue, green and yellow license plate color location recognition. The core code is as follows:
# author:CSDN-Dragon少年
# 预处理
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) # 图片分辨率调整
blur = self.cfg["blur"]
# 高斯去噪
if blur > 0:
img = cv2.GaussianBlur(img, (blur, blur), 0)
oldimg = img
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
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 = [cnt for cnt in contours if cv2.contourArea(cnt) > self.Min_Area]
# 逐个排除不是车牌的矩形区域
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)
# 矩形区域可能是倾斜的矩形,需要矫正,以便使用颜色定位
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)
#使用颜色定位,排除不是车牌的矩形,目前只识别蓝、绿、黄车牌
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
Copy the code
So far, we can output the ROI region and license plate color, and the result is as follows:
Automatic license plate recognition:
License plate recognition blogger wrote a recognition system based on Opencv and SVM, due to the length of the code, this paper will not show (
Interested can private message bloggers to obtain the source code
).
This is where we can create a license plate recognition app, where
API Key and Secret Key
Later we call the license plate recognition detection interface will be used.
We can see the official help document, introduced how
Invoke the request URL data format to send the request to the API service address using POST
, you must take parameters in the URL
access_token
, can be generated through the BACKGROUND API Key and Secret Key. The API Key and Secret Key are the ones we mentioned above.
Let’s look at an example of code that calls the license plate recognition interface.
So how do we get a license plate number? You can see in the API documentation that there’s a
Words_result dictionary
, in which the
Color stands for license plate color
.
Number stands for license plate number
. So I can get the license plate color and license plate number.
The interface call process of license plate recognition has been basically clear, and the following code can be implemented.
# author: def get_token(self): The host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + self. Client_id + '&client_secret=' + self.client_secret response = requests.get(host) if response: Token_info = response.json() token_key = token_info['access_token'] return token_key # author: CSDN- def get_license_plate(self, car_pic): result = {} card_imgs, Colors = self. Pretreatment (car_pic) request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/license_plate" # binary mode to open the image file f = open(car_pic, 'rb') img = base64.b64encode(f.read()) params = {"image": img} access_token = self.get_token() request_url = request_url + "?access_token=" + access_token headers = {'content-type': 'application/x-www-form-urlencoded'} response = requests.post(request_url, data=params, headers=headers) if response: print(response.json()) license_result = response.json()['words_result']['number'] card_color = response.json()['words_result']['color'] if license_result ! = [] : result['InputTime'] = time.strftime("%Y-%m-%d %H:%M:%S") result['Type'] = self.cardtype[card_color] result['Picture'] = Card_imgs [0] result [' Number '] = "'. Join (license_result [:] 2) + ', '+'. Join (license_result [2:]) try: result['From'] = ''.join(self.Prefecture[license_result[0]][license_result[1]]) except: Result ['From'] = 'unknown' return result else: return NoneCopy the code
Then we can get the license plate color and license plate number, as follows:
3. Display and store license plate information
3.1 License Plate Information Display:
# author: CSDN-Dragon def __show(self, result, FileName): 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'] == 'blue ': Self.tablewidget.item (self.rowLength -1, 3).setBackground(QBrush(QColor(3, 128, 255))) elif result['Type'] == 'green ': self.tableWidget.item(self.rowLength -1, 3).setBackground(QBrush(QColor(3, 128, 255)) Self.tablewidget.item (self.rowLength -1, 3).setBackground(QBrush(QColor(98, 198, 148))) elif result['Type'] == 'yellow ': self.tableWidget.item(self.rowLength -1, 3).setBackground(QBrush(QColor(98, 198, 148)) 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, 4).setBackground(QBrush(QColor(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))Copy the code
The effect is as follows:
3.2 Information Export storage:
# author: def __writexls(self, DATA, path): wb = xlwt.workbook (); ws = wb.add_sheet('Data'); # data. insert(0, [' file name ',' license number ',' license number ']) for I, DATA in enumerate(DATA): For J, data in enumerate(data) : ws.write(I, j, data) wb.save(path) QMessageBox. Information (None, "Success "," Data saved!" , QMessageBox.Yes) def __writecsv(self, DATA, path): F = open(path, 'w') # DATA. Insert (0, [' id ',' id ',' id ',' id ']) for DATA in DATA: F.write ((',').join(data) + '\n') f.lose () QMessageBox. Information (None, "success "," Data saved! ") , QMessageBox.Yes) def __writeFiles(self): Path, filetype = QFileDialog. GetSaveFileName (None, "save as", the self. The ProjectPath, "Excel workbook (*. XLS);; CSV (comma separated)(*.csv)") if path == "": # unselected return if fileType == 'Excel workbook (*.xls)': Self.__writexls (self.data, path) elif fileType == 'CSV (comma separated)(*.csv)': self.__writecSV (self.data, path)Copy the code
The effect is as follows:
The license plate information is exported as follows:
So far, the entire license plate automatic recognition system is completed ~ today we are here, tomorrow continue to work hard!
⑥ Project source code cases to share
If you use it, you can take it away directly, in my QQ technical exchange group group number: 948351247 (pure technical exchange and resource sharing, advertising is not allowed) to take it away by yourself
Click here to collect