简体   繁体   中英

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

I am using my keras model to detect 2 categories using a modified tkinter program to that classifies butterfly species.

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()

and got this error

SystemError: returned NULL without setting an error

I have tried a fix from a similar question asked here but with no luck I think there is a problem when importing the image through tkinter and not through a file path?

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

full error message

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

The prepare function you implemented does the process of loading, resizing, reshaping images. The purpose of the function cv2.imread is to open an image from a given file path. But you fed the function prepare(new_array) where new_array is already the image itself, not the file path. I suggest two fixes, although both are conclusively equal.

Also, model.predict outputs the final layer in real numbers instead of integer-type class number. Therefore you must use model.predict_classes in this case. Also, because these functions default to batch mode, although you only feed a single image, you must assume the prediction to be an array, and index it.

First fix is to feed the file path and load the image inside the 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)

Next is to perform only reshaping in the 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)

I would also like to say that this type of resizing process is very inefficient. What would be a solution for an input pipeline is the preprocessing layers developed inside Tensorflow. You can create a model acting as an input pipeline.

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)

or use tf.image.resize , since they can processes batches of images without an explicit loop, and provides more features that can be applied simply.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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