def sample_patch_projective(image, inv_xform_3x3, patch_shape):
""" return a warped image as a numpy array with dtype float64 of size patch_size.
if input image is not already of type float64, it will be converted """
P = skimage.transform.ProjectiveTransform(inv_xform_3x3)
# skimage clips values to range [0,1] for floating point images. do scale and unscale here.
do_scale = False
og_dtype = image.dtype
if image.dtype in (np.float32, np.float64, np.float128, np.float16):
minval = np.nanmin(image)
maxval = np.nanmax(image)
# if range is good, no need to rescale
if minval < 0.0 or maxval > 1.0:
do_scale = True
# make a copy of image so as not to corrupt original data
image = image.copy()
scale_factor = maxval - minval
image -= minval
if scale_factor != 0:
image /= scale_factor
# do the warping
patch = skimage.transform.warp(image, P, output_shape=patch_shape, mode='constant', cval=np.nan)
# revert to original type if necessary
if og_dtype != patch.dtype:
if og_dtype == np.uint8:
patch = skimage.img_as_ubyte(patch)
elif og_dtype == np.bool:
patch = skimage.img_as_bool(patch)
elif og_dtype == np.uint16:
patch = skimage.img_as_uint(patch)
elif og_dtype == np.int16:
patch = skimage.img_as_int(patch)
else:
# just to straight cast, hope for the best
patch_out = np.zeros(patch.shape, og_dtype)
np.copyto(patch_out,patch)
patch = patch_out
# unscale if necessary
if do_scale:
patch *= scale_factor
patch += minval
return patch