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 fb1f8044 authored by Edward Andò's avatar Edward Andò
Browse files

spam-reg script plus some cleanup of spam-ereg

parent 9a86200c
#!/usr/bin/env python
"""
This script performs a registration between two images, aiming to measure a
single Phi (a homogeneous deformation function) to map im1 into im2
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 is a good initial starting point for a the measurement of a displacement
field, if there is a homogeneous background movement to measure
"""
import numpy
import argparse
#import spam.helpers
#import spam.mesh
#import spam.label
import spam.DIC
#import spam.deformation
import tifffile
import os
# Define argument parser object
parser = argparse.ArgumentParser(description="spam-register "+spam.helpers.optionsParser.GLPv3descriptionHeader +\
"This script tries to measure Phi from im1 to im2\n",
formatter_class=argparse.RawTextHelpFormatter)
# Parse arguments with external helper function
args = spam.helpers.optionsParser.register(parser)
print("Current Settings:")
argsDict = vars(args)
for key in sorted(argsDict):
print("\t{}: {}".format(key, argsDict[key]))
# Load reference image
im1 = tifffile.imread(args.im1.name)
if args.MASK1:
im1mask = tifffile.imread(args.MASK1.name) != 0
else:
im1mask = None
im2 = tifffile.imread(args.im2.name)
if args.PHIFILE is not None:
PhiFromFile = spam.helpers.readCorrelationTSV(args.PHIFILE.name, fieldBinRatio=args.PHIFILE_BIN_RATIO)
# If the read Phi-file has only one line -- it's a single point registration!
if PhiFromFile['fieldCoords'].shape[0] == 1:
PhiInit = PhiFromFile['PhiField'][0]
#regCentre = PhiFromFile['fieldCoords'][0]
#print("\tI read a registration from a file in binning {} at centre {} at this scale".format(args.PHIFILE_BIN_RATIO, regCentre) )
print("\tI read a registration from a file in binning {}".format(args.PHIFILE_BIN_RATIO))
print("\tTranslations (px)")
print("\t\t", spam.deformation.decomposePhi(PhiInit)['t'])
print("\tRotations (deg)")
print("\t\t", spam.deformation.decomposePhi(PhiInit)['r'])
# If the read F-file contains multiple lines it's an F field!
else:
print("You can't pass a field to register!!!")
exit()
else:
PhiInit = None
if args.INTERPOLATION_ORDER == 1:
# Override interpolator to save memory
interpolator = 'C'
else:
interpolator = 'python'
regReturns = spam.DIC.correlate.registerMultiscale(im1,
im2,
args.BIN_BEGIN, binStop=args.BIN_END,
margin=args.MARGIN,
PhiRigid=args.RIGID,
im1mask=im1mask,
interpolationOrder=args.INTERPOLATION_ORDER,
maxIterations=args.MAX_ITERATIONS,
deltaPhiMin=args.MIN_DELTA_PHI,
updateGradient=args.UPDATE_GRADIENT,
interpolator=interpolator,
verbose=True,
imShowProgress=args.GRAPH)
if regReturns['returnStatus'] == 2:
print("\n\nRegistration converged, great... saving")
if regReturns['returnStatus'] == 1:
print("\n\nRegistration hit max iterations, OK... saving")
if regReturns['returnStatus'] > 0 and args.DEF:
tifffile.imsave(args.OUT_DIR+"/"+os.path.splitext(os.path.basename(args.im1.name))[0]+'-reg-def.tif', spam.DIC.applyPhi(im1, Phi=regReturns['Phi']))
if regReturns['returnStatus'] < 0:
print("\n\nWe're saving this registration but we don't trust it at all")
spam.helpers.writeRegistrationTSV(args.OUT_DIR+"/"+args.PREFIX+".tsv", (numpy.array(im1.shape )-1)/2.0, regReturns)
......@@ -145,6 +145,7 @@ TTK_modules_pb = ["mesh", "label", "filters", "measurements", "kalisphera", "DIC
### also add it to the list in docs/source/scripts.rst
###############################################################
scripts = ['scripts/spam-mmr',
'scripts/spam-reg',
'scripts/spam-gdic',
"scripts/spam-ddic",
"scripts/spam-ldic",
......
......@@ -43,7 +43,7 @@ def ldicParser(parser):
parser.add_argument('inFiles',
nargs='+',
type=argparse.FileType('r'),
help="A space-separated list of two 3D greyscale tiff files to correlate, in order")
help="A space-separated list of two or more 3D greyscale tiff files to correlate, in order")
parser.add_argument('-mf1',
'--maskFile1',
......@@ -215,7 +215,7 @@ def ldicParser(parser):
help="Maximum iterations for grid-point registration. Default = 50")
parser.add_argument('-gpp',
'--grid-point-min-phi-change',
'--grid-point-min-delta-phi',
type=numpy.float,
default=0.001,
dest='GRID_POINT_MIN_PHI_CHANGE',
......@@ -597,8 +597,8 @@ def ddicParser(parser):
dest='LABEL_CORRELATE_MAX_ITERATIONS',
help="Maximum iterations for label correlation. Default = 50")
parser.add_argument('-lcp',
'--label-correlate-min-phi-change',
parser.add_argument('-lcdp',
'--label-correlate-min-delta-phi',
type=numpy.float,
default=0.001,
dest='LABEL_CORRELATE_MIN_PHI_CHANGE',
......@@ -1513,7 +1513,6 @@ def eregDiscreteParser(parser):
return args
def moveLabelsParser(parser):
parser.add_argument('LabFile',
metavar='LabFile',
......@@ -1919,3 +1918,154 @@ def deformImageFromFieldParser(parser):
return args
def register(parser):
parser.add_argument('im1',
metavar='im1',
type=argparse.FileType('r'),
help="Greyscale image of reference state for correlation")
parser.add_argument('im2',
metavar='im2',
type=argparse.FileType('r'),
help="Greyscale image of deformed state for correlation")
parser.add_argument('-mf1',
'--maskFile1',
dest='MASK1',
default=None,
type=argparse.FileType('r'),
help="Path to tiff file containing the mask of image 1 -- masks zones not to correlate, which should be == 0")
parser.add_argument('-pf',
'-phiFile',
dest='PHIFILE',
default=None,
type=argparse.FileType('r'),
help="Path to TSV file containing the deformation function field (required)")
parser.add_argument('-pfb',
'--phiFile-bin-ratio',
type=int,
default=1,
dest='PHIFILE_BIN_RATIO',
help="Ratio of binning level between loaded Phi file and current calculation. If the input Phi file has been obtained on a 500x500x500 image and now the calculation is on 1000x1000x1000, this should be 2. Default = 1")
parser.add_argument('-rig',
'--rigid',
action="store_true",
dest='RIGID',
help='Only do a rigid registration (i.e., displacements and rotations)?')
parser.add_argument('-bb',
'--binning-begin',
type=int,
default=4,
dest='BIN_BEGIN',
help='Initial binning to apply to input images for initial registration. Default = 4')
parser.add_argument('-be',
'--binning-end',
type=int,
default=1,
dest='BIN_END',
help='Binning level to stop at for initial registration. Default = 1')
parser.add_argument('-m',
'-mar',
'--margin',
type=float,
default=0.1,
dest='MARGIN',
help='Interpolation margin in proportions of image size. Default = 0.1, which means 0.1 * image size from both sides in all directions')
parser.add_argument('-m3',
'-mar3',
'--margin3',
nargs=3,
type=int,
default=None,
dest='MARGIN',
help="Interpolation margin in pixels. Default = 0.1 * image size from both sides in all directions")
parser.add_argument('-ug',
'--update-gradient',
action="store_true",
dest='UPDATE_GRADIENT',
help='Update gradient during newton iterations? More computation time but more robust and possibly fewer iterations. Default = False')
parser.add_argument('-it',
'--max-iterations',
type=int,
default=50,
dest='MAX_ITERATIONS',
help="Maximum number of iterations. Default = 50")
parser.add_argument('-dp',
'--min-delta-phi',
type=numpy.float,
default=0.0001,
dest='MIN_DELTA_PHI',
help="Minimum delta Phi for convergence. Default = 0.0001")
parser.add_argument('-o',
'--interpolation-order',
type=int,
default=1,
dest='INTERPOLATION_ORDER',
help="Interpolation order for image interpolation. Default = 1")
parser.add_argument('-g',
'--graph',
action="store_true",
default=False,
dest='GRAPH',
help="Activate graphical mode to look at iterations")
parser.add_argument('-od',
'--out-dir',
type=str,
default=None,
dest='OUT_DIR',
help="Output directory, default is the dirname of gmsh file")
parser.add_argument('-pre',
'--prefix',
type=str,
default=None,
dest='PREFIX',
help='Prefix for output files (without extension). Default is basename of mesh file')
parser.add_argument('-def',
'--save-deformed-image1',
action="store_true",
default=False,
dest='DEF',
help="Activate the saving of a deformed image 1 (as <im1>-reg-def.tif)")
args = parser.parse_args()
# If we have no out dir specified, deliver on our default promise -- this can't be done inline before since parser.parse_args() has not been run at that stage.
if args.OUT_DIR is None:
args.OUT_DIR = os.path.dirname(args.im1.name)
# However if we have no dir, notice this and make it the current directory.
if args.OUT_DIR == "":
args.OUT_DIR = "./"
else:
# Check existence of output directory
try:
if args.OUT_DIR:
os.makedirs(args.OUT_DIR)
else:
args.DIR_out = os.path.dirname(args.im1.name)
except OSError:
if not os.path.isdir(args.OUT_DIR):
raise
# Output file name prefix
if args.PREFIX is None:
args.PREFIX = os.path.splitext(os.path.basename(args.im1.name))[0] + "-" + os.path.splitext(os.path.basename(args.im2.name))[0] + "-registration"
return args
......@@ -954,13 +954,13 @@ class ereg(QWidget):
fileName = tmp if tmp.split(".")[-1] in ["tsv"] else tmp + ".tsv"
# save.writeRegistrationTSV(fileName, (numpy.array(self.images[1].shape) - 1) / 2.0, {
# 'PhiCentre': self.Phis[1], "returnStatus": 2, "iterations": self.iterations, "error": 100, "deltaPhiNorm": 0.1})
TSVheader = "Zpos\tYpos\tXpos\tFzz\tFzy\tFzx\tZdisp\tFyz\tFyy\tFyx\tYdisp\tFxz\tFxy\tFxx\tXdisp\tbin\treturnStatus"
TSVheader = "Zpos\tYpos\tXpos\tFzz\tFzy\tFzx\tZdisp\tFyz\tFyy\tFyx\tYdisp\tFxz\tFxy\tFxx\tXdisp\tbin\treturnStatus\tdeltaPhiNorm\terror\titerations"
centre = (numpy.array(self.images[0].shape)-1)/2.0
output = numpy.array([[centre[0]], [centre[1]], [centre[2]],
[self.Phis[1][0, 0]], [self.Phis[1][0, 1]], [self.Phis[1][0, 2]], [self.Phis[1][0, 3]],
[self.Phis[1][1, 0]], [self.Phis[1][1, 1]], [self.Phis[1][1, 2]], [self.Phis[1][1, 3]],
[self.Phis[1][2, 0]], [self.Phis[1][2, 1]], [self.Phis[1][2, 2]], [self.Phis[1][2, 3]],
[self.binning], [0]])
[self.binning], [0], [1.0], [self.images[0].mean()], [0] ])
numpy.savetxt(fileName, output.T, fmt='%.7f', delimiter='\t', newline='\n', comments='', header=TSVheader)
self.resultLabel.setText("Phi saved in: {}".format(os.path.join(os.getcwd(), fileName)))
self.resultLabel.setStyleSheet("QLabel {font-weight: bold; color: green;}")
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment