forked from ImSwitch/ImSwitch
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
80e5fdf
commit a9a9571
Showing
11 changed files
with
308 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
imswitch/imcontrol/controller/controllers/PixelCalibrationController.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import json | ||
import os | ||
|
||
import numpy as np | ||
import time | ||
import tifffile as tif | ||
import threading | ||
from datetime import datetime | ||
import cv2 | ||
|
||
from imswitch.imcommon.model import dirtools, initLogger, APIExport | ||
from ..basecontrollers import ImConWidgetController | ||
from imswitch.imcommon.framework import Signal, Thread, Worker, Mutex, Timer | ||
import time | ||
|
||
from ..basecontrollers import LiveUpdatedController | ||
|
||
#import NanoImagingPack as nip | ||
|
||
class PixelCalibrationController(LiveUpdatedController): | ||
"""Linked to PixelCalibrationWidget.""" | ||
|
||
sigImageReceived = Signal() | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
self._logger = initLogger(self) | ||
|
||
# Connect PixelCalibrationWidget signals | ||
#self._widget.PixelCalibrationLabelInfo.clicked.connect() | ||
self._widget.PixelCalibrationSnapPreviewButton.clicked.connect(self.snapPreview) | ||
self._widget.PixelCalibrationUndoButton.clicked.connect(self.undoSelection) | ||
self._widget.PixelCalibrationCalibrateButton.clicked.connect(self.startPixelCalibration) | ||
self.pixelSize=0 | ||
# select detectors | ||
allDetectorNames = self._master.detectorsManager.getAllDeviceNames() | ||
self.detector = self._master.detectorsManager[allDetectorNames[0]] | ||
|
||
|
||
def undoSelection(self): | ||
# recover the previous selection | ||
self._widget.canvas.undoSelection() | ||
|
||
def snapPreview(self): | ||
self._logger.info("Snap preview...") | ||
self.previewImage = self.detector.getLatestFrame() | ||
self._widget.canvas.setImage(self.previewImage) | ||
|
||
def startPixelCalibration(self): | ||
# initilaze setup | ||
# this is not a thread! | ||
self.pixelSize = self._widget.getPixelSize() | ||
self._widget.setInformationLabel(str(self.pixelSize)+" µm") | ||
|
||
|
||
|
||
|
||
# Copyright (C) 2020-2021 ImSwitch developers | ||
# This file is part of ImSwitch. | ||
# | ||
# ImSwitch is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# ImSwitch is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
imswitch/imcontrol/model/managers/PixelCalibrationManager.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import enum | ||
import glob | ||
import cv2 | ||
import os | ||
|
||
import numpy as np | ||
from PIL import Image | ||
from scipy import signal as sg | ||
|
||
from imswitch.imcommon.framework import Signal, SignalInterface | ||
from imswitch.imcommon.model import initLogger | ||
|
||
|
||
class PixelCalibrationManager(SignalInterface): | ||
sigPixelCalibrationMaskUpdated = Signal(object) # (maskCombined) | ||
|
||
def __init__(self, PixelCalibrationInfo, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
self.__logger = initLogger(self) | ||
|
||
if PixelCalibrationInfo is None: | ||
return | ||
|
||
self.update() | ||
|
||
def update(self): | ||
return None #returnmask.image() | ||
|
||
# Copyright (C) 2020-2021 ImSwitch developers | ||
# This file is part of ImSwitch. | ||
# | ||
# ImSwitch is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# ImSwitch is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
178 changes: 178 additions & 0 deletions
178
imswitch/imcontrol/view/widgets/PixelCalibrationWidget.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
import numpy as np | ||
import pyqtgraph as pg | ||
import cv2 | ||
import copy | ||
from qtpy import QtCore, QtWidgets, QtGui, QtWidgets | ||
from PyQt5.QtGui import QPixmap, QImage | ||
|
||
import sys | ||
from PyQt5.QtWidgets import (QApplication, QLabel, QWidget) | ||
from PyQt5.QtGui import QPainter, QColor, QPen | ||
from PyQt5.QtCore import Qt | ||
from qtpy import QtCore, QtWidgets, QtGui, QtWidgets | ||
import cv2 | ||
import numpy as np | ||
import copy | ||
from PyQt5.QtGui import QPixmap, QImage | ||
|
||
|
||
|
||
|
||
from imswitch.imcontrol.view import guitools | ||
from .basewidgets import NapariHybridWidget | ||
|
||
|
||
|
||
class PixelCalibrationWidget(NapariHybridWidget): | ||
""" Widget containing PixelCalibration interface. """ | ||
|
||
def __post_init__(self): | ||
#super().__init__(*args, **kwargs) | ||
# initialize all GUI elements | ||
|
||
# Add Painter for drawing a line on pixels | ||
self.canvas = Canvas() | ||
|
||
# Snap Preview Button | ||
self.PixelCalibrationSnapPreviewButton = guitools.BetterPushButton('Snap Preview') | ||
self.PixelCalibrationSnapPreviewButton.setCheckable(False) | ||
|
||
# Undo Button | ||
self.PixelCalibrationUndoButton = guitools.BetterPushButton('Undo') | ||
self.PixelCalibrationUndoButton.setCheckable(False) | ||
|
||
# editable for entering pixelvalues | ||
self.PixelCalibrationLabelKnownDistance = QtWidgets.QLabel('Known Distance: (µm)') | ||
self.PixelCalibrationEditFileName = QtWidgets.QLineEdit('100') | ||
self.PixelCalibrationCalibrateButton = guitools.BetterPushButton('Start') | ||
self.PixelCalibrationCalibrateButton.setCheckable(False) | ||
self.PixelCalibrationLabelInfo = QtWidgets.QLabel("") | ||
|
||
# Defining layout | ||
self.grid = QtWidgets.QGridLayout() | ||
self.setLayout(self.grid) | ||
|
||
# | ||
self.grid.addWidget(self.canvas, 0, 0, 3, 3) | ||
|
||
# | ||
self.grid.addWidget(self.PixelCalibrationSnapPreviewButton, 1, 0, 1, 1) | ||
self.grid.addWidget(self.PixelCalibrationUndoButton, 1, 1, 1, 1) | ||
self.grid.addWidget(self.PixelCalibrationCalibrateButton, 1, 2, 1, 1) | ||
|
||
# | ||
self.grid.addWidget(self.PixelCalibrationLabelKnownDistance, 2, 0, 1, 1) | ||
self.grid.addWidget(self.PixelCalibrationEditFileName, 2, 1, 1, 1) | ||
self.grid.addWidget(self.PixelCalibrationLabelInfo, 2, 2, 1, 1) | ||
|
||
self.layer = None | ||
|
||
|
||
def getPixelSize(self): | ||
knownDistance = int(self.PixelCalibrationEditFileName.text()) | ||
lineLength = self.canvas.getLineLength() | ||
pixelSize = knownDistance/lineLength | ||
return pixelSize | ||
|
||
|
||
def getCoordinateList(self): | ||
return self.canvas.getCoordinateList() | ||
|
||
def setInformationLabel(self, information): | ||
self.PixelCalibrationLabelInfo.setText(information) | ||
|
||
def setPreviewImage(self, image): | ||
self.canvas.setImage(image) | ||
|
||
class Canvas(QtWidgets.QLabel): | ||
def __init__(self): | ||
super().__init__() | ||
self.dimensions = (400,400) | ||
self.setFixedSize(self.dimensions[0],self.dimensions[1]) | ||
self.setImage() | ||
|
||
self.pos = None | ||
#self.setMouseTracking(False) | ||
self.pressPos = (0,0) | ||
self.lineCoordinates = (0,0,0,0) | ||
|
||
self.isTracking = False | ||
|
||
|
||
def setImage(self, npImage=None, pathImage='histo.jpg'): | ||
|
||
if npImage is None: | ||
npImage = np.array(cv2.imread(pathImage)) | ||
npImage = cv2.resize(npImage, self.dimensions) | ||
if len(npImage.shape) == 2: | ||
npImage = np.repeat(npImage[:,:,np.newaxis], 3, axis=2) | ||
|
||
height, width, channel = npImage.shape | ||
bytesPerLine = 3 * width | ||
qImage = QImage(npImage.data, width, height, bytesPerLine, QImage.Format_RGB888) | ||
self.imageNow = QPixmap(qImage) | ||
|
||
self.setPixmap(self.imageNow.scaled(self.dimensions[0], self.dimensions[1], QtCore.Qt.KeepAspectRatio)) | ||
|
||
def enterEvent(self, event): | ||
super().enterEvent(event) | ||
self.isTracking = True | ||
|
||
def leaveEvent(self, event): | ||
super().leaveEvent(event) | ||
self.isTracking = False | ||
|
||
def mouseMoveEvent(self, event): | ||
self.pos = event.pos() | ||
self.update() | ||
|
||
def paintEvent(self, event): | ||
if self.pos and self.isTracking: | ||
painter = QPainter(self) | ||
pen = QtGui.QPen() | ||
pen.setWidth(4) | ||
pen.setColor(QtGui.QColor('yellow')) | ||
painter.setPen(pen) | ||
try: | ||
painter.drawLine(self.pos.x(), self.pos.y(), self.pressPos.x(), self.pressPos.y()) | ||
painter.end() | ||
self.lineCoordinates = [self.pos.x(), self.pos.y(), self.pressPos.x(), self.pressPos.y()] | ||
except Exception as e: | ||
print (e) | ||
|
||
def mousePressEvent(self, event): | ||
if event.button() == Qt.LeftButton: | ||
self.pressPos = event.pos() | ||
self.setMouseTracking(True) | ||
|
||
def mouseReleaseEvent(self, event): | ||
# ensure that the left button was pressed *and* released within the | ||
# geometry of the widget; if so, emit the signal; | ||
if (self.pressPos is not None and | ||
event.button() == Qt.LeftButton and | ||
event.pos() in self.rect()): | ||
self.setMouseTracking(False) | ||
self.pressPos = None | ||
|
||
def getLineLength(self): | ||
try: | ||
lineLength = np.sqrt(np.abs(self.lineCoordinates[2]-self.lineCoordinates[0])**2+np.abs(self.lineCoordinates[3]-self.lineCoordinates[1])**2) | ||
except: | ||
lineLength = 1 | ||
return lineLength | ||
|
||
# Copyright (C) 2020-2021 ImSwitch developers | ||
# This file is part of ImSwitch. | ||
# | ||
# ImSwitch is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# ImSwitch is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters