繁体   English   中英

系统错误:<built-in function imread> 返回 NULL 没有设置错误(tkinter)</built-in>

[英]SystemError: <built-in function imread> returned NULL without setting an error (tkinter)

我正在使用我的 keras model 使用改进的 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:返回 NULL 未设置错误

我已尝试从此处提出的类似问题中进行修复,但没有运气,我认为通过 tkinter 而不是通过文件路径导入图像时出现问题?

使用cv2.imread: "<built-in function imread> returned NULL without setting an error",好像打不开图片或获取数据

完整的错误信息

Tkinter 回调 Traceback 中的异常(最近一次调用最后一次):
文件“C:\Users\1rock\anaconda3\envs\machL\lib\ tkinter_init _.py”,第 1883 行,调用return self.func(*args) 文件“C:/Users/1rock/anaconda3/envs/ machL/fly.py”,第 36 行,在命令 = lambda 中:classify(file_path),padx=10,pady=5) 文件“C:/Users/1rock/anaconda3/envs/machL/fly.py”,第 29 行,在分类 pred = model.predict([prepare(new_array)]) 文件“C:/Users/1rock/anaconda3/envs/machL/fly.py”,第 22 行,准备 img_array = cv2.imread(filepath, cv2 .IMREAD_GRAYSCALE) # 读入图像,转灰度 SystemError: returned NULL without setting an error

进程以退出代码 0 结束

您实现的准备 function 执行加载、调整大小、重塑图像的过程。 function cv2.imread的目的是从给定的文件路径打开图像。 但是您输入了 function prepare(new_array)其中new_array已经是图像本身,而不是文件路径。 我建议进行两个修复,尽管两者最终是相等的。

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

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

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 function 中执行整形。

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 内部开发的预处理层。 您可以创建一个 model 作为输入管道。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM