Fix: Session-Zugriff außerhalb des Request-Kontexts behoben

Problem: RuntimeError beim Zugriff auf session in Generator-Funktionen
Lösung:
- Liniendaten werden vor dem Generator aus der Session gelesen
- Als Parameter an detect_objects_from_webcam() übergeben
- Als Parameter an detect_objects_from_video() übergeben
- Reset-Button lädt jetzt die Seite neu (mit Bestätigungsdialog)

Technische Details:
- Generator-Funktionen haben keinen Request-Kontext
- Session-Werte müssen vor Generator-Start erfasst werden
- Counter-Reset funktioniert durch Seiten-Reload

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-08 14:48:09 +00:00
parent 504f8c0b69
commit 9145872ef1
3 changed files with 44 additions and 55 deletions

51
app.py
View File

@@ -66,11 +66,12 @@ def get_counting_line():
@app.route('/api/reset_count', methods=['POST'])
def reset_count():
"""API endpoint to reset the vehicle count"""
session['reset_count'] = True
return jsonify({'status': 'success'})
"""API endpoint to reset the vehicle count (requires page reload to take effect)"""
# Note: Count reset requires reloading the video stream
# The count is stored in the generator function's local variables
return jsonify({'status': 'success', 'message': 'Please reload the page to reset the count'})
def detect_objects_from_webcam():
def detect_objects_from_webcam(line_data):
count = 0
cap = cv2.VideoCapture(0) # 0 for the default webcam
@@ -80,6 +81,10 @@ def detect_objects_from_webcam():
vehicle_count = 0
vehicle_type_counts = {'car': 0, 'truck': 0, 'bus': 0, 'motorcycle': 0}
# Get line coordinates
line_start = (line_data['x1'], line_data['y1'])
line_end = (line_data['x2'], line_data['y2'])
while True:
ret, frame = cap.read()
if not ret:
@@ -90,18 +95,6 @@ def detect_objects_from_webcam():
# Resize the frame to (1020, 600)
frame = cv2.resize(frame, (1020, 600))
# Get counting line from session (default to horizontal middle line)
line_data = session.get('counting_line', {'x1': 0, 'y1': 300, 'x2': 1020, 'y2': 300})
line_start = (line_data['x1'], line_data['y1'])
line_end = (line_data['x2'], line_data['y2'])
# Check if count should be reset
if session.get('reset_count', False):
counted_ids.clear()
vehicle_count = 0
vehicle_type_counts = {'car': 0, 'truck': 0, 'bus': 0, 'motorcycle': 0}
session['reset_count'] = False
# Draw counting line (dashed yellow line with black gaps)
cv2.line(frame, line_start, line_end, (0, 255, 255), 2, cv2.LINE_AA)
# Draw dashed effect
@@ -166,7 +159,9 @@ def detect_objects_from_webcam():
@app.route('/webcam_feed')
def webcam_feed():
return Response(detect_objects_from_webcam(),
# Get line data from session before starting generator
line_data = session.get('counting_line', {'x1': 0, 'y1': 300, 'x2': 1020, 'y2': 300})
return Response(detect_objects_from_webcam(line_data),
mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/upload', methods=['POST'])
@@ -199,7 +194,7 @@ def play_video(filename):
def send_video(filename):
return send_from_directory('uploads', filename)
def detect_objects_from_video(video_path):
def detect_objects_from_video(video_path, line_data):
cap = cv2.VideoCapture(video_path)
count = 0
@@ -209,6 +204,10 @@ def detect_objects_from_video(video_path):
vehicle_count = 0
vehicle_type_counts = {'car': 0, 'truck': 0, 'bus': 0, 'motorcycle': 0}
# Get line coordinates
line_start = (line_data['x1'], line_data['y1'])
line_end = (line_data['x2'], line_data['y2'])
while cap.isOpened():
ret, frame = cap.read()
if not ret:
@@ -220,18 +219,6 @@ def detect_objects_from_video(video_path):
# Resize the frame to (1020, 600)
frame = cv2.resize(frame, (1020, 600))
# Get counting line from session (default to horizontal middle line)
line_data = session.get('counting_line', {'x1': 0, 'y1': 300, 'x2': 1020, 'y2': 300})
line_start = (line_data['x1'], line_data['y1'])
line_end = (line_data['x2'], line_data['y2'])
# Check if count should be reset
if session.get('reset_count', False):
counted_ids.clear()
vehicle_count = 0
vehicle_type_counts = {'car': 0, 'truck': 0, 'bus': 0, 'motorcycle': 0}
session['reset_count'] = False
# Draw counting line (dashed yellow line with black gaps)
cv2.line(frame, line_start, line_end, (0, 255, 255), 2, cv2.LINE_AA)
# Draw dashed effect
@@ -297,7 +284,9 @@ def detect_objects_from_video(video_path):
@app.route('/video_feed/<filename>')
def video_feed(filename):
video_path = os.path.join('uploads', filename)
return Response(detect_objects_from_video(video_path),
# Get line data from session before starting generator
line_data = session.get('counting_line', {'x1': 0, 'y1': 300, 'x2': 1020, 'y2': 300})
return Response(detect_objects_from_video(video_path, line_data),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':

View File

@@ -174,6 +174,7 @@
});
resetCountBtn.addEventListener('click', () => {
if (confirm('Zähler zurücksetzen? Die Seite wird neu geladen.')) {
fetch('/api/reset_count', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
@@ -181,11 +182,10 @@
.then(res => res.json())
.then(data => {
console.log('Count reset:', data);
infoText.textContent = 'Zähler wurde zurückgesetzt!';
setTimeout(() => {
infoText.textContent = 'Klicke auf "Zähllinie setzen" und dann zweimal auf das Video, um die Zähllinie zu definieren.';
}, 2000);
// Reload page to reset the video stream and counter
location.reload();
});
}
});
function drawLine() {

View File

@@ -174,6 +174,7 @@
});
resetCountBtn.addEventListener('click', () => {
if (confirm('Zähler zurücksetzen? Die Seite wird neu geladen.')) {
fetch('/api/reset_count', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
@@ -181,11 +182,10 @@
.then(res => res.json())
.then(data => {
console.log('Count reset:', data);
infoText.textContent = 'Zähler wurde zurückgesetzt!';
setTimeout(() => {
infoText.textContent = 'Klicke auf "Zähllinie setzen" und dann zweimal auf das Video, um die Zähllinie zu definieren.';
}, 2000);
// Reload page to reset the video stream and counter
location.reload();
});
}
});
function drawLine() {