diff --git a/skimage/viewer/plugins/lineprofile.py b/skimage/viewer/plugins/lineprofile.py deleted file mode 100644 index 9dee09e2..00000000 --- a/skimage/viewer/plugins/lineprofile.py +++ /dev/null @@ -1,240 +0,0 @@ -import numpy as np -import scipy.ndimage as ndi -from skimage.util.dtype import dtype_range - -from .plotplugin import PlotPlugin - - -__all__ = ['LineProfile'] - - -class LineProfile(PlotPlugin): - """Plugin to compute interpolated intensity under a scan line on an image. - - See PlotPlugin and Plugin classes for additional details. - - Parameters - ---------- - linewidth : float - Line width for interpolation. Wider lines average over more pixels. - epsilon : float - Maximum pixel distance allowed when selecting end point of scan line. - limits : tuple or {None, 'image', 'dtype'} - (minimum, maximum) intensity limits for plotted profile. The following - special values are defined: - - None : rescale based on min/max intensity along selected scan line. - 'image' : fixed scale based on min/max intensity in image. - 'dtype' : fixed scale based on min/max intensity of image dtype. - """ - name = 'Line Profile' - draws_on_image = True - - def __init__(self, linewidth=1, epsilon=5, limits='image', **kwargs): - super(LineProfile, self).__init__(**kwargs) - self.linewidth = linewidth - self.epsilon = epsilon - self._active_pt = None - self._limit_type = limits - self.line_kwargs = dict(color='y', lw=linewidth, alpha=0.5, marker='s', - markersize=5, solid_capstyle='butt') - print self.help() - - def attach(self, image_viewer): - super(LineProfile, self).attach(image_viewer) - - image = image_viewer.original_image - - if self._limit_type == 'image': - self.limits = (np.min(image), np.max(image)) - elif self._limit_type == 'dtype': - self.self._limit_type = dtype_range[image.dtype.type] - elif self._limit_type is None or len(self._limit_type) == 2: - self.limits = self._limit_type - else: - raise ValueError("Unrecognized `limits`: %s" % self._limit_type) - - if not self._limit_type is None: - self.ax.set_ylim(self.limits) - - h, w = image.shape - self._init_end_pts = np.array([[w/3, h/2], [2*w/3, h/2]]) - self.end_pts = self._init_end_pts.copy() - - x, y = np.transpose(self.end_pts) - self.scan_line = image_viewer.ax.plot(x, y, **self.line_kwargs)[0] - self.artists.append(self.scan_line) - - scan_data = profile_line(image, self.end_pts) - self.profile = self.ax.plot(scan_data, 'k-')[0] - self._autoscale_view() - - self.connect_image_event('key_press_event', self.on_key_press) - self.connect_image_event('button_press_event', self.on_mouse_press) - self.connect_image_event('button_release_event', self.on_mouse_release) - self.connect_image_event('motion_notify_event', self.on_move) - self.connect_image_event('scroll_event', self.on_scroll) - - self.image_viewer.redraw() - - def help(self): - helpstr = ("Line profile tool", - "+ and - keys or mouse scroll changes width of scan line.", - "Select and drag ends of the scan line to adjust it.") - return '\n'.join(helpstr) - - def get_profile(self): - """Return intensity profile of the selected line. - - Returns - ------- - end_pts: (2, 2) array - The positions ((x1, y1), (x2, y2)) of the line ends. - profile: 1d array - Profile of intensity values. - """ - end_pts = self.scan_line.get_xydata() - profile = self.profile.get_ydata() - return end_pts, profile - - def on_scroll(self, event): - if not event.inaxes: return - if event.button == 'up': - self._thicken_scan_line() - elif event.button == 'down': - self._shrink_scan_line() - - def on_key_press(self, event): - if not event.inaxes: return - elif event.key == '+': - self._thicken_scan_line() - elif event.key == '-': - self._shrink_scan_line() - elif event.key == 'r': - self.reset() - - def _thicken_scan_line(self): - self.linewidth += 1 - self.line_changed(None, None) - - def _shrink_scan_line(self): - if self.linewidth > 1: - self.linewidth -= 1 - self.line_changed(None, None) - - def _autoscale_view(self): - if self.limits is None: - self.ax.autoscale_view(tight=True) - else: - self.ax.autoscale_view(scaley=False, tight=True) - - def get_pt_under_cursor(self, event): - """Return index of the end point under cursor, if sufficiently close""" - xy = np.asarray(self.scan_line.get_xydata()) - xyt = self.scan_line.get_transform().transform(xy) - xt, yt = xyt[:, 0], xyt[:, 1] - d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2) - indseq = np.nonzero(np.equal(d, np.amin(d)))[0] - ind = indseq[0] - if d[ind] >= self.epsilon: - ind = None - return ind - - def on_mouse_press(self, event): - if event.button != 1: return - if event.inaxes==None: return - self._active_pt = self.get_pt_under_cursor(event) - - def on_mouse_release(self, event): - if event.button != 1: return - self._active_pt = None - - def on_move(self, event): - if event.button != 1: return - if self._active_pt is None: return - if not self.image_viewer.ax.in_axes(event): return - x,y = event.xdata, event.ydata - self.line_changed(x, y) - - def reset(self): - self.end_pts = self._init_end_pts.copy() - self.scan_line.set_data(np.transpose(self.end_pts)) - self.line_changed(None, None) - - def line_changed(self, x, y): - if x is not None: - self.end_pts[self._active_pt, :] = x, y - self.scan_line.set_data(np.transpose(self.end_pts)) - self.scan_line.set_linewidth(self.linewidth) - - scan = profile_line(self.image_viewer.original_image, self.end_pts, - linewidth=self.linewidth) - self.profile.set_xdata(np.arange(scan.shape[0])) - self.profile.set_ydata(scan) - - self.ax.relim() - - if self.useblit: - self.image_viewer.canvas.restore_region(self.img_background) - self.ax.draw_artist(self.scan_line) - self.ax.draw_artist(self.profile) - self.image_viewer.canvas.blit(self.image_viewer.ax.bbox) - - self._autoscale_view() - - self.image_viewer.redraw() - self.redraw() - - -def profile_line(img, end_pts, linewidth=1): - """Return the intensity profile of an image measured along a scan line. - - Parameters - ---------- - img : 2d array - The image. - end_pts: (2, 2) list - End points ((x1, y1), (x2, y2)) of scan line. - linewidth: int - Width of the scan, perpendicular to the line - - Returns - ------- - return_value : array - The intensity profile along the scan line. The length of the profile - is the ceil of the computed length of the scan line. - """ - point1, point2 = end_pts - x1, y1 = point1 = np.asarray(point1, dtype = float) - x2, y2 = point2 = np.asarray(point2, dtype = float) - dx, dy = point2 - point1 - - # Quick calculation if perfectly horizontal or vertical (remove?) - if x1 == x2: - pixels = img[min(y1, y2) : max(y1, y2)+1, - x1 - linewidth / 2 : x1 + linewidth / 2 + 1] - intensities = pixels.mean(axis = 1) - return intensities - elif y1 == y2: - pixels = img[y1 - linewidth / 2 : y1 + linewidth / 2 + 1, - min(x1, x2) : max(x1, x2)+1] - intensities = pixels.mean(axis = 0) - return intensities - - theta = np.arctan2(dy,dx) - a = dy/dx - b = y1 - a * x1 - length = np.hypot(dx, dy) - - line_x = np.linspace(min(x1, x2), max(x1, x2), np.ceil(length)) - line_y = line_x * a + b - y_width = abs(linewidth * np.cos(theta)/2) - perp_ys = np.array([np.linspace(yi - y_width, - yi + y_width, linewidth) for yi in line_y]) - perp_xs = - a * perp_ys + (line_x + a * line_y)[:, np.newaxis] - - perp_lines = np.array([perp_ys, perp_xs]) - pixels = ndi.map_coordinates(img, perp_lines) - intensities = pixels.mean(axis=1) - - return intensities diff --git a/skimage/viewer/plugins/plotplugin.py b/skimage/viewer/plugins/plotplugin.py deleted file mode 100644 index fa06088d..00000000 --- a/skimage/viewer/plugins/plotplugin.py +++ /dev/null @@ -1,50 +0,0 @@ -import numpy as np -from PyQt4 import QtGui - -import matplotlib.pyplot as plt - -from ..utils import MatplotlibCanvas -from .base import Plugin - - -class PlotCanvas(MatplotlibCanvas): - """Canvas for displaying images. - - This canvas derives from Matplotlib, and has attributes `fig` and `ax`, - which point to Matplotlib figure and axes. - """ - def __init__(self, parent, height, width, **kwargs): - self.fig, self.ax = plt.subplots(figsize=(height, width), **kwargs) - super(PlotCanvas, self).__init__(parent, self.fig, **kwargs) - self.setMinimumHeight(150) - -class PlotPlugin(Plugin): - """Plugin for ImageViewer that contains a plot canvas. - - Base class for plugins that contain a Matplotlib plot canvas, which can, - for example, display an image histogram. - - See base Plugin class for additional details. - """ - - def attach(self, image_viewer): - super(PlotPlugin, self).attach(image_viewer) - # Add plot for displaying intensity profile. - self.add_plot() - - def redraw(self): - """Redraw plot.""" - self.canvas.draw_idle() - - def add_plot(self, height=4, width=4): - self.canvas = PlotCanvas(self, height, width) - self.fig = self.canvas.fig - #TODO: Converted color is slightly different than Qt background. - qpalette = QtGui.QPalette() - qcolor = qpalette.color(QtGui.QPalette.Window) - bgcolor = qcolor.toRgb().value() - if np.isscalar(bgcolor): - bgcolor = str(bgcolor / 255.) - self.fig.patch.set_facecolor(bgcolor) - self.ax = self.canvas.ax - self.layout.addWidget(self.canvas, self.row, 0) diff --git a/viewer_examples/plugins/lineprofile.py b/viewer_examples/plugins/lineprofile.py deleted file mode 100644 index 2f1b2cdc..00000000 --- a/viewer_examples/plugins/lineprofile.py +++ /dev/null @@ -1,9 +0,0 @@ -from skimage import data -from skimage.viewer import ImageViewer -from skimage.viewer.plugins.lineprofile import LineProfile - - -image = data.camera() -viewer = ImageViewer(image) -viewer += LineProfile() -viewer.show()