...
 
Commits (3)
......@@ -164,6 +164,9 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.hqiSpinBox.setMinimum(0)
self.hqiSpinBox.setMaximum(100)
self.hqiSpinBox.setMaximumWidth(100)
minHQI = self.dataset.resultParams['minHQI']
if minHQI is not None:
self.hqiSpinBox.setValue(minHQI)
self.hqiSpinBox.valueChanged.connect(self.applyHQIThresholdToResults)
minHQI = self.dataset.resultParams['minHQI']
if minHQI is not None:
......@@ -301,8 +304,11 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.refSelector.setDisabled(False)
def importTrueMatchResults(self):
if self.importWindow is not None:
del self.importWindow
self.importWindow = LoadTrueMatchResults(self.particleContainer, self)
self.importWindow.exec()
# self.importWindow.exec()
@QtCore.pyqtSlot()
def applyHQIThresholdToResults(self):
......@@ -622,8 +628,9 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
def closeEvent(self, event):
for window in [self.importWindow, self.dbWin]:
try: window.close()
except: pass
if window is not None:
window.close()
self.viewparent.imparent.particelAnalysisAct.setChecked(False)
event.accept()
......
......@@ -169,4 +169,4 @@ class ExpExcelDialog(QtWidgets.QDialog):
report.to_excel(writer, sheet_name = 'Particle Statistics', index=False)
writer.save()
self.accept()
QtWidgets.QMessageBox.about(self, 'Particles succesfully exported', 'List saved to' + str(xlsname))
\ No newline at end of file
QtWidgets.QMessageBox.about(self, 'Particles succesfully exported', 'List saved to\n' + str(xlsname))
\ No newline at end of file
This diff is collapsed.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
GEPARD - Gepard-Enabled PARticle Detection
Copyright (C) 2018 Lars Bittrich and Josef Brandt, Leibniz-Institut für
Polymerforschung Dresden e. V. <bittrich-lars@ipfdd.de>
This program 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.
This program 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, see COPYING.
If not, see <https://www.gnu.org/licenses/>.
"""
import numpy as np
import cv2
def getContourStatsWithPixelScale(cnt, pixelscale):
long, short, longellipse, shortellipse, area = getContourStats(cnt)
return long*pixelscale, short*pixelscale, longellipse*pixelscale, shortellipse*pixelscale, area*pixelscale**2
def getContourStats(cnt):
##characterize particle
longellipse, shortellipse = np.nan, np.nan
if cnt.shape[0] >= 5: ##at least 5 points required for ellipse fitting...
ellipse = cv2.fitEllipse(cnt)
shortellipse, longellipse = ellipse[1]
rect = cv2.minAreaRect(cnt)
long, short = rect[1]
if short>long:
long, short = short, long
area = cv2.contourArea(cnt)
return long, short, longellipse, shortellipse, area
\ No newline at end of file
......@@ -31,25 +31,8 @@ from PyQt5 import QtWidgets, QtCore
from copy import deepcopy
from .particlePainter import ParticlePainter
from .particleCharacterization import getContourStatsWithPixelScale
def getContourStatsWithPixelScale(contours, pixelscale):
##characterize particle
longellipse, shortellipse = np.nan, np.nan
cnt = contours
if cnt.shape[0] >= 5: ##at least 5 points required for ellipse fitting...
ellipse = cv2.fitEllipse(cnt)
shortellipse, longellipse = ellipse[1]
rect = cv2.minAreaRect(cnt)
long, short = rect[1]
if short>long:
long, short = short, long
area = cv2.contourArea(cnt)
return long*pixelscale, short*pixelscale, longellipse*pixelscale, shortellipse*pixelscale, area*pixelscale**2
class ParticleContextMenu(QtWidgets.QMenu):
......
......@@ -268,7 +268,7 @@ class DataSet(object):
self.particleContainer.setMeasurementScanIndex(indexOfNewMeas, scanIndex)
curParticle.addMeasurement(self.particleContainer.measurements[indexOfNewMeas])
if self.results['polymers'] is not None: #transfer results
if hasattr(self, 'results') and self.results['polymers'] is not None: #transfer results
for particle in self.particleContainer.particles:
for meas in particle.measurements:
specIndex = meas.getScanIndex()
......
......@@ -28,6 +28,8 @@ from skimage.feature import peak_local_max
from skimage.morphology import watershed
from random import random
from .analysis.particleCharacterization import getContourStats
class Parameter(object):
def __init__(self, name, dtype, value=None, minval=None, maxval=None,
decimals=0, stepsize=1, helptext=None, show=False, linkedParameter=None):
......@@ -282,21 +284,6 @@ class Segmentation(object):
sure_fg = cv2.dilate(sure_fg, np.ones((3, 3)))
return sure_fg
def characterizeParticle(self, contours):
longellipse, shortellipse = np.nan, np.nan
cnt = contours
if cnt.shape[0] >= 5: ##at least 5 points required for ellipse fitting...
ellipse = cv2.fitEllipse(cnt)
shortellipse, longellipse = ellipse[1]
rect = cv2.minAreaRect(cnt)
long, short = rect[1]
if short>long:
long, short = short, long
return long, short, longellipse, shortellipse, cv2.contourArea(cnt)
def getMeasurementPoints(self, binParticle, numPoints=1):
binParticle = cv2.copyMakeBorder(binParticle, 1, 1, 1, 1, 0)
......@@ -449,7 +436,6 @@ class Segmentation(object):
img[np.nonzero(sure_bg)] |= 2
return img, 1
dist_transform = cv2.distanceTransform(thresh, cv2.DIST_L2,5)
print("distanceTransform")
if self.cancelcomputation:
......@@ -464,7 +450,7 @@ class Segmentation(object):
return None, None, None
if return_step=="watershed":
return np.uint8(255*(markers!=0)), 0
if cv2.__version__ > '3.5':
contours, hierarchy = cv2.findContours(markers, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
else:
......@@ -484,7 +470,8 @@ class Segmentation(object):
label = markers[cnt[0,0,1],cnt[0,0,0]]
if label==0:
continue
particlestats.append(self.characterizeParticle(cnt))
stats = getContourStats(cnt)
particlestats.append(stats)
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()
......