0

I have a Tkinter app for detecting the objects by importing images or videos from my system(using my custom model which predict fine when used via cmd predict function).

It works well, without any errors but it doesn't display the image which gets imported neither it showcases detections after clicking on Detect button. Basically the output is "blank".

My model image resolution is 640x640 and my system image size is 3840x2160

import tkinter as tk
from tkinter import filedialog
import cv2
import numpy as np
import onnxruntime
from PIL import Image, ImageTk

class ObjectDetector:
    def __init__(self, model_path):
        self.session = onnxruntime.InferenceSession(model_path)
        self.input_name = self.session.get_inputs()[0].name
        self.output_name = self.session.get_outputs()[0].name
        self.input_shape = self.session.get_inputs()[0].shape[2:]  # Get input shape from model

    def detect_objects(self, image):
        input_image = cv2.resize(image, (self.input_shape[1], self.input_shape[0]))  # Resize image
        input_image = np.transpose(input_image, (2, 0, 1))  # Change to NCHW format
        input_image = np.expand_dims(input_image, axis=0).astype(np.float32)
        input_image /= 255.0  # Normalize image
        outputs = self.session.run([self.output_name], {self.input_name: input_image})
        return outputs[0]

class App:
    def __init__(self, root):
        self.root = root
        self.root.title("Object Detection App")

        self.detector = None
        self.image_path = None

        self.create_widgets()

    def create_widgets(self):
        self.select_button = tk.Button(self.root, text="Select Image or Video", command=self.select_file)
        self.select_button.pack()

        self.detect_button = tk.Button(self.root, text="Detect Objects", command=self.detect_objects, state=tk.DISABLED)
        self.detect_button.pack()

        # Use a smaller canvas size
        self.canvas = tk.Canvas(self.root, bg="white", width=800, height=600)
        self.canvas.pack()

    def select_file(self):
        self.image_path = filedialog.askopenfilename()
        if self.image_path.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
            self.detect_button.config(state="normal")
            self.display_image()
        else:
            self.detect_button.config(state="disabled")

    def display_image(self):
        if self.image_path:
            image = cv2.imread(self.image_path)
            image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
            image = cv2.resize(image, (800, 600))  # Resize image to fit canvas
            img_tk = self.convert_image_to_tkinter(image)
            self.canvas.create_image(0, 0, anchor=tk.NW, image=img_tk)

    def detect_objects(self):
        if self.image_path:
            if self.image_path.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
                image = cv2.imread(self.image_path)
                detector = ObjectDetector("C:/Software/anaconda22/envs/yolov8_custom/yolov8m_custom.onnx")
                results = detector.detect_objects(image)
                self.draw_bounding_boxes(image, results)
                img_tk = self.convert_image_to_tkinter(image)
                self.canvas.create_image(0, 0, anchor=tk.NW, image=img_tk)
            else:
                print("Unsupported file format. Please select an image file.")

    def draw_bounding_boxes(self, image, results):
        for result in results:
            for detection in result:
                score = detection[-1]
                if score > 0.2:  # Filter out detections with low confidence
                    if len(detection) >= 7:  # Check if the detection array has enough elements
                        x_min, y_min, x_max, y_max = detection[-4:]
                        # Scale bounding box coordinates to fit canvas size
                        x_min *= (800 / image.shape[1])
                        y_min *= (600 / image.shape[0])
                        x_max *= (800 / image.shape[1])
                        y_max *= (600 / image.shape[0])
                        cv2.rectangle(image, (int(x_min), int(y_min)), (int(x_max), int(y_max)), (0, 255, 0), 2)

    def convert_image_to_tkinter(self, image):
        img = Image.fromarray(image)
        img_tk = ImageTk.PhotoImage(image=img)
        return img_tk

if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.mainloop()

I have tried including labels also for the draw_bounding_boxes func but even that didn't work.

3
  • minimal reproducible example required. find out if this is an issue with Tkinter or with the computer vision part. replace each half with a trivial substitute (tkinter: cv.imshow and waitkey, computer vision: numpy array generated in code) Commented Jun 13, 2024 at 8:34
  • I cannot use yolo8 Commented Jun 13, 2024 at 11:47
  • Add this on line 62 and 63, cv2.imshow('Image', image) and cv2.waitKey(0) in display_image() function. Commented Jun 13, 2024 at 12:03

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.