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