liuwenzhe 5 months ago
parent baff77c028
commit 365035bfc3

@ -6,304 +6,342 @@ import numpy as np
import tkinter as tk
from tkinter import ttk
from PIL import ImageTk, Image
from tkinter import filedialog
# plt显示彩色图片
def plt_show0(img):
# cv2与plt的图像通道不同cv2为[b,g,r];plt为[r, g, b]
b, g, r = cv2.split(img)
img = cv2.merge([r, g, b])
plt.imshow(img)
plt.show()
def eaowej(file_path):
global history
# plt显示灰度图片
def plt_show(img):
plt.imshow(img, cmap='gray')
plt.show()
# plt显示灰度图片
def plt_show(img):
plt.imshow(img, cmap='gray')
plt.show()
# 图像去噪灰度处理
def gray_guss(image):
image = cv2.GaussianBlur(image, (3, 3), 0)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
return gray_image
# 图像去噪灰度处理
def gray_guss(image):
image = cv2.GaussianBlur(image, (3, 3), 0)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
return gray_image
# 读取待检测图片
origin_image = cv2.imread('../xiangA.jpg')
# 读取待检测图片
origin_image = cv2.imread(file_path)
# 复制一张图片,在复制图上进行图像操作,保留原图
image = origin_image.copy()
# 复制一张图片,在复制图上进行图像操作,保留原图
image = origin_image.copy()
# 图像去噪灰度处理
gray_image = gray_guss(image)
# 图像去噪灰度处理
gray_image = gray_guss(image)
# x方向上的边缘检测增强边缘信息
Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0)
absX = cv2.convertScaleAbs(Sobel_x)
image = absX
# x方向上的边缘检测增强边缘信息
Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0)
absX = cv2.convertScaleAbs(Sobel_x)
image = absX
# 图像阈值化操作——获得二值化图
ret, image = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU)
# 图像阈值化操作——获得二值化图
ret, image = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU)
# 显示灰度图像
plt_show(image)
# 形态学(从图像中提取对表达和描绘区域形状有意义的图像分量)——闭操作
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 10))
image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernelX,iterations = 1)
# 显示灰度图像
plt_show(image)
# 腐蚀erode和膨胀dilate
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 1))
kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 20))
#x方向进行闭操作抑制暗细节
image = cv2.dilate(image, kernelX)
image = cv2.erode(image, kernelX)
#y方向的开操作
image = cv2.erode(image, kernelY)
image = cv2.dilate(image, kernelY)
# 中值滤波(去噪)
image = cv2.medianBlur(image, 21)
# 显示灰度图像
plt_show(image)
# 获得轮廓
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for item in contours:
rect = cv2.boundingRect(item)
x = rect[0]
y = rect[1]
weight = rect[2]
height = rect[3]
# 根据轮廓的形状特点,确定车牌的轮廓位置并截取图像
if (weight > (height * 3.5)) and (weight < (height * 4)):
image = origin_image[y:y + height, x:x + weight]
plt_show0(image)
#车牌字符分割
# 图像去噪灰度处理
gray_image = gray_guss(image)
# 图像阈值化操作——获得二值化图
ret, image = cv2.threshold(gray_image, 0, 255, cv2.THRESH_OTSU)
plt_show(image)
#膨胀操作,使“津”字膨胀为一个近似的整体,为分割做准备
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
image = cv2.dilate(image, kernel)
plt_show(image)
# 查找轮廓
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
words = []
word_images = []
#对所有轮廓逐一操作
for item in contours:
word = []
rect = cv2.boundingRect(item)
x = rect[0]
y = rect[1]
weight = rect[2]
height = rect[3]
word.append(x)
word.append(y)
word.append(weight)
word.append(height)
words.append(word)
# 排序车牌号有顺序。words是一个嵌套列表
words = sorted(words,key=lambda s:s[0],reverse=False)
i = 0
#word中存放轮廓的起始点和宽高
for word in words:
# 筛选字符的轮廓
if (word[3] > (word[2] * 1.5)) and (word[3] < (word[2] * 3.5)) and (word[2] > 25):
i = i+1
splite_image = image[word[1]:word[1] + word[3], word[0]:word[0] + word[2]]
word_images.append(splite_image)
#print(i)
#print(words)
for i,j in enumerate(word_images):
plt.subplot(1,7,i+1)
plt.imshow(word_images[i],cmap='gray')
plt.show()
#模版匹配
# 准备模板(template[0-9]为数字模板;)
template = ['0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','J','K',
'L','M','N','P','Q','R','S','T','U','V',
'W','X','Y','Z','','','','','',
'','','','','','','','','',
'','','','','','','','','',
'','','','','','','','']
# 读取一个文件夹下的所有图片,输入参数是文件名,返回模板文件地址列表
def read_directory(directory_name):
referImg_list = []
for filename in os.listdir(directory_name):
referImg_list.append(directory_name + "/" + filename)
return referImg_list
# 获得中文模板列表(只匹配车牌的第一个字符)
def get_chinese_words_list():
chinese_words_list = []
for i in range(34,64):
#将模板存放在字典中
c_word = read_directory('./refer1/'+ template[i])
chinese_words_list.append(c_word)
return chinese_words_list
chinese_words_list = get_chinese_words_list()
# 获得英文模板列表(只匹配车牌的第二个字符)
def get_eng_words_list():
eng_words_list = []
for i in range(10,34):
e_word = read_directory('./refer1/'+ template[i])
eng_words_list.append(e_word)
return eng_words_list
eng_words_list = get_eng_words_list()
# 获得英文和数字模板列表(匹配车牌后面的字符)
def get_eng_num_words_list():
eng_num_words_list = []
for i in range(0,34):
word = read_directory('./refer1/'+ template[i])
eng_num_words_list.append(word)
return eng_num_words_list
eng_num_words_list = get_eng_num_words_list()
# 读取一个模板地址与图片进行匹配,返回得分
def template_score(template,image):
#将模板进行格式转换
template_img=cv2.imdecode(np.fromfile(template,dtype=np.uint8),1)
template_img = cv2.cvtColor(template_img, cv2.COLOR_RGB2GRAY)
#模板图像阈值化处理——获得黑白图
ret, template_img = cv2.threshold(template_img, 0, 255, cv2.THRESH_OTSU)
# height, width = template_img.shape
# image_ = image.copy()
# image_ = cv2.resize(image_, (width, height))
image_ = image.copy()
#获得待检测图片的尺寸
height, width = image_.shape
# 将模板resize至与图像一样大小
template_img = cv2.resize(template_img, (width, height))
# 模板匹配,返回匹配得分
result = cv2.matchTemplate(image_, template_img, cv2.TM_CCOEFF)
return result[0][0]
# 对分割得到的字符逐一匹配
def template_matching(word_images):
results = []
for index,word_image in enumerate(word_images):
if index==0:
best_score = []
for chinese_words in chinese_words_list:
score = []
for chinese_word in chinese_words:
result = template_score(chinese_word,word_image)
score.append(result)
best_score.append(max(score))
i = best_score.index(max(best_score))
# print(template[34+i])
r = template[34+i]
results.append(r)
continue
if index==1:
best_score = []
for eng_word_list in eng_words_list:
score = []
for eng_word in eng_word_list:
result = template_score(eng_word,word_image)
score.append(result)
best_score.append(max(score))
i = best_score.index(max(best_score))
# print(template[10+i])
r = template[10+i]
results.append(r)
continue
else:
best_score = []
for eng_num_word_list in eng_num_words_list:
score = []
for eng_num_word in eng_num_word_list:
result = template_score(eng_num_word,word_image)
score.append(result)
best_score.append(max(score))
i = best_score.index(max(best_score))
# print(template[i])
r = template[i]
results.append(r)
continue
return results
word_images_ = word_images.copy()
# 调用函数获得结果
result = template_matching(word_images_)
#print(result)
# "".join(result)函数将列表转换为拼接好的字符串,方便结果显示
#print( "".join(result))
from PIL import ImageFont, ImageDraw, Image
height,weight = origin_image.shape[0:2]
#print(height)
#print(weight)
image_1 = origin_image.copy()
cv2.rectangle(image_1, (int(0.2*weight), int(0.75*height)), (int(weight*0.9), int(height*0.95)), (0, 255, 0), 5)
#设置需要显示的字体
fontpath = "font/simsun.ttc"
font = ImageFont.truetype(fontpath,64)
img_pil = Image.fromarray(image_1)
draw = ImageDraw.Draw(img_pil)
#绘制文字信息
draw.text((int(0.2*weight)+25, int(0.75*height)), "".join(result), font = font, fill = (255, 255, 0))
bk_img = np.array(img_pil)
#print(result)
print( "".join(result))
plt_show0(bk_img)
# 使用PIL将numpy数组转换为Image对象
image_tk = Image.fromarray(cv2.cvtColor(bk_img, cv2.COLOR_BGR2RGB))
# 初始化Tkinter窗口
root = tk.Tk()
root.title("车牌识别结果")
# 显示灰度图像
plt_show(image)
# 形态学(从图像中提取对表达和描绘区域形状有意义的图像分量)——闭操作
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 10))
image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernelX,iterations = 1)
# 显示灰度图像
plt_show(image)
# 腐蚀erode和膨胀dilate
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 1))
kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 20))
#x方向进行闭操作抑制暗细节
image = cv2.dilate(image, kernelX)
image = cv2.erode(image, kernelX)
#y方向的开操作
image = cv2.erode(image, kernelY)
image = cv2.dilate(image, kernelY)
# 中值滤波(去噪)
image = cv2.medianBlur(image, 21)
# 显示灰度图像
plt_show(image)
# 获得轮廓
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for item in contours:
rect = cv2.boundingRect(item)
x = rect[0]
y = rect[1]
weight = rect[2]
height = rect[3]
# 根据轮廓的形状特点,确定车牌的轮廓位置并截取图像
if (weight > (height * 3.5)) and (weight < (height * 4)):
image = origin_image[y:y + height, x:x + weight]
plt_show0(image)
#车牌字符分割
# 图像去噪灰度处理
gray_image = gray_guss(image)
# 将Image对象转换为Tkinter支持的PhotoImage对象
photo_image = ImageTk.PhotoImage(image_tk)
# 图像阈值化操作——获得二值化图
ret, image = cv2.threshold(gray_image, 0, 255, cv2.THRESH_OTSU)
plt_show(image)
# 创建标签以显示图像
label = ttk.Label(root, image=photo_image)
label.pack() # 将标签添加到窗口中并自动调整大小
#膨胀操作,使“津”字膨胀为一个近似的整体,为分割做准备
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
image = cv2.dilate(image, kernel)
plt_show(image)
# 查找轮廓
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
words = []
word_images = []
#对所有轮廓逐一操作
for item in contours:
word = []
rect = cv2.boundingRect(item)
x = rect[0]
y = rect[1]
weight = rect[2]
height = rect[3]
word.append(x)
word.append(y)
word.append(weight)
word.append(height)
words.append(word)
# 排序车牌号有顺序。words是一个嵌套列表
words = sorted(words,key=lambda s:s[0],reverse=False)
i = 0
#word中存放轮廓的起始点和宽高
for word in words:
# 筛选字符的轮廓
if (word[3] > (word[2] * 1.5)) and (word[3] < (word[2] * 3.5)) and (word[2] > 25):
i = i+1
splite_image = image[word[1]:word[1] + word[3], word[0]:word[0] + word[2]]
word_images.append(splite_image)
#print(i)
#print(words)
for i,j in enumerate(word_images):
plt.subplot(1,7,i+1)
plt.imshow(word_images[i],cmap='gray')
plt.show()
#模版匹配
# 准备模板(template[0-9]为数字模板;)
template = ['0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','J','K',
'L','M','N','P','Q','R','S','T','U','V',
'W','X','Y','Z','','','','','',
'','','','','','','','','',
'','','','','','','','','',
'','','','','','','','']
# 读取一个文件夹下的所有图片,输入参数是文件名,返回模板文件地址列表
def read_directory(directory_name):
referImg_list = []
for filename in os.listdir(directory_name):
referImg_list.append(directory_name + "/" + filename)
return referImg_list
# 获得中文模板列表(只匹配车牌的第一个字符)
def get_chinese_words_list():
chinese_words_list = []
for i in range(34,64):
#将模板存放在字典中
c_word = read_directory('./refer1/'+ template[i])
chinese_words_list.append(c_word)
return chinese_words_list
chinese_words_list = get_chinese_words_list()
# 获得英文模板列表(只匹配车牌的第二个字符)
def get_eng_words_list():
eng_words_list = []
for i in range(10,34):
e_word = read_directory('./refer1/'+ template[i])
eng_words_list.append(e_word)
return eng_words_list
eng_words_list = get_eng_words_list()
# 获得英文和数字模板列表(匹配车牌后面的字符)
def get_eng_num_words_list():
eng_num_words_list = []
for i in range(0,34):
word = read_directory('./refer1/'+ template[i])
eng_num_words_list.append(word)
return eng_num_words_list
eng_num_words_list = get_eng_num_words_list()
# 读取一个模板地址与图片进行匹配,返回得分
def template_score(template,image):
#将模板进行格式转换
template_img=cv2.imdecode(np.fromfile(template,dtype=np.uint8),1)
template_img = cv2.cvtColor(template_img, cv2.COLOR_RGB2GRAY)
#模板图像阈值化处理——获得黑白图
ret, template_img = cv2.threshold(template_img, 0, 255, cv2.THRESH_OTSU)
# height, width = template_img.shape
# image_ = image.copy()
# image_ = cv2.resize(image_, (width, height))
image_ = image.copy()
#获得待检测图片的尺寸
height, width = image_.shape
# 将模板resize至与图像一样大小
template_img = cv2.resize(template_img, (width, height))
# 模板匹配,返回匹配得分
result = cv2.matchTemplate(image_, template_img, cv2.TM_CCOEFF)
return result[0][0]
# 对分割得到的字符逐一匹配
def template_matching(word_images):
results = []
for index,word_image in enumerate(word_images):
if index==0:
best_score = []
for chinese_words in chinese_words_list:
score = []
for chinese_word in chinese_words:
result = template_score(chinese_word,word_image)
score.append(result)
best_score.append(max(score))
i = best_score.index(max(best_score))
# print(template[34+i])
r = template[34+i]
results.append(r)
continue
if index==1:
best_score = []
for eng_word_list in eng_words_list:
score = []
for eng_word in eng_word_list:
result = template_score(eng_word,word_image)
score.append(result)
best_score.append(max(score))
i = best_score.index(max(best_score))
# print(template[10+i])
r = template[10+i]
results.append(r)
continue
else:
best_score = []
for eng_num_word_list in eng_num_words_list:
score = []
for eng_num_word in eng_num_word_list:
result = template_score(eng_num_word,word_image)
score.append(result)
best_score.append(max(score))
i = best_score.index(max(best_score))
# print(template[i])
r = template[i]
results.append(r)
continue
return results
word_images_ = word_images.copy()
# 调用函数获得结果
result = template_matching(word_images_)
#print(result)
# "".join(result)函数将列表转换为拼接好的字符串,方便结果显示
#print( "".join(result))
history.append("".join(result))
from PIL import ImageFont, ImageDraw, Image
height,weight = origin_image.shape[0:2]
#print(height)
#print(weight)
image_1 = origin_image.copy()
cv2.rectangle(image_1, (int(0.2*weight), int(0.75*height)), (int(weight*0.9), int(height*0.95)), (0, 255, 0), 5)
#设置需要显示的字体
fontpath = "font/simsun.ttc"
font = ImageFont.truetype(fontpath,64)
img_pil = Image.fromarray(image_1)
draw = ImageDraw.Draw(img_pil)
#绘制文字信息
draw.text((int(0.2*weight)+25, int(0.75*height)), "".join(result), font = font, fill = (255, 255, 0))
bk_img = np.array(img_pil)
#print(result)
return bk_img
root = tk.Tk()
root.title("图片导入器")
root.geometry("1000x1000")
# 用于存储历史记录的列表
history = []
current_image_label = None
# 全局变量,用于存储加载的图像
# 显示图像的函数
def show_image(image):
global current_image_label # 引用全局变量
if current_image_label is not None: # 如果存在先前的Label先删除它
current_image_label.pack_forget() # 使用pack_forget()移除组件
pil_image = ImageTk.PhotoImage(image=Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)))
lbl_image = tk.Label(root, image=pil_image)
lbl_image.image = pil_image # 保持对图像的引用,防止垃圾回收
lbl_image.pack()
current_image_label = lbl_image # 更新全局变量存储新的Label引用
def open_image():
# 弹出文件选择对话框并返回用户选择的文件路径
file_path = filedialog.askopenfilename()
return file_path
def load_and_show_image():
file_path = open_image() # 调用函数获取文件路径
show_image(eaowej(file_path)) # 传递文件路径给加载图像的函数
# 显示历史记录的函数
def plt_show0(img):
# cv2与plt的图像通道不同cv2为[b,g,r];plt为[r, g, b]
b, g, r = cv2.split(img)
img = cv2.merge([r, g, b])
plt.imshow(img)
plt.show()
# 防止Tkinter在图像数据被垃圾回收时删除图像
label.image = photo_image
# 运行Tkinter事件循环
def show_history():
# 创建一个新的窗口来显示历史记录
history_window = tk.Toplevel(root)
history_window.title("历史记录")
history_window.geometry("600x400") # 根据需要调整大小
# 创建一个文本框来显示历史记录
txt_history = tk.Text(history_window, height=10, width=50)
txt_history.pack(pady=20)
# 将历史记录数据添加到文本框中
for record in history:
txt_history.insert(tk.END, record + "\n")
button_history = tk.Button(root, text="查看历史记录", command=show_history)
button_history.pack()
# 创建一个按钮,点击时调用 load_and_show_image 函数
button = tk.Button(root, text="导入图片", command=load_and_show_image)
button.pack()
root.mainloop()
print(history)
Loading…
Cancel
Save