├── .idea ├── .gitignore ├── VLPR.iml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── other.xml └── vcs.xml ├── README.md ├── app ├── RBG_HSV.py ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── chuli.cpython-36.pyc │ ├── img_function.cpython-36.pyc │ ├── img_math.cpython-36.pyc │ └── img_recognition.cpython-36.pyc ├── chepai │ ├── 1.jpg │ ├── 10.jpg │ ├── 11.jpg │ ├── 12.jpg │ ├── 13.jpg │ ├── 14.jpg │ ├── 15.jpg │ ├── 16.jpg │ ├── 17.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── 5.jpg │ ├── 6.jpg │ ├── 7.jpg │ ├── 8.jpg │ └── 9.jpg ├── chuli.py ├── favicon.ico ├── img.png ├── img_function.py ├── img_math.py ├── img_recognition.py ├── main.py ├── pic │ ├── hy.png │ └── locate.png ├── svm.dat ├── svmchinese.dat └── tmp │ ├── chechar1.jpg │ ├── chechar2.jpg │ ├── chechar3.jpg │ ├── chechar4.jpg │ ├── chechar5.jpg │ ├── chechar6.jpg │ ├── chechar7.jpg │ ├── chechar8.jpg │ ├── chepai_xingtai.jpg │ ├── gray_img.jpg │ ├── img_caijian.jpg │ ├── img_dst.jpg │ ├── img_edge.jpg │ ├── img_gray.jpg │ ├── img_opening.jpg │ ├── img_threshold.jpg │ ├── img_xingtai.jpg │ └── oldimg.jpg └── exe ├── chepai ├── 1.jpg ├── 10.jpg ├── 11.jpg ├── 12.jpg ├── 13.jpg ├── 14.jpg ├── 15.jpg ├── 16.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg ├── 6.jpg ├── 7.jpg ├── 8.jpg └── 9.jpg ├── main.exe ├── pic ├── hy.png └── locate.png ├── svm.dat └── svmchinese.dat /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /../../../../../:\code\Python\license-plate-recognition\.idea/dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/VLPR.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/other.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 基于OpenCV的车牌识别系统设计与实现 2 |

3 | 4 | 5 | ### 运行环境 6 | python 3.6.2 7 | 8 | opencv-python 4.5.3.56 9 | 10 | pillow 8.3.1 11 | 12 | numpy 1.19.5 13 | 14 | tk 8.6.11 15 |

16 | 17 | ### 如果你觉得有用 18 |

19 | 20 | 21 |

