Compare commits
37 Commits
Intervalls
...
master
Author | SHA1 | Date | |
---|---|---|---|
368d686e21 | |||
d065c58ab2 | |||
fa23410c8d | |||
d79fd5e427 | |||
1c5afb9e45 | |||
6b0b8274ad | |||
5d5a9077a9 | |||
4b6f98fbec | |||
a0d57e4cd8 | |||
38475f3457 | |||
3154a5cd3c | |||
406505af6b | |||
5b76520bbb | |||
c4267cce7a | |||
15cf3cf5d9 | |||
6cfc8baac8 | |||
1340b94b0e | |||
f707b8474b | |||
55d66b05fe | |||
cf1c4ce07c | |||
40aa48c860 | |||
438240cc9a | |||
453fd4035d | |||
82dbafdf94 | |||
c65c015b64 | |||
343a52f170 | |||
0a0b013f84 | |||
6f811dd0ae | |||
aaf1b6add8 | |||
2dd385684c | |||
2dcf76ce67 | |||
3b465ce763 | |||
7f94258a99 | |||
b6c3ff5a42 | |||
db476fbce2 | |||
7c2c8f1b4d | |||
7704a34b1c |
20
README.md
20
README.md
@ -1,21 +1,19 @@
|
|||||||
# Driving Simulator Team Video
|
# Driving Simulator Team Video
|
||||||
|
|
||||||
## Projektbeschreibung
|
## Projektbeschreibung
|
||||||
ToDo
|
Dieser Code ermittelt die Herzfrequenz einer Person anhand eines aufgenommenen Videos von deren Gesicht auf Basis des Eulerian Video Magnification (EVM) Verfahrens. Desweiteren ist ein Interface enthalten, das neben der Steuerung des Programms auch einen Testing-Modus zulässt.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
|
||||||
## Verwendung
|
## Verwendung
|
||||||
Wenn ein fertiges feature in den Master Branch gemerged wird muss die code_version variable in der main.py inkrementiert werden. Für kleine features wird die nachkomma stelle inkrementiert, bei großen features wird die vorkomma stelle erhöht und die nachkomma stelle auf 0 gesetzt.
|
Wenn ein fertiges feature in den Master Branch gemerged wird muss die code_version variable in der main.py inkrementiert werden. Für kleine features wird die nachkomma stelle inkrementiert, bei großen features wird die vorkomma stelle erhöht und die nachkomma stelle auf 0 gesetzt.
|
||||||
ToDo
|
|
||||||
(ergänzen welche sachen nicht gepusht werden müssen)
|
## Bedienungsanleitung
|
||||||
|
**Recording**: Aufösung und fps der verwendeten Kamera müssen eingetragen werden, ebenso der gewünschte Videoname. Videos beliebiger Länge können über "Aufnahme starten/stoppen" aufgezeichnet werden.
|
||||||
|
**Processing**: Über das Textfenster oder den Button "Video auswählen" kann das auszuwertende Video gewählt werden. Der Button "Verarbeiten" startet die Pulsberechnung, deren Ergebnis im Terminal ausgegeben wird.
|
||||||
|
**Create Testcase**: Solange das Programm noch nicht final ist, ist es mit einem Testing-Modus ausgestattet. Die eizustellenden Parameter entsprechen möglichen Einflüssen auf die Berechnung und sollten im Entwicklungsverlauf entsprechend der Testergebnisse angepasst werden. Der Button "Testcase aufnehmen" startet die Aufnahme, die nach der zuvor eingetragenen Zeit stoppt. Das Video wird gespeichert und in der Testcases-Excel-Datei wird ein entsprechender neuer Antrag angelegt.
|
||||||
|
**Testing**: Die Buttons "Open Testcase/-run Excel" öffnen die jeweiligen Excel-Tabellen. Der Button "Test durchführen" startet die Auswertung aller in der Testcases-Excel-Datei aufgelisteten Videos und trägt die Ergebnisse in die Testrun-Excel-Datei ein. Anschließend wird eine nach Genauigkeit der Auswertung sortierte Kopie der Testcases-Excel-Datei erstellt.
|
||||||
|
|
||||||
## Beiträge
|
## Beiträge
|
||||||
ToDo
|
Siehe author_contribution.md
|
||||||
|
|
||||||
## Lizenz
|
|
||||||
ToDo
|
|
||||||
|
|
||||||
## Danksagungen
|
|
||||||
ToDo
|
|
57
Testauswertung/prozentuale_Abweichung.py
Normal file
57
Testauswertung/prozentuale_Abweichung.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import openpyxl
|
||||||
|
|
||||||
|
def lese_zwei_spalten(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 berechne_prozentuale_abweichung(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
|
||||||
|
abweichungen = [((abs(float(b) - float(a)) / float(a)) * 100) if float(a) != 0 else None for a, b in zip(liste1, liste2)]
|
||||||
|
|
||||||
|
return abweichungen
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
# Funktionsaufruf
|
||||||
|
|
||||||
|
values_col1, values_col2 = lese_zwei_spalten('Testcase_excel_dataset.xlsx')
|
||||||
|
|
||||||
|
print(values_col1)
|
||||||
|
print(values_col2)
|
||||||
|
|
||||||
|
abweichungen = berechne_prozentuale_abweichung(values_col1, values_col2)
|
||||||
|
|
||||||
|
write_string_to_excel('Testcase_excel_dataset.xlsx', abweichungen, 18)
|
||||||
|
|
42
Testauswertung/tabelle_umstrukturieren.py
Normal file
42
Testauswertung/tabelle_umstrukturieren.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import openpyxl
|
||||||
|
|
||||||
|
def kopiere_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 sortiere_excel_tabelle(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
|
||||||
|
kopiere_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()
|
||||||
|
|
||||||
|
|
||||||
|
# Beispielaufruf
|
||||||
|
input_file_path = 'Testcase_excel_dataset.xlsx'
|
||||||
|
output_file_path = 'Testcases_nach_Genauigkeit.xlsx'
|
||||||
|
|
||||||
|
sortiere_excel_tabelle(input_file_path, output_file_path)
|
52
Testauswertung/tabellen_zusammenfuehren.py
Normal file
52
Testauswertung/tabellen_zusammenfuehren.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
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_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):
|
||||||
|
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()
|
||||||
|
|
||||||
|
# Funktionsaufrufe
|
||||||
|
|
||||||
|
input_string = excel_row_to_string('Testruns.xlsx')
|
||||||
|
|
||||||
|
write_string_to_excel('Testcase_excel_dataset.xlsx', input_string)
|
||||||
|
|
@ -6,13 +6,16 @@
|
|||||||
- Contribution: Algorithm development, Python Code
|
- Contribution: Algorithm development, Python Code
|
||||||
- Email: gelsingerro81137@th-nuernberg.de
|
- Email: gelsingerro81137@th-nuernberg.de
|
||||||
|
|
||||||
|
### Jonathan Frei
|
||||||
|
- Contribution: Algorithm Development, Python Code, Testing
|
||||||
|
- Email: freijo85382@th-nuernberg.de
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
|
|
||||||
### Roberto Gelsinger
|
### Roberto Gelsinger
|
||||||
|
|
||||||
#### General Contributen
|
#### General Contributen
|
||||||
- **Creating README.md**
|
- **Creating README.md structure**
|
||||||
- **Creating requiremenents.txt**
|
- **Creating requiremenents.txt**
|
||||||
- **Creating author_contribution.md structure**
|
- **Creating author_contribution.md structure**
|
||||||
- **Added Docstrings to the code**
|
- **Added Docstrings to the code**
|
||||||
@ -64,6 +67,30 @@
|
|||||||
- **Create testcase sample for test automation**
|
- **Create testcase sample for test automation**
|
||||||
- **Testing and optimizing the code**
|
- **Testing and optimizing the code**
|
||||||
|
|
||||||
|
### Jonathan Frei
|
||||||
|
|
||||||
|
#### General Contribution
|
||||||
|
- **Creating README.md**
|
||||||
|
- **Algorithm Designs on previous versions**
|
||||||
|
|
||||||
|
#### Code Contribution
|
||||||
|
- **general**
|
||||||
|
- Edited other Authors' codes for bugfixing
|
||||||
|
|
||||||
|
- **prozentuale_Abweichung.py**
|
||||||
|
- Calculates percentual deviation between our calculated and the external measured value
|
||||||
|
- Adds the percentual deviation to the testcases excel sheet
|
||||||
|
|
||||||
|
- **tabellen_umstrukturieren.py**
|
||||||
|
- Sorts the rows of the testcases excel sheet by percentual deviation
|
||||||
|
|
||||||
|
- **tabellen_zusammenführen.py**
|
||||||
|
- Merges the testruns excel sheet into the testcases excel sheet
|
||||||
|
|
||||||
|
#### Testing Contribution
|
||||||
|
- **Designed testing environments**
|
||||||
|
- **Created various testcases**
|
||||||
|
- **Ran rest runs in multiple code versions for code optimization**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
151
code/excel_evaluation.py
Normal file
151
code/excel_evaluation.py
Normal 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')
|
||||||
|
|
@ -18,6 +18,7 @@ import eulerian
|
|||||||
from constants import freq_max, freq_min
|
from constants import freq_max, freq_min
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from excel_update import color_cells_based_on_deviation
|
from excel_update import color_cells_based_on_deviation
|
||||||
|
from excel_evaluation import evaluation
|
||||||
|
|
||||||
|
|
||||||
def process_video_for_excel(selected_video_name):
|
def process_video_for_excel(selected_video_name):
|
||||||
@ -38,15 +39,16 @@ def process_video_for_excel(selected_video_name):
|
|||||||
|
|
||||||
|
|
||||||
print("Reading + preprocessing video...")
|
print("Reading + preprocessing video...")
|
||||||
video_frames, frame_ct, fps = facedetection.read_video("videos/"+selected_video_name)
|
video_frames, frame_ct, fps = facedetection.read_video("code/videos/"+selected_video_name)
|
||||||
|
|
||||||
|
|
||||||
print("Building Laplacian video pyramid...")
|
print("Building Laplacian video pyramid...")
|
||||||
lap_video = pyramids.build_video_pyramid(video_frames)
|
lap_video = pyramids.build_video_pyramid(video_frames)
|
||||||
|
|
||||||
|
print(len(lap_video))
|
||||||
|
|
||||||
for i, video in enumerate(lap_video):
|
for i, video in enumerate(lap_video):
|
||||||
|
print("test")
|
||||||
if i == 0 or i == len(lap_video)-1:
|
if i == 0 or i == len(lap_video)-1:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -130,3 +132,7 @@ def process_all_videos_and_save_results(testcase_excel_file_path, testruns_excel
|
|||||||
color_cells_based_on_deviation(testruns_excel_file_path, testcase_excel_file_path)
|
color_cells_based_on_deviation(testruns_excel_file_path, testcase_excel_file_path)
|
||||||
|
|
||||||
print("Zellen gefärbt")
|
print("Zellen gefärbt")
|
||||||
|
|
||||||
|
evaluation(testcase_excel_file_path, testruns_excel_file_path)
|
||||||
|
|
||||||
|
print("Testcases sortiert")
|
77
code/facedetection1.py
Normal file
77
code/facedetection1.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
"""
|
||||||
|
Abhängigkeiten:
|
||||||
|
- cv2 (OpenCV-Paket)
|
||||||
|
- numpy
|
||||||
|
|
||||||
|
Autor: Ihr Name
|
||||||
|
Datum: Erstellungs- oder Änderungsdatum
|
||||||
|
Version: Modulversion
|
||||||
|
"""
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_alt2.xml")
|
||||||
|
eyeCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_eye.xml")
|
||||||
|
|
||||||
|
def read_video(path):
|
||||||
|
"""
|
||||||
|
Liest ein Video, erkennt Gesichter und extrahiert Regionen von Interesse (ROIs).
|
||||||
|
|
||||||
|
Diese Funktion nimmt einen Pfad zu einer Videodatei und liest das Video. Während des Lesens erkennt sie
|
||||||
|
Gesichter im Video und extrahiert die ROIs (Gesichtsbereiche), die anschließend in einer Liste von Frames
|
||||||
|
gespeichert werden. Die Frames werden für spätere Verarbeitungsschritte skaliert.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): Der Pfad zur Videodatei.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: Ein Tupel, bestehend aus:
|
||||||
|
- video_frames (list): Eine Liste von Frames, die die ROIs (Gesichtsbereiche) darstellen.
|
||||||
|
- frame_ct (int): Die Anzahl der extrahierten Frames.
|
||||||
|
- fps (int): Die Bildrate (Frames pro Sekunde) des Videos.
|
||||||
|
"""
|
||||||
|
cap = cv2.VideoCapture(path)
|
||||||
|
fps = int(cap.get(cv2.CAP_PROP_FPS))
|
||||||
|
video_frames = []
|
||||||
|
|
||||||
|
while cap.isOpened():
|
||||||
|
ret, img = cap.read()
|
||||||
|
if not ret:
|
||||||
|
break
|
||||||
|
|
||||||
|
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||||
|
faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
|
||||||
|
|
||||||
|
for (x, y, w, h) in faces:
|
||||||
|
face_roi_gray = gray[y:y+h, x:x+w]
|
||||||
|
face_roi_color = img[y:y+h, x:x+w]
|
||||||
|
eyes = eyeCascade.detectMultiScale(face_roi_gray)
|
||||||
|
|
||||||
|
# Annahme: Wir brauchen mindestens zwei Augen für die Berechnung
|
||||||
|
if len(eyes) == 2:
|
||||||
|
# Berechne die Position und Größe des Stirnbereichs
|
||||||
|
eye1_x, eye1_y, eye1_w, eye1_h = eyes[0]
|
||||||
|
eye2_x, eye2_y, eye2_w, eye2_h = eyes[1]
|
||||||
|
|
||||||
|
# Bestimme die horizontale Position und Breite des Stirnbereichs
|
||||||
|
forehead_x = min(eye1_x, eye2_x)
|
||||||
|
forehead_w = max(eye1_x + eye1_w, eye2_x + eye2_w) - forehead_x
|
||||||
|
|
||||||
|
# Bestimme die vertikale Position und Höhe des Stirnbereichs
|
||||||
|
forehead_y = 0
|
||||||
|
forehead_h = int((min(eye1_y, eye2_y) - forehead_y) / 3)
|
||||||
|
|
||||||
|
# Extrahiere und skaliere den Stirnbereich
|
||||||
|
forehead_roi = face_roi_color[forehead_y:forehead_y + forehead_h, forehead_x:forehead_x + forehead_w]
|
||||||
|
forehead_resized = cv2.resize(forehead_roi, (500, 500))
|
||||||
|
video_frames.append(forehead_resized.astype("float") / 255.0)
|
||||||
|
|
||||||
|
cap.release()
|
||||||
|
|
||||||
|
for frame in video_frames:
|
||||||
|
cv2.imshow("frame", frame)
|
||||||
|
cv2.waitKey(20)
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
|
||||||
|
return video_frames, len(video_frames), fps
|
61
code/facedetection2.py
Normal file
61
code/facedetection2.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
"""
|
||||||
|
Abhängigkeiten:
|
||||||
|
- cv2 (OpenCV-Paket)
|
||||||
|
- numpy
|
||||||
|
|
||||||
|
Autor: Ihr Name
|
||||||
|
Datum: Erstellungs- oder Änderungsdatum
|
||||||
|
Version: Modulversion
|
||||||
|
"""
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_alt2.xml")
|
||||||
|
|
||||||
|
def read_video(path):
|
||||||
|
"""
|
||||||
|
Liest ein Video, erkennt Gesichter und extrahiert Regionen von Interesse (ROIs).
|
||||||
|
|
||||||
|
Diese Funktion nimmt einen Pfad zu einer Videodatei und liest das Video. Während des Lesens erkennt sie
|
||||||
|
Gesichter im Video und extrahiert die ROIs (Gesichtsbereiche), die anschließend in einer Liste von Frames
|
||||||
|
gespeichert werden. Die Frames werden für spätere Verarbeitungsschritte skaliert.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): Der Pfad zur Videodatei.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: Ein Tupel, bestehend aus:
|
||||||
|
- video_frames (list): Eine Liste von Frames, die die ROIs (Gesichtsbereiche) darstellen.
|
||||||
|
- frame_ct (int): Die Anzahl der extrahierten Frames.
|
||||||
|
- fps (int): Die Bildrate (Frames pro Sekunde) des Videos.
|
||||||
|
"""
|
||||||
|
cap = cv2.VideoCapture(path)
|
||||||
|
fps = int(cap.get(cv2.CAP_PROP_FPS))
|
||||||
|
video_frames = []
|
||||||
|
|
||||||
|
while cap.isOpened():
|
||||||
|
ret, img = cap.read()
|
||||||
|
if not ret:
|
||||||
|
break
|
||||||
|
|
||||||
|
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||||
|
|
||||||
|
# Detect faces
|
||||||
|
faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
|
||||||
|
|
||||||
|
# Extract ROIs and resize
|
||||||
|
for (x, y, w, h) in faces:
|
||||||
|
face_roi = cv2.resize(img[y:y+h, x:x+w], (500, 500))
|
||||||
|
frame = face_roi.astype("float") / 255.0
|
||||||
|
video_frames.append(frame)
|
||||||
|
|
||||||
|
cap.release()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for frame in video_frames:
|
||||||
|
cv2.imshow("frame", frame)
|
||||||
|
cv2.waitKey(20)
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
return video_frames, len(video_frames), fps
|
43
code/main.py
43
code/main.py
@ -27,8 +27,9 @@ code_version= "1.0"
|
|||||||
|
|
||||||
|
|
||||||
current_dir = os.getcwd()
|
current_dir = os.getcwd()
|
||||||
testcase_excel_file_path = os.path.join(current_dir, 'testing/excel/Testcase_excel_dataset.xlsx')
|
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, 'testing/excel/Testruns.xlsx')
|
testruns_excel_file_path = os.path.join(current_dir, 'code/testing/excel/Testruns.xlsx')
|
||||||
|
evaluation_excel_file_path = os.path.join(current_dir, 'Testcases_nach_Genauigkeit.xlsx')
|
||||||
|
|
||||||
class VideoProcessingApp(tk.Tk):
|
class VideoProcessingApp(tk.Tk):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -62,6 +63,9 @@ class VideoProcessingApp(tk.Tk):
|
|||||||
def open_testrun_excel_file(self):
|
def open_testrun_excel_file(self):
|
||||||
os.startfile(testruns_excel_file_path)
|
os.startfile(testruns_excel_file_path)
|
||||||
|
|
||||||
|
def open_evaluation_excel_file(self):
|
||||||
|
os.startfile(evaluation_excel_file_path)
|
||||||
|
|
||||||
def test_data_set(self):
|
def test_data_set(self):
|
||||||
kommentar = self.testrun_kommentar_entry.get("1.0", "end-1c")
|
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)
|
process_all_videos_and_save_results(testcase_excel_file_path,testruns_excel_file_path,code_version,kommentar)
|
||||||
@ -186,26 +190,32 @@ class VideoProcessingApp(tk.Tk):
|
|||||||
|
|
||||||
|
|
||||||
def check_recording_status(self):
|
def check_recording_status(self):
|
||||||
excel_file_path = 'testing/excel/Testcase_excel_dataset.xlsx'
|
excel_file_path = 'code/testing/excel/Testcase_excel_dataset.xlsx'
|
||||||
global recording_finished # Deklarieren Sie die Verwendung der globalen Variable
|
global recording_finished
|
||||||
|
|
||||||
if recording_finished_event.is_set():
|
if recording_finished_event.is_set():
|
||||||
|
|
||||||
recording_finished_event.clear()
|
recording_finished_event.clear()
|
||||||
video_name = self.testcase_name_entry.get()
|
video_name = self.testcase_name_entry.get()
|
||||||
length = int(self.video_length_entry.get()) # Hole die Länge des Videos
|
length = int(self.video_length_entry.get())
|
||||||
pulse = simpledialog.askinteger("Puls", "Bitte geben Sie Ihren Puls ein:")
|
pulse = simpledialog.askinteger("Puls", "Bitte geben Sie Ihren Puls ein:")
|
||||||
|
|
||||||
if pulse is not None:
|
if pulse is not None:
|
||||||
new_video_name = f"{video_name}_{length}_{pulse}.avi"
|
new_video_name = f"{video_name}_{length}_{pulse}.avi"
|
||||||
original_video_path = os.path.join('videos', f"{video_name}.avi")
|
original_video_path = os.path.join('code', 'videos', f"{video_name}.avi")
|
||||||
new_video_path = os.path.join('videos', new_video_name)
|
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)
|
os.rename(original_video_path, new_video_path)
|
||||||
print(f"Video umbenannt zu {new_video_name}")
|
print(f"Video umbenannt zu {new_video_name}")
|
||||||
self.write_to_excel(new_video_name, excel_file_path)
|
self.write_to_excel(new_video_name, excel_file_path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Fehler beim Umbenennen der Datei: {e}")
|
||||||
else:
|
else:
|
||||||
print("recording_finished ist False, warte auf Aufnahmeende")
|
|
||||||
print("Kein Puls eingegeben.")
|
print("Kein Puls eingegeben.")
|
||||||
# Planen Sie die nächste Überprüfung
|
|
||||||
|
|
||||||
self.after(100, self.check_recording_status)
|
self.after(100, self.check_recording_status)
|
||||||
|
|
||||||
@ -264,7 +274,7 @@ class VideoProcessingApp(tk.Tk):
|
|||||||
self.app_name_label.config(fg="#c82423", bg="#FFFFFF")
|
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
|
# Laden Sie das Bild mit PIL und konvertieren Sie es in ein Format, das Tkinter verwenden kann
|
||||||
self.image = Image.open("code\Interface\ohmbild2.png")
|
self.image = Image.open(r"code\interface\ohmbild2.png")
|
||||||
self.resized_image = self.image.resize((50, 30), Image.LANCZOS)
|
self.resized_image = self.image.resize((50, 30), Image.LANCZOS)
|
||||||
self.photo = ImageTk.PhotoImage(self.resized_image)
|
self.photo = ImageTk.PhotoImage(self.resized_image)
|
||||||
|
|
||||||
@ -531,16 +541,21 @@ class VideoProcessingApp(tk.Tk):
|
|||||||
|
|
||||||
# Button open testcase excel
|
# 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 = tk.Button(self.testing_frame, text="Open Testcase Excel", command=self.open_testcase_excel_file)
|
||||||
self.open_testcase_button.place(x=10, y=200)
|
self.open_testcase_button.place(x=10, y=180)
|
||||||
self.open_testcase_button.config(bg="#c82423", fg="#FFFFFF")
|
self.open_testcase_button.config(bg="#c82423", fg="#FFFFFF")
|
||||||
# Button open testrun excel
|
# 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 = tk.Button(self.testing_frame, text="Open Testrun Excel", command=self.open_testrun_excel_file)
|
||||||
self.open_testrun_button.place(x=10, y=235)
|
self.open_testrun_button.place(x=10, y=215)
|
||||||
self.open_testrun_button.config(bg="#c82423", fg="#FFFFFF")
|
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_evaluation_excel_file)
|
||||||
|
self.open_testrun_button.place(x=10, y=250)
|
||||||
|
self.open_testrun_button.config(bg="#c82423", fg="#FFFFFF")
|
||||||
|
|
||||||
|
|
||||||
def initialize_icon(self):
|
def initialize_icon(self):
|
||||||
# Icon ändern
|
# Icon ändern
|
||||||
self.iconbitmap('code\Interface\ohm.ico')
|
self.iconbitmap(r'code\interface\ohm.ico')
|
||||||
# Ändert die Hintergrundfarbe
|
# Ändert die Hintergrundfarbe
|
||||||
self.configure(bg="#FFFFFF")
|
self.configure(bg="#FFFFFF")
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ def process_video(selected_video_name):
|
|||||||
|
|
||||||
# Preprocessing phase
|
# Preprocessing phase
|
||||||
print("Reading + preprocessing video...")
|
print("Reading + preprocessing video...")
|
||||||
video_frames, frame_ct, fps = facedetection.read_video("videos/"+selected_video_name)
|
video_frames, frame_ct, fps = facedetection.read_video("code/videos/"+selected_video_name)
|
||||||
|
|
||||||
# Build Laplacian video pyramid
|
# Build Laplacian video pyramid
|
||||||
print("Building Laplacian video pyramid...")
|
print("Building Laplacian video pyramid...")
|
||||||
|
@ -56,7 +56,7 @@ def record_video(video_name="aufgenommenes_video", length=5,testcase_resolution1
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
output_folder = "videos"
|
output_folder = "code/videos"
|
||||||
output_file = os.path.join(output_folder, video_name + ".avi")
|
output_file = os.path.join(output_folder, video_name + ".avi")
|
||||||
frame_rate = testcase_fps
|
frame_rate = testcase_fps
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ def record_normal_video(video_name="aufgenommenes_video",video_resolution1=2560,
|
|||||||
Args:
|
Args:
|
||||||
video_name (str): Der Basisname der Videodatei (Standard ist "aufgenommenes_video").
|
video_name (str): Der Basisname der Videodatei (Standard ist "aufgenommenes_video").
|
||||||
"""
|
"""
|
||||||
output_folder = "videos"
|
output_folder = "code/videos"
|
||||||
output_file = os.path.join(output_folder, video_name + ".avi")
|
output_file = os.path.join(output_folder, video_name + ".avi")
|
||||||
|
|
||||||
cap = cv2.VideoCapture(0)
|
cap = cv2.VideoCapture(0)
|
||||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
tkinter
|
tk
|
||||||
numpy
|
numpy
|
||||||
openpyxl
|
openpyxl
|
||||||
pandas
|
pandas
|
||||||
|
Loading…
x
Reference in New Issue
Block a user