系统错误:<内置函数 imread> 返回 NULL,未设置错误 (tkinter)



我使用我的keras模型来检测两个类别,使用一个修改的tkinter程序来对蝴蝶物种进行分类。

import tkinter as tk
from tkinter import filedialog
from tkinter import *
from PIL import ImageTk, Image
import numpy
import cv2
import tensorflow as tf
model = tf.keras.models.load_model("64x300-CNN.model")
classes = ["real", "fake"]
top=tk.Tk()
top.geometry('800x600')
top.title('Butterfly Classification')
top.configure(background='#CDCDCD')
label=Label(top,background='#CDCDCD', font=('arial',15,'bold'))
sign_image = Label(top)
def prepare(filepath):
IMG_SIZE = 50  # 50 in txt-based
img_array = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)  # read in the image, convert to grayscale
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))  # resize image to match model's expected sizing
return new_array.reshape(-1, IMG_SIZE, IMG_SIZE, 1)  # return the image with shaping that TF wants.
def classify(file_path):
global label_packed
new_array = cv2.imread(file_path, 1)
pred = model.predict([prepare(new_array)])
sign = classes[pred]
print(sign)
label.configure(foreground='#011638', text=sign)
def show_classify_button(file_path):
classify_b=Button(top,text="Classify Image",
command=lambda: classify(file_path),padx=10,pady=5)
classify_b.configure(background='#364156', foreground='white',
font=('arial',10,'bold'))
classify_b.place(relx=0.79,rely=0.46)
def upload_image():
try:
file_path=filedialog.askopenfilename()
uploaded=Image.open(file_path)
uploaded.thumbnail(((top.winfo_width()/2.25),
(top.winfo_height()/2.25)))
im=ImageTk.PhotoImage(uploaded)
sign_image.configure(image=im)
sign_image.image=im
label.configure(text='')
show_classify_button(file_path)
except:
pass
upload=Button(top,text="Upload an image",command=upload_image,
padx=10,pady=5)
upload.configure(background='#364156', foreground='white',
font=('arial',10,'bold'))
upload.pack(side=BOTTOM,pady=50)
sign_image.pack(side=BOTTOM,expand=True)
label.pack(side=BOTTOM,expand=True)
heading = Label(top, text="Butterfly Classification",pady=20, font=('arial',20,'bold'))
heading.configure(background='#CDCDCD',foreground='#364156')
heading.pack()
top.mainloop()

得到这个错误

SystemError:返回NULL而未设置错误

我尝试过解决这里提出的类似问题,但运气不好,我认为通过tkinter而不是通过文件路径导入图像时有问题?

使用cv2.imread:"lt;内置函数imread>返回NULL而不设置错误";,就好像它可以';t打开图片或获取数据

完整错误消息

Tkinter回调Traceback中的异常(最近一次调用是最后一次(:
File"C: \Users\1lock\anaconda3\envs\machL\lib\tkinter_init_.py",第1883行,在调用中返回self.func(*args(File";C:/Users/1rock/anaconda3/envs/machL/fly.py";,第36行,incommand=lambda:classification(file_path(,padx=10,pady=5(file"C:/Users/1rock/anaconda3/envs/machL/fly.py";,第29行,分类pred=模型预测([prepare(new_array(](文件";C:/Users/1rock/anaconda3/envs/machL/fly.py";,第22行,准备中img_array=cv2.imread(filepath,cv2.imread_GRAYSCALE(#读取图像,转换为灰度系统错误:返回NULL,未设置错误

进程已完成,退出代码为0

您实现的prepare函数完成加载、调整大小和重塑图像的过程。函数cv2.imread的目的是从给定的文件路径打开图像。但是您提供了函数prepare(new_array),其中new_array已经是图像本身,而不是文件路径。我建议两种解决方案,尽管两者完全相同。

此外,model.predict以实数而不是整数类型的类编号输出最终层。因此,在这种情况下必须使用model.predict_classes。此外,由于这些函数默认为批处理模式,尽管您只提供单个图像,但您必须假设预测是一个数组,并对其进行索引

第一个修复方法是在prepare函数中提供文件路径并加载图像。

def prepare(filepath):
IMG_SIZE = 50  # 50 in txt-based
img_array = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)  # read in the image, convert to grayscale
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))  # resize image to match model's expected sizing
return new_array.reshape(-1, IMG_SIZE, IMG_SIZE, 1)  # return the image with shaping that TF wants.
def classify(file_path):
global label_packed
pred = model.predict_classes([prepare(file_path)])
sign = classes[pred[0,0]]
print(sign)
label.configure(foreground='#011638', text=sign)

接下来是仅在prepare函数中执行整形。

def prepare(img_array):
IMG_SIZE = 50  # 50 in txt-based
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))  # resize image to match model's expected sizing
return new_array.reshape(-1, IMG_SIZE, IMG_SIZE, 1)  # return the image with shaping that TF wants.
def classify(file_path):
global label_packed
new_array = cv2.imread(file_path, 1)
pred = model.predict_classes([prepare(new_array)])
sign = classes[pred[0,0]]
print(sign)
label.configure(foreground='#011638', text=sign)

我还想说,这种类型的调整大小的过程是非常低效的。输入管道的解决方案是Tensorflow内部开发的预处理层。您可以创建一个充当输入管道的模型。

input_pipeline=tf.keras.models.Sequential([
tf.keras.layers.experimental.preprocessing.Resizing(h,w,..),
tf.keras.layers.experimental.preprocessing...
])
...
new_array=input_pipeline.predict(img_array)

或者使用tf.image.resize,因为它们可以在没有显式循环的情况下处理一批批图像,并且提供了更多可以简单应用的功能。

最新更新