Browse Source

Dateien hochladen nach „“

Habe nochmal Dateipfade anpassen müssen, jetzt läuft alles final
master
Jonathan Frei 9 months ago
parent
commit
c65c015b64
5 changed files with 412 additions and 0 deletions
  1. 15
    0
      constants.py
  2. 52
    0
      eulerian.py
  3. 151
    0
      excel_evaluation.py
  4. 138
    0
      excel_processing.py
  5. 56
    0
      excel_update.py

+ 15
- 0
constants.py View File

@@ -0,0 +1,15 @@
"""
Parameter:
-minimale und maximale Frequenz
-Alpha-Wert


Autor: Roberto Gelsinger
Datum: 07.12.2023
Version: Modulversion
"""


freq_min = 1 # Minimale Frequenzgrenze
freq_max = 3 # Maximale Frequenzgrenze
alpha = 100 # Alpha-Wert für die Analyse

+ 52
- 0
eulerian.py View File

@@ -0,0 +1,52 @@
"""
Abhängigkeiten:
- numpy
- scipy.signal (butter, lfilter)
- constants (für die Verwendung von 'alpha')

Autor: Roberto Gelsinger
Datum: 07.12.2023
Version: Modulversion
"""

import numpy as np
from scipy.signal import butter, lfilter
from constants import alpha

def fft_filter(video, freq_min, freq_max, fps):
"""
Diese Funktion nimmt Videodaten, eine Frequenzbandbreite und die Bildrate (FPS) des Videos entgegen.
Sie filtert das Video, um nur Frequenzen im angegebenen Band zu verstärken. Das verstärkte Video, die FFT-Daten
und die Frequenzen werden zurückgegeben.

Args:
video (ndarray): Die Videodaten als ndarray.
freq_min (float): Die untere Grenzfrequenz des zu verstärkenden Frequenzbands.
freq_max (float): Die obere Grenzfrequenz des zu verstärkenden Frequenzbands.
fps (int): Die Bildrate (Frames pro Sekunde) des Videos.

Returns:
tuple: Ein Tupel, bestehend aus:
- amplified_video (ndarray): Das verstärkte Videodaten als ndarray.
- fft (ndarray): Die FFT-Daten des verstärkten Videos.
- frequencies (ndarray): Die zugehörigen Frequenzen der FFT.
"""
nyquist = 0.5 * fps
low = freq_min / nyquist
high = freq_max / nyquist
# Min-Max-Frequenzen filtern
b, a = butter(4, [low, high], btype='band')

filtered_video = np.zeros_like(video)
for i in range(video.shape[2]):
filtered_video[:, :, i] = lfilter(b, a, video[:, :, i])

# Verstärkung
amplified_video = np.abs(filtered_video) * alpha

fft = np.fft.fft(amplified_video, axis=0)
frequencies = np.fft.fftfreq(amplified_video.shape[0], d=1.0 / fps)

return amplified_video, fft, frequencies

+ 151
- 0
excel_evaluation.py View File

