From f1fcb2d7958c7f842cf9a614363237e3d599b33f Mon Sep 17 00:00:00 2001 From: Josef Brandt Date: Mon, 2 Dec 2019 12:43:56 +0100 Subject: [PATCH] Autofocus Option selectable by checkbox in WITecCom --- .gitignore | 6 ++ ramancom/WITecCOM.py | 19 +++--- ramanscanui.py | 68 ++++++++++++-------- sampleview.py | 7 ++- segmentation.py | 146 ++++++++++++++++++++++--------------------- 5 files changed, 139 insertions(+), 107 deletions(-) diff --git a/.gitignore b/.gitignore index fd4eb08..192a19d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,9 @@ external/build/ ramancom/renishawcom.py ramancom/renishawtesting.py + +*.exp + +*.lib + +*.obj diff --git a/ramancom/WITecCOM.py b/ramancom/WITecCOM.py index 2528aed..e8b2d55 100644 --- a/ramancom/WITecCOM.py +++ b/ramancom/WITecCOM.py @@ -53,7 +53,9 @@ class WITecCOM(RamanBase): hostname = gethostname() self.IBUCSAccess = win32com.client.DispatchEx(self.CLSID, machine=hostname, clsctx=pythoncom.CLSCTX_REMOTE_SERVER) - + self.advancedInterface = False + self.doAutoFocus = False + def connect(self): if not self.IBUCSAccess.RequestWriteAccess(True): self.connected = False @@ -167,9 +169,8 @@ class WITecCOM(RamanBase): try: self.getAdvancedCOMFeatures(IBUCSCore) self.advancedInterface = True - print('using advanced WITec features!') + self.doAutoFocus = False except pythoncom.com_error: - print('not using advanced WITec features!') self.advancedInterface = False self.connected = True @@ -201,9 +202,9 @@ class WITecCOM(RamanBase): from .advancedWITec import AdvancedWITecSpectra except ModuleNotFoundError: from advancedWITec import AdvancedWITecSpectra - self.advSpec = AdvancedWITecSpectra() - - self.ramanParameters.append(RamanSettingParam('Autofocus', 'checkBox', default=True)) + self.advSpec = AdvancedWITecSpectra() + if 'Autofocus' not in [param.name for param in self.ramanParameters]: + self.ramanParameters.append(RamanSettingParam('Autofocus', 'checkBox', default=False)) def getBrightness(self): assert self.connected @@ -342,7 +343,8 @@ class WITecCOM(RamanBase): if not self.advancedInterface: self.triggerTimeSeriesMeasurement(num) else: - self.doSpectralAutoFocus() + if self.doAutoFocus: + self.doSpectralAutoFocus() self.acquireSilentSpectrum(num) def finishMeasurement(self): @@ -378,6 +380,9 @@ class WITecCOM(RamanBase): def initateSilentSpectrumAcquisition(self, ramanSettings): self.advSpec.setDatasetPath(ramanSettings['path']) + + self.doAutoFocus = ramanSettings['Autofocus'] + self.advSpec.createTmpSpecFolder() state = self.BeamPathState.GetValue() if state == 'Video': diff --git a/ramanscanui.py b/ramanscanui.py index 9c4551a..d66b533 100644 --- a/ramanscanui.py +++ b/ramanscanui.py @@ -99,33 +99,13 @@ class RamanScanUI(QtWidgets.QWidget): hbox = QtWidgets.QHBoxLayout() self.params = [] - for param in self.ramanctrl.ramanParameters: - if param.dtype == 'int': - self.params.append(QtWidgets.QSpinBox()) - self.params[-1].setMinimum(param.minVal) - self.params[-1].setMaximum(param.maxVal) - self.params[-1].setValue(param.value) - if param.dtype == 'double': - self.params.append(QtWidgets.QDoubleSpinBox()) - self.params[-1].setMinimum(param.minVal) - self.params[-1].setMaximum(param.maxVal) - self.params[-1].setValue(param.value) - if param.dtype == 'combobox': - self.params.append(QtWidgets.QComboBox()) - self.params[-1].addItems([str(i) for i in param.valList]) - - - self.group2 = QtWidgets.QGroupBox("Raman settings", self) - grid2 = QtWidgets.QFormLayout() - - for index, param in enumerate(self.params): - param.setMinimumWidth(70) - grid2.addRow(QtWidgets.QLabel(self.ramanctrl.ramanParameters[index].name), param) + self.paramsGroup = QtWidgets.QGroupBox("Raman settings") + self.paramsLayout = QtWidgets.QFormLayout() self.prun = QtWidgets.QPushButton("Raman scan", self) self.prun.released.connect(self.run) - grid2.addRow(self.prun) - self.group2.setLayout(grid2) + self.paramsGroup.setLayout(self.paramsLayout) + self.updateRamanParameters() self.pexit = QtWidgets.QPushButton("Cancel", self) self.pexit.released.connect(self.stopScan) @@ -139,7 +119,7 @@ class RamanScanUI(QtWidgets.QWidget): hbox.addStretch() hbox.addWidget(self.pexit) - vbox.addWidget(self.group2) + vbox.addWidget(self.paramsGroup) vbox.addLayout(hbox) vbox.addWidget(self.progresstime) vbox.addWidget(self.progressbar) @@ -148,6 +128,42 @@ class RamanScanUI(QtWidgets.QWidget): self.setWindowTitle("Raman Scan") self.setVisible(False) + def updateRamanParameters(self): + """ + Update the raman parameters in the layout + :return: + """ + for index in reversed(range(self.paramsLayout.count())): + widget = self.paramsLayout.itemAt(index).widget() + self.paramsLayout.removeWidget(widget) + widget.setParent(None) + + self.params = [] + for param in self.ramanctrl.ramanParameters: + if param.dtype == 'int': + self.params.append(QtWidgets.QSpinBox()) + self.params[-1].setMinimum(param.minVal) + self.params[-1].setMaximum(param.maxVal) + self.params[-1].setValue(param.value) + if param.dtype == 'double': + self.params.append(QtWidgets.QDoubleSpinBox()) + self.params[-1].setMinimum(param.minVal) + self.params[-1].setMaximum(param.maxVal) + self.params[-1].setValue(param.value) + if param.dtype == 'combobox': + self.params.append(QtWidgets.QComboBox()) + self.params[-1].addItems([str(i) for i in param.valList]) + if param.dtype== 'checkBox': + self.params.append(QtWidgets.QCheckBox()) + self.params[-1].setChecked(param.value) + + for index, param in enumerate(self.params): + param.setMinimumWidth(70) + self.paramsLayout.addRow(QtWidgets.QLabel(self.ramanctrl.ramanParameters[index].name), param) + + self.paramsLayout.addRow(self.prun) + self.paramsGroup.setLayout(self.paramsLayout) + def makeGetFnameLambda(self, msg, path, fileType, btn): return lambda : self.getFName(msg, path, fileType, btn) @@ -247,7 +263,7 @@ class RamanScanUI(QtWidgets.QWidget): else: self.view.highLightRamanIndex(0) self.view.blockUI() - self.group2.setEnabled(False) + self.paramsGroup.setEnabled(False) self.progresstime.setEnabled(True) self.progressbar.setEnabled(True) self.progressbar.setRange(0, len(scanpoints)) diff --git a/sampleview.py b/sampleview.py index ac5aa87..01ed369 100644 --- a/sampleview.py +++ b/sampleview.py @@ -220,6 +220,7 @@ class SampleView(QtWidgets.QGraphicsView): elif mode == "RamanScan": self.removeSeedPointMarkers() self.ramanwidget.resetDataset(self.dataset) + self.ramanwidget.updateRamanParameters() self.ramanwidget.setVisible(True) #show legend: @@ -350,9 +351,9 @@ class SampleView(QtWidgets.QGraphicsView): p0 = self.mapToScene(event.pos()) self.moveStageToPosition(p0) -# elif self.mode=="ParticleDetection": -# p0 = self.mapToScene(event.pos()) -# self.detectionwidget.setImageCenter([p0.x(), p0.y()]) + elif self.mode=="ParticleDetection": + p0 = self.mapToScene(event.pos()) + self.detectionwidget.setImageCenter([p0.x(), p0.y()]) else: p0 = self.mapToScene(event.pos()) diff --git a/segmentation.py b/segmentation.py index bd4133f..3c9a801 100644 --- a/segmentation.py +++ b/segmentation.py @@ -110,7 +110,7 @@ class Segmentation(object): Parameter("maxholebrightness", float, self.detectParams['maxholebrightness'], 0, 1, 2, 0.02, helptext="Close holes brighter than..", show = True), Parameter("minparticlearea", int, self.detectParams['minparticlearea'], 1, 1000, 0, 50, helptext="Min. particle pixel area", show=False), Parameter("enableMaxArea", np.bool, self.detectParams['enableMaxArea'], helptext="enable filtering for maximal pixel area", show=False, linkedParameter='maxparticlearea'), - Parameter("maxparticlearea", int, self.detectParams['maxparticlearea'], 10, 1E9, 0, 50, helptext="Max. particle pixel area", show=True), + Parameter("maxparticlearea", int, self.detectParams['maxparticlearea'], 10, 1E9, 0, 50, helptext="Max. particle pixel area", show=False), Parameter("minparticledistance", int, self.detectParams['minparticledistance'], 5, 1000, 0, 5, helptext="Min. distance between particles", show=False), Parameter("measurefrac", float, self.detectParams['measurefrac'], 0, 1, 2, stepsize = 0.05, helptext="measure fraction of particles", show=False), Parameter("closeBackground", np.bool, self.detectParams['closeBackground'], helptext="close holes in sure background", show=False), @@ -253,83 +253,87 @@ class Segmentation(object): for label in range(1, n): area = stats[label, cv2.CC_STAT_AREA] if self.minparticlearea < area < maxArea: - print(f'processing {label} of {n} compontents') up = stats[label, cv2.CC_STAT_TOP] left = stats[label, cv2.CC_STAT_LEFT] width = stats[label, cv2.CC_STAT_WIDTH] height = stats[label, cv2.CC_STAT_HEIGHT] - subthresh = np.uint8(255 * (labels[up:(up+height), left:(left+width)] == label)) - subdist = cv2.distanceTransform(subthresh, cv2.DIST_L2, 3) - - sure_fg = self.getSureForeground(subthresh, subdist, self.minparticledistance) - sure_bg = cv2.dilate(subthresh, np.ones((5, 5)), iterations = 1) - if self.closeBackground: - sure_bg = self.closeHoles(sure_bg) - - # modify sure_fg and sure_bg with seedpoints and deletepoints - for p in np.int32(seedpoints): - cv2.circle(sure_fg, tuple([p[0]-left, p[1]-up]), int(p[2]), 1, -1) - cv2.circle(sure_bg, tuple([p[0]-left, p[1]-up]), int(p[2]), 1, -1) - for p in np.int32(deletepoints): - cv2.circle(sure_fg, tuple([p[0]-left, p[1]-up]), int(p[2]), 0, -1) - cv2.circle(sure_bg, tuple([p[0]-left, p[1]-up]), int(p[2]), 0, -1) - - if self.cancelcomputation: - return None, None - - if return_step=="sure_fg": - preview_surefg = self.addToPreviewImage(sure_fg, up, left, preview_surefg) - preview_surebg = self.addToPreviewImage(sure_bg, up, left, preview_surebg) - continue - - unknown = cv2.subtract(sure_bg, sure_fg) - - ret, markers = cv2.connectedComponents(sure_fg) - markers = markers+1 - markers[unknown==255] = 0 - - markers = ndi.label(sure_fg)[0] - markers = watershed(-subdist, markers, mask=sure_bg, compactness = self.compactness, watershed_line = True) #labels = 0 for background, 1... for particles - - if self.cancelcomputation: - return None, None - - if return_step=="watershed": - previewImage = self.addToPreviewImage(markers, up, left, previewImage) - continue - - if cv2.__version__ > '3.5': - contours, hierarchy = cv2.findContours(markers, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE) +# if width > 25000 or height > 25000: + if False: + print(f'skipping{label} of {n} compontents, too large: {width} x {height} pixel!!!') else: - temp, contours, hierarchy = cv2.findContours(markers, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE) - if self.cancelcomputation: - return None, None + print(f'processing {label} of {n} compontents, {width} x {height} pixel') + subthresh = np.uint8(255 * (labels[up:(up+height), left:(left+width)] == label)) + subdist = cv2.distanceTransform(subthresh, cv2.DIST_L2, 3) - tmpcontours = [contours[i] for i in range(len(contours)) if hierarchy[0,i,3]<0] - - for cnt in tmpcontours: - if cv2.contourArea(cnt) >= self.minparticlearea: - label = markers[cnt[0,0,1],cnt[0,0,0]] - if label==0: - continue - - x0, x1 = cnt[:,0,0].min(), cnt[:,0,0].max() - y0, y1 = cnt[:,0,1].min(), cnt[:,0,1].max() - subimg = (markers[y0:y1+1,x0:x1+1]).copy() - subimg[subimg!=label] = 0 - y, x = self.getMeasurementPoints(subimg) - - for i in range(len(cnt)): - cnt[i][0][0] += left - cnt[i][0][1] += up - - finalcontours.append(cnt) - measurementPoints[particleIndex] = [] + sure_fg = self.getSureForeground(subthresh, subdist, self.minparticledistance) + sure_bg = cv2.dilate(subthresh, np.ones((5, 5)), iterations = 1) + if self.closeBackground: + sure_bg = self.closeHoles(sure_bg) + + # modify sure_fg and sure_bg with seedpoints and deletepoints + for p in np.int32(seedpoints): + cv2.circle(sure_fg, tuple([p[0]-left, p[1]-up]), int(p[2]), 1, -1) + cv2.circle(sure_bg, tuple([p[0]-left, p[1]-up]), int(p[2]), 1, -1) + for p in np.int32(deletepoints): + cv2.circle(sure_fg, tuple([p[0]-left, p[1]-up]), int(p[2]), 0, -1) + cv2.circle(sure_bg, tuple([p[0]-left, p[1]-up]), int(p[2]), 0, -1) + + if self.cancelcomputation: + return None, None + + if return_step=="sure_fg": + preview_surefg = self.addToPreviewImage(sure_fg, up, left, preview_surefg) + preview_surebg = self.addToPreviewImage(sure_bg, up, left, preview_surebg) + continue + + unknown = cv2.subtract(sure_bg, sure_fg) + + ret, markers = cv2.connectedComponents(sure_fg) + markers = markers+1 + markers[unknown==255] = 0 + + markers = ndi.label(sure_fg)[0] + markers = watershed(-subdist, markers, mask=sure_bg, compactness = self.compactness, watershed_line = True) #labels = 0 for background, 1... for particles + + if self.cancelcomputation: + return None, None + + if return_step=="watershed": + previewImage = self.addToPreviewImage(markers, up, left, previewImage) + continue + + if cv2.__version__ > '3.5': + contours, hierarchy = cv2.findContours(markers, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE) + else: + temp, contours, hierarchy = cv2.findContours(markers, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE) + if self.cancelcomputation: + return None, None - for index in range(0, len(x)): - newMeasPoint = MeasurementPoint(particleIndex, x[index] + x0 + left, y[index] + y0 + up) - measurementPoints[particleIndex].append(newMeasPoint) - particleIndex += 1 + tmpcontours = [contours[i] for i in range(len(contours)) if hierarchy[0,i,3]<0] + + for cnt in tmpcontours: + if cv2.contourArea(cnt) >= self.minparticlearea: + label = markers[cnt[0,0,1],cnt[0,0,0]] + if label==0: + continue + + x0, x1 = cnt[:,0,0].min(), cnt[:,0,0].max() + y0, y1 = cnt[:,0,1].min(), cnt[:,0,1].max() + subimg = (markers[y0:y1+1,x0:x1+1]).copy() + subimg[subimg!=label] = 0 + y, x = self.getMeasurementPoints(subimg) + + for i in range(len(cnt)): + cnt[i][0][0] += left + cnt[i][0][1] += up + + finalcontours.append(cnt) + measurementPoints[particleIndex] = [] + + for index in range(0, len(x)): + newMeasPoint = MeasurementPoint(particleIndex, x[index] + x0 + left, y[index] + y0 + up) + measurementPoints[particleIndex].append(newMeasPoint) + particleIndex += 1 if return_step == 'sure_fg': img = np.zeros_like(preview_surefg) -- GitLab