Files
displayarray/cvpubsubs/webcam_pub/pub_cam.py

94 lines
3.2 KiB
Python

import threading
import time
import cv2
import numpy as np
from cvpubsubs.webcam_pub.camctrl import CamCtrl
from .np_cam import NpCam
if False:
from typing import Union, Tuple
def pub_cam_loop(cam_id, # type: Union[int, str]
request_size=(1280, 720), # type: Tuple[int, int]
high_speed=False, # type: bool
fps_limit=240 # type: float
): # type: (...)->bool
"""Publishes whichever camera you select to CVCams.<cam_id>.Vid
You can send a quit command 'quit' to CVCams.<cam_id>.Cmd
Status information, such as failure to open, will be posted to CVCams.<cam_id>.Status
:param high_speed: Selects mjpeg transferring, which most cameras seem to support, so speed isn't limited
:param fps_limit: Limits the frames per second.
:param cam_id: An integer representing which webcam to use, or a string representing a video file.
:param request_size: A tuple with width, then height, to request the video size.
:return: True if loop ended normally, False if it failed somehow.
"""
if isinstance(cam_id, (int, str)):
name = str(cam_id)
elif isinstance(cam_id, np.ndarray):
name = str(hash(str(cam_id)))
else:
raise TypeError("Only strings or ints representing cameras, or numpy arrays representing pictures supported.")
if isinstance(cam_id, (int, str)):
cam = cv2.VideoCapture(cam_id)
elif isinstance(cam_id, np.ndarray):
cam = NpCam(cam_id) # type: NpCam
else:
raise TypeError("Only strings or ints representing cameras, or numpy arrays representing pictures supported.")
CamCtrl.register_cam(name)
# cam.set(cv2.CAP_PROP_CONVERT_RGB, 0)
frame_counter = 0
sub = CamCtrl.cam_cmd_sub(name)
sub.return_on_no_data = ''
msg = ''
if high_speed:
cam.set(cv2.CAP_PROP_FOURCC, cv2.CAP_OPENCV_MJPEG)
cam.set(cv2.CAP_PROP_FRAME_WIDTH, request_size[0])
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, request_size[1])
if not cam.isOpened():
CamCtrl.cv_cams_dict[name].status_pub.publish("failed")
return False
now = time.time()
while msg != 'quit':
time.sleep(1. / (fps_limit - (time.time() - now)))
now = time.time()
(ret, frame) = cam.read() # type: Tuple[bool, np.ndarray ]
if ret is False or not isinstance(frame, np.ndarray):
cam.release()
CamCtrl.cv_cams_dict[name].status_pub.publish("failed")
return False
if cam.get(cv2.CAP_PROP_FRAME_COUNT) > 0:
frame_counter += 1
if frame_counter >= cam.get(cv2.CAP_PROP_FRAME_COUNT):
frame_counter = 0
cam = cv2.VideoCapture(cam_id)
CamCtrl.cv_cams_dict[name].frame_pub.publish(frame)
msg = sub.get()
sub.release()
cam.release()
return True
def pub_cam_thread(cam_id, # type: Union[int, str]
request_ize=(1280, 720), # type: Tuple[int, int]
high_speed=False, # type: bool
fps_limit=240 # type: float
):
# type: (...) -> threading.Thread
t = threading.Thread(target=pub_cam_loop, args=(cam_id, request_ize, high_speed, fps_limit))
t.start()
return t