Skip to main content

Overview

The main.py GUI application provides an intuitive, full-featured interface for waste detection and classification. It includes real-time video feed, visual classification feedback, and color-coded detection boxes.
The GUI requires the setUp folder with background images and classification icons, plus the trained model at Modelos/best.pt.

Launching the GUI

1

Navigate to Source Directory

Open your terminal and go to the project directory:
cd /path/to/reciclaje-ai/source
2

Verify Required Assets

Ensure you have the setUp folder with required images:
ls setUp/
# Should show: Canva.png, metal.png, vidrio.png, plastico.png, 
#              carton.png, medical.png, metaltxt.png, vidriotxt.png,
#              plasticotxt.png, cartontxt.png, medicaltxt.png
3

Run the GUI Application

Execute main.py:
python main.py
The GUI window will open with title “RECICLAJE INTELIGENTE” (Intelligent Recycling).
4

Start Detecting

The application automatically:
  • Initializes the camera (index 0)
  • Loads the YOLOv8 model
  • Begins real-time detection
  • Displays classification results

GUI Layout

The application window is 1280x720 pixels with three main areas:

Layout Regions

Video Feed

Position: Center-left (320, 180)Size: 640px width (auto-scaled)Shows live camera feed with bounding boxes

Detection Image

Position: Left panel (75, 260)Displays icon of detected waste type

Classification Text

Position: Right panel (995, 310)Shows classification label image

Detection Features

Color-Coded Classifications

Each waste type has a unique color for easy identification:
Color: Yellow (RGB: 255, 255, 0)Class ID: 0
main.py:82-95
if cls == 0:
    # Draw
    cv2.rectangle(frame_show, (x1, y1), (x2, y2), (255, 255, 0), 2)
    # Text
    text = f'{clsName[cls]} {int(conf) * 100}%'
    sizetext = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 1, 2)
    dim = sizetext[0]
    baseline = sizetext[1]
    # Rect
    cv2.rectangle(frame_show, (x1, y1 - dim[1] - baseline), (x1 + dim[0], y1 + baseline), (0, 0, 0),cv2.FILLED)
    cv2.putText(frame_show, text, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2)
    
    # Clasificacion
    images(img_metal, img_metaltxt)
Displays metal.png and metaltxt.png when metal is detected.

Smart Label Rendering

The GUI uses intelligent text rendering with background boxes:
main.py:87-92
text = f'{clsName[cls]} {int(conf) * 100}%'
sizetext = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 1, 2)
dim = sizetext[0]
baseline = sizetext[1]
# Black background rectangle for text visibility
cv2.rectangle(frame_show, (x1, y1 - dim[1] - baseline), (x1 + dim[0], y1 + baseline), (0, 0, 0), cv2.FILLED)
cv2.putText(frame_show, text, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2)
Black background rectangles behind labels ensure text is readable against any background color.

Core Functions

Scanning Function

The heart of the GUI is the Scanning() function that runs continuously:
main.py:38-176
def Scanning():
    global img_metal, img_glass, img_plastic, img_carton, img_medical
    global img_metaltxt, img_glasstxt, img_plastictxt, img_cartontxt, img_medicaltxt, pantalla
    global lblimg, lblimgtxt

    # Interfaz
    lblimg = Label(pantalla)
    lblimg.place(x=75, y=260)

    lblimgtxt = Label(pantalla)
    lblimgtxt.place(x=995, y=310)
    detect = False

    # Read VideoCapture
    if cap is not None:
        ret, frame = cap.read()
        frame_show =cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        # True
        if ret == True:
            # Yolo | AntiSpoof
            results = model(frame, stream=True, verbose=False)
            # ... detection logic ...
            
            if detect == False:
                # Clean
                clean_lbl()

            # Resize
            frame_show = imutils.resize(frame_show, width=640)

            # Convertimos el video
            im = Image.fromarray(frame_show)
            img = ImageTk.PhotoImage(image=im)

            # Mostramos en el GUI
            lblVideo.configure(image=img)
            lblVideo.image = img
            lblVideo.after(10, Scanning)  # Recursively call every 10ms

        else:
            cap.release()
Key behaviors:
  • Runs every 10 milliseconds (lblVideo.after(10, Scanning))
  • Clears classification images when no objects detected
  • Handles color space conversion (BGR to RGB)
  • Resizes video to 640px width for display

Image Display Function

