Source code for bb_stitcher.picking.picker

#  Licensed under the Apache License, Version 2.0 (the "License"); you may
#  not use this file except in compliance with the License. You may obtain
#  a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#  License for the specific language governing permissions and limitations
#  under the License.
"""Initialise a GUI to pick various points on images.

This Module provides a class to initialise a GUI, to pick various points
on one or multiple images.
"""
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

import bb_stitcher.helpers as helpers
import bb_stitcher.picking.draggables as draggs


[docs]class PointPicker(object): """GUI for picking points.""" def __init__(self): """Initialise GUI to pick various point on an image.""" mpl.rcParams['keymap.quit'] = ['q', 'ctrl+w', 'cmd+w'] mpl.rcParams['keymap.home'] = ['h', 'home'] mpl.rcParams['keymap.zoom'] = ['z', 'o'] mpl.rcParams['keymap.save'] = ['ctrl+s']
[docs] def pick(self, images, all_pts=True): """Initialise a GUI to pick points on multiple images. A matplot GUI will be initialised, where the user can pick multiple points on the **N** ``images``. Afterwards the :obj:`PointPicker` will return **N** ndarrays, which holds the coordinates of the marked points. Each ndarray holds the points for one image. Args: images (list(ndarray)): List of images (ndarray) all_pts (bool): If ``True`` all points will be returned and else just 'selected' \ points will be returned. Returns: list(ndarray): Returns a List of length **N**, where each cell contains a ndarray \ *(M,2)*, which holds the coordinates of the *M* marked points per image. """ imgs_a = [] for img in images: imgs_a.append(helpers.add_alpha_channel(img)) count_images = len(imgs_a) # creating one list per image, which will hold the draggable marks # e.g. for 2 images: # dms_per_image = [[<dragableMarks first image>],[<dragableMarks second image>]] dms_per_image = [] for __ in range(count_images): dms_per_image.append(draggs.DraggableMarkList()) def _on_click(event): # double click left mouse button if event.button == 1 and event.dblclick: for i, ax in enumerate(axes): if event.inaxes == ax: marker, = ax.plot( event.xdata, event.ydata, 'xr', markersize=10, markeredgewidth=2) dm = draggs.DraggableMark(marker, imgs_a[i]) dm.connect() dms_per_image[i].append(dm) fig.canvas.draw() fig, axes = plt.subplots( nrows=1, ncols=count_images, tight_layout=False) fig.canvas.mpl_connect('button_press_event', _on_click) fig.canvas.set_window_title('Point Picker | r-refine point | s-select point | z-zoom | ' 'p-pan | q-quit/finish') # if the nrows == 1 and ncols == 1 the function of plt.subplots returns a single # class 'matplotlib.axes._subplots.AxesSubplot' but we want always an array if count_images == 1: axes = np.array([axes]) for i, image in enumerate(imgs_a): # don't draw y-axis on every image, just on first image if i > 0: plt.setp(axes[i].get_yticklabels(), visible=False) axes[i].imshow(image) plt.show() points = [] for i, dms in enumerate(dms_per_image): points_per_image = dms.get_points(all_pts=all_pts) points.append(points_per_image) return points