Files
arduino-vehicle/cam/app.py
T
2026-06-11 15:29:12 -04:00

100 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# app.py — PS3 Eye + Flask — FINAL, LED STAYS ON, 60 fps
from flask import Flask, Response, render_template_string
import cv2
import time
import numpy as np
app = Flask(__name__)
# ←←← CAMERA IS NO LONGER GLOBAL — created on first use
camera = None
def get_camera():
global camera
if camera is None or not camera.isOpened():
print("Initializing PS3 Eye (index 2, V4L2)...")
camera = cv2.VideoCapture(2, cv2.CAP_V4L2)
if not camera.isOpened():
raise RuntimeError("Cannot open PS3 Eye")
camera.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M','J','P','G'))
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
camera.set(cv2.CAP_PROP_FPS, 60)
camera.set(cv2.CAP_PROP_BUFFERSIZE, 1)
# Wake-up sequence — LED turns on here and stays on
print("Warming up camera — LED should turn ON now...")
for i in range(60):
ret, _ = camera.read()
if ret and i == 30:
print("Camera alive — LED ON permanently")
time.sleep(0.5)
w = camera.get(cv2.CAP_PROP_FRAME_WIDTH)
h = camera.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = camera.get(cv2.CAP_PROP_FPS)
print(f"Camera initialized → {w}x{h} @ {fps} fps")
return camera
frame_counter = 0
last_time = time.time()
def generate_frames():
global frame_counter, last_time
cam = get_camera() # ← ensures camera exists and is warm
while True:
success, frame = cam.read()
if not success:
frame = np.zeros((480, 640, 3), np.uint8)
cv2.putText(frame, "NO FRAME", (100, 240), cv2.FONT_HERSHEY_SIMPLEX, 2, (0,0,255), 5)
else:
now = time.time()
if now - last_time >= 1.0:
print(f"Live → ~{frame_counter/(now-last_time):.1f} fps")
frame_counter = 0
last_time = now
frame_counter += 1
ret, buffer = cv2.imencode('.jpg', frame, [int(cv2.IMWRITE_JPEG_QUALITY), 82])
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + buffer.tobytes() + b'\r\n')
@app.route('/')
def index():
return render_template_string('''
<!DOCTYPE html>
<html>
<head>
<title>PS3 Eye — 60 fps Live</title>
<style>
body {background:#000; color:#0f0; font-family:monospace; text-align:center; margin:0; padding:20px;}
img {width:90vw; max-width:960px; border:8px solid #0f0; border-radius:15px;}
h1 {text-shadow:0 0 20px #0f0;}
</style>
</head>
<body>
<h1>PS3 Eye — 640×480 @ 60 fps</h1>
<img src="/video_feed">
<p>LED should stay ON permanently</p>
</body>
</html>
''')
@app.route('/video_feed')
def video_feed():
return Response(generate_frames(),
mimetype='multipart/x-mixed-replace; boundary=frame')
# Only release when the entire Python process exits
import atexit
atexit.register(lambda: camera.release() if camera and camera.isOpened() else None)
if __name__ == '__main__':
try:
app.run(host='0.0.0.0', port=5000, threaded=True)
finally:
if camera and camera.isOpened():
camera.release()
print("Camera released on shutdown")