mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-29 23:08:44 +08:00
Fixed Python 3 import errors, added alpha and rgba properties
This commit is contained in:
+70
-23
@@ -1,10 +1,7 @@
|
||||
import os
|
||||
import imghdr
|
||||
import shutil
|
||||
from collections import namedtuple
|
||||
from io import BytesIO
|
||||
from urlparse import urlparse
|
||||
from urllib2 import urlopen
|
||||
|
||||
import numpy as np
|
||||
from skimage import io
|
||||
@@ -13,6 +10,10 @@ from skimage.transform import resize
|
||||
from skimage.color import color_dict
|
||||
from skimage._shared import six
|
||||
|
||||
from six.moves.urllib_parse import urlparse
|
||||
from six.moves.urllib import request
|
||||
urlopen = request.urlopen
|
||||
|
||||
|
||||
# Convert colors from `skimage.color` to uint8 and allow access through
|
||||
# dict or a named tuple.
|
||||
@@ -75,15 +76,18 @@ class Pixel(object):
|
||||
Vertical coordinate of this pixel (bottom = 0).
|
||||
rgb : tuple
|
||||
RGB tuple with red, green, and blue components (0-255)
|
||||
alpha : int
|
||||
Transparency component (0-255), 255 (opaque) by default
|
||||
|
||||
"""
|
||||
def __init__(self, pic, array, x, y, rgb):
|
||||
def __init__(self, pic, array, x, y, rgb, alpha=255):
|
||||
self._picture = pic
|
||||
self._x = x
|
||||
self._y = y
|
||||
self._red = self._validate(rgb[0])
|
||||
self._green = self._validate(rgb[1])
|
||||
self._blue = self._validate(rgb[2])
|
||||
self._alpha = self._validate(alpha)
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
@@ -125,6 +129,16 @@ class Pixel(object):
|
||||
self._blue = self._validate(value)
|
||||
self._setpixel()
|
||||
|
||||
@property
|
||||
def alpha(self):
|
||||
"""The transparency component of the pixel (0-255)."""
|
||||
return self._alpha
|
||||
|
||||
@alpha.setter
|
||||
def alpha(self, value):
|
||||
self._alpha = self._validate(value)
|
||||
self._setpixel()
|
||||
|
||||
@property
|
||||
def rgb(self):
|
||||
"""The RGB color components of the pixel (3 values 0-255)."""
|
||||
@@ -132,7 +146,21 @@ class Pixel(object):
|
||||
|
||||
@rgb.setter
|
||||
def rgb(self, value):
|
||||
self._red, self._green, self._blue = (self._validate(v) for v in value)
|
||||
if len(value) == 4:
|
||||
self.rgba = value
|
||||
else:
|
||||
self._red, self._green, self._blue = (self._validate(v) for v in value)
|
||||
self._alpha = 255
|
||||
self._setpixel()
|
||||
|
||||
@property
|
||||
def rgba(self):
|
||||
"""The RGB color and transparency components of the pixel (4 values 0-255)."""
|
||||
return (self.red, self.green, self.blue, self.alpha)
|
||||
|
||||
@rgba.setter
|
||||
def rgba(self, value):
|
||||
self._red, self._green, self._blue, self._alpha = (self._validate(v) for v in value)
|
||||
self._setpixel()
|
||||
|
||||
def _validate(self, value):
|
||||
@@ -149,16 +177,16 @@ class Pixel(object):
|
||||
|
||||
def _setpixel(self):
|
||||
# RGB + alpha
|
||||
self._picture.xy_array[self._x, self._y] = self.rgb + (255,)
|
||||
self._picture.xy_array[self._x, self._y] = self.rgba
|
||||
self._picture._array_modified()
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Pixel):
|
||||
return self.rgb == other.rgb
|
||||
return self.rgba == other.rgba
|
||||
|
||||
def __repr__(self):
|
||||
args = self.red, self.green, self.blue
|
||||
return "Pixel(red={0}, green={1}, blue={2})".format(*args)
|
||||
args = self.red, self.green, self.blue, self.alpha
|
||||
return "Pixel(red={0}, green={1}, blue={2}, alpha={3})".format(*args)
|
||||
|
||||
|
||||
class Picture(object):
|
||||
@@ -169,9 +197,9 @@ class Picture(object):
|
||||
path : str
|
||||
Path to an image file to load.
|
||||
array : array
|
||||
Raw RGB image data [0-255], with origin at top-left.
|
||||
Raw RGB or RGBA image data [0-255], with origin at top-left.
|
||||
xy_array : array
|
||||
Raw RGB image data [0-255], with origin at bottom-left.
|
||||
Raw RGB or RGBA image data [0-255], with origin at bottom-left.
|
||||
|
||||
Examples
|
||||
--------
|
||||
@@ -215,24 +243,21 @@ class Picture(object):
|
||||
msg = "Must provide a single keyword arg (path, array, xy_array)."
|
||||
ValueError(msg)
|
||||
elif path is not None:
|
||||
self.array = img_as_ubyte(io.imread(path))
|
||||
self._path = path
|
||||
|
||||
# Copy to in-memory buffer to get format (in case path was a url)
|
||||
if urlparse(path).scheme == "":
|
||||
self.array = img_as_ubyte(io.imread(path))
|
||||
self._format = imghdr.what(path)
|
||||
else:
|
||||
data = BytesIO()
|
||||
shutil.copyfileobj(urlopen(path), data)
|
||||
data.seek(0)
|
||||
self._format = imghdr.what(data)
|
||||
del data
|
||||
data = urlopen(path).read()
|
||||
self.array = img_as_ubyte(io.imread(BytesIO(data)))
|
||||
self._format = imghdr.what("", h=data)
|
||||
elif array is not None:
|
||||
self.array = array
|
||||
elif xy_array is not None:
|
||||
self.xy_array = xy_array
|
||||
|
||||
# Force RGBA internally (max alpha)
|
||||
# Force RGBA internally (use max alpha)
|
||||
if self.array.shape[-1] == 3:
|
||||
self.array = np.insert(self.array, 3, values=255, axis=2)
|
||||
|
||||
@@ -245,14 +270,18 @@ class Picture(object):
|
||||
size : tuple
|
||||
Width and height of the picture in pixels.
|
||||
color : tuple or str
|
||||
RGB tuple with the fill color for the picture [0-255] or a valid
|
||||
RGB or RGBA tuple with the fill color for the picture [0-255] or a valid
|
||||
key in `color_dict`.
|
||||
"""
|
||||
if isinstance(color, six.string_types):
|
||||
color = color_dict[color]
|
||||
rgb_size = tuple(size) + (3,)
|
||||
rgb_size = tuple(size) + (len(color),)
|
||||
array = np.ones(rgb_size, dtype=np.uint8) * color
|
||||
array = np.insert(array, 3, values=255, axis=2)
|
||||
|
||||
# Force RGBA internally (use max alpha)
|
||||
if array.shape[-1] == 3:
|
||||
array = np.insert(array, 3, values=255, axis=2)
|
||||
|
||||
return Picture(array=array)
|
||||
|
||||
@property
|
||||
@@ -396,13 +425,31 @@ class Picture(object):
|
||||
def blue(self, value):
|
||||
self._set_channel(2, value)
|
||||
|
||||
@property
|
||||
def alpha(self):
|
||||
"""The transparency component of the pixel (0-255)."""
|
||||
return self._get_channel(3).ravel()
|
||||
|
||||
@alpha.setter
|
||||
def alpha(self, value):
|
||||
self._set_channel(3, value)
|
||||
|
||||
@property
|
||||
def rgb(self):
|
||||
"""The RGB color components of the pixel (3 values 0-255)."""
|
||||
return self.xy_array
|
||||
return self.xy_array[:, :, :3]
|
||||
|
||||
@rgb.setter
|
||||
def rgb(self, value):
|
||||
self.xy_array[:, :, :3] = value
|
||||
|
||||
@property
|
||||
def rgba(self):
|
||||
"""The RGBA color components of the pixel (4 values 0-255)."""
|
||||
return self.xy_array
|
||||
|
||||
@rgba.setter
|
||||
def rgba(self, value):
|
||||
self.xy_array[:] = value
|
||||
|
||||
def __iter__(self):
|
||||
|
||||
@@ -13,8 +13,8 @@ IMAGE_PATH = os.path.join(data_dir, "chelsea.png")
|
||||
SMALL_IMAGE_PATH = os.path.join(data_dir, "block.png")
|
||||
|
||||
|
||||
def _array_2d_to_RGB(array):
|
||||
return np.tile(array[:, :, np.newaxis], (1, 1, 3))
|
||||
def _array_2d_to_RGBA(array):
|
||||
return np.tile(array[:, :, np.newaxis], (1, 1, 4))
|
||||
|
||||
|
||||
def test_xy_to_array_origin():
|
||||
@@ -82,6 +82,28 @@ def test_pixel_rgb():
|
||||
for i, channel in enumerate((pixel.red, pixel.green, pixel.blue)):
|
||||
assert_equal(channel, i + 3)
|
||||
|
||||
pixel.rgb = np.arange(4)
|
||||
assert_equal(pixel.rgb, np.arange(3))
|
||||
|
||||
|
||||
def test_pixel_rgba():
|
||||
pic = novice.Picture.from_size((3, 3), color=(10, 10, 10))
|
||||
pixel = pic[0, 0]
|
||||
pixel.rgba = np.arange(4)
|
||||
|
||||
assert_equal(pixel.rgba, np.arange(4))
|
||||
for i, channel in enumerate((pixel.red, pixel.green, pixel.blue, pixel.alpha)):
|
||||
assert_equal(channel, i)
|
||||
|
||||
pixel.red = 3
|
||||
pixel.green = 4
|
||||
pixel.blue = 5
|
||||
pixel.alpha = 6
|
||||
assert_equal(pixel.rgba, np.arange(4) + 3)
|
||||
|
||||
for i, channel in enumerate((pixel.red, pixel.green, pixel.blue, pixel.alpha)):
|
||||
assert_equal(channel, i + 3)
|
||||
|
||||
|
||||
def test_pixel_rgb_float():
|
||||
pixel = novice.Picture.from_size((1, 1))[0, 0]
|
||||
@@ -89,6 +111,12 @@ def test_pixel_rgb_float():
|
||||
assert_equal(pixel.rgb, (1, 1, 1))
|
||||
|
||||
|
||||
def test_pixel_rgba_float():
|
||||
pixel = novice.Picture.from_size((1, 1))[0, 0]
|
||||
pixel.rgba = (1.1, 1.1, 1.1, 1.1)
|
||||
assert_equal(pixel.rgba, (1, 1, 1, 1))
|
||||
|
||||
|
||||
def test_modified_on_set():
|
||||
pic = novice.Picture(SMALL_IMAGE_PATH)
|
||||
pic[0, 0] = (1, 1, 1)
|
||||
@@ -157,7 +185,7 @@ def test_indexing():
|
||||
|
||||
|
||||
def test_picture_slice():
|
||||
array = _array_2d_to_RGB(np.arange(0, 10)[np.newaxis, :])
|
||||
array = _array_2d_to_RGBA(np.arange(0, 10)[np.newaxis, :])
|
||||
pic = novice.Picture(array=array)
|
||||
|
||||
x_slice = slice(3, 8)
|
||||
@@ -167,7 +195,7 @@ def test_picture_slice():
|
||||
|
||||
def test_move_slice():
|
||||
h, w = 3, 12
|
||||
array = _array_2d_to_RGB(np.linspace(0, 255, h * w).reshape(h, w))
|
||||
array = _array_2d_to_RGBA(np.linspace(0, 255, h * w).reshape(h, w))
|
||||
array = array.astype(np.uint8)
|
||||
|
||||
pic = novice.Picture(array=array)
|
||||
@@ -187,7 +215,7 @@ def test_move_slice():
|
||||
|
||||
def test_negative_index():
|
||||
n = 10
|
||||
array = _array_2d_to_RGB(np.arange(0, n)[np.newaxis, :])
|
||||
array = _array_2d_to_RGBA(np.arange(0, n)[np.newaxis, :])
|
||||
# Test both x and y indices.
|
||||
pic = novice.Picture(array=array)
|
||||
assert pic[-1, 0] == pic[n - 1, 0]
|
||||
@@ -197,7 +225,7 @@ def test_negative_index():
|
||||
|
||||
def test_negative_slice():
|
||||
n = 10
|
||||
array = _array_2d_to_RGB(np.arange(0, n)[np.newaxis, :])
|
||||
array = _array_2d_to_RGBA(np.arange(0, n)[np.newaxis, :])
|
||||
# Test both x and y slices.
|
||||
pic = novice.Picture(array=array)
|
||||
assert pic[-3:, 0] == pic[n - 3:, 0]
|
||||
@@ -207,7 +235,7 @@ def test_negative_slice():
|
||||
|
||||
def test_getitem_with_step():
|
||||
h, w = 5, 5
|
||||
array = _array_2d_to_RGB(np.linspace(0, 255, h * w).reshape(h, w))
|
||||
array = _array_2d_to_RGBA(np.linspace(0, 255, h * w).reshape(h, w))
|
||||
pic = novice.Picture(array=array)
|
||||
sliced_pic = pic[::2, ::2]
|
||||
assert sliced_pic == novice.Picture(array=array[::2, ::2])
|
||||
@@ -267,6 +295,12 @@ def test_pixel_blue_raises():
|
||||
pixel.blue = 256
|
||||
|
||||
|
||||
@raises(ValueError)
|
||||
def test_pixel_alpha_raises():
|
||||
pixel = novice.Picture.from_size((1, 1))[0, 0]
|
||||
pixel.alpha = 256
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy import testing
|
||||
testing.run_module_suite()
|
||||
|
||||
Reference in New Issue
Block a user