Commit 0b37b55e authored by Thomas Dowrick's avatar Thomas Dowrick

Issue #11: Update Viewers to implement record button, after changes to TimestampVideoWriter

parent cb3a78ad
Pipeline #1782 failed with stages
in 14 minutes and 1 second
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys import sys
import logging
from sksurgerydavinci.ui.sksurgerydavinci_command_line import main from sksurgerydavinci.ui.sksurgerydavinci_command_line import main
......
...@@ -3,9 +3,8 @@ ...@@ -3,9 +3,8 @@
# pylint: disable=fixme, attribute-defined-outside-init # pylint: disable=fixme, attribute-defined-outside-init
# pylint: disable=no-name-in-module, too-many-public-methods # pylint: disable=no-name-in-module, too-many-public-methods
import os import os
import datetime
import cv2 from PySide2.QtCore import Qt, Signal
from PySide2.QtCore import Qt, Signal, QTimer
from PySide2.QtWidgets import QSlider, QVBoxLayout, QHBoxLayout, \ from PySide2.QtWidgets import QSlider, QVBoxLayout, QHBoxLayout, \
QLabel, QPushButton, \ QLabel, QPushButton, \
QMessageBox, QApplication, \ QMessageBox, QApplication, \
...@@ -47,9 +46,6 @@ class UI(QWidget): ...@@ -47,9 +46,6 @@ class UI(QWidget):
self.screen = None self.screen = None
self.screen_geometry = None self.screen_geometry = None
self.timer = QTimer()
self.timer.timeout.connect(self.save_frame_to_video)
self.show() self.show()
def add_vtk_overlay_window(self, overlay_window): def add_vtk_overlay_window(self, overlay_window):
...@@ -88,12 +84,11 @@ class UI(QWidget): ...@@ -88,12 +84,11 @@ class UI(QWidget):
self.other_buttons.addWidget(self.exit_button) self.other_buttons.addWidget(self.exit_button)
def add_record_buttons(self): def add_record_buttons(self):
""" Add buttons to take screenshot and record video. """ """ Add buttons to take screenshot and record video.
Button callbacks should be implmenented in the Viewer class. """
self.screenshot_button = QPushButton('Take screenshot') self.screenshot_button = QPushButton('Take screenshot')
self.screenshot_button.clicked.connect(self.on_screenshot_clicked)
self.record_button = QPushButton('Record video') self.record_button = QPushButton('Record video')
self.record_button.clicked.connect(self.on_record_start_clicked)
self.record_buttons_layout = QHBoxLayout() self.record_buttons_layout = QHBoxLayout()
self.record_buttons_layout.addWidget(self.screenshot_button) self.record_buttons_layout.addWidget(self.screenshot_button)
...@@ -114,34 +109,6 @@ class UI(QWidget): ...@@ -114,34 +109,6 @@ class UI(QWidget):
self.exit_signal.emit() self.exit_signal.emit()
QApplication.exit() QApplication.exit()
def on_screenshot_clicked(self):
""" Save a screenshot to disk, using date and time as filename """
fname = datetime.datetime.now().strftime("%Y-%m-%d.%H-%M-%S") + '.png'
self.vtk_overlay.save_scene_to_file(fname)
def on_record_start_clicked(self):
""" Start recording a video using current time as filename """
self.record_button.setText("Stop recording")
self.record_button.clicked.connect(self.on_record_stop_clicked)
fname = datetime.datetime.now().strftime("%Y-%m-%d.%H-%M-%S") + '.avi'
fps = 20
width, height = self.vtk_overlay.width(), self.vtk_overlay.height()
self.video_out = cv2.VideoWriter(fname, cv2.VideoWriter_fourcc('M','J','P','G'), fps, (width, height))
self.timer.start(1000/fps)
def on_record_stop_clicked(self):
""" Stop recording data to file and restore button settings. """
self.timer.stop()
self.video_out.release()
self.record_button.setText("Record video")
self.record_button.clicked.connect(self.on_record_start_clicked)
def save_frame_to_video(self):
self.video_out.write(self.vtk_overlay.convert_scene_to_numpy_array())
def add_vtk_models(self, vtk_models): def add_vtk_models(self, vtk_models):
""" Add VTK models to the UI and vtk_overlay_window """ Add VTK models to the UI and vtk_overlay_window
......
...@@ -7,7 +7,6 @@ import logging ...@@ -7,7 +7,6 @@ import logging
from sksurgerydavinci import __version__ from sksurgerydavinci import __version__
from sksurgerydavinci.ui.sksurgerydavinci_demo import run_demo from sksurgerydavinci.ui.sksurgerydavinci_demo import run_demo
logging.basicConfig(level=logging.INFO)
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
def main(args=None): def main(args=None):
...@@ -47,6 +46,13 @@ def main(args=None): ...@@ -47,6 +46,13 @@ def main(args=None):
type=str, type=str,
help="Location of directory containing models to be loaded") help="Location of directory containing models to be loaded")
parser.add_argument(
"-l",
"--logging_debug",
action="store_true",
help="Enable Debug level logging"
)
version_string = __version__ version_string = __version__
friendly_version_string = version_string if version_string else 'unknown' friendly_version_string = version_string if version_string else 'unknown'
parser.add_argument( parser.add_argument(
...@@ -56,6 +62,13 @@ def main(args=None): ...@@ -56,6 +62,13 @@ def main(args=None):
args = parser.parse_args(args) args = parser.parse_args(args)
if args.logging_debug:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)
print(args) print(args)
run_demo(args) run_demo(args)
\ No newline at end of file
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
"""Hello world demo module""" """Hello world demo module"""
import sys import sys
import vtk import vtk
from PySide2.QtWidgets import QApplication from PySide2.QtWidgets import QApplication
from sksurgeryvtk.models.vtk_surface_model_directory_loader \ from sksurgeryvtk.models.vtk_surface_model_directory_loader \
......
""" Mono/Stereo viewing windows for Ardavinci""" """ Mono/Stereo viewing windows for Ardavinci"""
import logging import logging
import datetime
from PySide2 import QtWidgets from PySide2 import QtWidgets
from sksurgeryvtk.widgets.vtk_overlay_window import VTKOverlayWindow from sksurgeryvtk.widgets.vtk_overlay_window import VTKOverlayWindow
from sksurgeryutils.common_overlay_apps import OverlayOnVideoFeed from sksurgeryutils.common_overlay_apps import OverlayOnVideoFeed
...@@ -55,6 +56,8 @@ class MonoViewer(QtWidgets.QWidget): ...@@ -55,6 +56,8 @@ class MonoViewer(QtWidgets.QWidget):
self.overlay_window = OverlayOnVideoFeed(video_source) self.overlay_window = OverlayOnVideoFeed(video_source)
self.UI = UI(self.overlay_window) self.UI = UI(self.overlay_window)
self.UI.screenshot_button.clicked.connect(self.on_screenshot_clicked)
self.UI.record_button.clicked.connect(self.on_record_start_clicked)
def add_vtk_models(self, models): def add_vtk_models(self, models):
""" """
...@@ -68,6 +71,25 @@ class MonoViewer(QtWidgets.QWidget): ...@@ -68,6 +71,25 @@ class MonoViewer(QtWidgets.QWidget):
""" Start the viewer. """ """ Start the viewer. """
self.overlay_window.start() self.overlay_window.start()
def on_screenshot_clicked(self):
""" Save a screenshot to disk, using date and time as filename """
fname = datetime.datetime.now().strftime("%Y-%m-%d.%H-%M-%S") + '.png'
self.overlay_window.vtk_overlay_window.save_scene_to_file(fname)
def on_record_start_clicked(self):
""" Start recording a video using current time as filename """
self.UI.record_button.setText("Stop recording")
self.UI.record_button.clicked.disconnect()
self.UI.record_button.clicked.connect(self.on_record_stop_clicked)
self.overlay_window.on_record_start()
def on_record_stop_clicked(self):
""" Stop recording data to file and restore button settings. """
self.overlay_window.on_record_stop()
self.UI.record_button.setText("Record video")
self.UI.record_button.clicked.disconnect()
self.UI.record_button.clicked.connect(self.on_record_start_clicked)
class StereoViewerBase(QtWidgets.QWidget): class StereoViewerBase(QtWidgets.QWidget):
...@@ -75,10 +97,21 @@ class StereoViewerBase(QtWidgets.QWidget): ...@@ -75,10 +97,21 @@ class StereoViewerBase(QtWidgets.QWidget):
Base class for StereoViewers. Base class for StereoViewers.
""" """
def __init__(self):
# Left/right stereo views and UI view.
# These are overridden in subclasses.
# Included here for clarity.
super().__init__()
self.UI = None
self.left_view = None
self.right_view = None
def setup_widgets(self): def setup_widgets(self):
""" Sync the cameras between the widgets, """ Sync the cameras between the widgets,
and setup Qt output signal. """ and setup Qt output signal. """
self.UI = UI(self.ui_window) self.UI = UI(self.ui_window)
self.UI.screenshot_button.clicked.connect(self.on_screenshot_clicked)
self.UI.record_button.clicked.connect(self.on_record_start_clicked)
self.left_overlay = self.left_view.vtk_overlay_window self.left_overlay = self.left_view.vtk_overlay_window
self.right_overlay = self.right_view.vtk_overlay_window self.right_overlay = self.right_view.vtk_overlay_window
...@@ -193,6 +226,38 @@ class StereoViewerBase(QtWidgets.QWidget): ...@@ -193,6 +226,38 @@ class StereoViewerBase(QtWidgets.QWidget):
self.right_view.stop() self.right_view.stop()
self.ui_window.stop() self.ui_window.stop()
def on_screenshot_clicked(self):
""" Save a screenshot to disk, using date and time as filename """
fname_base = datetime.datetime.now().strftime("%Y-%m-%d.%H-%M-%S")
fname_left = fname_base + '-LEFT.png'
fname_right = fname_base + '-RIGHT.png'
self.left_overlay.save_scene_to_file(fname_left)
self.right_overlay.save_scene_to_file(fname_right)
def on_record_start_clicked(self):
""" Start recording a video. In the MockStereoViewer we only need
to record the 'left' input, as the right view is a duplicate of the
left.
The proper StereoViewer class extends this method to also record
the right view."""
self.video_fname_base = 'outputs/' + \
datetime.datetime.now().strftime("%Y-%m-%d.%H-%M-%S")
fname_left = self.video_fname_base + '-LEFT.avi'
self.left_view.output_filename = fname_left
self.left_view.on_record_start()
self.UI.record_button.setText("Stop recording")
self.UI.record_button.clicked.disconnect()
self.UI.record_button.clicked.connect(self.on_record_stop_clicked)
def on_record_stop_clicked(self):
""" Stop recording data to file and restore button settings. """
self.left_view.on_record_stop()
self.UI.record_button.setText("Record video")
self.UI.record_button.clicked.disconnect()
self.UI.record_button.clicked.connect(self.on_record_start_clicked)
class MockStereoViewer(StereoViewerBase): class MockStereoViewer(StereoViewerBase):
""" """
...@@ -218,6 +283,7 @@ class MockStereoViewer(StereoViewerBase): ...@@ -218,6 +283,7 @@ class MockStereoViewer(StereoViewerBase):
self.setup_widgets() self.setup_widgets()
class StereoViewer(StereoViewerBase): class StereoViewer(StereoViewerBase):
"""Stereo viewer, creates an overlay window for each """Stereo viewer, creates an overlay window for each
video input. video input.
...@@ -239,3 +305,16 @@ class StereoViewer(StereoViewerBase): ...@@ -239,3 +305,16 @@ class StereoViewer(StereoViewerBase):
self.ui_window.set_source_window(self.left_view) self.ui_window.set_source_window(self.left_view)
self.setup_widgets() self.setup_widgets()
def on_record_start_clicked(self):
""" Start recording a video using current time as filename """
super().on_record_start_clicked()
fname_right = self.video_fname_base + '-RIGHT.avi'
self.right_view.output_filename = fname_right
self.right_view.on_record_start()
def on_record_stop_clicked(self):
""" Stop recording data to file and restore button settings. """
self.right_view.on_record_stop()
super().on_record_stop_clicked()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment