def coarse_to_fine(I0, I1, solver, downscale=2, nlevel=10, min_size=16,
                   dtype='float32'):
    """Generic coarse to fine solver.

    Parameters
    ----------
    I0 : ndarray
        The first gray scale image of the sequence.
    I1 : ndarray
        The second gray scale image of the sequence.
    solver : callable
        The solver applyed at each pyramid level.
    downscale : float
        The pyramid downscale factor.
    nlevel : int
        The maximum number of pyramid levels.
    min_size : int
        The minimum size for any dimension of the pyramid levels.
    dtype : dtype
        Output data type.

    Returns
    -------
    flow : ndarray
        The estimated optical flow components for each axis.

    """

    if I0.shape != I1.shape:
        raise ValueError("Input images should have the same shape")

    if np.dtype(dtype).char not in 'efdg':
        raise ValueError("Only floating point data type are valid"
                         " for optical flow")

    pyramid = list(zip(get_pyramid(convert(I0, dtype),
                                   downscale, nlevel, min_size),
                       get_pyramid(convert(I1, dtype),
                                   downscale, nlevel, min_size)))

    # Initialization to 0 at coarsest level.
    flow = np.zeros((pyramid[0][0].ndim, ) + pyramid[0][0].shape,
                    dtype=dtype)

    flow = solver(pyramid[0][0], pyramid[0][1], flow)

    for J0, J1 in pyramid[1:]:
        flow = solver(J0, J1, resize_flow(flow, J0.shape))

    return flow
예제 #2
0
def test_range_extra_dtypes():
    """Test code paths that are not skipped by `test_range`"""

    # Add non-standard data types that are allowed by the `convert` function.
    dtype_range_extra = dtype_range.copy()
    dtype_range_extra.update({
        np.int32: (-2147483648, 2147483647),
        np.uint32: (0, 4294967295)
    })

    dtype_pairs = [(np.uint8, np.uint32), (np.int8, np.uint32),
                   (np.int8, np.int32), (np.int32, np.int8),
                   (np.float64, np.float32), (np.int32, np.float32)]

    for dtype_in, dt in dtype_pairs:
        imin, imax = dtype_range_extra[dtype_in]
        x = np.linspace(imin, imax, 10).astype(dtype_in)

        with expected_warnings(['precision loss|sign loss|\A\Z']):
            y = convert(x, dt)

        omin, omax = dtype_range_extra[dt]
        yield (_verify_range,
               "From %s to %s" % (np.dtype(dtype_in), np.dtype(dt)), y, omin,
               omax, np.dtype(dt))
예제 #3
0
 def add_noise(self, mean=0, var=0.01):
     img = np.multiply(self.img, 1. / 255, dtype=np.float64)
     noise = np.random.normal(mean, var ** 0.5,
                              img.shape)
     img = convert(img, np.floating)
     out = img + noise
     return out
예제 #4
0
def test_range_extra_dtypes():
    """Test code paths that are not skipped by `test_range`"""

    # Add non-standard data types that are allowed by the `convert` function.
    dtype_range_extra = dtype_range.copy()
    dtype_range_extra.update({np.int32: (-2147483648, 2147483647),
                              np.uint32: (0, 4294967295)})

    dtype_pairs = [(np.uint8, np.uint32),
                   (np.int8, np.uint32),
                   (np.int8, np.int32),
                   (np.int32, np.int8),
                   (np.float64, np.float32),
                   (np.int32, np.float32)]

    for dtype_in, dt in dtype_pairs:
        imin, imax = dtype_range_extra[dtype_in]
        x = np.linspace(imin, imax, 10).astype(dtype_in)
        
        with expected_warnings(['precision loss|sign loss|\A\Z']):
            y = convert(x, dt)

        omin, omax = dtype_range_extra[dt]
        yield (_verify_range,
               "From %s to %s" % (np.dtype(dtype_in), np.dtype(dt)),
               y, omin, omax, np.dtype(dt))
