国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于Python_opencv的車牌識別系統(tǒng)

這篇具有很好參考價(jià)值的文章主要介紹了基于Python_opencv的車牌識別系統(tǒng)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

基于python_opencv的車牌識別系統(tǒng)

一、說明

根據(jù)現(xiàn)有的車牌識別系統(tǒng),本人對代碼進(jìn)行了優(yōu)化,原有功能:

1、對圖片中的車牌號進(jìn)行識別,并對車牌所屬地可視化
2、將識別出的車牌號、車牌所屬地等信息導(dǎo)出Excel表格
3、根據(jù)QtDesinger設(shè)計(jì)GUI界面,將程序系統(tǒng)化

添加功能:調(diào)用攝像頭實(shí)時(shí)識別捕捉到的車牌信息,并可視化

鏈接: 最新代碼傳送門

下圖分別是調(diào)用攝像頭和直接識別圖像的畫面:
基于Python_opencv的車牌識別系統(tǒng)
基于Python_opencv的車牌識別系統(tǒng)

二、具體實(shí)現(xiàn)流程

整個(gè)項(xiàng)目為模塊化處理,按文件分為:

  1. Recognition.py(識別模塊)
  2. UI_main(主函數(shù)及UI模塊)
  3. SVM訓(xùn)練模塊
  4. 路由配置模塊
Recognition模塊

此模塊問本項(xiàng)目的核心,主要包含的功能有:
1、讀取圖像
使用cv2.imdecode()函數(shù)將圖片文件轉(zhuǎn)換成流數(shù)據(jù),賦值到內(nèi)存緩存中,便于后續(xù)圖像操作。使用cv2.resize()函數(shù)對讀取的圖像進(jìn)行縮放,以免圖像過大導(dǎo)致識別耗時(shí)過長。

    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] = 0
        if point[1] < 0:
            point[1] = 0

2、圖像預(yù)處理

    def __preTreatment(self, car_pic):
        if type(car_pic) == type("openc"):
            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)  # 圖片分辨率調(diào)整
        # cv2.imshow('Image', img)

3、利用投影法,根據(jù)設(shè)定的閾值和圖片直方圖,找出波峰,用于分隔字符,得到逐個(gè)字符圖片

 def __find_waves(self, threshold, histogram):
        up_point = -1  # 上升點(diǎn)
        is_peak = False
        if histogram[0] > threshold:
            up_point = 0
            is_peak = True
        wave_peaks = []
        for i, x in enumerate(histogram):
            if is_peak and x < threshold:
                if i - up_point > 2:
                    is_peak = False
                    wave_peaks.append((up_point, i))
            elif not is_peak and x >= threshold:
                is_peak = True
                up_point = i
        if is_peak and up_point != -1 and i - up_point > 
            wave_peaks.append((up_point, i))
        return wave_peaks

    def __seperate_card(self, img, waves):
        part_cards = []
        for wave in waves:
            part_cards.append(img[:, wave[0]:wave[1]])
        return part_cards

4、高斯去噪
使用cv2.GaussianBlur()進(jìn)行高斯去噪。使cv2.morphologyEx()函數(shù)進(jìn)行開運(yùn)算,再使用cv2.addWeighted()函數(shù)將運(yùn)算結(jié)果與原圖像做一次融合,從而去掉孤立的小點(diǎn),毛刺等噪聲。

        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)  # 開運(yùn)算
        img_opening = cv2.addWeighted(img, 1, img_opening, -1, 0);  # 與上一次開運(yùn)算結(jié)果融合

5、排除不是車牌的矩形區(qū)域

car_contours = []
        for cnt in contours:
            # 框選 生成最小外接矩形 返回值(中心(x,y), (寬,高), 旋轉(zhuǎn)角度)
            rect = cv2.minAreaRect(cnt)
            # print('寬高:',rect[1])
            area_width, area_height = rect[1]
            # 選擇寬大于高的區(qū)域
            if area_width < area_height:
                area_width, area_height = area_height, area_width
            wh_ratio = area_width / area_height
            # print('寬高比:',wh_ratio)
            # 要求矩形區(qū)域長寬比在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 )

6、分割字符并識別車牌文字
使用cv2.threshold()函數(shù)進(jìn)行二值化處理,再使用cv2.Canny()函數(shù)找到各區(qū)域邊緣,使用cv2.morphologyEx()cv2.morphologyEx()兩個(gè)函數(shù)分別進(jìn)行一次開運(yùn)算(先腐蝕運(yùn)算,再膨脹運(yùn)算)和一個(gè)閉運(yùn)算(先膨脹運(yùn)算,再腐蝕運(yùn)算),去掉較小區(qū)域,同時(shí)填平小孔,彌合小裂縫。將車牌位置凸顯出來

    def __identification(self, card_imgs, colors,model,modelchinese):
        # 識別車牌中的字符
        result = {}
        predict_result = []
        roi = None
        card_color = None
        for i, color in enumerate(colors):
            if color in ("blue", "yellow", "green"):
                card_img = card_imgs[i]
                # old_img = card_img
                # 做一次銳化處理
                kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)  # 銳化
                card_img = cv2.filter2D(card_img, -1, kernel=kernel)
                # cv2.imshow("custom_blur", card_img)

                # RGB轉(zhuǎn)GARY
                gray_img = cv2.cvtColor(card_img, cv2.COLOR_BGR2GRAY)
                # cv2.imshow('gray_img', gray_img)

                # 黃、綠車牌字符比背景暗、與藍(lán)車牌剛好相反,所以黃、綠車牌需要反向
                if color == "green" or color == "yellow":
                    gray_img = cv2.bitwise_not(gray_img)
                # 二值化
                ret, gray_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
                # cv2.imshow('gray_img', gray_img)

                # 查找水平直方圖波峰
                x_histogram = np.sum(gray_img, axis=1)
                # 最小值
                x_min = np.min(x_histogram)
                # 均值
                x_average = np.sum(x_histogram) / x_histogram.shape[0]
                x_threshold = (x_min + x_average) / 2
                wave_peaks = self.__find_waves(x_threshold, x_histogram)
                if len(wave_peaks) == 0:
                    continue

                # 認(rèn)為水平方向,最大的波峰為車牌區(qū)域
                wave = max(wave_peaks, key=lambda x: x[1] - x[0])
                gray_img = gray_img[wave[0]:wave[1]]
                # cv2.imshow('gray_img', gray_img)

                # 查找垂直直方圖波峰
                row_num, col_num = gray_img.shape[:2]
                # 去掉車牌上下邊緣1個(gè)像素,避免白邊影響閾值判斷
                gray_img = gray_img[1:row_num - 1]
                # cv2.imshow('gray_img', gray_img)
                y_histogram = np.sum(gray_img, axis=0)
                y_min = np.min(y_histogram)
                y_average = np.sum(y_histogram) / y_histogram.shape[0]
                y_threshold = (y_min + y_average) / 5  # U和0要求閾值偏小,否則U和0會被分成兩半

                wave_peaks = self.__find_waves(y_threshold, y_histogram)
                # print(wave_peaks)

                # for wave in wave_peaks:
                #	cv2.line(card_img, pt1=(wave[0], 5), pt2=(wave[1], 5), color=(0, 0, 255), thickness=2)
                # 車牌字符數(shù)應(yīng)大于6
                if len(wave_peaks) <= 6:
                    #   print(wave_peaks)
                    continue

                wave = max(wave_peaks, key=lambda x: x[1] - x[0])
                max_wave_dis = wave[1] - wave[0]
                # 判斷是否是左側(cè)車牌邊緣
                if wave_peaks[0][1] - wave_peaks[0][0] < max_wave_dis / 3 and wave_peaks[0][0] == 0:
                    wave_peaks.pop(0)

                # 組合分離漢字
                cur_dis = 0
                for i, wave in enumerate(wave_peaks):
                    if wave[1] - wave[0] + cur_dis > max_wave_dis * 0.6:
                        break
                    else:
                        cur_dis += wave[1] - wave[0]
                if i > 0:
                    wave = (wave_peaks[0][0], wave_peaks[i][1])
                    wave_peaks = wave_peaks[i + 1:]
                    wave_peaks.insert(0, wave)

                # 去除車牌上的分隔點(diǎn)
                point = wave_peaks[2]
                if point[1] - point[0] < max_wave_dis / 3:
                    point_img = gray_img[:, point[0]:point[1]]
                    if np.mean(point_img) < 255 / 5:
                        wave_peaks.pop(2)

                if len(wave_peaks) <= 6:
                    # print("peak less 2:", wave_peaks)
                    continue
                # print(wave_peaks)
                # 分割牌照字符
                part_cards = self.__seperate_card(gray_img, wave_peaks)

                # 分割輸出
                #for i, part_card in enumerate(part_cards):
                #    cv2.imshow(str(i), part_card)

                # 識別
                for i, part_card in enumerate(part_cards):
                    # 可能是固定車牌的鉚釘
                    if np.mean(part_card) < 255 / 5:
                        continue
                    part_card_old = part_card
                    w = abs(part_card.shape[1] - self.SZ) // 2

                    # 邊緣填充
                    part_card = cv2.copyMakeBorder(part_card, 0, 0, w, w, cv2.BORDER_CONSTANT, value=[0, 0, 0])
                    # cv2.imshow('part_card', part_card)

                    # 圖片縮放(縮?。?/span>
                    part_card = cv2.resize(part_card, (self.SZ, self.SZ), interpolation=cv2.INTER_AREA)
                    # cv2.imshow('part_card', part_card)

                    part_card = SVM_Train.preprocess_hog([part_card])

                    if i == 0:  # 識別漢字
                        resp = self.modelchinese.predict(part_card)  # 匹配樣本
                        charactor = self.provinces[int(resp[0]) - self.PROVINCE_START]
                        # print(charactor)
                    else:  # 識別字母
                        resp = self.model.predict(part_card)  # 匹配樣本
                        charactor = chr(resp[0])
                        # print(charactor)
                    # 判斷最后一個(gè)數(shù)是否是車牌邊緣,假設(shè)車牌邊緣被認(rèn)為是1
                    if charactor == "1" and i == len(part_cards) - 1:
                        if color == 'blue' and len(part_cards) > 7:
                            if part_card_old.shape[0] / part_card_old.shape[1] >= 7:  # 1太細(xì),認(rèn)為是邊緣
                                continue
                        elif color == 'blue' and len(part_cards) > 7:
                            if part_card_old.shape[0] / part_card_old.shape[1] >= 7:  # 1太細(xì),認(rèn)為是邊緣
                                continue
                        elif color == 'green' and len(part_cards) > 8:
                            if part_card_old.shape[0] / part_card_old.shape[1] >= 7:  # 1太細(xì),認(rèn)為是邊緣
                                continue
                    predict_result.append(charactor)
                roi = card_img  # old_img
                card_color = color
                break

        return predict_result, roi, card_color  # 識別到的字符、定位的車牌圖像、車牌顏色

UI_main模塊

此模塊主要包含UI界面的設(shè)計(jì)的控件,圖片識別的入口函數(shù),攝像頭識別入口函數(shù),Excel表格生成函數(shù):

1、UI界面主類

class Ui_MainWindow(object):

    def __init__(self):
        self.RowLength = 0
        self.Data = [['文件名稱', '錄入時(shí)間', '車牌號碼', '車牌類型', '識別耗時(shí)', '車牌信息']]

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1213, 680)
        MainWindow.setFixedSize(1213, 680)  # 設(shè)置窗體固定大小
        MainWindow.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)

        self.centralwidget = QtWidgets.QWidget(MainWindow)    #圖片區(qū)域
        self.centralwidget.setObjectName("centralwidget")
        self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
        self.scrollArea.setGeometry(QtCore.QRect(690, 10, 511, 491))
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(10, 10, 509, 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, 441))
        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)  #設(shè)置布局
        self.tableWidget.setGeometry(QtCore.QRect(10, 40, 651, 581))  # 581))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(6)
        self.tableWidget.setColumnWidth(0, 106)  # 設(shè)置1列的寬度
        self.tableWidget.setColumnWidth(1, 106)  # 設(shè)置2列的寬度
        self.tableWidget.setColumnWidth(2, 106)  # 設(shè)置3列的寬度
        self.tableWidget.setColumnWidth(3, 106)  # 設(shè)置4列的寬度
        self.tableWidget.setColumnWidth(4, 106)  # 設(shè)置5列的寬度
        self.tableWidget.setColumnWidth(5, 106)  # 設(shè)置6列的寬度
        self.tableWidget.setHorizontalHeaderLabels(["圖片名稱", "錄入時(shí)間", "識別耗時(shí)", "車牌號碼", "車牌類型", "車牌信息"])
        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(10, 50, 80, 30))
        self.pushButton_2.setObjectName("pushButton_2")

        self.pushButton = QtWidgets.QPushButton(self.scrollAreaWidgetContents_4)
        self.pushButton.setGeometry(QtCore.QRect(10, 90, 80, 30))
        self.pushButton.setObjectName("pushButton")

        self.pushButton_3 = QtWidgets.QPushButton(self.scrollAreaWidgetContents_4)
        self.pushButton_3.setGeometry(QtCore.QRect(100, 50, 50, 70))
        self.pushButton_3.setObjectName("pushButton_3")

        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)  # 設(shè)置點(diǎn)擊事件
        self.pushButton_2.clicked.connect(self.__writeFiles)  # 設(shè)置點(diǎn)擊事件
        self.pushButton_3.clicked.connect(self.__openVideo)  #設(shè)置事件

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.ProjectPath = os.getcwd()  # 獲取當(dāng)前工程文件位置

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "車牌識別系統(tǒng)"))
        self.label_0.setText(_translate("MainWindow", "原始圖片:"))
        self.label.setText(_translate("MainWindow", ""))
        self.label_1.setText(_translate("MainWindow", "識別結(jié)果:"))
        self.label_2.setText(_translate("MainWindow", "車牌區(qū)域:"))
        self.label_3.setText(_translate("MainWindow", ""))
        self.pushButton.setText(_translate("MainWindow", "打開文件"))
        self.pushButton_2.setText(_translate("MainWindow", "導(dǎo)出數(shù)據(jù)"))
        self.pushButton_3.setText(_translate("MainWindow", "攝像"))
        self.label_4.setText(_translate("MainWindow", "控制面板:"))
        self.scrollAreaWidgetContents_1.show()

