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
Hide 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
)
...
...
@@ -419,6 +422,9 @@ class ParticleDetectionView(QtWidgets.QWidget):
self
.
autoUpdateCheckBox
.
setMaximumWidth
(
200
)
self
.
autoUpdateCheckBox
.
setChecked
(
True
)
vbox
.
addWidget
(
self
.
autoUpdateCheckBox
)
self
.
progressbar
=
TimeEstimateProgressbar
()
vbox
.
addWidget
(
self
.
progressbar
)
hbox2
=
QtWidgets
.
QHBoxLayout
()
self
.
pdetectsub
=
QtWidgets
.
QPushButton
(
"Detect"
,
self
)
...
...
@@ -634,21 +640,22 @@ class ParticleDetectionView(QtWidgets.QWidget):
self
.
updateImageSeeds
()
def
detectShow
(
self
,
showname
):
self
.
saveDetectParams
(
self
.
dataset
)
img
=
self
.
subimg
.
copy
()
kwargs
=
{}
for
ui
,
name
,
valuefunc
,
showbtn
in
self
.
parameters
:
kwargs
[
name
]
=
valuefunc
()
self
.
seg
.
setParameters
(
**
kwargs
)
seedradius
=
self
.
seedradiusedit
.
value
()
if
showname
is
not
None
:
stepImg
,
imgtype
=
self
.
seg
.
apply2Image
(
img
,
self
.
imglabel
.
seedpoints
,
self
.
imglabel
.
seeddeletepoints
,
seedradius
,
self
.
dataset
,
return_step
=
showname
)
self
.
imglabel
.
showStep
(
stepImg
,
imgtype
)
else
:
measurementpoints
,
contours
=
self
.
seg
.
apply2Image
(
img
,
self
.
imglabel
.
seedpoints
,
self
.
imglabel
.
seeddeletepoints
,
seedradius
,
self
.
dataset
)
self
.
imglabel
.
updateDetectionResults
(
contours
,
measurementpoints
)
if
not
self
.
threadrunning
:
self
.
saveDetectParams
(
self
.
dataset
)
img
=
self
.
subimg
.
copy
()
kwargs
=
{}
for
ui
,
name
,
valuefunc
,
showbtn
in
self
.
parameters
:
kwargs
[
name
]
=
valuefunc
()
self
.
seg
.
setParameters
(
**
kwargs
)
seedradius
=
self
.
seedradiusedit
.
value
()
if
showname
is
not
None
:
stepImg
,
imgtype
=
self
.
seg
.
apply2Image
(
img
,
self
.
imglabel
.
seedpoints
,
self
.
imglabel
.
seeddeletepoints
,
seedradius
,
self
.
dataset
,
return_step
=
showname
)
self
.
imglabel
.
showStep
(
stepImg
,
imgtype
)
else
:
measurementpoints
,
contours
=
self
.
seg
.
apply2Image
(
img
,
self
.
imglabel
.
seedpoints
,
self
.
imglabel
.
seeddeletepoints
,
seedradius
,
self
.
dataset
)
self
.
imglabel
.
updateDetectionResults
(
contours
,
measurementpoints
)
@
QtCore
.
pyqtSlot
()
def
clearDetection
(
self
):
...
...
@@ -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
)
...
...
@@ -709,6 +727,25 @@ class ParticleDetectionView(QtWidgets.QWidget):
self
.
setWindowTitle
(
f
'
{
numParticles
}
Particles (
{
numMeasurements
}
Measurements)'
)
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
=
{}
...
...
@@ -720,8 +757,9 @@ class ParticleDetectionView(QtWidgets.QWidget):
kwargs
[
name
]
=
valuefunc
()
seedradius
=
self
.
seedradiusedit
.
value
()
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
...
...
@@ -337,13 +338,10 @@ class OpticalScan(QtWidgets.QWidget):
self
.
prun
.
released
.
connect
(
self
.
run
)
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
()
self
.
circlerad
=
QtWidgets
.
QRadioButton
(
"Circle"
)
...
...
@@ -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
):
def
__init__
(
self
,
dataset
=
None
,
parent
=
None
):
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"
)
...
...
@@ -158,7 +167,8 @@ class Segmentation(object):
if
self
.
activateContrastCurve
:
xi
,
arr
=
self
.
calculateHistFunction
(
self
.
contrastCurve
)
gray
=
arr
[
gray
]
print
(
"contrast curve"
)
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,83 +270,110 @@ 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
))
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
]
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
)
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
):
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
):
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
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
]
try
:
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
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
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
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
tmpcontours
=
[
contours
[
i
]
for
i
in
range
(
len
(
contours
))
if
hierarchy
[
0
,
i
,
3
]
<
0
]
for
cnt
in
tmpcontours
:
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
()
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
)
subimg
=
(
markers
[
y0
:
y1
+
1
,
x0
:
x1
+
1
]).
copy
()
subimg
[
subimg
!=
tmplabel
]
=
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
]
+
=
left
cnt
[
i
][
0
][
1
]
+
=
up
cnt
[
i
][
0
][
0
]
=
int
(
round
(
cnt
[
i
][
0
][
0
]
*
scaleFactor
))
cnt
[
i
][
0
][
1
]
=
int
(
round
(
cnt
[
i
][
0
][
1
]
*
scaleFactor
))
finalcontours
.
append
(
cnt
)
measurementPoints
[
particleIndex
]
=
[]
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
)
for
index
in
range
(
0
,
len
(
x
)):
newMeasPoint
=
MeasurementPoint
(
particleIndex
,
x
[
index
]
+
x0
+
left
,
y
[
index
]
+
y0
+
up
)
measurementPoints
[
particleIndex
].
append
(
newMeasPoint
)
particleIndex
+=
1
particleIndex
+=
1
self
.
detectionState
.
emit
(
f
'DO: newVal=
{
label
}
'
)
if
return_step
==
'sure_fg'
:
img
=
np
.
zeros_like
(
preview_surefg
)
...
...
@@ -360,6 +400,8 @@ class Segmentation(object):
total_time
=
time
()
-
t0
print
(
'segmentation took'
,
total_time
,
'seconds'
)