├── .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 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
5 |
6 |
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
--------------------------------------------------------------------------------