Commit 467d0c8a authored by Josef Brandt's avatar Josef Brandt

Downscale video image

A scaling factor can be indicated in the gepard.cfg
parent ec4f0cff
...@@ -28,3 +28,5 @@ instrumentcom/renishawtesting.py ...@@ -28,3 +28,5 @@ instrumentcom/renishawtesting.py
*.pyc *.pyc
*.jdx *.jdx
instrumentcom/thermoFTIRCom.py
...@@ -11,6 +11,8 @@ raman_interface = SIMULATED_RAMAN_CONTROL ...@@ -11,6 +11,8 @@ raman_interface = SIMULATED_RAMAN_CONTROL
[General Microscope Setup] [General Microscope Setup]
magnification = 20 magnification = 20
# The scale factor allows downscaling the video image of the microscope camera in order to reduce final image size
videoImageScaleFactor = 1.0
[Renishaw] [Renishaw]
#information specific for renishaw control #information specific for renishaw control
......
...@@ -29,19 +29,20 @@ import logging.handlers ...@@ -29,19 +29,20 @@ import logging.handlers
import cv2 import cv2
from time import localtime, strftime from time import localtime, strftime
from typing import List, TYPE_CHECKING from typing import List, TYPE_CHECKING
from ..imagestitch import imageStacking
from ..helperfunctions import cv2imread_fix, cv2imwrite_fix, getInstrumentControl, positionWidgetOnScreen
from ..opticalbackground import BackGroundManager
from .uielements import TimeEstimateProgressbar from .uielements import TimeEstimateProgressbar
from .zlevelsetter import ZLevelSetter from .zlevelsetter import ZLevelSetter
from ..imagestitch import imageStacking
from ..helperfunctions import cv2imread_fix, cv2imwrite_fix, positionWidgetOnScreen
from ..opticalbackground import BackGroundManager
from ..scenePyramid import ScenePyramid from ..scenePyramid import ScenePyramid
from ..gepardlogging import setDefaultLoggingConfig from ..gepardlogging import setDefaultLoggingConfig
from ..instrumentcom.instrumentComBase import InstrumentComBase
if TYPE_CHECKING: if TYPE_CHECKING:
from ..sampleview import SampleView from ..sampleview import SampleView
def scan(path, sol, zpositions, grid, controlclass, dataqueue, def scan(path, sol, zpositions, grid, instrctrlClass, videoScaleFac: float, dataqueue,
stopevent, logpath, ishdr=False): stopevent, logpath, ishdr=False):
if ishdr: if ishdr:
merge_mertens = cv2.createMergeMertens() merge_mertens = cv2.createMergeMertens()
...@@ -55,7 +56,8 @@ def scan(path, sol, zpositions, grid, controlclass, dataqueue, ...@@ -55,7 +56,8 @@ def scan(path, sol, zpositions, grid, controlclass, dataqueue,
logger.info('starting new optical scan') logger.info('starting new optical scan')
try: try:
instrctrl = controlclass(logger) instrctrl: InstrumentComBase = instrctrlClass(logger)
instrctrl.setVideoScaleFactor(videoScaleFac)
instrctrl.updateImageConfig(os.path.dirname(logpath)) instrctrl.updateImageConfig(os.path.dirname(logpath))
instrctrl.connect() instrctrl.connect()
zlist = list(enumerate(zpositions)) zlist = list(enumerate(zpositions))
...@@ -707,7 +709,7 @@ class OpticalScanUI(QtWidgets.QWidget): ...@@ -707,7 +709,7 @@ class OpticalScanUI(QtWidgets.QWidget):
self.dataqueue = Queue() self.dataqueue = Queue()
logpath = os.path.join(self.dataset.path, 'opticalScanLog.txt') logpath = os.path.join(self.dataset.path, 'opticalScanLog.txt')
self.process = Process(target=scan, args=(path, sol, self.dataset.zpositions, self.process = Process(target=scan, args=(path, sol, self.dataset.zpositions,
self.dataset.grid, self.instrctrl.__class__, self.dataset.grid, self.instrctrl.__class__, self.instrctrl.videoScaleFactor,
self.dataqueue, self.processstopevent, self.dataqueue, self.processstopevent,
logpath, self.hdrcheck.isChecked())) logpath, self.hdrcheck.isChecked()))
self.process.start() self.process.start()
......
...@@ -22,7 +22,6 @@ If not, see <https://www.gnu.org/licenses/>. ...@@ -22,7 +22,6 @@ If not, see <https://www.gnu.org/licenses/>.
import numpy as np import numpy as np
import cv2 import cv2
import os import os
import sys
from PyQt5 import QtWidgets, QtCore from PyQt5 import QtWidgets, QtCore
try: try:
...@@ -32,8 +31,10 @@ except ImportError: ...@@ -32,8 +31,10 @@ except ImportError:
skimread = None skimread = None
skimsave = None skimsave = None
from .instrumentcom.instrumentComBase import InstrumentComBase
from logging import Logger from logging import Logger
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .instrumentcom.instrumentComBase import InstrumentComBase
def cv2imread_fix(fname, flags=cv2.IMREAD_COLOR): def cv2imread_fix(fname, flags=cv2.IMREAD_COLOR):
...@@ -105,11 +106,12 @@ def polygoncovering(boundary, wx, wy): ...@@ -105,11 +106,12 @@ def polygoncovering(boundary, wx, wy):
return poslist return poslist
def getInstrumentControl(controlclass: InstrumentComBase, logger: Logger) -> InstrumentComBase: def getInstrumentControl(controlclass: 'InstrumentComBase', logger: Logger) -> 'InstrumentComBase':
simulatedInterface: bool = False simulatedInterface: bool = False
if 'simulatedInterface' in controlclass.__dict__.keys(): if 'simulatedInterface' in controlclass.__dict__.keys():
if controlclass.__dict__['simulatedInterface'] == True: if controlclass.__dict__['simulatedInterface'] == True:
simulatedInterface = True simulatedInterface = True
if simulatedInterface: if simulatedInterface:
instrctrl = controlclass(logger, ui=False) instrctrl = controlclass(logger, ui=False)
else: else:
...@@ -131,7 +133,7 @@ def needsFTIRAperture(sampleview) -> bool: ...@@ -131,7 +133,7 @@ def needsFTIRAperture(sampleview) -> bool:
return needsAperture return needsAperture
def lightModeSwitchNeeded(instrctrl: InstrumentComBase) -> bool: def lightModeSwitchNeeded(instrctrl: 'InstrumentComBase') -> bool:
switchNeeded: bool = False switchNeeded: bool = False
if instrctrl.name == 'RenishawCOM': if instrctrl.name == 'RenishawCOM':
instrctrl.connect() instrctrl.connect()
......
...@@ -380,6 +380,7 @@ class WITecCOM(InstrumentComBase): ...@@ -380,6 +380,7 @@ class WITecCOM(InstrumentComBase):
self.ImageNameMan.SetValue(fname) self.ImageNameMan.SetValue(fname)
self.ImageSaveMan.OperateTrigger() self.ImageSaveMan.OperateTrigger()
sleep(.1) sleep(.1)
self._scaleVideoImage(fname)
@comErrorRepeater @comErrorRepeater
def getImageDimensions(self, mode = 'df'): def getImageDimensions(self, mode = 'df'):
......
...@@ -18,15 +18,32 @@ You should have received a copy of the GNU General Public License ...@@ -18,15 +18,32 @@ You should have received a copy of the GNU General Public License
along with this program, see COPYING. along with this program, see COPYING.
If not, see <https://www.gnu.org/licenses/>. If not, see <https://www.gnu.org/licenses/>.
""" """
import cv2
from ..helperfunctions import cv2imread_fix, cv2imwrite_fix
class InstrumentComBase(object): class InstrumentComBase(object):
videoScaleFactor: float = 1.0
@classmethod
def setVideoScaleFactor(cls, newFac) -> None:
cls.videoScaleFactor = float(newFac)
def __init__(self, logger=None): def __init__(self, logger=None):
self.name = None self.name = None
self.connected = False self.connected = False
self.timeseries = False self.timeseries = False
self.logger = logger self.logger = logger
def _scaleVideoImage(self, imagePath: str) -> None:
"""
For convenience.. Takes the image at the indicated path and scales it to the videoScaleFactor.
"""
img = cv2imread_fix(imagePath)
img = cv2.resize(img, None, fx=self.videoScaleFactor, fy=self.videoScaleFactor)
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
cv2imwrite_fix(imagePath, img)
def getRamanPositionShift(self): def getRamanPositionShift(self):
""" Compute the shift between laser spot and image center""" """ Compute the shift between laser spot and image center"""
raise NotImplementedError raise NotImplementedError
...@@ -60,10 +77,6 @@ class InstrumentComBase(object): ...@@ -60,10 +77,6 @@ class InstrumentComBase(object):
""" Get the image width and height in um and the orientation angle in degrees. """ Get the image width and height in um and the orientation angle in degrees.
""" """
raise NotImplementedError raise NotImplementedError
# IT IS NOT NEEDED, ISN'T IT??
# def startSinglePointScan(self):
# raise NotImplementedError
def initiateMeasurement(self, specScanSettings): def initiateMeasurement(self, specScanSettings):
raise NotImplementedError raise NotImplementedError
......
...@@ -29,6 +29,7 @@ config = configparser.ConfigParser() ...@@ -29,6 +29,7 @@ config = configparser.ConfigParser()
config.read(os.path.join(defaultPath, 'gepard.cfg')) config.read(os.path.join(defaultPath, 'gepard.cfg'))
interface = "SIMULATED_RAMAN_CONTROL" interface = "SIMULATED_RAMAN_CONTROL"
videoImgScale = 1.0
class SpecScanParameter(object): class SpecScanParameter(object):
...@@ -63,7 +64,6 @@ class SpecScanParameter(object): ...@@ -63,7 +64,6 @@ class SpecScanParameter(object):
try: try:
defaultPath = config["Defaults"]["file_path"] defaultPath = config["Defaults"]["file_path"]
print('default Path is now:', defaultPath)
except KeyError: except KeyError:
pass pass
...@@ -72,6 +72,12 @@ try: ...@@ -72,6 +72,12 @@ try:
except KeyError: except KeyError:
pass pass
try:
videoImgScale = config["General Microscope Setup"]["videoImageScaleFactor"]
except KeyError:
pass
if interface == "SIMULATED_RAMAN_CONTROL": if interface == "SIMULATED_RAMAN_CONTROL":
from .simulated.simulatedraman import SimulatedRaman from .simulated.simulatedraman import SimulatedRaman
InstrumentControl = SimulatedRaman InstrumentControl = SimulatedRaman
...@@ -95,7 +101,6 @@ elif interface == "RENISHAW_CONTROL": ...@@ -95,7 +101,6 @@ elif interface == "RENISHAW_CONTROL":
InstrumentControl.cam_df_dims = [float(df_dims[0]), float(df_dims[1])] InstrumentControl.cam_df_dims = [float(df_dims[0]), float(df_dims[1])]
except: except:
print('Invalid image dimensions in config file!') print('Invalid image dimensions in config file!')
# InstrumentControl.defaultMeasTemplate = config["Renishaw"]["defaultMeasTemplate"]
InstrumentControl.measTemplatePath = config["Renishaw"]["measTemplatePath"] InstrumentControl.measTemplatePath = config["Renishaw"]["measTemplatePath"]
print(InstrumentControl.measTemplatePath) print(InstrumentControl.measTemplatePath)
InstrumentControl.specScanParameters = InstrumentControl.updateSpecScanParameters(InstrumentControl, InstrumentControl.measTemplatePath) InstrumentControl.specScanParameters = InstrumentControl.updateSpecScanParameters(InstrumentControl, InstrumentControl.measTemplatePath)
...@@ -106,3 +111,5 @@ elif interface == "THERMO_FTIR": ...@@ -106,3 +111,5 @@ elif interface == "THERMO_FTIR":
from .thermoFTIRCom import ThermoFTIRCom from .thermoFTIRCom import ThermoFTIRCom
InstrumentControl = ThermoFTIRCom InstrumentControl = ThermoFTIRCom
simulatedRaman = False simulatedRaman = False
InstrumentControl.setVideoScaleFactor(videoImgScale)
...@@ -122,12 +122,8 @@ class FakeParticle: ...@@ -122,12 +122,8 @@ class FakeParticle:
class FakeCamera: class FakeCamera:
# TODO: Implement a small angle to simulate a tilted camera! # TODO: Implement a small angle to simulate a tilted camera!
def __init__(self): def __init__(self):
self.imgDims: Tuple[int, int] = (500, 250) # width, height of camera imgage self.imgDims: Tuple[int, int] = (600, 350) # width, height of camera imgage in pixel
self.pixelscale: float = 1.0 # µm/px self.pixelscale: float = 1.0 # µm/px
self.sizeScale: float = 100.0 # smaller values make particles rendered smaller and vice versa
self.threshold: float = 0.7 # threshold for determining particles. Larger values -> smaller particles
self.numZLevels: int = 7 # number of z-levels cached for faking depth of field
self.maxZDiff: float = 100 # max difference in z that is simulated.
self.currentImage: np.ndarray = np.zeros((self.imgDims[1], self.imgDims[0], 3)) self.currentImage: np.ndarray = np.zeros((self.imgDims[1], self.imgDims[0], 3))
self.fakeFilter: FakeFilter = FakeFilter() self.fakeFilter: FakeFilter = FakeFilter()
......
...@@ -26,7 +26,7 @@ import cv2 ...@@ -26,7 +26,7 @@ import cv2
import json import json
import numpy as np import numpy as np
from typing import List from typing import List
from .imageGenerator import FakeCamera from .imageGenerator import FakeCamera, FakeFilter
from ..instrumentComBase import InstrumentComBase from ..instrumentComBase import InstrumentComBase
from ...helperfunctions import getAppFolder from ...helperfunctions import getAppFolder
...@@ -266,23 +266,23 @@ class SimulatedStageUI(QtWidgets.QWidget): ...@@ -266,23 +266,23 @@ class SimulatedStageUI(QtWidgets.QWidget):
self.stageParent.moveToPosition(newPos[0], newPos[1], newPos[2]) self.stageParent.moveToPosition(newPos[0], newPos[1], newPos[2])
def _moveToPresetPosition(self, btn: QtWidgets.QPushButton, stepSize: float = 1000) -> None: def _moveToPresetPosition(self, btn: QtWidgets.QPushButton) -> None:
label: str = btn.text() label: str = btn.text()
filter: FakeFilter = self.stageParent.camera.fakeFilter
margin: float = 0.9
newPos: List[float] = [0.0, 0.0, 0.0] newPos: List[float] = [0.0, 0.0, 0.0]
if label == 'UpperLeft': if label == 'UpperLeft':
newPos[0] -= stepSize newPos[0] = filter.xRange[0] * margin
newPos[1] += stepSize newPos[1] = filter.yRange[1] * margin
elif label == 'UpperRight': elif label == 'UpperRight':
newPos[0] += stepSize newPos[0] = filter.xRange[1] * margin
newPos[1] += stepSize newPos[1] = filter.yRange[1] * margin
elif label == 'LowerLeft': elif label == 'LowerLeft':
newPos[0] -= stepSize newPos[0] = filter.xRange[0] * margin
newPos[1] -= stepSize newPos[1] = filter.yRange[0] * margin
elif label == 'LowerRight': elif label == 'LowerRight':
newPos[0] += stepSize newPos[0] = filter.xRange[1] * margin
newPos[1] -= stepSize newPos[1] = filter.yRange[0] * margin
elif label == 'Center':
pass
self.stageParent.moveToPosition(newPos[0], newPos[1], newPos[2]) self.stageParent.moveToPosition(newPos[0], newPos[1], newPos[2])
......
...@@ -43,7 +43,6 @@ class SimulatedRaman(InstrumentComBase): ...@@ -43,7 +43,6 @@ class SimulatedRaman(InstrumentComBase):
self.znum = 4 self.znum = 4
self.gridnum = 36 self.gridnum = 36
self.positionindex = 0 self.positionindex = 0
self.imageindex = 0
def getRamanPositionShift(self): def getRamanPositionShift(self):
return 0., 0. return 0., 0.
...@@ -51,7 +50,6 @@ class SimulatedRaman(InstrumentComBase): ...@@ -51,7 +50,6 @@ class SimulatedRaman(InstrumentComBase):
def connect(self): def connect(self):
self.stage.connect() self.stage.connect()
self.connected = True self.connected = True
self.imageindex = 0
return True return True
def disconnect(self): def disconnect(self):
...@@ -84,7 +82,7 @@ class SimulatedRaman(InstrumentComBase): ...@@ -84,7 +82,7 @@ class SimulatedRaman(InstrumentComBase):
def saveImage(self, fname): def saveImage(self, fname):
assert self.connected assert self.connected
cv2imwrite_fix(fname, self.stage.getCurrentCameraImage()) cv2imwrite_fix(fname, self.stage.getCurrentCameraImage())
self.imageindex = (self.imageindex+1) % (self.znum*self.gridnum) self._scaleVideoImage(fname)
def getImageDimensions(self, mode='df'): def getImageDimensions(self, mode='df'):
""" """
...@@ -92,7 +90,9 @@ class SimulatedRaman(InstrumentComBase): ...@@ -92,7 +90,9 @@ class SimulatedRaman(InstrumentComBase):
""" """
assert self.connected assert self.connected
camDims: tuple = self.stage.camera.imgDims camDims: tuple = self.stage.camera.imgDims
return camDims[0], camDims[1], 0 # TODO: RE-Implement a small angle to simulate a tilted camera! # TODO: RE-Implement a small angle to simulate a tilted camera!
angle: float = 0.0
return camDims[0], camDims[1], angle
def startSinglePointScan(self): def startSinglePointScan(self):
assert self.connected assert self.connected
......
...@@ -12,20 +12,18 @@ from typing import TYPE_CHECKING ...@@ -12,20 +12,18 @@ from typing import TYPE_CHECKING
from ..sampleview import SampleView from ..sampleview import SampleView
from ..dataset import DataSet from ..dataset import DataSet
from ..analysis.particleContainer import ParticleContainer from ..analysis.particleContainer import ParticleContainer
from ..analysis.particleAndMeasurement import Measurement
from ..instrumentcom.instrumentComBase import InstrumentComBase from ..instrumentcom.instrumentComBase import InstrumentComBase
from ..instrumentcom.instrumentConfig import defaultPath from ..instrumentcom.simulated.simulatedStage import SimulatedStage
from ..gui.opticalscanui import OpticalScanUI, PointCoordinates from ..gui.opticalscanui import OpticalScanUI, PointCoordinates
from ..gui.detectionview import ParticleDetectionView, ImageView from ..gui.detectionview import ParticleDetectionView, ImageView
from ..gui.specscanui import SpecScanUI from ..gui.specscanui import SpecScanUI
from ..gui.viewItems.detectItems import SeedPoint
from ..gui.viewItemHandler import ViewItemHandler from ..gui.viewItemHandler import ViewItemHandler
from ..workmodes import ModeHandler, ModeOpticalScan, ModeParticleDetection, ModeSpectrumScan from ..workmodes import ModeHandler, ModeOpticalScan, ModeParticleDetection, ModeSpectrumScan
if TYPE_CHECKING: if TYPE_CHECKING:
from ..__main__ import GEPARDMainWindow from ..__main__ import GEPARDMainWindow
def testGepard(gepard): def testGepard(gepard):
gepard.testCase = TestGepard(gepard) gepard.testCase = TestGepard(gepard)
gepard.testCase.start_automated_test() gepard.testCase.start_automated_test()
...@@ -67,17 +65,19 @@ class TestGepard(unittest.TestCase): ...@@ -67,17 +65,19 @@ class TestGepard(unittest.TestCase):
# SET UP OPTICAL SCAN # SET UP OPTICAL SCAN
moveMargin: int = 300 moveMargin: int = 300
curPos: tuple = self.instrctrl.getPosition()
self.assertEqual(type(self.modeHandler.activeMode), ModeOpticalScan) self.assertEqual(type(self.modeHandler.activeMode), ModeOpticalScan)
oscanWidget: OpticalScanUI = self.modeHandler.oscanMode.widget oscanWidget: OpticalScanUI = self.modeHandler.oscanMode.widget
self.assertEqual(type(oscanWidget), OpticalScanUI) self.assertEqual(type(oscanWidget), OpticalScanUI)
self.assertTrue(oscanWidget.isVisible()) self.assertTrue(oscanWidget.isVisible())
oscanWidget.zLevelSetter.numLevelsSpinbox.setValue(3) oscanWidget.zLevelSetter.numLevelsSpinbox.setValue(3)
simulatedStage: SimulatedStage = self.sampleview.instrctrl.stage
simulatedStage.moveToPosition(0, 0, 0)
points: PointCoordinates = oscanWidget.points points: PointCoordinates = oscanWidget.points
points.read(0) points.read(0)
self.instrctrl.moveToAbsolutePosition(curPos[0] + moveMargin, curPos[1] + moveMargin, curPos[2]) self.instrctrl.moveToAbsolutePosition(moveMargin, moveMargin, 0)
points.read(1) points.read(1)
self.instrctrl.moveToAbsolutePosition(curPos[0] - moveMargin, curPos[1] - moveMargin, curPos[2]) self.instrctrl.moveToAbsolutePosition(-moveMargin, -moveMargin, 0)
points.read(2) points.read(2)
oscanWidget.pareaselect.click() oscanWidget.pareaselect.click()
......
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