mpl-interactions icon indicating copy to clipboard operation
mpl-interactions copied to clipboard

image_segmenter: Enable saving of verts or path coordinates for a image_segmenter object

Open wgottwald opened this issue 3 years ago • 11 comments

Problem:

Paths of the ROIs are not returned by image_segmenter

Explanantion:

After segmenting an image, the .verts attributes are not saved. It would be good to access them later, not just the mask.

Proposed Solution

Add the verts and the paths of the drawn ROI as a property to an image_segmenter object. Similar to mask.

wgottwald avatar Mar 02 '23 09:03 wgottwald

One complication is how to deal with difference between erasing and drawing paths. Would probalby have to return something like

{"drawing": [path, path, path....], "erasing": [path, path, path]}

how's that sound?

ianhi avatar Mar 02 '23 15:03 ianhi

Yes thats probably an issue. But in the end the interesting output are just the coordinates of the final roi that one has drawn. The motivation here is that I can display that later onto the image I have drawn it on or any other image with the same dimensions for that matter.

wgottwald avatar Mar 02 '23 15:03 wgottwald

But in the end the interesting output are just the coordinates of the final roi that one has drawn.

So you basically want the outline of a mask? Can you take the mask you drawn and take it's outline using some skimage functions?

ianhi avatar Mar 02 '23 15:03 ianhi

Yes thats also a solution. I just thought if its an easy fix to include the path coordinates as a property that would be cleaner.

wgottwald avatar Mar 02 '23 15:03 wgottwald

Just to disambiguate: When you say path coordinates, do you mean the sort of sum of paths, or all the individual paths that were used to create the masks?

For example this is a valid mask to draw: image

but it's not obvious to me that there's a nice way to represent that with a single path

ianhi avatar Mar 02 '23 15:03 ianhi

I mean something like this: (where the red line is the path that has been extracted from the verts parameter)

Figure 1(4)

wgottwald avatar Mar 02 '23 16:03 wgottwald

I guess my thought is that that is really two different red lines. Also how did you generate the red line, programaticcaly from verts? If there is an easy way to combine the paths into one shape that I'm not aware of I'd be stoked to include that

ianhi avatar Mar 02 '23 18:03 ianhi

I thought about this a bit more and while there is a make_compount_path function that only works for purely additive paths, since this allows erasing I don't think there's a super easy way to combine them into one (or multiple paths.

based on your image i think what you want is contours which should be easy to create directly from the mask:

borrowing from this example I did this

fig, ax = plt.subplots()
contours = measure.find_contours(segmenter.mask)
ax.imshow(segmenter.mask)
for contour in contours:
    ax.plot(contour[:, 1], contour[:, 0], linewidth=2, color='r')
    

which gives this:

image

ianhi avatar Mar 02 '23 21:03 ianhi

I guess my thought is that that is really two different red lines. Also how did you generate the red line, programaticcaly from verts? If there is an easy way to combine the paths into one shape that I'm not aware of I'd be stoked to include that

I generated them like this (in a Jupyter-lab notebook):

import sys
from mpl_interactions import image_segmenter
import numpy as np
import matplotlib.pyplot as plt
%matplotlib widget
import ipywidgets as widgets
test_array = np.zeros((128,128,4))
bar = image_segmenter(test_array[:,:,2],nclasses=2)

Call that in a new cell to draw the ROI:

bar

Save the verts as a list in a new cell:

path_coords = bar.verts

Set erase to True in a new cell:

bar.erasing = True

Go back to cell that calls bar and execute that:

bar

Draw a erasing ROI on it and then save that into a new parameter in yet another cell:

eraser_coords = bar.verts

Plot the mask and the boundaries:

plt.close('all')
fig,ax=plt.subplots(1)
ax.imshow(bar.mask)

for n in range(len(path_coords)-1):
    ax.plot([path_coords[n][0],path_coords[n+1][0]],[path_coords[n][1],path_coords[n+1][1]],color='r')
for n in range(len(eraser_coords)-1):
    ax.plot([eraser_coords[n][0],eraser_coords[n+1][0]],[eraser_coords[n][1],eraser_coords[n+1][1]],color='r')

wgottwald avatar Mar 03 '23 08:03 wgottwald

I thought about this a bit more and while there is a make_compount_path function that only works for ...

Thanks for pointing this out, that makes the most sense to me actually. Will try to implement it like this.

wgottwald avatar Mar 03 '23 08:03 wgottwald

I wrote a function that accomplishes extracting the contours from the mask, where would you place such a function within the package? Into generic.py under the segmenter?

wgottwald avatar Mar 04 '23 07:03 wgottwald