Skip to content

Commit ca55ca3

Browse files
author
Michael Hughes
committed
Mosaic bug fix
1 parent ca5be2e commit ca55ca3

File tree

6 files changed

+121
-58
lines changed

6 files changed

+121
-58
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
66

77
[project]
88
name = "PyFibreBundle"
9-
version = "1.3.4"
9+
version = "1.3.5"
1010
description = "Image processing of images acquired through fibre imaging bundle, including core removal, mosaicing and super-resolution.."
1111
readme = "README.md"
1212
authors = [{ name = "Michael Hughes", email = "m.r.hughes@kent.ac.uk" }]

src/pybundle/core_interpolation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ def recon_tri_interp(img, calib, **kwargs):
413413
# Triangular linear interpolation
414414
if numba and numbaAvailable:
415415
if calib.mask is not None:
416-
maskNumba = np.squeeze(np.reshape(calib.mask, (np.product(np.shape(calib.mask)),1)))
416+
maskNumba = np.squeeze(np.reshape(calib.mask, (np.prod(np.shape(calib.mask)),1)))
417417
else:
418418
maskNumba = None
419419
pixelVal = grid_data_numba(calib.baryCoords, cVals, calib.coreIdx, calib.mapping, maskNumba)

src/pybundle/mosaic.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ def __init__(self, mosaicSize, **kwargs):
107107
self.resetSharpness = kwargs.get('resetSharpness', None)
108108

109109
# These are created the first time they are needed
110-
self.mosaic = []
111-
self.mask = []
112-
self.blendMask = []
110+
self.mosaic = None
111+
self.mask = None
112+
self.blendMask = None
113113

114114
# Initial values
115115
self.lastShift = [0,0]
@@ -266,7 +266,7 @@ def __initialise_mosaic(self, img):
266266
if self.imageType is None:
267267
self.imageType = img.dtype
268268

269-
if np.size(self.mask) == 0:
269+
if self.mask is None:
270270
self.mask = pybundle.get_mask(np.zeros([self.imSize,self.imSize]),(self.imSize/2,self.imSize/2,self.cropSize / 2))
271271

272272
if self.col:
@@ -302,6 +302,7 @@ def __insert_into_mosaic(mosaic, img, mask, position):
302302

303303
oldRegion = mosaic[px:px + np.shape(img)[0] , py :py + np.shape(img)[1]]
304304

305+
305306
oldRegion[np.array(mask)] = img[np.array(mask)]
306307
mosaic[px:px + np.shape(img)[0] , py :py + np.shape(img)[1]] = oldRegion
307308

