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

1""" 

2Library of SPAM image correlation functions. 

3Copyright (C) 2020 SPAM Contributors 

4 

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. 

9 

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. 

14 

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""" 

18 

19import numpy 

20 

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 

24 

25 

26def _errorCalc(im1, im2): 

27 return numpy.nansum(numpy.square(numpy.subtract(im1, im2))) / numpy.nansum(im1) 

28 

29 

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. 

35 

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. 

38 

39 Values of NCC > 0.99 can generally be trusted. 

40 

41 Parameters 

42 ---------- 

43 imagette1 : 3D numpy array of floats 

44 Imagette 1 is the smaller reference image 

45 

46 imagette2 : 3D numpy array of floats 

47 Imagette 2 is the bigger image inside which to search 

48 

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 

53 

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 

58 

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 

63 

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 

68 

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" 

80 

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 

89 

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 

98 

99 # Run the actual pixel search 

100 returns = numpy.zeros(4, dtype="<f4") 

101 pixelSearchCPP(imagette1.astype("<f4"), imagette2.astype("<f4"), returns) 

102 

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 

113 

114 else: 

115 return numpy.array(returns[0:3]), returns[3]