mirror of
https://github.com/EyeTrackVR/EyeTrackVR.git
synced 2025-11-04 14:39:42 +08:00
Seaweed Serial cam support
This commit is contained in:
parent
fdb4e7eb1f
commit
65f6aa7181
@ -3,7 +3,8 @@ from enum import Enum
|
|||||||
import threading
|
import threading
|
||||||
import queue
|
import queue
|
||||||
import cv2
|
import cv2
|
||||||
|
import serial
|
||||||
|
import time
|
||||||
WAIT_TIME = 0.1
|
WAIT_TIME = 0.1
|
||||||
|
|
||||||
|
|
||||||
@ -47,22 +48,31 @@ class Camera:
|
|||||||
# If things aren't open, retry until they are. Don't let read requests come in any earlier
|
# If things aren't open, retry until they are. Don't let read requests come in any earlier
|
||||||
# than this, otherwise we can deadlock ourselves.
|
# than this, otherwise we can deadlock ourselves.
|
||||||
if (
|
if (
|
||||||
self.config.capture_source != None and self.config.capture_source != ""
|
self.config.capture_source != None and self.config.capture_source != ""
|
||||||
):
|
):
|
||||||
if (
|
if (self.current_capture_source[:3] == "COM"):
|
||||||
self.wired_camera is None
|
if (
|
||||||
or not self.wired_camera.isOpened()
|
self.serial_connection is None
|
||||||
or self.camera_status == CameraState.DISCONNECTED
|
or self.camera_status == CameraState.DISCONNECTED
|
||||||
or self.config.capture_source != self.current_capture_source
|
or self.config.capture_source != self.current_capture_source
|
||||||
):
|
):
|
||||||
print(self.error_message.format(self.config.capture_source))
|
port = self.current_capture_source
|
||||||
# This requires a wait, otherwise we can error and possible screw up the camera
|
self.start_serial_connection(port)
|
||||||
# firmware. Fickle things.
|
else:
|
||||||
if self.cancellation_event.wait(WAIT_TIME):
|
if (
|
||||||
return
|
self.wired_camera is None
|
||||||
self.current_capture_source = self.config.capture_source
|
or not self.wired_camera.isOpened()
|
||||||
self.wired_camera = cv2.VideoCapture(self.current_capture_source)
|
or self.camera_status == CameraState.DISCONNECTED
|
||||||
should_push = False
|
or self.config.capture_source != self.current_capture_source
|
||||||
|
):
|
||||||
|
print(self.error_message.format(self.config.capture_source))
|
||||||
|
# This requires a wait, otherwise we can error and possible screw up the camera
|
||||||
|
# firmware. Fickle things.
|
||||||
|
if self.cancellation_event.wait(WAIT_TIME):
|
||||||
|
return
|
||||||
|
self.current_capture_source = self.config.capture_source
|
||||||
|
self.wired_camera = cv2.VideoCapture(self.current_capture_source)
|
||||||
|
should_push = False
|
||||||
else:
|
else:
|
||||||
# We don't have a capture source to try yet, wait for one to show up in the GUI.
|
# We don't have a capture source to try yet, wait for one to show up in the GUI.
|
||||||
if self.cancellation_event.wait(WAIT_TIME):
|
if self.cancellation_event.wait(WAIT_TIME):
|
||||||
@ -73,8 +83,11 @@ class Camera:
|
|||||||
# python event as a contextless, resettable one-shot channel.
|
# python event as a contextless, resettable one-shot channel.
|
||||||
if should_push and not self.capture_event.wait(timeout=0.02):
|
if should_push and not self.capture_event.wait(timeout=0.02):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.get_wired_camera_picture(should_push)
|
if (self.current_capture_source[:3] == "COM"):
|
||||||
|
self.get_serial_camera_picture(should_push)
|
||||||
|
else:
|
||||||
|
self.get_wired_camera_picture(should_push)
|
||||||
if not should_push:
|
if not should_push:
|
||||||
# if we get all the way down here, consider ourselves connected
|
# if we get all the way down here, consider ourselves connected
|
||||||
self.camera_status = CameraState.CONNECTED
|
self.camera_status = CameraState.CONNECTED
|
||||||
@ -90,10 +103,74 @@ class Camera:
|
|||||||
if should_push:
|
if should_push:
|
||||||
self.push_image_to_queue(image, frame_number, fps)
|
self.push_image_to_queue(image, frame_number, fps)
|
||||||
except:
|
except:
|
||||||
print("\033[91m[WARN] Capture source problem, assuming camera disconnected, waiting for reconnect...\033[0m")
|
print(
|
||||||
|
"Capture source problem, assuming camera disconnected, waiting for reconnect."
|
||||||
|
)
|
||||||
self.camera_status = CameraState.DISCONNECTED
|
self.camera_status = CameraState.DISCONNECTED
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_serial_camera_picture(self, should_push):
|
||||||
|
start = time.time()
|
||||||
|
try:
|
||||||
|
bytes = self.serialByteBuffer
|
||||||
|
if self.serial_connection.in_waiting:
|
||||||
|
bytes += self.serial_connection.read(4096) # Read in initial bytes
|
||||||
|
|
||||||
|
a = bytes.find(b'\xff\xd8') # Find start byte for jpeg image
|
||||||
|
b = bytes.find(b'\xff\xd9') # Fine end byte for jpeg image
|
||||||
|
|
||||||
|
# If the first found end byte is before the start byte, keep reading in serial
|
||||||
|
# data and discarding the old data until the start byte is before the end byte
|
||||||
|
while a > b:
|
||||||
|
bytes = bytes[a:]
|
||||||
|
a = bytes.find(b'\xff\xd8')
|
||||||
|
b = bytes.find(b'\xff\xd9')
|
||||||
|
if a == -1 or b == -1:
|
||||||
|
bytes += self.serial_connection.read(2048)
|
||||||
|
|
||||||
|
if a != -1 and b != -1: # If there is jpeg data
|
||||||
|
jpg = bytes[a:b+2] # Create the string of bytes for the current jpeg
|
||||||
|
bytes = bytes[b+2:] # Clear the buffer until the end of our current jpeg
|
||||||
|
self.serialByteBuffer = bytes
|
||||||
|
|
||||||
|
if jpg:
|
||||||
|
# Create jpeg frame from byte string
|
||||||
|
image = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
|
||||||
|
if image is None:
|
||||||
|
print("image not found")
|
||||||
|
else:
|
||||||
|
self.frame_number = self.frame_number + 1
|
||||||
|
fps = 1/(time.time() - start) # Calculate FPS - This could use a better implementation
|
||||||
|
if should_push:
|
||||||
|
self.push_image_to_queue(image, self.frame_number, fps)
|
||||||
|
|
||||||
|
except UnboundLocalError as ex:
|
||||||
|
print(ex)
|
||||||
|
except Exception as ex:
|
||||||
|
print(ex.__class__)
|
||||||
|
print(
|
||||||
|
"Serial capture source problem, assuming camera disconnected, waiting for reconnect.")
|
||||||
|
self.camera_status = CameraState.DISCONNECTED
|
||||||
|
pass
|
||||||
|
|
||||||
|
def start_serial_connection(self, port):
|
||||||
|
try:
|
||||||
|
serialInst = serial.Serial()
|
||||||
|
print("setting baudrate")
|
||||||
|
serialInst.baudrate = 2000000
|
||||||
|
print("baudrate set")
|
||||||
|
|
||||||
|
serialInst.port = port
|
||||||
|
serialInst.setDTR(False)
|
||||||
|
serialInst.setRTS(False)
|
||||||
|
|
||||||
|
serialInst.open()
|
||||||
|
print("port open")
|
||||||
|
self.serial_connection = serialInst
|
||||||
|
self.camera_status = CameraState.CONNECTED
|
||||||
|
except:
|
||||||
|
print("Error Opening Serial Port")
|
||||||
|
|
||||||
def push_image_to_queue(self, image, frame_number, fps):
|
def push_image_to_queue(self, image, frame_number, fps):
|
||||||
# If there's backpressure, just yell. We really shouldn't have this unless we start getting
|
# If there's backpressure, just yell. We really shouldn't have this unless we start getting
|
||||||
# some sort of capture event conflict though.
|
# some sort of capture event conflict though.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user