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'])
|
@app.route('/api/reset_count', methods=['POST'])
|
||||||
def reset_count():
|
def reset_count():
|
||||||
"""API endpoint to reset the vehicle count"""
|
"""API endpoint to reset the vehicle count (requires page reload to take effect)"""
|
||||||
session['reset_count'] = True
|
# Note: Count reset requires reloading the video stream
|
||||||
return jsonify({'status': 'success'})
|
# 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
|
count = 0
|
||||||
cap = cv2.VideoCapture(0) # 0 for the default webcam
|
cap = cv2.VideoCapture(0) # 0 for the default webcam
|
||||||
|
|
||||||
@@ -80,6 +81,10 @@ def detect_objects_from_webcam():
|
|||||||
vehicle_count = 0
|
vehicle_count = 0
|
||||||
vehicle_type_counts = {'car': 0, 'truck': 0, 'bus': 0, 'motorcycle': 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:
|
while True:
|
||||||
ret, frame = cap.read()
|
ret, frame = cap.read()
|
||||||
if not ret:
|
if not ret:
|
||||||
@@ -90,18 +95,6 @@ def detect_objects_from_webcam():
|
|||||||
# Resize the frame to (1020, 600)
|
# Resize the frame to (1020, 600)
|
||||||
frame = cv2.resize(frame, (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)
|
# Draw counting line (dashed yellow line with black gaps)
|
||||||
cv2.line(frame, line_start, line_end, (0, 255, 255), 2, cv2.LINE_AA)
|
cv2.line(frame, line_start, line_end, (0, 255, 255), 2, cv2.LINE_AA)
|
||||||
# Draw dashed effect
|
# Draw dashed effect
|
||||||
@@ -166,7 +159,9 @@ def detect_objects_from_webcam():
|
|||||||
|
|
||||||
@app.route('/webcam_feed')
|
@app.route('/webcam_feed')
|
||||||
def 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')
|
mimetype='multipart/x-mixed-replace; boundary=frame')
|
||||||
|
|
||||||
@app.route('/upload', methods=['POST'])
|
@app.route('/upload', methods=['POST'])
|
||||||
@@ -199,7 +194,7 @@ def play_video(filename):
|
|||||||
def send_video(filename):
|
def send_video(filename):
|
||||||
return send_from_directory('uploads', 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)
|
cap = cv2.VideoCapture(video_path)
|
||||||
count = 0
|
count = 0
|
||||||
|
|
||||||
@@ -209,6 +204,10 @@ def detect_objects_from_video(video_path):
|
|||||||
vehicle_count = 0
|
vehicle_count = 0
|
||||||
vehicle_type_counts = {'car': 0, 'truck': 0, 'bus': 0, 'motorcycle': 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():
|
while cap.isOpened():
|
||||||
ret, frame = cap.read()
|
ret, frame = cap.read()
|
||||||
if not ret:
|
if not ret:
|
||||||
@@ -220,18 +219,6 @@ def detect_objects_from_video(video_path):
|
|||||||
# Resize the frame to (1020, 600)
|
# Resize the frame to (1020, 600)
|
||||||
frame = cv2.resize(frame, (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)
|
# Draw counting line (dashed yellow line with black gaps)
|
||||||
cv2.line(frame, line_start, line_end, (0, 255, 255), 2, cv2.LINE_AA)
|
cv2.line(frame, line_start, line_end, (0, 255, 255), 2, cv2.LINE_AA)
|
||||||
# Draw dashed effect
|
# Draw dashed effect
|
||||||
@@ -297,7 +284,9 @@ def detect_objects_from_video(video_path):
|
|||||||
@app.route('/video_feed/<filename>')
|
@app.route('/video_feed/<filename>')
|
||||||
def video_feed(filename):
|
def video_feed(filename):
|
||||||
video_path = os.path.join('uploads', 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')
|
mimetype='multipart/x-mixed-replace; boundary=frame')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -174,18 +174,18 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
resetCountBtn.addEventListener('click', () => {
|
resetCountBtn.addEventListener('click', () => {
|
||||||
fetch('/api/reset_count', {
|
if (confirm('Zähler zurücksetzen? Die Seite wird neu geladen.')) {
|
||||||
method: 'POST',
|
fetch('/api/reset_count', {
|
||||||
headers: { 'Content-Type': 'application/json' }
|
method: 'POST',
|
||||||
})
|
headers: { 'Content-Type': 'application/json' }
|
||||||
.then(res => res.json())
|
})
|
||||||
.then(data => {
|
.then(res => res.json())
|
||||||
console.log('Count reset:', data);
|
.then(data => {
|
||||||
infoText.textContent = 'Zähler wurde zurückgesetzt!';
|
console.log('Count reset:', data);
|
||||||
setTimeout(() => {
|
// Reload page to reset the video stream and counter
|
||||||
infoText.textContent = 'Klicke auf "Zähllinie setzen" und dann zweimal auf das Video, um die Zähllinie zu definieren.';
|
location.reload();
|
||||||
}, 2000);
|
});
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function drawLine() {
|
function drawLine() {
|
||||||
|
|||||||
@@ -174,18 +174,18 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
resetCountBtn.addEventListener('click', () => {
|
resetCountBtn.addEventListener('click', () => {
|
||||||
fetch('/api/reset_count', {
|
if (confirm('Zähler zurücksetzen? Die Seite wird neu geladen.')) {
|
||||||
method: 'POST',
|
fetch('/api/reset_count', {
|
||||||
headers: { 'Content-Type': 'application/json' }
|
method: 'POST',
|
||||||
})
|
headers: { 'Content-Type': 'application/json' }
|
||||||
.then(res => res.json())
|
})
|
||||||
.then(data => {
|
.then(res => res.json())
|
||||||
console.log('Count reset:', data);
|
.then(data => {
|
||||||
infoText.textContent = 'Zähler wurde zurückgesetzt!';
|
console.log('Count reset:', data);
|
||||||
setTimeout(() => {
|
// Reload page to reset the video stream and counter
|
||||||
infoText.textContent = 'Klicke auf "Zähllinie setzen" und dann zweimal auf das Video, um die Zähllinie zu definieren.';
|
location.reload();
|
||||||
}, 2000);
|
});
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function drawLine() {
|
function drawLine() {
|
||||||
|
|||||||
Reference in New Issue
Block a user