Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
GEPARD
GEPARD
Commits
38f99d4e
Commit
38f99d4e
authored
Dec 02, 2019
by
Josef Brandt
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/SegmentationRefactoring' into Tiling2Develop
parents
f1fcb2d7
2efa7d08
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
310 additions
and
141 deletions
+310
-141
detectionview.py
detectionview.py
+58
-20
opticalscan.py
opticalscan.py
+13
-26
ramanscanui.py
ramanscanui.py
+11
-20
segmentation.py
segmentation.py
+117
-75
uielements.py
uielements.py
+111
-0
No files found.
detectionview.py
View file @
38f99d4e
...
...
@@ -27,6 +27,7 @@ from threading import Thread
from
.segmentation
import
Segmentation
from
.analysis.particleCharacterization
import
getParticleStatsWithPixelScale
,
loadZValImageFromDataset
from
.errors
import
InvalidParticleError
from
.uielements
import
TimeEstimateProgressbar
from
.scenePyramid
import
ScenePyramid
Nscreen
=
1000
...
...
@@ -290,8 +291,10 @@ class ParticleDetectionView(QtWidgets.QWidget):
self
.
img
=
pyramid
.
getFullImage
()
self
.
imgclip
=
0
,
0
,
0
,
0
self
.
seg
=
Segmentation
(
self
.
dataset
,
self
)
self
.
seg
.
detectionState
.
connect
(
self
.
updateDetectionState
)
self
.
thread
=
None
self
.
view
:
QtWidgets
.
QGraphicsView
=
parent
self
.
threadrunning
=
False
self
.
view
=
parent
vbox
=
QtWidgets
.
QVBoxLayout
()
hbox
=
QtWidgets
.
QHBoxLayout
()
...
...
@@ -315,7 +318,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
self
.
showseedpoints
.
setChecked
(
True
)
self
.
setImageCenter
()
g
roup
=
QtWidgets
.
QGroupBox
(
"Detection settings"
,
self
)
self
.
detectParamsG
roup
=
QtWidgets
.
QGroupBox
(
"Detection settings"
,
self
)
grid
=
QtWidgets
.
QGridLayout
()
self
.
parameters
=
[]
checkBoxesToLink
=
{}
...
...
@@ -397,8 +400,8 @@ class ParticleDetectionView(QtWidgets.QWidget):
grid
.
addWidget
(
self
.
showseedpoints
,
i
+
2
,
0
,
1
,
2
,
QtCore
.
Qt
.
AlignLeft
)
grid
.
addWidget
(
QtWidgets
.
QLabel
(
"Click mouse to add seeds, Click+Shift to add deletepoints"
),
i
+
3
,
0
,
1
,
2
,
QtCore
.
Qt
.
AlignLeft
)
grid
.
addWidget
(
QtWidgets
.
QLabel
(
"Click+Alt removes seeds near cursor"
),
i
+
4
,
0
,
1
,
2
,
QtCore
.
Qt
.
AlignLeft
)
g
roup
.
setLayout
(
grid
)
vbox
.
addWidget
(
g
roup
)
self
.
detectParamsG
roup
.
setLayout
(
grid
)
vbox
.
addWidget
(
self
.
detectParamsG
roup
)
self
.
updateSeedsInSampleViewBtn
=
QtWidgets
.
QPushButton
(
"Update Seedpoints in fullimage view"
,
self
)
self
.
updateSeedsInSampleViewBtn
.
released
.
connect
(
self
.
updateSeedsInSampleview
)
...
...
@@ -420,6 +423,9 @@ class ParticleDetectionView(QtWidgets.QWidget):
self
.
autoUpdateCheckBox
.
setChecked
(
True
)
vbox
.
addWidget
(
self
.
autoUpdateCheckBox
)
self
.
progressbar
=
TimeEstimateProgressbar
()
vbox
.
addWidget
(
self
.
progressbar
)
hbox2
=
QtWidgets
.
QHBoxLayout
()
self
.
pdetectsub
=
QtWidgets
.
QPushButton
(
"Detect"
,
self
)
self
.
pdetectall
=
QtWidgets
.
QPushButton
(
"Detect all"
,
self
)
...
...
@@ -634,6 +640,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
self
.
updateImageSeeds
()
def
detectShow
(
self
,
showname
):
if
not
self
.
threadrunning
:
self
.
saveDetectParams
(
self
.
dataset
)
img
=
self
.
subimg
.
copy
()
kwargs
=
{}
...
...
@@ -671,16 +678,26 @@ class ParticleDetectionView(QtWidgets.QWidget):
def
blockUI
(
self
):
self
.
pdetectsub
.
setEnabled
(
False
)
self
.
pclear
.
setEnabled
(
False
)
self
.
detectParamsGroup
.
setEnabled
(
False
)
self
.
updateSeedsInSampleViewBtn
.
setEnabled
(
False
)
self
.
hideSeedsInSampleViewBtn
.
setEnabled
(
False
)
def
unBlockUI
(
self
):
self
.
pdetectsub
.
setEnabled
(
True
)
self
.
pclear
.
setEnabled
(
True
)
self
.
detectParamsGroup
.
setEnabled
(
True
)
self
.
updateSeedsInSampleViewBtn
.
setEnabled
(
True
)
self
.
hideSeedsInSampleViewBtn
.
setEnabled
(
True
)
def
raiseWarning
(
self
,
warning
):
QtWidgets
.
QMessageBox
.
critical
(
self
,
"Warning"
,
warning
)
@
QtCore
.
pyqtSlot
()
def
detectParticles
(
self
):
"""
Detect all particles
:return:
"""
self
.
saveDetectParams
(
self
.
dataset
)
if
self
.
thread
is
not
None
and
self
.
thread
.
is_alive
():
self
.
cancelThread
()
...
...
@@ -700,6 +717,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
if
self
.
thread
is
not
None
:
if
not
self
.
threadrunning
:
self
.
thread
=
None
self
.
progressbar
.
disable
()
self
.
unBlockUI
()
self
.
pdetectall
.
setText
(
"Detect all"
)
self
.
imageUpdate
.
emit
(
self
.
view
.
microscopeMode
)
...
...
@@ -710,6 +728,25 @@ class ParticleDetectionView(QtWidgets.QWidget):
else
:
self
.
timer
.
start
(
100.
)
@
QtCore
.
pyqtSlot
(
str
)
def
updateDetectionState
(
self
,
message
):
"""
Updates the progressbar and its text-label to the current state of the detection
:return:
"""
if
message
.
find
(
'DO'
)
==
-
1
:
self
.
progressbar
.
setMessage
(
message
)
else
:
if
message
.
find
(
'setup'
)
!=
-
1
:
self
.
progressbar
.
resetTimerAndCounter
()
self
.
progressbar
.
enable
()
elif
message
.
find
(
'maxVal'
)
!=
-
1
:
maxVal
=
int
(
message
.
split
(
'='
)[
-
1
])
self
.
progressbar
.
setMaxValue
(
maxVal
)
elif
message
.
find
(
'newVal'
)
!=
-
1
:
newVal
=
int
(
message
.
split
(
'='
)[
-
1
])
self
.
progressbar
.
setValue
(
newVal
)
def
_worker
(
self
):
kwargs
=
{}
seedpoints
,
deletepoints
=
[],
[]
...
...
@@ -722,6 +759,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
self
.
seg
.
setParameters
(
**
kwargs
)
measurementPoints
,
contours
=
self
.
seg
.
apply2Image
(
self
.
img
,
seedpoints
,
deletepoints
,
seedradius
,
self
.
dataset
)
if
measurementPoints
is
None
:
# computation was canceled
return
...
...
opticalscan.py
View file @
38f99d4e
...
...
@@ -28,8 +28,9 @@ import sys, os
import
cv2
from
.helperfunctions
import
cv2imread_fix
,
cv2imwrite_fix
from
time
import
time
import
datetime
import
sys
from
.opticalbackground
import
BackGroundManager
from
.uielements
import
TimeEstimateProgressbar
from
.zlevelsetter
import
ZLevelSetter
from
.scenePyramid
import
ScenePyramid
...
...
@@ -338,11 +339,8 @@ class OpticalScan(QtWidgets.QWidget):
self
.
pexit
.
released
.
connect
(
self
.
stopScan
)
self
.
prun
.
setEnabled
(
False
)
self
.
timelabeltext
=
"Estimated time to finish: "
self
.
progressbar
=
QtWidgets
.
QProgressBar
(
self
)
self
.
progresstime
=
QtWidgets
.
QLabel
(
self
.
timelabeltext
,
self
)
self
.
progresstime
.
setEnabled
(
False
)
self
.
progressbar
.
setEnabled
(
False
)
self
.
progressbar
=
TimeEstimateProgressbar
()
self
.
progressbar
.
disable
()
radioGroup
=
QtWidgets
.
QGroupBox
(
'Shape'
)
radioLayout
=
QtWidgets
.
QHBoxLayout
()
...
...
@@ -404,7 +402,6 @@ class OpticalScan(QtWidgets.QWidget):
optionsLayout
.
addLayout
(
vbox2
)
mainLayout
.
addLayout
(
optionsLayout
)
mainLayout
.
addWidget
(
self
.
progresstime
)
mainLayout
.
addWidget
(
self
.
progressbar
)
mainLayout
.
addLayout
(
btnLayout
)
...
...
@@ -441,6 +438,7 @@ class OpticalScan(QtWidgets.QWidget):
QtWidgets
.
QMessageBox
.
Yes
|
QtWidgets
.
QMessageBox
.
No
,
QtWidgets
.
QMessageBox
.
No
)
if
reply
==
QtWidgets
.
QMessageBox
.
Yes
:
self
.
progressbar
.
resetTimerAndCounter
()
self
.
timer
.
stop
()
self
.
processstopevent
.
set
()
self
.
process
.
join
()
...
...
@@ -684,12 +682,9 @@ class OpticalScan(QtWidgets.QWidget):
self
.
dataqueue
,
self
.
processstopevent
,
self
.
logpath
,
self
.
hdrcheck
.
isChecked
()))
self
.
process
.
start
()
self
.
starttime
=
time
()
self
.
progresstime
.
setEnabled
(
True
)
self
.
progressbar
.
setEnabled
(
True
)
self
.
progressbar
.
setRange
(
0
,
len
(
self
.
dataset
.
grid
))
self
.
progressbar
.
setValue
(
0
)
#self.view.imgdata = None
self
.
progressbar
.
enable
()
self
.
progressbar
.
resetTimerAndCounter
()
self
.
progressbar
.
setMaxValue
(
len
(
self
.
dataset
.
grid
))
self
.
pyramid
.
resetScene
()
self
.
view
.
blockUI
()
grid
=
np
.
asarray
(
self
.
dataset
.
grid
)
...
...
@@ -734,14 +729,7 @@ class OpticalScan(QtWidgets.QWidget):
removeSrcTiles
(
names
,
self
.
dataset
.
getScanPath
())
self
.
progressbar
.
setValue
(
i
+
1
)
if
i
>
3
:
timerunning
=
time
()
-
self
.
starttime
ttot
=
timerunning
*
Ngrid
/
(
i
+
1
)
time2go
=
ttot
-
timerunning
self
.
progresstime
.
setText
(
self
.
timelabeltext
+
str
(
datetime
.
timedelta
(
seconds
=
round
(
time2go
))))
# reload image in sampleview, calls loadPixmap
# not needed anymore as the scene gets manipulated directly via self.pyramid
# self.imageUpdate.emit(self.view.microscopeMode)
self
.
imageUpdate
.
emit
(
self
.
view
.
microscopeMode
)
if
i
==
Ngrid
-
1
:
# cv2imwrite_fix(self.dataset.getImageName(), cv2.cvtColor(self.view.imgdata, cv2.COLOR_RGB2BGR))
...
...
@@ -756,9 +744,8 @@ class OpticalScan(QtWidgets.QWidget):
self
.
view
.
saveDataSet
()
self
.
view
.
unblockUI
()
self
.
view
.
switchMode
(
"ParticleDetection"
)
self
.
progressbar
.
setValue
(
0
)
self
.
progressbar
.
setEnabled
(
False
)
self
.
progresstime
.
setEnabled
(
False
)
self
.
progressbar
.
resetTimerAndCounter
()
self
.
progressbar
.
disable
()
self
.
close
()
return
self
.
timer
.
start
(
100.
)
...
...
ramanscanui.py
View file @
38f99d4e
...
...
@@ -24,10 +24,10 @@ import numpy as np
from
multiprocessing
import
Process
,
Queue
,
Event
import
queue
from
time
import
time
from
.external
import
tsp
import
datetime
import
sys
import
os
from
.external
import
tsp
from
.uielements
import
TimeEstimateProgressbar
def
reorder
(
points
,
N
=
20
):
y0
,
y1
=
points
[:,
1
].
min
(),
points
[:,
1
].
max
()
...
...
@@ -110,18 +110,15 @@ class RamanScanUI(QtWidgets.QWidget):
self
.
pexit
=
QtWidgets
.
QPushButton
(
"Cancel"
,
self
)
self
.
pexit
.
released
.
connect
(
self
.
stopScan
)
self
.
prun
.
setEnabled
(
False
)
self
.
progressbar
=
QtWidgets
.
QProgressBar
(
self
)
self
.
timelabeltext
=
"Estimated time to finish: "
self
.
progresstime
=
QtWidgets
.
QLabel
(
self
.
timelabeltext
,
self
)
self
.
progresstime
.
setEnabled
(
False
)
self
.
progressbar
.
setEnabled
(
False
)
self
.
progressbar
=
TimeEstimateProgressbar
()
self
.
progressbar
.
disable
()
hbox
.
addStretch
()
hbox
.
addWidget
(
self
.
pexit
)
vbox
.
addWidget
(
self
.
paramsGroup
)
vbox
.
addLayout
(
hbox
)
vbox
.
addWidget
(
self
.
progresstime
)
vbox
.
addWidget
(
self
.
progressbar
)
self
.
setLayout
(
vbox
)
...
...
@@ -189,6 +186,7 @@ class RamanScanUI(QtWidgets.QWidget):
QtWidgets
.
QMessageBox
.
No
,
QtWidgets
.
QMessageBox
.
No
)
if
reply
==
QtWidgets
.
QMessageBox
.
Yes
:
self
.
timer
.
stop
()
self
.
progressbar
.
resetTimerAndCounter
()
self
.
processstopevent
.
set
()
self
.
process
.
join
()
self
.
dataqueue
.
close
()
...
...
@@ -264,10 +262,9 @@ class RamanScanUI(QtWidgets.QWidget):
self
.
view
.
highLightRamanIndex
(
0
)
self
.
view
.
blockUI
()
self
.
paramsGroup
.
setEnabled
(
False
)
self
.
progresstime
.
setEnabled
(
True
)
self
.
progressbar
.
setEnabled
(
True
)
self
.
progressbar
.
setRange
(
0
,
len
(
scanpoints
))
self
.
progressbar
.
setValue
(
0
)
self
.
progressbar
.
enable
()
self
.
progressbar
.
resetTimerAndCounter
()
self
.
progressbar
.
setMaxValue
(
len
(
scanpoints
))
self
.
ramanctrl
.
disconnect
()
self
.
processstopevent
=
Event
()
self
.
dataqueue
=
Queue
()
...
...
@@ -295,11 +292,6 @@ class RamanScanUI(QtWidgets.QWidget):
self
.
view
.
highLightRamanIndex
(
i
+
1
)
#go to next scanmarker
Npoints
=
len
(
self
.
dataset
.
particleContainer
.
getMeasurementPixelCoords
())
if
i
>
3
:
timerunning
=
time
()
-
self
.
starttime
ttot
=
timerunning
*
Npoints
/
(
i
+
1
)
time2go
=
ttot
-
timerunning
self
.
progresstime
.
setText
(
self
.
timelabeltext
+
str
(
datetime
.
timedelta
(
seconds
=
round
(
time2go
))))
if
i
==
Npoints
-
1
:
self
.
process
.
join
()
self
.
dataqueue
.
close
()
...
...
@@ -307,9 +299,8 @@ class RamanScanUI(QtWidgets.QWidget):
self
.
dataset
.
ramanscandone
=
True
self
.
view
.
saveDataSet
()
self
.
view
.
unblockUI
()
self
.
progressbar
.
setValue
(
0
)
self
.
progressbar
.
setEnabled
(
False
)
self
.
progresstime
.
setEnabled
(
False
)
self
.
progressbar
.
resetTimerAndCounter
()
self
.
progressbar
.
disable
()
self
.
close
()
return
self
.
timer
.
start
(
100.
)
...
...
segmentation.py
View file @
38f99d4e
...
...
@@ -28,6 +28,8 @@ from skimage.feature import peak_local_max
from
skimage.morphology
import
watershed
import
skfuzzy
as
fuzz
import
random
from
PyQt5
import
QtCore
def
closeHolesOfSubImage
(
subimg
):
subimg
=
cv2
.
copyMakeBorder
(
subimg
,
1
,
1
,
1
,
1
,
0
)
...
...
@@ -63,8 +65,10 @@ class MeasurementPoint(object):
self
.
x
=
x
self
.
y
=
y
class
Segmentation
(
object
):
class
Segmentation
(
QtCore
.
QObject
):
detectionState
=
QtCore
.
pyqtSignal
(
str
)
def
__init__
(
self
,
dataset
=
None
,
parent
=
None
):
super
(
Segmentation
,
self
).
__init__
()
self
.
cancelcomputation
=
False
self
.
parent
=
parent
self
.
defaultParams
=
{
'adaptiveHistEqu'
:
False
,
...
...
@@ -84,6 +88,7 @@ class Segmentation(object):
'minparticledistance'
:
20
,
'closeBackground'
:
False
,
'fuzzycluster'
:
False
,
'maxComponentSize'
:
20000
,
'measurefrac'
:
1
,
'compactness'
:
0.0
,
'seedRad'
:
3
}
...
...
@@ -115,6 +120,7 @@ class Segmentation(object):
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
),
Parameter
(
"fuzzycluster"
,
np
.
bool
,
self
.
detectParams
[
'fuzzycluster'
],
helptext
=
'Enable Fuzzy Clustering'
,
show
=
False
),
Parameter
(
"maxComponentSize"
,
int
,
self
.
detectParams
[
'maxComponentSize'
],
100
,
1E6
,
0
,
100
,
helptext
=
'Maximum size in x or y of connected component.
\n
Larger components are scaled down accordingly'
,
show
=
False
),
Parameter
(
"sure_fg"
,
None
,
helptext
=
"Show sure foreground"
,
show
=
True
),
Parameter
(
"compactness"
,
float
,
self
.
detectParams
[
'compactness'
],
0
,
1
,
2
,
0.05
,
helptext
=
"watershed compactness"
,
show
=
False
),
Parameter
(
"watershed"
,
None
,
helptext
=
"Show watershed markers"
,
show
=
True
),
...
...
@@ -140,8 +146,10 @@ class Segmentation(object):
:return:
"""
t0
=
time
()
self
.
detectionState
.
emit
(
'DO: setup'
)
gray
=
self
.
convert2Gray
(
img
)
self
.
detectionState
.
emit
(
'finished GrayScale'
)
print
(
"gray"
)
if
self
.
adaptiveHistEqu
:
...
...
@@ -149,6 +157,7 @@ class Segmentation(object):
numTilesY
=
round
(
img
.
shape
[
0
]
/
self
.
claheTileSize
)
clahe
=
cv2
.
createCLAHE
(
clipLimit
=
2.0
,
tileGridSize
=
(
numTilesY
,
numTilesX
))
gray
=
clahe
.
apply
(
gray
)
self
.
detectionState
.
emit
(
'finished CLAHE'
)
if
return_step
==
"claheTileSize"
:
return
gray
,
0
print
(
"adaptive Histogram Adjustment"
)
...
...
@@ -159,6 +168,7 @@ class Segmentation(object):
xi
,
arr
=
self
.
calculateHistFunction
(
self
.
contrastCurve
)
gray
=
arr
[
gray
]
print
(
"contrast curve"
)
self
.
detectionState
.
emit
(
'finished Contrast Curve'
)
if
self
.
cancelcomputation
:
return
None
,
None
...
...
@@ -171,6 +181,7 @@ class Segmentation(object):
del
gray
if
return_step
==
"blurRadius"
:
return
blur
,
0
self
.
detectionState
.
emit
(
'finished Blurring'
)
print
(
"blur"
)
if
self
.
cancelcomputation
:
return
None
,
None
...
...
@@ -215,6 +226,7 @@ class Segmentation(object):
thresh
=
self
.
closeBrightHoles
(
thresh
,
blur
,
self
.
maxholebrightness
)
del
blur
print
(
"thresholded"
)
self
.
detectionState
.
emit
(
'finished thresholding'
)
# modify thresh with seedpoints and deletepoints
for
p
in
np
.
int32
(
seedpoints
):
...
...
@@ -235,6 +247,8 @@ class Segmentation(object):
'''the peak_local_max function takes the min distance between peaks. Unfortunately, that means that individual
particles smaller than that distance are consequently disregarded. Hence, we need a connectec_components approach'''
n
,
labels
,
stats
,
centroids
=
cv2
.
connectedComponentsWithStats
(
thresh
,
8
,
cv2
.
CV_32S
)
self
.
detectionState
.
emit
(
'finished connected components search'
)
self
.
detectionState
.
emit
(
f
'DO: maxVal=
{
n
-
1
}
'
)
del
thresh
measurementPoints
=
{}
...
...
@@ -249,7 +263,6 @@ class Segmentation(object):
else
:
previewImage
=
np
.
zeros
(
img
.
shape
[:
2
])
for
label
in
range
(
1
,
n
):
area
=
stats
[
label
,
cv2
.
CC_STAT_AREA
]
if
self
.
minparticlearea
<
area
<
maxArea
:
...
...
@@ -257,26 +270,35 @@ class Segmentation(object):
left
=
stats
[
label
,
cv2
.
CC_STAT_LEFT
]
width
=
stats
[
label
,
cv2
.
CC_STAT_WIDTH
]
height
=
stats
[
label
,
cv2
.
CC_STAT_HEIGHT
]
# if width > 25000 or height > 25000:
if
False
:
print
(
f
'skipping
{
label
}
of
{
n
}
compontents, too large:
{
width
}
x
{
height
}
pixel!!!'
)
else
:
print
(
f
'processing
{
label
}
of
{
n
}
compontents,
{
width
}
x
{
height
}
pixel'
)
subthresh
=
np
.
uint8
(
255
*
(
labels
[
up
:(
up
+
height
),
left
:(
left
+
width
)]
==
label
))
scaleFactor
=
1.0
if
width
>
self
.
maxComponentSize
or
height
>
self
.
maxComponentSize
:
scaleFactor
=
max
([
width
/
self
.
maxComponentSize
,
height
/
self
.
maxComponentSize
])
subthresh
=
cv2
.
resize
(
subthresh
,
None
,
fx
=
1
/
scaleFactor
,
fy
=
1
/
scaleFactor
)
subdist
=
cv2
.
distanceTransform
(
subthresh
,
cv2
.
DIST_L2
,
3
)
sure_fg
=
self
.
getSureForeground
(
subthresh
,
subdist
,
self
.
minparticledistance
)
minDistance
=
round
(
self
.
minparticledistance
/
scaleFactor
)
sure_fg
=
self
.
getSureForeground
(
subthresh
,
subdist
,
minDistance
)
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
)
x
=
int
(
round
(
p
[
0
]
/
scaleFactor
)
-
left
)
y
=
int
(
round
(
p
[
1
]
/
scaleFactor
)
-
up
)
radius
=
int
(
round
(
p
[
2
]
/
scaleFactor
))
cv2
.
circle
(
sure_fg
,
(
x
,
y
),
radius
,
1
,
-
1
)
cv2
.
circle
(
sure_bg
,
(
x
,
y
),
radius
,
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
)
x
=
int
(
round
(
p
[
0
]
/
scaleFactor
)
-
left
)
y
=
int
(
round
(
p
[
1
]
/
scaleFactor
)
-
up
)
radius
=
int
(
round
(
p
[
2
]
/
scaleFactor
))
cv2
.
circle
(
sure_fg
,
(
x
,
y
),
radius
,
1
,
-
1
)
cv2
.
circle
(
sure_bg
,
(
x
,
y
),
radius
,
1
,
-
1
)
if
self
.
cancelcomputation
:
return
None
,
None
...
...
@@ -293,7 +315,11 @@ class Segmentation(object):
markers
[
unknown
==
255
]
=
0
markers
=
ndi
.
label
(
sure_fg
)[
0
]
try
:
markers
=
watershed
(
-
subdist
,
markers
,
mask
=
sure_bg
,
compactness
=
self
.
compactness
,
watershed_line
=
True
)
#labels = 0 for background, 1... for particles
except
MemoryError
:
self
.
parent
.
raiseWarning
(
'Segmentation failed due to large connected components.
\n
Please reduce maximal connected Component Size.'
)
return
None
,
None
if
self
.
cancelcomputation
:
return
None
,
None
...
...
@@ -312,17 +338,28 @@ class Segmentation(object):
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
:
contourArea
=
cv2
.
contourArea
(
cnt
)
*
scaleFactor
**
2
if
contourArea
>=
self
.
minparticlearea
:
tmplabel
=
markers
[
cnt
[
0
,
0
,
1
],
cnt
[
0
,
0
,
0
]]
if
tmplabel
==
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
subimg
[
subimg
!=
tmp
label
]
=
0
y
,
x
=
self
.
getMeasurementPoints
(
subimg
)
if
scaleFactor
!=
1
:
x0
=
int
(
round
(
x0
*
scaleFactor
))
y0
=
int
(
round
(
y0
*
scaleFactor
))
x
=
[
int
(
round
(
subX
*
scaleFactor
))
for
subX
in
x
]
y
=
[
int
(
round
(
subY
*
scaleFactor
))
for
subY
in
y
]
for
i
in
range
(
len
(
cnt
)):
cnt
[
i
][
0
][
0
]
=
int
(
round
(
cnt
[
i
][
0
][
0
]
*
scaleFactor
))
cnt
[
i
][
0
][
1
]
=
int
(
round
(
cnt
[
i
][
0
][
1
]
*
scaleFactor
))
for
i
in
range
(
len
(
cnt
)):
cnt
[
i
][
0
][
0
]
+=
left
cnt
[
i
][
0
][
1
]
+=
up
...
...
@@ -333,8 +370,11 @@ class Segmentation(object):
for
index
in
range
(
0
,
len
(
x
)):
newMeasPoint
=
MeasurementPoint
(
particleIndex
,
x
[
index
]
+
x0
+
left
,
y
[
index
]
+
y0
+
up
)
measurementPoints
[
particleIndex
].
append
(
newMeasPoint
)
particleIndex
+=
1
self
.
detectionState
.
emit
(
f
'DO: newVal=
{
label
}
'
)
if
return_step
==
'sure_fg'
:
img
=
np
.
zeros_like
(
preview_surefg
)
img
[
np
.
nonzero
(
preview_surefg
)]
|=
1
...
...
@@ -360,6 +400,8 @@ class Segmentation(object):
total_time
=
time
()
-
t0
print
(
'segmentation took'
,
total_time
,
'seconds'
)
total_time
=
round
(
total_time
,
2
)
self
.
detectionState
.
emit
(
f
'finished particle detection after
{
total_time
}
seconds'
)
return
measurementPoints
,
finalcontours
...
...
uielements.py
0 → 100644
View file @
38f99d4e
#!/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/>.
"""
from
PyQt5
import
QtWidgets
from
time
import
time
import
datetime
class
TimeEstimateProgressbar
(
QtWidgets
.
QGroupBox
):
"""
A progressbar with time estimate for computationally expensive tasks. It contains the actual progressbar together
with a text label that is updated accordingly. It also estimates the remaining progress time.
Call enable and disable-methods for optically enabling and disabling the widgets.
Call resetTimerAndCounter before the process starts,
Then set the maxValue using the setMaxValue method.
Finally, for pushing an update, use the setValue method. It will update the text label as well.
Furthermore, a text message can be pushed to the text label at any time, using the setMessage method.
:return:
"""
def
__init__
(
self
):
super
(
TimeEstimateProgressbar
,
self
).
__init__
()
layout
=
QtWidgets
.
QVBoxLayout
()
self
.
setLayout
(
layout
)
self
.
timelabeltext
=
"Estimated time to finish: - "
self
.
progressbar
=
QtWidgets
.
QProgressBar
(
self
)
self
.
progresstime
=
QtWidgets
.
QLabel
(
self
.
timelabeltext
,
self
)
self
.
progresstime
.
setEnabled
(
False
)
self
.
progressbar
.
setEnabled
(
False
)
self
.
maxVal
=
None
self
.
startTime
=
None
layout
.
addWidget
(
self
.
progresstime
)
layout
.
addWidget
(
self
.
progressbar
)
def
setMaxValue
(
self
,
maxVal
):
"""
Sets the maximal value of the progressbar. Also needed for estimating remaining time.
:return:
"""
self
.
maxVal
=
maxVal
self
.
progressbar
.
setRange
(
0
,
self
.
maxVal
)
def
enable
(
self
):
"""
Enables the UI widgets.
:return:
"""
self
.
progressbar
.
setEnabled
(
True
)
self
.
progresstime
.
setEnabled
(
True
)
def
disable
(
self
):
"""
Disables the UI widgets.
:return:
"""
self
.
progressbar
.
setEnabled
(
False
)
self
.
progresstime
.
setEnabled
(
False
)
def
resetTimerAndCounter
(
self
):
"""
Resets the timer and sets the progressbar to value 0
:return:
"""
self
.
startTime
=
time
()
self
.
progressbar
.
setValue
(
0
)
def
setMessage
(
self
,
msg
):
"""
Pushes a message to the progressbar's textlabel.
:return:
"""
self
.
progresstime
.
setText
(
msg
)
def
setValue
(
self
,
newValue
):
"""
Sets the value of the progressbar and calls updating the TimeLabel
:return:
"""
self
.
progressbar
.
setValue
(
newValue
)
self
.
_updatetTimeLabel
()
def
_updatetTimeLabel
(
self
):
"""
Calculates remaining Time and updates the label.
:return:
"""
if
self
.
progressbar
.
value
()
>
3
:
timerunning
=
time
()
-
self
.
startTime
ttot
=
timerunning
*
self
.
maxVal
/
(
self
.
progressbar
.
value
()
+
1
)
time2go
=
ttot
-
timerunning
self
.
progresstime
.
setText
(
self
.
timelabeltext
+
str
(
datetime
.
timedelta
(
seconds
=
round
(
time2go
))))
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment