Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
model_server
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Christopher Randolph Rhodes
model_server
Commits
5243e3cf
Commit
5243e3cf
authored
1 year ago
by
Christopher Randolph Rhodes
Browse files
Options
Downloads
Patches
Plain Diff
Consolidated 2d and 3d patch exporting; tests pass
parent
9dd88f7e
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
extensions/chaeo/products.py
+55
-70
55 additions, 70 deletions
extensions/chaeo/products.py
extensions/chaeo/tests/test_zstack.py
+32
-1
32 additions, 1 deletion
extensions/chaeo/tests/test_zstack.py
extensions/chaeo/zmask.py
+1
-2
1 addition, 2 deletions
extensions/chaeo/zmask.py
with
88 additions
and
73 deletions
extensions/chaeo/products.py
+
55
−
70
View file @
5243e3cf
from
PIL
import
Image
,
ImageDraw
,
ImageFont
from
pathlib
import
Path
def
draw_boxes_on_2d_image
(
img
,
boxes
,
**
kwargs
):
pilimg
=
Image
.
fromarray
(
np
.
copy
(
img
))
# drawing modifies array in-place
draw
=
ImageDraw
.
Draw
(
pilimg
)
font_size
=
kwargs
.
get
(
'
font_size
'
,
18
)
linewidth
=
kwargs
.
get
(
'
linewidth
'
,
4
)
import
numpy
as
np
from
PIL
import
Image
,
ImageDraw
draw
.
font
=
ImageFont
.
truetype
(
font
=
"
arial.ttf
"
,
size
=
font_size
)
from
skimage.io
import
imsave
from
tifffile
import
imwrite
for
box
in
boxes
:
y0
=
box
[
'
info
'
].
y0
y1
=
box
[
'
info
'
].
y1
x0
=
box
[
'
info
'
].
x0
x1
=
box
[
'
info
'
].
x1
xm
=
round
((
x0
+
x1
)
/
2
)
from
model_server.accessors
import
GenericImageDataAccessor
from
model_server.process
import
pad
,
rescale
,
resample_to_8bit
la
=
box
[
'
info
'
].
label
zi
=
box
[
'
info
'
].
zi
def
_write_patch_to_file
(
where
,
fname
,
data
):
ext
=
fname
.
split
(
'
.
'
)[
-
1
].
upper
()
where
.
mkdir
(
parents
=
True
,
exist_ok
=
True
)
draw
.
rectangle
([(
x0
,
y0
),
(
x1
,
y1
)],
outline
=
'
white
'
,
width
=
linewidth
)
if
ext
==
'
PNG
'
:
assert
data
.
dtype
==
'
uint8
'
,
f
'
Invalid data type
{
data
.
dtype
}
'
assert
data
.
shape
[
2
]
==
1
,
f
'
Cannot export multichannel images as PNGs; RGB not supported
'
assert
data
.
shape
[
3
]
==
1
,
f
'
Cannot export z-stacks as PNGs
'
imsave
(
where
/
fname
,
data
[:,
:,
0
,
0
],
check_contrast
=
False
)
return
True
if
kwargs
.
get
(
'
add_label
'
)
is
True
:
draw
.
text
((
xm
,
y0
),
f
'
Z
{
zi
:
04
d
}
-L
{
la
:
04
d
}
'
,
fill
=
'
white
'
,
anchor
=
'
mb
'
)
elif
ext
in
[
'
TIF
'
,
'
TIFF
'
]:
zcyx
=
np
.
moveaxis
(
data
,
[
3
,
2
,
0
,
1
],
[
0
,
1
,
2
,
3
])
imwrite
(
where
/
fname
,
zcyx
,
imagej
=
True
)
return
True
return
pilimg
else
:
raise
Exception
(
f
'
Unsupported file extension:
{
ext
}
'
)
def
generate_patches
(
desc
,
stack
,
boxes
,
rescale_clip
=
0.0
,
pad_to
=
256
,
proj
=
lambda
x
:
x
.
max
(
axis
=
0
),
def
export_patches_from_zstack
(
where
:
Path
,
stack
:
GenericImageDataAccessor
,
zmask_meta
:
list
,
rescale_clip
:
float
=
0.0
,
pad_to
:
int
=
256
,
make_3d
:
bool
=
False
,
prefix
=
'
patch
'
,
**
kwargs
):
patch_dir
=
root
/
'
output
'
/
'
patches
'
/
desc
patch_dir
.
mkdir
(
parents
=
True
,
exist_ok
=
True
)
assert
stack
.
chroma
==
1
,
'
Expecting monochromatic image data
'
assert
stack
.
nz
>
1
,
'
Expecting z-stack
'
exported
=
[]
for
mi
in
zmask_meta
:
obj
=
mi
[
'
info
'
]
sl
=
mi
[
'
slice
'
]
rbb
=
mi
[
'
relative_bounding_box
'
]
for
box
in
boxes
:
obj
=
box
[
'
info
'
]
sl
=
box
[
'
slice
'
]
rbb
=
box
[
'
relative_bounding_box
'
]
if
make_3d
:
patch
=
stack
.
data
[
sl
]
else
:
patch
=
np
.
max
(
stack
.
data
[
sl
],
axis
=
3
,
keepdims
=
True
)
patch
=
proj
(
stack
[
sl
])
patch_fname
=
f
'
{
prefix
}
-la
{
obj
.
label
:
04
d
}
-zi
{
obj
.
zi
:
04
d
}
'
assert
len
(
patch
.
shape
)
==
4
assert
patch
.
shape
[
2
]
==
stack
.
chroma
# assert patch.shape[3] == 1 # should not get to zstacks by this point
if
rescale_clip
is
not
None
:
patch
=
rescale
(
patch
,
rescale_clip
)
...
...
@@ -52,46 +66,17 @@ def generate_patches(
x1
=
rbb
[
'
x1
'
]
y1
=
rbb
[
'
y1
'
]
pilimg
=
Image
.
fromarray
(
patch
)
# drawing modifies array in-place
draw
=
ImageDraw
.
Draw
(
pilimg
)
draw
.
rectangle
([(
x0
,
y0
),
(
x1
,
y1
)],
outline
=
'
white
'
,
width
=
kwargs
.
get
(
'
linewidth
'
,
1
))
patch
=
np
.
array
(
pilimg
)
for
zi
in
range
(
0
,
patch
.
shape
[
3
]):
pilimg
=
Image
.
fromarray
(
patch
[:,
:,
0
,
zi
])
# drawing modifies array in-place
draw
=
ImageDraw
.
Draw
(
pilimg
)
draw
.
rectangle
([(
x0
,
y0
),
(
x1
,
y1
)],
outline
=
'
white
'
,
width
=
kwargs
.
get
(
'
linewidth
'
,
1
))
patch
[:,
:,
0
,
zi
]
=
np
.
array
(
pilimg
)
if
pad_to
:
patch
=
pad
(
patch
,
pad_to
)
imsave
(
patch_dir
/
(
patch_fname
+
'
.png
'
),
resample
(
patch
),
check_contrast
=
False
,
)
print
(
f
'
Successfully wrote
{
len
(
boxes
)
}
patches to:
\n
{
patch_dir
}
'
)
def
generate_3d_patches
(
# in extensions.chaeo.products
desc
,
stack
,
boxes
,
rescale_clip
=
0.0
,
pad_to
=
256
,
prefix
=
'
patch
'
,
proj
=
lambda
x
:
x
,
):
patch_dir
=
root
/
'
output
'
/
'
3d_patches
'
/
desc
patch_dir
.
mkdir
(
parents
=
True
,
exist_ok
=
True
)
for
box
in
boxes
:
obj
=
box
[
'
info
'
]
sl
=
box
[
'
slice
'
]
patch
=
proj
(
stack
[
sl
])
patch_fname
=
f
'
{
prefix
}
-la
{
obj
.
label
:
04
d
}
-zi
{
obj
.
zi
:
04
d
}
'
if
rescale_clip
is
not
None
:
patch
=
rescale
(
patch
,
rescale_clip
)
if
pad_to
:
patch
=
pad_3d
(
patch
,
pad_to
)
imwrite
(
patch_dir
/
(
patch_fname
+
'
.tif
'
),
patch
,
imagej
=
True
)
print
(
f
'
Successfully wrote
{
len
(
boxes
)
}
patches to:
\n
{
patch_dir
}
'
)
\ No newline at end of file
ext
=
'
tif
'
if
make_3d
else
'
png
'
fname
=
f
'
{
prefix
}
-la
{
obj
.
label
:
04
d
}
-zi
{
obj
.
zi
:
04
d
}
.
{
ext
}
'
success
=
_write_patch_to_file
(
where
,
fname
,
resample_to_8bit
(
patch
))
exported
.
append
(
fname
)
return
success
,
exported
\ No newline at end of file
This diff is collapsed.
Click to expand it.
extensions/chaeo/test_zstack.py
→
extensions/chaeo/
tests/
test_zstack.py
+
32
−
1
View file @
5243e3cf
...
...
@@ -5,6 +5,7 @@ import numpy as np
from
conf.testing
import
output_path
from
extensions.chaeo.conf.testing
import
multichannel_zstack
,
pixel_classifier
,
pipeline_params
from
extensions.chaeo.products
import
export_patches_from_zstack
from
extensions.chaeo.zmask
import
build_zmask_from_object_mask
from
model_server.accessors
import
generate_file_accessor
,
InMemoryDataAccessor
,
write_accessor_data_to_file
from
extensions.ilastik.models
import
IlastikObjectClassifierModel
,
IlastikPixelClassifierModel
...
...
@@ -51,6 +52,8 @@ class TestZStackDerivedDataProducts(unittest.TestCase):
ar
=
meta
[
1
][
'
info
'
].
area
self
.
assertGreaterEqual
(
sh
[
0
]
*
sh
[
1
],
ar
)
return
zmask
,
meta
def
test_zmask_makes_correct_contours
(
self
):
return
self
.
test_zmask_makes_correct_boxes
(
mask_type
=
'
contours
'
)
...
...
@@ -58,4 +61,32 @@ class TestZStackDerivedDataProducts(unittest.TestCase):
return
self
.
test_zmask_makes_correct_boxes
(
filters
=
{
'
area
'
:
(
1e3
,
1e4
)})
def
test_zmask_makes_correct_expanded_boxes
(
self
):
return
self
.
test_zmask_makes_correct_boxes
(
expand_box_by
=
(
64
,
2
))
\ No newline at end of file
return
self
.
test_zmask_makes_correct_boxes
(
expand_box_by
=
(
64
,
2
))
def
test_make_2d_patches_from_zmask
(
self
):
zmask
,
meta
=
self
.
test_zmask_makes_correct_boxes
(
filters
=
{
'
area
'
:
(
1e3
,
1e4
)},
expand_box_by
=
(
64
,
2
)
)
success
,
files
=
export_patches_from_zstack
(
output_path
/
'
2d_patches
'
,
self
.
stack
.
get_one_channel_data
(
channel
=
1
),
meta
,
draw_bounding_box
=
True
,
)
self
.
assertTrue
(
success
)
self
.
assertGreaterEqual
(
len
(
files
),
1
)
def
test_make_3d_patches_from_zmask
(
self
):
zmask
,
meta
=
self
.
test_zmask_makes_correct_boxes
(
filters
=
{
'
area
'
:
(
1e3
,
1e4
)},
expand_box_by
=
(
64
,
2
),
)
success
,
files
=
export_patches_from_zstack
(
output_path
/
'
3d_patches
'
,
self
.
stack
.
get_one_channel_data
(
channel
=
1
),
meta
,
make_3d
=
True
)
self
.
assertTrue
(
success
)
self
.
assertGreaterEqual
(
len
(
files
),
1
)
This diff is collapsed.
Click to expand it.
extensions/chaeo/zmask.py
+
1
−
2
View file @
5243e3cf
...
...
@@ -5,7 +5,6 @@ from skimage.measure import find_contours, label, regionprops_table
from
model_server.accessors
import
GenericImageDataAccessor
# build a single boolean 3d mask (objects v. bboxes) and return bounding boxes
def
build_zmask_from_object_mask
(
obmask
:
GenericImageDataAccessor
,
zstack
:
GenericImageDataAccessor
,
...
...
@@ -97,7 +96,7 @@ def build_zmask_from_object_mask(
'
x1
'
:
ob
.
x1
-
x0
,
}
sl
=
np
.
s_
[
y0
:
y1
,
x0
:
x1
,
0
,
z0
:
z1
+
1
]
sl
=
np
.
s_
[
y0
:
y1
,
x0
:
x1
,
:
,
z0
:
z1
+
1
]
# compute contours
obmask
=
(
lamap
==
ob
.
label
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment