current position:Home>Together with Python to do a license plate automatic recognition system, fun and practical!

Together with Python to do a license plate automatic recognition system, fun and practical!

2021-08-22 21:24:08 Dragon junior

Preface

Some time ago , use PyQt5 I wrote two articles , About Python Make a cool music player Custom desktop animation pendant . Some fans asked me , Why use PyQt5? I haven't touched before PyQt5, Can you share more development cases in this regard ?

Today I will continue to share with you a practical case , Take it with you Python Of PyQt5 Develop an automatic license plate recognition system !

First, let's take a look at the final effect of the license plate recognition system : Insert picture description here
below , We begin to introduce how to implement this automatic license plate recognition system .

One 、 Core function design

On the whole , First of all we have to do UI Interface construction design , According to the function of license plate recognition system, the screen layout is carried out ; Secondly, the main function of our license plate recognition system is vehicle picture reading, recognition and display 、 The license plate in the picture ROI Area acquisition 、 License plate recognition result output display .

For the result output display , We mainly include reading the picture name 、 Read the entry time 、 Identify the license plate number 、 Identify the license plate color 、 Identify where the license plate belongs . Finally, we can export the data information of the license plate recognition system to local storage .

Dismantling needs , The core functions can be roughly sorted out as follows :

  • UI Design layout

    • The identification information is displayed in the left area , Include picture name 、 Read the entry time 、 Identify the license plate number 、 Identify the license plate color 、 Identify the location of the license plate
    • The right side can be divided into 3 Regions , The top area contains the form , Maximize , Turn off the function ; The middle area shows the read vehicle picture ; The bottom area contains the license plate display area 、 Read the picture 、 License plate information storage function
  • License plate recognition

    • Extract and output the license plate area by reading the picture
    • Automatic license plate recognition result output
  • License plate information display and storage

    • Display all kinds of license plate information according to the automatic recognition results
    • Store the vehicle license plate recognition information entered for recognition

Two 、 Implementation steps

1. UI Design layout

According to the functions required for license plate recognition , First of all to UI Layout design , We still use it this time pyqt5. The core design code is as follows :

# author:CSDN-Dragon juvenile 
def setupUi(self, MainWindow):
    MainWindow.setObjectName("MainWindow")
    MainWindow.resize(1213, 670)
    MainWindow.setFixedSize(1213, 670)  #  Set the fixed size of the form 
    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)  #  Set up 1 The width of the column 
    self.tableWidget.setColumnWidth(1, 130)  #  Set up 2 The width of the column 
    self.tableWidget.setColumnWidth(2, 110)  #  Set up 3 The width of the column 
    self.tableWidget.setColumnWidth(3, 90)  #  Set up 4 The width of the column 
    self.tableWidget.setColumnWidth(4, 181)  #  Set up 5 The width of the column 
    self.tableWidget.setHorizontalHeaderLabels([" Image name ", " Input time ", " license plate ", " License plate type ", " License plate information "])
    self.tableWidget.setRowCount(self.RowLength)
    self.tableWidget.verticalHeader().setVisible(False)  #  Hide vertical header )
    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)  #  Set click event 
    self.pushButton.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#2B2B2B;}''')
    self.pushButton_2.clicked.connect(self.__writeFiles)  #  Set click event 
    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()  #  Create the grid layout layer of the left part 
    self.close_widget.setLayout(self.close_layout)  #  Set the layout of the left part to grid 
    self.left_close = QPushButton("")  #  close button 
    self.left_close.clicked.connect(self.close)
    self.left_visit = QPushButton("")  #  Blank button 
    self.left_visit.clicked.connect(MainWindow.big)
    self.left_mini = QPushButton("")  #  Minimize button 
    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)  #  Set the size of the close button 
    self.left_visit.setFixedSize(15, 15)  #  Set the button size 
    self.left_mini.setFixedSize(15, 15)  #  Set the minimize button size 
    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()  #  Get the current project file location 
    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)  #  Set window transparency 
    MainWindow.setAttribute(Qt.WA_TranslucentBackground)
    MainWindow.setWindowFlag(Qt.FramelessWindowHint)  #  Hide borders 

