SystemError:<builtin function imread>返回NULL而未设置错误(tkinter)

2024-04-27 00:29:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用我的keras模型,通过修改tkinter程序对蝴蝶物种进行分类,来检测2个类别

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: returned NULL without setting an error

我已经尝试了一个类似问题的修复,但没有运气,我认为通过tkinter而不是通过文件路径导入图像时会出现问题

Using cv2.imread: "<built-in function imread> returned NULL without setting an error", as if it can't open the picture or get the data

完整错误消息

Exception in Tkinter callback Traceback (most recent call last):
File "C:\Users\1rock\anaconda3\envs\machL\lib\tkinter_init_.py", line 1883, in call return self.func(*args) File "C:/Users/1rock/anaconda3/envs/machL/fly.py", line 36, in command=lambda: classify(file_path),padx=10,pady=5) File "C:/Users/1rock/anaconda3/envs/machL/fly.py", line 29, in classify pred = model.predict([prepare(new_array)]) File "C:/Users/1rock/anaconda3/envs/machL/fly.py", line 22, in prepare img_array = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE) # read in the image, convert to grayscale SystemError: returned NULL without setting an error

Process finished with exit code 0


Tags: pathinimageimportmodeltkinterconfiguretop
1条回答
网友
1楼 · 发布于 2024-04-27 00:29:11

您实现的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,因为它们可以在没有显式循环的情况下处理成批的图像,并提供更多可以简单应用的功能

相关问题 更多 >