Commit 10a9ca43 authored by Matt Clarkson's avatar Matt Clarkson

Issue #1: Merge in scikit-surgeryvideolag.

parent 16d4a974
......@@ -3,4 +3,3 @@ omit =
./sksurgeryvideoutils/_version.py
./sksurgeryvideoutils/__init__.py
./sksurgeryvideoutils/__main__.py
./sksurgeryvideoutils/ui/sksurgeryvideoutils_command_line.py
......@@ -4,3 +4,7 @@
# doc/requirements.rst
numpy
six
opencv-contrib-python
--extra-index-url http://download.qt.io/snapshots/ci/pyside/5.9/latest/ --trusted-host download.qt.io
PySide2
scikit-surgeryimage
......@@ -19,7 +19,7 @@ setup(
long_description_content_type='text/x-rst',
url='https://weisslab.cs.ucl.ac.uk/WEISS/SoftwareRepositories/SNAPPY/scikit-surgeryvideoutils',
author='Matt Clarkson',
author_email='YOUR-EMAIL@ucl.ac.uk',
author_email='m.clarkson@ucl.ac.uk',
license='BSD-3 license',
classifiers=[
'Development Status :: 3 - Alpha',
......@@ -57,7 +57,7 @@ setup(
entry_points={
'console_scripts': [
'sksurgeryvideoutils=sksurgeryvideoutils.__main__:main',
'sksurgeryvidelag=sksurgeryvideoutils.ui.sksurgeryvideolag:main',
],
},
)
......@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
import sys
from sksurgeryvideoutils.ui.sksurgeryvideoutils_command_line import main
from sksurgeryvideoutils.ui.sksurgeryvideolag_command_line import main
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""scikit-surgeryvideoutils"""
import sys
if __name__ == "__main__" and not __package__:
# To allow the package's main function to be executed without the -m switch,
# i.e. "python sksurgeryvideoutils", we have to explicitly set the
# module name and append the parent directory to the sys.path (see PEP 366)
from os import path
__package__ = "sksurgeryvideoutils" # pylint: disable=redefined-builtin
sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
sys.path.append(path.dirname(path.dirname(__file__)))
# pylint: disable=wrong-import-position
from sksurgeryvideoutils.ui.sksurgeryvideoutils_command_line import main
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
# coding=utf-8
"""Command line processing"""
import argparse
from sksurgeryvideoutils import __version__
from sksurgeryvideoutils.ui.sksurgeryvideolag_demo import run_demo
def main(args=None):
"""Entry point for sksurgeryvideolag application"""
default_camera_interval = 33
default_screen_interval = 15
parser = argparse.ArgumentParser(description='sksurgeryvideolag')
parser.add_argument("-c", "--camera",
required=False,
default=0,
type=int,
help="Camera index")
parser.add_argument("-x", "--x_size",
required=False,
default=640,
type=int,
help="Image width")
parser.add_argument("-y", "--y_size",
required=False,
default=480,
type=int,
help="Image height")
parser.add_argument("-g", "--grab",
required=False,
default=default_camera_interval,
type=int,
help="Time interval for camera grab (ms) ["
+ str(default_camera_interval) + " ms]")
parser.add_argument("-m", "--milliseconds",
required=False,
default=default_screen_interval,
type=int,
help="Time interval for screen update (ms) ["
+ str(default_screen_interval) + " ms]")
parser.add_argument("-f", "--fullscreen",
required=False,
default=False,
type=bool,
help="Full screen")
version_string = __version__
friendly_version_string = version_string if version_string else 'unknown'
parser.add_argument(
"-v", "--version",
action='version',
version='scikit-surgeryvideolag version ' + friendly_version_string)
args = parser.parse_args(args)
run_demo(args.camera,
args.x_size,
args.y_size,
args.grab,
args.milliseconds,
args.fullscreen)
# coding=utf-8
""" Demo app, to show OpenCV video and PySide2 widgets together."""
import sys
import time
import ctypes
import six
import cv2
from PySide2 import QtCore, QtWidgets, QtGui
from PySide2.QtCore import Slot
# pylint: disable=too-many-instance-attributes
class DemoGui(QtWidgets.QWidget):
""" Demo GUI, with 2 QLabel side by side."""
def __init__(self, camera, width, height, grab, milliseconds):
super().__init__()
self.text = QtWidgets.QLabel("Hello World")
self.text.setAlignment(QtCore.Qt.AlignCenter)
self.font = QtGui.QFont()
self.font = self.text.font()
self.font.setBold(True)
self.text.setFont(self.font)
self.layout = QtWidgets.QHBoxLayout()
self.layout.addWidget(self.text)
if camera < 0:
self.cap = None
else:
self.cap = cv2.VideoCapture(camera) # pylint: disable=no-member
self.cap.set(3, width)
self.cap.set(4, height)
if not self.cap.isOpened():
raise ValueError("Unable to open camera:" + str(camera))
grabbed, self.frame = self.cap.read()
if not grabbed:
raise RuntimeError("Failed to grab first frame.")
if self.frame.shape[0] != height:
raise ValueError("Grabbed image has wrong number of rows:"
+ str(self.frame.shape[0]))
if self.frame.shape[1] != width:
raise ValueError("Grabbed image has wrong number of columns:"
+ str(self.frame.shape[1]))
self.image_label = QtWidgets.QLabel("Hello Image")
self.image_label.setAlignment(QtCore.Qt.AlignCenter)
self.layout.addWidget(self.image_label)
self.setLayout(self.layout)
self.grab = QtCore.QTimer()
self.grab.setInterval(grab)
self.clock = QtCore.QTimer()
self.clock.setInterval(milliseconds)
# pylint: disable=maybe-no-member
self.clock.timeout.connect(self.update_clock)
self.elapsed = QtCore.QElapsedTimer()
self.number_frames = 0
self.total_time_to_grab = 0.0
self.total_time_to_decode = 0.0
self.total_time_to_display = 0.0
self.elapsed.start()
self.clock.start()
if camera >= 0:
# pylint: disable=maybe-no-member
self.grab.timeout.connect(self.update_image)
self.grab.start()
else:
self.setMinimumSize(400, 400)
def __del__(self):
six.print_("Exiting after " + str(self.elapsed.elapsed()) + " ms.")
if self.number_frames > 0:
six.print_("grab="
+ str(1000 * self.total_time_to_grab
/ self.number_frames)
+ " ms, decode="
+ str(1000 * self.total_time_to_decode
/ self.number_frames)
+ " ms, display="
+ str(1000 * self.total_time_to_display
/ self.number_frames)
+ " ms."
)
@Slot()
def update_clock(self):
"""Updates the millisecond value."""
self.font.setPointSize(self.height() // 6)
self.text.setFont(self.font)
self.text.setText(str(self.elapsed.elapsed()))
@Slot()
def update_image(self):
"""Updates the image."""
# Force updating the GUI to get the latest possible time.
self.text.update()
start_time = time.time()
# Then grab image
grabbed = self.cap.grab()
if not grabbed:
raise RuntimeError("Failed to grab frame number:"
+ str(self.number_frames))
# Independently work out the total time grabbing.
grab_time = time.time()
self.total_time_to_grab += (grab_time - start_time)
# Then decode image
self.cap.retrieve(self.frame)
# OpenCV does BGR, Qt wants RGB
# pylint: disable=no-member
rgb_frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
# Independently work out the total time decoding.
decode_time = time.time()
self.total_time_to_decode += (decode_time - grab_time)
# Workaround for memory leak.
# See: https://bugreports.qt.io/browse/PYSIDE-140
# Should be fixed properly in PySide 5.11.3
# Once we upgrade to 5.11.3, take out the hack on
# the ch and rcount variables, and just create qimage
# and then instantiate pixmap from qimage.
pointer_to_buffer = ctypes.c_char.from_buffer(rgb_frame, 0)
rcount = ctypes.c_long.from_address(id(pointer_to_buffer)).value
qimage = QtGui.QImage(pointer_to_buffer,
rgb_frame.shape[1],
rgb_frame.shape[0],
QtGui.QImage.Format_RGB888)
if sys.version[0] == '3':
ctypes.c_long.from_address(id(pointer_to_buffer)).value = rcount
pixmap = QtGui.QPixmap.fromImage(qimage)
self.image_label.setPixmap(pixmap)
# Independently work out the total time displaying.
display_time = time.time()
self.total_time_to_display += (display_time - decode_time)
self.number_frames += 1
def run_demo(camera, width, height, grab, clock, fullscreen):
""" Prints command line args, and launches main screen."""
six.print_("Camera:" + str(camera))
six.print_(" Width:" + str(width))
six.print_(" Height:" + str(height))
six.print_("Timer interval for grab:" + str(grab))
six.print_("Timer interval for clock:" + str(clock))
app = QtWidgets.QApplication([])
widget = DemoGui(camera, width, height, grab, clock)
if fullscreen:
widget.showFullScreen()
widget.show()
return sys.exit(app.exec_())
# coding=utf-8
"""Command line processing"""
import argparse
from sksurgeryvideoutils import __version__
from sksurgeryvideoutils.ui.sksurgeryvideoutils_demo import run_demo
def main(args=None):
"""Entry point for scikit-surgeryvideoutils application"""
parser = argparse.ArgumentParser(description='scikit-surgeryvideoutils')
parser.add_argument("-t", "--text",
required=False,
default="This is scikit-surgeryvideoutils",
type=str,
help="Text to display")
parser.add_argument("--console", required=False,
action='store_true',
help="If set, scikit-surgeryvideoutils "
"will not bring up a graphical user interface")
version_string = __version__
friendly_version_string = version_string if version_string else 'unknown'
parser.add_argument(
"-v", "--version",
action='version',
version='scikit-surgeryvideoutils version ' + friendly_version_string)
args = parser.parse_args(args)
run_demo(args.console, args.text)
# coding=utf-8
"""Hello world demo module"""
import six
def run_demo(console, text):
"""Show message"""
six.print_(text)
if not console:
from tkinter import Tk, Label
root = Tk()
label = Label(root, text=text)
label.pack()
#uncomment root.mainloop() to enter tk main loop.
#Delete any unit tests covering this section first
#though as they will not complete.
#root.mainloop()
return True
......@@ -32,7 +32,7 @@ unsafe-load-any-extension=no
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
extension-pkg-whitelist=numpy
extension-pkg-whitelist=numpy,PySide2,cv2
# Allow optimization of some AST trees. This will activate a peephole AST
# optimizer, which will apply various small optimizations. For instance, it can
......
# coding=utf-8
"""sksurgeryvideolag tests"""
from sksurgeryvideoutils.ui.sksurgeryvideolag_demo import run_demo
def test_sksurgeryvideolag():
# placeholder for now.
assert True
# coding=utf-8
"""scikit-surgeryvideoutils tests"""
from sksurgeryvideoutils.ui.sksurgeryvideoutils_demo import run_demo
import six
# Pytest style
def test_using_pytest_sksurgeryvideoutils():
console = True
assert run_demo(console, "Hello World") == True
# Disable this test if root.mainloop is uncommented in
# run_demo()
def test_using_pytest_cookienewwithgitinit_withTK():
try:
import tkinter
try:
console=False
assert run_demo(console, "Hello World") == True
except tkinter.TclError:
six.print_("Got TCL error, probably no DISPLAY set, that's OK.")
assert True
except:
six.print_("Got another error (not TCL), that's not OK.")
assert False
except ModuleNotFoundError:
six.print_("Got module not found on tkinter, please check your python installation")
#we're not trying to test whether we have tkinter so this is ok
assert True
except ImportError:
six.print_("Got import error on tkinter, please check your python installation")
#we're not trying to test whether we have tkinter so this is ok
assert True
except:
assert False
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