Untitled
unknown
plain_text
a year ago
11 kB
5
Indexable
import customtkinter as ctk
import tkinter as tk
from PIL import Image
import os
import numpy as np
from datetime import datetime
import cv2
import tflite_runtime.interpreter as tflite
from pathlib import Path
import math
class CircularProgress(ctk.CTkCanvas):
def __init__(self, parent, size=100, fg_color="#2CC985", bg_color="#2B2B2B", text="", text_color="white", **kwargs):
super().__init__(parent, width=size, height=size, bg=parent.cget("fg_color"), highlightthickness=0, **kwargs)
self.size = size
self.fg_color = fg_color
self.bg_color = bg_color
self.text = text
self.text_color = text_color
self.percentage = 0
self.warning_threshold = 90
self.draw()
def draw(self):
self.delete("progress")
self.delete("text")
# Background circle
padding = 2
self.create_oval(padding, padding, self.size-padding, self.size-padding,
fill=self.bg_color, width=0, tags="progress")
if self.percentage > 0:
start_angle = 90
extent = -(self.percentage/100 * 360)
# Calculate coordinates for arc
x0 = padding
y0 = padding
x1 = self.size - padding
y1 = self.size - padding
# Draw progress arc
arc_color = "#FF5555" if self.percentage >= self.warning_threshold else self.fg_color
self.create_arc(x0, y0, x1, y1,
start=start_angle, extent=extent,
fill="", width=3,
style="arc", outline=arc_color,
tags="progress")
# Add text
self.create_text(self.size/2, self.size/2,
text=self.text, fill=self.text_color,
font=("Helvetica", int(self.size/8), "bold"),
tags="text")
def set_percentage(self, percentage):
self.percentage = min(100, max(0, percentage))
self.draw()
class WasteClassificationGUI:
def __init__(self):
self.setup_window()
self.setup_model()
self.setup_camera()
self.create_folders()
self.setup_styles()
self.create_main_screen()
self.current_screen = "main"
self.timer = None
def setup_window(self):
self.root = ctk.CTk()
self.root.geometry("1024x600")
self.root.title("Waste Classification")
self.root.attributes('-fullscreen', True)
ctk.set_appearance_mode("dark")
def setup_model(self):
MODEL_PATH = "ei-v2-transfer-learning-tensorflow-lite-float32-model.lite"
self.interpreter = tflite.Interpreter(model_path=MODEL_PATH)
self.interpreter.allocate_tensors()
self.input_details = self.interpreter.get_input_details()
self.output_details = self.interpreter.get_output_details()
self.height = self.input_details[0]['shape'][1]
self.width = self.input_details[0]['shape'][2]
self.class_names = ["Biomüll", "Gelber Sack", "Papier", "Restmüll"]
def setup_camera(self):
from picamera2 import Picamera2
self.camera = Picamera2()
self.camera.preview_configuration.main.size = (1920, 1440)
self.camera.preview_configuration.main.format = "RGB888"
self.camera.configure("preview")
self.camera.set_controls({"AfMode": 2})
self.camera.start()
def create_folders(self):
self.base_dir = Path("captured_images")
for class_name in self.class_names:
(self.base_dir / class_name).mkdir(parents=True, exist_ok=True)
def setup_styles(self):
self.colors = {
"Biomüll": "#8B4513",
"Gelber Sack": "#FFD700",
"Papier": "#4169E1",
"Restmüll": "#808080",
"background": "#1E1E1E",
"timer": "#FFFFFF",
"text": "#FFFFFF"
}
def create_timer_bar(self, parent, duration=5000):
timer_frame = ctk.CTkFrame(parent, fg_color="transparent")
timer_frame.pack(fill="x", padx=10, pady=5)
self.timer_bar = ctk.CTkProgressBar(timer_frame)
self.timer_bar.pack(fill="x", padx=5)
self.timer_bar.set(1.0)
def update_timer(remaining):
if remaining <= 0:
self.show_main_screen()
return
self.timer_bar.set(remaining/duration)
self.root.after(50, update_timer, remaining - 50)
update_timer(duration)
def create_main_screen(self):
self.main_frame = ctk.CTkFrame(self.root, fg_color=self.colors["background"])
self.main_frame.pack(fill="both", expand=True)
# Circles container
circles_frame = ctk.CTkFrame(self.main_frame, fg_color="transparent")
circles_frame.pack(expand=True)
self.circles = {}
circle_size = 150
for i, class_name in enumerate(self.class_names):
circle_frame = ctk.CTkFrame(circles_frame, fg_color="transparent")
circle_frame.pack(side="left", padx=20)
circle = CircularProgress(circle_frame, size=circle_size,
fg_color=self.colors[class_name],
bg_color="#2B2B2B",
text=class_name)
circle.pack(pady=10)
slider = ctk.CTkSlider(circle_frame, from_=0, to=100,
command=lambda val, c=circle: c.set_percentage(val))
slider.pack(pady=5)
slider.set(0)
self.circles[class_name] = {"circle": circle, "slider": slider}
# Bottom buttons
button_frame = ctk.CTkFrame(self.main_frame, fg_color="transparent")
button_frame.pack(side="bottom", fill="x", padx=20, pady=20)
scan_button = ctk.CTkButton(button_frame, text="Scan",
command=self.start_scan,
width=100)
scan_button.pack(side="left")
def start_scan(self):
image = self.camera.capture_array()
prediction, confidence = self.classify_image(image)
self.show_result_screen(prediction, confidence, image)
def classify_image(self, image):
processed_image = self.preprocess_image(image)
self.interpreter.set_tensor(self.input_details[0]['index'], processed_image)
self.interpreter.invoke()
output = self.interpreter.get_tensor(self.output_details[0]['index'])
max_index = np.argmax(output[0])
confidence = output[0][max_index] * 100
prediction = self.class_names[max_index]
return prediction, confidence
def preprocess_image(self, image):
resized = cv2.resize(image, (self.width, self.height))
normalized = resized / 255.0
return np.expand_dims(normalized, axis=0).astype(np.float32)
def show_result_screen(self, prediction, confidence, image):
self.clear_current_screen()
result_frame = ctk.CTkFrame(self.root, fg_color=self.colors["background"])
result_frame.pack(fill="both", expand=True)
self.create_timer_bar(result_frame)
heading = ctk.CTkLabel(result_frame,
text=f"Detected: {prediction}",
font=("Helvetica", 24, "bold"))
heading.pack(pady=20)
confidence_label = ctk.CTkLabel(result_frame,
text=f"Confidence: {confidence:.1f}%",
font=("Helvetica", 18))
confidence_label.pack(pady=10)
buttons_frame = ctk.CTkFrame(result_frame, fg_color="transparent")
buttons_frame.pack(pady=20)
ctk.CTkButton(buttons_frame,
text="✓",
command=lambda: self.handle_feedback(True, prediction, image),
width=60).pack(side="left", padx=10)
ctk.CTkButton(buttons_frame,
text="✗",
command=lambda: self.handle_feedback(False, prediction, image),
width=60).pack(side="left", padx=10)
def handle_feedback(self, is_correct, prediction, image):
if is_correct:
self.save_image(image, prediction)
self.show_thank_you_screen()
else:
self.show_correction_screen(image)
def show_correction_screen(self, image):
self.clear_current_screen()
correction_frame = ctk.CTkFrame(self.root, fg_color=self.colors["background"])
correction_frame.pack(fill="both", expand=True)
self.create_timer_bar(correction_frame)
heading = ctk.CTkLabel(correction_frame,
text="Select correct category:",
font=("Helvetica", 24, "bold"))
heading.pack(pady=20)
buttons_frame = ctk.CTkFrame(correction_frame, fg_color="transparent")
buttons_frame.pack(expand=True)
for class_name in self.class_names:
btn = ctk.CTkButton(buttons_frame,
text=class_name,
fg_color=self.colors[class_name],
command=lambda c=class_name: self.handle_correction(c, image))
btn.pack(pady=10)
def handle_correction(self, correct_class, image):
self.save_image(image, correct_class)
self.show_thank_you_screen()
def show_thank_you_screen(self):
self.clear_current_screen()
thank_you_frame = ctk.CTkFrame(self.root, fg_color=self.colors["background"])
thank_you_frame.pack(fill="both", expand=True)
self.create_timer_bar(thank_you_frame, duration=3000)
heading = ctk.CTkLabel(thank_you_frame,
text="Thank you for your feedback!",
font=("Helvetica", 24, "bold"))
heading.pack(expand=True)
def save_image(self, image, class_name):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
save_path = self.base_dir / class_name / f"capture_{timestamp}.jpg"
cv2.imwrite(str(save_path), cv2.cvtColor(image, cv2.COLOR_RGB2BGR))
def clear_current_screen(self):
for widget in self.root.winfo_children():
widget.destroy()
def show_main_screen(self):
self.clear_current_screen()
self.create_main_screen()
def run(self):
self.root.mainloop()
if __name__ == "__main__":
app = WasteClassificationGUI()
app.run()Editor is loading...
Leave a Comment