Skip to content

Commit

Permalink
Merge pull request #1072 from blink1073/add-viewer-tests
Browse files Browse the repository at this point in the history
Add Viewer Tests
  • Loading branch information
jni committed Jul 18, 2014
2 parents a2e2895 + 243d550 commit 0c31487
Show file tree
Hide file tree
Showing 14 changed files with 659 additions and 68 deletions.
2 changes: 1 addition & 1 deletion skimage/viewer/canvastools/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def _on_key_press(self, event):
@property
def geometry(self):
"""Geometry information that gets passed to callback functions."""
raise NotImplementedError
return None


class ToolHandles(object):
Expand Down
4 changes: 2 additions & 2 deletions skimage/viewer/canvastools/linetool.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def on_enter(pts):

@property
def end_points(self):
return self._end_pts
return self._end_pts.astype(int)

@end_points.setter
def end_points(self, pts):
Expand Down Expand Up @@ -191,7 +191,7 @@ def _shrink_scan_line(self):
self.callback_on_change(self.geometry)


if __name__ == '__main__':
if __name__ == '__main__': # pragma: no cover
import matplotlib.pyplot as plt
from skimage import data

Expand Down
2 changes: 1 addition & 1 deletion skimage/viewer/canvastools/painttool.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def at(self, row, col):
return [slice(ymin, ymax), slice(xmin, xmax)]


if __name__ == '__main__':
if __name__ == '__main__': # pragma: no cover
np.testing.rundocs()
from skimage import data

Expand Down
2 changes: 1 addition & 1 deletion skimage/viewer/canvastools/recttool.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def geometry(self):
return self.extents


if __name__ == '__main__':
if __name__ == '__main__': # pragma: no cover
import matplotlib.pyplot as plt
from skimage import data

Expand Down
3 changes: 2 additions & 1 deletion skimage/viewer/plugins/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ def closeEvent(self, event):

def clean_up(self):
self.remove_image_artists()
self.image_viewer.plugins.remove(self)
if self in self.image_viewer.plugins:
self.image_viewer.plugins.remove(self)
self.image_viewer.reset_image()
self.image_viewer.redraw()

Expand Down
22 changes: 12 additions & 10 deletions skimage/viewer/plugins/lineprofile.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def attach(self, image_viewer):
if self._limit_type == 'image':
self.limits = (np.min(image), np.max(image))
elif self._limit_type == 'dtype':
self._limit_type = dtype_range[image.dtype.type]
self.limits = dtype_range[image.dtype.type]
elif self._limit_type is None or len(self._limit_type) == 2:
self.limits = self._limit_type
else:
Expand Down Expand Up @@ -91,6 +91,7 @@ def get_profiles(self):
profile: list of 1d arrays
Profile of intensity values. Length 1 (grayscale) or 3 (rgb).
"""
self._update_data()
profiles = [data.get_ydata() for data in self.profile]
return self.line_tool.end_points, profiles

Expand All @@ -103,8 +104,15 @@ def _autoscale_view(self):
def line_changed(self, end_points):
x, y = np.transpose(end_points)
self.line_tool.end_points = end_points
scan = measure.profile_line(self.image_viewer.original_image,
*end_points[:, ::-1],
self._update_data()
self.ax.relim()

self._autoscale_view()
self.redraw()

def _update_data(self):
scan = measure.profile_line(self.image_viewer.image,
*self.line_tool.end_points[:, ::-1],
linewidth=self.line_tool.linewidth)
self.scan_data = scan
if scan.ndim == 1:
Expand All @@ -117,11 +125,6 @@ def line_changed(self, end_points):
self.profile[i].set_xdata(np.arange(scan.shape[0]))
self.profile[i].set_ydata(scan[:, i])

self.ax.relim()

self._autoscale_view()
self.redraw()

def reset_axes(self, scan_data):
# Clear lines out
for line in self.ax.lines:
Expand All @@ -147,7 +150,7 @@ def output(self):
The line scan values across the image.
"""
end_points = self.line_tool.end_points
line_image = np.zeros(self.image_viewer.original_image.shape[:2],
line_image = np.zeros(self.image_viewer.image.shape[:2],
np.uint8)
width = self.line_tool.linewidth
if width > 1:
Expand All @@ -162,4 +165,3 @@ def output(self):
rr, cc = draw.line(y1, x1, y2, x2)
line_image[rr, cc] = 255
return line_image, self.scan_data

185 changes: 185 additions & 0 deletions skimage/viewer/tests/test_plugins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# -*- coding: utf-8 -*-
import numpy as np
import skimage
import skimage.data as data
from skimage.filter.rank import median
from skimage.morphology import disk
from numpy.testing import assert_equal, assert_allclose, assert_almost_equal
from numpy.testing.decorators import skipif

try:
from skimage.viewer.qt import qt_api
from skimage.viewer import ImageViewer
from skimage.viewer.plugins import (
LineProfile, Measure, CannyPlugin, LabelPainter, Crop, ColorHistogram,
PlotPlugin)
from skimage.viewer.plugins.base import Plugin
from skimage.viewer.widgets import Slider
viewer_available = not qt_api is None
except ImportError:
viewer_available = False


def setup_line_profile(image, limits='image'):
viewer = ImageViewer(skimage.img_as_float(image))
plugin = LineProfile(limits=limits)
viewer += plugin
return plugin


@skipif(not viewer_available)
def test_line_profile():
""" Test a line profile using an ndim=2 image"""
plugin = setup_line_profile(data.camera())
line_image, scan_data = plugin.output()
for inp in [line_image.nonzero()[0].size,
line_image.sum() / line_image.max(),
scan_data.size]:
assert_equal(inp, 172)
assert_equal(line_image.shape, (512, 512))
assert_allclose(scan_data.max(), 0.9176, rtol=1e-3)
assert_allclose(scan_data.mean(), 0.2812, rtol=1e-3)


@skipif(not viewer_available)
def test_line_profile_rgb():
""" Test a line profile using an ndim=3 image"""
plugin = setup_line_profile(data.chelsea(), limits=None)
for i in range(6):
plugin.line_tool._thicken_scan_line()
line_image, scan_data = plugin.output()
assert_equal(line_image[line_image == 128].size, 750)
assert_equal(line_image[line_image == 255].size, 151)
assert_equal(line_image.shape, (300, 451))
assert_equal(scan_data.shape, (151, 3))
assert_allclose(scan_data.max(), 0.772, rtol=1e-3)
assert_allclose(scan_data.mean(), 0.4359, rtol=1e-3)


@skipif(not viewer_available)
def test_line_profile_dynamic():
"""Test a line profile updating after an image transform"""
image = data.coins()[:-50, :] # shave some off to make the line lower
image = skimage.img_as_float(image)
viewer = ImageViewer(image)

lp = LineProfile(limits='dtype')
viewer += lp

line = lp.get_profiles()[-1][0]
assert line.size == 129
assert_almost_equal(np.std(viewer.image), 0.208, 3)
assert_almost_equal(np.std(line), 0.229, 3)
assert_almost_equal(np.max(line) - np.min(line), 0.725, 1)

viewer.image = skimage.img_as_float(median(image,
selem=disk(radius=3)))

line = lp.get_profiles()[-1][0]
assert_almost_equal(np.std(viewer.image), 0.198, 3)
assert_almost_equal(np.std(line), 0.220, 3)
assert_almost_equal(np.max(line) - np.min(line), 0.639, 1)


@skipif(not viewer_available)
def test_measure():
image = data.camera()
viewer = ImageViewer(image)
m = Measure()
viewer += m

m.line_changed([(0, 0), (10, 10)])
assert_equal(str(m._length.text), '14.1')
assert_equal(str(m._angle.text[:5]), '135.0')


@skipif(not viewer_available)
def test_canny():
image = data.camera()
viewer = ImageViewer(image)
c = CannyPlugin()
viewer += c

canny_edges = viewer.show(False)
viewer.close()
edges = canny_edges[0][0]
assert edges.sum() == 2852


@skipif(not viewer_available)
def test_label_painter():
image = data.camera()
moon = data.moon()
viewer = ImageViewer(image)
lp = LabelPainter()
viewer += lp

assert_equal(lp.radius, 5)
lp.label = 1
assert_equal(str(lp.label), '1')
lp.label = 2
assert_equal(str(lp.paint_tool.label), '2')
assert_equal(lp.paint_tool.radius, 5)
lp._on_new_image(moon)
assert_equal(lp.paint_tool.shape, moon.shape)


@skipif(not viewer_available)
def test_crop():
image = data.camera()
viewer = ImageViewer(image)
c = Crop()
viewer += c

c.crop((0, 100, 0, 100))
assert_equal(viewer.image.shape, (101, 101))


@skipif(not viewer_available)
def test_color_histogram():
image = skimage.img_as_float(data.load('color.png'))
viewer = ImageViewer(image)
ch = ColorHistogram(dock='right')
viewer += ch

assert_almost_equal(viewer.image.std(), 0.352, 3),
ch.ab_selected((0, 100, 0, 100)),
assert_almost_equal(viewer.image.std(), 0.325, 3)


@skipif(not viewer_available)
def test_plot_plugin():
viewer = ImageViewer(data.moon())
plugin = PlotPlugin(image_filter=lambda x: x)
viewer += plugin

assert_equal(viewer.image, data.moon())
plugin._update_original_image(data.coins())
assert_equal(viewer.image, data.coins())
viewer.close()


@skipif(not viewer_available)
def test_plugin():
img = skimage.img_as_float(data.moon())
viewer = ImageViewer(img)

def median_filter(img, radius=3):
return median(img, selem=disk(radius=radius))

plugin = Plugin(image_filter=median_filter)
viewer += plugin

plugin += Slider('radius', 1, 5)

assert_almost_equal(np.std(viewer.image), 12.556, 3)

plugin.filter_image()

assert_almost_equal(np.std(viewer.image), 12.931, 3)

plugin.show()
plugin.close()
plugin.clean_up()
img, _ = plugin.output()
assert_equal(img, viewer.image)

0 comments on commit 0c31487

Please sign in to comment.