frames are now stored and returned as dictionaries with source name as key. Set to version 1.0.0 because this is a major breaking change.
This commit is contained in:
@ -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.5"
|
__version__ = "1.0.0"
|
||||||
|
|
||||||
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
|
||||||
|
@ -35,7 +35,7 @@ class SubscriberWindows(object):
|
|||||||
"""Create the array displaying window."""
|
"""Create the array displaying window."""
|
||||||
self.source_names: List[Union[str, int]] = []
|
self.source_names: List[Union[str, int]] = []
|
||||||
self.close_threads: Optional[List[Thread]] = []
|
self.close_threads: Optional[List[Thread]] = []
|
||||||
self.frames: List[np.ndarray] = []
|
self.frames: Dict[Union[str, int], np.ndarray] = {}
|
||||||
self.input_vid_global_names: List[str] = []
|
self.input_vid_global_names: List[str] = []
|
||||||
self.window_names: List[str] = []
|
self.window_names: List[str] = []
|
||||||
self.input_cams: List[str] = []
|
self.input_cams: List[str] = []
|
||||||
@ -117,71 +117,98 @@ class SubscriberWindows(object):
|
|||||||
mousey = MouseEvent(event, x, y, flags, param)
|
mousey = MouseEvent(event, x, y, flags, param)
|
||||||
window_commands.mouse_pub.publish(mousey)
|
window_commands.mouse_pub.publish(mousey)
|
||||||
|
|
||||||
def display_frames(self, frames, win_num=0, ids=None):
|
def display_frames(self, frames, win_num=0, prepend_name=""):
|
||||||
"""Display a list of frames on multiple windows."""
|
"""Display a list of frames on multiple windows."""
|
||||||
if isinstance(frames, Exception):
|
if isinstance(frames, Exception):
|
||||||
raise frames
|
raise frames
|
||||||
for f in range(len(frames)):
|
if isinstance(frames, dict):
|
||||||
# detect nested:
|
for f_name, f in frames.items():
|
||||||
if (
|
for i in range(len(f)):
|
||||||
isinstance(frames[f], (list, tuple))
|
# detect nested:
|
||||||
or frames[f].dtype.num == 17
|
if (
|
||||||
or (
|
isinstance(f[i], (list, tuple))
|
||||||
len(frames[f].shape) != 2
|
or f[i].dtype.num == 17
|
||||||
and (len(frames[f].shape) != 3 or frames[f].shape[-1] != 3)
|
or (
|
||||||
)
|
len(f[i].shape) != 2
|
||||||
):
|
and (len(f[i].shape) != 3 or f[i].shape[-1] != 3)
|
||||||
win_num = self.display_frames(frames[f], win_num, ids)
|
)
|
||||||
else:
|
):
|
||||||
if len(self.window_names) <= win_num:
|
win_num = self.display_frames(
|
||||||
self.add_window(str(win_num))
|
f[i], win_num, prepend_name=f"{f_name} - "
|
||||||
cv2.imshow(
|
)
|
||||||
self.window_names[win_num] + " (press ESC to quit)", frames[f]
|
else:
|
||||||
)
|
if len(self.window_names) <= win_num:
|
||||||
win_num += 1
|
self.add_window(f"{prepend_name}{win_num}")
|
||||||
|
cv2.imshow(
|
||||||
|
self.window_names[win_num] + " (press ESC to quit)", f[i]
|
||||||
|
)
|
||||||
|
win_num += 1
|
||||||
|
else:
|
||||||
|
for f in range(len(frames)):
|
||||||
|
# detect nested:
|
||||||
|
if (
|
||||||
|
isinstance(frames[f], (list, tuple))
|
||||||
|
or frames[f].dtype.num == 17
|
||||||
|
or (
|
||||||
|
len(frames[f].shape) != 2
|
||||||
|
and (len(frames[f].shape) != 3 or frames[f].shape[-1] != 3)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
win_num = self.display_frames(frames[f], win_num, prepend_name)
|
||||||
|
else:
|
||||||
|
if len(self.window_names) <= win_num:
|
||||||
|
self.add_window(f"{prepend_name} {win_num}")
|
||||||
|
cv2.imshow(
|
||||||
|
self.window_names[win_num] + " (press ESC to quit)", frames[f]
|
||||||
|
)
|
||||||
|
win_num += 1
|
||||||
return win_num
|
return win_num
|
||||||
|
|
||||||
def __check_too_many_channels(self):
|
def __check_too_many_channels(self):
|
||||||
for f in range(len(self.frames)):
|
for f_name, f in self.frames.items():
|
||||||
if isinstance(self.frames[f], Exception):
|
for i in range(len(f)):
|
||||||
raise self.frames[f]
|
if isinstance(f[i], Exception):
|
||||||
if (
|
raise f[i]
|
||||||
isinstance(self.frames[f], np.ndarray)
|
if (
|
||||||
and self.frames[f].shape[-1] not in [1, 3]
|
isinstance(f[i], np.ndarray)
|
||||||
and len(self.frames[f].shape) != 2
|
and f[i].shape[-1] not in [1, 3]
|
||||||
):
|
and len(f[i].shape) != 2
|
||||||
print(
|
):
|
||||||
f"Too many channels in output. (Got {self.frames[f].shape[-1]} instead of 1 or 3.) "
|
print(
|
||||||
f"Frame selection callback added."
|
f"Too many channels in output. (Got {f[i].shape[-1]} instead of 1 or 3.) "
|
||||||
)
|
f"Frame selection callback added."
|
||||||
print(
|
)
|
||||||
"Ctrl+scroll to change first channel.\n"
|
print(
|
||||||
"Shift+scroll to change second channel.\n"
|
"Ctrl+scroll to change first channel.\n"
|
||||||
"Alt+scroll to change third channel."
|
"Shift+scroll to change second channel.\n"
|
||||||
)
|
"Alt+scroll to change third channel."
|
||||||
sel = SelectChannels()
|
)
|
||||||
sel.enable_mouse_control()
|
sel = SelectChannels()
|
||||||
sel.mouse_print_channels = True
|
sel.enable_mouse_control()
|
||||||
self.callbacks.append(sel)
|
sel.mouse_print_channels = True
|
||||||
for fr in range(len(self.frames)):
|
self.callbacks.append(sel)
|
||||||
self.frames[fr] = self.callbacks[-1](self.frames[fr])
|
for fr in range(len(f)):
|
||||||
break
|
f[fr] = self.callbacks[-1](f[fr])
|
||||||
|
break
|
||||||
|
|
||||||
def update_frames(self):
|
def update_frames(self):
|
||||||
"""Update the windows with the newest data for all frames."""
|
"""Update the windows with the newest data for all frames."""
|
||||||
self.frames = []
|
self.frames = {}
|
||||||
|
|
||||||
for i in range(len(self.input_vid_global_names)):
|
for i in range(len(self.input_vid_global_names)):
|
||||||
if self.input_vid_global_names[i] in self.FRAME_DICT and not isinstance(
|
if self.input_vid_global_names[i] in self.FRAME_DICT and not isinstance(
|
||||||
self.FRAME_DICT[self.input_vid_global_names[i]], NoData
|
self.FRAME_DICT[self.input_vid_global_names[i]], NoData
|
||||||
):
|
):
|
||||||
self.frames.append(self.FRAME_DICT[self.input_vid_global_names[i]])
|
if self.input_vid_global_names[i] not in self.frames.keys():
|
||||||
if isinstance(self.frames, np.ndarray) and len(self.frames.shape) <= 3:
|
self.frames[self.input_vid_global_names[i]] = []
|
||||||
self.frames = [self.frames]
|
self.frames[self.input_vid_global_names[i]].append(
|
||||||
|
self.FRAME_DICT[self.input_vid_global_names[i]]
|
||||||
|
)
|
||||||
if len(self.callbacks) > 0:
|
if len(self.callbacks) > 0:
|
||||||
for c in self.callbacks:
|
for c in self.callbacks:
|
||||||
frame = c(self.frames[-1])
|
frame = c(self.frames[self.input_vid_global_names[i]][-1])
|
||||||
if frame is not None:
|
if frame is not None:
|
||||||
self.frames[-1] = frame
|
self.frames[self.input_vid_global_names[i]][-1] = frame
|
||||||
if not self.silent:
|
if not self.silent:
|
||||||
self.__check_too_many_channels()
|
self.__check_too_many_channels()
|
||||||
self.FRAME_DICT[self.input_vid_global_names[i]] = NoData()
|
self.FRAME_DICT[self.input_vid_global_names[i]] = NoData()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = 'displayarray'
|
name = 'displayarray'
|
||||||
version = '0.7.5'
|
version = '1.0.0'
|
||||||
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'
|
||||||
|
@ -193,7 +193,7 @@ def test_update_frames():
|
|||||||
|
|
||||||
sw.update_frames()
|
sw.update_frames()
|
||||||
|
|
||||||
assert sw.frames == [frame]
|
assert sw.frames == {"0": [frame]}
|
||||||
mock_imshow.assert_called_once_with("displayarray (press ESC to quit)", frame)
|
mock_imshow.assert_called_once_with("displayarray (press ESC to quit)", frame)
|
||||||
|
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ def test_update_frames_callback():
|
|||||||
|
|
||||||
sw.update_frames()
|
sw.update_frames()
|
||||||
|
|
||||||
assert sw.frames == [frame3, frame3]
|
assert sw.frames == {"0": [frame3], "1": [frame3]}
|
||||||
assert np.all(cb.mock_calls[0].args[0] == frame)
|
assert np.all(cb.mock_calls[0].args[0] == frame)
|
||||||
assert np.all(cb2.mock_calls[0].args[0] == frame2)
|
assert np.all(cb2.mock_calls[0].args[0] == frame2)
|
||||||
mock_imshow.assert_has_calls(
|
mock_imshow.assert_has_calls(
|
||||||
@ -260,7 +260,7 @@ def test_update_frames_too_many_channels():
|
|||||||
assert isinstance(sw.callbacks[-1], SelectChannels)
|
assert isinstance(sw.callbacks[-1], SelectChannels)
|
||||||
assert sw.callbacks[-1].mouse_control is not None
|
assert sw.callbacks[-1].mouse_control is not None
|
||||||
assert sw.callbacks[-1].mouse_print_channels is True
|
assert sw.callbacks[-1].mouse_print_channels is True
|
||||||
assert sw.frames[0].shape[-1] == 3
|
assert sw.frames["0"][0].shape[-1] == 3
|
||||||
|
|
||||||
|
|
||||||
def test_update_frames_nested():
|
def test_update_frames_nested():
|
||||||
@ -275,47 +275,47 @@ def test_update_frames_nested():
|
|||||||
|
|
||||||
sw.update_frames()
|
sw.update_frames()
|
||||||
|
|
||||||
assert np.all(sw.frames[0] == np.ones((20, 100, 100, 3)))
|
assert np.all(sw.frames["0"][0] == np.ones((20, 100, 100, 3)))
|
||||||
assert len(sw.frames) == 1
|
assert len(sw.frames) == 1
|
||||||
assert mock_imshow.mock_calls[0].args[0] == "displayarray (press ESC to quit)"
|
assert mock_imshow.mock_calls[0].args[0] == "displayarray (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[0].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[0].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[1].args[0] == "1 (press ESC to quit)"
|
assert mock_imshow.mock_calls[1].args[0] == "0 - 1 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[1].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[1].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[2].args[0] == "2 (press ESC to quit)"
|
assert mock_imshow.mock_calls[2].args[0] == "0 - 2 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[2].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[2].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[3].args[0] == "3 (press ESC to quit)"
|
assert mock_imshow.mock_calls[3].args[0] == "0 - 3 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[3].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[3].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[4].args[0] == "4 (press ESC to quit)"
|
assert mock_imshow.mock_calls[4].args[0] == "0 - 4 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[4].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[4].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[5].args[0] == "5 (press ESC to quit)"
|
assert mock_imshow.mock_calls[5].args[0] == "0 - 5 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[5].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[5].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[6].args[0] == "6 (press ESC to quit)"
|
assert mock_imshow.mock_calls[6].args[0] == "0 - 6 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[6].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[6].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[7].args[0] == "7 (press ESC to quit)"
|
assert mock_imshow.mock_calls[7].args[0] == "0 - 7 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[7].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[7].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[8].args[0] == "8 (press ESC to quit)"
|
assert mock_imshow.mock_calls[8].args[0] == "0 - 8 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[8].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[8].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[9].args[0] == "9 (press ESC to quit)"
|
assert mock_imshow.mock_calls[9].args[0] == "0 - 9 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[9].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[9].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[10].args[0] == "10 (press ESC to quit)"
|
assert mock_imshow.mock_calls[10].args[0] == "0 - 10 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[10].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[10].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[11].args[0] == "11 (press ESC to quit)"
|
assert mock_imshow.mock_calls[11].args[0] == "0 - 11 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[11].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[11].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[12].args[0] == "12 (press ESC to quit)"
|
assert mock_imshow.mock_calls[12].args[0] == "0 - 12 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[12].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[12].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[13].args[0] == "13 (press ESC to quit)"
|
assert mock_imshow.mock_calls[13].args[0] == "0 - 13 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[13].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[13].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[14].args[0] == "14 (press ESC to quit)"
|
assert mock_imshow.mock_calls[14].args[0] == "0 - 14 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[14].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[14].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[15].args[0] == "15 (press ESC to quit)"
|
assert mock_imshow.mock_calls[15].args[0] == "0 - 15 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[15].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[15].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[16].args[0] == "16 (press ESC to quit)"
|
assert mock_imshow.mock_calls[16].args[0] == "0 - 16 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[16].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[16].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[17].args[0] == "17 (press ESC to quit)"
|
assert mock_imshow.mock_calls[17].args[0] == "0 - 17 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[17].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[17].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[18].args[0] == "18 (press ESC to quit)"
|
assert mock_imshow.mock_calls[18].args[0] == "0 - 18 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[18].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[18].args[1] == np.ones((100, 100, 3)))
|
||||||
assert mock_imshow.mock_calls[19].args[0] == "19 (press ESC to quit)"
|
assert mock_imshow.mock_calls[19].args[0] == "0 - 19 (press ESC to quit)"
|
||||||
assert np.all(mock_imshow.mock_calls[19].args[1] == np.ones((100, 100, 3)))
|
assert np.all(mock_imshow.mock_calls[19].args[1] == np.ones((100, 100, 3)))
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user