22 | -------------------------------------------------------------------------------- /app/RBG_HSV.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | 4 | def cv_show(name, img): 5 | cv2.imshow(name, img) 6 | cv2.waitKey(0) 7 | cv2.destroyAllWindows() 8 | 9 | 10 | #read 11 | img = cv2.imread("img.png") 12 | 13 | img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 14 | 15 | img_hsv 16 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/__init__.py -------------------------------------------------------------------------------- /app/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /app/__pycache__/chuli.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/__pycache__/chuli.cpython-36.pyc -------------------------------------------------------------------------------- /app/__pycache__/img_function.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/__pycache__/img_function.cpython-36.pyc -------------------------------------------------------------------------------- /app/__pycache__/img_math.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/__pycache__/img_math.cpython-36.pyc -------------------------------------------------------------------------------- /app/__pycache__/img_recognition.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/__pycache__/img_recognition.cpython-36.pyc -------------------------------------------------------------------------------- /app/chepai/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/1.jpg -------------------------------------------------------------------------------- /app/chepai/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/10.jpg -------------------------------------------------------------------------------- /app/chepai/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/11.jpg -------------------------------------------------------------------------------- /app/chepai/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/12.jpg -------------------------------------------------------------------------------- /app/chepai/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/13.jpg -------------------------------------------------------------------------------- /app/chepai/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/14.jpg -------------------------------------------------------------------------------- /app/chepai/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/15.jpg -------------------------------------------------------------------------------- /app/chepai/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/16.jpg -------------------------------------------------------------------------------- /app/chepai/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/17.jpg -------------------------------------------------------------------------------- /app/chepai/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/2.jpg -------------------------------------------------------------------------------- /app/chepai/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/3.jpg -------------------------------------------------------------------------------- /app/chepai/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/4.jpg -------------------------------------------------------------------------------- /app/chepai/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/5.jpg -------------------------------------------------------------------------------- /app/chepai/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/6.jpg -------------------------------------------------------------------------------- /app/chepai/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/7.jpg -------------------------------------------------------------------------------- /app/chepai/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/8.jpg -------------------------------------------------------------------------------- /app/chepai/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/chepai/9.jpg -------------------------------------------------------------------------------- /app/chuli.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | from tkinter import ttk 3 | from PIL import Image, ImageTk 4 | import img_math,cv2,os 5 | 6 | class App(ttk.Frame): 7 | width = 750 #宽 8 | heigh = 400 #高 9 | def __init__(self, win): 10 | ttk.Frame.__init__(self,win) 11 | self.pack() 12 | win.title("车牌识别系统") 13 | win.geometry('+300+200') 14 | win.minsize(App.width,App.heigh) 15 | 16 | frame_1 = ttk.Frame(self) 17 | frame_1.grid(column=0, row=0) 18 | 19 | frame_2 = ttk.Frame(self) 20 | frame_2.grid(column=1, row=0) 21 | 22 | frame_3 = ttk.Frame(self) 23 | frame_3.grid(column=2, row=0) 24 | 25 | frame_4 = ttk.Frame(self) 26 | frame_4.grid(column=0, row=1) 27 | 28 | 29 | 30 | #显示分离后的车牌字符 31 | frame_5111 = ttk.Frame(self) 32 | frame_5111.grid(column=1, row=1) 33 | 34 | #显示分离后的车牌字符 35 | frame_5 = ttk.Frame(frame_5111) 36 | frame_5.pack() 37 | frame_5222 = ttk.Frame(frame_5111) 38 | frame_5222.pack() 39 | 40 | 41 | frame_6 = ttk.Frame(self) 42 | frame_6.grid(column=2, row=1) 43 | 44 | self.image_1 = ttk.Label(frame_1) 45 | self.image_1.pack() 46 | self.image_11 = ttk.Label(frame_1,text='灰度变化',font=('Times', '14')) 47 | self.image_11.pack() 48 | 49 | self.image_2 = ttk.Label(frame_2) 50 | self.image_2.pack() 51 | self.image_22 = ttk.Label(frame_2,text='边缘检测',font=('Times', '14')) 52 | self.image_22.pack() 53 | 54 | self.image_3 = ttk.Label(frame_3) 55 | self.image_3.pack() 56 | self.image_33 = ttk.Label(frame_3,text='形态学处理',font=('Times', '14')) 57 | self.image_33.pack() 58 | 59 | self.image_4 = ttk.Label(frame_4) 60 | self.image_4.pack() 61 | self.image_44 = ttk.Label(frame_4,text='车牌定位',font=('Times', '14')) 62 | self.image_44.pack() 63 | 64 | self.image_5_1 = ttk.Label(frame_5) 65 | self.image_5_1.grid(column=0, row=0) 66 | self.image_5_2 = ttk.Label(frame_5) 67 | self.image_5_2.grid(column=1, row=0) 68 | self.image_5_3 = ttk.Label(frame_5) 69 | self.image_5_3.grid(column=2, row=0) 70 | self.image_5_4 = ttk.Label(frame_5) 71 | self.image_5_4.grid(column=3, row=0) 72 | self.image_5_5 = ttk.Label(frame_5) 73 | self.image_5_5.grid(column=4, row=0) 74 | self.image_5_6 = ttk.Label(frame_5) 75 | self.image_5_6.grid(column=5, row=0) 76 | self.image_5_7 = ttk.Label(frame_5) 77 | self.image_5_7.grid(column=6, row=0) 78 | self.image_5_8 = ttk.Label(frame_5222,text='字符分割',font=('Times', '14')) 79 | self.image_5_8.pack() 80 | 81 | # self.image_6 = ttk.Label(frame_6) 82 | # self.image_6.pack() 83 | chu = ttk.Button( 84 | frame_6, text="退出", width=20, command=self.close_window) 85 | chu.grid(column=0, row=2) 86 | self.jiazai() 87 | 88 | def get_imgtk(self, img_bgr): 89 | img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) 90 | im = Image.fromarray(img) 91 | pil_image_resized = im.resize((250,170),Image.ANTIALIAS) 92 | imgtk = ImageTk.PhotoImage(image=pil_image_resized) 93 | return imgtk 94 | 95 | def get_imgtk_1(self, img_bgr): 96 | img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) 97 | im = Image.fromarray(img) 98 | pil_image_resized = im.resize((30,30),Image.ANTIALIAS) 99 | imgtk = ImageTk.PhotoImage(image=pil_image_resized) 100 | return imgtk 101 | 102 | def jiazai(self): 103 | img_1 = img_math.img_read("tmp/img_gray.jpg") 104 | self.img1 = self.get_imgtk(img_1) 105 | self.image_1.configure(image=self.img1) 106 | 107 | img_2 = img_math.img_read("tmp/img_edge.jpg") 108 | self.img2 = self.get_imgtk(img_2) 109 | self.image_2.configure(image=self.img2) 110 | 111 | img_3 = img_math.img_read("tmp/img_xingtai.jpg") 112 | self.img3 = self.get_imgtk(img_3) 113 | self.image_3.configure(image=self.img3) 114 | 115 | img_4 = img_math.img_read("tmp/img_caijian.jpg") 116 | self.img4 = self.get_imgtk(img_4) 117 | self.image_4.configure(image=self.img4) 118 | 119 | 120 | img_5_1 = img_math.img_read("tmp/chechar1.jpg") 121 | self.img51 = self.get_imgtk_1(img_5_1) 122 | self.image_5_1.configure(image=self.img51) 123 | 124 | img_5_2 = img_math.img_read("tmp/chechar2.jpg") 125 | self.img52 = self.get_imgtk_1(img_5_2) 126 | self.image_5_2.configure(image=self.img52) 127 | 128 | img_5_3 = img_math.img_read("tmp/chechar3.jpg") 129 | self.img53 = self.get_imgtk_1(img_5_3) 130 | self.image_5_3.configure(image=self.img53) 131 | 132 | img_5_4 = img_math.img_read("tmp/chechar4.jpg") 133 | self.img54 = self.get_imgtk_1(img_5_4) 134 | self.image_5_4.configure(image=self.img54) 135 | 136 | img_5_5 = img_math.img_read("tmp/chechar5.jpg") 137 | self.img55 = self.get_imgtk_1(img_5_5) 138 | self.image_5_5.configure(image=self.img55) 139 | 140 | img_5_6 = img_math.img_read("tmp/chechar6.jpg") 141 | self.img56 = self.get_imgtk_1(img_5_6) 142 | self.image_5_6.configure(image=self.img56) 143 | 144 | img_5_7 = img_math.img_read("tmp/chechar7.jpg") 145 | self.img57 = self.get_imgtk_1(img_5_7) 146 | self.image_5_7.configure(image=self.img57) 147 | 148 | def close_window(self): 149 | uu = ['tmp/' + i for i in os.listdir('tmp/')] 150 | for i in uu: 151 | os.remove(i) 152 | print("destroy") 153 | root.destroy() 154 | 155 | if __name__ == '__main__': 156 | root = tk.Tk() 157 | app = App(root) 158 | root.mainloop() -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/favicon.ico -------------------------------------------------------------------------------- /app/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/img.png -------------------------------------------------------------------------------- /app/img_function.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | import numpy as np 4 | import img_math 5 | import img_recognition 6 | 7 | SZ = 20 # 训练图片长宽 8 | MAX_WIDTH = 1000 # 原始图片最大宽度 9 | Min_Area = 2000 # 车牌区域允许最大面积 10 | PROVINCE_START = 1000 11 | 12 | def cv_show(name, img): 13 | cv2.imshow(name, img) 14 | cv2.waitKey(0) 15 | cv2.destroyAllWindows() 16 | 17 | 18 | class StatModel(object): 19 | def load(self, fn): 20 | self.model = self.model.load(fn) 21 | 22 | def save(self, fn): 23 | self.model.save(fn) 24 | 25 | 26 | class SVM(StatModel): 27 | def __init__(self, C=1, gamma=0.5): 28 | self.model = cv2.ml.SVM_create() 29 | self.model.setGamma(gamma) 30 | self.model.setC(C) 31 | self.model.setKernel(cv2.ml.SVM_RBF) 32 | self.model.setType(cv2.ml.SVM_C_SVC) 33 | 34 | # # 训练svm 35 | # def train(self, samples, responses): 36 | # self.model.train(samples, cv2.ml.ROW_SAMPLE, responses) 37 | 38 | # 字符识别 39 | def predict(self, samples): 40 | r = self.model.predict(samples) 41 | return r[1].ravel() 42 | 43 | 44 | class CardPredictor: 45 | def __init__(self): 46 | pass 47 | 48 | def train_svm(self): 49 | # 识别英文字母和数字 50 | self.model = SVM(C=1, gamma=0.5) 51 | # 识别中文 52 | self.modelchinese = SVM(C=1, gamma=0.5) 53 | if os.path.exists("svm.dat"): 54 | self.model.load("svm.dat") 55 | if os.path.exists("svmchinese.dat"): 56 | self.modelchinese.load("svmchinese.dat") 57 | 58 | def img_first_pre(self, car_pic_file): 59 | """ 60 | :param car_pic_file: 图像文件 61 | :return:已经处理好的图像文件 原图像文件 62 | """ 63 | if type(car_pic_file) == type(""): 64 | img = img_math.img_read(car_pic_file) #读取文件 65 | else: 66 | img = car_pic_file 67 | 68 | pic_hight, pic_width = img.shape[:2] #取彩色图片的高、宽 69 | if pic_width > MAX_WIDTH: 70 | resize_rate = MAX_WIDTH / pic_width 71 | # 缩小图片 72 | img = cv2.resize(img, (MAX_WIDTH, int(pic_hight * resize_rate)), interpolation=cv2.INTER_AREA) 73 | # 关于interpolation 有几个参数可以选择: 74 | # cv2.INTER_AREA - 局部像素重采样,适合缩小图片。 75 | # cv2.INTER_CUBIC和 cv2.INTER_LINEAR 更适合放大图像,其中INTER_LINEAR为默认方法。 76 | 77 | img = cv2.GaussianBlur(img, (5, 5), 0) 78 | # 高斯滤波是一种线性平滑滤波,对于除去高斯噪声有很好的效果 79 | # 0 是指根据窗口大小( 5,5 )来计算高斯函数标准差 80 | 81 | oldimg = img 82 | cv2.imwrite("tmp/oldimg.jpg", oldimg) 83 | 84 | 85 | # 转换成灰度图像 86 | # 转换颜色空间 cv2.cvtColor 87 | # BGR ---> Gray cv2.COLOR_BGR2GRAY 88 | # BGR ---> HSV cv2.COLOR_BGR2HSV 89 | img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 90 | 91 | cv2.imwrite("tmp/img_gray.jpg", img) 92 | 93 | #ones()返回一个全1的n维数组 94 | Matrix = np.ones((20, 20), np.uint8) 95 | 96 | # 开运算:先进性腐蚀再进行膨胀就叫做开运算。它被用来去除噪声。 cv2.MORPH_OPEN 97 | img_opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, Matrix) 98 | 99 | # 图片叠加与融合 100 | # g (x) = (1 − α)f0 (x) + αf1 (x) a→(0,1)不同的a值可以实现不同的效果 101 | img_opening = cv2.addWeighted(img, 1, img_opening, -1, 0) 102 | cv2.imwrite("tmp/img_opening.jpg", img_opening) 103 | # 创建20*20的元素为1的矩阵 开操作,并和img重合 104 | 105 | 106 | # Otsu’s二值化 107 | ret, img_thresh = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) 108 | cv2.imwrite("tmp/img_threshold.jpg", img_thresh) 109 | 110 | # Canny 边缘检测 111 | # 较大的阈值2用于检测图像中明显的边缘 一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的 112 | # 较小的阈值1用于将这些间断的边缘连接起来 113 | img_edge = cv2.Canny(img_thresh, 100, 200) 114 | cv2.imwrite("tmp/img_edge.jpg", img_edge) 115 | 116 | Matrix = np.ones((4, 19), np.uint8) 117 | # 闭运算:先膨胀再腐蚀 118 | img_edge1 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, Matrix) 119 | # 开运算 120 | img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, Matrix) 121 | cv2.imwrite("tmp/img_xingtai.jpg", img_edge2) 122 | return img_edge2, oldimg 123 | 124 | def img_only_color(self, filename, oldimg, img_contours): 125 | """ 126 | :param filename: 图像文件 127 | :param oldimg: 原图像文件 128 | :return: 识别到的字符、定位的车牌图像、车牌颜色 129 | """ 130 | pic_hight, pic_width = img_contours.shape[:2] # #取彩色图片的高、宽 131 | # 在 OpenCV 的 HSV 格式中,H(色彩/色度)的取值范围是 [0,179],S(饱和度)的取值范围 [0,255],V(亮度)的取值范围 [0,255]。 132 | 133 | lower_blue = np.array([100, 110, 105]) 134 | upper_blue = np.array([130, 255, 255]) 135 | lower_yellow = np.array([12, 88, 99]) 136 | upper_yellow = np.array([35, 255, 255]) 137 | lower_green = np.array([18, 20, 132]) 138 | upper_green = np.array([79, 255, 255]) 139 | 140 | # lower_blue = np.array([100, 110, 110]) 141 | # upper_blue = np.array([130, 255, 255]) 142 | # lower_yellow = np.array([15, 55, 55]) 143 | # upper_yellow = np.array([50, 255, 255]) 144 | # lower_green = np.array([50, 50, 50]) 145 | # upper_green = np.array([100, 255, 255]) 146 | 147 | 148 | # BGR ---> HSV 149 | hsv = cv2.cvtColor(filename, cv2.COLOR_BGR2HSV) 150 | # cv_show('hsv', hsv) 151 | 152 | # 利用cv2.inRange函数设阈值,去除背景部分 153 | # 参数1:原图 154 | # 参数2:图像中低于值,图像值变为0 155 | # 参数3:图像中高于值,图像值变为0 156 | mask_blue = cv2.inRange(hsv, lower_blue, upper_blue) 157 | # cv_show('mask_blue', mask_blue) 158 | mask_yellow = cv2.inRange(hsv, lower_yellow, upper_yellow) 159 | # cv_show('mask_yellow', mask_yellow) 160 | mask_green = cv2.inRange(hsv, lower_green, upper_green) 161 | # cv_show('mask_green', mask_green) 162 | 163 | # 图像算术运算 按位运算 按位操作有: AND, OR, NOT, XOR 等 164 | output = cv2.bitwise_and(hsv, hsv, mask=mask_blue + mask_yellow + mask_green) 165 | # 根据阈值找到对应颜色 166 | 167 | output = cv2.cvtColor(output, cv2.COLOR_BGR2GRAY) 168 | # cv_show('output', output) 169 | 170 | Matrix = np.ones((20, 20), np.uint8) 171 | #使用一个 20x20 的卷积核 172 | img_edge1 = cv2.morphologyEx(output, cv2.MORPH_CLOSE, Matrix) #闭运算 173 | img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, Matrix) #开运算 174 | 175 | 176 | card_contours = img_math.img_findContours(img_edge2) 177 | card_imgs = img_math.img_Transform(card_contours, oldimg, pic_width, pic_hight) 178 | colors, car_imgs = img_math.img_color(card_imgs) 179 | 180 | predict_result = [] 181 | predict_str = "" 182 | roi = None 183 | card_color = None 184 | 185 | for i, color in enumerate(colors): 186 | 187 | if color in ("blue", "yellow", "green"): 188 | card_img = card_imgs[i] 189 | 190 | try: 191 | gray_img = cv2.cvtColor(card_img, cv2.COLOR_BGR2GRAY) 192 | cv2.imwrite("tmp/gray_img.jpg", gray_img) 193 | except: 194 | print("gray转换失败") 195 | 196 | # 黄、绿车牌字符比背景暗、与蓝车牌刚好相反,所以黄、绿车牌需要反向 197 | if color == "green" or color == "yellow": 198 | gray_img = cv2.bitwise_not(gray_img) 199 | ret, gray_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) 200 | cv2.imwrite("tmp/chepai_xingtai.jpg", gray_img) 201 | x_histogram = np.sum(gray_img, axis=1) 202 | 203 | x_min = np.min(x_histogram) 204 | x_average = np.sum(x_histogram) / x_histogram.shape[0] 205 | x_threshold = (x_min + x_average) / 2 206 | wave_peaks = img_math.find_waves(x_threshold, x_histogram) 207 | 208 | if len(wave_peaks) == 0: 209 | # print("peak less 0:") 210 | continue 211 | # 认为水平方向,最大的波峰为车牌区域 212 | wave = max(wave_peaks, key=lambda x: x[1] - x[0]) 213 | 214 | 215 | gray_img = gray_img[wave[0]:wave[1]] 216 | # 查找垂直直方图波峰 217 | row_num, col_num = gray_img.shape[:2] 218 | # 去掉车牌上下边缘1个像素,避免白边影响阈值判断 219 | gray_img = gray_img[1:row_num - 1] 220 | y_histogram = np.sum(gray_img, axis=0) 221 | y_min = np.min(y_histogram) 222 | y_average = np.sum(y_histogram) / y_histogram.shape[0] 223 | y_threshold = (y_min + y_average) / 5 # U和0要求阈值偏小,否则U和0会被分成两半 224 | wave_peaks = img_math.find_waves(y_threshold, y_histogram) 225 | if len(wave_peaks) < 6: 226 | # print("peak less 1:", len(wave_peaks)) 227 | continue 228 | 229 | wave = max(wave_peaks, key=lambda x: x[1] - x[0]) 230 | max_wave_dis = wave[1] - wave[0] 231 | # 判断是否是左侧车牌边缘 232 | if wave_peaks[0][1] - wave_peaks[0][0] < max_wave_dis / 3 and wave_peaks[0][0] == 0: 233 | wave_peaks.pop(0) 234 | 235 | # 组合分离汉字 236 | cur_dis = 0 237 | for i, wave in enumerate(wave_peaks): 238 | if wave[1] - wave[0] + cur_dis > max_wave_dis * 0.6: 239 | break 240 | else: 241 | cur_dis += wave[1] - wave[0] 242 | if i > 0: 243 | wave = (wave_peaks[0][0], wave_peaks[i][1]) 244 | wave_peaks = wave_peaks[i + 1:] 245 | wave_peaks.insert(0, wave) 246 | 247 | point = wave_peaks[2] 248 | point_img = gray_img[:, point[0]:point[1]] 249 | if np.mean(point_img) < 255 / 5: 250 | wave_peaks.pop(2) 251 | 252 | if len(wave_peaks) <= 6: 253 | # print("peak less 2:", len(wave_peaks)) 254 | continue 255 | # print(wave_peaks) 256 | 257 | # wave_peaks 车牌字符 类型列表 包含7个(开始的横坐标,结束的横坐标) 258 | 259 | 260 | 261 | part_cards = img_math.seperate_card(gray_img, wave_peaks) 262 | 263 | for i, part_card in enumerate(part_cards): 264 | # 可能是固定车牌的铆钉 265 | 266 | if np.mean(part_card) < 255 / 5: 267 | # print("a point") 268 | continue 269 | part_card_old = part_card 270 | 271 | w = abs(part_card.shape[1] - SZ) // 2 272 | 273 | part_card = cv2.copyMakeBorder(part_card, 0, 0, w, w, cv2.BORDER_CONSTANT, value=[0, 0, 0]) 274 | part_card = cv2.resize(part_card, (SZ, SZ), interpolation=cv2.INTER_AREA) 275 | 276 | part_card = img_recognition.preprocess_hog([part_card]) 277 | if i == 0: # 第一个字符为汉字 278 | resp = self.modelchinese.predict(part_card) 279 | charactor = img_recognition.provinces[int(resp[0]) - PROVINCE_START] 280 | else: # 其余为英文或数字 281 | resp = self.model.predict(part_card) 282 | charactor = chr(resp[0]) 283 | # 判断最后一个数是否是车牌边缘,假设车牌边缘被认为是1 284 | if charactor == "1" and i == len(part_cards) - 1: 285 | if part_card_old.shape[0] / part_card_old.shape[1] > 8.39: # 1太细,认为是边缘 286 | continue 287 | predict_result.append(charactor) 288 | predict_str = "".join(predict_result) 289 | 290 | roi = card_img 291 | card_color = color 292 | break 293 | cv2.imwrite("tmp/img_caijian.jpg", roi) 294 | return predict_str, roi, card_color # 识别到的字符、定位的车牌图像、车牌颜色 295 | -------------------------------------------------------------------------------- /app/img_math.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | Min_Area = 2000 # 车牌区域允许最大面积 5 | 6 | """ 7 | 该文件包含读文件函数 8 | 取零值函数 9 | 矩阵校正函数 10 | 颜色判断函数 11 | """ 12 | 13 | def img_read(filename): 14 | ''' 15 | 以uint8方式读取filename 16 | 放入imdecode中,cv2.IMREAD_COLOR读取彩色照片 17 | ''' 18 | 19 | #cv2.IMREAD_COLOR:读入一副彩色图像。图像的透明度会被忽略,这是默认参数 20 | #cv2.IMREAD_GRAYSCALE:以灰度模式读入图像 21 | #cv2.IMREAD_UNCHANGED:读入一幅图像,并且包括图像的 alpha 通道 22 | return cv2.imdecode(np.fromfile(filename, dtype=np.uint8), cv2.IMREAD_COLOR) 23 | 24 | 25 | 26 | def find_waves(threshold, histogram): 27 | up_point = -1 # 上升点 28 | is_peak = False 29 | if histogram[0] > threshold: 30 | up_point = 0 31 | is_peak = True 32 | wave_peaks = [] 33 | for i, x in enumerate(histogram): 34 | if is_peak and x < threshold: 35 | if i - up_point > 2: 36 | is_peak = False 37 | wave_peaks.append((up_point, i)) 38 | elif not is_peak and x >= threshold: 39 | is_peak = True 40 | up_point = i 41 | if is_peak and up_point != -1 and i - up_point > 4: 42 | wave_peaks.append((up_point, i)) 43 | return wave_peaks 44 | 45 | 46 | def point_limit(point): 47 | if point[0] < 0: 48 | point[0] = 0 49 | if point[1] < 0: 50 | point[1] = 0 51 | 52 | 53 | def accurate_place(card_img_hsv, limit1, limit2, color): 54 | row_num, col_num = card_img_hsv.shape[:2] 55 | xl = col_num 56 | xr = 0 57 | yh = 0 58 | yl = row_num 59 | row_num_limit = 21 60 | col_num_limit = col_num * 0.8 if color != "green" else col_num * 0.5 # 绿色有渐变 61 | for i in range(row_num): 62 | count = 0 63 | for j in range(col_num): 64 | H = card_img_hsv.item(i, j, 0) 65 | S = card_img_hsv.item(i, j, 1) 66 | V = card_img_hsv.item(i, j, 2) 67 | if limit1 < H <= limit2 and 34 < S and 46 < V: 68 | count += 1 69 | if count > col_num_limit: 70 | if yl > i: 71 | yl = i 72 | if yh < i: 73 | yh = i 74 | for j in range(col_num): 75 | count = 0 76 | for i in range(row_num): 77 | H = card_img_hsv.item(i, j, 0) 78 | S = card_img_hsv.item(i, j, 1) 79 | V = card_img_hsv.item(i, j, 2) 80 | if limit1 < H <= limit2 and 34 < S and 46 < V: 81 | count += 1 82 | if count > row_num - row_num_limit: 83 | if xl > j: 84 | xl = j 85 | if xr < j: 86 | xr = j 87 | return xl, xr, yh, yl 88 | 89 | 90 | def img_findContours(img_contours): 91 | # 查找轮廓 92 | # cv2.findContours() 93 | # 有三个参数,第一个是输入图像,第二个是轮廓检索模式,第三个是轮廓近似方法。参数为二值图,即黑白的(不是灰度图) 94 | # 返回值有三个,第一个是图像,第二个是轮廓,第三个是(轮廓的)层析结构。 95 | # 轮廓(第二个返回值)是一个 Python列表,其中存储这图像中的所有轮廓。 96 | # 每一个轮廓都是一个 Numpy 数组,包含对象边界点(x,y)的坐标。 97 | contours, hierarchy = cv2.findContours(img_contours, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 98 | # cv2.RETR_TREE建立一个等级树结构的轮廓 99 | # cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素, 100 | # 只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息 101 | 102 | # cv2.contourArea计算该轮廓的面积 103 | contours = [cnt for cnt in contours if cv2.contourArea(cnt) > Min_Area] 104 | # print("findContours len = ", len(contours)) 105 | 106 | # 面积小的都筛选掉 107 | car_contours = [] 108 | for cnt in contours: 109 | ant = cv2.minAreaRect(cnt)# 得到最小外接矩形的(中心(x,y), (宽,高), 旋转角度) 110 | width, height = ant[1] 111 | if width < height: 112 | width, height = height, width 113 | ration = width / height 114 | 115 | if 2 < ration < 5.5: 116 | car_contours.append(ant) 117 | box = cv2.boxPoints(ant) # 获得要绘制这个矩形的 4 个角点 118 | 119 | return car_contours 120 | 121 | 122 | def img_Transform(car_contours, oldimg, pic_width, pic_hight): 123 | """ 124 | 进行矩形矫正 125 | """ 126 | car_imgs = [] 127 | for car_rect in car_contours: #(中心(x,y), (宽,高), 旋转角度) 128 | if -1 < car_rect[2] < 1: 129 | angle = 1 130 | # 对于角度为-1 1之间时,默认为1 131 | else: 132 | angle = car_rect[2] 133 | car_rect = (car_rect[0], (car_rect[1][0] + 5, car_rect[1][1] + 5), angle) 134 | 135 | box = cv2.boxPoints(car_rect) # 获得要绘制这个矩形的 4 个角点 136 | 137 | heigth_point = right_point = [0, 0] 138 | left_point = low_point = [pic_width, pic_hight] 139 | 140 | for point in box: 141 | if left_point[0] > point[0]: 142 | left_point = point 143 | if low_point[1] > point[1]: 144 | low_point = point 145 | if heigth_point[1] < point[1]: 146 | heigth_point = point 147 | if right_point[0] < point[0]: 148 | right_point = point 149 | 150 | if left_point[1] <= right_point[1]: # 正角度,根据左右顶点判断 151 | new_right_point = [right_point[0], heigth_point[1]] 152 | pts2 = np.float32([left_point, heigth_point, new_right_point]) # 字符只是高度需要改变 153 | pts1 = np.float32([left_point, heigth_point, right_point]) 154 | 155 | # 仿射变换 156 | M = cv2.getAffineTransform(pts1, pts2) 157 | dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight)) # 平移图像 158 | cv2.imwrite("tmp/img_dst.jpg", dst) 159 | 160 | 161 | point_limit(new_right_point) 162 | point_limit(heigth_point) 163 | point_limit(left_point) 164 | 165 | car_img = dst[int(left_point[1]):int(heigth_point[1]), int(left_point[0]):int(new_right_point[0])] 166 | car_imgs.append(car_img) 167 | 168 | elif left_point[1] > right_point[1]: # 负角度,根据左右顶点判断 169 | new_left_point = [left_point[0], heigth_point[1]] 170 | pts2 = np.float32([new_left_point, heigth_point, right_point]) # 字符只是高度需要改变 171 | pts1 = np.float32([left_point, heigth_point, right_point]) 172 | 173 | M = cv2.getAffineTransform(pts1, pts2) 174 | dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight)) # 平移图像 175 | cv2.imwrite("tmp/img_dst.jpg", dst) 176 | 177 | 178 | point_limit(right_point) 179 | point_limit(heigth_point) 180 | point_limit(new_left_point) 181 | car_img = dst[int(right_point[1]):int(heigth_point[1]), int(new_left_point[0]):int(right_point[0])] 182 | 183 | car_imgs.append(car_img) 184 | 185 | return car_imgs 186 | 187 | def img_color(card_imgs): 188 | """ 189 | 颜色判断函数 190 | """ 191 | colors = [] 192 | for card_index, card_img in enumerate(card_imgs): 193 | 194 | green = yello = blue = black = white = 0 195 | try: 196 | card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV) 197 | except: 198 | print("矫正矩形出错, 转换失败")# 可能原因:上面矫正矩形出错 199 | 200 | if card_img_hsv is None: 201 | continue 202 | row_num, col_num = card_img_hsv.shape[:2] 203 | card_img_count = row_num * col_num 204 | 205 | for i in range(row_num): 206 | for j in range(col_num): 207 | H = card_img_hsv.item(i, j, 0) 208 | S = card_img_hsv.item(i, j, 1) 209 | V = card_img_hsv.item(i, j, 2) 210 | if 11 < H <= 34 and S > 34: 211 | yello += 1 212 | elif 35 < H <= 99 and S > 34: 213 | green += 1 214 | elif 99 < H <= 124 and S > 34: 215 | blue += 1 216 | 217 | if 0 < H < 180 and 0 < S < 255 and 0 < V < 46: 218 | black += 1 219 | elif 0 < H < 180 and 0 < S < 43 and 221 < V < 225: 220 | white += 1 221 | color = "no" 222 | 223 | limit1 = limit2 = 0 224 | if yello * 2 >= card_img_count: 225 | color = "yellow" 226 | limit1 = 11 227 | limit2 = 34 # 有的图片有色偏偏绿 228 | elif green * 2 >= card_img_count: 229 | color = "green" 230 | limit1 = 35 231 | limit2 = 99 232 | elif blue * 2 >= card_img_count: 233 | color = "blue" 234 | limit1 = 100 235 | limit2 = 124 # 有的图片有色偏偏紫 236 | elif black + white >= card_img_count * 0.7: 237 | color = "bw" 238 | colors.append(color) 239 | card_imgs[card_index] = card_img 240 | 241 | if limit1 == 0: 242 | continue 243 | xl, xr, yh, yl = accurate_place(card_img_hsv, limit1, limit2, color) 244 | if yl == yh and xl == xr: 245 | continue 246 | need_accurate = False 247 | if yl >= yh: 248 | yl = 0 249 | yh = row_num 250 | need_accurate = True 251 | if xl >= xr: 252 | xl = 0 253 | xr = col_num 254 | need_accurate = True 255 | 256 | if color == "green": 257 | card_imgs[card_index] = card_img 258 | else: 259 | card_imgs[card_index] = card_img[yl:yh, xl:xr] if color != "green" or yl < (yh - yl) // 4 else card_img[ 260 | yl - ( 261 | yh - yl) // 4:yh, 262 | xl:xr] 263 | 264 | if need_accurate: 265 | card_img = card_imgs[card_index] 266 | card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV) 267 | xl, xr, yh, yl = accurate_place(card_img_hsv, limit1, limit2, color) 268 | if yl == yh and xl == xr: 269 | continue 270 | if yl >= yh: 271 | yl = 0 272 | yh = row_num 273 | if xl >= xr: 274 | xl = 0 275 | xr = col_num 276 | if color == "green": 277 | card_imgs[card_index] = card_img 278 | else: 279 | card_imgs[card_index] = card_img[yl:yh, xl:xr] if color != "green" or yl < (yh - yl) // 4 else card_img[ 280 | yl - ( 281 | yh - yl) // 4:yh, 282 | xl:xr] 283 | return colors, card_imgs 284 | 285 | def seperate_card(img, waves): 286 | """ 287 | 分离车牌字符 288 | """ 289 | h , w = img.shape 290 | part_cards = [] 291 | i = 0 292 | for wave in waves: 293 | i = i+1 294 | part_cards.append(img[:, wave[0]:wave[1]]) 295 | chrpic = img[0:h,wave[0]:wave[1]] 296 | 297 | 298 | 299 | #保存分离后的车牌图片 300 | cv2.imwrite('tmp/chechar{}.jpg'.format(i),chrpic) 301 | 302 | 303 | return part_cards 304 | 305 | -------------------------------------------------------------------------------- /app/img_recognition.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | from numpy.linalg import norm 4 | 5 | SZ = 20 # 训练图片长宽 6 | MAX_WIDTH = 1000 # 原始图片最大宽度 7 | Min_Area = 2000 # 车牌区域允许最大面积 8 | PROVINCE_START = 1000 9 | # 来自opencv的sample,用于svm训练 10 | # def deskew(img): 11 | # m = cv2.moments(img) 12 | # if abs(m['mu02']) < 1e-2: 13 | # return img.copy() 14 | # skew = m['mu11'] / m['mu02'] 15 | # M = np.float32([[1, skew, -0.5 * SZ * skew], [0, 1, 0]]) 16 | # img = cv2.warpAffine(img, M, (SZ, SZ), flags=cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR) 17 | # return img 18 | 19 | 20 | # # 来自opencv的sample,用于svm训练 21 | def preprocess_hog(digits): 22 | samples = [] 23 | for img in digits: 24 | gx = cv2.Sobel(img, cv2.CV_32F, 1, 0) 25 | gy = cv2.Sobel(img, cv2.CV_32F, 0, 1) 26 | mag, ang = cv2.cartToPolar(gx, gy) 27 | bin_n = 16 28 | bin = np.int32(bin_n * ang / (2 * np.pi)) 29 | bin_cells = bin[:10, :10], bin[10:, :10], bin[:10, 10:], bin[10:, 10:] 30 | mag_cells = mag[:10, :10], mag[10:, :10], mag[:10, 10:], mag[10:, 10:] 31 | hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)] 32 | hist = np.hstack(hists) 33 | 34 | # transform to Hellinger kernel 35 | eps = 1e-7 36 | hist /= hist.sum() + eps 37 | hist = np.sqrt(hist) 38 | hist /= norm(hist) + eps 39 | 40 | samples.append(hist) 41 | return np.float32(samples) 42 | 43 | 44 | provinces = [ 45 | "zh_cuan", "川", 46 | "zh_e", "鄂", 47 | "zh_gan", "赣", 48 | "zh_gan1", "甘", 49 | "zh_gui", "贵", 50 | "zh_gui1", "桂", 51 | "zh_hei", "黑", 52 | "zh_hu", "沪", 53 | "zh_ji", "冀", 54 | "zh_jin", "津", 55 | "zh_jing", "京", 56 | "zh_jl", "吉", 57 | "zh_liao", "辽", 58 | "zh_lu", "鲁", 59 | "zh_meng", "蒙", 60 | "zh_min", "闽", 61 | "zh_ning", "宁", 62 | "zh_qing", "青", 63 | "zh_qiong", "琼", 64 | "zh_shan", "陕", 65 | "zh_su", "苏", 66 | "zh_sx", "晋", 67 | "zh_wan", "皖", 68 | "zh_xiang", "湘", 69 | "zh_xin", "新", 70 | "zh_yu", "豫", 71 | "zh_yu1", "渝", 72 | "zh_yue", "粤", 73 | "zh_yun", "云", 74 | "zh_zang", "藏", 75 | "zh_zhe", "浙" 76 | ] 77 | 78 | color_tr = { 79 | "green": ("绿牌", "#55FF55"), 80 | "yellow": ("黄牌", "#FFFF00"), 81 | "blue": ("蓝牌", "#6666FF") 82 | } 83 | 84 | 85 | -------------------------------------------------------------------------------- /app/main.py: -------------------------------------------------------------------------------- 1 | import cv2,os 2 | from tkinter.filedialog import askopenfilename 3 | from tkinter import ttk 4 | import tkinter as tk 5 | from PIL import Image, ImageTk 6 | import img_function as predict 7 | import img_math as img_math 8 | import img_recognition as img_rec 9 | 10 | 11 | class UI_main(ttk.Frame): 12 | pic_path = "" #图片路径 13 | pic_source = "" 14 | colorimg = 'white' #车牌颜色 15 | cameraflag = 0 16 | width = 700 #宽 17 | height = 400 #高 18 | color_transform = img_rec.color_tr 19 | 20 | def __init__(self, win): 21 | ttk.Frame.__init__(self, win) 22 | 23 | 24 | win.title("车牌识别系统") 25 | win.geometry('+300+200') 26 | win.minsize(UI_main.width,UI_main.height) 27 | win.configure(relief=tk.RIDGE) 28 | # win.update() 29 | 30 | 31 | self.pack(fill=tk.BOTH) 32 | frame_left = ttk.Frame(self) 33 | frame_right_1 = ttk.Frame(self) 34 | frame_right_2 = ttk.Frame(self) 35 | frame_left.pack(side=tk.LEFT, expand=1, fill=tk.BOTH) 36 | frame_right_1.pack(side=tk.TOP, expand=1, fill=tk.Y) 37 | frame_right_2.pack() 38 | 39 | #界面左边 --->车牌识别主界面大图片 40 | self.image_ctl = ttk.Label(frame_left) 41 | self.image_ctl.pack() 42 | 43 | #界面右边 --->定位车牌位置、识别结果 44 | ttk.Label(frame_right_1, text='定位车牌:', font=('Times', '14')).grid( 45 | column=0, row=6, sticky=tk.NW) 46 | 47 | 48 | self.roi_ct2 = ttk.Label(frame_right_1) 49 | self.roi_ct2.grid(column=0, row=7, sticky=tk.W,pady=5) 50 | ttk.Label(frame_right_1, text='识别结果:', font=('Times', '14')).grid( 51 | column=0, row=8, sticky=tk.W,pady=5) 52 | self.r_ct2 = ttk.Label(frame_right_1, text="", font=('Times', '20')) 53 | self.r_ct2.grid(column=0, row=9, sticky=tk.W,pady=5) 54 | 55 | #车牌颜色 56 | self.color_ct2 = ttk.Label(frame_right_1,background=self.colorimg, 57 | text="", width="4",font=('Times', '14')) 58 | self.color_ct2.grid(column=0, row=10, sticky=tk.W) 59 | 60 | #界面右下角 61 | from_pic_ctl = ttk.Button( 62 | frame_right_2, text="车牌图片", width=20, command=self.from_pic) 63 | from_pic_ctl.grid(column=0, row=1) 64 | 65 | #清除识别数据 66 | from_pic_chu = ttk.Button( 67 | frame_right_2, text="清除识别数据", width=20, command=self.clean) 68 | from_pic_chu.grid(column=0, row=2) 69 | #查看图像处理过程 70 | from_pic_chu = ttk.Button( 71 | frame_right_2, text="查看图像处理过程", width=20, command=self.pic_chuli) 72 | from_pic_chu.grid(column=0, row=3) 73 | 74 | 75 | 76 | self.clean() 77 | 78 | self.predictor = predict.CardPredictor() 79 | self.predictor.train_svm() 80 | 81 | def get_imgtk(self, img_bgr): 82 | img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) 83 | im = Image.fromarray(img) 84 | pil_image_resized = im.resize((500,400),Image.ANTIALIAS) 85 | imgtk = ImageTk.PhotoImage(image=pil_image_resized) 86 | return imgtk 87 | 88 | #显示图片处理过程 89 | def pic_chuli(self): 90 | os.system("python ./chuli.py") 91 | 92 | def pic(self, pic_path): 93 | img_bgr = img_math.img_read(pic_path) 94 | first_img, oldimg = self.predictor.img_first_pre(img_bgr) 95 | if not self.cameraflag: 96 | self.imgtk = self.get_imgtk(img_bgr) 97 | self.image_ctl.configure(image=self.imgtk) 98 | r_color, roi_color, color_color = self.predictor.img_only_color(oldimg, 99 | oldimg, first_img) 100 | self.color_ct2.configure(background=color_color) 101 | # try: 102 | # Plate = HyperLPR_PlateRecogntion(img_bgr) 103 | # r_color = Plate[0][0] 104 | # except: 105 | # pass 106 | self.show_roi(r_color, roi_color, color_color) 107 | self.colorimg = color_color 108 | print( color_color,"|", 109 | r_color, self.pic_source) 110 | 111 | #来自图片--->打开系统接口获取图片绝对路径 112 | def from_pic(self): 113 | self.cameraflag = 0 114 | self.pic_path = askopenfilename(title="选择识别图片", filetypes=[( 115 | "图片", "*.jpg;*.jpeg;*.png")]) 116 | 117 | self.clean() 118 | # self.pic_source = "本地文件:" + self.pic_path 119 | self.pic(self.pic_path) 120 | 121 | 122 | def show_roi(self, r, roi, color): # 车牌定位后的图片 123 | if r: 124 | try: 125 | roi = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB) 126 | roi = Image.fromarray(roi) 127 | pil_image_resized = roi.resize((200, 50), Image.ANTIALIAS) 128 | self.tkImage2 = ImageTk.PhotoImage(image=pil_image_resized) 129 | self.roi_ct2.configure(image=self.tkImage2, state='enable') 130 | except: 131 | pass 132 | self.r_ct2.configure(text=str(r)) 133 | try: 134 | c = self.color_transform[color] 135 | self.color_ct2.configure(text=c[0], state='enable') 136 | except: 137 | self.color_ct2.configure(state='disabled') 138 | 139 | #清除识别数据,还原初始结果 140 | def clean(self): 141 | img_bgr3 = img_math.img_read("pic/hy.png") 142 | self.imgtk2 = self.get_imgtk(img_bgr3) 143 | self.image_ctl.configure(image=self.imgtk2) 144 | 145 | self.r_ct2.configure(text="") 146 | self.color_ct2.configure(text="", state='enable') 147 | #显示车牌颜色 148 | self.color_ct2.configure(background='white' ,text="颜色", state='enable') 149 | self.pilImage3 = Image.open("pic/locate.png") 150 | pil_image_resized = self.pilImage3.resize((200, 50), Image.ANTIALIAS) 151 | self.tkImage3 = ImageTk.PhotoImage(image=pil_image_resized) 152 | self.roi_ct2.configure(image=self.tkImage3, state='enable') 153 | 154 | 155 | if __name__ == '__main__': 156 | win = tk.Tk() 157 | 158 | ui_main= UI_main(win) 159 | # 进入消息循环 160 | win.mainloop() 161 | -------------------------------------------------------------------------------- /app/pic/hy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/pic/hy.png -------------------------------------------------------------------------------- /app/pic/locate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/pic/locate.png -------------------------------------------------------------------------------- /app/tmp/chechar1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/chechar1.jpg -------------------------------------------------------------------------------- /app/tmp/chechar2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/chechar2.jpg -------------------------------------------------------------------------------- /app/tmp/chechar3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/chechar3.jpg -------------------------------------------------------------------------------- /app/tmp/chechar4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/chechar4.jpg -------------------------------------------------------------------------------- /app/tmp/chechar5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/chechar5.jpg -------------------------------------------------------------------------------- /app/tmp/chechar6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/chechar6.jpg -------------------------------------------------------------------------------- /app/tmp/chechar7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/chechar7.jpg -------------------------------------------------------------------------------- /app/tmp/chechar8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/chechar8.jpg -------------------------------------------------------------------------------- /app/tmp/chepai_xingtai.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/chepai_xingtai.jpg -------------------------------------------------------------------------------- /app/tmp/gray_img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/gray_img.jpg -------------------------------------------------------------------------------- /app/tmp/img_caijian.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/img_caijian.jpg -------------------------------------------------------------------------------- /app/tmp/img_dst.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/img_dst.jpg -------------------------------------------------------------------------------- /app/tmp/img_edge.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/img_edge.jpg -------------------------------------------------------------------------------- /app/tmp/img_gray.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/img_gray.jpg -------------------------------------------------------------------------------- /app/tmp/img_opening.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/img_opening.jpg -------------------------------------------------------------------------------- /app/tmp/img_threshold.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/img_threshold.jpg -------------------------------------------------------------------------------- /app/tmp/img_xingtai.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/img_xingtai.jpg -------------------------------------------------------------------------------- /app/tmp/oldimg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/app/tmp/oldimg.jpg -------------------------------------------------------------------------------- /exe/chepai/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/1.jpg -------------------------------------------------------------------------------- /exe/chepai/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/10.jpg -------------------------------------------------------------------------------- /exe/chepai/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/11.jpg -------------------------------------------------------------------------------- /exe/chepai/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/12.jpg -------------------------------------------------------------------------------- /exe/chepai/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/13.jpg -------------------------------------------------------------------------------- /exe/chepai/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/14.jpg -------------------------------------------------------------------------------- /exe/chepai/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/15.jpg -------------------------------------------------------------------------------- /exe/chepai/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/16.jpg -------------------------------------------------------------------------------- /exe/chepai/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/2.jpg -------------------------------------------------------------------------------- /exe/chepai/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/3.jpg -------------------------------------------------------------------------------- /exe/chepai/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/4.jpg -------------------------------------------------------------------------------- /exe/chepai/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/5.jpg -------------------------------------------------------------------------------- /exe/chepai/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/6.jpg -------------------------------------------------------------------------------- /exe/chepai/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/7.jpg -------------------------------------------------------------------------------- /exe/chepai/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/8.jpg -------------------------------------------------------------------------------- /exe/chepai/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/chepai/9.jpg -------------------------------------------------------------------------------- /exe/main.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/main.exe -------------------------------------------------------------------------------- /exe/pic/hy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/pic/hy.png -------------------------------------------------------------------------------- /exe/pic/locate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skci/VLPR/8d09c85ab2c2c9ccd0523c0dd3aa78222e5a5d9e/exe/pic/locate.png --------------------------------------------------------------------------------