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
819efb02
Commit
819efb02
authored
Nov 14, 2019
by
Robert
Committed by
Robert Ohmacht
Nov 14, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
-initial integration of ScenePyramid from GepardEvaluation into Gepard
parent
1fff5fef
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1906 additions
and
883 deletions
+1906
-883
dataset.py
dataset.py
+15
-0
detectionview.py
detectionview.py
+65
-26
legacyConvert.py
legacyConvert.py
+8
-1
opticalbackground.py
opticalbackground.py
+1
-1
opticalscan.py
opticalscan.py
+60
-31
sampleview.py
sampleview.py
+858
-824
scenePyramid.py
scenePyramid.py
+899
-0
No files found.
dataset.py
View file @
819efb02
...
...
@@ -135,6 +135,9 @@ class DataSet(object):
self
.
coordinatetransform
=
None
# if imported form extern source coordinate system may be rotated
self
.
signx
=
1.
self
.
signy
=
-
1.
# tiling parameters
self
.
pyramidParams
=
None
# parameters specifically for raman scan
self
.
pshift
=
None
# shift of raman scan position relative to image center
...
...
@@ -169,6 +172,12 @@ class DataSet(object):
def
__eq__
(
self
,
other
):
return
recursiveDictCompare
(
self
.
__dict__
,
other
.
__dict__
)
def
getPyramidParams
(
self
):
return
self
.
pyramidParams
def
setPyramidParams
(
self
,
pyramid_params
):
self
.
pyramidParams
=
pyramid_params
def
getPixelScale
(
self
,
mode
=
None
):
if
mode
is
None
:
...
...
@@ -275,6 +284,12 @@ class DataSet(object):
self
.
__dict__
.
update
(
loadData
(
fname
).
__dict__
)
return
fname
def
getTilePath
(
self
):
scandir
=
os
.
path
.
join
(
self
.
path
,
"tiles"
)
if
not
os
.
path
.
exists
(
scandir
):
os
.
mkdir
(
scandir
)
return
scandir
def
getScanPath
(
self
):
scandir
=
os
.
path
.
join
(
self
.
path
,
"scanimages"
)
if
not
os
.
path
.
exists
(
scandir
):
...
...
detectionview.py
View file @
819efb02
...
...
@@ -27,6 +27,7 @@ from threading import Thread
from
.segmentation
import
Segmentation
from
.analysis.particleCharacterization
import
getParticleStatsWithPixelScale
,
loadZValImageFromDataset
from
.errors
import
InvalidParticleError
from
.scenePyramid
import
ScenePyramid
Nscreen
=
1000
...
...
@@ -269,14 +270,15 @@ class ParticleDetectionView(QtWidgets.QWidget):
imageUpdate
=
QtCore
.
pyqtSignal
(
str
,
name
=
'imageUpdate'
)
#str = 'df' (= darkfield) or 'bf' (=bright field)
detectionFinished
=
QtCore
.
pyqtSignal
(
name
=
'detectionFinished'
)
def
__init__
(
self
,
img
,
dataset
,
parent
=
None
):
def
__init__
(
self
,
pyramid
:
ScenePyramid
,
dataset
,
parent
=
None
):
super
().
__init__
(
parent
,
QtCore
.
Qt
.
Window
)
self
.
dataset
=
self
.
verifySeedpoints
(
dataset
)
self
.
img
=
img
self
.
imgclip
=
0
,
0
,
0
,
0
self
.
pyramid
=
pyramid
self
.
img
=
pyramid
.
getFullImage
(.
5
)
self
.
imgclip
=
0
,
0
,
0
,
0
self
.
seg
=
Segmentation
(
self
.
dataset
,
self
)
self
.
thread
=
None
self
.
view
=
parent
self
.
view
:
QtWidgets
.
QGraphicsView
=
parent
vbox
=
QtWidgets
.
QVBoxLayout
()
hbox
=
QtWidgets
.
QHBoxLayout
()
...
...
@@ -529,33 +531,69 @@ class ParticleDetectionView(QtWidgets.QWidget):
self
.
updateImageSeeds
()
def
setImageCenter
(
self
,
center
=
None
):
'''
as more than the tiles are part of the scene
bounding rect may be bigger than just a rect around the tiles
tiles should be grouped
'''
width
,
height
=
self
.
pyramid
.
getBoundingRectDim
()
if
center
is
None
:
centerx
=
self
.
img
.
shape
[
1
]
//
2
centery
=
self
.
img
.
shape
[
0
]
//
2
centerx
=
width
//
2
centery
=
height
//
2
else
:
centerx
,
centery
=
center
if
self
.
img
.
shape
[
0
]
<
Nscreen
:
centery
=
self
.
img
.
shape
[
0
]
//
2
if
self
.
img
.
shape
[
1
]
<
Nscreen
:
centerx
=
self
.
img
.
shape
[
1
]
//
2
if
height
<
Nscreen
:
centery
=
height
//
2
if
width
<
Nscreen
:
centerx
=
width
//
2
if
not
self
.
drag
:
self
.
lastcenter
=
centerx
,
centery
n1
,
n2
=
int
(
centery
-
Nscreen
//
2
),
int
(
centery
+
Nscreen
//
2
+
1
)
m1
,
m2
=
int
(
centerx
-
Nscreen
//
2
),
int
(
centerx
+
Nscreen
//
2
+
1
)
if
n1
<
0
:
n2
-=
n1
n1
=
0
if
n2
>
self
.
img
.
shape
[
0
]:
n1
-=
n2
-
self
.
img
.
shape
[
0
]
if
n1
<
0
:
n1
=
0
n2
=
self
.
img
.
shape
[
0
]
if
m1
<
0
:
m2
-=
m1
m1
=
0
if
m2
>
self
.
img
.
shape
[
1
]:
m1
-=
m2
-
self
.
img
.
shape
[
1
]
if
m1
<
0
:
m1
=
0
m2
=
self
.
img
.
shape
[
1
]
y1
,
y2
=
centery
-
Nscreen
//
2
,
centery
+
Nscreen
//
2
+
1
x1
,
x2
=
centerx
-
Nscreen
//
2
,
centerx
+
Nscreen
//
2
+
1
if
y1
<
0
:
y2
-=
y1
y1
=
0
if
y2
>
height
:
y1
-=
y2
-
height
if
y1
<
0
:
y1
=
0
y2
=
height
if
x1
<
0
:
x2
-=
x1
x1
=
0
if
x2
>
width
:
x1
-=
x2
-
width
if
x1
<
0
:
x1
=
0
x2
=
width
self
.
imgclip
=
int
(
y1
),
int
(
y2
),
int
(
x1
),
int
(
x2
)
self
.
subimg
,
pix
=
self
.
pyramid
.
getSubImage
(
self
.
imgclip
)
'''
img = QtGui.QImage(x2 - x1, y2 - y1, QtGui.QImage.Format_RGB888)
self.view.scene().render(
QtGui.QPainter(img),
QtCore.QRectF(0, 0, img.width(), img.height()),
#QtCore.QRectF(x1 + x0, y1 + y0, x2 - x1, y2 - y1)
QtCore.QRectF(x1, y1, x2 - x1, y2 - y1)
)
#pix = self.view.grab(QtCore.QRect(x1 + x0, y1 + y0, x2 - x1, y2 - y1))
# @see https://stackoverflow.com/a/11399959
#img = pix.toImage().convertToFormat(QtGui.QImage.Format_RGB888)
ptr = img.bits()
#ptr.setsize(img.byteCount())
ptr.setsize(img.height() * img.width() * 3)
self.subimg = np.asarray(ptr).reshape(img.height(), img.width(), 3)
pix = QtGui.QPixmap()
pix.convertFromImage(img)
'''
'''
sub = self.img[n1:n2,m1:m2,:].copy()
self.imgclip = n1,n2,m1,m2
self.subimg = sub
...
...
@@ -564,6 +602,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
pix = QtGui.QPixmap()
pix.convertFromImage(QtGui.QImage(sub.data, width, height,
bytesPerLine, QtGui.QImage.Format_RGB888))
'''
self
.
imglabel
.
clearData
()
self
.
imglabel
.
setPixmap
(
pix
)
self
.
updateImageSeeds
()
...
...
legacyConvert.py
View file @
819efb02
...
...
@@ -27,8 +27,9 @@ from .helperfunctions import cv2imread_fix, cv2imwrite_fix
from
.analysis.particleContainer
import
ParticleContainer
from
.analysis
import
particleCharacterization
as
pc
from
.errors
import
InvalidParticleError
from
.scenePyramid
import
ScenePyramid
currentVersion
=
4
currentVersion
=
5
def
legacyConversion
(
dset
,
recreatefullimage
=
False
):
if
dset
.
version
==
0
:
...
...
@@ -110,6 +111,12 @@ def legacyConversion(dset, recreatefullimage=False):
removeLegacyAttributes
(
dset
)
dset
.
version
=
4
dset
.
save
()
if
dset
.
version
==
4
:
print
(
"Converting legacy version 4 to 5"
)
ScenePyramid
.
createFromFullImage
(
dset
)
dset
.
version
=
5
dset
.
save
()
# add later conversion for higher version numbers here
...
...
opticalbackground.py
View file @
819efb02
...
...
@@ -106,7 +106,7 @@ class BackGroundManager(QtWidgets.QWidget):
p0
=
[
points
[:,
0
].
min
(),
points
[:,
1
].
max
()]
p1
=
[
points
[:,
0
].
max
(),
points
[:,
1
].
min
()]
reply
=
QtWidgets
.
QMessageBox
.
question
(
self
,
'Message'
,
f
"The stage will move
{
round
(
3
*
width
)
}
in x and
{
round
(
3
*
height
)
}
in y.
\n
Continue?"
,
reply
=
QtWidgets
.
QMessageBox
.
question
(
self
,
'Message'
,
f
"The stage will move
{
round
(
3
*
width
)
}
in x and
{
round
(
3
*
height
)
}
in y.
\n
Continue?"
,
QtWidgets
.
QMessageBox
.
Yes
|
QtWidgets
.
QMessageBox
.
No
,
QtWidgets
.
QMessageBox
.
No
)
if
reply
==
QtWidgets
.
QMessageBox
.
Yes
:
fullimg
=
None
...
...
opticalscan.py
View file @
819efb02
...
...
@@ -31,6 +31,7 @@ from time import time
import
datetime
from
.opticalbackground
import
BackGroundManager
from
.zlevelsetter
import
ZLevelSetter
from
.scenePyramid
import
ScenePyramid
def
scan
(
path
,
sol
,
zpositions
,
grid
,
controlclass
,
dataqueue
,
stopevent
,
logpath
=
''
,
ishdr
=
False
):
...
...
@@ -84,10 +85,10 @@ def scan(path, sol, zpositions, grid, controlclass, dataqueue,
def
subtractBackground
(
image
,
background
):
avg
=
np
.
mean
(
background
)
subtracted
=
np
.
clip
(
np
.
array
(
image
-
background
+
avg
,
dtype
=
np
.
uint8
),
0
,
255
)
subtracted
=
np
.
clip
(
np
.
array
(
image
-
background
+
avg
,
dtype
=
np
.
uint8
),
0
,
255
)
return
subtracted
def
loadAndPasteImage
(
srcnames
,
fullimage
,
fullzval
,
width
,
height
,
def
loadAndPasteImage
(
srcnames
,
pyramid
,
fullzval
,
width
,
height
,
rotationvalue
,
p0
,
p1
,
p
,
background
=
None
):
colimgs
=
[]
for
name
in
srcnames
:
...
...
@@ -102,15 +103,22 @@ def loadAndPasteImage(srcnames, fullimage, fullzval, width, height,
c
,
s
=
np
.
cos
(
np
.
radians
(
rotationvalue
)),
np
.
sin
(
np
.
radians
(
rotationvalue
))
dx
,
dy
=
(
x
-
p0
[
0
])
/
width
*
img
.
shape
[
1
],
(
p0
[
1
]
-
y
)
/
height
*
img
.
shape
[
0
]
M
=
np
.
float32
([[
c
,
s
,
dx
],[
-
s
,
c
,
dy
]])
if
fullimage
is
not
None
:
cv2
.
warpAffine
(
img
,
M
,
(
Nx
,
Ny
),
fullimage
,
borderMode
=
cv2
.
BORDER_TRANSPARENT
)
cv2
.
warpAffine
(
zval
,
M
,
(
Nx
,
Ny
),
fullzval
,
borderMode
=
cv2
.
BORDER_TRANSPARENT
)
dst
=
fullimage
zval
=
fullzval
else
:
dst
=
cv2
.
warpAffine
(
img
,
M
,
(
Nx
,
Ny
))
zval
=
cv2
.
warpAffine
(
zval
,
M
,
(
Nx
,
Ny
))
M
=
np
.
float32
([[
c
,
s
,
dx
],
[
-
s
,
c
,
dy
]])
dst
=
None
if
pyramid
is
not
None
:
if
fullzval
is
not
None
:
cv2
.
warpAffine
(
zval
,
M
,
(
Nx
,
Ny
),
fullzval
,
borderMode
=
cv2
.
BORDER_TRANSPARENT
)
zval
=
fullzval
else
:
zval
=
cv2
.
warpAffine
(
zval
,
M
,
(
Nx
,
Ny
))
pyramid
.
addSrcTile
(
img
,
np
.
float32
([[
c
,
s
,
0
],
[
-
s
,
c
,
0
]]),
(
dx
,
dy
),
(
Nx
,
Ny
)
)
return
dst
,
zval
...
...
@@ -231,12 +239,13 @@ class OpticalScan(QtWidgets.QWidget):
def
__init__
(
self
,
ramanctrl
,
dataset
,
logpath
=
''
,
parent
=
None
):
super
().
__init__
(
parent
,
QtCore
.
Qt
.
Window
)
self
.
logpath
=
logpath
self
.
view
=
parent
self
.
view
:
QtWidgets
.
QGraphicsView
=
parent
mainLayout
=
QtWidgets
.
QVBoxLayout
()
pointgroup
=
QtWidgets
.
QGroupBox
(
"Point coordinates [µm]"
,
self
)
self
.
ramanctrl
=
ramanctrl
self
.
dataset
=
dataset
self
.
pyramid
:
ScenePyramid
=
None
self
.
positions
=
[]
self
.
process
=
None
self
.
points
=
PointCoordinates
(
5
,
self
.
ramanctrl
,
self
)
...
...
@@ -425,6 +434,9 @@ class OpticalScan(QtWidgets.QWidget):
self
.
boundaryUpdate
.
emit
()
self
.
prun
.
setEnabled
(
True
)
def
setPyramid
(
self
,
pyramid
):
self
.
pyramid
=
pyramid
def
resetDataset
(
self
,
ds
):
self
.
dataset
=
ds
self
.
points
.
createWidgets
(
5
,
list
(
zip
(
ds
.
fitindices
,
ds
.
fitpoints
)))
...
...
@@ -482,22 +494,34 @@ class OpticalScan(QtWidgets.QWidget):
Nx
,
Ny
=
int
((
p1
[
0
]
-
p0
[
0
]
+
width
)
/
width
*
img
.
shape
[
1
]),
int
((
p0
[
1
]
-
p1
[
1
]
+
height
)
/
height
*
img
.
shape
[
0
])
+
10
# + 10 because of rotation and hopefully it will be small
c
,
s
=
np
.
cos
(
np
.
radians
(
rotationvalue
)),
np
.
sin
(
np
.
radians
(
rotationvalue
))
dx
,
dy
=
(
x
-
p0
[
0
])
/
width
*
img
.
shape
[
1
],
(
p0
[
1
]
-
y
)
/
height
*
img
.
shape
[
0
]
M
=
np
.
float32
([[
c
,
s
,
dx
],[
-
s
,
c
,
dy
]])
dst
=
cv2
.
warpAffine
(
img
,
M
,
(
Nx
,
Ny
))
if
self
.
view
.
imgdata
is
not
None
and
self
.
dataset
.
lastpos
is
not
None
:
lp
=
self
.
dataset
.
lastpos
dx
,
dy
=
(
lp
[
0
]
-
p0
[
0
])
/
width
*
img
.
shape
[
1
],
(
p0
[
1
]
-
lp
[
1
])
/
height
*
img
.
shape
[
0
]
full
=
self
.
view
.
imgdata
M
=
np
.
float32
([[
1
,
0
,
dx
],[
0
,
1
,
dy
]])
try
:
full
=
cv2
.
warpAffine
(
full
,
M
,
(
Nx
,
Ny
))
#fails, if image dimensions are >32767x32767px...
dst
=
cv2
.
max
(
full
,
dst
)
except
:
QtWidgets
.
QMessageBox
.
critical
(
self
,
'Error'
,
'Image is too large
\n
Select smaller region.'
)
raise
return
M
=
np
.
float32
([[
c
,
s
,
dx
],
[
-
s
,
c
,
dy
]])
#dst = cv2.warpAffine(img, M, (Nx, Ny))
M_rot
=
np
.
float32
([[
c
,
s
,
0
],
[
-
s
,
c
,
0
]])
img_rot
=
cv2
.
warpAffine
(
img
,
M_rot
,
(
img
.
shape
[
1
],
img
.
shape
[
0
]
+
10
))
# calc new pixel start coords for tile
# @see https://stackoverflow.com/a/43166421/9880753
c_dest
=
cv2
.
transform
(
np
.
float32
([[(
0
,
0
)]]),
np
.
float32
([[
c
,
s
,
dx
],
[
-
s
,
c
,
dy
]]))
self
.
pyramid
.
addSrcTileSimple
(
img_rot
,
(
c_dest
[
0
][
0
][
0
],
c_dest
[
0
][
0
][
1
]),
p0
)
#if self.view.imgdata is not None and self.dataset.lastpos is not None:
# lp = self.dataset.lastpos
# dx, dy = (lp[0]-p0[0])/width*img.shape[1], (p0[1]-lp[1])/height*img.shape[0]
# full = self.view.imgdata
# M = np.float32([[1,0,dx],[0,1,dy]])
# try:
# full = cv2.warpAffine(full, M, (Nx, Ny)) #fails, if image dimensions are >32767x32767px...
# dst = cv2.max(full, dst)
# except:
# QtWidgets.QMessageBox.critical(self, 'Error', 'Image is too large\nSelect smaller region.')
# raise
# return
self
.
view
.
imgdata
=
dst
#
self.view.imgdata = dst
self
.
dataset
.
lastpos
=
p0
self
.
dataset
.
maxdim
=
p0
+
p1
self
.
dataset
.
readin
=
False
...
...
@@ -621,7 +645,8 @@ class OpticalScan(QtWidgets.QWidget):
self
.
progressbar
.
setEnabled
(
True
)
self
.
progressbar
.
setRange
(
0
,
len
(
self
.
dataset
.
grid
))
self
.
progressbar
.
setValue
(
0
)
self
.
view
.
imgdata
=
None
#self.view.imgdata = None
self
.
pyramid
.
resetScene
()
self
.
view
.
blockUI
()
grid
=
np
.
asarray
(
self
.
dataset
.
grid
)
p0
=
[
grid
[:,
0
].
min
(),
grid
[:,
1
].
max
()]
...
...
@@ -657,7 +682,7 @@ class OpticalScan(QtWidgets.QWidget):
else
:
background_img
=
None
self
.
view
.
imgdata
,
self
.
dataset
.
zvalimg
=
loadAndPasteImage
(
names
,
self
.
view
.
imgdata
,
self
.
dataset
.
zvalimg
,
width
,
height
,
self
.
view
.
imgdata
,
self
.
dataset
.
zvalimg
=
loadAndPasteImage
(
names
,
self
.
pyramid
,
self
.
dataset
.
zvalimg
,
width
,
height
,
rotationvalue
,
p0
,
p1
,
p
,
background
=
background_img
)
self
.
progressbar
.
setValue
(
i
+
1
)
if
i
>
3
:
...
...
@@ -665,15 +690,19 @@ class OpticalScan(QtWidgets.QWidget):
ttot
=
timerunning
*
Ngrid
/
(
i
+
1
)
time2go
=
ttot
-
timerunning
self
.
progresstime
.
setText
(
self
.
timelabeltext
+
str
(
datetime
.
timedelta
(
seconds
=
round
(
time2go
))))
self
.
imageUpdate
.
emit
(
self
.
view
.
microscopeMode
)
# reload image in sampleview, calls loadPixmap
# not needed anymore as the scene gets manipulated directly via self.pyramid
#self.imageUpdate.emit(self.view.microscopeMode)
if
i
==
Ngrid
-
1
:
cv2imwrite_fix
(
self
.
dataset
.
getImageName
(),
cv2
.
cvtColor
(
self
.
view
.
imgdata
,
cv2
.
COLOR_RGB2BGR
))
#
cv2imwrite_fix(self.dataset.getImageName(), cv2.cvtColor(self.view.imgdata, cv2.COLOR_RGB2BGR))
self
.
dataset
.
saveZvalImg
()
self
.
process
.
join
()
self
.
dataqueue
.
close
()
self
.
dataqueue
.
join_thread
()
self
.
pyramid
.
toDataset
()
if
self
.
deleteImgChecker
.
isChecked
():
path
=
self
.
dataset
.
getScanPath
()
files
=
os
.
listdir
(
path
)
...
...
sampleview.py
View file @
819efb02
This diff is collapsed.
Click to expand it.
scenePyramid.py
0 → 100644
View file @
819efb02
This diff is collapsed.
Click to expand it.
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