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:
51
app.py
51
app.py
@@ -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__':
|
||||
|
||||
@@ -174,18 +174,18 @@
|
||||
});
|
||||
|
||||
resetCountBtn.addEventListener('click', () => {
|
||||
fetch('/api/reset_count', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
.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);
|
||||
});
|
||||
if (confirm('Zähler zurücksetzen? Die Seite wird neu geladen.')) {
|
||||
fetch('/api/reset_count', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
console.log('Count reset:', data);
|
||||
// Reload page to reset the video stream and counter
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function drawLine() {
|
||||
|
||||
@@ -174,18 +174,18 @@
|
||||
});
|
||||
|
||||
resetCountBtn.addEventListener('click', () => {
|
||||
fetch('/api/reset_count', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
.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);
|
||||
});
|
||||
if (confirm('Zähler zurücksetzen? Die Seite wird neu geladen.')) {
|
||||
fetch('/api/reset_count', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
console.log('Count reset:', data);
|
||||
// Reload page to reset the video stream and counter
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function drawLine() {
|
||||
|
||||
Reference in New Issue
Block a user