RNiftyReg
An R interface to the NiftyReg medical image registration library
Science Score: 26.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
○CITATION.cff file
-
✓codemeta.json file
Found codemeta.json file -
✓.zenodo.json file
Found .zenodo.json file -
○DOI references
-
○Academic publication links
-
○Committers with academic emails
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (15.6%) to scientific vocabulary
Keywords
image-registration
medical-imaging
r
transformations
Last synced: 6 months ago
·
JSON representation
Repository
An R interface to the NiftyReg medical image registration library
Basic Info
Statistics
- Stars: 43
- Watchers: 4
- Forks: 6
- Open Issues: 0
- Releases: 3
Topics
image-registration
medical-imaging
r
transformations
Created over 14 years ago
· Last pushed 10 months ago
Metadata Files
Readme
Changelog
README.Rmd
```{r, echo=FALSE}
options(mmand.display.newDevice=FALSE)
knitr::opts_chunk$set(collapse=TRUE, fig.path="tools/figures/", dpi=150, fig.dim=c(3.49,2.42))
```
[](https://cran.r-project.org/package=RNiftyReg) [](https://github.com/jonclayden/RNiftyReg/actions/workflows/ci.yaml) [](https://app.codecov.io/gh/jonclayden/RNiftyReg) [](https://cran.r-project.org/package=RNiftyReg)
# RNiftyReg: Nifty Registration in R
The `RNiftyReg` package is an R-native interface to the [NiftyReg image registration library](https://github.com/KCL-BMEIS/niftyreg). The package incorporates the library, so it does not need to be installed separately, and it replaces the NiftyReg command-line front-end with a direct, in-memory bridge to R, based on [the `RNifti` package](https://github.com/jonclayden/RNifti).
This `README` file primarily covers version 2.0.0 of the package and later. The interface was substantially reworked in that version to make it more natural and less verbose, and earlier versions are incompatible.
The package can be installed from CRAN, or the latest development version obtained directly from GitHub:
```{r, eval=FALSE}
## install.packages("remotes")
remotes::install_github("jonclayden/RNiftyReg")
```
The [`mmand` package](https://github.com/jonclayden/mmand) for image processing may also be useful, and is used in some of the examples below.
## Contents
- [Reading and writing images](#reading-and-writing-images)
- [Image registration](#image-registration)
- [Applying and manipulating transformations](#applying-and-manipulating-transformations)
- [Convenience functions](#convenience-functions)
## Reading and writing images
`RNiftyReg` may be used to register and manipulate two and three dimensional images of any sort, although its origins are in medical imaging. Medical images in the standard NIfTI-1 format may be read into R using the `readNifti` function, which is based on the first-party [`RNifti` package](https://github.com/jonclayden/RNifti).
```{r}
library(RNiftyReg)
image <- readNifti(system.file("extdata", "epi_t2.nii.gz", package="RNiftyReg"))
```
This image is an R array with some additional attributes containing information such as its dimensions and the size of its pixels (or voxels, in this case, since it is a 3D image).
As mentioned above, however, images do not have to be in NIfTI-1 format. Any numeric matrix or array can be used, and standard image formats such as JPEG and PNG can be read in using additional packages. For example,
```{r}
## install.packages("jpeg")
library(jpeg)
image <- readJPEG(system.file("extdata", "house_colour_large.jpg", package="RNiftyReg"))
```
Complementary `writeNifti` and `writeJPEG` functions are provided by the `RNifti` and `jpeg` packages, respectively.
## Image registration
Once two or more images have been read into R, they can be registered. Registration is the dual operation of searching a space of transformations for the best way to align two images, and then resampling one image onto the grid of the other. The images need not be the same size or in the same orientation.
There are two main classes of transformation available: linear and nonlinear. Linear, and specifically *affine*, transforms can represent translation, scaling and rotation in 2D or 3D space. They have up to 12 degrees of freedom and are appropriate to capture global shifts between images. Nonlinear transformations have many more degrees of freedom, and can capture localised distortions between images, but they are more time-consuming to estimate and more complex to work with.
Some sample 3D medical images are included with the package. We begin by registering two brain scan images, of the same person, with different contrasts. First we read them in, and then we pass them to the package's core registration function, `niftyreg`.
```{r, eval=FALSE}
source <- readNifti(system.file("extdata", "epi_t2.nii.gz", package="RNiftyReg"))
target <- readNifti(system.file("extdata", "flash_t1.nii.gz", package="RNiftyReg"))
result <- niftyreg(source, target)
```
The last command will take a few seconds to complete. The `result` is a list with a number of components, the most important of which is the resampled source image in target space, `result$image`.
By default the transformation will be an affine matrix. If we want to allow for a nonlinear transformation, with scope for local deformations between one space and the other, we can perform an additional registration as follows.
```{r, eval=FALSE}
result <- niftyreg(source, target, scope="nonlinear", init=forward(result))
```
Notice the `scope` argument, and also the fact that we use the result of the previous linear registration to initialise the nonlinear one. (The `forward` function extracts the forward transformation from the previous registration.) This should result in reduced convergence time, since the affine transformation provides a first approximation for the nonlinear registration algorithm. Nevertheless, this algorithm will generally take longer to complete.
## Applying and manipulating transformations
Once a transformation between two images has been established through registration, it can be extracted, applied to another image or pixel coordinates, or manipulated. Transformations can also be read from or written to file, or created from scratch. Registration is by default symmetric, meaning that forward and reverse transformations are calculated simultaneously. These can be extracted using the `forward` and `reverse` functions.
Let's use a simple image by way of example. We will need the `jpeg` package to read it in, and the `mmand` package (version 1.2.0 or later) to visualise it.
```{r, house}
## install.packages(c("jpeg","mmand"))
library(jpeg); library(mmand)
house <- readJPEG(system.file("extdata", "house_colour_large.jpg", package="RNiftyReg"))
display(house)
```
Clearly this is a colour image, with red, green and blue channels. `RNiftyReg` can work with it in this format, but internally the channels will be averaged before the registration starts. This step performs a colour-to-greyscale conversion equivalent to
```{r, house-bw}
house_bw <- apply(house, 1:2, mean)
display(house_bw)
```
Now, instead of registering the image to another image, let's create a simple affine transformation that applies a skew to the image.
```{r}
affine <- buildAffine(skews=0.1, source=house)
print(affine)
```
So, this is a diagonal matrix with just a single off-diagonal element, which produces the skew effect. (The sign is negative because NiftyReg actually represents transforms from target to source space, not the more intuitive reverse.) Let's apply it to the image using the important `applyTransform` function, and see the effect.
```{r, house-skewed}
house_skewed <- applyTransform(affine, house)
display(house_skewed)
```
Moreover, we can transform a pixel coordinate into the space of the skewed image:
```{r}
applyTransform(affine, c(182,262,1))
```
Notice that the skew changes the first coordinate (in the up-down direction), but not the second (in the left-right direction) or third (the colour channel number).
Finally, we can register the original image to the skewed one, to recover the transformation:
```{r}
result <- niftyreg(house, house_skewed, scope="affine")
print(forward(result))
```
Notice that the estimated transformation closely approximates the generative one, with the element in row 1, column 2 being very close to -0.1. We can decompose this estimated transformation and recover the skew component:
```{r}
decomposeAffine(forward(result))$skews
```
Two other manipulations can be helpful to know about. The first is calculating a half-transform, which can be used to transform the image into a space halfway to the target. For example, using our registration result from above,
```{r, house-halfskewed}
half_xfm <- halfTransform(forward(result))
display(applyTransform(half_xfm, house))
```
This results in half of the skew effect being applied. Finally, the `composeTransforms` function allows the effects of two transforms to be combined together. Combining a half-transform with itself will result in the original full transform.
```{r}
all.equal(forward(result), composeTransforms(half_xfm,half_xfm), check.attributes=FALSE)
```
## Convenience functions
The package provides a group of convenience functions—`translate`, `rescale`, `skew` and `rotate`—which can be used to quickly apply simple transformations to an image. For example, the skew operation applied above can be more compactly written as
```{r, house-reskewed}
house_skewed <- skew(house, 0.1)
display(house_skewed)
```
Since these take the image as their first argument, they are compatible with the chaining operator from the [popular `magrittr` package](https://cran.r-project.org/package=magrittr). However, because such a chain applies multiple transformations to an image, there may be a loss of precision, or of data, compared to a single more complex operation. For example, while
```{r, house-transformed1}
library(magrittr)
house_transformed <- house %>% rotate(pi/4, anchor="centre") %>% translate(30)
display(house_transformed)
```
is much more readable than
```{r, house-transformed2}
xfm <- composeTransforms(buildAffine(angles=pi/4, anchor="centre", source=house), buildAffine(translation=30, source=house))
house_transformed <- applyTransform(xfm, house)
display(house_transformed)
```
the latter avoids the creation of a black band across the top of the final image, since it has access to the full content of the original image, rather than just the truncated version produced by the rotation.
Owner
- Name: Jon Clayden
- Login: jonclayden
- Kind: user
- Location: United Kingdom
- Company: University College London
- Website: https://www.clayden.org
- Twitter: jonclayden
- Repositories: 46
- Profile: https://github.com/jonclayden
Image processing, scientific computing and data science, mostly with R and C++
GitHub Events
Total
- Watch event: 5
- Push event: 5
- Create event: 2
Last Year
- Watch event: 5
- Push event: 5
- Create event: 2
Committers
Last synced: about 1 year ago
Top Committers
| Name | Commits | |
|---|---|---|
| Jon Clayden | c****e@c****g | 545 |
Committer Domains (Top 20 + Academic)
clayden.org: 1
Issues and Pull Requests
Last synced: 11 months ago
All Time
- Total issues: 22
- Total pull requests: 0
- Average time to close issues: about 2 months
- Average time to close pull requests: N/A
- Total issue authors: 18
- Total pull request authors: 0
- Average comments per issue: 6.23
- Average comments per pull request: 0
- Merged pull requests: 0
- Bot issues: 0
- Bot pull requests: 0
Past Year
- Issues: 0
- Pull requests: 0
- Average time to close issues: N/A
- Average time to close pull requests: N/A
- Issue authors: 0
- Pull request authors: 0
- Average comments per issue: 0
- Average comments per pull request: 0
- Merged pull requests: 0
- Bot issues: 0
- Bot pull requests: 0
Top Authors
Issue Authors
- muschellij2 (3)
- DanRuderman (2)
- CST333 (2)
- Nickname777777 (1)
- christmanjc (1)
- mpadge (1)
- Jonathan-Gore (1)
- charleswg (1)
- ReddyRaveen (1)
- NHPatterson (1)
- Veerle-Haemels (1)
- HikaruSama233 (1)
- gangcai (1)
- daniel-adrian (1)
- ms-program (1)
Pull Request Authors
Top Labels
Issue Labels
Pull Request Labels
Packages
- Total packages: 2
-
Total downloads:
- cran 1,489 last-month
- Total docker downloads: 21,785
-
Total dependent packages: 4
(may contain duplicates) -
Total dependent repositories: 16
(may contain duplicates) - Total versions: 44
- Total maintainers: 1
cran.r-project.org: RNiftyReg
Image Registration Using the 'NiftyReg' Library
- Homepage: https://github.com/jonclayden/RNiftyReg
- Documentation: http://cran.r-project.org/web/packages/RNiftyReg/RNiftyReg.pdf
- License: GPL-2
-
Latest release: 2.8.4
published over 1 year ago
Rankings
Dependent repos count: 7.1%
Stargazers count: 7.9%
Dependent packages count: 9.3%
Forks count: 9.6%
Average: 12.3%
Downloads: 14.1%
Docker downloads count: 25.7%
Maintainers (1)
Last synced:
6 months ago
conda-forge.org: r-rniftyreg
- Homepage: https://github.com/jonclayden/RNiftyReg
- License: GPL-2.0-only
-
Latest release: 2.7.0
published over 5 years ago
Rankings
Dependent repos count: 34.0%
Stargazers count: 40.5%
Average: 42.9%
Forks count: 46.0%
Dependent packages count: 51.2%
Last synced:
6 months ago
Dependencies
DESCRIPTION
cran
- RNifti * imports
- Rcpp * imports
- ore * imports
- covr * suggests
- jpeg * suggests
- loder * suggests
- mmand * suggests
- testthat * suggests