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:
simleek
2020-04-29 13:21:12 -07:00
parent 18335d6260
commit 337dd5f276
4 changed files with 102 additions and 75 deletions

View File

@ -4,7 +4,7 @@ Display any array, webcam, or video file.
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 .frame.frame_publishing import publish_updates_zero_mq, publish_updates_ros

View File

@ -35,7 +35,7 @@ class SubscriberWindows(object):
"""Create the array displaying window."""
self.source_names: List[Union[str, int]] = []
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.window_names: List[str] = []
self.input_cams: List[str] = []
@ -117,71 +117,98 @@ class SubscriberWindows(object):
mousey = MouseEvent(event, x, y, flags, param)
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."""
if isinstance(frames, Exception):
raise frames
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, ids)
else:
if len(self.window_names) <= win_num:
self.add_window(str(win_num))
cv2.imshow(
self.window_names[win_num] + " (press ESC to quit)", frames[f]
)
win_num += 1
if isinstance(frames, dict):
for f_name, f in frames.items():
for i in range(len(f)):
# detect nested:
if (
isinstance(f[i], (list, tuple))
or f[i].dtype.num == 17
or (
len(f[i].shape) != 2
and (len(f[i].shape) != 3 or f[i].shape[-1] != 3)
)
):
win_num = self.display_frames(
f[i], win_num, prepend_name=f"{f_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)", 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
def __check_too_many_channels(self):
for f in range(len(self.frames)):
if isinstance(self.frames[f], Exception):
raise self.frames[f]
if (
isinstance(self.frames[f], np.ndarray)
and self.frames[f].shape[-1] not in [1, 3]
and len(self.frames[f].shape) != 2
):
print(
f"Too many channels in output. (Got {self.frames[f].shape[-1]} instead of 1 or 3.) "
f"Frame selection callback added."
)
print(
"Ctrl+scroll to change first channel.\n"
"Shift+scroll to change second channel.\n"
"Alt+scroll to change third channel."
)
sel = SelectChannels()
sel.enable_mouse_control()
sel.mouse_print_channels = True
self.callbacks.append(sel)
for fr in range(len(self.frames)):
self.frames[fr] = self.callbacks[-1](self.frames[fr])
break
for f_name, f in self.frames.items():
for i in range(len(f)):
if isinstance(f[i], Exception):
raise f[i]
if (
isinstance(f[i], np.ndarray)
and f[i].shape[-1] not in [1, 3]
and len(f[i].shape) != 2
):
print(
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"
"Shift+scroll to change second channel.\n"
"Alt+scroll to change third channel."
)
sel = SelectChannels()
sel.enable_mouse_control()
sel.mouse_print_channels = True
self.callbacks.append(sel)
for fr in range(len(f)):
f[fr] = self.callbacks[-1](f[fr])
break
def update_frames(self):
"""Update the windows with the newest data for all frames."""
self.frames = []
self.frames = {}
for i in range(len(self.input_vid_global_names)):
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.frames.append(self.FRAME_DICT[self.input_vid_global_names[i]])
if isinstance(self.frames, np.ndarray) and len(self.frames.shape) <= 3:
self.frames = [self.frames]
if self.input_vid_global_names[i] not in self.frames.keys():
self.frames[self.input_vid_global_names[i]] = []
self.frames[self.input_vid_global_names[i]].append(
self.FRAME_DICT[self.input_vid_global_names[i]]
)
if len(self.callbacks) > 0:
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:
self.frames[-1] = frame
self.frames[self.input_vid_global_names[i]][-1] = frame
if not self.silent:
self.__check_too_many_channels()
self.FRAME_DICT[self.input_vid_global_names[i]] = NoData()

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = 'displayarray'
version = '0.7.5'
version = '1.0.0'
description = 'Tool for displaying numpy arrays.'
authors = ['SimLeek <simulator.leek@gmail.com>']
license = 'MIT'

View File

@ -193,7 +193,7 @@ def test_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)
@ -219,7 +219,7 @@ def test_update_frames_callback():
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(cb2.mock_calls[0].args[0] == frame2)
mock_imshow.assert_has_calls(
@ -260,7 +260,7 @@ def test_update_frames_too_many_channels():
assert isinstance(sw.callbacks[-1], SelectChannels)
assert sw.callbacks[-1].mouse_control is not None
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():
@ -275,47 +275,47 @@ def test_update_frames_nested():
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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)))