-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunctions.py
279 lines (217 loc) · 6.82 KB
/
functions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
import tifffile as tiff
import numpy as np
import os
import fnmatch
import matplotlib.pyplot as plt
import scipy.ndimage as simg
import skimage as ski
# TODOs :
# this code consideres that the input images are 8-bits, but it would be more convenient to have a function that checks that.
def createNewDirectory(directory: str, newFileName: str):
"""
Create new folder.
Returns the path of the new folder.
"""
newDir = directory+"/"+newFileName
if not os.path.exists(newDir):
os.makedirs(newDir)
return newDir
def listNameOfFiles(directory: str, extension="tif") -> list:
"""
Fetch files name.
Does not consider .DS_Store files.
Returns a list of the names of the files.
"""
foundFiles = []
for file in os.listdir(directory):
if fnmatch.fnmatch(file, f'*.{extension}'):
if file == ".DS_Store":
pass
else:
foundFiles.append(file)
foundFiles.sort()
return foundFiles
def read_file(file_path):
"""
Reads the .tif file and convert them in a np.array.
Returns the file as a np.array.
"""
image_array = tiff.imread(file_path)
return image_array
def fix_polygon(image, firstLinePosition):
"""
Replaces the black horizontal lines by the average of the value of the pixel
before and after the pixel in the line.
First value in range is the position of the first black line from the top of the image.
Returns the image as a np.array without the black horizontal line.
"""
for i in range(firstLinePosition, 511, 36):
image[i] = image[i+1]/2 + image[i-1]/2
firstLinePosition = firstLinePosition + 8 - 36
if firstLinePosition < 0:
firstLinePosition += 36
for i in range(firstLinePosition, 511, 36):
image[i] = image[i+1]/2 + image[i-1]/2
return image
def deleteRowInImage(image, rowsToDelete):
"""
Delete rows in a numpy array according to the number of rows set with rowsToBeDeleted.
Returns the new numpy array without the rows.
"""
x = 0
while x < rowsToDelete:
image = np.delete(image, 0, 0)
x += 1
return image
def sumPixels(directory:str, filesName):
"""
Reads all images in directory and sums the value of each pixels.
Returns an image with the sum of all pixels.
"""
firstPath = directory + "/" + filesName[0]
firstImage = read_file(file_path=firstPath)
pixels = np.zeros(shape=(firstImage.shape[0], firstImage.shape[1]), dtype=np.float64)
for name in filesName:
filePath = directory + "/" + name
image = read_file(file_path=filePath)
x = 0
y = 0
while x < firstImage.shape[0]:
while y < firstImage.shape[1]:
pixels[x][y] = pixels[x][y] + image[x][y]
y += 1
y = 0
x += 1
return pixels
def normalizeImage(image):
"""
Creates an image with pixels in float 64 varying form 0 to 1 according to the intensity of each pixels from the input image.
"""
newImage = np.zeros(shape=(image.shape[0], image.shape[1]))
maxPixel = np.amax(image)
x = 0
y = 0
while x < image.shape[0]:
while y < image.shape[1]:
newImage[x][y] = image[x][y]/maxPixel
y += 1
y = 0
x += 1
return newImage
def rescaleImage(image, pixelRange=255):
"""
Normalizes the image with the function normalizeImage.
Rescales the image on the range defined with the variable pixelRange.
"""
normImage = normalizeImage(image=image)
rescaledImage = np.zeros(shape=(image.shape[0], image.shape[1]))
x = 0
y = 0
while x < image.shape[0]:
while y < image.shape[1]:
rescaledImage[x][y] = normImage[x][y] * pixelRange
y += 1
y = 0
x += 1
return rescaledImage
def inversePixels(image):
"""
Takes the input image and inverses the pixels (0s become 1s and 1s become 0s).
"""
inverseImage = np.zeros(shape=(image.shape[0], image.shape[1]))
maxPixel = np.amax(image)
x = 0
y = 0
while x < image.shape[0]:
while y < image.shape[1]:
inverseImage[x][y] = maxPixel - image[x][y]
y += 1
y = 0
x +=1
return inverseImage
def createAverageImage(directory: str, filesName):
"""
With the image directory, averages them all to produce a final image for correction.
Returns the resultant average image.
"""
pixels = sumPixels(directory=directory, filesName=filesName)
numberOfImages = len(filesName)
x = 0
y = 0
while x < pixels.shape[0]:
while y < pixels.shape[1]:
pixels[x][y] = pixels[x][y]/numberOfImages
y += 1
y = 0
x += 1
return pixels
def averageTwoListsElementWise(list1, list2):
"""
Input two lists and each element are going to be averaged together.
If list1 = (1,2,3) and list2 = (3,4,5), then this function returns [2.0, 3.0, 4.0].
"""
newList = list(zip(list1, list2))
meanList = []
for i in newList:
meanList.append(sum(i) / len(i))
return meanList
def averageRowsOfTwoImages(image1, image2, row1, row2):
"""
This function takes two .tif images and average each element according to their row number.
If row1 and row2 = 0, the first row of each image are averaged together, element by element.
The average finishes when the row of image 1 does not exist anymore.
"""
while row1 < image1.shape[0]:
image1[row1] = averageTwoListsElementWise(list1=image1[row1], list2=image2[row2])
row1 += 1
row2 += 1
return image1
def createIntensityCorrectionImage(image):
"""
From an average image of all images in a set, generates the intensity correction image that should be applied on individual images.
Applies a gaussian blur on the correction image to smoothen the stuff.
Returns the intensity correction image with values between 0 and 1.
"""
inverseImage = inversePixels(image=image)
rescaledImage = rescaleImage(image=inverseImage)
correction = simg.gaussian_filter(rescaledImage, sigma=10, mode="nearest")
return correction
def adjustIntensity(image, correction):
"""
Takes an image and multiplies each pixels by the correcponding pixel in the correction image.
Returns the image corrected in intensity.
"""
image = image.astype(np.float64)
x = 0
y = 0
while x < image.shape[0]:
while y < image.shape[1]:
image[x][y] = image[x][y] * correction[x][y]
y += 1
y = 0
x += 1
new8bitImage = np.uint8(rescaleImage(image))
# adjust the background for better contrast. Here the background is defined as any pixel under 20.
x = 0
y = 0
while x < new8bitImage.shape[0]:
while y < new8bitImage.shape[1]:
if new8bitImage[x][y] < 20:
new8bitImage[x][y] = 0
y += 1
y = 0
x += 1
return new8bitImage
def stitchTwoImagesVertical(image1, image2, overlap):
"""
Averages the rows corresponding to the overlap of the two images and concatenate the rest of the images.
Stitching image 1 with the image 2 under it.
Returns the vertically stitched images.
"""
overlapedRows = int(512 * overlap / 100)
rowImage1 = image1.shape[0] - overlapedRows - 1
rowImage2 = 0
averageImage = averageRowsOfTwoImages(image1, image2, row1=rowImage1, row2=rowImage2)
del_image2 = deleteRowInImage(image=image2, rowsToDelete=overlapedRows)
stitchImage = np.concatenate((image1, del_image2), axis=0)
return stitchImage