diff --git a/requirements.txt b/requirements.txt index 159497f7..a6ce2bf2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,6 +2,7 @@ bleak>="1.0.0" flask>="3.1.1" pypylon>= "4.0.0" onnxruntime>= "1.18.0" +onnxruntime-gpu>= "1.18.0" opencv-python>= "4.9.0" pytest>= "8.0.0" pytest-playwright>= "0.4.0" diff --git a/run.ps1 b/run.ps1 new file mode 100644 index 00000000..a0e5fd64 --- /dev/null +++ b/run.ps1 @@ -0,0 +1,8 @@ +# Activate the virtual environment +. .\.venv\Scripts\Activate.ps1 + +# Install dependencies +pip install -r requirements.txt + +# Run the Flask application +python src/controllerSoftware/app.py diff --git a/run.sh b/run.sh new file mode 100644 index 00000000..fb14d636 --- /dev/null +++ b/run.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .venv/bin/activate +pip install -r requirements.txt +python src/controllerSoftware/app.py diff --git a/src/controllerSoftware/app.py b/src/controllerSoftware/app.py index 0d5dfd4d..14f43533 100644 --- a/src/controllerSoftware/app.py +++ b/src/controllerSoftware/app.py @@ -1,4 +1,4 @@ -from flask import Flask, render_template, request, jsonify +from flask import Flask, render_template, request, jsonify, Response import asyncio from bleak import BleakScanner, BleakClient import threading @@ -7,6 +7,7 @@ import json import sys import signal import os +import cv2 from vision import VisionSystem # ================================================================================================= @@ -281,6 +282,22 @@ def get_pupil_data(): return jsonify(success=True, data=data) return jsonify(success=False, message="Vision system not initialized"), 500 +def gen_frames(): + """Generator function for video streaming.""" + while True: + frame = vision_system.get_annotated_frame() + if frame is not None: + ret, buffer = cv2.imencode('.jpg', frame) + frame = buffer.tobytes() + yield (b'--frame\r\n' + b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') + +@app.route('/video_feed') +def video_feed(): + """Video streaming route.""" + return Response(gen_frames(), + mimetype='multipart/x-mixed-replace; boundary=frame') + # ================================================================================================= # APP STARTUP # ================================================================================================= diff --git a/src/controllerSoftware/deepstream_pipeline.py b/src/controllerSoftware/deepstream_pipeline.py index 3e894d3a..403e4248 100644 --- a/src/controllerSoftware/deepstream_pipeline.py +++ b/src/controllerSoftware/deepstream_pipeline.py @@ -4,6 +4,7 @@ gi.require_version('Gst', '1.0') from gi.repository import Gst, GLib import pyds import threading +import numpy as np try: from pypylon import pylon except ImportError: @@ -21,6 +22,7 @@ class DeepStreamPipeline: self.pipeline = None self.loop = GLib.MainLoop() self.pupil_data = None + self.annotated_frame = None self.camera = None self.frame_feeder_thread = None self.is_running = False @@ -94,6 +96,9 @@ class DeepStreamPipeline: except StopIteration: break + # Get frame as numpy array + self.annotated_frame = pyds.get_nvds_buf_surface(hash(gst_buffer), frame_meta.batch_id) + l_obj = frame_meta.obj_meta_list while l_obj is not None: try: @@ -149,9 +154,8 @@ class DeepStreamPipeline: return source = Gst.ElementFactory.make("appsrc", "app-source") - # ... (element creation remains the same) pgie = Gst.ElementFactory.make("nvinfer", "primary-inference") - sink = Gst.ElementFactory.make("fakesink", "sink") + sink = Gst.ElementFactory.make("appsink", "app-sink") videoconvert = Gst.ElementFactory.make("nvvideoconvert", "nv-videoconvert") @@ -163,6 +167,11 @@ class DeepStreamPipeline: pgie.set_property('config-file-path', "pgie_yolov10_config.txt") + # Set appsink properties + sink.set_property("emit-signals", True) + sink.set_property("max-buffers", 1) + sink.set_property("drop", True) + self.pipeline.add(source) self.pipeline.add(videoconvert) self.pipeline.add(pgie) @@ -221,6 +230,12 @@ class DeepStreamPipeline: """ return self.pupil_data + def get_annotated_frame(self): + """ + Retrieves the annotated frame from the pipeline. + """ + return self.annotated_frame + if __name__ == '__main__': config = {} pipeline = DeepStreamPipeline(config) diff --git a/src/controllerSoftware/static/script.js b/src/controllerSoftware/static/script.js index 7a2bc34a..0cec6b23 100644 --- a/src/controllerSoftware/static/script.js +++ b/src/controllerSoftware/static/script.js @@ -282,4 +282,33 @@ $(document).ready(function() { setInterval(checkBleStatus, 2000); checkBleStatus(); // Initial check + + function getPupilData() { + $.ajax({ + url: '/vision/pupil_data', + type: 'GET', + success: function(response) { + if (response.success && response.data) { + var pupilData = response.data; + var pupilPosition = pupilData.pupil_position; + var pupilDiameter = pupilData.pupil_diameter; + + // Update text fields + $('#pupil-center').text(`(${pupilPosition[0]}, ${pupilPosition[1]})`); + $('#pupil-area').text(pupilDiameter); + + // Draw on canvas + var canvas = $('#pupil-canvas')[0]; + var ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.beginPath(); + ctx.arc(pupilPosition[0] / 2, pupilPosition[1] / 2, pupilDiameter / 2, 0, 2 * Math.PI); + ctx.fillStyle = 'red'; + ctx.fill(); + } + } + }); + } + + setInterval(getPupilData, 500); // Fetch data every 500ms }); \ No newline at end of file diff --git a/src/controllerSoftware/static/style.css b/src/controllerSoftware/static/style.css index 24220f44..941fe415 100644 --- a/src/controllerSoftware/static/style.css +++ b/src/controllerSoftware/static/style.css @@ -23,6 +23,35 @@ body { align-items: flex-start; gap: 40px; } + +#vision-system { + display: flex; + flex-direction: column; + align-items: center; +} + +#pupil-detection { + margin-bottom: 20px; + text-align: center; +} + +#pupil-canvas { + border: 1px solid #ccc; + background-color: #f0f0f0; +} + +#pupil-data p { + margin: 5px 0; +} + +#video-feed { + text-align: center; +} + +#video-feed img { + border: 1px solid #ccc; +} + .matrix-grid { display: grid; grid-template-columns: repeat(5, 70px); diff --git a/src/controllerSoftware/templates/index.html b/src/controllerSoftware/templates/index.html index 11c0daa7..a85e6d61 100644 --- a/src/controllerSoftware/templates/index.html +++ b/src/controllerSoftware/templates/index.html @@ -76,6 +76,20 @@ +
Center: (x, y)
+Area: 0
+