From 9caaa51cf581999c33727e584ccb8460e0f52131 Mon Sep 17 00:00:00 2001 From: Lucca Pirovano Date: Thu, 11 Jun 2026 15:29:12 -0400 Subject: [PATCH] adding to gitea repo --- cam/app.py | 99 ++++++++++++++++++++++++++++++++++++++++ cam/templates/index.html | 16 +++++++ cam/test.py | 20 ++++++++ 3 files changed, 135 insertions(+) create mode 100644 cam/app.py create mode 100644 cam/templates/index.html create mode 100644 cam/test.py diff --git a/cam/app.py b/cam/app.py new file mode 100644 index 0000000..6c92ef8 --- /dev/null +++ b/cam/app.py @@ -0,0 +1,99 @@ +# 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(''' + + + + PS3 Eye — 60 fps Live + + + +

PS3 Eye — 640×480 @ 60 fps

+ +

LED should stay ON permanently

+ + + ''') + +@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") diff --git a/cam/templates/index.html b/cam/templates/index.html new file mode 100644 index 0000000..013cbbc --- /dev/null +++ b/cam/templates/index.html @@ -0,0 +1,16 @@ + + + + Server Webcam Stream + + + +

Live Feed from Server Webcam

+ Server webcam +

Refresh the page if the stream stops.

+ + diff --git a/cam/test.py b/cam/test.py new file mode 100644 index 0000000..4cd502d --- /dev/null +++ b/cam/test.py @@ -0,0 +1,20 @@ +import cv2 + +cap = cv2.VideoCapture(2, cv2.CAP_V4L2) # try 0,1 + different backends +cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) +cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) +cap.set(cv2.CAP_PROP_FPS, 60) + +while True: + ret, frame = cap.read() + if ret: + cv2.imshow('PS3 Eye Test - Should be 60fps', frame) + print("Got frame!") + else: + print("No frame") + + if cv2.waitKey(1) & 0xFF == ord('q'): + break + +cap.release() +cv2.destroyAllWindows()