@@ -0,0 +1,151 @@
import openpyxl
def excel_row_to_string(file_path):
# Öffne die Excel-Datei
workbook = openpyxl.load_workbook(file_path)
# Wähle das Arbeitsblatt aus
sheet = workbook['Sheet1']
# Erhalte die angegebene Zeile als Liste von Zellen
row_values = [cell.value for cell in sheet[2]]
# Ergebnisse werden ab Spalte 5 eingetragen
selected_columns = list(range(4, len(row_values)))
# Wähle nur die gewünschten Spalten aus
selected_values = [row_values[col] for col in selected_columns]
# Schließe die Excel-Datei
workbook.close()
# Konvertiere die Liste von Zellen in einen String
row_string = ', '.join(str(value) for value in selected_values)
return row_string
def write_subdivided_string_to_excel(file_path, input_string):
# Öffne die Excel-Datei
workbook = openpyxl.load_workbook(file_path)
# Wähle das Arbeitsblatt aus
sheet = workbook['Sheet1']
# Teile den String nach jedem Komma auf
parts = input_string.split(',')
# Trage jeden Teil des Strings in eine neue Zeile ein
for i, part in enumerate(parts, 1):
#Spalte 17 kann sich je nach Tabellenstruktur ändern!
sheet.cell(row=2 + i - 1, column=17, value=part.strip()) # strip entfernt mögliche Leerzeichen
# Speichere die Änderungen
workbook.save(file_path)
# Schließe die Excel-Datei
workbook.close()
def read_columns(file_path):
# Öffne die Excel-Datei
workbook = openpyxl.load_workbook(file_path)
# Wähle das Arbeitsblatt aus
sheet = workbook['Sheet1']
# Lese die Werte der beiden Spalten aus
values_column1 = [cell.value for cell in sheet['O']][1:]
values_column2 = [cell.value for cell in sheet['Q']][1:]
# Schließe die Excel-Datei
workbook.close()
return values_column1, values_column2
def calculate_deviation(liste1, liste2):
# Überprüfe, ob die Listen die gleiche Länge haben
if len(liste1) != len(liste2):
raise ValueError("Die Listen müssen die gleiche Länge haben")
# Berechne die prozentuale Abweichung zwischen den Werten
deviations = [((abs(float(b) - float(a)) / float(a)) * 100) if float(a) != 0 else None for a, b in zip(liste1, liste2)]
return deviations
def write_string_to_excel(file_path, input_string, column):
# Öffne die Excel-Datei
workbook = openpyxl.load_workbook(file_path)
# Wähle das Arbeitsblatt aus
sheet = workbook['Sheet1']
# Trage jeden Buchstaben des Strings in eine eigene Zeile ein
for i, char in enumerate(input_string, 1):
sheet.cell(row=2 + i - 1, column=column, value=char)
# Speichere die Änderungen
workbook.save(file_path)
# Schließe die Excel-Datei
workbook.close()
def copy_header(input_sheet, output_sheet):
# Kopiere den Header manuell in das Ausgabe-Arbeitsblatt
for row in input_sheet.iter_rows(min_row=1, max_row=1, values_only=True):
output_sheet.append(row)
def sort_excel(input_file_path, output_file_path, ):
# Öffne die Eingabe-Excel-Datei
input_workbook = openpyxl.load_workbook(input_file_path)
input_sheet = input_workbook['Sheet1']
# Erstelle eine neue Excel-Tabelle für die sortierten Zeilen
output_workbook = openpyxl.Workbook()
output_sheet = output_workbook.active
# Kopiere den Header ins Ausgabe-Arbeitsblatt
copy_header(input_sheet, output_sheet)
# Lese die Daten-Zeilen aus der Tabelle
data_rows = list(input_sheet.iter_rows(min_row=2, values_only=True))
# Sortiere die Daten-Zeilen nach dem Wert der angegebenen Spalte
sorted_data_rows = sorted(data_rows, key=lambda x: x[18 - 1]) # -1, da Listenindizes bei 0 beginnen
# Schreibe die sortierten Daten-Zeilen in die neue Tabelle
for row in sorted_data_rows:
output_sheet.append(row)
# Speichere die Änderungen in der neuen Excel-Datei
output_workbook.save(output_file_path)
# Schließe die Excel-Dateien
input_workbook.close()
output_workbook.close()
#Sollten mehrere Testruns ausgewertet werden wollen, müssen die enthaltenen Funktionen umstrukturiert werden
#Aktuell wird nur der Testrun in Zeile 1 ausgewertet
#Eine Weitere Funktion, die zwei Tabellenzeilen tauscht, wäre der einfachste workaround
def evaluation(testcases, testruns):
#liest die Ergebnisse des Testruns aus
#bei mehreren Testruns muss diese Funktion angepasst werden!
input_string = excel_row_to_string(testruns)
#schreibt die Berechneten Ergebnisse in die Testcases-Tabelle
write_subdivided_string_to_excel(testcases, input_string)
#liest die gemessenen und die errechneten Werte aus den Testcases
values_col1, values_col2 = read_columns(testcases)
#berechnet aus diesen Werten die prozentuale Abweichung
deviations = calculate_deviation(values_col1, values_col2)
#Trägt die prozentualen Abweichungen in die Testcases-Tabelle
#je nach Tabellenstruktur kann sich die 18 ändern!
write_string_to_excel(testcases, deviations, 18)
#Gibt die eine Kopie der Testcases-Tabelle sortiert nach Genauigkeit aus
sort_excel(testcases, 'Testcases_nach_Genauigkeit.xlsx')

+ 138
- 0
excel_processing.py View File