Handles classification image updates:
main.py:15-35
def images(img, imgtxt):
    img = img
    imgtxt = imgtxt

    # Img Detect
    img = np.array(img, dtype="uint8")
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    img = Image.fromarray(img)

    img_ = ImageTk.PhotoImage(image=img)
    lblimg.configure(image=img_)
    lblimg.image = img_

    # Img Text
    imgtxt = np.array(imgtxt, dtype="uint8")
    imgtxt = cv2.cvtColor(imgtxt, cv2.COLOR_BGR2RGB)
    imgtxt = Image.fromarray(imgtxt)

    img_txt = ImageTk.PhotoImage(image=imgtxt)
    lblimgtxt.configure(image=img_txt)
    lblimgtxt.image = img_txt

Clean Label Function

Clears classification images when no detection occurs:
main.py:10-13
def clean_lbl():
    # Clean
    lblimg.config(image='')
    lblimgtxt.config(image='')

Application Initialization

The ventana_principal() function sets up the entire application:
main.py:182-225
def ventana_principal():
    global cap, lblVideo, model, clsName, img_metal, img_glass, img_plastic, img_carton, img_medical
    global img_metaltxt, img_glasstxt, img_plastictxt, img_cartontxt, img_medicaltxt, pantalla
    
    # Ventana principal
    pantalla = Tk()
    pantalla.title("RECICLAJE INTELIGENTE")
    pantalla.geometry("1280x720")

    # Background
    imagenF = PhotoImage(file="setUp/Canva.png")
    background = Label(image=imagenF, text="Inicio")
    background.place(x=0, y=0, relwidth=1, relheight=1)

    # Model
    model = YOLO('Modelos/best.pt')

    # Clases
    clsName = ['Metal', 'Glass', 'Plastic', 'Carton', 'Medical']

    # Images
    img_metal = cv2.imread("setUp/metal.png")
    img_glass = cv2.imread("setUp/vidrio.png")
    img_plastic = cv2.imread("setUp/plastico.png")
    img_carton = cv2.imread("setUp/carton.png")
    img_medical = cv2.imread("setUp/medical.png")
    img_metaltxt = cv2.imread("setUp/metaltxt.png")
    img_glasstxt = cv2.imread("setUp/vidriotxt.png")
    img_plastictxt = cv2.imread("setUp/plasticotxt.png")
    img_cartontxt = cv2.imread("setUp/cartontxt.png")
    img_medicaltxt = cv2.imread("setUp/medicaltxt.png")

    # Video
    lblVideo = Label(pantalla)
    lblVideo.place(x=320, y=180)

    # Elegimos la camara
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
    cap.set(3, 1280)
    cap.set(4, 720)
    Scanning()

    # Eject
    pantalla.mainloop()
The GUI uses cv2.CAP_DSHOW on Windows for DirectShow support. On Linux/Mac, this flag is ignored automatically.

Required Assets

The GUI requires these image files in the setUp/ directory:

Background

  • Canva.png: Main application background (1280x720)

Classification Icons

Waste Type Icons

  • metal.png
  • vidrio.png (glass)
  • plastico.png
  • carton.png
  • medical.png

Text Label Icons

  • metaltxt.png
  • vidriotxt.png
  • plasticotxt.png
  • cartontxt.png
  • medicaltxt.png

Performance Considerations

Frame Rate Optimization

The GUI updates every 10ms, targeting ~100 FPS update rate:
main.py:176
lblVideo.after(10, Scanning)
If experiencing performance issues, increase the delay value (e.g., 20ms for ~50 FPS).

Video Resizing

Video is resized to 640px width for efficient display:
main.py:167
frame_show = imutils.resize(frame_show, width=640)
Original capture resolution (1280x720) is used for detection, ensuring accuracy.

Troubleshooting

If you get file not found errors:
  1. Create the setUp directory in your source folder
  2. Add all required background and icon images
  3. Ensure image filenames match exactly (case-sensitive)
mkdir setUp
# Add your image files to setUp/
If the GUI freezes:
  1. Check camera connection
  2. Verify model file exists at Modelos/best.pt
  3. Ensure no other application is using the camera
  4. Try reducing detection frequency by increasing the delay in line 176
Verify:
  1. All image files exist in setUp/ directory
  2. Images are readable (not corrupted)
  3. File permissions allow reading
ls -l setUp/*.png
If cv2.CAP_DSHOW causes issues:
main.py:219
# Try without DirectShow flag
cap = cv2.VideoCapture(0)
The GUI performs color space conversions between BGR and RGB:
  • Camera input: BGR (OpenCV default)
  • Display output: RGB (Tkinter/PIL requirement)
If colors appear inverted, verify conversion at line 54:
frame_show = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

Closing the Application

To exit the GUI:
  1. Click the window close button (X)
  2. Camera will be released automatically
  3. All resources cleaned up via cap.release()

Next Steps

Camera Configuration

Learn how to optimize camera settings for better detection

CLI Detection

Use the lightweight command-line interface

Build docs developers (and LLMs) love