Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image segmentation view improvement #1131

Merged

Conversation

jmancewicz
Copy link
Contributor

Changed the imageSegmentation view extension so that rather than displaying the segmentation image,
screen shot 2016-10-01 at 10 21 28 am

The segmentation image overlays the input image with a solid outline around each class.
screen shot 2016-10-01 at 10 21 07 am

The opacity of the segmented regions and the opacity of the mask of the non-segmented regions are adjustable.
screen shot 2016-10-01 at 10 18 27 am
screen shot 2016-10-01 at 10 18 45 am

I've removed the color to class legend from the header and put a legend or relevant classes beneath each image. When the pointer is over a segmented region, the corresponding class in the legend is highlighted.

screen shot 2016-10-01 at 10 28 28 am

Copy link
Contributor

@gheinrich gheinrich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brilliant!

I saw some strange things in the UI with the rounding:
screenshot from 2016-10-03 14 16 52

Made a couple of minor comments - looks very good!

@@ -6,6 +6,8 @@
import matplotlib as mpl
import numpy as np
import PIL.Image
import json
import skfmm
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lukeyeager usually prefers seeing non-standard package imports below (line 14)

Copy link
Contributor Author

@jmancewicz jmancewicz Oct 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gheinrich, this seems PEP8 compliant (https://www.python.org/dev/peps/pep-0008/#imports) in the third party block.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just move json up above import os

if self.class_labels:
text = "%s (%s)" % (text, self.class_labels[int(c)])
legend.append({'image': image, 'text': text})
legend = self.get_legend_for(self.found_classes)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're not using the legend anymore in the header template, correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Great catch.


# remember the classes we found
found_classes = np.unique(data)
found_classes = np.unique(class_data)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we still need self.found_classes below? Now that we have one legend per image I think this can go away.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, you're good.


zeros = np.zeros(class_data.shape)
# Assuming that class 0 is the background
mask = np.greater(class_data, zeros)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have to create the zeros array? I think you can use np.greater to compare against a scalar:

>>> x=np.array([0,1,2,0,4])
>>> mask=np.greater(x,0)
>>> mask
array([False,  True,  True, False,  True], dtype=bool)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

fill_data[:, :, 3] = mask * 255

# Black mask of non-segmented pixels
mask_data = np.zeros(fill_data.shape, dtype='uint8')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need this line? I think the below one is enough (?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The np.zeros create RGBA data. the line below sets the A component. Is there some pythonic trickery that I'm missing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my mistake, sorry.

# Assuming that class 0 is the background.
line_mask = np.zeros(class_data.shape, dtype=bool)
for c in (x for x in found_classes if x != 0):
c_mask = np.equal(class_data, zeros + c)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can also do without zeros here:

>>> x=np.array([0,1,1,2])
>>> np.equal(x,1)
array([False,  True,  True, False], dtype=bool)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

# Find the signed distance from the zero contour
distance = skfmm.distance(c_mask.astype('float32') - 0.5)
# Accumulate the mask for all classes
line_mask |= c_mask & np.less(distance, zeros + 3)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

neat!

@@ -38,7 +38,7 @@ def __init__(self, model, images, epoch, layers, resize=True, **kwargs):

@override
def __getstate__(self):
fields_to_save = ['_id', '_name']
fields_to_save = ['_id', '_name', 'status_history']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this commit. I needed for something a while back, which I no longer recall. Removing.

Copy link
Contributor

@gheinrich gheinrich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very nice!

@jmancewicz jmancewicz force-pushed the image-segmentation-view-improvement branch from ee5f90c to a9284ab Compare October 4, 2016 03:49

# add the outlines to the input image
for x in xrange(3):
input_data[:, :, x] = (input_data[:, :, x] * (1 - line_mask) +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't work if input_data is a grayscale image (with shape e.g. [256,256])

Copy link
Contributor

@gheinrich gheinrich Oct 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, this should be done within the if len(found_classes)>1 otherwise line_mask is uninitialized

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gheinrich, did you try this with a (256, 256)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jmancewicz yes, this was an image from the Sunnybrook dataset (with channel conversion = 'none')

fill_data[:, :, x] * line_mask)

# Input image with outlines
input_image = PIL.Image.fromarray(input_data)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this work if input_data.dtype!='uint8'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but that's in an upcoming PR.

@jmancewicz jmancewicz merged commit fdb8256 into NVIDIA:master Oct 12, 2016
@jmancewicz jmancewicz deleted the image-segmentation-view-improvement branch October 12, 2016 00:18
SlipknotTN pushed a commit to cynnyx/DIGITS that referenced this pull request Mar 30, 2017
…w-improvement

Image segmentation view improvement
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants