Vous avez reçu un message "Your GitLab account has been locked ..." ? Pas d'inquiétude : lisez cet article https://docs.gricad-pages.univ-grenoble-alpes.fr/help/unlock/

Commit aef83ee2 authored by Olga Stamati's avatar Olga Stamati
Browse files

docs for spam-deformImageFromFiled rename to spam-deformImage, and docs

parent 2e1c7d9c
Pipeline #67378 passed with stages
in 27 minutes and 3 seconds
This diff is collapsed.
This diff is collapsed.
......@@ -603,11 +603,11 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2"
inkscape:cx="270.38141"
inkscape:cy="-41.923998"
inkscape:zoom="1.8632813"
inkscape:cx="163.95238"
inkscape:cy="86.330248"
inkscape:document-units="px"
inkscape:current-layer="g1777"
inkscape:current-layer="g1613"
showgrid="true"
inkscape:snap-bbox="true"
inkscape:bbox-nodes="true"
......@@ -625,7 +625,7 @@
inkscape:snap-global="false"
inkscape:window-width="1861"
inkscape:window-height="1056"
inkscape:window-x="1979"
inkscape:window-x="59"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false" />
......@@ -722,7 +722,7 @@
y="40.843662"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:32px;font-family:'TeX Gyre Pagella Math';-inkscape-font-specification:'TeX Gyre Pagella Math, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#333333" /></flowRegion><flowPara
id="flowPara1112"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:cmr10;-inkscape-font-specification:cmr10">axial displacement [px]</flowPara></flowRoot> <g
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'TeX Gyre Pagella Math';-inkscape-font-specification:'TeX Gyre Pagella Math';fill:#000000;fill-opacity:1">axial displacement [px]</flowPara></flowRoot> <g
id="g1142"
transform="matrix(0,-0.6561,0.6561,0,11.953564,71.368903)">
<g
......@@ -742,7 +742,7 @@
width="238.57143"
id="rect1126" /></flowRegion><flowPara
id="flowPara1130"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:cmr10;-inkscape-font-specification:cmr10">70</flowPara></flowRoot> </g>
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'TeX Gyre Pagella Math';-inkscape-font-specification:'TeX Gyre Pagella Math'">70</flowPara></flowRoot> </g>
</g>
<g
id="g1160"
......@@ -761,7 +761,7 @@
width="238.57143"
id="rect1144" /></flowRegion><flowPara
id="flowPara1148"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:cmr10;-inkscape-font-specification:cmr10">10</flowPara></flowRoot> </g>
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'TeX Gyre Pagella Math';-inkscape-font-specification:'TeX Gyre Pagella Math'">10</flowPara></flowRoot> </g>
</g>
</g>
<g
......@@ -780,7 +780,7 @@
x="252.85715"
y="40.843662"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:30.06956863px;font-family:'TeX Gyre Pagella Math';-inkscape-font-specification:'TeX Gyre Pagella Math, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#333333" /></flowRegion><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:cmr10;-inkscape-font-specification:cmr10"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'TeX Gyre Pagella Math';-inkscape-font-specification:'TeX Gyre Pagella Math'"
id="flowPara1483">-5</flowPara></flowRoot> <flowRoot
transform="matrix(0,0.40545974,-0.40545974,0,41.322118,369.02765)"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:30.06956863px;line-height:1.25;font-family:'TeX Gyre Pagella Math';-inkscape-font-specification:'TeX Gyre Pagella Math, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#333333;fill-opacity:1;stroke:none"
......@@ -795,7 +795,7 @@
width="238.57143"
id="rect1489" /></flowRegion><flowPara
id="flowPara1493"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:cmr10;-inkscape-font-specification:cmr10">2</flowPara></flowRoot> <flowRoot
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'TeX Gyre Pagella Math';-inkscape-font-specification:'TeX Gyre Pagella Math'">2</flowPara></flowRoot> <flowRoot
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:56.50266647px;line-height:1.25;font-family:cmr10;-inkscape-font-specification:'cmr10, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
id="flowRoot1497"
xml:space="preserve"><flowRegion
......@@ -805,7 +805,7 @@
height="73.5"
width="230.5"
id="rect1501" /></flowRegion><flowPara
id="flowPara1503"></flowPara></flowRoot> </g>
id="flowPara1503" /></flowRoot> </g>
<flowRoot
transform="matrix(0.35513546,0,0,0.35513546,509.85559,425.09713)"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:32px;line-height:1.25;font-family:'TeX Gyre Pagella Math';-inkscape-font-specification:'TeX Gyre Pagella Math, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#333333;fill-opacity:1;stroke:none"
......@@ -819,7 +819,7 @@
height="71.714287"
width="379.57144"
id="rect1459" /></flowRegion><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:cmr10;-inkscape-font-specification:cmr10"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'TeX Gyre Pagella Math';-inkscape-font-specification:'TeX Gyre Pagella Math';fill:#000000;fill-opacity:1"
id="flowPara1463">return status</flowPara></flowRoot> <g
clip-path="url(#clipPath1621)"
id="g1617"
......
This diff is collapsed.
This diff is collapsed.
......@@ -262,7 +262,7 @@ The script can be run like this:
- If **returnStatus = -3**: Registration **diverged** on displacement or volumetric change condition. Retry with a higher margin ``-m``?
- Check the **greylevel residual fields**.
If not saved, create the deformed image 1 by running :ref:`deformImage`.
If not asked with ``-def``, create the deformed image 1 by running :ref:`deformImage`.
Compare the initial difference (im1.tif - im2.tif) and the new difference (im1Def.tif - im2.tif), which should look like this:
.. figure:: images/tutorial/scripts/regResult.png
......@@ -273,7 +273,7 @@ The script can be run like this:
Are you satisfied with this **overall** deformation?
If yes, and you wish to go and look **locally**, **keep this Φ** and move towards :ref:`pixelSearch` or :ref:`ldic`.
If yes, and you wish to go and look **locally**, **keep this Φ** and move towards :ref:`pixelSearch`, :ref:`ldic` or :ref:`ddic`.
|
|
......@@ -344,7 +344,7 @@ It measures a **displacement field** with a **1-pixel sensitivity** that maps im
For **discrete** mode:
- ``-ld``: Number of times to dilate labels before extracting them (see :ref:`labelToolkitTutorial`)
- ``-vt``: **I thought that was an option!!**
- ``-lvt``: Labels with volume **smaller** than this threshold are ignored
``Output:``
......@@ -391,7 +391,10 @@ For the **discrete** mode, the script can be run like this:
- Check the **pixelSearchCC** values. A cross-correlation procedure is **successful** when the **correlation coefficient** is **close to 1**. Are these values low? Perhaps think of a coarser field (increase ``-ns``)? And then pass this to the finer one through `spam-passField`
- Check the measured **displacements**. If you notice that the displacement values hit the limits of your input search range, retry by increasing this range
- Check the measured **displacement fields**. Do the points move as you would expect? For example you are pulling your material from the bottom edge. Do the displacement vectors point downwards increasing from the top to the bottom of your field?
- Check the **residual fields**. Use the measured displacement field to deform im1. Check the initial difference (im2.tif - im1.tif) and the new difference (im2.tif - im1Def.tif).
- Check the **greylevel residual fields**. Create the deformed image 1 by running :ref:`deformImage`. Compare the initial difference (im1.tif - im2.tif) and the new difference (im1Def.tif - im2.tif). It should look like this:
.. figure:: images/tutorial/scripts/psResult.png
:align: center
Are you satisfied with the measured displacement field?
......@@ -733,7 +736,7 @@ This script facilitates the manipulation of different Φ fields, applying a sing
1. A **single** deformation function (one-line file). This is typically the result of :ref:`ereg` or :ref:`register`
2. A **field** of deformation functions (multiple-line file). For example, the result of :ref:`pixelSearch`, :ref:`pixelSearchPropagate`, :ref:`ldic`, :ref:`ddic`
If this file refers to downscaled images, use ``-pfb`` to set the correct binning ratio
If this file refers to downscaled\upscaled images, use ``-pfb`` to set the correct binning ratio
**Optional**
- ``-np``: Number of **parallel processes** to use. If not passed, all the CPUs available in the system will be used
......@@ -827,7 +830,7 @@ This script **corrects** or **filters** a deformation **field**.
- It is **recommended** to use this script **before** calculating **strains**.
.. ATTENTION:: Only **one operation** is allowed at a time. This means that you can either ask for a **correction** **OR** a **filtering** of your input field.
.. ATTENTION:: Only **one operation** is allowed at a time. This means that you can either ask for **correction** **OR** **filtering** of your input field.
You can for example:
1. Run a first computation for correcting badly correlated points and
......@@ -839,30 +842,33 @@ This script **corrects** or **filters** a deformation **field**.
The **selection** of bad points can be based on **one** of the following metrics:
- The **correlation coefficient**, activated with ``-scct``
A point's correlation coefficient is the result of :ref:`pixelSearch` or :ref:`pixelSearchPropagate`.
Typically a point with a coefficient **greater** than **0.99** is considered as **successfully** correlated
- The **return status**, activated with ``-srs``
A point's return status is the result of :ref:`ldic` or :ref:`ddic`. A return status equals to **2** means that the local algorithm inside ``spam.DIC.register()`` has **converged**
A point's return status is the result of :ref:`ldic` or :ref:`ddic`.
A return status equal to **2** means that the local algorithm inside ``spam.DIC.register()`` has **converged**.
A threshold below which points are considered bad can set with ``-srst``.
- The **correlation coefficient**, activated with ``-scc``
A point's correlation coefficient is the result of :ref:`pixelSearch` or :ref:`pixelSearchPropagate`.
Typically a point with a coefficient **greater** than **0.99** is considered as **successfully** correlated.
A threshold below which points are considered bad can be set with ``-scct``.
- The **local coherency**, activated with ``-slqc``
As per per Masullo and Theunissen 2016, a point's local coherency is the average residual between the point's displacement and a second-order parabolic surface,
fitted to the point's closest N neighbours and evaluated at the point's position.
Typically, a point with a coherency value **smaller** than **0.1** is classified as **coherent**.
The estimation of the local coherency is implemented in ``spam.DIC.estimateLocalQuadraticCoherency()`` and is based on https://gricad-gitlab.univ-grenoble-alpes.fr/DVC/pt4d.
Typically, a point with a coherency value **smaller** than **0.1** is classified as **coherent**. Thus, no input coherency threshold is allowed.
The **correction** of bad points can be done with **one** of the following operations:
- Inverse distance weighting of closest good neighbours, activated with ``-cint``
- Gaussian distance weighting of closest good neighbours, activated with
- Local quadratic fit of closest good neighbours, activated with ``-clqf``
Closest neighbours are selected based on distance ``-nr`` or number ``-nn``.
This script **filters** the input field based on:
- An overall median filter, activated with ``-fm`` with a given radius ``-fmr``
- An overall median filter, activated with ``-fm`` with a given radius ``-fmr``.
You can choose to filter all components of Φ ( ``-F all`` ) or only the displacements ( ``-F no``).
For both correction and filtering, this script by default **ignores background points** based their return status (*i.e, returnStatus=-5*). If you want to change this behaviour see ``-nomask`` input option.
......@@ -872,7 +878,10 @@ This script **corrects** or **filters** a deformation **field**.
**Required**
- ``-pf``: *".tsv"* file containing the deformation **field**. This file can come either from :ref:`pixelSearch`, :ref:`pixelSearchPropagate`, :ref:`ldic`, :ref:`passPhi` or :ref:`filterPhi`. If this file refers to downscaled images, use ``-pfb`` to set the correct binning ratio
- ``-pf``: *".tsv"* file containing the deformation **field**.
This file can come either from :ref:`pixelSearch`, :ref:`pixelSearchPropagate`, :ref:`ldic`, :ref:`passPhi` or :ref:`filterPhi`.
If this file refers to downscaled/upscaled images, use ``-pfb`` to set the correct binning ratio
**Optional**
......@@ -885,10 +894,10 @@ This script **corrects** or **filters** a deformation **field**.
- ``-scc``: Selects **bad** points based on their **correlation coefficient**. This is for fields coming from :ref:`pixelSearch`, :ref:`pixelSearchPropagate`. See ``-scct`` for setting the threshold. Disactivates ``-slqc``
- ``-scct``: Correlation coefficient **threshold below** which points are considered **bad**. Default behaviour selects points with CC<=0.99
- ``-slqc``: Selects **bad** points based on their local quadratic coherency value. Default behaviour selects points with coherency **bigger** or equal to 0.1. This threshold is **not** modifiable
- ``-cint``: **Corrects** selected **bad** points by an **interpolation** of the extracted neighbours' Φ with weights equal to the **inverse** of the **distance**. See ``-m`` to select the interpolated components
- ``-m``: Choose which **part of Φ** (see :ref:`imageCorrelationTheory`) will be corrected/filtered. If **"all"** all deformation components are considered (default behaviour). If **"rigid"** the rigid body motion is considered. If **"disp"** only displacements are considered
- ``-cint``: **Corrects** selected **bad** points by an **interpolation** of the extracted neighbours' Φ with weights equal to the **inverse** of the **distance**. See ``-F`` to select the interpolated components
- ``-F``: Choose which **part of Φ** (see :ref:`imageCorrelationTheory`) will be corrected/filtered. If **"all"** all deformation components are considered (default behaviour). If **"rigid"** the rigid body motion is considered. If **"no"** only displacements are considered
- ``-clqf``: **Corrects** selected **bad** points based on local **quadratic fit** of the extracted neighbours. The filt only applies to the **displacement** vector
- ``-fm``: Activates an overall **median filter** on the deformation field. ``-m`` can be set either as **"all"** or as **"disp"**. The filtering operation is allowed only if **none** of ``-scc``, ``-slqc`` or ``-slqc`` is passed
- ``-fm``: Activates an overall **median filter** on the deformation field. ``-F`` can be set either as **"all"** or as **"no"**. The filtering operation is allowed only if **none** of ``-scc``, ``-slqc`` or ``-slqc`` is passed
- ``-fmr``: Sets the radius (in pixels) of the median filter. Default behaviour is a radius of 1 pixel
- ``-od``: Defines the **output** directory
- ``-pre``: Defines the prefix for the **output** files
......@@ -902,7 +911,7 @@ This script **corrects** or **filters** a deformation **field**.
- A *".tsv"* file containing:
- The points position (Z, Y, X) which are the **same** as the **input** field
- The components of the points deformation functions (*Fzz*, *Fzy*, *Fzx*, *Zdisp*, *etc*). See :ref:`imageCorrelationTheory` for explanation of these components. Deformation components of **good** and **background** points are **not modified**
- The components of each point's deformation function (*Fzz*, *Fzy*, *Fzx*, *Zdisp*, *etc*). See :ref:`imageCorrelationTheory` for explanation of these components. Deformation components of **good** and **background** points are **not modified**
- Information related to the iterative algorithm status (*returnStatus*, *iterations*, *etc*). Values of **good** and **background** points are **not modified**. *returnStatus* of corrected/filtered **bad** points is set equal to 1
- If asked with ``-tif`` or ``-vtk``: Files containing the corrected/filtered deformation fields
......@@ -916,11 +925,10 @@ For a **correction** operation the script can be run like this:
(spam) $ spam-filterPhiField # the script
-pf /path/to/my/data/PhiField.tsv\ # the file containing the deformation field
-srs -srst 1\ # select bad correlation points based on return status equal or less than 1
-nn 27\ # extract closest 27 good neighbours
-cint -m "disp"\ # correct displacements of bad points based on an inverse weighted distance interpolation of extracted good neighbours displacements
-nn X\ # extract closest X good neighbours
-cint -F "no"\ # correct displacements of bad points based on an inverse weighted distance interpolation of extracted good neighbours displacements
-tif -vtk # ask for TIFF file and VTK outputs
The script can be run like this:
For a **filtering** operation the script can be run like this:
......@@ -929,12 +937,12 @@ For a **filtering** operation the script can be run like this:
$ source path/to/spam/venv/bin/activate
(spam) $ spam-filterPhiField # the script
-pf /path/to/my/data/PhiField.tsv\ # the file containing the deformation field
-fm -fmr 2 -m "disp"\ # ask for a median filter of the input displacements with a radius of 2 px
-fm -fmr X -F "all"\ # ask for a median filter of the input displacements with a radius of X px
-tif -vtk # ask for TIFF file and VTK outputs
.. tip:: The result of this script could look like this:
.. figure:: images/tutorial/scripts/filterOutput.png
.. figure:: images/tutorial/scripts/filterResult.png
:align: center
Are you satisfied with the corrected/filtered displacement field?
......@@ -1008,11 +1016,79 @@ The script can be run like this:
.. _deformImage:
Deform image script (spam-deformImageFromField)
--------------------------------------------------
Deform image script (spam-deformImage)
-----------------------------------------
This script deforms an image based on a given deformation.
.. tip:: When to use this script?
When you measured a **deformation** between two configurations and you want to **apply** it to your **initial configuration** (or im1) and **see** **how** it is deformed:
.. figure:: images/tutorial/scripts/defInput.png
:align: center
Greylevel images and their measured displacement field coming from :ref:`pixelSearch` after being filtered by running :ref:`filterPhi`
.. IMPORTANT::
The input deformation file can be:
- A **single** deformation function: The measured Φ matrix is used to **map** each voxel position from the initial to the deformed configuration (x' = Φx)
- A **field** of deformation functions: The **displacement** part of the Φ field is used to triangulate (using CGAL) the displaced measurement positions and interpolate the greyvalue of each voxel
``Input:``
.............
**Required**
- **A TIFF greyscale image**, representing the initial (im1) configuration that will be deformed
- ``-pf``: *".tsv"* file containing the input deformation field
.. HINT:: This can be either:
1. A **single** deformation function (one-line file). This is typically the result of :ref:`ereg` or :ref:`register`
2. A **field** of deformation functions (multiple-line file). For example, the result of :ref:`pixelSearch`, :ref:`pixelSearchPropagate` or :ref:`ldic`
If this file refers to downscaled/upscaled images, use ``-pfb`` to set the correct binning ratio
**Optional**
- ``-rr``: Only if input ``-pf`` is a **single matrix**. Deforms the image using only the **rigid** part of Φ (only translations and rotations)
- ``-a``: Only if input ``-pf`` is a **field**. CGAL Alpha value for triangulation cleanup (negative = auto, zero = no cleanup, positive = userval)
- ``-rad``: Only if input ``-pf`` is a **field**. Exclude points outside a given **radius**. Assumes a cylinder with the axis in z-direction
- ``-od``: Defines the **output** directory
- ``-pre`` Defines the prefix for the **output** file
.. - ``-cgs``: Only if input ``-pf`` is a **field**. Corrects greyvalues according to strain in tetrahedron. For a dry sample, greyvalues of vacuum should be =0 (Stavropoulou et al. 2020 Frontiers Eq. 12 with mu_w=0)
``Output:``
.............
This scripts deforms an image based on an input deformation file.
- A *".tif"* file corresponding to im1 deformed by the input deformation file
The script can be run like this:
.. code-block:: console
$ source path/to/spam/venv/bin/activate
(spam) $ spam-passPhiField # the script
/path/to/my/data/im1.tif # the 3D image (tiff file) to be deformed
-pf /path/to/my/data/PhiField.tsv\ # the file containing the deformation file
-r X # the radius to exclude points from the triangulation
.. tip:: It is highly recommended to use this script to calculate **greylevel residual fields** and **evaluate** any of your **correlation** steps:
.. figure:: images/tutorial/scripts/defResult.png
:align: center
Greylevel images and their residual fields before and after a correlation
|
|
|
|
|
|
|
......
#!/usr/bin/env python
"""
This script deforms an image according to an input deformation field using SPAM functions
Copyright (C) 2020 SPAM Contributors
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
This script can be very useful for generating deformed images to calculate a residual field
The current implementation will mesh correlation points with tetrahedra and deform them with displacements,
this has the advantage of speed, but the interpolation of displacements is approximative.
We don't use the more accurate `spam.DIC.deformationFunction.applyPhiField` which is slow for large images
"""
import numpy
import argparse
import spam.helpers
import spam.mesh
import spam.label
import spam.DIC
import spam.deformation
import tifffile
# Define argument parser object
parser = argparse.ArgumentParser(description="spam-deformImage "+spam.helpers.optionsParser.GLPv3descriptionHeader +\
"This deforms our input image according to some measured kinematics.\n"+\
"If a registration is given, it is wholly applied, otherwise if a displacement"+\
"field is given, it is triangulated and the displacements are applied",
formatter_class=argparse.RawTextHelpFormatter)
# Parse arguments with external helper function
args = spam.helpers.optionsParser.deformImageParser(parser)
print("spam-deformImage: Current Settings:")
argsDict = vars(args)
for key in sorted(argsDict):
print("\t{}: {}".format(key, argsDict[key]))
print()
# Read displacements file
TSV = spam.helpers.readCorrelationTSV(args.PHIFILE.name, fieldBinRatio=args.PHIFILE_BIN_RATIO, readConvergence=True)
im = tifffile.imread(args.inFile.name)
# in case of a registration (assuming it's applied in the middle of the volume)
if TSV['PhiField'].shape[0] == 1:
print("Registration mode, assuming Phi should be applied in the middle")
Phi = TSV['PhiField'][0]
if args.RIGID:
PhiDecomposed = spam.deformation.decomposePhi(Phi)
Phi = spam.deformation.computePhi({'t': PhiDecomposed['t'],
'r': PhiDecomposed['r']})
print("Using only rigid part of the registration")
imdef = spam.DIC.applyPhi(im, Phi=Phi)
else:
# Define a linear mask for points
mask = numpy.zeros(TSV['fieldCoords'].shape[0], dtype=bool)
# Accept points that have converged
mask[TSV['returnStatus']==2] = True
if args.RADIUS is not None:
# Also exclude based on radius
radius = args.RADIUS
y = TSV['fieldCoords'][:,1].copy()
y -= (im.shape[1]-1)/2.0
x = TSV['fieldCoords'][:,2].copy()
x -= (im.shape[2]-1)/2.0
r = numpy.sqrt( numpy.square(x) + numpy.square(y))
mask[r > args.RADIUS] = False
print("Proportion of correlation points included {:0.0f}%".format(100*(mask.sum()/(len(mask)-1))))
# update points
points = TSV['fieldCoords'][mask]
# update displacements
disp = TSV['PhiField'][mask][:,0:3,-1]
print("\tnPoints = ",points.shape[0])
# 2019-12-10 EA and OS: triangulate in the deformed configuration
conn = spam.mesh.triangulate(points+disp, alpha=args.TRI_ALPHA)
print("\tnTets = ",conn.shape[0])
print("\tGenerating labelled tet image... ", end='')
# 2019-12-10 EA and OS: label tetrahedra in deformed configuration
tetLabel = spam.label.labelTetrahedra(im.shape, points+disp, conn)
print("done")
imdef = numpy.zeros_like(im, dtype='<f4')
print("Interpolating image... ", end='')
# 2019-12-10 EA and OS: look up pixels, remember im is the reference configuration that we are deforming
spam.DIC.DICToolkit.applyMeshTransformation(im.astype('<f4'),
tetLabel.astype("<u4"),
imdef,
conn.astype("<u4"),
(points+disp).astype("<f8"),
disp.astype("<f8"))
print("done")
if args.CORRECT_GREY_FOR_STRAIN:
print("Correcting greyvalues for strain, assuming that vacuum greylevel = 0.0", end='')
# We're going to pre-deform the greylevels using the tetLabel as a mask
volumesRef = spam.mesh.tetVolumes(points, conn)
volumesDef = spam.mesh.tetVolumes(points+disp, conn)
volStrain = volumesDef/volumesRef
volStrain[volumesRef == 0] = 0.0
correction = spam.label.convertLabelToFloat(tetLabel, volStrain)
imdef /= correction
del correction
print("done")
print("Saving deformed image:\n\t{}".format(args.OUT_DIR + "/" + args.PREFIX + ".tif"))
tifffile.imsave(args.OUT_DIR + "/" + args.PREFIX + ".tif", imdef.astype(im.dtype))
#!/usr/bin/env python
"""
This script deforms an image according to an input deformation field using SPAM functions
Copyright (C) 2020 SPAM Contributors
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
This script can be very useful for generating deformed images to calculate a residual field
The current implementation will mesh correlation points with tetrahedra and deform them with displacements,
this has the advantage of speed, but the interpolation of displacements is approximative.
We don't use the more accurate `spam.DIC.deformationFunction.applyPhiField` which is slow for large images
"""
from __future__ import print_function
import numpy
import argparse
import spam.helpers
import spam.mesh
import spam.label
import spam.DIC
import spam.deformation
import tifffile
# Define argument parser object
parser = argparse.ArgumentParser(description="spam-deformImageFromField "+spam.helpers.optionsParser.GLPv3descriptionHeader +\
"This deforms our input image according to some measured kinematics.\n"+\
"If a registration is given, it is wholly applied, otherwise if a displacement"+\
"field is given, it is triangulated and the displacements are applied",
formatter_class=argparse.RawTextHelpFormatter)
# Parse arguments with external helper function
args = spam.helpers.optionsParser.deformImageFromFieldParser(parser)
print("spam-deformImageFromField: Current Settings:")
argsDict = vars(args)
for key in sorted(argsDict):
print("\t{}: {}".format(key, argsDict[key]))
print()
# Read displacements file
TSV = spam.helpers.readCorrelationTSV(args.PHIFILE.name, fieldBinRatio=args.PHIFILE_BIN_RATIO, readConvergence=True)
im = tifffile.imread(args.inFile.name)
# in case of a registration (assuming it's applied in the middle of the volume)
if TSV['PhiField'].shape[0] == 1:
print("Registration mode, assuming Phi should be applied in the middle")
Phi = TSV['PhiField'][0]
if args.RIGID:
PhiDecomposed = spam.deformation.decomposePhi(Phi)
Phi = spam.deformation.computePhi({'t': PhiDecomposed['t'],
'r': PhiDecomposed['r']})
print("Using only rigid part of the registration")
imdef = spam.DIC.applyPhi(im, Phi=Phi)
else:
# Define a linear mask for points
mask = numpy.zeros(TSV['fieldCoords'].shape[0], dtype=bool)
# Accept points that have converged
mask[TSV['returnStatus']==2] = True
if args.RADIUS is not None:
# Also exclude based on radius
radius = args.RADIUS
y = TSV['fieldCoords'][:,1].copy()
y -= (im.shape[1]-1)/2.0
x = TSV['fieldCoords'][:,2].copy()
x -= (im.shape[2]-1)/2.0
r = numpy.sqrt( numpy.square(x) + numpy.square(y))
mask[r > args.RADIUS] = False
print("Proportion of correlation points included {:0.0f}%".format(100*(mask.sum()/(len(mask)-1))))
# update points
points = TSV['fieldCoords'][mask]
# update displacements
disp = TSV['PhiField'][mask][:,0:3,-1]
print("\tnPoints = ",points.shape[0])
# 2019-12-10 EA and OS: triangulate in the deformed configuration
conn = spam.mesh.triangulate(points+disp, alpha=args.TRI_ALPHA)
print("\tnTets = ",conn.shape[0])
print("\tGenerating labelled tet image... ", end='')
# 2019-12-10 EA and OS: label tetrahedra in deformed configuration
tetLabel = spam.label.labelTetrahedra(im.shape, points+disp, conn)
print("done")
imdef = numpy.zeros_like(im, dtype='<f4')
print("Interpolating image... ", end='')
# 2019-12-10 EA and OS: look up pixels, remember im is the reference configuration that we are deforming
spam.DIC.DICToolkit.applyMeshTransformation(im.astype('<f4'),
tetLabel.astype("<u4"),
imdef,
conn.astype("<u4"),
(points+disp).astype("<f8"),
disp.astype("<f8"))
print("done")
if args.CORRECT_GREY_FOR_STRAIN:
print("Correcting greyvalues for strain, assuming that vacuum greylevel = 0.0", end='')
# We're going to pre-deform the greylevels using the tetLabel as a mask
volumesRef = spam.mesh.tetVolumes(points, conn)
volumesDef = spam.mesh.tetVolumes(points+disp, conn)
volStrain = volumesDef/volumesRef
volStrain[volumesRef == 0] = 0.0
correction = spam.label.convertLabelToFloat(tetLabel, volStrain)
imdef /= correction
del correction
print("done")
print("Saving deformed image:\n\t{}".format(args.OUT_DIR + "/" + args.PREFIX + ".tif"))
tifffile.imsave(args.OUT_DIR + "/" + args.PREFIX + ".tif", imdef.astype(im.dtype))
print('Please use the spam-deformImage script')