Coverage for /usr/local/lib/python3.8/site-packages/spam/DIC/pixelSearch.py: 70%
20 statements
« prev ^ index » next coverage.py v7.2.3, created at 2023-11-22 13:26 +0000
« prev ^ index » next coverage.py v7.2.3, created at 2023-11-22 13:26 +0000
1"""
2Library of SPAM image correlation functions.
3Copyright (C) 2020 SPAM Contributors
5This program is free software: you can redistribute it and/or modify it
6under the terms of the GNU General Public License as published by the Free
7Software Foundation, either version 3 of the License, or (at your option)
8any later version.
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13more details.
15You should have received a copy of the GNU General Public License along with
16this program. If not, see <http://www.gnu.org/licenses/>.
17"""
19import numpy
21# 2017-05-29 ER and EA
22# This is spam's C++ DIC toolkit, but since we're in the tools/ directory we can import it directly
23from spam.DIC.DICToolkit import pixelSearch as pixelSearchCPP
26def _errorCalc(im1, im2):
27 return numpy.nansum(numpy.square(numpy.subtract(im1, im2))) / numpy.nansum(im1)
30def pixelSearch(
31 imagette1, imagette2, imagette1mask=None, imagette2mask=None, returnError=False
32):
33 """
34 This function performs a pixel-by-pixel search in 3D for a small reference imagette1 within a larger imagette2.
36 The normalised correlation coefficient (NCC) is computed for EVERY combination of the displacements of imagette1 defined within imagette2.
37 What is returned is the highest NCC value obtained and the position where it was obtained with respect to the origin in imagette2.
39 Values of NCC > 0.99 can generally be trusted.
41 Parameters
42 ----------
43 imagette1 : 3D numpy array of floats
44 Imagette 1 is the smaller reference image
46 imagette2 : 3D numpy array of floats
47 Imagette 2 is the bigger image inside which to search
49 imagette1mask : 3D numpy array of bools, optional
50 A mask for imagette1 to define which pixels to include in the correlation
51 (True = Correlate these pixels, False = Skip),
52 Default = no mask
54 imagette2mask : 3D numpy array of bools, optional
55 A mask for imagette2 to define which pixels to include in the correlation
56 (True = Correlate these pixels, False = Skip),
57 Default = no mask
59 returnError : bool, optional
60 Return a normalised sum of squared differences error compatible with
61 register() family of functions? If yes, it's the last returned variable
62 Default = False
64 Returns
65 -------
66 p : 3-component vector
67 Z, Y, X position with respect to origin in imagette2 of imagette1 to get best NCC
69 cc : float
70 Normalised correlation coefficient, ~0.5 is random, >0.99 is very good correlation.
71 """
72 # Note
73 # ----
74 # It important to remember that the C code runs A BIT faster in its current incarnation when it has
75 # a cut-out im2 to deal with (this is related to processor optimistaions).
76 # Cutting out imagette2 to just fit around the search range might save a bit of time
77 assert numpy.all(
78 imagette2.shape >= imagette1.shape
79 ), "spam.DIC.pixelSearch(): imagette2 should be bigger or equal to imagette1 in all dimensions"
81 if imagette1mask is not None:
82 assert (
83 imagette1.shape == imagette1mask.shape
84 ), "spam.DIC.pixelSearch: imagette1mask ({}) should have same size as imagette1 ({})".format(
85 imagette1mask.shape, imagette1.shape
86 )
87 imagette1 = imagette1.astype("<f4")
88 imagette1[imagette1mask == 0] = numpy.nan
90 if imagette2mask is not None:
91 assert (
92 imagette2.shape == imagette2mask.shape
93 ), "spam.DIC.pixelSearch: imagette2mask ({}) should have same size as imagette2 ({})".format(
94 imagette2mask.shape, imagette2.shape
95 )
96 imagette2 = imagette2.astype("<f4")
97 imagette2[imagette2mask == 0] = numpy.nan
99 # Run the actual pixel search
100 returns = numpy.zeros(4, dtype="<f4")
101 pixelSearchCPP(imagette1.astype("<f4"), imagette2.astype("<f4"), returns)
103 if returnError:
104 error = _errorCalc(
105 imagette1,
106 imagette2[
107 int(returns[0]) : int(returns[0]) + imagette1.shape[0],
108 int(returns[1]) : int(returns[1]) + imagette1.shape[1],
109 int(returns[2]) : int(returns[2]) + imagette1.shape[2],
110 ],
111 )
112 return numpy.array(returns[0:3]), returns[3], error
114 else:
115 return numpy.array(returns[0:3]), returns[3]