@@ -0,0 +1,138 @@
"""
Abhängigkeiten:
- pyramids (für den Aufbau der Bildpyramiden)
- heartrate (zur Berechnung der Herzfrequenz)
- preprocessing (für die Video-Vorverarbeitung)
- eulerian (für die Euler'sche Video-Magnifikation)
- tkinter und constants (für die GUI und Konstantenverwaltung)
Autor: Roberto Gelsinger
Datum: 07.12.2023
Version: Modulversion
"""
import pyramids
import heartrate
import facedetection
import eulerian
from constants import freq_max, freq_min
import pandas as pd
from excel_update import color_cells_based_on_deviation
from excel_evaluation import evaluation
def process_video_for_excel(selected_video_name):
"""
Verarbeitet ein ausgewähltes Video, um die Herzfrequenz der abgebildeten Person zu ermitteln.
Dieser Prozess umfasst die Vorverarbeitung des Videos, den Aufbau einer Laplace-Pyramide,
die Anwendung von FFT-Filterung und Euler'scher Magnifikation, und schließlich die Berechnung
der Herzfrequenz aus den Video-Daten.
Args:
selected_video_name (str): Der Name des zu verarbeitenden Videos.
Returns:
None: Die Funktion gibt direkt die berechnete Herzfrequenz auf der Konsole aus.
"""
print("Reading + preprocessing video...")
video_frames, frame_ct, fps = facedetection.read_video("code/videos/"+selected_video_name)
print("Building Laplacian video pyramid...")
lap_video = pyramids.build_video_pyramid(video_frames)
print(len(lap_video))
for i, video in enumerate(lap_video):
print("test")
if i == 0 or i == len(lap_video)-1:
continue
print("Running FFT and Eulerian magnification...")
result, fft, frequencies = eulerian.fft_filter(video, freq_min, freq_max, fps)
lap_video[i] += result
print("Calculating heart rate...")
heart_rate = heartrate.find_heart_rate(fft, frequencies, freq_min, freq_max)
print("Heart rate: ", heart_rate*0.7, "bpm")
return heart_rate *0.7
def process_all_videos_and_save_results(testcase_excel_file_path, testruns_excel_file_path, code_version, kommentar):
try:
df_testruns = pd.read_excel(testruns_excel_file_path)
except FileNotFoundError:
df_testruns = pd.DataFrame()
df_testcases = pd.read_excel(testcase_excel_file_path)
existing_testcases = [col for col in df_testruns.columns if col.startswith('Testcase_')]
new_testcases = [f'Testcase_{tc}' for tc in df_testcases['Testcase'] if f'Testcase_{tc}' not in existing_testcases]
if df_testruns.empty:
df_testruns = pd.DataFrame(columns=['Testnummer', 'Codeversion', 'Kommentar', 'Abweichung'])
for col in new_testcases:
df_testruns[col] = None
df_testruns.to_excel(testruns_excel_file_path, index=False)
if new_testcases:
print(f"Folgende neue Testcases wurden hinzugefügt: {new_testcases}")
else:
print("Keine neuen Testcases zum Hinzufügen gefunden.")
next_testcase_index = len(df_testruns) + 1
new_run = {
'Testnummer': next_testcase_index,
'Codeversion': code_version,
'Kommentar': kommentar,
'Abweichung': 'Wert_für_Abweichung'
}
for index, row in df_testcases.iterrows():
video_name = row['VideoName']
heart_rate = process_video_for_excel(video_name)
testcase_column_name = f'Testcase_{row["Testcase"]}'
new_run[testcase_column_name] = heart_rate
try:
df_testruns = df_testruns._append(new_run, ignore_index=True)
except TypeError:
pass
df_testruns.to_excel(testruns_excel_file_path, index=False)
print("Testrun wurde verarbeitet und das Ergebnis in der Testruns-Excel-Datei gespeichert.")
color_cells_based_on_deviation(testruns_excel_file_path, testcase_excel_file_path)
print("Zellen gefärbt")
evaluation(testcase_excel_file_path, testruns_excel_file_path)
print("Testcases sortiert")

+ 56
- 0
excel_update.py View File

@@ -0,0 +1,56 @@
import openpyxl
from openpyxl.styles import PatternFill
import pandas as pd

def fill_cell(ws, cell, color):
fill = PatternFill(start_color=color, end_color=color, fill_type='solid')
cell.fill = fill

def calculate_and_fill_deviation(ws, row, absolute_deviations):
if absolute_deviations:
average_deviation = sum(absolute_deviations) / len(absolute_deviations)
deviation_cell = ws.cell(row=row[0].row, column=4) # Angenommen, die 'Abweichung'-Spalte ist Spalte D
deviation_cell.value = average_deviation
# Färbe die Zelle basierend auf der durchschnittlichen Abweichung
if average_deviation < 5:
fill_color = 'FF00FF00' # Grün
elif 5 <= average_deviation < 10:
fill_color = 'FFFFFF00' # Gelb
else:
fill_color = 'FFFF0000' # Rot
fill_cell(ws, deviation_cell, fill_color)

def color_cells_based_on_deviation(testruns_excel_file_path, testcases_excel_file_path):
wb_testruns = openpyxl.load_workbook(testruns_excel_file_path)
ws_testruns = wb_testruns.active
df_testcases = pd.read_excel(testcases_excel_file_path)

for row in ws_testruns.iter_rows(min_row=2, max_row=ws_testruns.max_row):
deviations = []
absolute_deviations = []

for cell in row[4:]:
header_cell_value = ws_testruns.cell(row=1, column=cell.column).value
if header_cell_value and "Testcase" in header_cell_value:
testcase_num = int(header_cell_value.split('_')[1])
expected_pulse_row = df_testcases[df_testcases['Testcase'] == testcase_num]
if not expected_pulse_row.empty:
expected_pulse = expected_pulse_row.iloc[0]['Puls']
actual_pulse = cell.value
if actual_pulse is not None and expected_pulse is not None:
relative_deviation = (actual_pulse - expected_pulse) / expected_pulse * 100
absolute_deviation = abs(relative_deviation)
deviations.append(relative_deviation)
absolute_deviations.append(absolute_deviation)

if absolute_deviation < 5:
fill_color = 'FF00FF00' # Grün
elif 5 <= absolute_deviation < 10:
fill_color = 'FFFFA500' if relative_deviation < 0 else 'FFFFFF00' # Orange für niedriger, Gelb für höher
else:
fill_color = 'FFC0CB' if relative_deviation < 0 else 'FFFF0000' # Rosa für niedriger, Rot für höher
fill_cell(ws_testruns, cell, fill_color)

calculate_and_fill_deviation(ws_testruns, row, absolute_deviations)

wb_testruns.save(testruns_excel_file_path)

Loading…
Cancel
Save