""" Abhängigkeiten: - tkinter (Tkinter-Bibliothek) - recording (Modul für die Videoaufnahme) - processing (Modul für die Videoverarbeitung) - tkinter.filedialog (Dateiauswahldialog) - os Autor: Roberto Gelsinger Datum: 07.12.2023 Version: Modulversion """ import tkinter as tk from recording import start_recording, recording_finished_event from recording import start_recording,start_normal_recording,stop_normal_recording from processing import process_video from tkinter import filedialog from tkinter import simpledialog import os from PIL import ImageTk, Image import pandas as pd from excel_processing import process_all_videos_and_save_results from datetime import datetime recording_finished = False code_version= "1.0" current_dir = os.getcwd() testcase_excel_file_path = os.path.join(current_dir, 'code/testing/excel/Testcase_excel_dataset.xlsx') testruns_excel_file_path = os.path.join(current_dir, 'code/testing/excel/Testruns.xlsx') class VideoProcessingApp(tk.Tk): def __init__(self): super().__init__() self.title("Driving Simulator EVM") self.geometry('530x380') #self.resizable(False, False) self.frames = {} #init user interface() self.initialize_header_frame() self.initialize_toolbar() self.initialize_icon() self.setup_recording_controls() self.setup_testcase_controls() self.setup_testing_controls() self.setup_video_processing_controls() self.center_window() self.selected_button = None self.check_recording_status() self.mainloop() def open_testcase_excel_file(self): os.startfile(testcase_excel_file_path) def open_testrun_excel_file(self): os.startfile(testruns_excel_file_path) def test_data_set(self): kommentar = self.testrun_kommentar_entry.get("1.0", "end-1c") process_all_videos_and_save_results(testcase_excel_file_path,testruns_excel_file_path,code_version,kommentar) def start_normal_recording_with_input(self): """ Startet die Videoaufnahme mit dem eingegebenen Videonamen. Der Name wird aus dem Tkinter Entry-Widget gelesen. """ video_name = self.video_name_entry.get() # Holt den Text aus dem Textfeld video_resolution1 = int(self.aufnahme_aufloesung1_entry.get()) video_resolution2 = int(self.aufnahme_aufloesung2_entry.get()) fps = int(self.aufnahme_fps_entry.get()) start_normal_recording(video_name,video_resolution1,video_resolution2,fps) def write_to_excel(self, video_name, excel_path): # Datenerfassung date = datetime.now().strftime("%Y-%m-%d") time = datetime.now().strftime("%H:%M:%S") licht = self.testcase_licht_entry.get() webcam_name = self.testcase_kamera_entry.get() testperson_name = self.testcase_testperson_entry.get() abstand = int(self.testcase_abstand_entry.get()) winkel = self.testcase_winkel_entry.get() hintergrund = self.testcase_hintergrund_entry.get() video_length = int(self.video_length_entry.get()) auflösung = f"{int(self.testcase_resolution1_entry.get())}x{int(self.testcase_resolution2_entry.get())}" fps = int(self.testcase_fps_entry.get()) kommentar = self.testcase_kommentar_entry.get("1.0", "end-1c") # Entferne die Dateiendung (z.B. '.avi') und extrahiere dann den Puls video_name_without_extension = video_name.split('.')[0] puls_part = video_name_without_extension.split('_')[-1] try: puls = int(puls_part) except ValueError: puls = '' # Setze Puls auf einen leeren String, falls keine gültige Zahl gefunden wird # Versuche, die vorhandene Datei zu lesen, erstelle eine neue, wenn sie nicht existiert try: existing_df = pd.read_excel(excel_path) except FileNotFoundError: existing_df = pd.DataFrame(columns=['Testcase','Date', 'Time', 'VideoName', 'CodeVersion', 'Testperson', 'Abstand', 'Videolänge', 'Webcam', 'Auflösung', 'FPS', 'Winkel', 'Hintergrund', 'Licht', 'Puls', 'Kommentar']) # Neue Datenreihe erstellen next_testcase_index = len(existing_df) + 1 new_data = pd.DataFrame({'Testcase': [next_testcase_index],'Date': [date], 'Time': [time], 'VideoName': [video_name], 'CodeVersion': [code_version], 'Testperson': [testperson_name], 'Abstand': [abstand], 'Videolänge': [video_length], 'Webcam': [webcam_name], 'Auflösung': [auflösung], 'FPS': [fps], 'Winkel': [winkel], 'Hintergrund': [hintergrund], 'Licht': [licht], 'Puls': [puls], 'Kommentar': [kommentar]}) # Daten zur existierenden DataFrame hinzufügen updated_df = existing_df._append(new_data, ignore_index=True) # DataFrame in Excel schreiben if not existing_df.empty: # Modus 'a' (Anhängen) verwenden, wenn die DataFrame nicht leer ist with pd.ExcelWriter(excel_path, engine='openpyxl', mode='a', if_sheet_exists='replace') as writer: updated_df.to_excel(writer, index=False, sheet_name='Sheet1') else: # Modus 'w' (Schreiben) verwenden, wenn die DataFrame leer ist oder die Datei nicht existiert with pd.ExcelWriter(excel_path, engine='openpyxl', mode='w') as writer: updated_df.to_excel(writer, index=False, sheet_name='Sheet1') def start_recording_with_input(self): """ Startet die Videoaufnahme mit dem eingegebenen Videonamen. Der Name wird aus dem Tkinter Entry-Widget gelesen. """ video_name = self.testcase_name_entry.get() video_length = int(self.video_length_entry.get()) # Hole die Länge des Videos testcase_resolution1 = int(self.testcase_resolution1_entry.get()) testcase_resolution2 = int(self.testcase_resolution2_entry.get()) testcase_fps=int(self.testcase_fps_entry.get()) start_recording(video_name, video_length,testcase_resolution1,testcase_resolution2,testcase_fps) def select_video(self): """ Öffnet einen Dateidialog zum Auswählen eines Videos und setzt den Namen des ausgewählten Videos in das Tkinter Entry-Widget für die Videoverarbeitung. """ selected_video_path = filedialog.askopenfilename() # Den ausgewählten Videopfad abfragen if selected_video_path: selected_video_name = os.path.basename(selected_video_path) # Extrahieren Sie den Videonamen self.videoprocessing_name_entry.delete(0, tk.END) # Löschen Sie den aktuellen Text im Textfeld self.videoprocessing_name_entry.insert(0, selected_video_name) # Fügen Sie den Videonamen ein def process_selected_video(self): """ Verarbeitet das ausgewählte Video, dessen Name aus dem Tkinter Entry-Widget gelesen wird. """ selected_video_name = self.videoprocessing_name_entry.get() # Den ausgewählten Videonamen abfragen if selected_video_name: process_video(selected_video_name) def check_recording_status(self): excel_file_path = 'code/testing/excel/Testcase_excel_dataset.xlsx' global recording_finished if recording_finished_event.is_set(): recording_finished_event.clear() video_name = self.testcase_name_entry.get() length = int(self.video_length_entry.get()) pulse = simpledialog.askinteger("Puls", "Bitte geben Sie Ihren Puls ein:") if pulse is not None: new_video_name = f"{video_name}_{length}_{pulse}.avi" original_video_path = os.path.join('code', 'videos', f"{video_name}.avi") new_video_path = os.path.join('code', 'videos', new_video_name) if not os.path.exists(original_video_path): print(f"Datei nicht gefunden: {original_video_path}") return try: os.rename(original_video_path, new_video_path) print(f"Video umbenannt zu {new_video_name}") self.write_to_excel(new_video_name, excel_file_path) except Exception as e: print(f"Fehler beim Umbenennen der Datei: {e}") else: print("Kein Puls eingegeben.") self.after(100, self.check_recording_status) #ui relateted methods def center_window(self): # Aktualisieren der "idle" Aufgaben um die Größe korrekt zu erhalten self.update_idletasks() # Berechnen der Breite und Höhe für das Zentrieren des Fensters window_width = self.winfo_width() window_height = self.winfo_height() # Finden der Mitte des Bildschirms screen_width = self.winfo_screenwidth() screen_height = self.winfo_screenheight() # Berechnen der x und y Koordinaten, um das Fenster in der Mitte des Bildschirms zu positionieren x_coordinate = int((screen_width / 2) - (window_width / 2)) y_coordinate = int((screen_height / 2) - (window_height / 2)) self.geometry(f"{window_width}x{window_height}+{x_coordinate}+{y_coordinate}") #displaying selected frame def show_frame(self, frame_name): # Verstecke alle Frames und setze die Button-Farben zurück Create Testcase for name, fr in self.frames.items(): fr.pack_forget() if name == "Recording": self.btn_recording.configure(bg='white',fg='black', relief=tk.RAISED) elif name == "Processing": self.btn_processing.configure(bg='white',fg='black', relief=tk.RAISED) elif name == "Testing": self.btn_testing.configure(bg='white',fg='black', relief=tk.RAISED) elif name == "Create Testcase": self.btn_testcase.configure(bg='white',fg='black', relief=tk.RAISED) # Zeige den ausgewählten Frame frame = self.frames[frame_name] frame.pack(fill="both", expand=True) # Hebe den entsprechenden Button hervor if frame_name == "Recording": self.btn_recording.configure(bg='#c82423',fg='white', relief=tk.SUNKEN) elif frame_name == "Processing": self.btn_processing.configure(bg='#c82423',fg='white', relief=tk.SUNKEN) elif frame_name == "Testing": self.btn_testing.configure(bg='#c82423',fg='white', relief=tk.SUNKEN) elif frame_name == "Create Testcase": self.btn_testcase.configure(bg='#c82423',fg='white', relief=tk.SUNKEN) def initialize_header_frame(self): # Header-Frame für App-Name und Icon header_frame = tk.Frame(self, bd=1, relief=tk.RAISED, bg='white') header_frame.pack(side=tk.TOP, fill=tk.X) # App-Name Label self.app_name_label = tk.Label(header_frame, text="Driving Simulator-EVM", font=('Helvetica', 28, 'bold'), bg='white', fg='red') self.app_name_label.pack(side=tk.LEFT, padx=10) self.app_name_label.config(fg="#c82423", bg="#FFFFFF") # Laden Sie das Bild mit PIL und konvertieren Sie es in ein Format, das Tkinter verwenden kann self.image = Image.open(r"code\interface\ohmbild2.png") self.resized_image = self.image.resize((50, 30), Image.LANCZOS) self.photo = ImageTk.PhotoImage(self.resized_image) # Erstellen Sie ein Label-Widget, um das Bild anzuzeigen self.picture = tk.Label(self, image=self.photo) self.picture.place(x=445, y=0) self.picture.config(bg="#FFFFFF") def initialize_toolbar(self): toolbar = tk.Frame(self, bd=1, relief=tk.RAISED, bg='white') toolbar.pack(side=tk.TOP, fill=tk.X) self.btn_recording = tk.Button(toolbar, text="Recording", bg='white', command=lambda: self.show_frame("Recording")) self.btn_recording.pack(side=tk.LEFT, padx=2, pady=2) self.btn_processing = tk.Button(toolbar, text="Processing", bg='white', command=lambda: self.show_frame("Processing")) self.btn_processing.pack(side=tk.LEFT, padx=2, pady=2) self.btn_testcase = tk.Button(toolbar, text="Create Testcase", bg='white', command=lambda: self.show_frame("Create Testcase")) self.btn_testcase.pack(side=tk.LEFT, padx=3, pady=3) self.btn_testing = tk.Button(toolbar, text="Testing", bg='white', command=lambda: self.show_frame("Testing")) self.btn_testing.pack(side=tk.LEFT, padx=3, pady=3) def setup_recording_controls(self): self.recording_frame = tk.Frame(self) self.recording_frame.configure(bg='white') self.frames["Recording"] = self.recording_frame # mainlabel for recording self.recording_main_label = tk.Label(self.recording_frame, text="Recording", font=("Helvetica", 20)) self.recording_main_label.place(x=25, y=10) self.recording_main_label.config(bg="#FFFFFF") self.video_name_entry_label = tk.Label(self.recording_frame, text="Videoname(Output)", font=("Helvetica", 10)) self.video_name_entry_label.place(x=25, y=60) self.video_name_entry_label.config(bg="#FFFFFF") self.video_name_entry = tk.Entry(self.recording_frame) self.video_name_entry.place(x=25, y=85) self.video_name_entry.config(bg="#FFFFFF") self.aufnahme_entry_label = tk.Label(self.recording_frame, text="Auflösung,FPS", font=("Helvetica", 10)) self.aufnahme_entry_label.place(x=25, y=110) self.aufnahme_entry_label.config(bg="#FFFFFF") self.aufnahme_aufloesung1_entry = tk.Entry(self.recording_frame) self.aufnahme_aufloesung1_entry.place(x=25, y=140) self.aufnahme_aufloesung1_entry.config(bg="#FFFFFF", width=5) self.aufnahme_aufloesung1_entry.insert(0, 2560) self.aufnahme_aufloesung_x_entry_label = tk.Label(self.recording_frame, text="x", font=("Helvetica", 8)) self.aufnahme_aufloesung_x_entry_label.place(x=60, y=140) self.aufnahme_aufloesung_x_entry_label.config(bg="#FFFFFF") self.aufnahme_aufloesung2_entry = tk.Entry(self.recording_frame) self.aufnahme_aufloesung2_entry.place(x=72, y=140) self.aufnahme_aufloesung2_entry.config(bg="#FFFFFF", width=5) self.aufnahme_aufloesung2_entry.insert(0, 1440) self.aufnahme_aufloesung_komma_entry_label = tk.Label(self.recording_frame, text=",", font=("Helvetica", 8)) self.aufnahme_aufloesung_komma_entry_label.place(x=105, y=140) self.aufnahme_aufloesung_komma_entry_label.config(bg="#FFFFFF") self.aufnahme_fps_entry = tk.Entry(self.recording_frame) self.aufnahme_fps_entry.place(x=115, y=140) self.aufnahme_fps_entry.config(bg="#FFFFFF", width=4) self.aufnahme_fps_entry.insert(0, 20) # Buttons self.start_button = tk.Button(self.recording_frame, text="Aufnahme starten", command=self.start_normal_recording_with_input) self.start_button.place(x=25, y=175) self.start_button.config(bg="#c82423", fg="#FFFFFF") self.stop_button = tk.Button(self.recording_frame, text="Aufnahme stoppen", command=stop_normal_recording) self.stop_button.place(x=25, y=210) self.stop_button.config(bg="#c82423", fg="#FFFFFF") def setup_video_processing_controls(self): self.processing_frame = tk.Frame(self) self.processing_frame.configure(bg='white') self.frames["Processing"] = self.processing_frame # mainlabel for processing self.processing_main_label = tk.Label(self.processing_frame, text="Processing", font=("Helvetica", 20)) self.processing_main_label.place(x=10, y=10) self.processing_main_label.config(bg="#FFFFFF") self.videoprocessing_name_entry_label = tk.Label(self.processing_frame, text="Videoname(Loaded)", font=("Helvetica", 10)) self.videoprocessing_name_entry_label.place(x=10, y=60) self.videoprocessing_name_entry_label.config(bg="#FFFFFF") self.videoprocessing_name_entry = tk.Entry(self.processing_frame) self.videoprocessing_name_entry.place(x=10, y=85) self.videoprocessing_name_entry.config(bg="#FFFFFF") # Button to select video for processing self.select_video_button = tk.Button(self.processing_frame, text="Video auswählen", command=self.select_video) self.select_video_button.place(x=10, y=120) self.select_video_button.config(bg="#c82423", fg="#FFFFFF") # Button to start processing self.processing_button = tk.Button(self.processing_frame, text="Verarbeiten", command=self.process_selected_video) self.processing_button.place(x=10, y=160) self.processing_button.config(bg="#c82423", fg="#FFFFFF") def setup_testcase_controls(self): self.testcase_frame = tk.Frame(self, bg='white') self.frames["Create Testcase"] = self.testcase_frame # mainlabel for Recording(Testcase) self.recording_testcase_label = tk.Label(self.testcase_frame, text="Record Testcase", font=("Helvetica", 20)) self.recording_testcase_label.place(x=10, y=10) self.recording_testcase_label.config(bg="#FFFFFF") #kommentar self.testcase_kommentar_entry_label = tk.Label(self.testcase_frame, text="Kommentar", font=("Helvetica", 10)) self.testcase_kommentar_entry_label.place(x=320, y=60) self.testcase_kommentar_entry_label.config(bg="#FFFFFF") self.testcase_kommentar_entry = tk.Text(self.testcase_frame, height=4.5, width=20) self.testcase_kommentar_entry.place(x=320, y=85) self.testcase_kommentar_entry.config(bg="#FFFFFF") #code version self.testcase_version_entry_label = tk.Label(self.testcase_frame, text="Version: "+code_version, font=("Helvetica", 10)) self.testcase_version_entry_label.place(x=240, y=20) self.testcase_version_entry_label.config(bg="#FFFFFF") #licht self.testcase_licht_entry_label = tk.Label(self.testcase_frame, text="Licht", font=("Helvetica", 10)) self.testcase_licht_entry_label.place(x=10, y=180) self.testcase_licht_entry_label.config(bg="#FFFFFF") self.testcase_licht_entry = tk.Entry(self.testcase_frame) self.testcase_licht_entry.place(x=10, y=205) self.testcase_licht_entry.config(bg="#FFFFFF") #kamera self.testcase_kamera_entry_label = tk.Label(self.testcase_frame, text="Webcam(Name)", font=("Helvetica", 10)) self.testcase_kamera_entry_label.place(x=10, y=240) self.testcase_kamera_entry_label.config(bg="#FFFFFF") self.testcase_kamera_entry = tk.Entry(self.testcase_frame) self.testcase_kamera_entry.place(x=10, y=265) self.testcase_kamera_entry.config(bg="#FFFFFF") #testperson self.testcase_testperson_entry_label = tk.Label(self.testcase_frame, text="Testperson(Name)", font=("Helvetica", 10)) self.testcase_testperson_entry_label.place(x=160, y=60) self.testcase_testperson_entry_label.config(bg="#FFFFFF") self.testcase_testperson_entry = tk.Entry(self.testcase_frame) self.testcase_testperson_entry.place(x=160, y=85) self.testcase_testperson_entry.config(bg="#FFFFFF") #abstand self.testcase_abstand_entry_label = tk.Label(self.testcase_frame, text="Abstand zur Kamera", font=("Helvetica", 10)) self.testcase_abstand_entry_label.place(x=160, y=120) self.testcase_abstand_entry_label.config(bg="#FFFFFF") self.testcase_abstand_entry = tk.Entry(self.testcase_frame) self.testcase_abstand_entry.place(x=160, y=145) self.testcase_abstand_entry.config(bg="#FFFFFF") #Winkel self.testcase_winkel_entry_label = tk.Label(self.testcase_frame, text="Kamerawinkel", font=("Helvetica", 10)) self.testcase_winkel_entry_label.place(x=160, y=180) self.testcase_winkel_entry_label.config(bg="#FFFFFF") self.testcase_winkel_entry = tk.Entry(self.testcase_frame) self.testcase_winkel_entry.place(x=160, y=205) self.testcase_winkel_entry.config(bg="#FFFFFF") #Hintergrund self.testcase_hintergrund_entry_label = tk.Label(self.testcase_frame, text="Hintergrund", font=("Helvetica", 10)) self.testcase_hintergrund_entry_label.place(x=160, y=240) self.testcase_hintergrund_entry_label.config(bg="#FFFFFF") self.testcase_hintergrund_entry = tk.Entry(self.testcase_frame) self.testcase_hintergrund_entry.place(x=160, y=265) self.testcase_hintergrund_entry.config(bg="#FFFFFF") #videoname self.testcase_name_entry_label = tk.Label(self.testcase_frame, text="Videoname(Output)", font=("Helvetica", 10)) self.testcase_name_entry_label.place(x=10, y=60) self.testcase_name_entry_label.config(bg="#FFFFFF") self.testcase_name_entry = tk.Entry(self.testcase_frame) self.testcase_name_entry.place(x=10, y=85) self.testcase_name_entry.config(bg="#FFFFFF") #videolänge self.video_length_entry_label = tk.Label(self.testcase_frame, text="Videolänge (Sek.)", font=("Helvetica", 10)) self.video_length_entry_label.place(x=10, y=120) self.video_length_entry_label.config(bg="#FFFFFF") self.video_length_entry = tk.Entry(self.testcase_frame) self.video_length_entry.place(x=10, y=145) self.video_length_entry.config(bg="#FFFFFF") #auflösung und fps self.testcase_resolution_label = tk.Label(self.testcase_frame, text="Auflösung,FPS", font=("Helvetica", 10)) self.testcase_resolution_label.place(x=320, y=180) self.testcase_resolution_label.config(bg="#FFFFFF") self.testcase_resolution1_entry = tk.Entry(self.testcase_frame) self.testcase_resolution1_entry.place(x=320, y=205) self.testcase_resolution1_entry.config(bg="#FFFFFF", width=5) self.testcase_resolution1_entry.insert(0, 2560) self.resolution_x_label = tk.Label(self.testcase_frame, text="x", font=("Helvetica", 8)) self.resolution_x_label.place(x=365, y=205) self.resolution_x_label.config(bg="#FFFFFF") self.testcase_resolution2_entry = tk.Entry(self.testcase_frame) self.testcase_resolution2_entry.place(x=377, y=205) self.testcase_resolution2_entry.config(bg="#FFFFFF", width=5) self.testcase_resolution2_entry.insert(0, 1440) self.resolution_comma_label = tk.Label(self.testcase_frame, text=",", font=("Helvetica", 8)) self.resolution_comma_label.place(x=410, y=205) self.resolution_comma_label.config(bg="#FFFFFF") self.testcase_fps_entry = tk.Entry(self.testcase_frame) self.testcase_fps_entry.place(x=420, y=205) self.testcase_fps_entry.config(bg="#FFFFFF", width=4) self.testcase_fps_entry.insert(0, 20) # Button to start testcase recording self.create_testcase_button = tk.Button(self.testcase_frame, text="Testcase aufnehmen", command=self.start_recording_with_input) self.create_testcase_button.place(x=320, y=240) self.create_testcase_button.config(bg="#c82423", fg="#FFFFFF") def setup_testing_controls(self): self.testing_frame = tk.Frame(self, bg='white') self.frames["Testing"] = self.testing_frame #kommentar self.testrun_kommentar_entry_label = tk.Label(self.testing_frame, text="Kommentar", font=("Helvetica", 10)) self.testrun_kommentar_entry_label.place(x=10, y=60) self.testrun_kommentar_entry_label.config(bg="#FFFFFF") self.testrun_kommentar_entry = tk.Text(self.testing_frame, height=4.5, width=20) self.testrun_kommentar_entry.place(x=10, y=85) self.testrun_kommentar_entry.config(bg="#FFFFFF") # mainlabel for testing self.testing_main_label = tk.Label(self.testing_frame, text="Testing", font=("Helvetica", 20)) self.testing_main_label.place(x=10, y=10) self.testing_main_label.config(bg="#FFFFFF") # Button to start test self.test_button = tk.Button(self.testing_frame, text="Test durchführen", command=self.test_data_set) self.test_button.place(x=350, y=60) self.test_button.config(bg="#c82423", fg="#FFFFFF") # Button open testcase excel self.open_testcase_button = tk.Button(self.testing_frame, text="Open Testcase Excel", command=self.open_testcase_excel_file) self.open_testcase_button.place(x=10, y=180) self.open_testcase_button.config(bg="#c82423", fg="#FFFFFF") # Button open testrun excel self.open_testrun_button = tk.Button(self.testing_frame, text="Open Testrun Excel", command=self.open_testrun_excel_file) self.open_testrun_button.place(x=10, y=215) self.open_testrun_button.config(bg="#c82423", fg="#FFFFFF") # Button open sorted excel self.open_testrun_button = tk.Button(self.testing_frame, text="Open Evaluation Excel", command=self.open_testrun_excel_file) self.open_testrun_button.place(x=10, y=250) self.open_testrun_button.config(bg="#c82423", fg="#FFFFFF") def initialize_icon(self): # Icon ändern self.iconbitmap(r'code\interface\ohm.ico') # Ändert die Hintergrundfarbe self.configure(bg="#FFFFFF") def main(): app = VideoProcessingApp() app.mainloop() if __name__ == "__main__": main()