def _warp(self, geometry, gsd, dem, proj, dtype, buf=0):
transpix = self._transpix(geometry, gsd, dem, proj)
xmin, xmax, ymin, ymax = (int(max(transpix[0,:,:].min() - buf, 0)),
int(min(transpix[0,:,:].max() + buf, self.shape[1])),
int(max(transpix[1,:,:].min() - buf, 0)),
int(min(transpix[1,:,:].max() + buf, self.shape[2])))
transpix[0,:,:] = transpix[0,:,:] - xmin
transpix[1,:,:] = transpix[1,:,:] - ymin
data = self[:,xmin:xmax, ymin:ymax].compute(get=dask.get) # read(quiet=True)
if data.shape[1]*data.shape[2] > 0:
return np.rollaxis(np.dstack([tf.warp(data[b,:,:], transpix, preserve_range=True, order=3, mode="edge") for b in xrange(data.shape[0])]).astype(dtype), 2, 0)
else:
return np.zeros((data.shape[0], transpix.shape[1], transpix.shape[2]))
python类warp()的实例源码
def TF_shear(x, shear=0.0):
assert len(x.shape) == 3
h, w, nc = x.shape
# Perform shear
xc = warp(x, AffineTransform(shear=shear), mode='edge')
return xc
def TF_translate(img, x, y):
return warp(img, AffineTransform(translation=(x, y)), mode='edge')
def warp_image(self, tile: HipsTile) -> np.ndarray:
"""Warp a HiPS tile and a sky image."""
return warp(
tile.data,
self.projection(tile),
output_shape=self.geometry.shape,
preserve_range=True,
)
def __init__(self, img,
ransac_options=RANSAC_OPTIONS,
opt_method=OPTIMIZATION_METHOD,
opt_options=OPTIMIZATION_OPTIONS,
mask=None,
min_line_length=20,
max_line_gap=3,
angle_tolerance=30
):
self.angle_tolerance = angle_tolerance
self.ransac_options = ransac_options
self.opt_method = opt_method
self.opt_options = opt_options
self.data = img
self.mask = mask
if mask is not None and np.all(mask == False):
self.mask = None
self.l, self.w = img.shape[:2]
self.lines = _extract_lines(img,
mask=self.mask,
min_line_length=min_line_length,
max_line_gap=max_line_gap)
if len(self.lines) > 0:
self.vlines, self.hlines = _vh_lines(self.lines,
ransac_options=self.ransac_options,
angle_lo=90 - self.angle_tolerance,
angle_hi=90 + self.angle_tolerance
)
lrud = _solve_lrud(self.hlines, self.vlines, self.w, self.l,
opt_options=opt_options,
opt_method=opt_method)
self.dl, self.dr, self.du, self.dd = lrud
self.H = H(self.dl, self.dr, self.du, self.dd, self.w, self.l)
self.inv_H = np.linalg.inv(self.H)
self.rectified = tf.warp(img, self.H)
if mask is not None:
self.rectified_mask = tf.warp(mask, self.H)
else:
self.rectified_mask = None
else:
self.vlines = []
self.hlines = []
self.H = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=float)
self.inv_H = self.H
self.rectified = img.copy()
if self.mask is not None:
self.rectified_mask = self.mask.copy()
else:
self.rectified_mask = None
def augment(images):
pixels = images[0].shape[1]
center = pixels/2.-0.5
random_flip_x = P.AUGMENTATION_PARAMS['flip'] and np.random.randint(2) == 1
random_flip_y = P.AUGMENTATION_PARAMS['flip'] and np.random.randint(2) == 1
# Translation shift
shift_x = np.random.uniform(*P.AUGMENTATION_PARAMS['translation_range'])
shift_y = np.random.uniform(*P.AUGMENTATION_PARAMS['translation_range'])
rotation_degrees = np.random.uniform(*P.AUGMENTATION_PARAMS['rotation_range'])
zoom_factor = np.random.uniform(*P.AUGMENTATION_PARAMS['zoom_range'])
#zoom_factor = 1 + (zoom_f/2-zoom_f*np.random.random())
if CV2_AVAILABLE:
M = cv2.getRotationMatrix2D((center, center), rotation_degrees, zoom_factor)
M[0, 2] += shift_x
M[1, 2] += shift_y
for i in range(len(images)):
image = images[i]
if CV2_AVAILABLE:
#image = image.transpose(1,2,0)
image = cv2.warpAffine(image, M, (pixels, pixels))
if random_flip_x:
image = cv2.flip(image, 0)
if random_flip_y:
image = cv2.flip(image, 1)
#image = image.transpose(2,0,1)
images[i] = image
else:
if random_flip_x:
#image = image.transpose(1,0)
image[:,:] = image[::-1,:]
#image = image.transpose(1,0)
if random_flip_y:
image = image.transpose(1,0)
image[:,:] = image[::-1,:]
image = image.transpose(1,0)
rotate(image, rotation_degrees, reshape=False, output=image)
#image2 = zoom(image, [zoom_factor,zoom_factor])
image2 = crop_or_pad(image, pixels, -3000)
shift(image2, [shift_x,shift_y], output=image)
#affine_transform(image, np.array([[zoom_x,0], [0,zoom_x]]), output=image)
#z = AffineTransform(scale=(2,2))
#image = warp(image, z.params)
images[i] = image
return images
def swirl(x, center=None, strength=1, radius=100, rotation=0, output_shape=None, order=1, mode='constant', cval=0, clip=True, preserve_range=False, is_random=False):
"""Swirl an image randomly or non-randomly, see `scikit-image swirl API <http://scikit-image.org/docs/dev/api/skimage.transform.html#skimage.transform.swirl>`_
and `example <http://scikit-image.org/docs/dev/auto_examples/plot_swirl.html>`_.
Parameters
-----------
x : numpy array
An image with dimension of [row, col, channel] (default).
center : (row, column) tuple or (2,) ndarray, optional
Center coordinate of transformation.
strength : float, optional
The amount of swirling applied.
radius : float, optional
The extent of the swirl in pixels. The effect dies out rapidly beyond radius.
rotation : float, (degree) optional
Additional rotation applied to the image, usually [0, 360], relates to center.
output_shape : tuple (rows, cols), optional
Shape of the output image generated. By default the shape of the input image is preserved.
order : int, optional
The order of the spline interpolation, default is 1. The order has to be in the range 0-5. See skimage.transform.warp for detail.
mode : {‘constant’, ‘edge’, ‘symmetric’, ‘reflect’, ‘wrap’}, optional
Points outside the boundaries of the input are filled according to the given mode, with ‘constant’ used as the default. Modes match the behaviour of numpy.pad.
cval : float, optional
Used in conjunction with mode ‘constant’, the value outside the image boundaries.
clip : bool, optional
Whether to clip the output to the range of values of the input image. This is enabled by default, since higher order interpolation may produce values outside the given input range.
preserve_range : bool, optional
Whether to keep the original range of values. Otherwise, the input image is converted according to the conventions of img_as_float.
is_random : boolean, default False
If True, random swirl.
- random center = [(0 ~ x.shape[0]), (0 ~ x.shape[1])]
- random strength = [0, strength]
- random radius = [1e-10, radius]
- random rotation = [-rotation, rotation]
Examples
---------
>>> x --> [row, col, 1] greyscale
>>> x = swirl(x, strength=4, radius=100)
"""
assert radius != 0, Exception("Invalid radius value")
rotation = np.pi / 180 * rotation
if is_random:
center_h = int(np.random.uniform(0, x.shape[0]))
center_w = int(np.random.uniform(0, x.shape[1]))
center = (center_h, center_w)
strength = np.random.uniform(0, strength)
radius = np.random.uniform(1e-10, radius)
rotation = np.random.uniform(-rotation, rotation)
max_v = np.max(x)
if max_v > 1: # Note: the input of this fn should be [-1, 1], rescale is required.
x = x / max_v
swirled = skimage.transform.swirl(x, center=center, strength=strength, radius=radius, rotation=rotation,
output_shape=output_shape, order=order, mode=mode, cval=cval, clip=clip, preserve_range=preserve_range)
if max_v > 1:
swirled = swirled * max_v
return swirled
def projective_transform_by_points(x, src, dst, map_args={}, output_shape=None, order=1, mode='constant', cval=0.0, clip=True, preserve_range=False):
"""Projective transform by given coordinates, usually 4 coordinates. see `scikit-image <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`_.
Parameters
-----------
x : numpy array
An image with dimension of [row, col, channel] (default).
src : list or numpy
The original coordinates, usually 4 coordinates of (x, y).
dst : list or numpy
The coordinates after transformation, the number of coordinates is the same with src.
map_args : dict, optional
Keyword arguments passed to inverse_map.
output_shape : tuple (rows, cols), optional
Shape of the output image generated. By default the shape of the input image is preserved. Note that, even for multi-band images, only rows and columns need to be specified.
order : int, optional
The order of interpolation. The order has to be in the range 0-5:
- 0 Nearest-neighbor
- 1 Bi-linear (default)
- 2 Bi-quadratic
- 3 Bi-cubic
- 4 Bi-quartic
- 5 Bi-quintic
mode : {‘constant’, ‘edge’, ‘symmetric’, ‘reflect’, ‘wrap’}, optional
Points outside the boundaries of the input are filled according to the given mode. Modes match the behaviour of numpy.pad.
cval : float, optional
Used in conjunction with mode ‘constant’, the value outside the image boundaries.
clip : bool, optional
Whether to clip the output to the range of values of the input image. This is enabled by default, since higher order interpolation may produce values outside the given input range.
preserve_range : bool, optional
Whether to keep the original range of values. Otherwise, the input image is converted according to the conventions of img_as_float.
Examples
--------
>>> Assume X is an image from CIFAR 10, i.e. shape == (32, 32, 3)
>>> src = [[0,0],[0,32],[32,0],[32,32]]
>>> dst = [[10,10],[0,32],[32,0],[32,32]]
>>> x = projective_transform_by_points(X, src, dst)
References
-----------
- `scikit-image : geometric transformations <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`_
- `scikit-image : examples <http://scikit-image.org/docs/dev/auto_examples/index.html>`_
"""
if type(src) is list: # convert to numpy
src = np.array(src)
if type(dst) is list:
dst = np.array(dst)
if np.max(x)>1: # convert to [0, 1]
x = x/255
m = transform.ProjectiveTransform()
m.estimate(dst, src)
warped = transform.warp(x, m, map_args=map_args, output_shape=output_shape, order=order, mode=mode, cval=cval, clip=clip, preserve_range=preserve_range)
return warped
# Numpy and PIL
def augment(images):
pixels = images[0].shape[1]
center = pixels/2.-0.5
random_flip_x = P.AUGMENTATION_PARAMS['flip'] and np.random.randint(2) == 1
random_flip_y = P.AUGMENTATION_PARAMS['flip'] and np.random.randint(2) == 1
# Translation shift
shift_x = np.random.uniform(*P.AUGMENTATION_PARAMS['translation_range'])
shift_y = np.random.uniform(*P.AUGMENTATION_PARAMS['translation_range'])
rotation_degrees = np.random.uniform(*P.AUGMENTATION_PARAMS['rotation_range'])
zoom_factor = np.random.uniform(*P.AUGMENTATION_PARAMS['zoom_range'])
#zoom_factor = 1 + (zoom_f/2-zoom_f*np.random.random())
if CV2_AVAILABLE:
M = cv2.getRotationMatrix2D((center, center), rotation_degrees, zoom_factor)
M[0, 2] += shift_x
M[1, 2] += shift_y
for i in range(len(images)):
image = images[i]
if CV2_AVAILABLE:
#image = image.transpose(1,2,0)
image = cv2.warpAffine(image, M, (pixels, pixels))
if random_flip_x:
image = cv2.flip(image, 0)
if random_flip_y:
image = cv2.flip(image, 1)
#image = image.transpose(2,0,1)
images[i] = image
else:
if random_flip_x:
#image = image.transpose(1,0)
image[:,:] = image[::-1,:]
#image = image.transpose(1,0)
if random_flip_y:
image = image.transpose(1,0)
image[:,:] = image[::-1,:]
image = image.transpose(1,0)
rotate(image, rotation_degrees, reshape=False, output=image)
#image2 = zoom(image, [zoom_factor,zoom_factor])
image2 = crop_or_pad(image, pixels, -3000)
shift(image2, [shift_x,shift_y], output=image)
#affine_transform(image, np.array([[zoom_x,0], [0,zoom_x]]), output=image)
#z = AffineTransform(scale=(2,2))
#image = warp(image, z.params)
images[i] = image
return images
def image_deformation(self,image):
random_shear_angl = np.random.random() * np.pi/6 - np.pi/12
random_rot_angl = np.random.random() * np.pi/6 - np.pi/12 - random_shear_angl
random_x_scale = np.random.random() * .4 + .8
random_y_scale = np.random.random() * .4 + .8
random_x_trans = np.random.random() * image.shape[0] / 4 - image.shape[0] / 8
random_y_trans = np.random.random() * image.shape[1] / 4 - image.shape[1] / 8
dx = image.shape[0]/2. \
- random_x_scale * image.shape[0]/2 * np.cos(random_rot_angl)\
+ random_y_scale * image.shape[1]/2 * np.sin(random_rot_angl + random_shear_angl)
dy = image.shape[1]/2. \
- random_x_scale * image.shape[0]/2 * np.sin(random_rot_angl)\
- random_y_scale * image.shape[1]/2 * np.cos(random_rot_angl + random_shear_angl)
trans_mat = AffineTransform(rotation=random_rot_angl,
translation=(dx + random_x_trans,
dy + random_y_trans),
shear = random_shear_angl,
scale = (random_x_scale,random_y_scale))
return warp(image,trans_mat.inverse,output_shape=image.shape)
# def get_valid(self,size = 1000):
# data = self.mnist.train.next_batch(size)
# images = np.zeros((size,32,32))
# labels = data[1]
# for i in range(1000):
# images[i,:,:] = misc.imresize(np.reshape(data[0][i],(28,28)),(32,32))
# return images,labels
# def shuffle(self):
# pass
# def next_batch(self,batch_size):
# data = self.mnist.train.next_batch(batch_size)
# images = np.zeros((batch_size,32,32))
# labels = data[1]
# for i in range(batch_size):
# images[i,:,:] = misc.imresize(np.reshape(data[0][i],(28,28)),(32,32))
# return images,labels
# def get_valid(self,size = 500):
# data = self.mnist.train.next_batch(size)
# images = np.zeros((size,32,32))
# labels = data[1]
# for i in range(500):
# images[i,:,:] = misc.imresize(np.reshape(data[0][i],(28,28)),(32,32))
# return images,labels
# def shuffle(self):
# pass
# def next_batch(self,batch_size):
# data = self.mnist.train.next_batch(batch_size)
# images = np.zeros((batch_size,32,32))
# labels = data[1]
# for i in range(batch_size):
# images[i,:,:] = misc.imresize(np.reshape(data[0][i],(28,28)),(32,32))
# return images,labels
def swirl(x, center=None, strength=1, radius=100, rotation=0, output_shape=None, order=1, mode='constant', cval=0, clip=True, preserve_range=False, is_random=False):
"""Swirl an image randomly or non-randomly, see `scikit-image swirl API <http://scikit-image.org/docs/dev/api/skimage.transform.html#skimage.transform.swirl>`_
and `example <http://scikit-image.org/docs/dev/auto_examples/plot_swirl.html>`_.
Parameters
-----------
x : numpy array
An image with dimension of [row, col, channel] (default).
center : (row, column) tuple or (2,) ndarray, optional
Center coordinate of transformation.
strength : float, optional
The amount of swirling applied.
radius : float, optional
The extent of the swirl in pixels. The effect dies out rapidly beyond radius.
rotation : float, (degree) optional
Additional rotation applied to the image, usually [0, 360], relates to center.
output_shape : tuple (rows, cols), optional
Shape of the output image generated. By default the shape of the input image is preserved.
order : int, optional
The order of the spline interpolation, default is 1. The order has to be in the range 0-5. See skimage.transform.warp for detail.
mode : {‘constant’, ‘edge’, ‘symmetric’, ‘reflect’, ‘wrap’}, optional
Points outside the boundaries of the input are filled according to the given mode, with ‘constant’ used as the default. Modes match the behaviour of numpy.pad.
cval : float, optional
Used in conjunction with mode ‘constant’, the value outside the image boundaries.
clip : bool, optional
Whether to clip the output to the range of values of the input image. This is enabled by default, since higher order interpolation may produce values outside the given input range.
preserve_range : bool, optional
Whether to keep the original range of values. Otherwise, the input image is converted according to the conventions of img_as_float.
is_random : boolean, default False
If True, random swirl.
- random center = [(0 ~ x.shape[0]), (0 ~ x.shape[1])]
- random strength = [0, strength]
- random radius = [1e-10, radius]
- random rotation = [-rotation, rotation]
Examples
---------
>>> x --> [row, col, 1] greyscale
>>> x = swirl(x, strength=4, radius=100)
"""
assert radius != 0, Exception("Invalid radius value")
rotation = np.pi / 180 * rotation
if is_random:
center_h = int(np.random.uniform(0, x.shape[0]))
center_w = int(np.random.uniform(0, x.shape[1]))
center = (center_h, center_w)
strength = np.random.uniform(0, strength)
radius = np.random.uniform(1e-10, radius)
rotation = np.random.uniform(-rotation, rotation)
max_v = np.max(x)
if max_v > 1: # Note: the input of this fn should be [-1, 1], rescale is required.
x = x / max_v
swirled = skimage.transform.swirl(x, center=center, strength=strength, radius=radius, rotation=rotation,
output_shape=output_shape, order=order, mode=mode, cval=cval, clip=clip, preserve_range=preserve_range)
if max_v > 1:
swirled = swirled * max_v
return swirled
def projective_transform_by_points(x, src, dst, map_args={}, output_shape=None, order=1, mode='constant', cval=0.0, clip=True, preserve_range=False):
"""Projective transform by given coordinates, usually 4 coordinates. see `scikit-image <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`_.
Parameters
-----------
x : numpy array
An image with dimension of [row, col, channel] (default).
src : list or numpy
The original coordinates, usually 4 coordinates of (width, height).
dst : list or numpy
The coordinates after transformation, the number of coordinates is the same with src.
map_args : dict, optional
Keyword arguments passed to inverse_map.
output_shape : tuple (rows, cols), optional
Shape of the output image generated. By default the shape of the input image is preserved. Note that, even for multi-band images, only rows and columns need to be specified.
order : int, optional
The order of interpolation. The order has to be in the range 0-5:
- 0 Nearest-neighbor
- 1 Bi-linear (default)
- 2 Bi-quadratic
- 3 Bi-cubic
- 4 Bi-quartic
- 5 Bi-quintic
mode : {‘constant’, ‘edge’, ‘symmetric’, ‘reflect’, ‘wrap’}, optional
Points outside the boundaries of the input are filled according to the given mode. Modes match the behaviour of numpy.pad.
cval : float, optional
Used in conjunction with mode ‘constant’, the value outside the image boundaries.
clip : bool, optional
Whether to clip the output to the range of values of the input image. This is enabled by default, since higher order interpolation may produce values outside the given input range.
preserve_range : bool, optional
Whether to keep the original range of values. Otherwise, the input image is converted according to the conventions of img_as_float.
Examples
--------
>>> Assume X is an image from CIFAR 10, i.e. shape == (32, 32, 3)
>>> src = [[0,0],[0,32],[32,0],[32,32]] # [w, h]
>>> dst = [[10,10],[0,32],[32,0],[32,32]]
>>> x = projective_transform_by_points(X, src, dst)
References
-----------
- `scikit-image : geometric transformations <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`_
- `scikit-image : examples <http://scikit-image.org/docs/dev/auto_examples/index.html>`_
"""
if type(src) is list: # convert to numpy
src = np.array(src)
if type(dst) is list:
dst = np.array(dst)
if np.max(x)>1: # convert to [0, 1]
x = x/255
m = transform.ProjectiveTransform()
m.estimate(dst, src)
warped = transform.warp(x, m, map_args=map_args, output_shape=output_shape, order=order, mode=mode, cval=cval, clip=clip, preserve_range=preserve_range)
return warped
# Numpy and PIL
def swirl(x, center=None, strength=1, radius=100, rotation=0, output_shape=None, order=1, mode='constant', cval=0, clip=True, preserve_range=False, is_random=False):
"""Swirl an image randomly or non-randomly, see `scikit-image swirl API <http://scikit-image.org/docs/dev/api/skimage.transform.html#skimage.transform.swirl>`_
and `example <http://scikit-image.org/docs/dev/auto_examples/plot_swirl.html>`_.
Parameters
-----------
x : numpy array
An image with dimension of [row, col, channel] (default).
center : (row, column) tuple or (2,) ndarray, optional
Center coordinate of transformation.
strength : float, optional
The amount of swirling applied.
radius : float, optional
The extent of the swirl in pixels. The effect dies out rapidly beyond radius.
rotation : float, (degree) optional
Additional rotation applied to the image, usually [0, 360], relates to center.
output_shape : tuple (rows, cols), optional
Shape of the output image generated. By default the shape of the input image is preserved.
order : int, optional
The order of the spline interpolation, default is 1. The order has to be in the range 0-5. See skimage.transform.warp for detail.
mode : {‘constant’, ‘edge’, ‘symmetric’, ‘reflect’, ‘wrap’}, optional
Points outside the boundaries of the input are filled according to the given mode, with ‘constant’ used as the default. Modes match the behaviour of numpy.pad.
cval : float, optional
Used in conjunction with mode ‘constant’, the value outside the image boundaries.
clip : bool, optional
Whether to clip the output to the range of values of the input image. This is enabled by default, since higher order interpolation may produce values outside the given input range.
preserve_range : bool, optional
Whether to keep the original range of values. Otherwise, the input image is converted according to the conventions of img_as_float.
is_random : boolean, default False
If True, random swirl.
- random center = [(0 ~ x.shape[0]), (0 ~ x.shape[1])]
- random strength = [0, strength]
- random radius = [1e-10, radius]
- random rotation = [-rotation, rotation]
Examples
---------
>>> x --> [row, col, 1] greyscale
>>> x = swirl(x, strength=4, radius=100)
"""
assert radius != 0, Exception("Invalid radius value")
rotation = np.pi / 180 * rotation
if is_random:
center_h = int(np.random.uniform(0, x.shape[0]))
center_w = int(np.random.uniform(0, x.shape[1]))
center = (center_h, center_w)
strength = np.random.uniform(0, strength)
radius = np.random.uniform(1e-10, radius)
rotation = np.random.uniform(-rotation, rotation)
max_v = np.max(x)
if max_v > 1: # Note: the input of this fn should be [-1, 1], rescale is required.
x = x / max_v
swirled = skimage.transform.swirl(x, center=center, strength=strength, radius=radius, rotation=rotation,
output_shape=output_shape, order=order, mode=mode, cval=cval, clip=clip, preserve_range=preserve_range)
if max_v > 1:
swirled = swirled * max_v
return swirled
def projective_transform_by_points(x, src, dst, map_args={}, output_shape=None, order=1, mode='constant', cval=0.0, clip=True, preserve_range=False):
"""Projective transform by given coordinates, usually 4 coordinates. see `scikit-image <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`_.
Parameters
-----------
x : numpy array
An image with dimension of [row, col, channel] (default).
src : list or numpy
The original coordinates, usually 4 coordinates of (x, y).
dst : list or numpy
The coordinates after transformation, the number of coordinates is the same with src.
map_args : dict, optional
Keyword arguments passed to inverse_map.
output_shape : tuple (rows, cols), optional
Shape of the output image generated. By default the shape of the input image is preserved. Note that, even for multi-band images, only rows and columns need to be specified.
order : int, optional
The order of interpolation. The order has to be in the range 0-5:
- 0 Nearest-neighbor
- 1 Bi-linear (default)
- 2 Bi-quadratic
- 3 Bi-cubic
- 4 Bi-quartic
- 5 Bi-quintic
mode : {‘constant’, ‘edge’, ‘symmetric’, ‘reflect’, ‘wrap’}, optional
Points outside the boundaries of the input are filled according to the given mode. Modes match the behaviour of numpy.pad.
cval : float, optional
Used in conjunction with mode ‘constant’, the value outside the image boundaries.
clip : bool, optional
Whether to clip the output to the range of values of the input image. This is enabled by default, since higher order interpolation may produce values outside the given input range.
preserve_range : bool, optional
Whether to keep the original range of values. Otherwise, the input image is converted according to the conventions of img_as_float.
Examples
--------
>>> Assume X is an image from CIFAR 10, i.e. shape == (32, 32, 3)
>>> src = [[0,0],[0,32],[32,0],[32,32]]
>>> dst = [[10,10],[0,32],[32,0],[32,32]]
>>> x = projective_transform_by_points(X, src, dst)
References
-----------
- `scikit-image : geometric transformations <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`_
- `scikit-image : examples <http://scikit-image.org/docs/dev/auto_examples/index.html>`_
"""
if type(src) is list: # convert to numpy
src = np.array(src)
if type(dst) is list:
dst = np.array(dst)
if np.max(x)>1: # convert to [0, 1]
x = x/255
m = transform.ProjectiveTransform()
m.estimate(dst, src)
warped = transform.warp(x, m, map_args=map_args, output_shape=output_shape, order=order, mode=mode, cval=cval, clip=clip, preserve_range=preserve_range)
return warped
# Numpy and PIL
def projective_transform_by_points(x, src, dst, map_args={}, output_shape=None, order=1, mode='constant', cval=0.0, clip=True, preserve_range=False):
"""Projective transform by given coordinates, usually 4 coordinates. see `scikit-image <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`_.
Parameters
-----------
x : numpy array
An image with dimension of [row, col, channel] (default).
src : list or numpy
The original coordinates, usually 4 coordinates of (x, y).
dst : list or numpy
The coordinates after transformation, the number of coordinates is the same with src.
map_args : dict, optional
Keyword arguments passed to inverse_map.
output_shape : tuple (rows, cols), optional
Shape of the output image generated. By default the shape of the input image is preserved. Note that, even for multi-band images, only rows and columns need to be specified.
order : int, optional
The order of interpolation. The order has to be in the range 0-5:
- 0 Nearest-neighbor
- 1 Bi-linear (default)
- 2 Bi-quadratic
- 3 Bi-cubic
- 4 Bi-quartic
- 5 Bi-quintic
mode : {‘constant’, ‘edge’, ‘symmetric’, ‘reflect’, ‘wrap’}, optional
Points outside the boundaries of the input are filled according to the given mode. Modes match the behaviour of numpy.pad.
cval : float, optional
Used in conjunction with mode ‘constant’, the value outside the image boundaries.
clip : bool, optional
Whether to clip the output to the range of values of the input image. This is enabled by default, since higher order interpolation may produce values outside the given input range.
preserve_range : bool, optional
Whether to keep the original range of values. Otherwise, the input image is converted according to the conventions of img_as_float.
Examples
--------
>>> Assume X is an image from CIFAR 10, i.e. shape == (32, 32, 3)
>>> src = [[0,0],[0,32],[32,0],[32,32]]
>>> dst = [[10,10],[0,32],[32,0],[32,32]]
>>> x = projective_transform_by_points(X, src, dst)
References
-----------
- `scikit-image : geometric transformations <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`_
- `scikit-image : examples <http://scikit-image.org/docs/dev/auto_examples/index.html>`_
"""
if type(src) is list: # convert to numpy
src = np.array(src)
if type(dst) is list:
dst = np.array(dst)
if np.max(x)>1: # convert to [0, 1]
x = x/255
m = transform.ProjectiveTransform()
m.estimate(dst, src)
warped = transform.warp(x, m, map_args=map_args, output_shape=output_shape, order=order, mode=mode, cval=cval, clip=clip, preserve_range=preserve_range)
return warped
# Numpy and PIL
def rectify_image(image, clip_factor=6, algorithm='independent',
reestimate=False):
"""Rectified image with vanishing point computed using ransac.
Parameters
----------
image: ndarray
Image which has to be rectified.
clip_factor: float, optional
Proportion of image in multiples of image size to be retained if gone
out of bounds after homography.
algorithm: one of {'3-line', 'independent'}
independent ransac algorithm finds the orthogonal vanishing points by
applying ransac twice.
3-line algorithm finds the orthogonal vanishing points together, but
assumes knowledge of focal length.
reestimate: bool
If ransac results are to be reestimated using least squares with
inlers. Turn this off if getting bad results.
Returns
-------
warped_img: ndarray
Rectified image.
"""
if type(image) is not np.ndarray:
image = io.imread(image)
# Compute all edgelets.
edgelets1 = compute_edgelets(image)
if algorithm == 'independent':
# Find first vanishing point
vp1 = ransac_vanishing_point(edgelets1, 2000, threshold_inlier=5)
if reestimate:
vp1 = reestimate_model(vp1, edgelets1, 5)
# Remove inlier to remove dominating direction.
edgelets2 = remove_inliers(vp1, edgelets1, 10)
# Find second vanishing point
vp2 = ransac_vanishing_point(edgelets2, 2000, threshold_inlier=5)
if reestimate:
vp2 = reestimate_model(vp2, edgelets2, 5)
elif algorithm == '3-line':
focal_length = None
vp1, vp2 = ransac_3_line(edgelets1, focal_length,
num_ransac_iter=3000, threshold_inlier=5)
else:
raise KeyError(
"Parameter 'algorithm' has to be one of {'3-line', 'independent'}")
# Compute the homography and warp
warped_img = compute_homography_and_warp(image, vp1, vp2,
clip_factor=clip_factor)
return warped_img