2、識別入口函數(shù)

    def __vlpr(self, path):
        PR = PlateRecognition()
        result = PR.VLPR(path)
        return result

3、寫入及導(dǎo)出Excel表格文件

    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(str(result['UseTime']) + '秒'))
        self.tableWidget.setItem(self.RowLength - 1, 3, QTableWidgetItem(result['Number']))
        self.tableWidget.setItem(self.RowLength - 1, 4, QTableWidgetItem(result['Type']))
        if result['Type'] == '藍(lán)色牌照':
            self.tableWidget.item(self.RowLength - 1, 4).setBackground(QBrush(QColor(3, 128, 255)))
        elif result['Type'] == '綠色牌照':
            self.tableWidget.item(self.RowLength - 1, 4).setBackground(QBrush(QColor(98, 198, 148)))
        elif result['Type'] == '黃色牌照':
            self.tableWidget.item(self.RowLength - 1, 4).setBackground(QBrush(QColor(242, 202, 9)))
        self.tableWidget.setItem(self.RowLength - 1, 5, QTableWidgetItem(result['From']))

        # 顯示識別到的車牌位置
        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):
        wb = xlwt.Workbook();
        ws = wb.add_sheet('Data');

        for i, Data in enumerate(DATA):
            for j, data in enumerate(Data):
                ws.write(i, j, data)
        wb.save(path)
        QMessageBox.information(None, "成功", "數(shù)據(jù)已保存!", QMessageBox.Yes)

    def __writecsv(self, DATA, path):
        f = open(path, 'w')
        # DATA.insert(0, ['文件名稱','錄入時(shí)間', '車牌號碼', '車牌類型', '識別耗時(shí)', '車牌信息'])
        for data in DATA:
            f.write((',').join(data) + '\n')
        f.close()
        QMessageBox.information(None, "成功", "數(shù)據(jù)已保存!", 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)