예제 #5
0
def transform_from_corners(im):
    """ Allow the user to click on the sudoku grid corners, and then crop and warp it to get a squared grid """

    # Mark corners (1. Top left, 2. Bottom left, 3. Bottom right, 4. Top right)
    pl.figure()
    pl.title(
        "Click on corners (1. Top left, 2. Bottom left, 3. Bottom right, 4. Top right)"
    )
    pl.imshow(im)
    pl.gray()
    x = pl.ginput(4)  # Wait on user input clicks
    pl.close()

    # Top left, top right, bottom right, bottom left
    fp = np.array([np.array([p[0], p[1]]) for p in x])
    dim = 1000  # New size for the croped grid
    tp = np.array([[0, 0], [0, dim], [dim, dim], [dim, 0]])

    # Compute projective transform, and apply it through warping
    tform = tf.ProjectiveTransform()
    tform.estimate(tp, fp)
    output_shape = (dim, dim)
    # TOD.O: use scikit-image warp function to apply the transformation
    #warped = None
    warped = tf.warp(im, tform, output_shape=output_shape)

    # Convert result in the right format [0, 255]
    im = convert(warped, np.uint8)
    return im
예제 #6
0
def add_noise(p_img):
    p_img = np.multiply(p_img, 1.0 / 255, dtype=np.float64)
    mean, var = 0, 0.01
    noise = np.random.normal(mean, var**0.5, p_img.shape)
    p_img = convert(p_img, np.floating)
    out = p_img + noise
    return out
예제 #7
0
    def transform(self, image):
        result = gray2rgb(image)

        if self.keep_dtype:
            result = dtype.convert(result, image.dtype)

        return result
예제 #8
0
def test_subclass_conversion():
    """Check subclass conversion behavior"""
    x = np.array([-1, 1])

    for dtype in float_dtype_list:
        x = x.astype(dtype)
        y = convert(x, np.floating)
        assert y.dtype == x.dtype
예제 #9
0
    def transform(self, image: np.ndarray):
        if len(image.shape) != 3:
            raise ValueError("image.shape != 3 in {!r}".format(self))

        result = rgb2gray(image)

        if self.keep_dtype:
            result = dtype.convert(result, image.dtype)

        return result
예제 #10
0
def test_range_extra_dtypes(dtype_in, dt):
    """Test code paths that are not skipped by `test_range`"""

    imin, imax = dtype_range_extra[dtype_in]
    x = np.linspace(imin, imax, 10).astype(dtype_in)

    y = convert(x, dt)

    omin, omax = dtype_range_extra[dt]
    _verify_range("From %s to %s" % (np.dtype(dtype_in), np.dtype(dt)),
                  y, omin, omax, np.dtype(dt))
예제 #11
0
def test_float_conversion_dtype():
    """Test any convertion from a float dtype to an other."""
    x = np.array([-1, 1])

    # Test all combinations of dtypes convertions
    dtype_combin = np.array(np.meshgrid(float_dtype_list,
                                        float_dtype_list)).T.reshape(-1, 2)

    for dtype_in, dtype_out in dtype_combin:
        x = x.astype(dtype_in)
        y = convert(x, dtype_out)
        assert y.dtype == np.dtype(dtype_out)
예제 #12
0
def imread(record, dtype=None):
    """Load an image from a WARC record.

    Parameters
    ----------
    record : WARC Record

    """
    im = _imread.imread_from_blob(record.payload.read())
    if dtype is not None:
        im = convert(im, dtype)
    return im
예제 #13
0
def test_range_extra_dtypes(dtype_in, dt):
    """Test code paths that are not skipped by `test_range`"""

    imin, imax = dtype_range_extra[dtype_in]
    x = np.linspace(imin, imax, 10).astype(dtype_in)

    with expected_warnings(['precision loss|sign loss|\A\Z']):
        y = convert(x, dt)

    omin, omax = dtype_range_extra[dt]
    _verify_range("From %s to %s" % (np.dtype(dtype_in), np.dtype(dt)), y,
                  omin, omax, np.dtype(dt))
예제 #14
0
def test_range_extra_dtypes(dtype_in, dt):
    """Test code paths that are not skipped by `test_range`"""

    imin, imax = dtype_range_extra[dtype_in]
    x = np.linspace(imin, imax, 10).astype(dtype_in)

    with expected_warnings(['precision loss|sign loss|\A\Z']):
        y = convert(x, dt)

    omin, omax = dtype_range_extra[dt]
    _verify_range("From %s to %s" % (np.dtype(dtype_in), np.dtype(dt)),
                  y, omin, omax, np.dtype(dt))
예제 #15
0
def imread(fname, dtype=None):
    """Load an image from file.

    Parameters
    ----------
    fname : str
        Name of input file

    """
    im = _imread.imread(fname)
    if dtype is not None:
        im = convert(im, dtype)
    return im
예제 #16
0
def find_centroids(img, bkg=None, threshold=None, min_size=0):
    if bkg is None:
        bkg = gaussian(img, 10)
    bkg.astype(np.uint16)
    img = convert(img-bkg,np.uint8) #<- This changes the execution speed ~5-fold
    if threshold is None:
        threshold = mh.otsu(img)
#     mask = img>threshold
#     labels = np.array(mh.label(img>threshold)[0])
    labels = label(img>threshold)  # <- This is faster
    props = regionprops(labels, img, cache=True)  # <- Cache True is faster
#     num_pixels = [p['filled_area'] for p in props]
    centroids = [p['centroid'] for p in props if p['filled_area']>=min_size]
    return centroids
예제 #17
0
def test_float_conversion_dtype_warns():
    """Test that convert issues a warning when called"""
    from skimage.util.dtype import convert
    x = np.array([-1, 1])

    # Test all combinations of dtypes conversions
    dtype_combin = np.array(np.meshgrid(float_dtype_list,
                                        float_dtype_list)).T.reshape(-1, 2)

    for dtype_in, dtype_out in dtype_combin:
        x = x.astype(dtype_in)
        with expected_warnings(["The use of this function is discouraged"]):
            y = convert(x, dtype_out)
        assert y.dtype == np.dtype(dtype_out)
예제 #18
0
    def next_frame(self):
        hdr = self.fd.readline()
        if hdr == b"":
            return []

        if hdr[0:5] != b"FRAME":
            raise Exception("Invalid Y4M Frame")

        raw_y = self.fd.read(self.width * self.height)
        raw_u = self.fd.read(self.halfwidth * self.halfheight)
        raw_v = self.fd.read(self.halfwidth * self.halfheight)

        y = convert(
            np.frombuffer(raw_y,
                          dtype='uint8').reshape(self.height, self.width),
            np.float32)
        u = resize(
            convert(
                np.frombuffer(raw_u,
                              dtype='uint8').reshape(self.halfheight,
                                                     self.halfwidth),
                np.float32), (self.height, self.width), 0, 'reflect')
        v = resize(
            convert(
                np.frombuffer(raw_v,
                              dtype='uint8').reshape(self.halfheight,
                                                     self.halfwidth),
                np.float32), (self.height, self.width), 0, 'reflect')

        yuv = np.array([y, u, v])
        from skimage.color import yuv2rgb
        rgb = yuv2rgb(yuv.transpose(1, 2, 0)).transpose(2, 0, 1)
        #transform = np.array([[1, 0, 1.139883], [1, -0.39464233, -0.580621850], [1, 2.03206, 0]], dtype=np.float32)

        #rgb = yuv.transpose(1, 2, 0).dot(transform).transpose(2, 0, 1)
        return rgb
    def setup(self, dtype_in, N, order):
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore", "Possible precision loss")
            self.image = convert(np.random.random((N, N)), dtype=dtype_in)
        self.tform = SimilarityTransform(scale=1, rotation=np.pi / 10,
                                         translation=(0, 4))
        self.tform.params = self.tform.params.astype('float32')
        self.order = order

        if 'dtype' in inspect.signature(warp).parameters:
            self.warp = functools.partial(warp, dtype=self.image.dtype)
        else:
            # Keep a call to functools to have the same number of python
            # function calls
            self.warp = functools.partial(warp)
    def setup(self, dtype_in, N, order):
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore", "Possible precision loss")
            self.image = convert(np.random.random((N, N)), dtype=dtype_in)
        self.tform = SimilarityTransform(scale=1,
                                         rotation=np.pi / 10,
                                         translation=(0, 4))
        self.tform.params = self.tform.params.astype('float32')
        self.order = order

        if 'dtype' in inspect.signature(warp).parameters:
            self.warp = functools.partial(warp, dtype=self.image.dtype)
        else:
            # Keep a call to functools to have the same number of python
            # function calls
            self.warp = functools.partial(warp)