@@ -318,7 +319,7 @@ def __insert_into_mosaic_blended(mosaic, img, mask, blendMask, cropSize, blendDi
318319
img : img to insert, 2D/3D numpy array
319320
mask : 2D numpy array with values of 1 for pixels to be copied
320321
and 0 for pixels not to be copied. Must be same size as img.
321-
blendMask : the cosine window blending mask with weighted pixel values. If passed empty []
322+
blendMask : the cosine window blending mask with weighted pixel values. If None
322323
this will be created
323324
cropSize : size of input image.
324325
blendDist : number which controls the sptial extent of the blending
@@ -342,7 +343,7 @@ def __insert_into_mosaic_blended(mosaic, img, mask, blendMask, cropSize, blendDi
342343
blendingMask = np.max(blendingMask,2)
343344

344345
# If first time, create blend mask giving weights to apply for each pixel
345-
if blendMask == []:
346+
if blendMask is None:
346347
maskRad = cropSize / 2
347348
blendImageMask = Mosaic.__cosine_window(np.shape(oldRegion)[0], maskRad, blendDist)
348349

src/pybundle/pybundle.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import numpy as np
1515
import math
1616
import time
17+
import pickle
1718

1819
import cv2 as cv
1920
import pybundle
@@ -260,8 +261,6 @@ def __process_trilin(self, img):
260261
if self.srUseLut:
261262
if self.srCalibrationLUT is not None and self.srParamValue is not None:
262263
calibSR = self.srCalibrationLUT.calibrationSR(self.srParamValue)
263-
print("Taken calibration from LUT")
264-
print(calibSR)
265264
else:
266265
return None
267266
elif self.calibrationSR is not None:
@@ -787,7 +786,6 @@ def calibrate_sr(self):
787786
set of super-res shift images, coreSize and gridSize must have been
788787
set prior to calling this.
789788
"""
790-
791789
if self.srCalibImages is not None or self.srShifts is not None:
792790
self.calibrationSR = pybundle.SuperRes.calib_multi_tri_interp(
793791
self.calibImage, self.srCalibImages,
@@ -804,6 +802,23 @@ def calibrate_sr(self):
804802
darkFrame = self.srDarkFrame,
805803
filterSize = self.filterSize)
806804

805+
def save_calibration(self, filename):
806+
807+
if self.calibration is not None:
808+
with open(filename, 'wb') as pickleFile:
809+
pickle.dump(self.calibration, pickleFile)
810+
811+
def save_sr_calibration(self, filename):
812+
if self.calibrationSR is not None:
813+
with open(filename, 'wb') as pickleFile:
814+
pickle.dump(self.calibration, pickleFile)
815+
816+
817+
def load_calibration(self, filename):
818+
819+
with open(filename, 'rb') as pickleFile:
820+
self.calibration = pickle.load(pickleFile)
821+
807822

808823
def get_pixel_scale(self):
809824
""" Returns the scaling factor between the pixel size in the raw image

src/pybundle/super_res.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ def recon_multi_tri_interp(imgs, calib, numba = True):
294294
# Triangular linear interpolation
295295
if numba and numbaAvailable:
296296
if calib.mask is not None:
297-
maskNumba = np.squeeze(np.reshape(calib.mask, (np.product(np.shape(calib.mask)),1)))
297+
maskNumba = np.squeeze(np.reshape(calib.mask, (np.prod(np.shape(calib.mask)),1)))
298298
else:
299299
maskNumba = None
300300
pixelVal = pybundle.grid_data_numba(calib.baryCoords, cVals, calib.coreIdx, calib.mapping, maskNumba)

src/pybundle/utility.py

Lines changed: 93 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ def extract_central(img, boxSize = None):
2929
3030
Keyword Arguments:
3131
boxSize : size of cropping square, default is largest possible
32+
33+
Returns:
34+
ndarray, cropped image
3235
"""
3336

34-
3537
w = np.shape(img)[0]
3638
h = np.shape(img)[1]
3739

@@ -46,71 +48,74 @@ def extract_central(img, boxSize = None):
4648
return imgOut
4749

4850

49-
def to8bit(img, **kwargs):
51+
def to8bit(img, minVal = None, maxVal = None):
5052
""" Returns an 8 bit representation of image. If min and max are specified,
5153
these pixel values in the original image are mapped to 0 and 255
5254
respectively, otherwise the smallest and largest values in the
5355
whole image are mapped to 0 and 255, respectively.
5456
5557
Arguments:
56-
img : input image as 2D numpy array
58+
img : ndarray
59+
input image as 2D numpy array
5760
5861
Keyword Arguments:
59-
minVal : optional, pixel value to scale to 0
60-
maxVal : optional, pixel value to scale to 255
62+
minVal : float
63+
optional, pixel value to scale to 0
64+
maxVal : float
65+
optional, pixel value to scale to 255
6166
"""
62-
minV = kwargs.get("minVal", None)
63-
maxV = kwargs.get("maxVal", None)
64-
65-
67+
6668
img = img.astype('float64')
6769

68-
if minV is None:
69-
minV = np.min(img)
70+
if minVal is None:
71+
minVal = np.min(img)
7072

71-
img = img - minV
73+
img = img - minVal
7274

73-
if maxV is None:
74-
maxV = np.max(img)
75+
if maxVal is None:
76+
maxVal = np.max(img)
7577
else:
76-
maxV = maxV - minV
78+
maxVal = maxVal - minVal
7779

78-
img = img / maxV * 255
80+
img = img / maxVal * 255
7981
img = img.astype('uint8')
8082

8183
return img
8284

8385

84-
def to16bit(img, **kwargs):
86+
def to16bit(img, minVal = None, maxVal = None):
8587
""" Returns an 16 bit representation of image. If min and max are specified,
8688
these pixel values in the original image are mapped to 0 and 2^16
8789
respectively, otherwise the smallest and largest values in the
8890
whole image are mapped to 0 and 2^16 - 1, respectively.
8991
9092
Arguments:
91-
img : input image as 2D numpy array
93+
img : ndarray
94+
input image as 2D numpy array
9295
9396
Keyword Arguments:
94-
minVal : optional, pixel value to scale to 0
95-
maxVal : optional, pixel value to scale to 2^16 - 1
96-
"""
97-
minV = kwargs.get("minVal", None)
98-
maxV = kwargs.get("maxVal", None)
99-
97+
minVal : float
98+
optional, pixel value to scale to 0
99+
maxVal : float
100+
optional, pixel value to scale to 2^16 - 1
101+
102+
Returns:
103+
ndarray, 16 bit image
104+
"""
100105

101106
img = img.astype('float64')
102107

103-
if minV is None:
104-
minV = np.min(img)
108+
if minVal is None:
109+
minVal = np.min(img)
105110

106-
img = img - minV
111+
img = img - minVal
107112

108-
if maxV is None:
109-
maxV = np.max(img)
113+
if maxVal is None:
114+
maxVal = np.max(img)
110115
else:
111-
maxV = maxV - minV
116+
maxVal = maxVal - minVal
112117

113-
img = img / maxV * (2^16 - 1)
118+
img = img / maxVal * (2^16 - 1)
114119
img = img.astype('uint16')
115120

116121
return img
@@ -123,9 +128,14 @@ def radial_profile(img, centre):
123128
Returns radial profile as 1D numpy array
124129
125130
Arguments:
126-
img : input image as 2D numpy array
127-
centre : centre point for radial profile, tuple of (x,y)
131+
img : ndarray
132+
input image as 2D numpy array
133+
centre : (int, int)
134+
centre point for radial profile, tuple of (x,y)
135+
Returns:
136+
ndarray, 1D profile
128137
"""
138+
129139
y, x = np.indices((img.shape))
130140
r = np.sqrt((x - centre[1])**2 + (y - centre[0])**2)
131141
r = r.astype(int)
@@ -140,18 +150,30 @@ def radial_profile(img, centre):
140150

141151

142152
def save_image8(img, filename):
143-
""" Saves image as 8 bit tif without scaling"""
153+
""" Saves image as 8 bit tif without scaling.
154+
155+
Arguments:
156+
img : ndarray,
157+
input image as 2D numpy array
158+
159+
filename : str
160+
path to save to, folder must exist
161+
"""
162+
144163
im = Image.fromarray(img.astype('uint8'))
145164
im.save(filename)
146165

147166

148167

149168
def save_image16(img, filename):
150169
""" Saves image as 16 bit tif without scaling.
151-
170+
152171
Arguments:
153-
img: image as 2D/3D numpy array
154-
filname : str, path to file. Folder must exist.
172+
img : ndarray,
173+
input image as 2D numpy array
174+
175+
filename : str
176+
path to save to, folder must exist
155177
"""
156178
im = Image.fromarray(img.astype('uint16'))
157179
im.save(filename)
@@ -160,10 +182,13 @@ def save_image16(img, filename):
160182

161183
def save_image8_scaled(img, filename):
162184
""" Saves image as 8 bit tif with scaling to use full dynamic range.
163-
185+
164186
Arguments:
165-
img: image as 2D/3D numpy array
166-
filname : str, path to file. Folder must exist.
187+
img : ndarray,
188+
input image as 2D numpy array
189+
190+
filename : str
191+
path to save to, folder must exist
167192
"""
168193

169194
im = Image.fromarray(to8bit(img))
@@ -172,12 +197,15 @@ def save_image8_scaled(img, filename):
172197

173198
def save_image16_scaled(img, filename):
174199
""" Saves image as 16 bit tif with scaling to use full dynamic range.
175-
200+
176201
Arguments:
177-
img: image as 2D/3D numpy array
178-
filname : str, path to file. Folder must exist.
202+
img : ndarray,
203+
input image as 2D numpy array
204+
205+
filename : str
206+
path to save to, folder must exist
179207
"""
180-
208+
181209
im = Image.fromarray(to16bit(img)[0])
182210
im.save(filename)
183211

@@ -188,7 +216,11 @@ def average_channels(img):
188216
189217
190218
Arguments:
191-
img: image as 2D/3D numpy array
219+
img: ndarray
220+
image as 2D/3D numpy array
221+
222+
Returns:
223+
ndarray, averaged image
192224
"""
193225

194226
if img.ndim == 3:
@@ -203,16 +235,31 @@ def max_channels(img):
203235
204236
205237
Arguments:
206-
img: image as 2D/3D numpy array
238+
img: ndarray
239+
image as 2D/3D numpy array
240+
241+
Returns:
242+
ndarray, max value image
207243
"""
208244

209245
if img.ndim == 3:
210246
return np.max(img, 2)
211247
else:
212248
return img
213249

250+
214251
def resample(img, factor):
252+
""" Resizes an image by a factor.
215253
254+
Arguments:
255+
img : ndarray
256+
image as 2D numpy array
257+
factor : float,
258+
resize factor
259+
260+
Returns:
261+
ndarray, resmaple images
262+
"""
216263
h,w = np.shape(img)
217264
img = cv.resize(img, ( int(w * factor), int(h * factor)))
218265

0 commit comments

Comments
 (0)