@ -4,7 +4,7 @@ Display any array, webcam, or video file.
|
|||||||
display is a function that displays these in their own windows.
|
display is a function that displays these in their own windows.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = "0.7.4"
|
__version__ = "0.7.5"
|
||||||
|
|
||||||
from .window.subscriber_windows import display, breakpoint_display, read_updates
|
from .window.subscriber_windows import display, breakpoint_display, read_updates
|
||||||
from .frame.frame_publishing import publish_updates_zero_mq, publish_updates_ros
|
from .frame.frame_publishing import publish_updates_zero_mq, publish_updates_ros
|
||||||
|
@ -7,10 +7,13 @@ import cv2
|
|||||||
import warnings
|
import warnings
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
using_pyv4l2cam = False
|
||||||
try:
|
try:
|
||||||
if sys.platform == "linux":
|
if sys.platform == "linux":
|
||||||
from PyV4L2Cam.camera import Camera as pyv4lcamera
|
from PyV4L2Cam.camera import Camera as pyv4lcamera
|
||||||
from PyV4L2Cam.controls import ControlIDs as pyv4lcontrolids
|
from PyV4L2Cam.controls import ControlIDs as pyv4lcontrolids
|
||||||
|
|
||||||
|
using_pyv4l2cam = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
warnings.warn("Could not import PyV4L2Cam on linux. Camera capture will be slow.")
|
warnings.warn("Could not import PyV4L2Cam on linux. Camera capture will be slow.")
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
@ -28,6 +31,25 @@ from typing import Union, Tuple, Optional, Dict, Any, List, Callable
|
|||||||
FrameCallable = Callable[[np.ndarray], Optional[np.ndarray]]
|
FrameCallable = Callable[[np.ndarray], Optional[np.ndarray]]
|
||||||
|
|
||||||
|
|
||||||
|
def _v4l2_convert_mjpeg(mjpeg: bytes) -> Optional[np.ndarray]:
|
||||||
|
# Thanks: https://stackoverflow.com/a/21844162
|
||||||
|
a = mjpeg.find(b"\xff\xd8")
|
||||||
|
b = mjpeg.find(b"\xff\xd9")
|
||||||
|
|
||||||
|
if a == -1 or b == -1:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
jpg = mjpeg[a : b + 2]
|
||||||
|
frame = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
|
||||||
|
return frame
|
||||||
|
|
||||||
|
|
||||||
|
def _v4l2_convert_rgb24(rgb24: bytes, width: int, height: int) -> Optional[np.ndarray]:
|
||||||
|
nparr = np.frombuffer(rgb24, np.uint8)
|
||||||
|
np_frame = nparr.reshape((height, width, 3))
|
||||||
|
return np_frame
|
||||||
|
|
||||||
|
|
||||||
def pub_cam_loop_pyv4l2(
|
def pub_cam_loop_pyv4l2(
|
||||||
cam_id: Union[int, str, np.ndarray],
|
cam_id: Union[int, str, np.ndarray],
|
||||||
request_size: Tuple[int, int] = (-1, -1),
|
request_size: Tuple[int, int] = (-1, -1),
|
||||||
@ -75,18 +97,20 @@ def pub_cam_loop_pyv4l2(
|
|||||||
now = time.time()
|
now = time.time()
|
||||||
frame_bytes = cam.get_frame() # type: bytes
|
frame_bytes = cam.get_frame() # type: bytes
|
||||||
|
|
||||||
# Thanks: https://stackoverflow.com/a/21844162
|
if cam.pixel_format == "MJPEG":
|
||||||
a = frame_bytes.find(b"\xff\xd8")
|
nd_frame = _v4l2_convert_mjpeg(frame_bytes)
|
||||||
b = frame_bytes.find(b"\xff\xd9")
|
elif cam.pixel_format == "RGB24":
|
||||||
|
nd_frame = _v4l2_convert_rgb24(frame_bytes, cam.width, cam.height)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError(f"{cam.pixel_format} format not supported.")
|
||||||
|
|
||||||
if a == -1 or b == -1:
|
if nd_frame is not None:
|
||||||
|
subscriber_dictionary.CV_CAMS_DICT[name].frame_pub.publish(nd_frame)
|
||||||
|
else:
|
||||||
cam.close()
|
cam.close()
|
||||||
subscriber_dictionary.CV_CAMS_DICT[name].status_pub.publish("failed")
|
subscriber_dictionary.CV_CAMS_DICT[name].status_pub.publish("failed")
|
||||||
return False
|
return False
|
||||||
else:
|
|
||||||
jpg = frame_bytes[a : b + 2]
|
|
||||||
frame = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
|
|
||||||
subscriber_dictionary.CV_CAMS_DICT[name].frame_pub.publish(frame)
|
|
||||||
msg = sub.get()
|
msg = sub.get()
|
||||||
sub.release()
|
sub.release()
|
||||||
|
|
||||||
@ -170,8 +194,13 @@ def pub_cam_thread(
|
|||||||
) -> threading.Thread:
|
) -> threading.Thread:
|
||||||
"""Run pub_cam_loop in a new thread. Starts on creation."""
|
"""Run pub_cam_loop in a new thread. Starts on creation."""
|
||||||
|
|
||||||
if sys.platform == "linux" and (
|
if (
|
||||||
isinstance(cam_id, int) or (isinstance(cam_id, str) and "/dev/video" in cam_id)
|
sys.platform == "linux"
|
||||||
|
and using_pyv4l2cam
|
||||||
|
and (
|
||||||
|
isinstance(cam_id, int)
|
||||||
|
or (isinstance(cam_id, str) and "/dev/video" in cam_id)
|
||||||
|
)
|
||||||
):
|
):
|
||||||
pub_cam_loop = pub_cam_loop_pyv4l2
|
pub_cam_loop = pub_cam_loop_pyv4l2
|
||||||
else:
|
else:
|
||||||
|
@ -8,7 +8,7 @@ def profile_reading(total_seconds=5):
|
|||||||
t_init = t01 = time.time()
|
t_init = t01 = time.time()
|
||||||
times = []
|
times = []
|
||||||
started = False
|
started = False
|
||||||
for up in display(0, size=(9999, 9999)):
|
for up in display(0, size=(1, 1)):
|
||||||
if up:
|
if up:
|
||||||
t1 = time.time()
|
t1 = time.time()
|
||||||
if started:
|
if started:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = 'displayarray'
|
name = 'displayarray'
|
||||||
version = '0.7.4'
|
version = '0.7.5'
|
||||||
description = 'Tool for displaying numpy arrays.'
|
description = 'Tool for displaying numpy arrays.'
|
||||||
authors = ['SimLeek <simulator.leek@gmail.com>']
|
authors = ['SimLeek <simulator.leek@gmail.com>']
|
||||||
license = 'MIT'
|
license = 'MIT'
|
||||||
@ -9,7 +9,7 @@ repository = "https://github.com/simleek/displayarray"
|
|||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.6"
|
python = "^3.6"
|
||||||
opencv_python = "3.4.5.20"
|
opencv_python = "^4*"
|
||||||
docopt = "0.6.2"
|
docopt = "0.6.2"
|
||||||
numpy = "1.16.1"
|
numpy = "1.16.1"
|
||||||
localpubsub = "0.0.4"
|
localpubsub = "0.0.4"
|
||||||
|
Reference in New Issue
Block a user