Skip to content
This repository was archived by the owner on Feb 11, 2023. It is now read-only.

Commit b64d304

Browse files
authored
method: DROP (#39)
+ method: DROP #8 * convert MHD images * warping regist. results * loading mhd deform * update docs * update params
1 parent 340bb9c commit b64d304

File tree

13 files changed

+396
-22
lines changed

13 files changed

+396
-22
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,16 @@ For each benchmark experiment, the explanation about how to install and use a pa
215215
-script ./scripts/Python/run_ANTsPy.py \
216216
--visual --unique
217217
```
218+
* **[DROP](https://www.mrf-registration.net)** is image registration and motion estimation based on Markov Random Fields.
219+
```bash
220+
python bm_experiments/bm_DROP.py \
221+
-c ./data_images/pairs-imgs-lnds_histol.csv \
222+
-d ./data_images \
223+
-o ./results \
224+
-DROP ~/Applications/DROP/dropreg2d \
225+
--path_config ./configs/drop.txt \
226+
--visual --unique
227+
```
218228
* ...
219229

220230
Some more image registration methods integrated in ImageJ are listed in [Registration](https://imagej.net/Registration).

birl/cls_benchmark.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,11 @@ class ImRegBenchmark(Experiment):
130130
>>> from birl.utilities.data_io import create_folder, update_path
131131
>>> path_out = create_folder('temp_results')
132132
>>> path_csv = os.path.join(update_path('data_images'), 'pairs-imgs-lnds_mix.csv')
133-
>>> params = {'nb_workers': 1, 'unique': False, 'visual': True,
134-
... 'path_out': path_out, 'path_cover': path_csv}
133+
>>> params = {'path_cover': path_csv,
134+
... 'path_out': path_out,
135+
... 'nb_workers': 1,
136+
... 'unique': False,
137+
... 'visual': True}
135138
>>> benchmark = ImRegBenchmark(params)
136139
>>> benchmark.run()
137140
True
@@ -142,8 +145,11 @@ class ImRegBenchmark(Experiment):
142145
>>> from birl.utilities.data_io import create_folder, update_path
143146
>>> path_out = create_folder('temp_results')
144147
>>> path_csv = os.path.join(update_path('data_images'), 'pairs-imgs-lnds_mix.csv')
145-
>>> params = {'nb_workers': 2, 'unique': False, 'visual': True,
146-
... 'path_out': path_out, 'path_cover': path_csv}
148+
>>> params = {'path_cover': path_csv,
149+
... 'path_out': path_out,
150+
... 'nb_workers': 2,
151+
... 'unique': False,
152+
... 'visual': True}
147153
>>> benchmark = ImRegBenchmark(params)
148154
>>> benchmark.run()
149155
True
@@ -371,7 +377,7 @@ def __convert_gray(path_img_col):
371377
(path_img_move, COL_IMAGE_MOVE)]
372378
# TODO: find a way how to convert images in parallel inside mproc pool
373379
for path_img, col in iterate_mproc_map(__convert_gray, argv_params,
374-
nb_workers=1):
380+
nb_workers=1, desc=None):
375381
record[col + COL_IMAGE_EXT_TEMP] = path_img
376382
else:
377383
logging.warning('unrecognized pre-processing: %s', pproc)

birl/utilities/data_io.py

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111

1212
import numpy as np
1313
import pandas as pd
14+
import SimpleITK as sitk
1415
from PIL import Image
15-
from skimage.color import gray2rgb, rgb2hsv, hsv2rgb, rgb2lab, lab2rgb, lch2lab, lab2lch
16+
from skimage.color import (
17+
rgb2gray, gray2rgb, rgb2hsv, hsv2rgb, rgb2lab, lab2rgb, lch2lab, lab2lch)
1618

1719
#: landmarks coordinates, loading from CSV file
1820
LANDMARK_COORDS = ['X', 'Y']
@@ -344,6 +346,83 @@ def save_image(path_image, image):
344346
image.save(path_image)
345347

346348

349+
@io_image_decorate
350+
def convert_from_mhd(path_image, path_out_dir=None, img_ext='.png'):
351+
""" convert standard image to MHD format
352+
353+
.. ref:: https://www.programcreek.com/python/example/96382/SimpleITK.WriteImage
354+
355+
:param str path_image: path to the input image
356+
:param str path_out_dir: path to output directory, if None use the input dir
357+
:param str img_ext: image extension like PNG or JPEG
358+
:return str: path to exported image
359+
360+
>>> path_img = os.path.join(update_path('data_images'), 'images',
361+
... 'artificial_reference.jpg')
362+
>>> path_img = convert_to_mhd(path_img)
363+
>>> convert_from_mhd(path_img) # doctest: +ELLIPSIS
364+
'...artificial_reference.png'
365+
"""
366+
path_image = update_path(path_image)
367+
assert os.path.isfile(path_image), 'missing image: %s' % path_image
368+
# Reads the image using SimpleITK
369+
itk_image = sitk.ReadImage(path_image)
370+
371+
# Convert the image to a numpy array first and then shuffle the dimensions
372+
# to get axis in the order z,y,x
373+
img = sitk.GetArrayFromImage(itk_image)
374+
375+
# define output/destination path
376+
img_name = os.path.splitext(os.path.basename(path_image))[0]
377+
if not path_out_dir:
378+
path_out_dir = os.path.dirname(path_image)
379+
path_image = os.path.join(path_out_dir, img_name + img_ext)
380+
save_image(path_image, img)
381+
return path_image
382+
383+
384+
@io_image_decorate
385+
def convert_to_mhd(path_image, path_out_dir=None, to_gray=True, overwrite=True):
386+
""" converting standard image to MHD (Nifty format)
387+
388+
.. ref:: https://stackoverflow.com/questions/37290631
389+
390+
:param str path_image: path to the input image
391+
:param str path_out_dir: path to output directory, if None use the input dir
392+
:param bool overwrite: allow overwrite existing image
393+
:return str: path to exported image
394+
395+
>>> path_img = os.path.join(update_path('data_images'), 'images',
396+
... 'artificial_moving-affine.jpg')
397+
>>> convert_to_mhd(path_img) # doctest: +ELLIPSIS
398+
'...artificial_moving-affine.mhd'
399+
"""
400+
path_image = update_path(path_image)
401+
# define output/destination path
402+
img_name = os.path.splitext(os.path.basename(path_image))[0]
403+
if not path_out_dir:
404+
path_out_dir = os.path.dirname(path_image)
405+
path_image_new = os.path.join(path_out_dir, img_name + '.mhd')
406+
# in case the image exists and you are not allowed to overwrite it
407+
if os.path.isfile(path_image_new) and not overwrite:
408+
return path_image_new
409+
410+
img = load_image(path_image)
411+
# if required and RGB on input convert to gray-scale
412+
if to_gray and img.ndim == 3 and img.shape[2] in (3, 4):
413+
img = rgb2gray(img)
414+
# the MHD usually require pixel value range (0, 255)
415+
if np.max(img) <= 1.5:
416+
img = np.round(img * 255)
417+
np.clip(img, a_min=0, a_max=255, out=img)
418+
419+
image = sitk.GetImageFromArray(img.astype(np.uint8), isVector=False)
420+
421+
# do not use text in MHD, othwerwise it crash DROP method
422+
sitk.WriteImage(image, path_image_new, False)
423+
return path_image_new
424+
425+
347426
def image_histogram_matching(source, reference, use_color='hsv'):
348427
""" adjust image histogram between two images
349428

birl/utilities/experiments.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,10 @@ def parse_arg_params(parser, upper_dirs=None):
229229
def exec_commands(commands, path_logger=None, timeout=None):
230230
""" run the given commands in system Command Line
231231
232-
SEE: https://stackoverflow.com/questions/1996518
233-
https://www.quora.com/Whats-the-difference-between-os-system-and-subprocess-call-in-Python
232+
See refs:
233+
234+
* https://stackoverflow.com/questions/1996518
235+
* https://www.quora.com/Whats-the-difference-between-os-system-and-subprocess-call-in-Python
234236
235237
:param [str] commands: commands to be executed
236238
:param str path_logger: path to the logger
@@ -258,9 +260,11 @@ def exec_commands(commands, path_logger=None, timeout=None):
258260
for cmd in commands:
259261
outputs += [cmd.encode('utf-8')]
260262
try:
263+
# os.system(cmd)
264+
# NOTE: for some reason " in the command makes it crash, e.g with DROP
261265
outputs += [subprocess.check_output(cmd.split(), **options)]
262266
except subprocess.CalledProcessError as e:
263-
logging.exception(commands)
267+
logging.exception(cmd)
264268
outputs += [e.output]
265269
success = False
266270
# export the output if path exists

bm_ANHIR/evaluate_submission.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ def parse_landmarks(idx_row):
228228
def compute_scores(df_experiments, min_landmarks=1.):
229229
""" compute all main metrics
230230
231-
SEE: https://anhir.grand-challenge.org/Evaluation/
231+
.. ref:: https://anhir.grand-challenge.org/Evaluation/
232232
233233
:param DF df_experiments: complete experiments
234234
:param float min_landmarks: required number of submitted landmarks in range (0, 1),

bm_dataset/rescale_tissue_landmarks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@
5151
def arg_parse_params():
5252
""" argument parser from cmd
5353
54-
SEE: https://docs.python.org/3/library/argparse.html
5554
:return {str: ...}:
5655
"""
56+
# SEE: https://docs.python.org/3/library/argparse.html
5757
parser = argparse.ArgumentParser()
5858
parser.add_argument('-a', '--path_annots', type=str, required=False,
5959
help='path to folder with annotations')

bm_experiments/bm_ANTsPy.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,13 @@ class BmANTsPy(ImRegBenchmark):
7373
>>> from birl.utilities.data_io import create_folder, update_path
7474
>>> path_out = create_folder('temp_results')
7575
>>> fn_path_conf = lambda n: os.path.join(update_path('configs'), n)
76-
>>> params = {'nb_workers': 1, 'unique': False,
76+
>>> path_csv = os.path.join(update_path('data_images'), 'pairs-imgs-lnds_mix.csv')
77+
>>> params = {'path_cover': path_csv,
7778
... 'path_out': path_out,
78-
... 'path_cover': os.path.join(update_path('data_images'),
79-
... 'pairs-imgs-lnds_mix.csv'),
80-
... 'exec_Python': 'python', 'path_script': '.'}
79+
... 'nb_workers': 2,
80+
... 'unique': False,
81+
... 'exec_Python': 'python',
82+
... 'path_script': '.'}
8183
>>> benchmark = BmANTsPy(params)
8284
>>> benchmark.run() # doctest: +SKIP
8385
>>> del benchmark

0 commit comments

Comments
 (0)