# author:CSDN-Dragon juvenile 
def retranslateUi(self, MainWindow):
    _translate = QtCore.QCoreApplication.translate
    MainWindow.setWindowTitle(_translate("MainWindow", " License plate recognition system "))
    self.label_0.setText(_translate("MainWindow", " Original picture :"))
    self.label.setText(_translate("MainWindow", ""))
    self.label_1.setText(_translate("MainWindow", " Recognition result :"))
    self.label_2.setText(_translate("MainWindow", " License plate area :"))
    self.label_3.setText(_translate("MainWindow", ""))
    self.pushButton.setText(_translate("MainWindow", " Open file "))
    self.pushButton_2.setText(_translate("MainWindow", " Derived data "))
    self.label_4.setText(_translate("MainWindow", " event :"))
    self.scrollAreaWidgetContents_1.show()

UI The effect is as follows :
 Insert picture description here

2. License plate recognition

Next, we need to implement two core functions , Including access to License plate ROI Area and Automatic license plate recognition function .

License plate ROI Region extraction :

According to the read vehicle picture , Preprocessing is performed ROI Region extraction , Mainly through Opencv Image processing related knowledge points to complete . It mainly includes image denoising 、 Two valued 、 Edge contour extraction 、 Rectangular area correction 、 Blue, green and yellow license plate color location and recognition . The core code is as follows :

# author:CSDN-Dragon juvenile 
#  Preprocessing 
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)  #  Picture resolution adjustment 
    blur = self.cfg["blur"]
    #  Gaussian denoising 
    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)  #  Open operation 
    img_opening = cv2.addWeighted(img, 1, img_opening, -1, 0);  #  Merge with the result of the last open operation 
    # cv2.imshow('img_opening', img_opening)

    #  Find the edge of the image 
    ret, img_thresh = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)  #  Two valued 
    img_edge = cv2.Canny(img_thresh, 100, 200)
    # cv2.imshow('img_edge', img_edge)

    #  Use open and close operations to make the image edge a whole 
    kernel = np.ones((self.cfg["morphologyr"], self.cfg["morphologyc"]), np.uint8)
    img_edge1 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, kernel)  #  Closed operation 
    img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel)  #  Open operation 
    # cv2.imshow('img_edge2', img_edge2)
    # cv2.imwrite('./edge2.png', img_edge2)
    #  Find the rectangular area formed by the overall edge of the image , There may be a lot of , The license plate is in one of the rectangular areas 
    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]
    #  Exclude rectangular areas that are not license plates one by one 
    car_contours = []
    for cnt in contours:
        #  Frame selection   Generates the smallest circumscribed rectangle   Return value ( center (x,y), ( wide , high ),  Rotation Angle )
        rect = cv2.minAreaRect(cnt)
        # print(' Wide and high :',rect[1])
        area_width, area_height = rect[1]
        #  Select an area whose width is greater than its height 
        if area_width < area_height:
            area_width, area_height = area_height, area_width
        wh_ratio = area_width / area_height
        # print(' Aspect ratio :',wh_ratio)
        #  The length width ratio of the rectangular area is required to be 2 To 5.5 Between ,2 To 5.5 Is the aspect ratio of the license plate , The remaining rectangles are excluded 
        if wh_ratio > 2 and wh_ratio < 5.5:
            car_contours.append(rect)
            box = cv2.boxPoints(rect)
            box = np.int0(box)
    #  The rectangular area may be an inclined rectangle , Need correction , To use color positioning 
    card_imgs = []
    for rect in car_contours:
        if rect[2] > -1 and rect[2] < 1:  #  Create an angle , Make the left 、 high 、 Right 、 Low get the right value 
            angle = 1
        else:
            angle = rect[2]
        rect = (rect[0], (rect[1][0] + 5, rect[1][1] + 5), angle)  #  Expand the scope , Avoid the edge of the license plate being excluded 
        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]:  #  Positive angle 
            new_right_point = [right_point[0], heigth_point[1]]
            pts2 = np.float32([left_point, heigth_point, new_right_point])  #  Characters just need to be changed in height 
            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]:  #  Negative angle 

            new_left_point = [left_point[0], heigth_point[1]]
            pts2 = np.float32([new_left_point, heigth_point, right_point])  #  Characters just need to be changed in height 
            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)
    # Use color positioning , Exclude rectangles that are not license plates , At present, only blue 、 green 、 Yellow license plate 
    colors = []
    for card_index, card_img in enumerate(card_imgs):
        green = yellow = blue = black = white = 0
        try:
            #  There is a possibility of conversion failure , The reason comes from the error in correcting the rectangle above 
            card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
        except:
            print('BGR turn HSV Failure ')
            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

        #  Determine the license plate color 
        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:  #  Picture resolution adjustment 
                    yellow += 1
                elif 35 < H <= 99 and S > 34:  #  Picture resolution adjustment 
                    green += 1
                elif 99 < H <= 124 and S > 34:  #  Picture resolution adjustment 
                    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(' yellow :{:<6} green :{:<6} blue :{:<6}'.format(yellow,green,blue))

        limit1 = limit2 = 0
        if yellow * 2 >= card_img_count:
            color = "yellow"
            limit1 = 11
            limit2 = 34  #  Some pictures are colored green 
        elif green * 2 >= card_img_count:
            color = "green"
            limit1 = 35
            limit2 = 99
        elif blue * 2 >= card_img_count:
            color = "blue"
            limit1 = 100
            limit2 = 124  #  Some pictures are colored purple 
        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

        #  Relocate according to the color of the license plate , Reduce the edge, not the license plate boundary 
        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:  #  Probably x or y The direction is not reduced , Need to try again 
            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(' Color recognition results :' + colors[0])
    return card_imgs, colors

