Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[bumpversion]
current_version = 0.3.6
commit = False
tag = False

[bumpversion:file:VERSION]

[bumpversion:file:pyproject.toml]
search = version = "{current_version}"
replace = version = "{new_version}"

[bumpversion:file:plugin.json]

[bumpversion:file:ict.yaml]

[bumpversion:file:imageregistration.cwl]
35 changes: 15 additions & 20 deletions transforms/images/polus-image-registration-plugin/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@

FROM polusai/bfio:2.1.9

ARG EXEC_DIR="/opt/executables"
ARG DATA_DIR="/data"

RUN mkdir -p ${EXEC_DIR} \
&& mkdir -p ${DATA_DIR}/inputs \
&& mkdir ${DATA_DIR}/outputs

RUN apt-get update && \
apt-get -y install libglib2.0-0

COPY src ${EXEC_DIR}/
# Build from repo root (monorepo) or from this tool directory — both work.
FROM polusai/bfio:2.5.0
ENV EXEC_DIR="/opt/executables" POLUS_IMG_EXT=".ome.tif" POLUS_TAB_EXT=".csv" POLUS_LOG="INFO"
WORKDIR ${EXEC_DIR}

RUN pip3 install -r ${EXEC_DIR}/requirements.txt --no-cache-dir

COPY VERSION /

ENTRYPOINT ["python3", "/opt/executables/main.py"]
ENV TOOL_DIR="transforms/images/polus-image-registration-plugin"
RUN mkdir -p image-tools
COPY . ${EXEC_DIR}/image-tools
RUN apt-get update && apt-get install -y --no-install-recommends libglib2.0-0 \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install -U pip setuptools wheel \
&& python3 -c 'import sys; assert sys.version_info>=(3,11)' \
&& R="${EXEC_DIR}/image-tools" && M="$R/$TOOL_DIR" \
&& if [ -f "$M/pyproject.toml" ]; then pip3 install --no-cache-dir "$M"; \
else pip3 install --no-cache-dir "$R"; fi
ENTRYPOINT ["python3", "-m", "main"]
CMD ["--help"]
63 changes: 31 additions & 32 deletions transforms/images/polus-image-registration-plugin/README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,60 @@
# Polus Projective Transformation Image Registration Plugin

WIPP Plugin Title : Image Registration Plugin
WIPP Plugin Title : Image Registration Plugin

Contact [Gauhar Bains](mailto:gauhar.bains@labshare.org) for more information.

