Repository: scikit-image/scikit-image

Issue:
Image wrapper class confusing for scalar data
Examples:

```
>>> from skimage import data
>>> camera = data.camera()
>>> camera.max()
Image(255, dtype=uint8)
```

it would be nicer to have

```
>>> camera.max()
255
```

that is, just a scalar. Having an "Image" returned for the max value is a bit confusing.
Is it possible to change this behavior or not? 



Discussion:
I was wondering if this was going to bite us.  I think we should revert the imread behavior, and have the returned objects go back to numpy arrays.  If people want to display images in IPython, they can construct the Image class manually.  Should I go ahead?

I'm happy for this change. I've certainly never felt the need to use the Image class...

I have also never made use of the Image class...

Agreed :+1:

:+1: 


Resolving patch:
diff --git a/skimage/io/_io.py b/skimage/io/_io.py
--- a/skimage/io/_io.py
+++ b/skimage/io/_io.py
@@ -35,28 +35,33 @@ class Image(np.ndarray):
 
     These objects have tags for image metadata and IPython display protocol
     methods for image display.
-    """
 
-    tags = {'filename': '',
-            'EXIF': {},
-            'info': {}}
+    Parameters
+    ----------
+    arr : ndarray
+        Image data.
+    kwargs : Image tags as keywords
+        Specified in the form ``tag0=value``, ``tag1=value``.
+
+    Attributes
+    ----------
+    tags : dict
+        Meta-data.
+
+    """
 
     def __new__(cls, arr, **kwargs):
         """Set the image data and tags according to given parameters.
 
-        Parameters
-        ----------
-        arr : ndarray
-            Image data.
-        kwargs : Image tags as keywords
-            Specified in the form ``tag0=value``, ``tag1=value``.
-
         """
         x = np.asarray(arr).view(cls)
-        for tag, value in Image.tags.items():
-            setattr(x, tag, kwargs.get(tag, getattr(arr, tag, value)))
+        x.tags = kwargs
+
         return x
 
+    def __array_finalize__(self, obj):
+        self.tags = getattr(obj, 'tags', {})
+
     def _repr_png_(self):
         return self._repr_image_format('png')
 
@@ -147,7 +152,7 @@ def imread(fname, as_grey=False, plugin=None, flatten=None,
     if as_grey and getattr(img, 'ndim', 0) >= 3:
         img = rgb2grey(img)
 
-    return Image(img)
+    return img
 
 
 def imread_collection(load_pattern, conserve_memory=True,


Test patch:
diff --git a/skimage/io/tests/test_collection.py b/skimage/io/tests/test_collection.py
--- a/skimage/io/tests/test_collection.py
+++ b/skimage/io/tests/test_collection.py
@@ -57,7 +57,7 @@ def test_len(self):
     def test_getitem(self):
         num = len(self.collection)
         for i in range(-num, num):
-            assert type(self.collection[i]) is ioImage
+            assert type(self.collection[i]) is np.ndarray
         assert_array_almost_equal(self.collection[0],
                                   self.collection[-num])
 
diff --git a/skimage/io/tests/test_image.py b/skimage/io/tests/test_image.py
new file mode 100644
--- /dev/null
+++ b/skimage/io/tests/test_image.py
@@ -0,0 +1,17 @@
+from skimage.io import Image
+
+from numpy.testing import assert_equal, assert_array_equal
+
+def test_tags():
+    f = Image([1, 2, 3], foo='bar', sigma='delta')
+    g = Image([3, 2, 1], sun='moon')
+    h = Image([1, 1, 1])
+
+    assert_equal(f.tags['foo'], 'bar')
+    assert_array_equal((g + 2).tags['sun'], 'moon')
+    assert_equal(h.tags, {})
+
+if __name__ == "__main__":
+    from numpy.testing import run_module_suite
+    run_module_suite()
+
diff --git a/skimage/io/tests/test_pil.py b/skimage/io/tests/test_pil.py
--- a/skimage/io/tests/test_pil.py
+++ b/skimage/io/tests/test_pil.py
@@ -6,7 +6,8 @@
 from tempfile import NamedTemporaryFile
 
 from skimage import data_dir
-from skimage.io import imread, imsave, use_plugin, reset_plugins
+from skimage.io import (imread, imsave, use_plugin, reset_plugins,
+                        Image as ioImage)
 from skimage._shared.six.moves import StringIO
 
 
@@ -83,7 +84,7 @@ def test_imread_uint16():
 @skipif(not PIL_available)
 def test_repr_png():
     img_path = os.path.join(data_dir, 'camera.png')
-    original_img = imread(img_path)
+    original_img = ioImage(imread(img_path))
     original_img_str = original_img._repr_png_()
 
     with NamedTemporaryFile(suffix='.png') as temp_png: