Skip to content

Commit

Permalink
[#46] handle colored images
Browse files Browse the repository at this point in the history
  • Loading branch information
jeaunrg committed Jun 27, 2021
1 parent 5932a14 commit ed05680
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 55 deletions.
10 changes: 5 additions & 5 deletions config/default.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"window_size": [
958,
1003
1920,
1013
],
"window_position": [
960,
0
-48,
39
],
"module_width": 250,
"space_between_modules": [
Expand All @@ -32,7 +32,7 @@
"style": "Default",
"theme": "bright",
"filenames": [
"C:\\Users\\jean\\Desktop\\francis\\resources\\data\\out\\# not saved"
"C:/Users/jean/Desktop/francis/resources/data/out\\graph_27062021 15h22m54.iag"
],
"current_tab": 0
}
File renamed without changes
Binary file added resources/data/lena_colored.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/data/lena_gray.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 10 additions & 3 deletions src/model/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def load(self, path):
elif ext == '.nii' or path.endswith('.nii.gz'):
data = nib.load(path).get_fdata()
elif ext in ['.png', '.jpg']:
data = imageio.imread(path, as_gray=True)
data = imageio.imread(path)
else:
raise TypeError("{} not handle yet".format(ext))
return data
Expand Down Expand Up @@ -71,15 +71,22 @@ def save(self, data, path):
ni_img = nib.Nifti1Image(data, None)
nib.save(ni_img, path)
elif ext in ['.png', '.jpg']:
# 3D image can be saved as a list of 2D images in a directory
if len(data.shape) == 3:
data = np.squeeze(data)
if data.ndim == 3 and np.min(data.shape) < 5:
# save 3d image as rgb or rgba image if possible
# (smaller dimension send to the end)
data = np.rollaxis(data, np.argmin(data.shape), data.ndim)
elif data.ndim > 2:
# 3D image can be saved as a list of 2D images in a directory
# work for ndimage recursively
if not os.path.exists(root):
os.makedirs(root)
head, tail = os.path.split(root)
for i in range(data.shape[0]):
new_path = os.path.join(root, tail+str(i)+ext)
self.save(data[i], new_path)
return "images are saved in directory {}".format(root)

imageio.imwrite(path, data)
return "saved as {}".format(path)

Expand Down
14 changes: 7 additions & 7 deletions src/presenter/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def browse_path(self, module):
module.parameters.path.setToolTip(filename)

# ----------------------------- MODEL CALL --------------------------------#
@utils.manager(1)
@utils.manager(2)
def call_save(self, module):
"""
save the parent image as nifti file at specified path
Expand All @@ -237,7 +237,7 @@ def call_save(self, module):
"path": module.parameters.path.text()}
return function, args

@utils.manager(1)
@utils.manager(2)
def call_load(self, module):
"""
load any type of data
Expand All @@ -246,7 +246,7 @@ def call_load(self, module):
args = {"path": module.parameters.path.text()}
return function, args

@utils.manager(1)
@utils.manager(2)
def call_get_img_infos(self, module):
"""
get image info
Expand All @@ -258,7 +258,7 @@ def call_get_img_infos(self, module):
"info": module.parameters.infos.currentText()}
return function, args

@utils.manager(1)
@utils.manager(2)
def call_apply_threshold(self, module):
"""
compute 3d thresholding on the parent image
Expand All @@ -272,7 +272,7 @@ def call_apply_threshold(self, module):
"reverse": module.parameters.reversed.isChecked()}
return function, args

@utils.manager(1)
@utils.manager(2)
def call_apply_operation(self, module):
"""
compute operations between multiple images
Expand All @@ -287,7 +287,7 @@ def call_apply_operation(self, module):
"operation": utils.get_checked(module.parameters, ['add', 'multiply', 'subtract', 'divide'])}
return function, args

@utils.manager(1)
@utils.manager(2)
def call_apply_simple_operation(self, module):
"""
compute simple operations between an image and a float
Expand All @@ -300,7 +300,7 @@ def call_apply_simple_operation(self, module):
"operation": utils.get_checked(module.parameters, ['add', 'multiply', 'subtract', 'divide'])}
return function, args

@utils.manager(1)
@utils.manager(2)
def call_apply_basic_morpho(self, module):
"""
compute 3d morphological operation on the parent image
Expand Down
18 changes: 12 additions & 6 deletions src/view/graph_bricks.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,22 +405,28 @@ def snapMousePressEvent(self, event):
# set ratio between image and qpixmap
im = self.graph.resultStack.get(self.name)
if im is not None:
if len(im.shape) == 2:
ratio = im.shape[1] / self.result.width()
else:
if self.result.slicable:
ratio = im.shape[int(self.result.axis == 0)] / self.result.width()
else:
ratio = im.shape[1] / self.result.width()

# get click position
click_pos = np.array([event.pos().y(), event.pos().x()])
# define position in image
true_pos = np.rint(click_pos * ratio).astype(int)
try:
if len(im.shape) == 2:
if im.ndim == 2:
x, y, z = *true_pos, ''
value = im[x, y]
self.rightfoot.setText("%d " % im[x, y])
else:
elif self.result.slicable:
x, y, z = np.insert(true_pos, self.result.axis, self.result.currentSlice)
self.rightfoot.setText("%d " % im[x, y, z])
value = im[x, y, z]
else:
x, y, z = *true_pos, ''
value = "(" + " ".join(im[x, y].astype(str)) + ")"
self.leftfoot.setText("{0} {1} {2}".format(x, y, z))
self.rightfoot.setText(str(value))
except IndexError as e:
# click outside image
print(e)
Expand Down
84 changes: 50 additions & 34 deletions src/view/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,9 @@ class QImageRenderer(QtWidgets.QLabel):
def __init__(self, img, parent):
QtWidgets.QWidget.__init__(self)
self.img = self.formatImage(img)
self.dimension = len(self.img.shape)
if self.dimension == 3:
self.axis = 0
self.currentSlice = None

self.getImageType()

self.pixmap = None
self._parent = parent
self.updateSnap()
Expand All @@ -216,7 +215,7 @@ def formatImage(self, img):
return img

def wheelEvent(self, event):
if self.dimension != 3:
if not self.slicable:
return
if self.currentSlice is not None:
step = 1
Expand All @@ -231,7 +230,7 @@ def mouseDoubleClickEvent(self, event):
"""
update image axis on double click above image view
"""
if self.dimension != 3:
if not self.slicable:
return
if self.axis == 2:
self.axis = 0
Expand All @@ -240,37 +239,54 @@ def mouseDoubleClickEvent(self, event):
self.updateSnap()
self.syncSignal.emit()

def getImageType(self):
self.slicable = False
self.imgType = QtGui.QImage.Format_Grayscale8
if self.img.ndim == 3:
if self.img.shape[-1] == 3:
self.imgType = QtGui.QImage.Format_RGB888
elif self.img.shape[-1] == 4:
self.imgType = QtGui.QImage.Format_RGBA8888
else:
self.slicable = True

if self.slicable:
self.axis = 0
self.currentSlice = None

def getSliceParams(self):
if self.dimension == 2:
return self.img, self.img.shape[1], self.img.shape[0]
elif self.dimension == 3:
s = self.img.shape[self.axis]

# set current slice
if self.currentSlice is None:
self.currentSlice = int(s / 2)
elif self.currentSlice < 0:
self.currentSlice = 0
elif self.currentSlice >= s:
self.currentSlice = s-1

# snap axis slice
if self.axis == 0:
im_slice = self.img[self.currentSlice].copy()
_, h, w = self.img.shape
elif self.axis == 1:
im_slice = self.img[:, self.currentSlice].copy()
h, _, w = self.img.shape
elif self.axis == 2:
im_slice = self.img[:, :, self.currentSlice].copy()
h, w, _ = self.img.shape

return im_slice, w, h
if self.img.ndim == 2:
return self.img, self.img.shape[1], self.img.shape[0], self.img.shape[1]
elif self.img.ndim == 3:
if not self.slicable:
return self.img, self.img.shape[1], self.img.shape[0], self.img.shape[1] * self.img.shape[2]
else:
s = self.img.shape[self.axis]

# set current slice
if self.currentSlice is None:
self.currentSlice = int(s / 2)
elif self.currentSlice < 0:
self.currentSlice = 0
elif self.currentSlice >= s:
self.currentSlice = s-1

# snap axis slice
if self.axis == 0:
im_slice = self.img[self.currentSlice].copy()
_, h, w = self.img.shape
elif self.axis == 1:
im_slice = self.img[:, self.currentSlice].copy()
h, _, w = self.img.shape
elif self.axis == 2:
im_slice = self.img[:, :, self.currentSlice].copy()
h, w, _ = self.img.shape

return im_slice, w, h, w

def updateSnap(self):
im, w, h = self.getSliceParams()
qim = QtGui.QImage(im, w, h, w, QtGui.QImage.Format_Indexed8)
qim.setColorTable([QtGui.qRgba(255, 0, 0, 255)]+[QtGui.qRgba(i, i, i, 255) for i in range(1, 256)])
im, w, h, bytesPerLine = self.getSliceParams()
qim = QtGui.QImage(im, w, h, bytesPerLine, self.imgType)
self.pixmap = QtGui.QPixmap(qim)
self.pixmap = self.pixmap.scaledToWidth(self._parent.width() - 2,
QtCore.Qt.FastTransformation)
Expand Down

0 comments on commit ed05680

Please sign in to comment.