Untitled
unknown
plain_text
a year ago
11 kB
12
Indexable
import customtkinter as ctk
import tkinter as tk
from PIL import Image, ImageTk
import numpy as np
import cv2
import math
import os
from datetime import datetime
import tflite_runtime.interpreter as tflite
from picamera2 import Picamera2
import threading
import time
class CircularProgress(ctk.CTkCanvas):
def __init__(self, parent, name, color, size=100, **kwargs):
super().__init__(parent, width=size, height=size, **kwargs)
self.size = size
self.color = color
self.name = name
self.configure(bg=parent.cget('bg'))
self.value = 0
# Create background circle
padding = 2
self.create_oval(padding, padding, size-padding, size-padding,
width=2, outline='gray80')
# Create text
self.create_text(size/2, size/2, text=name, fill='white',
font=('Arial', int(size/8)))
self.arc = None
self.warning_glow = None
self.draw_progress(0)
def draw_progress(self, percentage):
self.value = percentage
angle = 360 * (percentage / 100)
# Remove existing arc
if self.arc is not None:
self.delete(self.arc)
if self.warning_glow is not None:
self.delete(self.warning_glow)
# Calculate arc coordinates
start_angle = -90
end_angle = start_angle + angle
# Add warning glow for >90%
if percentage > 90:
self.warning_glow = self.create_arc(4, 4, self.size-4, self.size-4,
start=start_angle, extent=angle,
outline='red', width=4, style='arc')
# Draw progress arc
self.arc = self.create_arc(4, 4, self.size-4, self.size-4,
start=start_angle, extent=angle,
outline=self.color, width=3, style='arc')
class Timer:
def __init__(self, duration, callback):
self.duration = duration
self.callback = callback
self.remaining = duration
self.running = False
self.thread = None
def start(self):
self.running = True
self.remaining = self.duration
self.thread = threading.Thread(target=self._run)
self.thread.daemon = True
self.thread.start()
def _run(self):
while self.running and self.remaining > 0:
time.sleep(0.1)
self.remaining -= 0.1
if self.running:
self.callback()
def stop(self):
self.running = False
if self.thread:
self.thread.join()
class WasteClassificationGUI:
def __init__(self):
self.setup_window()
self.setup_camera()
self.setup_model()
self.create_main_view()
# Create image storage folders
self.categories = {
"Biomüll": "brown",
"Gelber Sack": "yellow",
"Papier": "blue",
"Restmüll": "gray"
}
for category in self.categories:
os.makedirs(f"captured_images/{category}", exist_ok=True)
def setup_window(self):
self.root = ctk.CTk()
self.root.geometry("1024x600")
self.root.title("Waste Classification")
ctk.set_appearance_mode("dark")
self.root.attributes('-fullscreen', True)
# Create main container
self.main_container = ctk.CTkFrame(self.root)
self.main_container.pack(fill='both', expand=True)
def setup_camera(self):
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 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()
def create_main_view(self):
# Clear current view
for widget in self.main_container.winfo_children():
widget.destroy()
# Create header with progress circles
header = ctk.CTkFrame(self.main_container)
header.pack(fill='x', padx=20, pady=20)
# Create circular progress indicators
self.progress_widgets = {}
for i, (category, color) in enumerate(self.categories.items()):
progress = CircularProgress(header, category, color, size=120)
progress.grid(row=0, column=i, padx=20)
self.progress_widgets[category] = progress
# Create slider for each progress
slider = ctk.CTkSlider(self.main_container,
from_=0, to=100,
command=lambda val, cat=category:
self.update_progress(cat, val))
slider.pack(pady=5)
# Create scan button
scan_frame = ctk.CTkFrame(self.main_container)
scan_frame.pack(side='bottom', pady=20)
scan_button = ctk.CTkButton(scan_frame,
text="Scan",
command=self.capture_and_classify,
width=120, height=40)
scan_button.pack(side='left', padx=10)
def update_progress(self, category, value):
self.progress_widgets[category].draw_progress(value)
def create_timer_bar(self, parent, duration):
timer_frame = ctk.CTkFrame(parent)
timer_frame.pack(fill='x', pady=5)
self.timer_bar = ctk.CTkProgressBar(timer_frame)
self.timer_bar.pack(fill='x', padx=20)
self.timer_bar.set(1)
def update_timer():
remaining = duration
while remaining > 0 and hasattr(self, 'timer_bar'):
self.timer_bar.set(remaining/duration)
remaining -= 0.1
time.sleep(0.1)
threading.Thread(target=update_timer, daemon=True).start()
def show_classification_result(self, class_name, confidence):
result_window = ctk.CTkToplevel(self.root)
result_window.geometry("1024x600")
result_window.attributes('-fullscreen', True)
# Create timer bar
self.create_timer_bar(result_window, 5)
# Display result
result_frame = ctk.CTkFrame(result_window)
result_frame.pack(expand=True)
icon_label = ctk.CTkLabel(result_frame,
text="🗑️",
font=("Arial", 48))
icon_label.pack(pady=20)
result_label = ctk.CTkLabel(result_frame,
text=f"{class_name}\n{confidence:.1f}%",
font=("Arial", 24))
result_label.pack(pady=20)
# Feedback buttons
feedback_frame = ctk.CTkFrame(result_frame)
feedback_frame.pack(pady=20)
ctk.CTkButton(feedback_frame,
text="👍",
command=lambda: self.handle_feedback(True, class_name, result_window),
width=80).pack(side='left', padx=10)
ctk.CTkButton(feedback_frame,
text="👎",
command=lambda: self.handle_feedback(False, class_name, result_window),
width=80).pack(side='left', padx=10)
# Auto-close timer
Timer(5, result_window.destroy).start()
def handle_feedback(self, positive, predicted_class, window):
window.destroy()
if not positive:
self.show_correction_dialog(predicted_class)
else:
self.show_thank_you()
def show_correction_dialog(self, predicted_class):
dialog = ctk.CTkToplevel(self.root)
dialog.geometry("1024x600")
dialog.attributes('-fullscreen', True)
# Create timer bar
self.create_timer_bar(dialog, 5)
# Correction options
options_frame = ctk.CTkFrame(dialog)
options_frame.pack(expand=True)
label = ctk.CTkLabel(options_frame,
text="Please select the correct category:",
font=("Arial", 20))
label.pack(pady=20)
for category in self.categories:
ctk.CTkButton(options_frame,
text=category,
command=lambda cat=category: self.handle_correction(cat, dialog),
width=200).pack(pady=10)
# Auto-close timer
Timer(5, dialog.destroy).start()
def show_thank_you(self):
thank_you = ctk.CTkToplevel(self.root)
thank_you.geometry("1024x600")
thank_you.attributes('-fullscreen', True)
# Create timer bar
self.create_timer_bar(thank_you, 3)
# Thank you message
message = ctk.CTkLabel(thank_you,
text="Thank you for your feedback!",
font=("Arial", 24))
message.pack(expand=True)
# Auto-close timer
Timer(3, thank_you.destroy).start()
def handle_correction(self, correct_category, dialog):
dialog.destroy()
self.show_thank_you()
def capture_and_classify(self):
# Capture image
image = self.camera.capture_array()
# Preprocess image
height = self.input_details[0]['shape'][1]
width = self.input_details[0]['shape'][2]
processed_image = cv2.resize(image, (width, height))
processed_image = processed_image / 255.0
processed_image = np.expand_dims(processed_image, axis=0).astype(np.float32)
# Run inference
self.interpreter.set_tensor(self.input_details[0]['index'], processed_image)
self.interpreter.invoke()
predictions = self.interpreter.get_tensor(self.output_details[0]['index'])[0]
# Get result
max_index = np.argmax(predictions)
confidence = predictions[max_index] * 100
class_name = list(self.categories.keys())[max_index]
# Show result
self.show_classification_result(class_name, confidence)
def run(self):
self.root.mainloop()
if __name__ == "__main__":
app = WasteClassificationGUI()
app.run()Editor is loading...
Leave a Comment