Added high speed mode to cv pubsubs. Added files for pip. Fixed code to match PEP8.

This commit is contained in:
SimLeek
2018-01-27 14:26:52 -07:00
parent 28de026baf
commit 34fd3dcd0e
13 changed files with 98 additions and 62 deletions
+1 -1
View File
@@ -1 +1 @@
A simple pub-sub threaded cv webcam opener
A threaded PubSub OpenCV interface. Webcam and video feeds to multiple windows is supported.
+1 -1
View File
@@ -1,2 +1,2 @@
from .cv_webcam_pub import *
from .sub_win import sub_win_loop, frameDict
from .cv_window_sub import sub_win_loop, frame_dict
+2 -2
View File
@@ -1,5 +1,5 @@
from .listen_default import _listen_default
from .listen_default import listen_default
from .get_cam_ids import get_cam_ids
from .pub_cam import pub_cam_thread
from .frame_handler import frame_handler_thread
from .cam_ctrl import cam_ctrl
from .camctrl import CamCtrl
@@ -2,9 +2,10 @@ import pubsub
if False:
from typing import Union
class cam_ctrl:
class CamCtrl:
@staticmethod
def stop_cam(cam_id # type: Union[int, str]
):
pubsub.publish("cvcamhandlers." + str(cam_id) + ".cmd", 'q')
pubsub.publish("cvcamhandlers." + str(cam_id) + ".cmd", 'q')
+16 -12
View File
@@ -1,35 +1,39 @@
import pubsub
import numpy as np
import threading
from .listen_default import _listen_default
from .listen_default import listen_default
from .pub_cam import pub_cam_thread
if False:
from typing import Union, Tuple, Any, Callable
def frame_handler_loop(cam_id, # type: Union[int, str]
frame_handler, # type: Callable[[int, np.ndarray], Any]
frame_handler, # type: Callable[[np.ndarray, int], Any]
request_size=(1280, 720), # type: Tuple[int, int]
fps_limit = 60
high_speed=False, # type: bool
fps_limit=240 # type: float
):
t = pub_cam_thread(cam_id, request_size, fps_limit)
t = pub_cam_thread(cam_id, request_size, high_speed, fps_limit)
sub_cam = pubsub.subscribe("cvcams." + str(cam_id) + ".vid")
sub_owner = pubsub.subscribe("cvcamhandlers." + str(cam_id) + ".cmd")
msg_owner = ''
while msg_owner != 'q':
frame = _listen_default(sub_cam, timeout=.1) # type: np.ndarray
frame = listen_default(sub_cam, timeout=.1) # type: np.ndarray
if frame is not None:
frame = frame[0]
frame_handler(frame, cam_id)
msg_owner = _listen_default(sub_owner, block=False, empty='')
msg_owner = listen_default(sub_owner, block=False, empty='')
pubsub.publish("cvcams." + str(cam_id) + ".cmd", 'q')
t.join()
def frame_handler_thread(cam_id, # type: Union[int, str]
frame_handler, # type: Callable[[int, np.ndarray], Any]
request_size=(1280, 720), # type: Tuple[int, int]
fps_limit = 60
): # type: (...) -> threading.Thread
t = threading.Thread(target=frame_handler_loop, args=(cam_id, frame_handler, request_size, fps_limit))
frame_handler, # type: Callable[[int, np.ndarray], Any]
request_size=(1280, 720), # type: Tuple[int, int]
high_speed=False, # type: bool
fps_limit=240 # type: float
): # type: (...) -> threading.Thread
t = threading.Thread(target=frame_handler_loop, args=(cam_id, frame_handler, request_size, high_speed, fps_limit))
t.start()
return t
return t
-2
View File
@@ -14,5 +14,3 @@ def get_cam_ids(): # type: () -> List[int]
cam_list.append(len(cam_list))
return cam_list
+7 -6
View File
@@ -1,11 +1,12 @@
if False:
from typing import Any, Optional, queue
def _listen_default(sub, # type: queue
block=True, # type: bool
timeout=None, # type: Optional[float]
empty=None # type: Any
): # type: (...)->Any
def listen_default(sub, # type: queue
block=True, # type: bool
timeout=None, # type: Optional[float]
empty=None # type: Any
): # type: (...)->Any
try:
msg = (sub.listen(block=block, timeout=timeout))
try:
@@ -14,4 +15,4 @@ def _listen_default(sub, # type: queue
msg = empty
except queue.Empty:
msg = empty
return msg
return msg
+29 -21
View File
@@ -3,57 +3,65 @@ import cv2
import numpy as np
import time
import threading
from .listen_default import _listen_default
from .listen_default import listen_default
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]
fps_limit = 60
): # type: (...)->bool
"""
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 'q' to cvcams.<cam_id>.cmd
Status information, such as failure to open, will be posted to cvcams.<cam_id>.status
:param cam_id:
:param request_size:
:return:
: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.
"""
sub = pubsub.subscribe("cvcams." + str(cam_id) + ".cmd")
msg = ''
cam = cv2.VideoCapture(cam_id)
#cam.set(cv2.CAP_PROP_CONVERT_RGB, 0)
# cam.set(cv2.CAP_PROP_CONVERT_RGB, 0)
if high_speed:
cam.set(cv2.CAP_PROP_FOURCC, cv2.CAP_OPENCV_MJPEG)
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])
#cam.set(cv2.CAP_PROP_FPS, fps_limit) Breaks FPS with Windows. WTF guys...
if not cam.isOpened():
pubsub.publish("cvcams." + str(cam_id) + ".status", "failed")
return False
#now = time.time()
now = time.time()
while msg != 'q':
#time.sleep(1. / (fps_limit - (time.time() - now)))
#now = time.time()
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()
pubsub.publish("cvcams." + str(cam_id) + ".status", "failed")
return False
pubsub.publish("cvcams." + str(cam_id) + ".vid", (frame,))
msg = _listen_default(sub, block=False, empty='')
msg = listen_default(sub, block=False, empty='')
pass
cam.release()
return True
def pub_cam_thread(cam_id, # type: Union[int, str]
request_ize=(1280, 720), # type: Tuple[int, int]
fps_limit = 60
):
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, fps_limit))
t = threading.Thread(target=pub_cam_loop, args=(cam_id, request_ize, high_speed, fps_limit))
t.start()
return t
+7 -7
View File
@@ -1,11 +1,11 @@
import cv2
from .cv_webcam_pub.cam_ctrl import cam_ctrl
from .cv_webcam_pub.camctrl import CamCtrl
if False:
from typing import List
cvWindows = []
frameDict = {}
frame_dict = {}
# todo: figure out how to get the red x button to work. Try: https://stackoverflow.com/a/37881722/782170
@@ -16,20 +16,20 @@ def sub_win_loop(*,
input_cams=(0,)
):
global cvWindows
global frameDict
global frame_dict
while True:
for i in range(len(input_vid_global_names)):
if input_vid_global_names[i] in frameDict and frameDict[input_vid_global_names[i]] is not None:
if input_vid_global_names[i] in frame_dict and frame_dict[input_vid_global_names[i]] is not None:
if callbacks[i % len(callbacks)] is not None:
frames = callbacks[i % len(callbacks)](frameDict[input_vid_global_names[i]])
frames = callbacks[i % len(callbacks)](frame_dict[input_vid_global_names[i]])
else:
frames = frameDict[input_vid_global_names[i]]
frames = frame_dict[input_vid_global_names[i]]
for f in range(len(frames)):
cv2.imshow(names[f % len(names)], frames[f])
if cv2.waitKey(1) & 0xFF == ord('q'):
for name in names:
cv2.destroyWindow(name)
for c in input_cams:
cam_ctrl.stop_cam(c)
CamCtrl.stop_cam(c)
return
+2
View File
@@ -0,0 +1,2 @@
[metadata]
description-file = README.md
+13
View File
@@ -0,0 +1,13 @@
from distutils.core import setup
setup(
name= 'cv_pubsubs',
packages = ['cv_webcam_pub', 'cv_window_sub'],
version='0.1',
description='Pubsub interface for Python OpenCV',
author='Josh Miklos',
author_email='Simulator.Leek@gmail.com',
url='https://github.com/SimLeek/cv_pubsubs',
download_url='*',
keywords=['OpenCV', 'PubSub']
)
+5 -2
View File
@@ -9,9 +9,12 @@ class TestFrameHandler(ut.TestCase):
def test_frame_handler(frame, cam_id):
if self.i == 200:
w.cam_ctrl.stop_cam(cam_id)
w.CamCtrl.stop_cam(cam_id)
if self.i % 100 == 0:
print(frame.shape)
self.i += 1
w.frame_handler_thread(0, test_frame_handler)
w.frame_handler_thread(0, test_frame_handler,
request_size=(1280, 720),
high_speed=True,
fps_limit=240)
+12 -6
View File
@@ -1,17 +1,23 @@
import unittest as ut
import cv_pubsubs.cv_webcam_pub as w
from cv_pubsubs.sub_win import frameDict, sub_win_loop
from cv_pubsubs.cv_window_sub import frame_dict, sub_win_loop
class TestSubWin(ut.TestCase):
def test_sub(self):
def camHandler(frame, camId):
frameDict[str(camId) + "Frame"] = (frame,frame)
def cam_handler(frame, cam_id):
frame_dict[str(cam_id) + "Frame"] = (frame, frame)
t = w.frame_handler_thread(0, camHandler)
t = w.frame_handler_thread(0, cam_handler,
request_size=(1280, 720),
high_speed=True,
fps_limit=240
)
sub_win_loop(names=['cammy', 'cammy2'], input_vid_global_names=[str(0)+"Frame"])
sub_win_loop(names=['cammy', 'cammy2'],
input_vid_global_names=[str(0) + "Frame"])
w.cam_ctrl.stop_cam(0)
w.CamCtrl.stop_cam(0)
t.join()