4、圖片識別入口

    def __openimage(self):
        path, filetype = QFileDialog.getOpenFileName(None, "選擇文件", self.ProjectPath,
                                                     "JPEG Image (*.jpg);;PNG Image (*.png);;JFIF Image (*.jfif)")  # ;;All Files (*)
        if path == "":  # 未選擇文件
            return
        filename = path.split('/')[-1]

        # 尺寸適配
        size = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR).shape
        if size[0] / size[1] > 1.0907:
            w = 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 = 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)    #保存jpg
        result = self.__vlpr(path)  #識別
        if result is not None:
            self.Data.append(
                [filename, result['InputTime'], result['Number'], result['Type'], str(result['UseTime']) + '秒',
                 result['From']])
            self.__show(result, filename)
        else:
            QMessageBox.warning(None, "Error", "無法識別此圖像!", QMessageBox.Yes)

5、攝像頭識別入口

    def __openVideo(self):
        cap = cv2.VideoCapture(0)
        while True:
            success, img = cap.read()
            img1 = cv2.flip(img, 1)
            cv2.imshow("VideoData", img1)

            k = cv2.waitKey(1)

            if cv2.getWindowProperty('VideoData', cv2.WND_PROP_VISIBLE) < 1:
                break
            elif k == ord("s"):
                cv2.imwrite("index2.jpg", img1)   #讀取攝像頭
                cv2.destroyAllWindows()
        cap.release()

6、重寫MainWindow窗口

class MainWindow(QtWidgets.QMainWindow):

    def closeEvent(self, event):
        reply = QtWidgets.QMessageBox.question(self, '提示',
                                               "是否要退出程序?\n提示:退出后將丟失所有識別數(shù)據(jù)",
                                               QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                                               QtWidgets.QMessageBox.No)
        if reply == QtWidgets.QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
SVM訓(xùn)練模塊

此模塊主要用于對模型的準(zhǔn)確性進(jìn)行訓(xùn)練,包含字符中英文、數(shù)字的識別、圖片尺寸的訓(xùn)練,最后將模型保存在svmchinese.dat中:文章來源地址http://www.zghlxwxcb.cn/news/detail-414019.html


import cv2
import os
import numpy as np
from numpy.linalg import norm
from args import args

class StatModel(object):
    def load(self, fn):
        self.model = self.model.load(fn)

    def save(self, fn):
        self.model.save(fn)

class SVM(StatModel):
    def __init__(self, C=1, gamma=0.5):
        self.model = cv2.ml.SVM_create()
        self.model.setGamma(gamma)
        self.model.setC(C)
        self.model.setKernel(cv2.ml.SVM_RBF)
        self.model.setType(cv2.ml.SVM_C_SVC)
        # 不能保證包括所有省份

    # 訓(xùn)練svm
    def train(self, samples, responses):
        self.model.train(samples, cv2.ml.ROW_SAMPLE, responses)

    # 字符識別
    def predict(self, samples):
        r = self.model.predict(samples)
        return r[1].ravel()

# 定義參數(shù)
SZ = args.Size  # 訓(xùn)練圖片長寬
MAX_WIDTH = args.MAX_WIDTH  # 原始圖片最大寬度
Min_Area = args.Min_Area  # 車牌區(qū)域允許最大面積
PROVINCE_START = args.PROVINCE_START
provinces = args.provinces

# 來自opencv的sample,用于svm訓(xùn)練
def deskew(img):
    m = cv2.moments(img)
    if abs(m['mu02']) < 1e-2:
        return img.copy()
    skew = m['mu11'] / m['mu02']
    M = np.float32([[1, skew, -0.5 * SZ * skew], [0, 1, 0]])
    img = cv2.warpAffine(img, M, (SZ, SZ), flags=cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR)
    return img

# 來自opencv的sample,用于svm訓(xùn)練
def preprocess_hog(digits):
    samples = []
    for img in digits:
        gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
        gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
        mag, ang = cv2.cartToPolar(gx, gy)
        bin_n = 16
        bin = np.int32(bin_n * ang / (2 * np.pi))
        bin_cells = bin[:10, :10], bin[10:, :10], bin[:10, 10:], bin[10:, 10:]
        mag_cells = mag[:10, :10], mag[10:, :10], mag[:10, 10:], mag[10:, 10:]
        hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
        hist = np.hstack(hists)

        # transform to Hellinger kernel
        eps = 1e-7
        hist /= hist.sum() + eps
        hist = np.sqrt(hist)
        hist /= norm(hist) + eps

        samples.append(hist)
    return np.float32(samples)

