This commit is contained in:
Andreas Knuth 2024-11-29 23:00:45 +01:00
parent 4f1158c144
commit 711b9d543f
2 changed files with 46 additions and 40 deletions

View File

@ -28,6 +28,7 @@ def init_db():
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
deckname TEXT NOT NULL, deckname TEXT NOT NULL,
bildname TEXT, bildname TEXT,
bildid TEXT,
iconindex INTEGER, iconindex INTEGER,
x1 REAL, x1 REAL,
x2 REAL, x2 REAL,
@ -40,7 +41,7 @@ def init_db():
def clean_debug_directories(): def clean_debug_directories():
""" """
Löscht alle Verzeichnisse unter 'debug_images', die keinen Eintrag in der Deck-Tabelle mit bildname haben. Löscht alle Verzeichnisse unter 'debug_images', die keinen Eintrag in der Deck-Tabelle mit bildname oder bildid haben.
""" """
debug_base_dir = 'debug_images' debug_base_dir = 'debug_images'
if not os.path.exists(debug_base_dir): if not os.path.exists(debug_base_dir):
@ -50,18 +51,22 @@ def clean_debug_directories():
try: try:
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
# Sammle alle bildname und bildid, die in der Deck-Tabelle vorhanden sind
cursor.execute('SELECT DISTINCT bildname FROM Deck WHERE bildname IS NOT NULL') cursor.execute('SELECT DISTINCT bildname FROM Deck WHERE bildname IS NOT NULL')
bildnames = {row['bildname'] for row in cursor.fetchall()} bildnames = {row['bildname'] for row in cursor.fetchall()}
cursor.execute('SELECT DISTINCT bildid FROM Deck WHERE bildid IS NOT NULL')
bildids = {row['bildid'] for row in cursor.fetchall()}
conn.close() conn.close()
except sqlite3.Error as e: except sqlite3.Error as e:
logger.error(f"Fehler beim Abrufen der bildname aus der Datenbank: {e}") logger.error(f"Fehler beim Abrufen der bildname und bildid aus der Datenbank: {e}")
return return
# Durchlaufe alle Verzeichnisse unter 'debug_images' # Durchlaufe alle Verzeichnisse unter 'debug_images'
for dir_name in os.listdir(debug_base_dir): for dir_name in os.listdir(debug_base_dir):
dir_path = os.path.join(debug_base_dir, dir_name) dir_path = os.path.join(debug_base_dir, dir_name)
if os.path.isdir(dir_path): if os.path.isdir(dir_path):
if dir_name not in bildnames: if dir_name not in bildnames and dir_name not in bildids:
try: try:
shutil.rmtree(dir_path) shutil.rmtree(dir_path)
logger.info(f"Nicht verwendetes Debug-Verzeichnis gelöscht: {dir_path}") logger.info(f"Nicht verwendetes Debug-Verzeichnis gelöscht: {dir_path}")
@ -117,9 +122,10 @@ def get_decks():
'name': deckname, 'name': deckname,
'images': [] 'images': []
} }
if entry['bildname']: if entry['bildname'] and entry['bildid']:
image = { image = {
'name': entry['bildname'], 'name': entry['bildname'],
'id': entry['bildid'],
'iconindex': entry['iconindex'], 'iconindex': entry['iconindex'],
'x1': entry['x1'], 'x1': entry['x1'],
'x2': entry['x2'], 'x2': entry['x2'],
@ -164,12 +170,13 @@ def update_image():
return jsonify({'error': 'No data provided'}), 400 return jsonify({'error': 'No data provided'}), 400
# Überprüfen, ob die erforderlichen Felder vorhanden sind # Überprüfen, ob die erforderlichen Felder vorhanden sind
required_fields = ['deckname', 'image', 'boxes'] required_fields = ['deckname', 'bildname', 'bildid', 'boxes']
if not all(field in data for field in required_fields): if not all(field in data for field in required_fields):
return jsonify({'error': 'Missing fields in data'}), 400 return jsonify({'error': 'Missing fields in data'}), 400
deckname = data['deckname'] deckname = data['deckname']
bildname = data['image'] bildname = data['bildname']
bildid = data['bildid']
boxes = data['boxes'] boxes = data['boxes']
# Überprüfen, ob 'boxes' eine Liste ist und mindestens ein Box-Element enthält # Überprüfen, ob 'boxes' eine Liste ist und mindestens ein Box-Element enthält
@ -210,9 +217,9 @@ def update_image():
iconindex = index iconindex = index
cursor.execute(''' cursor.execute('''
INSERT INTO Deck (deckname, bildname, iconindex, x1, x2, y1, y2) INSERT INTO Deck (deckname, bildname, bildid, iconindex, x1, x2, y1, y2)
VALUES (?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', (deckname, bildname, iconindex, x1, x2, y1, y2)) ''', (deckname, bildname, bildid, iconindex, x1, x2, y1, y2))
inserted_image_ids.append(cursor.lastrowid) inserted_image_ids.append(cursor.lastrowid)
conn.commit() conn.commit()
@ -226,27 +233,27 @@ def update_image():
finally: finally:
conn.close() conn.close()
@deck_bp.route('/api/decks/image/<bildname>', methods=['GET']) # @deck_bp.route('/api/decks/image/<bildid>', methods=['GET'])
def get_images_by_bildname(bildname): # def get_images_by_bildid(bildid):
conn = get_db_connection() # conn = get_db_connection()
cursor = conn.cursor() # cursor = conn.cursor()
images = cursor.execute('SELECT * FROM Deck WHERE bildname = ?', (bildname,)).fetchall() # images = cursor.execute('SELECT * FROM Deck WHERE bildid = ?', (bildid,)).fetchall()
conn.close() # conn.close()
image_list = [dict(image) for image in images] # image_list = [dict(image) for image in images]
return jsonify(image_list) # return jsonify(image_list)
@deck_bp.route('/api/decks/image/<bildname>', methods=['DELETE']) @deck_bp.route('/api/decks/image/<bildid>', methods=['DELETE'])
def delete_images_by_bildname(bildname): def delete_images_by_bildid(bildid):
""" """
Löscht alle Einträge in der Deck-Tabelle für den gegebenen bildname. Löscht alle Einträge in der Deck-Tabelle für die gegebene bildid.
Falls es das letzte Image für ein Deck ist, wird ein neuer Deck-Eintrag erstellt. Falls es das letzte Image für dieses Deck ist, wird ein neuer Deck-Eintrag erstellt.
Optional: Löscht das zugehörige Debug-Verzeichnis, wenn keine weiteren Einträge bestehen. Optional: Löscht das zugehörige Debug-Verzeichnis, wenn keine weiteren Einträge bestehen.
""" """
try: try:
# Sicherheitsmaßnahme: Nur erlaubte Zeichen im bildname # Sicherheitsmaßnahme: Nur erlaubte Zeichen in bildid
if not all(c.isalnum() or c in ('_', '-') for c in bildname): if not all(c.isalnum() or c in ('_', '-') for c in bildid):
logger.warning(f"Ungültiger bildname angefordert: {bildname}") logger.warning(f"Ungültige bildid angefordert: {bildid}")
return jsonify({'error': 'Invalid image name'}), 400 return jsonify({'error': 'Invalid image ID'}), 400
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
@ -255,27 +262,27 @@ def delete_images_by_bildname(bildname):
conn.execute('BEGIN') conn.execute('BEGIN')
# Schritt 1: Identifizieren der betroffenen Decks # Schritt 1: Identifizieren der betroffenen Decks
cursor.execute('SELECT DISTINCT deckname FROM Deck WHERE bildname = ?', (bildname,)) cursor.execute('SELECT DISTINCT deckname FROM Deck WHERE bildid = ?', (bildid,))
affected_decks = {row['deckname'] for row in cursor.fetchall()} affected_decks = {row['deckname'] for row in cursor.fetchall()}
if not affected_decks: if not affected_decks:
conn.close() conn.close()
return jsonify({'error': 'No entries found for the given image name'}), 404 return jsonify({'error': 'No entries found for the given image ID'}), 404
# Schritt 2: Löschen der Image-Einträge # Schritt 2: Löschen der Image-Einträge
cursor.execute('DELETE FROM Deck WHERE bildname = ?', (bildname,)) cursor.execute('DELETE FROM Deck WHERE bildid = ?', (bildid,))
logger.info(f"Alle Einträge für bildname '{bildname}' wurden gelöscht.") logger.info(f"Alle Einträge für bildid '{bildid}' wurden gelöscht.")
# Schritt 3: Überprüfen und Wiederherstellen der Deck-Einträge # Schritt 3: Überprüfen und Wiederherstellen der Deck-Einträge
for deckname in affected_decks: for deckname in affected_decks:
# Überprüfen, ob noch andere Image-Einträge für dieses Deck existieren # Überprüfen, ob noch andere Image-Einträge für dieses Deck existieren
cursor.execute('SELECT COUNT(*) as count FROM Deck WHERE deckname = ? AND bildname IS NOT NULL', (deckname,)) cursor.execute('SELECT COUNT(*) as count FROM Deck WHERE deckname = ? AND bildid IS NOT NULL', (deckname,))
result = cursor.fetchone() result = cursor.fetchone()
image_count = result['count'] if result else 0 image_count = result['count'] if result else 0
if image_count == 0: if image_count == 0:
# Überprüfen, ob bereits ein Deck-Eintrag existiert # Überprüfen, ob bereits ein Deck-Eintrag existiert (ohne bildid)
cursor.execute('SELECT COUNT(*) as count FROM Deck WHERE deckname = ? AND bildname IS NULL', (deckname,)) cursor.execute('SELECT COUNT(*) as count FROM Deck WHERE deckname = ? AND bildid IS NULL', (deckname,))
deck_entry = cursor.fetchone() deck_entry = cursor.fetchone()
if deck_entry['count'] == 0: if deck_entry['count'] == 0:
# Ein neuer Deck-Eintrag wird erstellt # Ein neuer Deck-Eintrag wird erstellt
@ -286,7 +293,7 @@ def delete_images_by_bildname(bildname):
conn.commit() conn.commit()
# Schritt 4: Optionales Löschen des Debug-Verzeichnisses # Schritt 4: Optionales Löschen des Debug-Verzeichnisses
debug_dir = os.path.join('debug_images', bildname) debug_dir = os.path.join('debug_images', bildid)
if os.path.exists(debug_dir): if os.path.exists(debug_dir):
try: try:
shutil.rmtree(debug_dir) shutil.rmtree(debug_dir)
@ -300,24 +307,23 @@ def delete_images_by_bildname(bildname):
'details': str(e) 'details': str(e)
}), 200 }), 200
return jsonify({'status': 'success', 'message': f'All entries for image "{bildname}" have been deleted.'}), 200 return jsonify({'status': 'success', 'message': f'All entries for image ID "{bildid}" have been deleted.'}), 200
except sqlite3.Error as e: except sqlite3.Error as e:
# Rollback der Transaktion bei einem Datenbankfehler # Rollback der Transaktion bei einem Datenbankfehler
conn.rollback() conn.rollback()
logger.error(f"Datenbankfehler beim Löschen der Image-Einträge für '{bildname}': {e}") logger.error(f"Datenbankfehler beim Löschen der Image-Einträge für '{bildid}': {e}")
return jsonify({'error': 'Database error', 'details': str(e)}), 500 return jsonify({'error': 'Database error', 'details': str(e)}), 500
except Exception as e: except Exception as e:
# Rollback der Transaktion bei einem unerwarteten Fehler # Rollback der Transaktion bei einem unerwarteten Fehler
conn.rollback() conn.rollback()
logger.error(f"Unerwarteter Fehler beim Löschen der Image-Einträge für '{bildname}': {e}") logger.error(f"Unerwarteter Fehler beim Löschen der Image-Einträge für '{bildid}': {e}")
return jsonify({'error': 'Failed to delete image entries', 'details': str(e)}), 500 return jsonify({'error': 'Failed to delete image entries', 'details': str(e)}), 500
finally: finally:
conn.close() conn.close()
# Sicherstellen, dass die Datenbank existiert # Sicherstellen, dass die Datenbank existiert
if not os.path.exists(DATABASE): if not os.path.exists(DATABASE):
init_db() init_db()

