Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Sean Fitzgibbon
SlideR 🍔
Commits
2ceba27c
Commit
2ceba27c
authored
Jun 17, 2021
by
Sean Fitzgibbon
Browse files
Added support for jpeg2k in slide registration
parent
3d33fb27
Changes
5
Hide whitespace changes
Inline
Side-by-side
slider/chart_reg.py
View file @
2ceba27c
...
...
@@ -15,7 +15,7 @@ import numpy as np
import
matplotlib.pyplot
as
plt
def
register_chart_to_slide
(
chart
,
slide
,
out
,
rlevel
=
3
,
boundary_key
=
'outline'
):
def
register_chart_to_slide
(
chart
,
slide
,
out
,
rlevel
=
0
,
boundary_key
=
'outline'
):
# load chart
contour
,
cells
=
neurolucida
.
read
(
chart
)
...
...
@@ -53,8 +53,9 @@ def register_chart_to_slide(chart, slide, out, rlevel=3, boundary_key='outline')
# apply opt-xfm to contours and cells and save
contour_xfm
=
{
k
:
_apply_xfm
(
opt
,
v
[:,
:
2
]
*
[
1
,
-
1
]).
tolist
()
for
k
,
v
in
contour
.
items
()}
contour_xfm
=
{
k
:
_apply_xfm
(
opt
,
v
[:,
:
2
]
*
[
1
,
-
1
]).
tolist
()
for
k
,
v
in
contour
.
items
()
}
with
open
(
f
'
{
out
}
/contour.json'
,
'w'
)
as
fp
:
json
.
dump
(
contour_xfm
,
fp
,
indent
=
4
)
...
...
slider/default.json
→
slider/
resources/
default.json
View file @
2ceba27c
...
...
@@ -20,6 +20,7 @@
"file"
:
""
,
"storage"
:
"mem"
,
"dtype"
:
"f4"
,
"resolution_level"
:
4
,
"mask"
:
{
"file"
:
null
,
"normalise"
:
true
,
...
...
@@ -37,6 +38,7 @@
"file"
:
""
,
"storage"
:
"mem"
,
"dtype"
:
"f4"
,
"resolution_level"
:
4
,
"mask"
:
{
"file"
:
null
,
"normalise"
:
true
,
...
...
slider/slide_reg.py
View file @
2ceba27c
...
...
@@ -132,8 +132,7 @@ from tirl.transformations.nonlinear.displacement import TxDisplacementField
import
matplotlib.pyplot
as
plt
import
os.path
as
op
# TIRL IMPORTS
# DEFINITIONS
from
slider
import
util
# Rotation search: number of best initialisations to test
N_BEST
=
3
...
...
@@ -142,8 +141,37 @@ SNAPSHOT_EXT = "png"
# NumPy print formatting
np
.
set_printoptions
(
precision
=
4
)
def
_load_image
(
p
):
if
p
.
file
.
lower
().
endswith
(
'.jp2'
):
# if jpg2k
# load jp2
import
glymur
from
tirl.scripts.mnd.image
import
set_mask
jp2
=
glymur
.
Jp2k
(
p
.
file
)
img
=
jp2
.
read
(
rlevel
=
p
.
resolution_level
)
# adjust resolution by resolution_level
p
.
resolution
=
p
.
resolution
*
(
2
**
p
.
resolution_level
)
# create timg
timg
=
TImage
.
fromarray
(
img
,
dtype
=
p
.
dtype
,
tensor_axes
=
(
2
,))
timg
.
resolution
=
p
.
resolution
# add mask
set_mask
(
timg
,
scope
=
globals
(),
**
p
.
mask
)
# Export
tirl
.
scripts
.
mnd
.
inout
.
export
(
timg
,
p
.
export
,
default
=
None
)
# Snapshot
tirl
.
scripts
.
mnd
.
inout
.
snapshot
(
timg
,
p
.
snapshot
,
default
=
None
)
else
:
# else other image types
timg
=
tirl
.
scripts
.
mnd
.
inout
.
load_image
(
scope
=
globals
(),
**
p
)
return
timg
# IMPLEMENTATION
def
run
(
cnf
=
None
,
**
options
):
"""
...
...
@@ -179,12 +207,16 @@ def run(cnf=None, **options):
ext
=
ts
.
EXTENSIONS
[
"TImage"
]
p
.
moving
.
export
=
\
os
.
path
.
join
(
p
.
general
.
outputdir
,
f
"moving.
{
ext
}
"
)
moving
=
tirl
.
scripts
.
mnd
.
inout
.
load_image
(
scope
=
globals
(),
**
p
.
moving
)
# TODO: adjust resolution based on rlevel.
moving
=
_load_image
(
p
.
moving
)
if
p
.
fixed
.
export
is
True
:
ext
=
ts
.
EXTENSIONS
[
"TImage"
]
p
.
fixed
.
export
=
os
.
path
.
join
(
p
.
general
.
outputdir
,
f
"fixed.
{
ext
}
"
)
fixed
=
tirl
.
scripts
.
mnd
.
inout
.
load_image
(
scope
=
globals
(),
**
p
.
fixed
)
fixed
=
_load_image
(
p
.
fixed
)
# Having loaded both images, perform actions on the histology image prior
# to registration, unless it was loaded from a TImage.
...
...
@@ -579,6 +611,44 @@ def affine2d(fixed, moving, cnf):
moving
.
resample
(
1
,
copy
=
False
)
def
diffreg2d
(
fixed
,
moving
,
cnf
):
"""
Performs a non-linear registration. The transformation is parameterised as
a dense displacement field. The cost is MIND, and diffusion regularisation
is used to create smoothness in the deformation field.
"""
p
=
AttrMap
(
cnf
)
q
=
p
.
regparams
.
nonlinear
logger
=
logging
.
getLogger
(
p
.
logger
)
# Scaling-smoothing iteration
for
i
,
(
sc
,
sm
)
in
enumerate
(
zip
(
q
.
scaling
,
q
.
smoothing
)):
logger
.
debug
(
f
"Scale:
{
sc
}
, smoothing:
{
sm
}
px..."
)
# Prepare images for the current iteration
fixed
.
resample
(
1
/
sc
,
copy
=
False
)
moving
.
resample
(
1
/
sc
,
copy
=
False
)
fixed_smooth
=
fixed
.
smooth
(
sm
,
copy
=
True
)
moving_smooth
=
moving
.
smooth
(
sm
,
copy
=
True
)
# Prepare transformation to optimise
tx_nonlinear
=
fixed_smooth
.
domain
.
chain
[
-
1
]
# Set cost and regulariser
cost
=
CostMIND
(
moving_smooth
,
fixed_smooth
,
sigma
=
float
(
q
.
sigma
),
truncate
=
float
(
q
.
truncate
),
kernel
=
MK_FULL
)
regularisation
=
DiffusionRegulariser
(
tx_nonlinear
,
weight
=
float
(
q
.
regweight
))
# Optimise the non-linear transformation
GNOptimiserDiffusion
(
tx_nonlinear
,
cost
,
regularisation
,
maxiter
=
int
(
q
.
maxiter
[
i
]),
xtol_rel
=
q
.
xtol_rel
,
xtol_abs
=
q
.
xtol_abs
,
visualise
=
q
.
visualise
,
logger
=
logger
)()
# Transfer optimised transformations to the non-smoothed images
fixed
.
domain
=
fixed_smooth
.
domain
moving
.
domain
=
moving_smooth
.
domain
else
:
# Restore the original resolution of the images
fixed
.
resample
(
1
,
copy
=
False
)
moving
.
resample
(
1
,
copy
=
False
)
# AUXILIARY FUNCTIONS
...
...
@@ -798,6 +868,9 @@ def register_slide_to_slide(moving, moving_res, fixed, fixed_res, out, config):
"""
if
config
is
None
:
config
=
util
.
get_resource
(
'default.json'
)
if
os
.
path
.
isfile
(
config
):
with
open
(
config
,
"r"
)
as
fp
:
config
=
dict
(
json
.
load
(
fp
))
...
...
slider/util.py
0 → 100644
View file @
2ceba27c
#!/usr/bin/env python
import
os.path
as
op
def
get_slider_dir
()
->
str
:
rpath
=
op
.
realpath
(
op
.
dirname
(
op
.
abspath
(
__file__
)))
return
rpath
def
get_resource_path
()
->
str
:
rpath
=
op
.
realpath
(
op
.
join
(
op
.
dirname
(
op
.
abspath
(
__file__
)),
"resources"
))
return
rpath
def
get_resource
(
name
)
->
str
:
r
=
op
.
join
(
get_resource_path
(),
name
)
# asrt.assert_file_exists(r)
return
r
slider_app.py
View file @
2ceba27c
...
...
@@ -19,15 +19,17 @@ def add_slide_cli(subparsers):
help
=
"Moving slide image"
,
type
=
str
)
parser
.
add_argument
(
"moving_res"
,
metavar
=
"<moving-resolution>"
,
help
=
"Moving image resolution (mm)"
,
type
=
float
)
parser
.
add_argument
(
"fixed"
,
metavar
=
"<fixed>"
,
help
=
"Fixed slide image"
,
type
=
str
)
parser
.
add_argument
(
"fixed_res"
,
metavar
=
"<fixed-resolution>"
,
help
=
"Fixed image resolution (mm)"
,
type
=
float
)
parser
.
add_argument
(
"--out"
,
metavar
=
"<dir>"
,
help
=
"Output directory"
,
default
=
'./slider.reg'
,
type
=
str
,
required
=
False
)
parser
.
add_argument
(
"--config"
,
metavar
=
"<
default
.json>"
,
help
=
"configuration file"
,
default
=
'default.js
on
'
,
type
=
str
,
parser
.
add_argument
(
"--config"
,
metavar
=
"<
config
.json>"
,
help
=
"configuration file"
,
default
=
N
on
e
,
type
=
str
,
required
=
False
)
parser
.
set_defaults
(
method
=
'slide'
)
...
...
Write
Preview
Supports
Markdown
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