def train_svm(path):
    # 識別英文字母和數(shù)字
    Model = SVM(C=1, gamma=0.5)
    # 識別中文
    Modelchinese = SVM(C=1, gamma=0.5)
    # 英文字母和數(shù)字部分訓(xùn)練
    chars_train = []
    chars_label = []

    for root, dirs, files in os.walk(os.path.join(path,'chars')):
        if len(os.path.basename(root)) > 1:
            continue
        root_int = ord(os.path.basename(root))
        for filename in files:
            print('input:{}'.format(filename))
            filepath = os.path.join(root, filename)
            digit_img = cv2.imread(filepath)
            digit_img = cv2.cvtColor(digit_img, cv2.COLOR_BGR2GRAY)
            chars_train.append(digit_img)
            chars_label.append(root_int)

    chars_train = list(map(deskew, chars_train))
    chars_train = preprocess_hog(chars_train)
    chars_label = np.array(chars_label)
    Model.train(chars_train, chars_label)

    if not os.path.exists("svm.dat"):
        # 保存模型
        Model.save("svm.dat")
    else:
        # 更新模型
        os.remove("svm.dat")
        Model.save("svm.dat")

    # 中文部分訓(xùn)練
    chars_train = []
    chars_label = []

    for root, dirs, files in os.walk(os.path.join(path,'charsChinese')):
        if not os.path.basename(root).startswith("zh_"):
            continue
        pinyin = os.path.basename(root)
        index = provinces.index(pinyin) + PROVINCE_START + 1  # 1是拼音對應(yīng)的漢字
        for filename in files:
            print('input:{}'.format(filename))
            filepath = os.path.join(root, filename)
            digit_img = cv2.imread(filepath)
            digit_img = cv2.cvtColor(digit_img, cv2.COLOR_BGR2GRAY)
            chars_train.append(digit_img)
            chars_label.append(index)
    chars_train = list(map(deskew, chars_train))
    chars_train = preprocess_hog(chars_train)
    chars_label = np.array(chars_label)
    Modelchinese.train(chars_train, chars_label)

    if not os.path.exists("svmchinese.dat"):
        # 保存模型
        Modelchinese.save("svmchinese.dat")
    else:
        # 更新模型
        os.remove("svmchinese.dat")
        Modelchinese.save("svmchinese.dat")

if __name__ == '__main__':
    train_svm('train')
    print('完成')

路由配置模塊

from _collections import OrderedDict
# 導(dǎo)入Flask類
from flask import Flask, request, jsonify
from json_utils import jsonify
import numpy as np
import cv2
import time
from collections import OrderedDict
from Recognition import PlateRecognition

# 實(shí)例化
app = Flask(__name__)
PR = PlateRecognition()

# 設(shè)置編碼-否則返回?cái)?shù)據(jù)中文時(shí)候-亂碼
app.config['JSON_AS_ASCII'] = False

# route()方法用于設(shè)定路由;類似spring路由配置
@app.route('/', methods=['POST'])  # 在線識別
def forecast():
    # 獲取輸入數(shù)據(jù)
    stat = time.time()
    file = request.files['image']
    img_bytes = file.read()
    image = np.asarray(bytearray(img_bytes), dtype="uint8")
    image = cv2.imdecode(image, cv2.IMREAD_COLOR)
    RES = PR.VLPR(image)
    if RES is not None:
        result = OrderedDict(
            Error=0,
            Errmsg='success',
            InputTime=RES['InputTime'],
            UseTime='{:.2f}'.format(time.time() - stat),  # RES['UseTime'],
            Number=RES['Number'],
            From=RES['From'],
            Type=RES['Type'],
            List=RES['List'])
    else:
        result = OrderedDict(
            Error=1,
            Errmsg='unsuccess')
    return jsonify(result)


if __name__ == '__main__':
    # app.run(host, port, debug, options)
    # 默認(rèn)值:host=127.0.0.1(localhost), port=5000, debug=false
    app.run()

    # 本地路由地址,局域網(wǎng)下的主機(jī)均可通過該地址完成POST請求
    # app.run(host='192.168.1.100' )

    # 部署到服務(wù)器
    # from waitress import serve
    # serve(app, host=' IP  ', port=5000)