At this point, we can output the license plate ROI Area and license plate color , The effect is as follows :
 Insert picture description here
Automatic license plate recognition :

The license plate recognition blogger wrote a blog based on Opencv and SVM Our recognition system , Because the code is long , This article does not show ( Interested bloggers can get the source code ). This article introduces calling Baidu AI Provided License plate recognition interface Baidu AI Open platform links , The recognition effect is also very good .
 Insert picture description here
Here we can create a license plate recognition application , Among them API Key And Secret Key Later, we will use... When calling the license plate recognition and detection interface .
 Insert picture description here
We can see the official help documents , How to Call request URL data format , towards API Service address use POST Send a request , Must be in URL With parameters access_token, You can go through the backstage API Key and Secret Key Generate . Inside API Key and Secret Key That's what we mentioned above .
 Insert picture description here
Next, let's take a look at the code example of calling the license plate recognition interface .
 Insert picture description here
How do we get the recognized license plate number ?API You can see in the document that there is words_result Dictionaries , Among them color Represents the color of the license plate ,number Represents the license plate number . So I can know the recognized license plate color and license plate number .

 Insert picture description here
The interface calling process of license plate recognition is basically clear , Now you can implement the code .

# author:CSDN-Dragon juvenile 
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 juvenile 
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 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 None

So we can get the license plate color and license plate number , The effect is as follows :

 Insert picture description here

3. License plate information display and storage

3.1 License plate information display :
# author:CSDN-Dragon juvenile 
def __show(self, result, FileName):
    #  Show table 
    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'] == ' Blue license plate ':
        self.tableWidget.item(self.RowLength - 1, 3).setBackground(QBrush(QColor(3, 128, 255)))
    elif result['Type'] == ' Green license plate ':
        self.tableWidget.item(self.RowLength - 1, 3).setBackground(QBrush(QColor(98, 198, 148)))
    elif result['Type'] == ' Yellow license plate ':
        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)))
    #  Display the recognized license plate position 
    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))

The effect is as follows :
 Insert picture description here

3.2 Information export storage :
# author:CSDN-Dragon juvenile 
def __writexls(self, DATA, path):
    wb = xlwt.Workbook();
    ws = wb.add_sheet('Data');
    # DATA.insert(0, [' File name ',' Input time ', ' license plate ', ' License plate type ', ' License plate information '])
    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, [' File name ',' Input time ', ' license plate ', ' License plate type ', ' License plate information '])
    for data in DATA:
        f.write((',').join(data) + '\n')
    f.close()
    QMessageBox.information(None, " success ", " Data saved !", QMessageBox.Yes)

def __writeFiles(self):
    path, filetype = QFileDialog.getSaveFileName(None, " Save as ", self.ProjectPath,
                                                 "Excel  workbook (*.xls);;CSV ( Comma separated )(*.csv)")
    if path == "":  #  No choice 
        return
    if filetype == 'Excel  workbook (*.xls)':
        self.__writexls(self.Data, path)
    elif filetype == 'CSV ( Comma separated )(*.csv)':
        self.__writecsv(self.Data, path)

The effect is as follows :
 Insert picture description here
The exported license plate information data is as follows :
 Insert picture description here
thus , The whole automatic license plate recognition system is completed ~ That's all for today , Continue to work hard tomorrow !
 Insert picture description here
If this article is helpful to you , Please give me three likes , Focus on , With the support of collection .

It's not easy to create , It's not good to whore for nothing , Your support and recognition , It's the biggest driving force of my creation , See you in the next article !

Dragon juvenile | writing

If there are any mistakes in this blog , Please criticize , Thank you for !

copyright notice
author[Dragon junior],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2021/08/20210822212400999u.html