class SelectFromCollection(object): """Select indices from a matplotlib collection using `PolygonSelector`. Selected indices are saved in the `ind` attribute. This tool fades out the points that are not part of the selection (i.e., reduces their alpha values). If your collection has alpha < 1, this tool will permanently alter the alpha values. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, ax, collection, alpha_other=0.3): self.canvas = ax.figure.canvas self.collection = collection self.alpha_other = alpha_other self.xys = collection.get_offsets() self.Npts = len(self.xys) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, (self.Npts, 1)) self.poly = PolygonSelector(ax, self.onselect) self.ind = [] def onselect(self, verts): path = Path(verts) self.ind = np.nonzero(path.contains_points(self.xys))[0] self.fc[:, -1] = self.alpha_other self.fc[self.ind, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle() def disconnect(self): self.poly.disconnect_events() self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle()
class ChartSelector(object): def __init__(self, ax, chart_center, chart_size): self.canvas = ax.figure.canvas chart_height, chart_width = chart_size vertices = np.array([[ chart_center[0] - chart_width / 2, chart_center[1] + chart_height / 2 ], [ chart_center[0] + chart_width / 2, chart_center[1] + chart_height / 2 ], [ chart_center[0] + chart_width / 2, chart_center[1] - chart_height / 2 ], [ chart_center[0] - chart_width / 2, chart_center[1] - chart_height / 2 ], [ chart_center[0] - chart_width / 2, chart_center[1] + chart_height / 2 ]]) self.poly = PolygonSelector(ax, self.onselect, lineprops=dict(color='g', linewidth=5, alpha=1), markerprops=dict(mfc='r', markersize=10, alpha=1)) self.poly._xs = vertices[:, 0] self.poly._ys = vertices[:, 1] self.poly._polygon_completed = True self.poly._draw_polygon() self.vertices = vertices[:-1, :] def onselect(self, vertices): self.vertices = vertices self.canvas.draw_idle() def disconnect(self): self.poly.disconnect_events() self.canvas.draw_idle()
def __init__(self, ax, collection, alpha_other=0.3): self.canvas = ax.figure.canvas self.collection = collection self.alpha_other = alpha_other self.xys = collection.get_offsets() self.Npts = len(self.xys) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, (self.Npts, 1)) self.poly = PolygonSelector(ax, self.onselect) self.ind = []
def __init__(self, ax, grid, csv, image): self.canvas = ax.figure.canvas self.grid = grid self.csv = csv self.ax = ax self.image = image self.tool = LassoSelector(ax, onselect=self.onselect) self.ind = [] self.selection = []
def drawPolygon(self, click): print( "Click somewhere on the screen to start drawing the polygon.\n\n") self.rs = PolygonSelector(self.ax, self._drawPolygonEvent, markerprops=dict(markersize=1), lineprops=dict(linewidth=1, alpha=0.6, color='k'))
def enter_draw_mode(self) : """ Ensure that the next click after this fcn call will start drawing the polygon. """ # Remove the previous polygon if self.poly and self.poly._polygon_completed : self.remove_polygon() # Reset the flag indicating the first completion of a new polygon #self.first_time_complete = True # Create a PolygonSelector object and attach the draw lock to # it self.poly = PolygonSelector(self, self._on_polygon_complete, lineprops=self.polylineprops, markerprops=self.polymarkerprops, useblit=self.useblit) self.figure.canvas.widgetlock(self.poly)
class SelectFromArray(object): """Select indices from a matplotlib collection using `PolygonSelector`. Selected indices are saved in the `ind` attribute. This tool fades out the points that are not part of the selection (i.e., reduces their alpha values). If your collection has alpha < 1, this tool will permanently alter the alpha values. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, ax, x, y, alpha_other=0.3): self.canvas = ax.figure.canvas self.x, self.y = x, y self.xys = np.vstack((x, y)) self.Npts = len(self.xys) # Ensure that we have separate colors for each object self.poly = PolygonSelector(ax, self.onselect) self.ind = [] def onselect(self, verts): path = Path(verts) self.poly_mask = poly2mask(self.x, self.y, path) self.canvas.draw_idle() def disconnect(self): self.poly.disconnect_events() self.canvas.draw_idle()
def get_mask(self): data = self.resized fig = plt.figure() ax1 = fig.add_subplot(121) ax1.imshow(data) ax2 = fig.add_subplot(122) ax2.imshow(np.zeros_like(data)) plt.subplots_adjust() self.fig = fig self.poly = PolygonSelector(ax1, self.onselect)
def show_filtered_image(event): ''' shows the filtered image or the original image. If you press the button once, the respectively other option appears on the button. :param event: :return: ''' global sfi_button, im_f, im, im_mask, lasso2 # disconnects and stops the lassoselecto lasso2.disconnect_events() # showing the filtered image if sfi_button.label.get_text( ) == "show filtered\nimage": # checks the text displayed on the button im.remove() # removing unfiltered image im_f = ax.imshow(image_f) # showning filterd image lasso2 = PolygonSelector(ax, select_mask) # reinitalizing the selector if isinstance(mask_show, np.ndarray): # showing mask if already selected im_mask = ax.imshow(mask_show, alpha=0.2) sfi_button.label.set_text("show unfiltered\nimage") fig.canvas.draw_idle() # plot update return # showing the unfilterd image if sfi_button.label.get_text( ) == "show unfiltered\nimage": # checks the text displayed on the button im_f.remove() # removing unfiltered image im = ax.imshow(image) # showing filterd image lasso2 = PolygonSelector(ax, select_mask) # reinitalizing the selector if isinstance(mask_show, np.ndarray): # showing mask if alaready selected im_mask = ax.imshow(mask_show, alpha=0.2) sfi_button.label.set_text("show filtered\nimage") fig.canvas.draw_idle() # plot update return
def selectROI(region): import pylab from matplotlib.widgets import PolygonSelector fig, ax = plt.subplots() ax.imshow(frame) plt.title(region) def onselect(verts): np.savetxt(direc + '\\coordinates\\' + region, verts) polygon = PolygonSelector(ax, onselect) plt.show()
def selectROI(region, frame, main_dir): ## function that allows us to display a matplotlib interactive polygon selector to annotate the frame for each region (which is one of the arguments) ## fig, ax = plt.subplots() ax.imshow(frame) plt.title(region + ' - Press Q to move to the next location') ## this is the function that is fed to the polygon selector tool. All I am doing here is saving the coordinates for every polygon drawn to a text file of numpy coordinates ## ## this allows me to save them outside of the python kernel, and they can be pulled in later at any point ## def onselect(verts): np.savetxt(os.path.join(os.path.join(main_dir, 'coordinates'), region), verts) polygon = PolygonSelector(ax, onselect) plt.show()
def __init__(self, ax, grid, csv, image, regions=[], labels=[], fracs=[]): self.canvas = ax.figure.canvas self.grid = grid self.csv = csv self.ax = ax self.image = image self.tool = LassoSelector(ax, onselect=self.onselect) self.ind = [] self.selection = [] self.region = [] self.saved_regions = regions self.saved_labels = labels self.saved_fractions = fracs self.saved_max = [] self.saved_min = [] self.saved_avg = [] self.saved_maxavg = []
def getTargets(self, image, method, **kwargs): print("Add targets...\n") if method in ['poly', 'point']: figure = plt.figure() ax = plt.gca() plt.imshow(image) radius = kwargs['radius'] if 'radius' in kwargs else 2 n = kwargs['n'] if 'n' in kwargs else 100 if method == 'poly': ps = PolygonSelector(ax, lambda verts: self.computePolygon(verts, n = n) ) plt.show() elif method =='point': figure.canvas.mpl_connect('button_press_event', lambda event: self.computeCircle(event, radius = radius, n = n) ) plt.show() else: self.getTargetsFromImage( kwargs['L'], n )
def __init__(self, image, atom_positions, invert_selection=False): """Get a subset of atom positions using interactive tool. Access the selected atom positions in the atom_positions_selected attribute. Parameters ---------- image : 2D HyperSpy signal or 2D NumPy array atom_positions : list of lists, NumPy array In the form [[x0, y0]. [x1, y1], ...] invert_selection : bool, optional Get the atom positions outside the region, instead of the ones inside it. Default False Attributes ---------- atom_positions_selected : NumPy array """ self.image = image self.atom_positions = np.array(atom_positions) self.invert_selection = invert_selection self.atom_positions_selected = [] self.fig, self.ax = plt.subplots(figsize=(6, 6)) self.ax.set_title("Use the left mouse button to make the polygon.\n" "Click the first position to finish the polygon.\n" "Press ESC to reset the polygon, and hold SHIFT to\n" "move the polygon.") self.cax = self.ax.imshow(self.image) self.line_non_selected = self.ax.plot(self.atom_positions[:, 0], self.atom_positions[:, 1], 'o', color='red')[0] self.line_selected = None markerprops = dict(color='blue') lineprops = dict(color='blue') self.poly = PolygonSelector(self.ax, self.onselect, markerprops=markerprops, lineprops=lineprops) self.fig.tight_layout()
def __init__(self, image, dataType='image', xlim=None, ylim=None): self.x1 = 0.0 self.x2 = 0.0 self.y1 = 0.0 self.y2 = 0.0 self.verts = [] # Print instructions for the user self.instructions = "\nINSTRUCTIONS TO DRAW THE POLYGON\n\n"+\ "Select points in the figure by enclosing them within a polygon.\n"+\ "Press the 'esc' key to start a new polygon.\n"+\ "Try holding the 'shift' key to move all of the vertices.\n"+\ "Try holding the 'ctrl' key to move a single vertex." lineprops = dict(color='r', linestyle='-', linewidth=2, alpha=0.5) markerprops = dict(marker='o', markersize=7, mec='r', mfc='r', alpha=0.5) # Create the figure and plot the image fig = plt.figure(1) self.ax1 = fig.add_subplot(111) if dataType == 'image': self.ax1.imshow(image.T) elif dataType == 'points': self.ax1.plot(*image.T[0:2], 'ob', markersize=3) if xlim is not None: self.ax1.set_xlim(xlim[0], xlim[1]) if ylim is not None: self.ax1.set_ylim(ylim[0], ylim[1]) self.ps = PolygonSelector(self.ax1, self.onselect, lineprops=lineprops, markerprops=markerprops) plt.show()
def _select_roi(self): if self._active == 'roi': self._active=None self._actions['roi'].setChecked(False) self.lasso=None else: self._active='roi' self._actions['roi'].setChecked(True) # lasso disappears if window closed and reopened. Must check super if not self.unsorted:#self.fig is None: ax=self.figure.gca() h=self.histo if h.dims==2: #from polygonlasso import MyLassoSelector #self.lasso=MyLassoSelector(ax,self.select2dGate,useblit=False) self.lasso=PolygonSelector(ax,self.select2dGate,useblit=False, lineprops=dict(color='c', linestyle='-', linewidth=2, alpha=0.5)) else: self.lasso=SpanSelector(ax,self.select1dregion,"horizontal", rectprops = dict(facecolor='blue', alpha=0.5))
def ask_file(event): ''' opens a tk inter file browser. The selected file is loaded as an image to the window. Additionally the filtered image is calculated immediately. :param event: :return: ''' # opens dialog box for image selection global fig, ax, image, pix, image_f, im, lasso2 root = tk.Tk() root.withdraw() # file_path = filedialog.askopenfile() # loading the image image = plt.imread(file_path.name) # grey scale conversion, one could use some wights here if len(image.shape) == 3: #image=image[:,:,0] image = np.mean(image, axis=2) # filtering image image_f = normalize(image, lb=0.1, ub=99.9) # normalization to a range from 0 to 1 image_f = gaussian(image_f, sigma=s1) - gaussian( image_f, sigma=s2) # difference of gaussian filtering # displaying unfiltered image first im = ax.imshow(image) # you can choose a diffrent color map here fig.canvas.draw_idle() #plot update # coordinate of the image, later needed for selction pixx = np.arange(image.shape[0]) pixy = np.arange(image.shape[1]) xv, yv = np.meshgrid(pixy, pixx) pix = np.vstack((xv.flatten(), yv.flatten())).T # (re)initialize polygon selector #lasso2.disconnect_events() seems to have some kind of bug... lasso2 = PolygonSelector(ax, select_mask) # selector on bf image
class cursorpolyax(cursorax): """ A cursorax that allows drawing of a draggable polygon-ROI. By clicking on the plot, a cursor appears which behaves and can be accessed the same way as in :class:`cursorax <arpys.utilities.plotting.cursorax>`. Additionally, hitting the `draw_key` (`d` by default) puts user in `polygon-draw mode` where each subsequent click on the plot adds another corner to a polygon until it is completed by clicking on the starting point again. Once finished, each click just moves the cursor, as before. Hitting the `remove_key` (`e` by default) removes the polygon from the plot. At the moment of the polygon's completion, the function :meth:`on_polygon_complete <arpys.utilities.plotting.cursorpolyax.on_polygon_complete>` is executed. This function is a stub in the class definition and can be overwritten/reassigned by the user to perform any action desired on polygon completion. The vertices of the last completed polygon are present as an argument to :meth:`on_polygon_complete <kustom.plotting.cursorpolyax.on_polygon_complete>` and can also be accessed by :attr:`vertices` at any time. The actual magic here is done by :class:`PolygonSelector <matplotlib.widgets.PolygonSelector>` which this class mostly just provides a simple interface for ... :Known bugs: * Using :class:`PolygonSelector <matplotlib.widgets.PolygonSelector>`'s default 'remove' key (Esc) messes up reaction to :class:`cursorpolyax <arpys.utilities.plotting.cursorpolyax>`' keybinds. * Shift-dragging polygon makes the cursor jump. """ # The name under which this class of axes will be accessible from matplotlib name = 'cursorpoly' poly = None vertices = None polylineprops = dict(color='r', lw='1') polymarkerprops = dict(marker='None') draw_key = 'd' remove_key = 'e' # Blitting leads to weird behaviour useblit = False #first_time_complete = True def __init__(self, *args, **kwargs): """ The super-class's __init__ method connects the event handling but is going to use the definitions for :func: `on_click <kustom.plotting.cursorpolyax.on_click>` and :func: `on_press <kustom.plotting.cursorpolyas.on_press>` from this class. """ #cid = self.figure.canvas.mpl_connect('button_press_event', self.on_click) #pid = self.figure.canvas.mpl_connect('key_press_event', on_press) super().__init__(*args, **kwargs) def on_press(self, event): """ Handle keyboard press events. If the pressed key matches :attr: `draw_key <cursorax.draw_key>` or :attr: `remove_key <cursorpolyax.remove_key>` and the figure is not draw-locked, carry out the respective operations. """ # Don't do anything if someone else is drawing if not self.figure.canvas.widgetlock.available(self.poly): return if event.key == self.remove_key: # Remove the polygon and release the lock self.remove_polygon() return elif event.key == self.draw_key: self.enter_draw_mode() def enter_draw_mode(self): """ Ensure that the next click after this fcn call will start drawing the polygon. """ # Remove the previous polygon if self.poly and self.poly._polygon_completed: self.remove_polygon() # Reset the flag indicating the first completion of a new polygon #self.first_time_complete = True # Create a PolygonSelector object and attach the draw lock to # it self.poly = PolygonSelector(self, self._on_polygon_complete, lineprops=self.polylineprops, markerprops=self.polymarkerprops, useblit=self.useblit) self.figure.canvas.widgetlock(self.poly) def on_click(self, event): """ Handle mouse-click events. Just call the superclass' on_click method, which positions the cursor at the clicked location. That method check's itself whether the draw lock is free, so we don't get cursor jumps while we're drawing a polygon. """ # Release the draw lock if the polygon has been completed. Otherwise, # the cursor can't be repositioned. if self.poly and self.poly._polygon_completed: self.figure.canvas.widgetlock.release(self.poly) super().on_click(event) def remove_polygon(self): """ Make the polygon invisible, remove the reference to it (which should cause the underlying :class: `PolygonSelector <matplotlib.widgets.PolygonSelector>` object to be garbage collected) and release the draw lock. """ if not self.poly: return try: self.figure.canvas.widgetlock.release(self.poly) except: pass self.poly.set_visible(False) self.poly = None self.figure.canvas.draw() def _on_polygon_complete(self, vertices): """ Get a handle on the polygon's vertices and call the user-supplied :func: `on_polygon_complete <kustom.plotting.cursorpolyas.on_polygon_complete>`. """ self.vertices = vertices # Only do this the first time the polygon is completed NOTE If we # only do this the first time the polygon is completed, the function # wont be called when user moves the polygon with shift+drag. The # drawback of the way it is now is that this function gets called # every time the user clicks on the plot once the polygin has been # created.... #if self.first_time_complete : self.on_polygon_complete(vertices) #self.first_time_complete = False #self.figure.canvas.draw_idle() def on_polygon_complete(self, vertices): """ This method should be overridden/redefined by user. """ print(vertices)
def lasso_select(self, event): self.disconnect() self.tool = LassoSelector(self.ax, onselect=self.onselect) self.canvas.draw_idle()
def poly_select(self, event): self.disconnect() self.tool = PolygonSelector(self.ax, onselect=self.onselect, markerprops={'markersize': 3}) self.canvas.draw_idle()
class SelectFromCollection(object): """Select indices from a matplotlib collection using `PolygonSelector`. Selected pixels within the polygon is marked as True and saved in the member variable self.mask, in the same size as input AxesImage object with all the other pixels marked as False. Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. Examples -------- import matplotlib.pyplot as plt from mintpy.utils import readfile, plot as pp fig, ax = plt.subplots() data = readfile.read('velocity.h5', datasetName='velocity')[0] im = ax.imshow(data) selector = pp.SelectFromCollection(ax, im) plt.show() selector.disconnect() plt.figure() plt.imshow(selector.mask) plt.show() """ def __init__(self, ax, collection, alpha_other=0.3): self.canvas = ax.figure.canvas self.collection = collection self.prepare_coordinates() self.poly = PolygonSelector(ax, self.onselect) msg = "\nSelect points in the figure by enclosing them within a polygon.\n" msg += "Press the 'esc' key to start a new polygon.\n" msg += "Try hold to left key to move a single vertex.\n" msg += "After complete the selection, close the figure/window to continue.\n" print(msg) def prepare_coordinates(self): imgExt = self.collection.get_extent() self.length = int(imgExt[2] - imgExt[3]) self.width = int(imgExt[1] - imgExt[0]) yy, xx = np.mgrid[:self.length, :self.width] self.coords = np.hstack((xx.reshape(-1, 1), yy.reshape(-1, 1))) def onselect(self, verts): self.poly_path = Path(verts) self.mask = self.poly_path.contains_points(self.coords).reshape( self.length, self.width) self.canvas.draw_idle() def disconnect(self): self.poly.disconnect_events() self.canvas.draw_idle()
class SelectUtils(object): def __init__(self, ax, grid, csv, image, regions=[], labels=[], fracs=[]): self.canvas = ax.figure.canvas self.grid = grid self.csv = csv self.ax = ax self.image = image self.tool = LassoSelector(ax, onselect=self.onselect) self.ind = [] self.selection = [] self.region = [] self.saved_regions = regions self.saved_labels = labels self.saved_fractions = fracs self.saved_max = [] self.saved_min = [] self.saved_avg = [] self.saved_maxavg = [] self.saved_pixcount = [] def onselect(self, verts): print("selected!") reg = Path(verts) self.ind = reg.contains_points(self.grid, radius=1) mask = ~self.ind alpha = ( 0.6 + ma.masked_array(np.zeros_like(self.csv) + 0.4, mask=mask)).data self.selection = ma.masked_array(self.csv, mask=mask) self.region = reg self.image.set_alpha(alpha) self.canvas.draw_idle() def lasso_select(self, event): self.disconnect() self.tool = LassoSelector(self.ax, onselect=self.onselect) self.canvas.draw_idle() def poly_select(self, event): self.disconnect() self.tool = PolygonSelector(self.ax, onselect=self.onselect, markerprops={'markersize': 3}) self.canvas.draw_idle() def disconnect(self): self.tool.disconnect_events() self.canvas.draw_idle() def reset(self, event): self.disconnect() self.image.set_alpha(np.ones_like(self.csv)) self.canvas.draw_idle() def clear_polygons(self, event): self.disconnect() self.ax.clear() self.image = self.ax.imshow(self.csv, cmap='plasma', vmin=self.csv.min(), vmax=self.csv.max(), interpolation='none') self.ax.set_title("Press enter to accept selected points.") self.canvas.draw_idle() def save_selection(self, event): if event.key == "enter": label = input("Label for this region: ") frac = float(input("Area fraction: ")) max = np.max(self.selection) min = np.min(self.selection) avg = np.average(self.selection) avg_10max = np.average( heapq.nlargest(10, self.selection.compressed())) self.saved_regions.append(self.region) self.saved_labels.append(label) self.saved_fractions.append(frac) self.saved_max.append(max) self.saved_min.append(min) self.saved_avg.append(avg) self.saved_maxavg.append(avg_10max) self.saved_pixcount.append(self.selection.compressed().size) def refresh_results(self): #Used when paths are imported from prior image and results need to be re-calculated for the new image for reg in self.saved_regions: self.ind = reg.contains_points(self.grid, radius=1) mask = ~self.ind self.selection = ma.masked_array(self.csv, mask=mask) max = np.max(self.selection) min = np.min(self.selection) avg = np.average(self.selection) avg_10max = np.average( heapq.nlargest(10, self.selection.compressed())) self.saved_max.append(max) self.saved_min.append(min) self.saved_avg.append(avg) self.saved_maxavg.append(avg_10max) self.saved_pixcount.append(self.selection.compressed().size) def write(self, fname, volt, curr): output = open(fname, "a") if os.stat(fname).st_size == 0: output.write( "Region,Max T,Avg Max T (10 largest),Min T,Avg T,Voltage,Current,Power,Area Fraction,Pixel Count\n" ) for i, label in enumerate(self.saved_labels): output.write( "%s,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%i\n" % (label, self.saved_max[i], self.saved_maxavg[i], self.saved_min[i], self.saved_avg[i], volt, curr, volt * curr, self.saved_fractions[i], self.saved_pixcount[i])) output.close()
polygonVertices = [(min(max(0, entry[0]), imageHandler.xMax), min(max(0, entry[1]), imageHandler.yMax)) for entry in polygonVertices] xPoints, yPoints = np.meshgrid(np.arange(outAveraged.shape[2]), np.arange(outAveraged.shape[1])) xPoints, yPoints = xPoints.flatten(), yPoints.flatten() points = np.vstack((xPoints, yPoints)).T polyPath = Path(polygonVertices) imageMask = polyPath.contains_points(points) imageHandler.imageMask = imageMask.reshape( (outAveraged.shape[1], outAveraged.shape[2])) imageHandler.boundaryPoly = polyPath poly = PolygonSelector(ax, PolySelection) plt.show() plt.close() # # outAveraged = outAveraged * imageHandler.imageMask + 1 for centerSlice in range(len(wavelengths)): CLFrame = outAveraged[centerSlice, :, :] backgroundPoints = getBackgroundPoints(CLFrame, 0.01) backgroundAverage = np.mean(backgroundPoints) outAveragedBlurred[centerSlice, :, :] = gaussian_filter( CLFrame, sigma=gaussianSigma, truncate=truncateWindow) + backgroundAverage / 2
def init_plot(self, embedding, weights, on_selection, on_close, disable_select, top_level=False, labels=None, color_norm=None): """ Set the initial embedding and point weights to create and display the plot at iteration step=0""" # pylint: disable=attribute-defined-outside-init self.top_level = top_level self.labels = labels self.color_norm = color_norm self.disable_select = disable_select self.selection_mask = np.full(weights.shape, False) # Plot and image definition # self.rect = None self.extent = 2.8 self.cleanup = True self.rectangle_selector = None self.lasso_selector = None # Callbacks self.fig.canvas.mpl_connect('motion_notify_event', self.on_over) self.fig.canvas.mpl_connect('key_press_event', self.on_keypress) self.fig.canvas.mpl_connect('button_press_event', self.on_start_select) self.fig.canvas.mpl_connect('close_event', self.handle_close) # Brush support values self.in_selection = False self.in_paint = False self.dim_xy = (None, None) # displacement self.rorg_xy = (None, None) # The bottom left corner print("Show plot") plt.show(block=False) # Need no block for cooperation with tkinter self.embedding = embedding self.on_selection = on_selection self.on_close = on_close # pylint: enable=attribute-defined-outside-init x = embedding[:, 0] y = embedding[:, 1] if self.labels is None: self.scatter = self.ax.scatter(x, y, s=weights * 8, c='b', alpha=0.4, picker=10) else: self.scatter = self.ax.scatter( x, y, s=weights * 8, c=self.labels, # TODO make color map user selectable pylint: disable=fixme cmap=plt.cm.rainbow_r, # # pylint: disable=no-member norm=self.color_norm, alpha=0.4, picker=10) self.update_scatter_plot_limits(embedding) # Drawing selectors rectangle_selector = RectangleSelector(self.ax, self.on_end_rectangle_select, drawtype='box', useblit=True, button=[1, 3], rectprops=dict( facecolor=(1, 0, 0, 0.1), edgecolor=(1, 0, 0, 0.5), fill=False), minspanx=5, minspany=5, spancoords='pixels') lasso_selector = LassoSelector(self.ax, onselect=self.on_end_lasso_select, lineprops=dict(color=(1, 0, 0, 0.5))) ellipse_selector = EllipseSelector(self.ax, onselect=self.on_end_ellipse_select, drawtype='line', lineprops=dict(color=(1, 0, 0, 0.5))) polygon_selector = PolygonSelector(self.ax, onselect=self.on_end_lasso_select, lineprops=dict(color=(1, 0, 0, 0.5))) self.selectors = { DrawingShape.Lasso: lasso_selector, DrawingShape.Ellipse: ellipse_selector, DrawingShape.Rectangle: rectangle_selector, DrawingShape.Polygon: polygon_selector } # pylint: disable=attribute-defined-outside-init self.set_selector() # force rendering of facecolors self.fig.canvas.draw() self.facecolors = self.scatter.get_facecolors()
class Map(): """ This class provides a GUI interface and map object that represents a robot's environment. This will be used to graph a robots movements in an environment """ def __init__(self, height=100, width=100, points_per_side=1000): """ This function creates and initializes the Map with the given parameters. Parameters ---------- height: Integer The height of the map width: Integer The width of the map points_per_side: Integer The number of points on the map grid per side (x and y) Returns ------- Map object with the given parameters after the user has edited. """ self._h = height self._w = width self._pps = points_per_side self._objects = [] # Get figure objects and adjust for buttons self.setup() # Build map of points points_x = np.tile(np.linspace(0, self._w, self._pps), self._pps) points_y = np.repeat(np.linspace(0, self._h, self._pps), self._pps) self._pts = self._ax.scatter(points_x, points_y) self._coordinates = self._pts.get_offsets() #Make points invisible #self._pts.set_facecolors([0, 0, 0, 0]) self._pts.remove() self._map = np.zeros((self._pps - 1, self._pps - 1)) def edit(self): try: plt.close(self._fig) except: print("Exception") pass self.setup() plt.figure(self._fig.number) plt.show(block=True) def click_add_object(self, event): """ Callback for the 'Add Object' button """ self._poly_select.set_active(True) def click_clear(self, event): """ Callback for the 'Clear Objects' button """ for item in self._objects: item.remove() self._objects.clear() self._map = np.zeros((self._pps - 1, self._pps - 1)) def click_finished(self, event): """ Callback for the 'Finished' button """ plt.close(self._fig) @property def height(self): """ The height of the map (Max y value) """ return self._h @property def width(self): """ The width of the map (Max x value) """ return self._w @property def map(self): """ The map defined by the object. -1 indicates an obstacle. """ return self._map @property def pps(self): """ The number of points per side in the map. NOTE: The map property will be one point smaller in both directions as it is the gaps between the points. """ return self._pps @map.setter def map(self, new_map): """ This is a setter for the internal map object. This allows the user to manually edit a copy of the map and set it back in the object. """ self._map = new_map def setup(self): # Get figure objects and adjust for buttons self._fig = plt.figure() self._ax = self._fig.add_subplot(1, 1, 1) self._ax.set_title("Map Editor") self._fig.canvas.set_window_title('RoboLib') self._ax.set_xlim([0, self._w]) self._ax.set_ylim([0, self._h]) plt.subplots_adjust(bottom=0.2) # Build buttons button_location = plt.axes([0.8, 0.05, 0.15, 0.075]) self._add_object_button = Button(button_location, 'Add Object') self._add_object_button.on_clicked(self.click_add_object) button_location = plt.axes([0.6, 0.05, 0.18, 0.075]) self._clear_axes_button = Button(button_location, "Clear Objects") self._clear_axes_button.on_clicked(self.click_clear) button_location = plt.axes([0.4, 0.05, 0.15, 0.075]) self._finished_button = Button(button_location, 'Finished') self._finished_button.on_clicked(self.click_finished) # Clear from previous axis for patch in self._objects: patch.remove() for patch in self._objects: self._ax.add_patch(patch) self._poly_select = PolygonSelector(self._ax, self.on_poly_select) self._poly_select.set_active(False) def on_poly_select(self, verts): """ This function is called by the polygon select when a polygon is closed by the user. It adds a patch to the figure and updates the grid map. """ #Close and create patch TODO: Replace with Draggable verts.append(verts[0]) path = Path(verts) patch = patches.PathPatch(path) self._ax.add_patch(patch) self._objects.append(patch) # Find points which the polygon contains self._intersections = np.nonzero( path.contains_points(self._coordinates))[0] # Update the grid for index in self._intersections: x = index % self._pps y = floor(index / self._pps) if x != self._w and y != self._h: self._map[x, y] = -1 if x != 0 and y != 0: self._map[x - 1, y - 1] = -1 if x != self._w and y != 0: self._map[x, y - 1] = -1 if x != 0 and y != self._h: self._map[x - 1, y] = -1 # Necessary Matplotlib internal functions on the PolygonSelector self._poly_select._clean_event(self._poly_select._prev_event) self._poly_select.set_visible(True) self._poly_select._xs, self._poly_select._ys = [0], [0] self._poly_select._polygon_completed = False self._poly_select.update() self._poly_select.set_active(False)
minsize = 0 # default value, you can change this # custom color map for showing the mask of segmentation cmap_mask = LinearSegmentedColormap.from_list('mycmap', ["red", "white"]) # initializing the interactive window fig, ax = plt.subplots() txt = plt.text(0.25, 0.15, str("")) # text over sliding bar plt.subplots_adjust(left=0.25, bottom=0.25) # adding the open image button to the window ax_file, file_select = set_button([0.02, 0.5, 0.17, 0.05], 'open image', ask_file) # initialyzing the polygone selector lasso2 = PolygonSelector(ax, select_mask) # ## adds functionality to delete the mask of segemntation or the dish area on rioght mouse click delete_mask_event = fig.canvas.mpl_connect('button_press_event', delete_mask) # buttton so save the mask of the dish area ax_save_changes, save_changes_button = set_button([0.02, 0.4, 0.17, 0.05], 'save mask', save_mask) # buttton to swithc between the filtered and unfiltered images ax_sfi, sfi_button = set_button([0.02, 0.15, 0.17, 0.1], "show filtered\nimage", show_filtered_image) # adding the slider for thresholding ax_slider_tresh = plt.axes([0.25, 0.1, 0.65, 0.03]) # axis for the slider slider1 = Slider(ax_slider_tresh,
Polygon Selector ================ Shows how to create a polygon programmatically or interactively """ import matplotlib.pyplot as plt from matplotlib.widgets import PolygonSelector ############################################################################### # # To create the polygon programmatically fig, ax = plt.subplots() fig.show() selector = PolygonSelector(ax, lambda *args: None) # Add three vertices selector.verts = [(0.1, 0.4), (0.5, 0.9), (0.3, 0.2)] ############################################################################### # # To create the polygon interactively fig2, ax2 = plt.subplots() fig2.show() selector2 = PolygonSelector(ax2, lambda *args: None) print("Click on the figure to create a polygon.") print("Press the 'esc' key to start a new polygon.")
def imshow(self, image, slider=False, normalize=True, roi_callback=None, roi_drawtype='box', **kwargs): ''' Showing an image on the canvas, and optional sliders for colour adjustments. Redrawing image afterwards is quite fast because set_data is used instead imshow (matplotlib). INPUT ARGUMENTS slider Whether to draw the sliders for setting image cap values roi_callback A callable taking in x1,y1,x2,y2 roi_drawtype "box", "ellipse" "line" or "polygon" *kwargs go to imshow Returns the object returned by matplotlib's axes.imshow. ''' if image is None: image = self.imshow_image self.imshow_image = image # Slider if slider: # Check if the sliders exist. If not, create try: self.imshow_sliders except AttributeError: self.slider_axes = [ self.figure.add_axes(rect) for rect in ([0.2, 0.05, 0.6, 0.05], [0.2, 0, 0.6, 0.05]) ] self.imshow_sliders = [] self.imshow_sliders.append( matplotlib.widgets.Slider(self.slider_axes[0], 'Upper %', 0, 100, valinit=90, valstep=1)) self.imshow_sliders.append( matplotlib.widgets.Slider(self.slider_axes[1], 'Lower %', 0, 100, valinit=5, valstep=1)) for slider in self.imshow_sliders: slider.on_changed(lambda slider_val: self.imshow( None, slider=slider, **kwargs)) for ax in self.slider_axes: if ax.get_visible() == False: ax.set_visible(True) # Normalize using the known clipping values #image = image - lower_clip #image = image / upper_clip else: # Hide the sliders if they exist if getattr(self, 'imshow_sliders', None): for ax in self.slider_axes: if ax.get_visible() == True: ax.set_visible(False) print('axes not visible not') if getattr(self, 'imshow_sliders', None): # Check that the lower slider cannot go above the upper. if self.imshow_sliders[0].val < self.imshow_sliders[1].val: self.imshow_sliders[0].val = self.imshow_sliders[1].val upper_clip = np.percentile(image, self.imshow_sliders[0].val) lower_clip = np.percentile(image, self.imshow_sliders[1].val) image = np.clip(image, lower_clip, upper_clip) if normalize: image = image - np.min(image) image = image / np.max(image) # Just set the data or make an imshow plot if self._previous_shape == image.shape and ( roi_callback is None or roi_drawtype == self._previous_roi_drawtype): self.imshow_obj.set_data(image) else: if hasattr(self, 'imshow_obj'): # Fixed here. Without removing the AxesImages object plotting # goes increacingly slow every time when visiting this else block # Not sure if this is the best fix (does it free all memory) but # it seems to work well self.imshow_obj.remove() self.imshow_obj = self.ax.imshow(image, **kwargs) self.figure.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=None, hspace=None) self.ax.xaxis.set_major_locator(matplotlib.ticker.NullLocator()) self.ax.yaxis.set_major_locator(matplotlib.ticker.NullLocator()) if callable(roi_callback): if getattr(self, "roi_rectangle", None): if self._previous_roi_drawtype == 'line': self.roi_rectangle.disconnect() else: self.roi_rectangle.disconnect_events() if roi_drawtype == 'box': self.roi_rectangle = RectangleSelector( self.ax, self.__onSelectRectangle, useblit=True) elif roi_drawtype == 'ellipse': self.roi_rectangle = EllipseSelector( self.ax, self.__onSelectRectangle, useblit=True) elif roi_drawtype == 'line': self.roi_rectangle = ArrowSelector( self.ax, self.__onSelectRectangle) elif roi_drawtype == 'polygon': self.roi_rectangle = PolygonSelector( self.ax, self.__onSelectPolygon, useblit=True) else: raise ValueError( 'roi_drawtype either "box", "ellipse", "line", or "polygon", got {}' .format(roi_drawtype)) self.roi_callback = roi_callback self._previous_roi_drawtype = roi_drawtype self._previous_shape = image.shape self.canvas.draw() return self.imshow_obj
def drawAOI(self): """Function that allows speicification of area of interest (AOI) for analysis. """ with open(self.json_file, "r") as f: json_data = json.load(f) aoi_left_x = 0 aoi_left_y = 0 aoi_right_x = 0 aoi_right_y = 0 display_width = json_data["Analysis_Params"]["EyeTracker"]["Display_width"] display_height = json_data["Analysis_Params"]["EyeTracker"]["Display_height"] cnt = 0 img = None if os.path.isdir(self.path + "/Stimuli/"): for f in os.listdir(self.path + "/Stimuli/"): if f.split(".")[-1] in ['jpg', 'jpeg', 'png']: img = plt.imread(self.path + "/Stimuli/" + f) cnt += 1 break if cnt == 0: img = np.zeros((display_height, display_width, 3)) fig, ax = plt.subplots() fig.canvas.set_window_title("Draw AOI") ax.imshow(img) if self.aoi == "p": def onselect(verts): nonlocal vertices, canvas print('\nSelected points:') x = [] y = [] for i, j in vertices: print(round(i, 3), ",", round(j, 3)) x.append(i) y.append(j) vertices = verts canvas.draw_idle() canvas = ax.figure.canvas _ = PolygonSelector(ax, onselect, lineprops=dict(color='r', linestyle='-', linewidth=2, alpha=0.5), markerprops=dict(marker='o', markersize=7, mec='r', mfc='k', alpha=0.5)) vertices = [] print("1) 'esc' KEY: START A NEW POLYGON") print("2) 'shift' KEY: MOVE ALL VERTICES BY DRAGGING ANY EDGE") print("3) 'ctrl' KEY: MOVE A SINGLE VERTEX") plt.show() return vertices elif self.aoi == "r": def line_select_callback(eclick, erelease): nonlocal aoi_left_x, aoi_left_y, aoi_right_x, aoi_right_y aoi_left_x, aoi_left_y = round(eclick.xdata, 3), round(eclick.ydata, 3) aoi_right_x, aoi_right_y = round(erelease.xdata, 3), round(erelease.ydata, 3) print("Coordinates [(start_x, start_y), (end_x, end_y)]: ", "[(%6.2f, %6.2f), (%6.2f, %6.2f)]" % (aoi_left_x, aoi_left_y, aoi_right_x, aoi_right_y)) RS = RectangleSelector(ax, line_select_callback, drawtype='box', useblit=False, interactive=True) RS.to_draw.set_visible(True) plt.show() return [aoi_left_x, aoi_left_y, aoi_right_x, aoi_right_y] elif self.aoi == "e": x_dia = 0 y_dia = 0 centre = (0,0) def onselect(eclick, erelease): nonlocal x_dia, y_dia, centre x_dia = (erelease.xdata - eclick.xdata) y_dia = (erelease.ydata - eclick.ydata) centre = [round(eclick.xdata + x_dia/2., 3), round(eclick.ydata + y_dia/2., 3)] print("Centre: ", centre) print("X Diameter: ", x_dia) print("Y Diameter: ", y_dia) print() ES = EllipseSelector(ax, onselect, drawtype='box', interactive=True, lineprops=dict(color='g', linestyle='-', linewidth=2, alpha=0.5), marker_props=dict(marker='o', markersize=7, mec='g', mfc='k', alpha=0.5)) plt.show() return [centre, x_dia, y_dia]
def __init__(self, ax): self.canvas = ax.figure.canvas self.poly = PolygonSelector(ax, self.onselect) self.ind = []
def show_mask(prod, mask: np.ndarray) -> None: filter = (abs(prod.vh_image.mean() - (prod.vh_image.std( ) if prod.vh_image.mean() > 0.005 else prod.vh_image.min()))) min = 0.0 max = (prod.vh_image.mean() if prod.vv_image.mean() < prod.vh_image.mean() else prod.vh_image.mean()) # Update function for the PolygonSelector def onselect(verts): print("Creating Indices") # Path based on the verticies from the selection path = Path(verts) coords_pruned = prune(prod, verts) path_start = time.perf_counter() # Array of indices that are within the polygon ind = np.vstack( [[p[0] for p in coords_pruned if path.contains_point(p)], [p[1] for p in coords_pruned if path.contains_point(p)]]) path_end = time.perf_counter() print("Point in Polygon Time: ", path_end - path_start) mask_start = time.perf_counter() mask_edited = edit_mask_from_selection(mask, 1, verts, ind) mask_end = time.perf_counter() print("Mask Editing Time: ", mask_end - mask_start) return show_mask(prod, mask_edited) def update(val): show_mask(prod, create_mask(prod.vv_image, prod.vh_image, val)) mat = plt.matshow(mask) ax = plt.gca() # Calls onselect with an array of tuples defining the verticies of the polygon # Note: this is called any time the plot is clicked on! selector = PolygonSelector(plt.gca(), onselect) filter_slider = Slider(plt.axes([0.5, 0.025, 0.25, 0.04]), 'Filter', min, (max - min) / 2, valinit=filter, valstep=max / 10000) filter_slider.on_changed(update) button = Button(plt.axes([0.1, 0.025, 0.1, 0.04]), 'Save GeoTiff') button.on_clicked( lambda _: write_mask_to_file(mask, f'mask-{prod.mask_number}.tif', prod .projection, prod.geo_transform)) x = prod.vv_array y = prod.vh_array fig, axs = plt.subplots(1, 2, sharey=True, tight_layout=True) axs[0].hist(x, bins=50) axs[1].hist(y, bins=50) plt.show()