1

I'm fairly new to Python and am stuck on a problem...

I'm trying to draw a region of interest (ROI) on an image and calculate the average pixel value in that ROI.

To start, I tried the following - first I used matplotlib.widgets.PolygonSelector to draw a polygon, and then used path.contains_points to create a mask that I could then apply to the original image.

class ROIPolygon(object):
    def __init__(self, ax, row, col):
        self.canvas = ax.figure.canvas
        self.poly = PolygonSelector(ax,
                                    self.onselect,
                                    lineprops = dict(color = 'g', alpha = 1),
                                    markerprops = dict(mec = 'g', mfc = 'g', alpha = 1))
        self.path = None

    def onselect(self, verts):
        path = Path(verts)
        self.canvas.draw_idle()
        self.path = path

def get_mask(drawn_roi, row, col):
    for i in np.arange(row):
        for j in np.arange(col):
             if drawn_roi.path.contains_points([(j,i)]) == [True]:
                 mask[i][j] = 1
    mask_bool = mask.astype(bool)
    mask_bool = ~mask_bool
    return mask_bool

But when I tested this out on a small image containing only 4 colored pixels, I get this image before drawing ROI: enter image description here

And this one after drawing ROI: enter image description here

I expected the mask array to return only 4 False values.

[[ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True False False  True  True  True]
 [ True  True  True  True  True False False  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]]

But instead it returned 12 False values. As well, if I were to draw the ROI even larger, I would return more False values.

[[ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True False False False False  True  True]
 [ True  True  True  True False False False False  True  True]
 [ True  True  True  True False False False False  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True  True  True  True]]

So I am wondering if there is something wrong with my approach, or if there is a particular interaction between the PolygonSelector and path.contains_points I am missing?

Thanks!

lrnzcig
  • 3,868
  • 4
  • 36
  • 50
djeng
  • 11
  • 3
  • It would be great if you could post the data you used to generate the images. At the end, you get more chances of a good answer when you create a [reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). Thanks! – lrnzcig May 24 '19 at 07:17
  • It doesn't look like there is anything wrong with the code, nor with the outcome. The green polygon does indeed cover 12 points. Maybe you'd rather want to check for the corners (or edges) of the pixels, instead of their centers? That would require a new array with one more more item in each direction. – ImportanceOfBeingErnest May 24 '19 at 12:11
  • Ohhh yea..sorry I think I was confused with the contains_points. I assumed it only returned something if the value was non-zero. – djeng May 24 '19 at 13:55

1 Answers1

0

For anyone else that got confused as I was (by not reading documentation clearly), I solved my problem by altering my get_mask function as follows:

def get_mask(img_frame, drawn_roi, row, col):
    for i in np.arange(row):
        for j in np.arange(col):
             if np.logical_and(drawn_roi.path.contains_points([(j,i)]) == [True], img_frame[i][j] > 0):
                 mask[i][j] = 1
    mask_bool = mask.astype(bool)
    mask_bool = ~mask_bool
    return mask_bool
djeng
  • 11
  • 3