脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - 详细过程带你用Python做车牌自动识别系统

详细过程带你用Python做车牌自动识别系统

2021-12-25 00:28Dragon少年 Python

这篇文章主要介绍了带你用Python做车牌自动识别系统的详细过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

前言

前段时间,用pyqt5写了两篇文章,自己用python做的一款超炫酷音乐播放器用python做个个性的动画挂件让桌面不单调。有粉丝问我,为什么要用pyqt5?之前没接触过pyqt5,能不能多分享一些这方面的开发案例?

今天就继续给大家分享一个实战案例,带大家一起用python的pyqt5开发一个车牌自动识别系统!

首先一起来看看最终实现的车牌识别系统效果图:

详细过程带你用Python做车牌自动识别系统

下面,我们就开始介绍如何实现这款自动车牌识别系统。

一、核心功能设计

总体来说,我们首先要进行ui界面构建设计,根据车牌识别系统功能进行画面排版布局;其次我们的这款车牌识别系统的主要功能车辆图片读取识别显示、图片中车牌roi区域获取、车牌识别结果输出显示。

对于结果输出显示,我们主要包含了读取图片名称、读取录入时间、识别车牌号码、识别车牌颜色、识别车牌所属地。最后我们还可以将车牌识别系统的数据信息导出本地存储。

拆解需求,大致可以整理出核心功能如下:

ui设计排版布局

  • 左侧区域进行识别信息显示,包含图片名称、读取录入时间、识别车牌号码、识别车牌颜色、识别车牌所属地信息
  • 右侧可以分成3个区域,顶部区域包含窗体最小化,最大化,关闭功能;中间区域显示读取车辆图片;底部区域包含车牌显示区域、图片读取、车牌信息存储功能

车牌识别

  • 通过读取图片进行车牌区域提取输出
  • 车牌自动识别结果输出

车牌信息显示存储

  • 根据自动识别结果对车牌各类信息显示
  • 对录入识别的车辆车牌识别信息存储

二、实现步骤

1. ui设计排版布局

根据车牌识别需要的功能,首先进行ui布局设计,我们这次还是使用的pyqt5。核心设计代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# author:csdn-dragon少年
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()

ui实现效果如下:

详细过程带你用Python做车牌自动识别系统

2. 车牌识别

接下来我们需要实现两个核心功能,包括获取车牌roi区域车牌自动识别功能。

车牌roi区域提取:

根据读取的车辆图片,预处理进行车牌roi区域提取,主要通过opencv的图像处理相关知识点来完成。主要包括对图像去噪、二值化、边缘轮廓提取、矩形区域矫正、蓝绿黄车牌颜色定位识别。核心代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# 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

至此我们就可以输出车牌roi区域和车牌颜色了,效果如下:

详细过程带你用Python做车牌自动识别系统

车牌自动识别:

本篇介绍调用百度ai提供的车牌识别接口 – 百度ai开放平台链接,识别效果非常不错。

详细过程带你用Python做车牌自动识别系统

这里面我们可以创建一个车牌识别的应用,其中的api key及secret key后面我们调用车牌识别检测接口时会用到。

详细过程带你用Python做车牌自动识别系统

我们可以看到官方提供的帮助文档,介绍了如何调用请求url数据格式,向api服务地址使用post发送请求,必须在url中带上参数access_token,可通过后台的api key和secret key生成。这里面的api key和secret key就是我们上面提到的。

详细过程带你用Python做车牌自动识别系统

接下来我们看看调用车牌识别接口代码示例。

详细过程带你用Python做车牌自动识别系统

那我们如何获取识别的车牌号码呢?api文档可以看到里面有个words_result字典 ,其中的color代表车牌颜色 number代表车牌号码 。这样我就可以知道识别的车牌颜色和车牌号了。

详细过程带你用Python做车牌自动识别系统

车牌识别的接口调用流程基本已经清楚了,下面就可以进行代码实现了。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# author:csdn-dragon少年
def get_token(self):
    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-dragon少年
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"
    # 二进制方式打开图片文件
    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'] = '未知'
            return result
    else:
        return none

这样我们就可以拿到车牌颜色和车牌号码了,效果如下:

详细过程带你用Python做车牌自动识别系统

3. 车牌信息显示存储

3.1 车牌信息显示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# author:csdn-dragon少年
def __show(self, result, filename):
    # 显示表格
    self.rowlength = self.rowlength + 1
    if self.rowlength > 18:
        self.tablewidget.setcolumnwidth(5, 157)
    self.tablewidget.setrowcount(self.rowlength)
    self.tablewidget.setitem(self.rowlength - 1, 0, qtablewidgetitem(filename))
    self.tablewidget.setitem(self.rowlength - 1, 1, qtablewidgetitem(result['inputtime']))
    self.tablewidget.setitem(self.rowlength - 1, 2, qtablewidgetitem(result['number']))
    self.tablewidget.setitem(self.rowlength - 1, 3, qtablewidgetitem(result['type']))
    if result['type'] == '蓝色牌照':
        self.tablewidget.item(self.rowlength - 1, 3).setbackground(qbrush(qcolor(3, 128, 255)))
    elif result['type'] == '绿色牌照':
        self.tablewidget.item(self.rowlength - 1, 3).setbackground(qbrush(qcolor(98, 198, 148)))
    elif result['type'] == '黄色牌照':
        self.tablewidget.item(self.rowlength - 1, 3).setbackground(qbrush(qcolor(242, 202, 9)))
    self.tablewidget.setitem(self.rowlength - 1, 4, qtablewidgetitem(result['from']))
    self.tablewidget.item(self.rowlength - 1, 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))

效果如下:

详细过程带你用Python做车牌自动识别系统

3.2 信息导出存储:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# author:csdn-dragon少年
def __writexls(self, data, path):
    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)
def __writecsv(self, data, path):
    f = open(path, 'w')
    # data.insert(0, ['文件名称','录入时间', '车牌号码', '车牌类型', '车牌信息'])
    for data in data:
        f.write((',').join(data) + '\n')
    f.close()
    qmessagebox.information(none, "成功", "数据已保存!", qmessagebox.yes)
 
def __writefiles(self):
    path, filetype = qfiledialog.getsavefilename(none, "另存为", self.projectpath,
                                                 "excel 工作簿(*.xls);;csv (逗号分隔)(*.csv)")
    if path == "":  # 未选择
        return
    if filetype == 'excel 工作簿(*.xls)':
        self.__writexls(self.data, path)
    elif filetype == 'csv (逗号分隔)(*.csv)':
        self.__writecsv(self.data, path)

效果如下:

详细过程带你用Python做车牌自动识别系统

导出车牌信息数据如下:

详细过程带你用Python做车牌自动识别系统

至此,整个车牌自动识别系统就完成了~今天我们就到这里,明天继续努力!

详细过程带你用Python做车牌自动识别系统

如果本篇博客有任何错误,请批评指教,不胜感激 !

原文链接:https://blog.csdn.net/hhladminhhl/article/details/119779359

延伸 · 阅读

精彩推荐