到了這里,關(guān)于基于Python_opencv的車牌識別系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Python_Opencv圖像處理框架】信用卡數(shù)字識別項(xiàng)目

    【Python_Opencv圖像處理框架】信用卡數(shù)字識別項(xiàng)目

    本篇文章是opencv學(xué)習(xí)的第六篇文章,前面主要講解了對圖像的一些基本操作,這篇文章我們就開始大展身手,將前面所學(xué)的基礎(chǔ)操作活學(xué)活用。既能復(fù)習(xí)基礎(chǔ)操作,又能學(xué)到一些新的知識。作為初學(xué)者,我盡己所能,但仍會存在疏漏的地方,希望各位看官不吝指正?? 我們通

    2024年02月03日
    瀏覽(90)
  • 基于Python的車牌識別系統(tǒng)實(shí)現(xiàn)

    基于Python的車牌識別系統(tǒng)實(shí)現(xiàn)

    本文將以基于Python的車牌識別系統(tǒng)實(shí)現(xiàn)為方向,介紹車牌識別技術(shù)的基本原理、常用算法和方法,并詳細(xì)講解如何利用Python語言實(shí)現(xiàn)一個(gè)完整的車牌識別系統(tǒng)。

    2024年02月08日
    瀏覽(20)
  • 機(jī)器視覺畢業(yè)設(shè)計(jì) python車牌識別系統(tǒng) - opencv 深度學(xué)習(xí) 機(jī)器學(xué)習(xí)

    機(jī)器視覺畢業(yè)設(shè)計(jì) python車牌識別系統(tǒng) - opencv 深度學(xué)習(xí) 機(jī)器學(xué)習(xí)

    # 1 前言 ?? 基于python 機(jī)器視覺 的車牌識別系統(tǒng) ??學(xué)長這里給一個(gè)題目綜合評分(每項(xiàng)滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點(diǎn):2分 車牌識別其實(shí)是個(gè)經(jīng)典的機(jī)器視覺任務(wù)了,通過圖像處理技術(shù)檢測、定位、識別車牌上的字符,實(shí)現(xiàn)計(jì)算機(jī)對車牌的智能管理功能。如今在

    2024年02月13日
    瀏覽(28)
  • 基于Python的車牌識別系統(tǒng)的實(shí)現(xiàn)

    基于Python的車牌識別系統(tǒng)的實(shí)現(xiàn)

    目錄 第1章 緒論 1 1.1研究背景與意義 1 1.2課題研究現(xiàn)狀 1 1.3研究目標(biāo) 1 1.4研究內(nèi)容與論文組織結(jié)構(gòu) 1 第2章 相關(guān)理論與關(guān)鍵技術(shù) 3 2.1計(jì)算機(jī)視覺概述 3 2.2 Opencv計(jì)算機(jī)視覺函數(shù)庫 3 2.3車牌規(guī)律 4 2.4車牌識別技術(shù)概要 5 2.5車牌識別系統(tǒng)流程 5 2.5.1車牌圖像采集 5 2.5.2圖像預(yù)處理 5

    2024年02月06日
    瀏覽(19)
  • 車牌識別系統(tǒng)Python,基于深度學(xué)習(xí)CNN卷積神經(jīng)網(wǎng)絡(luò)算法

    車牌識別系統(tǒng)Python,基于深度學(xué)習(xí)CNN卷積神經(jīng)網(wǎng)絡(luò)算法

    車牌識別系統(tǒng),基于Python實(shí)現(xiàn),通過TensorFlow搭建CNN卷積神經(jīng)網(wǎng)絡(luò)模型,對車牌數(shù)據(jù)集圖片進(jìn)行訓(xùn)練最后得到模型,并基于Django框架搭建網(wǎng)頁端平臺,實(shí)現(xiàn)用戶在網(wǎng)頁端輸入一張圖片識別其結(jié)果,并基于Pyqt5搭建桌面端可視化界面。 在智能交通和車輛監(jiān)控領(lǐng)域,車牌識別技術(shù)扮

    2024年02月07日
    瀏覽(102)
  • 車牌識別 opencv python(簡單版)

    車牌識別 opencv python(簡單版)

    實(shí)驗(yàn)?zāi)繕?biāo) 使用形態(tài)學(xué)處理,識別圖片中車牌的位置,并識別每個(gè)字符的位置 實(shí)驗(yàn)原理 1.車牌識別: (1)車牌的背景色是 藍(lán)色 ,所以先提取圖中藍(lán)色的部分,轉(zhuǎn)化為二值圖像(藍(lán)色部分為1,其余為0)。 (2)再檢測 邊緣 ,標(biāo)出邊緣的外接矩形,根據(jù)此矩形的 長寬比 和面積,就

    2024年02月06日
    瀏覽(20)
  • 【Python實(shí)戰(zhàn)】——Python+Opencv是實(shí)現(xiàn)車牌自動(dòng)識別

    【Python實(shí)戰(zhàn)】——Python+Opencv是實(shí)現(xiàn)車牌自動(dòng)識別

    ??CSDN小墨曉末: https://blog.csdn.net/jd1813346972 ???個(gè)人介紹: 研一|統(tǒng)計(jì)學(xué)|干貨分享 ???????? 擅長Python、Matlab、R等主流編程軟件 ???????? 累計(jì)十余項(xiàng)國家級比賽獎(jiǎng)項(xiàng),參與研究經(jīng)費(fèi)10w、40w級橫向 該篇文章將以實(shí)戰(zhàn)形式演示利用Python結(jié)合Opencv實(shí)現(xiàn)車牌識

    2024年03月11日
    瀏覽(31)
  • 無法正確識別車牌(Python、OpenCv、Tesseract)

    我正在嘗試識別車牌,但出現(xiàn)了錯(cuò)誤,例如錯(cuò)誤/未讀取字符 以下是每個(gè)步驟的可視化: 從顏色閾值+變形關(guān)閉獲得遮罩 以綠色突出顯示的車牌輪廓過濾器 將板輪廓粘貼到空白遮罩上 Tesseract OCR的預(yù)期結(jié)果 BP 1309 GD 但我得到的結(jié)果是 BP 1309 6D 我試著把輪廓切成3片 是的,它是有

    2024年02月13日
    瀏覽(18)
  • 基于OpenCV+LPR模型端對端智能車牌識別——深度學(xué)習(xí)和目標(biāo)檢測算法應(yīng)用(含Python+Andriod全部工程源碼)+CCPD數(shù)據(jù)集

    基于OpenCV+LPR模型端對端智能車牌識別——深度學(xué)習(xí)和目標(biāo)檢測算法應(yīng)用(含Python+Andriod全部工程源碼)+CCPD數(shù)據(jù)集

    本項(xiàng)目基于CCPD數(shù)據(jù)集和LPR(License Plate Recognition,車牌識別)模型,結(jié)合深度學(xué)習(xí)和目標(biāo)檢測等先進(jìn)技術(shù),構(gòu)建了一個(gè)全面的車牌識別系統(tǒng),實(shí)現(xiàn)了從車牌檢測到字符識別的端到端解決方案。 首先,我們利用CCPD數(shù)據(jù)集,其中包含大量的中文車牌圖像,用于模型的訓(xùn)練和驗(yàn)證。

    2024年02月09日
    瀏覽(23)
  • 基于opencv的車牌識別系統(tǒng)(UI界面采用tkinter設(shè)計(jì))

    基于opencv的車牌識別系統(tǒng)(UI界面采用tkinter設(shè)計(jì))

    本系統(tǒng)采用python語言搭配opencv進(jìn)行開發(fā),在傳統(tǒng)的車牌識別項(xiàng)目上進(jìn)行改進(jìn),開發(fā)獨(dú)特的GUI界面,方便使用者的使用。 需要源碼的朋友點(diǎn)贊、關(guān)注我、再私信我獲取源碼,如果未能及時(shí)回復(fù)可以留下郵箱耐心等待奧 先上運(yùn)行截圖(下圖分別為圖片識別和攝像頭識別結(jié)果) 項(xiàng)

    2023年04月23日
    瀏覽(92)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包