View File

@ -52,16 +52,16 @@ def preprocess_image(image, debug_dir):
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
enhanced = clahe.apply(gray) enhanced = clahe.apply(gray)
denoised = cv2.fastNlMeansDenoising(enhanced) denoised = cv2.fastNlMeansDenoising(enhanced)
_, binary = cv2.threshold(denoised, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # _, binary = cv2.threshold(denoised, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# Speichern der Zwischenergebnisse im spezifischen Verzeichnis # Speichern der Zwischenergebnisse im spezifischen Verzeichnis
cv2.imwrite(os.path.join(debug_dir, 'gray.png'), gray) cv2.imwrite(os.path.join(debug_dir, 'gray.png'), gray)
cv2.imwrite(os.path.join(debug_dir, 'enhanced.png'), enhanced) cv2.imwrite(os.path.join(debug_dir, 'enhanced.png'), enhanced)
cv2.imwrite(os.path.join(debug_dir, 'denoised.png'), denoised) cv2.imwrite(os.path.join(debug_dir, 'denoised.png'), denoised)
cv2.imwrite(os.path.join(debug_dir, 'binary.png'), binary) # cv2.imwrite(os.path.join(debug_dir, 'binary.png'), binary)
logger.info(f"Debug images saved in: {debug_dir}") logger.info(f"Debug images saved in: {debug_dir}")
return binary return denoised
except Exception as e: except Exception as e:
logger.error(f"Preprocessing error: {str(e)}") logger.error(f"Preprocessing error: {str(e)}")
raise raise