I will provide the code first, this code is running normally in PyCharm as i wanted .
import os
import tkinter as tk
from tkinter import filedialog, ttk
from PIL import Image, ImageTk, ImageDraw
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
import numpy as np
import tensorflow as tf
import logging
# Configure logging
logging.basicConfig(filename='image_classification.log', level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s')
class ImageClassificationApp:
def __init__(self, root):
self.root = root
self.root.title("Image Classification App")
self.root.geometry("1040x780") # Increase GUI size by 30%
self.label = tk.Label(root, text="Upload images to classify")
self.label.pack()
self.upload_button = tk.Button(root, text="Upload Images", command=self.upload_images)
self.upload_button.pack()
self.canvas = tk.Canvas(root)
self.scrollbar = ttk.Scrollbar(root, orient="vertical", command=self.canvas.yview)
self.scrollable_frame = ttk.Frame(self.canvas)
self.scrollable_frame.bind(
"<Configure>",
lambda e: self.canvas.configure(
scrollregion=self.canvas.bbox("all")
)
)
self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.canvas.pack(side="left", fill="both", expand=True)
self.scrollbar.pack(side="right", fill="y")
self.progress = ttk.Progressbar(root, orient="horizontal", length=300, mode="determinate")
self.progress.pack(pady=10)
logging.info("Initialized ImageClassificationApp")
def upload_images(self):
file_paths = filedialog.askopenfilenames()
if file_paths:
logging.info(f"Uploaded images: {file_paths}")
self.show_images(file_paths)
def show_images(self, file_paths):
for widget in self.scrollable_frame.winfo_children():
widget.destroy()
row = 0
col = 0
self.progress["maximum"] = len(file_paths)
self.progress["value"] = 0
for file_path in file_paths:
try:
img = Image.open(file_path)
original_size = img.size
logging.info(f"Opened image: {file_path} with size {original_size}")
if original_size[0] < 150 or original_size[1] < 150:
logging.error(f"Image size is too small for ROI extraction: {original_size}")
continue
results, config_name, roi_images = self.predict_image(file_path)
# Check if results match the number of ROIs
if len(results) != len(roi_images):
logging.error("Mismatch between number of results and ROIs")
continue
# Draw ROI rectangles
draw = ImageDraw.Draw(img)
rois = [
((2, 2), (56, 35)),
((83, 34), (139, 74)),
((33, 95), (92, 136))
]
for i, ((x1, y1), (x2, y2)) in enumerate(rois):
logging.info(f"Processing ROI: {x1}, {y1}, {x2, y2}")
color = "green" if results[i] == "OK" else "red"
width = 2 if results[i] == "OK" else 4
draw.rectangle([x1, y1, x2, y2], outline=color, width=width)
photo = ImageTk.PhotoImage(img)
img_label = tk.Label(self.scrollable_frame, image=photo, borderwidth=2, relief="flat")
img_label.image = photo
img_label.grid(row=row, column=col, padx=5, pady=5)
color = 'green' if all(result == 'OK' for result in results) else 'red'
result_label = tk.Label(self.scrollable_frame, text=f'Prediction: {results}', fg=color)
result_label.grid(row=row + 1, column=col, padx=5, pady=5)
config_label = tk.Label(self.scrollable_frame, text=f'Configuration: {config_name}')
config_label.grid(row=row + 2, column=col, padx=5, pady=5)
filename_label = tk.Label(self.scrollable_frame, text=os.path.basename(file_path))
filename_label.grid(row=row + 3, column=col, padx=5, pady=5)
# Display ROI images and their results
for i, (roi_image, result) in enumerate(zip(roi_images, results)):
roi_photo = ImageTk.PhotoImage(roi_image)
roi_label = tk.Label(self.scrollable_frame, image=roi_photo, borderwidth=2, relief="flat")
roi_label.image = roi_photo
roi_label.grid(row=row, column=col + 1 + i, padx=5, pady=5)
roi_result_label = tk.Label(self.scrollable_frame, text=f'ROI {i+1} Result: {result}', fg=color)
roi_result_label.grid(row=row + 1, column=col + 1 + i, padx=5, pady=5)
# Add debug information below the image
debug_info = f"Original size: {original_size}\nROIs: {rois}"
debug_label = tk.Label(self.scrollable_frame, text=debug_info, fg="blue")
debug_label.grid(row=row + 4, column=col, padx=5, pady=5, columnspan=2)
col += 2 + len(roi_images) # Move to the next column for the next image
if col >= 6: # Change to 6 to fit 3 images per row
col = 0
row += 5 # Adjust row increment to fit debug info
self.progress["value"] += 1
self.root.update_idletasks()
logging.info(f"Processed image: {file_path}")
except Exception as e:
logging.error(f"Error processing {file_path}: {e}")
self.progress.pack_fet() # Hide progress bar after completion
logging.info("Completed processing all images")
def predict_image(self, image_path):
try:
if image_path is None:
logging.error("Error: image_path is None")
return ['Error'], 'None', []
img = image.load_img(image_path, target_size=(150, 150))
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0) / 255.0
if img_array is None:
logging.error("Error: img_array is None")
return ['Error'], 'None', []
# Extract ROIs
rois = [
((2, 2), (56, 35)),
((83, 34), (139, 74)),
((33, 95), (92, 136))
]
roi_images = []
results = []
for (x1, y1), (x2, y2) in rois:
logging.info(f"Processing ROI: {x1, y1, x2, y2}")
roi = img_array[:, y1:y2, x1:x2, :]
roi_resized = tf.image.resize(roi, (150, 150))
roi_image = Image.fromarray((roi_resized[0].numpy() * 255).astype(np.uint8))
roi_images.append(roi_image)
model_path = 'C:\\Users\\FA9JCWQ\\PycharmProjects\\rozpoznani_obrazku_vol3\\venv\\Lib\\Bin\\default.keras'
try:
default_model = load_model(model_path)
logging.info(f"Model loaded successfully from: {model_path}")
except Exception as e:
logging.error(f"Error loading model from {model_path}: {e}")
return ['Error'], 'None', []
logging.debug(f"Model object: {default_model}")
prediction = default_model.predict(roi_resized)
config_name = 'default.keras'
result = 'OK' if prediction[0][0] > 0.5 else 'NOK'
results.append(result)
logging.info(f"Predicted results for {image_path} using {config_name}: {results}")
return results, config_name, roi_images
except Exception as e:
logging.error(f"Error predicting {image_path}: {e}")
return ['Error'], 'None', []
if __name__ == "__main__":
root = tk.Tk()
app = ImageClassificationApp(root)
root.mainloop()
Script is running perfectly in PyCharm.
Also as the image prediction itself at 99%
I have created .exe file from this script using this command .
pyinstaller --onefile --windowed --add-data "C:\Users\FA9JCWQ\PycharmProjects\rozpoznani_obrazku_vol3\venv\Lib\Bin\default.keras:." --hidden-import tensorflow --hidden-import PIL --hidden-import tkinter --hidden-import numpy testing_space.py
.exe was created succesfully . Was ran normally, but after uploading the image in the GUI ,nothing happens .
I got this from my log files . Which i believe , there must be some problem loading default.keras before processing each ROI . I still cannot understand why is it running in PyCharm , but not after .exe .
All files have permisions , Firewall is not blocking it .
2025-03-18 13:57:06,302 - INFO - Uploaded images: ('C:/Users/FA9JCWQ/PycharmProjects/rozpoznani_obrazku_vol3/venv/Lib/Bin/Production/IMG_2084_grey_resized.jpeg',) 2025-03-18 13:57:06,330 - INFO - Opened image: C:/Users/FA9JCWQ/PycharmProjects/rozpoznani_obrazku_vol3/venv/Lib/Bin/Production/IMG_2084_grey_resized.jpeg with size (150, 150) 2025-03-18 13:57:06,330 - INFO - Processing ROI: (2, 2, 56, 35) 2025-03-18 13:57:06,877 - INFO - Model loaded successfully from: C:\Users\FA9JCWQ\PycharmProjects\rozpoznani_obrazku_vol3\venv\Lib\Bin\default.keras 2025-03-18 13:57:06,877 - DEBUG - Model object: <Sequential name=sequential, built=True> 2025-03-18 13:57:06,992 - ERROR - Error predicting C:/Users/FA9JCWQ/PycharmProjects/rozpoznani_obrazku_vol3/venv/Lib/Bin/Production/IMG_2084_grey_resized.jpeg: 'NoneType' object has no attribute 'write' 2025-03-18 13:57:06,992 - ERROR - Mismatch between number of results and ROIs 2025-03-18 13:57:06,992 - INFO - Completed processing all images