Commit 6f1d2d7f authored by Andy Regensky's avatar Andy Regensky
Browse files

Implement fisheye image overlay including arrow key navigation

parent b17fd617
......@@ -56,6 +56,10 @@ class MainViewModel(QObject):
self.uwc_sign = None
self.updateProjections()
# Fisheye background image
self._fisheye_images = []
self._current_fisheye_idx = 0
@property
def sensor_dimensions_valid(self):
return np.isclose(self.sensor_size_px[0]/self.sensor_size_mm[0],
......@@ -252,3 +256,22 @@ class MainViewModel(QObject):
self.block_ctr_pym = block_ctr_pym
self.block_ctr_pxm = block_ctr_pxm
self.didChange.emit()
def setFisheyeImages(self, images):
self._fisheye_images = images
self._current_fisheye_idx = 0
self.didChange.emit()
def nextFisheyeImage(self):
self._current_fisheye_idx += 1
self.didChange.emit()
def previousFisheyeImage(self):
self._current_fisheye_idx -= 1
self.didChange.emit()
@property
def currentFisheyeImage(self):
if len(self._fisheye_images) == 0:
return None
return self._fisheye_images[self._current_fisheye_idx % len(self._fisheye_images)]
from PySide2.QtWidgets import *
from PySide2.QtCore import Qt
import fishui.widgets as widgets
from fishui.MainViewModel import MainViewModel
......@@ -13,15 +14,19 @@ class MainWindow(QMainWindow):
self.distortionWidget = widgets.DistortionVisualizationWidget(self, self.viewModel)
# layout
splitter = QSplitter()
splitter = QSplitter(self)
splitter.addWidget(self.propertiesWidget)
splitter.addWidget(self.distortionWidget)
splitter.setHandleWidth(2)
splitter.setChildrenCollapsible(False)
splitter.setStyleSheet("QSplitter:handle { background-color: gray; }")
# widget = QWidget()
# widget.setLayout(layout)
self.setCentralWidget(splitter)
self.setFocus()
self.show()
def keyPressEvent(self, event):
if event.key() == Qt.Key_Right:
self.viewModel.nextFisheyeImage()
elif event.key() == Qt.Key_Left:
self.viewModel.previousFisheyeImage()
......@@ -2,7 +2,7 @@ from PySide2.QtWidgets import QWidget, QGridLayout, QLabel, QGraphicsBlurEffect,
from PySide2.QtCore import Qt, Slot
from fishui.MainViewModel import MainViewModel
from fishui.widgets.AspectRatioWidget import AspectRatioWidget
from fishui.widgets.FisheyeBlockWidget import FisheyeBlockWidget
from fishui.widgets.FisheyeWidget import FisheyeWidget
from fishui.widgets.PerspectiveBlockWidget import PerspectiveBlockWidget
......@@ -20,7 +20,7 @@ class DistortionVisualizationWidget(QWidget):
self.fisheyeLabel.setStyleSheet("font-weight: bold; font-size: 16px")
self.fisheyeLabel.setAlignment(Qt.AlignCenter)
self.fisheyeLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
self.fisheyeBlockWidget = AspectRatioWidget(FisheyeBlockWidget(self, viewModel), self)
self.fisheyeWidget = AspectRatioWidget(FisheyeWidget(self, viewModel), self)
# Perspective visualization
self.perspectiveLabel = QLabel(self)
......@@ -35,11 +35,12 @@ class DistortionVisualizationWidget(QWidget):
perspective_label_width = self.perspectiveLabel.sizeHint().width()
min_width_constraint = max(fisheye_label_width, perspective_label_width)
self.fisheyeLabel.setMinimumWidth(min_width_constraint)
self.perspectiveLabel.setMinimumWidth(min_width_constraint)
# Layout
layout = QGridLayout(self)
layout.addWidget(self.fisheyeLabel, 0, 0)
layout.addWidget(self.fisheyeBlockWidget, 1, 0)
layout.addWidget(self.fisheyeWidget, 1, 0)
layout.addWidget(self.perspectiveLabel, 0, 1)
layout.addWidget(self.perspectiveBlockWidget, 1, 1)
......@@ -68,15 +69,15 @@ class DistortionVisualizationWidget(QWidget):
if self.viewModel.sensor_dimensions_valid:
self.overlay.setVisible(False)
self.fisheyeLabel.setGraphicsEffect(None)
self.fisheyeBlockWidget.setGraphicsEffect(None)
self.fisheyeWidget.setGraphicsEffect(None)
self.perspectiveLabel.setGraphicsEffect(None)
self.perspectiveBlockWidget.setGraphicsEffect(None)
aspect_ratio = self.viewModel.sensor_size_px[0]/self.viewModel.sensor_size_px[1]
self.fisheyeBlockWidget.setAspectRatio(aspect_ratio)
self.fisheyeWidget.setAspectRatio(aspect_ratio)
self.perspectiveBlockWidget.setAspectRatio(aspect_ratio)
else:
self.overlay.setVisible(True)
self.fisheyeLabel.setGraphicsEffect(QGraphicsBlurEffect(self))
self.fisheyeBlockWidget.setGraphicsEffect(QGraphicsBlurEffect(self))
self.fisheyeWidget.setGraphicsEffect(QGraphicsBlurEffect(self))
self.perspectiveLabel.setGraphicsEffect(QGraphicsBlurEffect(self))
self.perspectiveBlockWidget.setGraphicsEffect(QGraphicsBlurEffect(self))
import sys
from PySide2.QtGui import QPainter, QColor, QPainterPath, QPen, QPalette, QPolygonF, QImage
from PySide2.QtWidgets import QWidget, QApplication, QMenu, QAction, QFileDialog
from PySide2.QtCore import QSize, Qt, QPointF, QRect, QRectF, Slot
from fishui.MainViewModel import MainViewModel
class FisheyeBackgroundWidget(QWidget):
def __init__(self, parent, viewModel: MainViewModel):
super().__init__(parent)
self.viewModel = viewModel
self.viewModel.didChange.connect(self.repaint)
self.show()
def sizeHint(self):
return QSize(400, 400)
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
painter.setWindow(QRect(0,
0,
self.viewModel.sensor_size_px[0],
self.viewModel.sensor_size_px[1]))
painter.setRenderHint(QPainter.Antialiasing)
painter.fillRect(painter.window(), QColor(255, 255, 255))
self.drawImage(painter)
self.drawFisheyeBoundary(painter)
painter.end()
def drawImage(self, painter):
image_file = self.viewModel.currentFisheyeImage
if image_file is None:
return
image = QImage(image_file)
rect = QRectF(0,
0,
self.viewModel.sensor_size_px[0],
self.viewModel.sensor_size_px[1])
painter.drawImage(rect, image, rect)
def drawFisheyeBoundary(self, painter):
pen = QPen()
pen.setColor(QColor(0, 0, 0))
pen.setWidth(painter.window().width()/200)
painter.setPen(pen)
painter.drawEllipse(
QRect(
self.viewModel.center[0] - self.viewModel.fov_180_radius,
self.viewModel.center[1] - self.viewModel.fov_180_radius,
2 * self.viewModel.fov_180_radius,
2 * self.viewModel.fov_180_radius
)
)
def contextMenuEvent(self, event):
menu = QMenu(self)
openAct = QAction("Open", self)
openAct.setStatusTip("Open a background image")
openAct.triggered.connect(self.openImage)
menu.addAction(openAct)
menu.exec_(event.globalPos())
@Slot()
def openImage(self):
image_files = QFileDialog.getOpenFileNames(self,
"Open images",
".",
"Images (*.png *.jpg)")[0]
self.viewModel.setFisheyeImages(image_files)
......@@ -19,7 +19,6 @@ class FisheyeBlockWidget(QWidget):
self.initialOrigin = None
self.initialMouse = None
# self.setMinimumSize(QSize(300, 300))
self.show()
@Slot()
......@@ -45,25 +44,9 @@ class FisheyeBlockWidget(QWidget):
self.viewModel.sensor_size_px[0],
self.viewModel.sensor_size_px[1]))
painter.setRenderHint(QPainter.Antialiasing)
painter.fillRect(painter.window(), QColor(255, 255, 255))
self.drawFisheyeBoundary(event, painter)
self.drawPolygons(event, painter)
painter.end()
def drawFisheyeBoundary(self, event, painter):
pen = QPen()
pen.setColor(QColor(0, 0, 0))
pen.setWidth(painter.window().width()/200)
painter.setPen(pen)
painter.drawEllipse(
QRect(
self.viewModel.center[0] - self.viewModel.fov_180_radius,
self.viewModel.center[1] - self.viewModel.fov_180_radius,
2 * self.viewModel.fov_180_radius,
2 * self.viewModel.fov_180_radius
)
)
def drawPolygons(self, event, painter):
orange = QColor(255, 127, 14)
blue = QColor(31, 119, 180)
......@@ -79,8 +62,9 @@ class FisheyeBlockWidget(QWidget):
painter.drawPolygon(self.fisheyePolygon)
def mousePressEvent(self, event):
self.initialOrigin = self.viewModel.origin
self.initialMouse = event.pos()
if event.button() == Qt.LeftButton:
self.initialOrigin = self.viewModel.origin
self.initialMouse = event.pos()
def mouseMoveEvent(self, event):
if self.initialMouse is not None:
......@@ -91,5 +75,6 @@ class FisheyeBlockWidget(QWidget):
self.viewModel.setOrigin(origin)
def mouseReleaseEvent(self, event):
self.initialOrigin = None
self.initialMouse = None
if event.button() == Qt.LeftButton:
self.initialOrigin = None
self.initialMouse = None
from PySide2.QtWidgets import QWidget, QGridLayout, QLabel, QGraphicsBlurEffect, QSizePolicy
from PySide2.QtCore import Qt, Slot, QSize
from fishui.MainViewModel import MainViewModel
from fishui.widgets.FisheyeBackgroundWidget import FisheyeBackgroundWidget
from fishui.widgets.FisheyeBlockWidget import FisheyeBlockWidget
# TODO: Overlaying widgets using QWidget leads to repainting all widgets if child widget is updated. Use QGraphics...?
class FisheyeWidget(QWidget):
def __init__(self, parent, viewModel: MainViewModel):
super().__init__(parent)
self.fisheyeBackgroundWidget = FisheyeBackgroundWidget(self, viewModel)
self.fisheyeBlockWidget = FisheyeBlockWidget(self, viewModel)
self.show()
def sizeHint(self):
return QSize(400, 400)
def resizeEvent(self, event):
w = event.size().width()
h = event.size().height()
self.fisheyeBackgroundWidget.setGeometry(0, 0, w, h)
self.fisheyeBlockWidget.setGeometry(0, 0, w, h)
def contextMenuEvent(self, event):
self.fisheyeBackgroundWidget.contextMenuEvent(event)
......@@ -96,9 +96,10 @@ class PerspectiveBlockWidget(QWidget):
painter.drawPolygon(self.controlPointMovedPolygon)
def mousePressEvent(self, event):
self.initialMV0 = self.viewModel.motion_vector_cp0
self.initialMV1 = self.viewModel.motion_vector_cp1
self.initialMouse = event.pos()
if event.button() == Qt.LeftButton:
self.initialMV0 = self.viewModel.motion_vector_cp0
self.initialMV1 = self.viewModel.motion_vector_cp1
self.initialMouse = event.pos()
def mouseMoveEvent(self, event):
if self.initialMouse is not None:
......@@ -115,6 +116,7 @@ class PerspectiveBlockWidget(QWidget):
self.viewModel.setMotionVectorCP0(motion_vector)
def mouseReleaseEvent(self, event):
self.initialMV0 = None
self.initialMV1 = None
self.initialMouse = None
if event.button() == Qt.LeftButton:
self.initialMV0 = None
self.initialMV1 = None
self.initialMouse = None
......@@ -221,7 +221,6 @@ class PropertiesWidget(QWidget):
"Open calibration data (.txt)",
".",
"Text files (""*.json)")[0]
try:
self.viewModel.setProjection(projection, calib_file)
except (ValueError, FileNotFoundError): # Errors if calib_file is invalid
......
from .AspectRatioWidget import AspectRatioWidget
from .FisheyeBackgroundWidget import FisheyeBackgroundWidget
from .FisheyeBlockWidget import FisheyeBlockWidget
from .FisheyeWidget import FisheyeWidget
from .PerspectiveBlockWidget import PerspectiveBlockWidget
from .DistortionVisualizationWidget import DistortionVisualizationWidget
from .PropertiesWidget import PropertiesWidget
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