예제 #21
0
def hsv_value(image_filter, image, *args, **kwargs):
    """Return color image by applying `image_filter` on HSV-value of `image`.

    Note that this function is intended for use with `adapt_rgb`.

    Parameters
    ----------
    image_filter : function
        Function that filters a gray-scale image.
    image : array
        Input image. Note that RGBA images are treated as RGB.
    """
    # Slice the first three channels so that we remove any alpha channels.
    hsv = color.rgb2hsv(image[:, :, :3])
    value = hsv[:, :, 2].copy()
    value = image_filter(value, *args, **kwargs)
    hsv[:, :, 2] = convert(value, hsv.dtype)
    return color.hsv2rgb(hsv)
예제 #22
0
def hsv_value(image_filter, image, *args, **kwargs):
    """Return color image by applying `image_filter` on HSV-value of `image`.

    Note that this function is intended for use with `adapt_rgb`.

    Parameters
    ----------
    image_filter : function
        Function that filters a gray-scale image.
    image : array
        Input image. Note that RGBA images are treated as RGB.
    """
    # Slice the first three channels so that we remove any alpha channels.
    hsv = color.rgb2hsv(image[:, :, :3])
    value = hsv[:, :, 2].copy()
    value = image_filter(value, *args, **kwargs)
    hsv[:, :, 2] = convert(value, hsv.dtype)
    return color.hsv2rgb(hsv)
예제 #23
0
def apply_C_filter(image, dll, c_function, filter_size, mode='constant', cval=0):
    """
    Apply a C function based filter on image

    Parameters
    ----------
    image : 2D array
        Input image.
    dll: str or a ctypes dll object
        If str: A dll name (including full path if not on the default search
        path).
    c_function: str or int
        If str: The name of the variable in the dll pointing to the function.
        If int: A Function pointer.
    filter_size : (2,) array
        Filter shape.
    mode : str
        Padding mode.
    cval : a scalar
        Padding fill value (applicable is mode == 'const')

    Returns
    -------
    output : array
        A 2D array of the same dtype and shape as the input array.
    """
    # A temporary confinment to float32
    image = convert(image, np.float32)
    if type(dll) is str:
        dll = ctypes.cdll.LoadLibrary(dll)
    if type(c_function) is str:
        # pfcn =  ctypes.c_voidp.in_dll(dll, c_function).value
        pfcn =  ctypes.cast(getattr(dll, c_function), ctypes.c_void_p).value
        #pfcn = getattr(dll, c_function)
    else:
        pfcn = c_function
    #pfcn = ctypes.cast(pfcn, ctypes.pointer)
    # Prepare paded data
    padded = fiter.gen_filter_matrix(image, filter_size, mode=mode, cval=cval)
    output = np.empty_like(image)
    padded.filter_with_C_callback_float(pfcn, output)
    return output
예제 #24
0
def resize_image(img, new_width, new_height):
    """Resize image to a ``new_width`` and ``new_height``.
    
    Args:
        img (np.array): An image.
        new_width (int): New width.
        new_height (int): New height.
    
    Returns:
        np.array: A resized image.
    
    Examples:
        >>> img = Image.open('share/Lenna.png')
        >>> img_resized = resize_image(img, 256, 256)
        >>> img_resized.shape
        (256, 256, 3)
    """
    img_new = resize(img, (int(new_width), int(new_height)),
                     anti_aliasing=True)
    return convert(img_new, dtype=img.dtype)
예제 #25
0
def image_data(itype, dtype):
    """Return test image array."""
    if itype in ('rgb', 'view'):
        data = DATA[..., [0, 2, 4]]
    elif itype == 'rgba':
        data = DATA[..., [0, 2, 4, -1]]
    elif itype == 'cmyk':
        data = DATA[..., [0, 2, 4, 6]]
    elif itype == 'cmyka':
        data = DATA[..., [0, 2, 4, 6, -1]]
    elif itype == 'gray':
        data = DATA[..., 0:1]
    elif itype == 'graya':
        data = DATA[..., [0, -1]]
    elif itype == 'rrggbbaa':
        data = numpy.moveaxis(DATA[..., [0, 2, 4, -1]], -1, 0)
    elif itype == 'rrggbb':
        data = numpy.moveaxis(DATA[..., [0, 2, 4]], -1, 0)
    elif itype == 'channels':
        data = DATA[..., :-1]
    elif itype == 'channelsa':
        data = DATA[..., :]
    elif itype == 'line':
        data = DATA[0:1, :, 0:1]
    else:
        raise ValueError('itype not found')

    # TODO: replace skimage convert with dtype codec
    data = convert(data.copy(), dtype)
    if dtype == 'uint16':
        # 12-bit
        data //= 16

    if itype == 'view':
        shape = data.shape
        temp = numpy.empty((shape[0] + 5, shape[1] + 5, shape[2]), dtype)
        temp[2:2 + shape[0], 3:3 + shape[1], :] = data
        data = temp[2:2 + shape[0], 3:3 + shape[1], :]

    return data
예제 #26
0
    def __new__(cls,
                array: ndarray,
                dtype: Optional[Type[Union[np.float64, np.float32,
                                           np.float16]]] = None,
                copy: bool = True,
                meta: Optional[dict] = None,
                band_info: Optional[BandInfo] = None,
                ndim_exp: Optional[int] = None):
        """Create a SpectralArray from a numpy ndarray and metadata.

        Args:
            array: Input data array as numpy ndarray.

            dtype: Target datatype. Only numpy floats allowed:
                   np.float16, np.float32, np.float64. Default: np.float32

            copy: By default, a copy of the input array is forced. If 'False',
                  will try to only use a view of the input array. This might
                  not work in some cases and also depends on the Python
                  interpreter.

            meta: Meta data dictionary.

            band_info: :class:`BandInfo` object holding the the
                       spectral band properties.

            ndim_exp: Number of dimension expected of the array. This is used
                      by inherited classes.

        Raises:
            DimensionError(ndim_exp, array.ndim)
            If number of dimensions of input array does not match the specified
            ndim_exp option.

        Returns:
            SpectralArray
        """

        # Check input types
        if not isinstance(array, np.ndarray):
            raise ValueError("SpectralArray expects a numpy array.")

        # Check number of dimension
        if ndim_exp is not None and ndim_exp != array.ndim:
            raise DimensionError(exp=ndim_exp, found=array.ndim)

        if not (meta is None or isinstance(meta, dict)):
            raise ValueError("SpectralArray expects meta data to be a dict.")

        if not (band_info is None or isinstance(band_info, BandInfo)):
            raise ValueError(
                "SpectralArray expects BandInfo or None instance.")

        # Check data size
        if array.size == 0:
            raise ValueError(
                f"Invalid array size. Must have at least one axis.")

        # Convert dtype to fit standard, this might force a copy
        if not array.dtype == dtype and dtype is not None:
            logger.warning(f"Converting type from {array.dtype} to {dtype}.")
            logger.warning(f"Range will be mapped to (0, 1).")

            if not copy:
                logger.warning("Dtype conversion without copying is not "
                               "possible. Ignoring 'copy' option.")

        # Set default dtype
        if dtype is None:
            dtype = np.float32

        if dtype in [np.float16, np.float32, np.float64]:
            conv_data = convert(array, dtype=dtype, force_copy=copy)

        else:
            raise ValueError(f"The passed dtype '{dtype}' is invalid. "
                             "Only numpy float types are allowed.")

        # Get object
        ob = conv_data.view(cls)

        # Get number of color channels from last axis
        ob._numChannels = ob.shape[-1]

        # Check that BandInfo is compatible with data
        ob._bandInfo = band_info
        if ob._bandInfo is not None \
                and not ob._numChannels == ob._bandInfo.num_channels:
            raise ValueError(
                f"The numbers of channels of the band info object "
                f"and the numbers of channels of the given data "
                f"does not match. Found "
                f"{ob._bandInfo.num_channels} and "
                f"{ob._numChannels} respectively.")

        # Set metadata
        ob._meta = meta if meta is not None else {}

        return ob
예제 #27
0
def match_template(image, template, pad_input=False):
    """Match a template to an image using normalized correlation.

    The output is an array with values between -1.0 and 1.0, which correspond
    to the probability that the template is found at that position.

    Parameters
    ----------
    image : array_like
        Image to process.
    template : array_like
        Template to locate.
    pad_input : bool
        If True, pad `image` with image mean so that output is the same size as
        the image, and output values correspond to the template center.
        Otherwise, the output is an array with shape `(M - m + 1, N - n + 1)`
        for an `(M, N)` image and an `(m, n)` template, and matches correspond
        to origin (top-left corner) of the template.

    Returns
    -------
    output : ndarray
        Correlation results between -1.0 and 1.0. For an `(M, N)` image and an
        `(m, n)` template, the `output` is `(M - m + 1, N - n + 1)` when
        `pad_input = False` and `(M, N)` when `pad_input = True`.

    Examples
    --------
    >>> template = np.zeros((3, 3))
    >>> template[1, 1] = 1
    >>> print template
    [[ 0.  0.  0.]
     [ 0.  1.  0.]
     [ 0.  0.  0.]]
    >>> image = np.zeros((6, 6))
    >>> image[1, 1] = 1
    >>> image[4, 4] = -1
    >>> print image
    [[ 0.  0.  0.  0.  0.  0.]
     [ 0.  1.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0. -1.  0.]
     [ 0.  0.  0.  0.  0.  0.]]
    >>> result = match_template(image, template)
    >>> print np.round(result, 3)
    [[ 1.    -0.125  0.     0.   ]
     [-0.125 -0.125  0.     0.   ]
     [ 0.     0.     0.125  0.125]
     [ 0.     0.     0.125 -1.   ]]
    >>> result = match_template(image, template, pad_input=True)
    >>> print np.round(result, 3)
    [[-0.125 -0.125 -0.125  0.     0.     0.   ]
     [-0.125  1.    -0.125  0.     0.     0.   ]
     [-0.125 -0.125 -0.125  0.     0.     0.   ]
     [ 0.     0.     0.     0.125  0.125  0.125]
     [ 0.     0.     0.     0.125 -1.     0.125]
     [ 0.     0.     0.     0.125  0.125  0.125]]
    """
    if np.any(np.less(image.shape, template.shape)):
        raise ValueError("Image must be larger than template.")
    image = convert(image, np.float32)
    template = convert(template, np.float32)

    if pad_input:
        pad_size = tuple(np.array(image.shape) + np.array(template.shape) - 1)
        pad_image = np.mean(image) * np.ones(pad_size, dtype=np.float32)
        h, w = image.shape
        i0, j0 = template.shape
        i0 /= 2
        j0 /= 2
        pad_image[i0:i0+h, j0:j0+w] = image
        image = pad_image
    result = _template.match_template(image, template)
    return result