For more information on WIPP, visit the [official WIPP page](https://isg.nist.gov/deepzoomweb/software/wipp).

## Description

This plugin registers an image collection. First it parses the image collection using `parser.py` into registration sets. Each registration set consists of: moving image, template image, similiar transformation images. The registration algorithm(explained in the next section, can be found in `image_registration.py`) registers the moving image with template image and stores the transformation required to do so. This stored transformation is used to transform each image in similar transformation list.
This plugin registers an image collection. First it parses the image collection using `parser.py` into registration sets. Each registration set consists of: moving image, template image, similiar transformation images. The registration algorithm(explained in the next section, can be found in `image_registration.py`) registers the moving image with template image and stores the transformation required to do so. This stored transformation is used to transform each image in similar transformation list.

## Algorithm

### To do
1. Find a better way to handle poorly correlated transforms.
1. Find a better way to handle poorly correlated transforms.
2. Find a more scalable approach to do rough transformation. The algorithm has been tested on images of size around 1.2 Gigapixel but a better approach may be needed for images significantly larger than these.

### Parsing
The parsing algorithm uses the functions from the `file_pattern utility`. It takes the following inputs : Filename pattern, registration variable, similar transformation variable. The registration variable helps determine the moving and the template images where as the similar transformation variable helps determine the similar transformation images. Note: The code produces the expected output when len(registration_variable)==len(similarity_variable)==1. The code will NOT spit out an error when the more than one variable is passed as registration or similarity variable, but additional testing needs to be done for this usecase.
### Parsing
The parsing algorithm uses the functions from the `file_pattern utility`. It takes the following inputs : Filename pattern, registration variable, similar transformation variable. The registration variable helps determine the moving and the template images where as the similar transformation variable helps determine the similar transformation images. Note: The code produces the expected output when len(registration_variable)==len(similarity_variable)==1. The code will NOT spit out an error when the more than one variable is passed as registration or similarity variable, but additional testing needs to be done for this usecase.

Some sample text files can be found in the examples folder. Short example shown below:
Some sample text files can be found in the examples folder. Short example shown below:

Parsing example :

`Inputs:`
Filepattern : `x{xxx}_y{yyy}_z{zzz}_c{ccc}_t{ttt}.ome.tif`
Registration_variable : `t`
similar_transformation_variable : `c`
template_ : `x001_y001_z001_c001_t001.ome.tif`
Parsing example :

`Output set 1 :`
Template Image: x001_y001_z001_c001_t001.ome.tif
Moving Image: x001_y001_z001_c001_t002.ome.tif
Similar Transformation Images : [ x001_y001_z001_c002_t002.ome.tif , x001_y001_z001_c003_t002.ome.tif ]
`Inputs:`
Filepattern : `x{xxx}_y{yyy}_z{zzz}_c{ccc}_t{ttt}.ome.tif`
Registration_variable : `t`
similar_transformation_variable : `c`
template_ : `x001_y001_z001_c001_t001.ome.tif`

`Output set 2:`
Template Image: x001_y002_z001_c001_t001.ome.tif
Moving Image: x001_y002_z001_c001_t002.ome.tif
Similar Transformation Images : [ x001_y002_z001_c002_t002.ome.tif , x001_y002_z001_c003_t002.ome.tif ]
`Output set 1 :`
Template Image: x001_y001_z001_c001_t001.ome.tif
Moving Image: x001_y001_z001_c001_t002.ome.tif
Similar Transformation Images : [ x001_y001_z001_c002_t002.ome.tif , x001_y001_z001_c003_t002.ome.tif ]

`Output set 2:`
Template Image: x001_y002_z001_c001_t001.ome.tif
Moving Image: x001_y002_z001_c001_t002.ome.tif
Similar Transformation Images : [ x001_y002_z001_c002_t002.ome.tif , x001_y002_z001_c003_t002.ome.tif ]


### Registration
The registration algorithm is present in `image_registration.py`. It uses projective transformation(Homography matrix) to alter the moving image and align it with the reference image. Background information about homography can be found here: https://en.wikipedia.org/wiki/Homography .
The moving image undergoes 2 transformations:

### Registration
The registration algorithm is present in `image_registration.py`. It uses projective transformation(Homography matrix) to alter the moving image and align it with the reference image. Background information about homography can be found here: https://en.wikipedia.org/wiki/Homography .
The moving image undergoes 2 transformations:
1. `Rough Transformation` : In this the whole moving image is transformed using the homography matrix calculated between the entire moving and template image.
2. `Fine Transformation` : To carry out fine transformation ,the homography matrix is found between the corresponding tiles of the roughly transformed moving image and the template image. Each image is divided into 4 tiles.
2. `Fine Transformation` : To carry out fine transformation ,the homography matrix is found between the corresponding tiles of the roughly transformed moving image and the template image. Each image is divided into 4 tiles.

To find the homography matrix(for fine or rough tranformation), we need coordinates of atleast 4 matching points in the template and the moving image. To do this the ORB feature detector has been used. However, its computationally very expensive to run feature matching on large images(our test data consists of 1.3 gigapixel images). To overcome this, the homography matrix at every step of our algorithm has been calculated between scaled down versions( 16 * 16 times smaller) of the respective images. To use this homography matrix on actual sized images, the matrix is scaled up using a scale matrix. The proof for upscaling a homography matrix is shown below.

To find the homography matrix(for fine or rough tranformation), we need coordinates of atleast 4 matching points in the template and the moving image. To do this the ORB feature detector has been used. However, its computationally very expensive to run feature matching on large images(our test data consists of 1.3 gigapixel images). To overcome this, the homography matrix at every step of our algorithm has been calculated between scaled down versions( 16 * 16 times smaller) of the respective images. To use this homography matrix on actual sized images, the matrix is scaled up using a scale matrix. The proof for upscaling a homography matrix is shown below.
`Proof` :

`Proof` :
Credit for proof : https://stackoverflow.com/questions/21019338/how-to-change-the-homography-with-the-scale-of-the-image/56623249

![homography](https://user-images.githubusercontent.com/48079888/78402511-b04d8200-75c8-11ea-9d22-cee13f3912db.gif)

Credit for proof : https://stackoverflow.com/questions/21019338/how-to-change-the-homography-with-the-scale-of-the-image/56623249

![homography](https://user-images.githubusercontent.com/48079888/78402511-b04d8200-75c8-11ea-9d22-cee13f3912db.gif)




Expand Down Expand Up @@ -83,4 +83,3 @@ This plugin takes one input argument and one output argument:
| `--template` | Template image to be used for image registration | Input | string |
| `--TransformationVariable` | variable to help identify which images have similar transformation | Input | string |
| `--outDir` | Output collection | Output | collection |

Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.3.5
0.3.6
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash

version=$(<VERSION)
docker build . -t polusai/image-registration-plugin:${version}
docker build . -t polusai/image-registration-plugin:${version}
4 changes: 2 additions & 2 deletions transforms/images/polus-image-registration-plugin/ict.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ author:
- Gauhar Bains
- Nick Schaub
contact: gauhar.bains@labshare.org
container: polusai/image-registration-plugin:0.3.5
container: polusai/image-registration-plugin:0.3.6
description: This plugin registers an image collection
entrypoint: '[python3, main.py]'
inputs:
Expand Down Expand Up @@ -86,4 +86,4 @@ ui:
key: inputs.method
title: Deformation method
type: select
version: 0.3.5
version: 0.3.6
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ outputs:
type: Directory
requirements:
DockerRequirement:
dockerPull: polusai/image-registration-plugin:0.3.5
dockerPull: polusai/image-registration-plugin:0.3.6
InitialWorkDirRequirement:
listing:
- entry: $(inputs.outDir)
Expand Down
186 changes: 93 additions & 93 deletions transforms/images/polus-image-registration-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,95 +1,95 @@
{
"name": "Image Registration",
"version": "0.3.5",
"title": "Image Registration",
"description": "This plugin registers an image collection",
"author": "Gauhar Bains (gauhar.bains@labshare.org), Nick Schaub (nick.schaub@nih.gov) ",
"institution": "National Center for Advancing Translational Sciences, National Institutes of Health",
"repository": "https://github.com/labshare/polus-plugins",
"website": "https://ncats.nih.gov/preclinical/core/informatics",
"citation": "",
"containerId": "polusai/image-registration-plugin:0.3.5",
"inputs": [
{
"name": "inpDir",
"type": "collection",
"description": "Input image collection to be processed by this plugin",
"required": true
},
{
"name": "filePattern",
"type": "string",
"description": "Filename pattern used to separate data",
"required": true
},
{
"name": "template",
"type": "string",
"description": "Template image to be used for image registration",
"required": true
},
{
"name": "registrationVariable",
"type": "string",
"description": "variable to help identify which images need to be registered to each other",
"required": true
},
{
"name": "TransformationVariable",
"type": "string",
"description": "variable to help identify which images have similar transformation",
"required": true
},
{
"name": "method",
"type": "enum",
"description": "Projective (8 degrees of freedom), Affine (6 degrees of freedom), Partial Affine (4 degrees of freedom)",
"options": {
"values": [
"Projective",
"Affine",
"PartialAffine"
]
}
"name": "Image Registration",
"version": "0.3.6",
"title": "Image Registration",
"description": "This plugin registers an image collection",
"author": "Gauhar Bains (gauhar.bains@labshare.org), Nick Schaub (nick.schaub@nih.gov) ",
"institution": "National Center for Advancing Translational Sciences, National Institutes of Health",
"repository": "https://github.com/labshare/polus-plugins",
"website": "https://ncats.nih.gov/preclinical/core/informatics",
"citation": "",
"containerId": "polusai/image-registration-plugin:0.3.6",
"inputs": [
{
"name": "inpDir",
"type": "collection",
"description": "Input image collection to be processed by this plugin",
"required": true
},
{
"name": "filePattern",
"type": "string",
"description": "Filename pattern used to separate data",
"required": true
},
{
"name": "template",
"type": "string",
"description": "Template image to be used for image registration",
"required": true
},
{
"name": "registrationVariable",
"type": "string",
"description": "variable to help identify which images need to be registered to each other",
"required": true
},
{
"name": "TransformationVariable",
"type": "string",
"description": "variable to help identify which images have similar transformation",
"required": true
},
{
"name": "method",
"type": "enum",
"description": "Projective (8 degrees of freedom), Affine (6 degrees of freedom), Partial Affine (4 degrees of freedom)",
"options": {
"values": [
"Projective",
"Affine",
"PartialAffine"
]
}
],
"outputs": [
{
"name": "outDir",
"type": "collection",
"description": "Output collection"
}
],
"ui": [
{
"key": "inputs.inpDir",
"title": "Input collection",
"description": "Input image collection to be processed by this plugin"
},
{
"key": "inputs.filePattern",
"title": "Filename pattern",
"description": "Filename pattern used to separate data"
},
{
"key": "inputs.template",
"title": "Template Image",
"description": "Template image to be used for image registration"
},
{
"key": "inputs.registrationVariable",
"title": "Registration Variable",
"description": "variable to help identify which images need to be registered to each other"
},
{
"key": "inputs.TransformationVariable",
"title": "Similar Transformation Variable",
"description": "variable to help identify which images have similar transformation"
},
{
"key": "inputs.method",
"title": "Deformation method",
"description": "Projective (8 degrees of freedom), Affine (6 degrees of freedom), Partial Affine (4 degrees of freedom)"
}
]
}
}
],
"outputs": [
{
"name": "outDir",
"type": "collection",
"description": "Output collection"
}
],
"ui": [
{
"key": "inputs.inpDir",
"title": "Input collection",
"description": "Input image collection to be processed by this plugin"
},
{
"key": "inputs.filePattern",
"title": "Filename pattern",
"description": "Filename pattern used to separate data"
},
{
"key": "inputs.template",
"title": "Template Image",
"description": "Template image to be used for image registration"
},
{
"key": "inputs.registrationVariable",
"title": "Registration Variable",
"description": "variable to help identify which images need to be registered to each other"
},
{
"key": "inputs.TransformationVariable",
"title": "Similar Transformation Variable",
"description": "variable to help identify which images have similar transformation"
},
{
"key": "inputs.method",
"title": "Deformation method",
"description": "Projective (8 degrees of freedom), Affine (6 degrees of freedom), Partial Affine (4 degrees of freedom)"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[project]
name = "polus-image-registration-plugin"
version = "0.3.6"
description = "This plugin registers an image collection"
requires-python = ">=3.11"
dependencies = [
"numpy>=1.26.4",
"opencv-python-headless>=4.7.0",
"filepattern>=2.2.1",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src"]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Image registration plugin."""
Loading
Loading