text:
"""Classes to represent keypoints, i.e. points given as xy-coordinates."""
from __future__ import print_function, division, absolute_import

import numpy as np
import scipy.spatial.distance
import six.moves as sm

from .. import imgaug as ia
from .base import IAugmentable
from .utils import (
    normalize_imglike_shape,
    project_coords,
    _remove_out_of_image_fraction_,
    _handle_on_image_shape
)

def compute_geometric_median(points=None, eps=1e-5, X=None):
    """Estimate the geometric median of points in 2D.

    Code from https://stackoverflow.com/a/30305181

    Parameters
    ----------
    points : (N,2) ndarray
        Points in 2D. Second axis must be given in xy-form.

    eps : float, optional
        Distance threshold when to return the median.

    X : None or (N,2) ndarray, optional
        Deprecated.

    Returns
    -------
    (2,) ndarray
        Geometric median as xy-coordinate.

    """
    # pylint: disable=invalid-name
    if X is not None:
        assert points is None
        ia.warn_deprecated("Using 'X' is deprecated, use 'points' instead.")
        points = X

    y = np.mean(points, 0)

    while True:
        dist = scipy.spatial.distance.cdist(points, [y])
        nonzeros = (dist != 0)[:, 0]

        dist_inv = 1 / dist[nonzeros]
        dist_inv_sum = np.sum(dist_inv)
        dist_inv_norm = dist_inv / dist_inv_sum
        T = np.sum(dist_inv_norm * points[nonzeros], 0)

        num_zeros = len(points) - np.sum(nonzeros)
        if num_zeros == 0:
            y1 = T
        elif num_zeros == len(points):
            return y
        else:
            R = (T - y) * dist_inv_sum
            r = np.linalg.norm(R)
            rinv = 0 if r == 0 else num_zeros/r
            y1 = max(0, 1-rinv)*T + min(1, rinv)*y

        if scipy.spatial.distance.euclidean(y, y1) < eps:
            return y1

        y = y1

class Keypoint(object):
    """A single keypoint (aka landmark) on an image.

    Parameters
    ----------
    x : number
        Coordinate of the keypoint on the x axis.

    y : number
        Coordinate of the keypoint on the y axis.

    """

    def __init__(self, x, y):
        self.x = x
        self.y = y

    @property
    def coords(self):
        """Get the xy-coordinates as an ``(N,2)`` ndarray.

        Added in 0.4.0.

        Returns
        -------
        ndarray
            An ``(N, 2)`` ``float32`` ndarray with ``N=1`` containing the
            coordinates of this keypoints.

        """
        arr = np.empty((1, 2), dtype=np.float32)
        arr[0, :] = [self.x, self.y]
        return arr

    @property
    def x_int(self):
        """Get the keypoint's x-coordinate, rounded to the closest integer.

        Returns
        -------
        result : int
            Keypoint's x-coordinate, rounded to the closest integer.

        """
        return int(np.round(self.x))

    @property
    def y_int(self):
        """Get the keypoint's y-coordinate, rounded to the closest integer.

        Returns
        -------
        result : int
            Keypoint's y-coordinate, rounded to the closest integer.

        """
        return int(np.round(self.y))

    @property
    def xy(self):
        """Get the keypoint's x- and y-coordinate as a single array.

        Added in 0.4.0.

        Returns
        -------
        ndarray
            A ``(2,)`` ``ndarray`` denoting the xy-coordinate pair.

        """
        return self.coords[0, :]

    @property
    def xy_int(self):
        """Get the keypoint's xy-coord, rounded to closest integer.

        Added in 0.4.0.

        Returns
        -------
        ndarray
            A ``(2,)`` ``ndarray`` denoting the xy-coordinate pair.

        """
        return np.round(self.xy).astype(np.int32)

    def project_(self, from_shape, to_shape):
        """Project in-place the keypoint onto a new position on a new image.

        E.g. if the keypoint is on its original image
        at ``x=(10 of 100 pixels)`` and ``y=(20 of 100 pixels)`` and is
        projected onto a new image with size ``(width=200, height=200)``, its
        new position will be ``(20, 40)``.

        This is intended for cases where the original image is resized.
        It cannot be used for more complex changes (e.g. padding, cropping).

        Added in 0.4.0.

        Parameters
        ----------
        from_shape : tuple of int
            Shape of the original image. (Before resize.)

        to_shape : tuple of int
            Shape of the new image. (After resize.)

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Keypoint object with new coordinates.
            The instance of the keypoint may have been modified in-place.

        """
        xy_proj = project_coords([(self.x, self.y)], from_shape, to_shape)
        self.x, self.y = xy_proj[0]
        return self

    def project(self, from_shape, to_shape):
        """Project the keypoint onto a new position on a new image.

        E.g. if the keypoint is on its original image
        at ``x=(10 of 100 pixels)`` and ``y=(20 of 100 pixels)`` and is
        projected onto a new image with size ``(width=200, height=200)``, its
        new position will be ``(20, 40)``.

        This is intended for cases where the original image is resized.
        It cannot be used for more complex changes (e.g. padding, cropping).

        Parameters
        ----------
        from_shape : tuple of int
            Shape of the original image. (Before resize.)

        to_shape : tuple of int
            Shape of the new image. (After resize.)

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Keypoint object with new coordinates.

        """
        return self.deepcopy().project_(from_shape, to_shape)

    def is_out_of_image(self, image):
        """Estimate whether this point is outside of the given image plane.

        Added in 0.4.0.

        Parameters
        ----------
        image : (H,W,...) ndarray or tuple of int
            Image dimensions to use.
            If an ``ndarray``, its shape will be used.
            If a ``tuple``, it is assumed to represent the image shape
            and must contain at least two integers.

        Returns
        -------
        bool
            ``True`` is the point is inside the image plane, ``False``
            otherwise.

        """
        shape = normalize_imglike_shape(image)
        height, width = shape[0:2]
        y_inside = (0 <= self.y < height)
        x_inside = (0 <= self.x < width)
        return not y_inside or not x_inside

    def compute_out_of_image_fraction(self, image):
        """Compute fraction of the keypoint that is out of the image plane.

        The fraction is always either ``1.0`` (point is outside of the image
        plane) or ``0.0`` (point is inside the image plane). This method
        exists for consistency with other augmentables, e.g. bounding boxes.

        Added in 0.4.0.

        Parameters
        ----------
        image : (H,W,...) ndarray or tuple of int
            Image dimensions to use.
            If an ``ndarray``, its shape will be used.
            If a ``tuple``, it is assumed to represent the image shape
            and must contain at least two integers.

        Returns
        -------
        float
            Either ``1.0`` (point is outside of the image plane) or
            ``0.0`` (point is inside of it).

        """
        return float(self.is_out_of_image(image))

    def shift_(self, x=0, y=0):
        """Move the keypoint around on an image in-place.

        Added in 0.4.0.

        Parameters
        ----------
        x : number, optional
            Move by this value on the x axis.

        y : number, optional
            Move by this value on the y axis.

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Keypoint object with new coordinates.
            The instance of the keypoint may have been modified in-place.

        """
        self.x += x
        self.y += y
        return self

    def shift(self, x=0, y=0):
        """Move the keypoint around on an image.

        Parameters
        ----------
        x : number, optional
            Move by this value on the x axis.

        y : number, optional
            Move by this value on the y axis.

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Keypoint object with new coordinates.

        """
        return self.deepcopy().shift_(x, y)

    def draw_on_image(self, image, color=(0, 255, 0), alpha=1.0, size=3,
                      copy=True, raise_if_out_of_image=False):
        """Draw the keypoint onto a given image.

        The keypoint is drawn as a square.

        Parameters
        ----------
        image : (H,W,3) ndarray
            The image onto which to draw the keypoint.

        color : int or list of int or tuple of int or (3,) ndarray, optional
            The RGB color of the keypoint.
            If a single ``int`` ``C``, then that is equivalent to ``(C,C,C)``.

        alpha : float, optional
            The opacity of the drawn keypoint, where ``1.0`` denotes a fully
            visible keypoint and ``0.0`` an invisible one.

        size : int, optional
            The size of the keypoint. If set to ``S``, each square will have
            size ``S x S``.

        copy : bool, optional
            Whether to copy the image before drawing the keypoint.

        raise_if_out_of_image : bool, optional
            Whether to raise an exception if the keypoint is outside of the
            image.

        Returns
        -------
        image : (H,W,3) ndarray
            Image with drawn keypoint.

        """
        # pylint: disable=redefined-outer-name
        if copy:
            image = np.copy(image)

        if image.ndim == 2:
            assert ia.is_single_number(color), (
                "Got a 2D image. Expected then 'color' to be a single number, "
                "but got %s." % (str(color),))
        elif image.ndim == 3 and ia.is_single_number(color):
            color = [color] * image.shape[-1]

        input_dtype = image.dtype
        alpha_color = color
        if alpha < 0.01:
            # keypoint invisible, nothing to do
            return image

        if alpha > 0.99:
            alpha = 1
        else:
            image = image.astype(np.float32, copy=False)
            alpha_color = alpha * np.array(color)

        height, width = image.shape[0:2]

        y, x = self.y_int, self.x_int

        x1 = max(x - size//2, 0)
        x2 = min(x + 1 + size//2, width)
        y1 = max(y - size//2, 0)
        y2 = min(y + 1 + size//2, height)

        x1_clipped, x2_clipped = np.clip([x1, x2], 0, width)
        y1_clipped, y2_clipped = np.clip([y1, y2], 0, height)

        x1_clipped_ooi = (x1_clipped < 0 or x1_clipped >= width)
        x2_clipped_ooi = (x2_clipped < 0 or x2_clipped >= width+1)
        y1_clipped_ooi = (y1_clipped < 0 or y1_clipped >= height)
        y2_clipped_ooi = (y2_clipped < 0 or y2_clipped >= height+1)
        x_ooi = (x1_clipped_ooi and x2_clipped_ooi)
        y_ooi = (y1_clipped_ooi and y2_clipped_ooi)
        x_zero_size = (x2_clipped - x1_clipped) < 1  # min size is 1px
        y_zero_size = (y2_clipped - y1_clipped) < 1
        if not x_ooi and not y_ooi and not x_zero_size and not y_zero_size:
            if alpha == 1:
                image[y1_clipped:y2_clipped, x1_clipped:x2_clipped] = color
            else:
                image[y1_clipped:y2_clipped, x1_clipped:x2_clipped] = (
                    (1 - alpha)
                    * image[y1_clipped:y2_clipped, x1_clipped:x2_clipped]
                    + alpha_color
                )
        else:
            if raise_if_out_of_image:
                raise Exception(
                    "Cannot draw keypoint x=%.8f, y=%.8f on image with "
                    "shape %s." % (y, x, image.shape))

        if image.dtype.name != input_dtype.name:
            if input_dtype.name == "uint8":
                image = np.clip(image, 0, 255, out=image)
            image = image.astype(input_dtype, copy=False)
        return image

    def generate_similar_points_manhattan(self, nb_steps, step_size,
                                          return_array=False):
        """Generate nearby points based on manhattan distance.

        To generate the first neighbouring points, a distance of ``S`` (step
        size) is moved from the center point (this keypoint) to the top,
        right, bottom and left, resulting in four new points. From these new
        points, the pattern is repeated. Overlapping points are ignored.

        The resulting points have a shape similar to a square rotated
        by ``45`` degrees.

        Parameters
        ----------
        nb_steps : int
            The number of steps to move from the center point.
            ``nb_steps=1`` results in a total of ``5`` output points (one
            center point + four neighbours).

        step_size : number
            The step size to move from every point to its neighbours.

        return_array : bool, optional
            Whether to return the generated points as a list of
            :class:`Keypoint` or an array of shape ``(N,2)``, where ``N`` is
            the number of generated points and the second axis contains the
            x-/y-coordinates.

        Returns
        -------
        list of imgaug.augmentables.kps.Keypoint or (N,2) ndarray
            If `return_array` was ``False``, then a list of :class:`Keypoint`.
            Otherwise a numpy array of shape ``(N,2)``, where ``N`` is the
            number of generated points and the second axis contains
            the x-/y-coordinates. The center keypoint (the one on which this
            function was called) is always included.

        """
        # TODO add test
        # Points generates in manhattan style with S steps have a shape
        # similar to a 45deg rotated square. The center line with the origin
        # point has S+1+S = 1+2*S points (S to the left, S to the right).
        # The lines above contain (S+1+S)-2 + (S+1+S)-2-2 + ... + 1 points.
        # E.g. for S=2 it would be 3+1=4 and for S=3 it would be 5+3+1=9.
        # Same for the lines below the center. Hence the total number of
        # points is S+1+S + 2*(S^2).
        nb_points = nb_steps + 1 + nb_steps + 2*(nb_steps**2)
        points = np.zeros((nb_points, 2), dtype=np.float32)

        # we start at the bottom-most line and move towards the top-most line
        yy = np.linspace(
            self.y - nb_steps * step_size,
            self.y + nb_steps * step_size,
            nb_steps + 1 + nb_steps)

        # bottom-most line contains only one point
        width = 1

        nth_point = 0
        for i_y, y in enumerate(yy):
            if width == 1:
                xx = [self.x]
            else:
                xx = np.linspace(
                    self.x - (width-1)//2 * step_size,
                    self.x + (width-1)//2 * step_size,
                    width)
            for x in xx:
                points[nth_point] = [x, y]
                nth_point += 1
            if i_y < nb_steps:
                width += 2
            else:
                width -= 2

        if return_array:
            return points
        return [self.deepcopy(x=point[0], y=point[1]) for point in points]

    def coords_almost_equals(self, other, max_distance=1e-4):
        """Estimate if this and another KP have almost identical coordinates.

        Added in 0.4.0.

        Parameters
        ----------
        other : imgaug.augmentables.kps.Keypoint or iterable
            The other keypoint with which to compare this one.
            If this is an ``iterable``, it is assumed to contain the
            xy-coordinates of a keypoint.

        max_distance : number, optional
            The maximum euclidean distance between a this keypoint and the
            other one. If the distance is exceeded, the two keypoints are not
            viewed as equal.

        Returns
        -------
        bool
            Whether the two keypoints have almost identical coordinates.

        """
        if ia.is_np_array(other):
            # we use flat here in case other is (N,2) instead of (4,)
            coords_b = other.flat
        elif ia.is_iterable(other):
            coords_b = list(ia.flatten(other))
        else:
            assert isinstance(other, Keypoint), (
                "Expected 'other' to be an iterable containing one "
                "(x,y)-coordinate pair or a Keypoint. "
                "Got type %s." % (type(other),))
            coords_b = other.coords.flat

        coords_a = self.coords

        return np.allclose(coords_a.flat, coords_b, atol=max_distance, rtol=0)

    def almost_equals(self, other, max_distance=1e-4):
        """Compare this and another KP's coordinates.

        .. note::

            This method is currently identical to ``coords_almost_equals``.
            It exists for consistency with ``BoundingBox`` and ``Polygons``.

        Added in 0.4.0.

        Parameters
        ----------
        other : imgaug.augmentables.kps.Keypoint or iterable
            The other object to compare against. Expected to be a
            ``Keypoint``.

        max_distance : number, optional
            See
            :func:`~imgaug.augmentables.kps.Keypoint.coords_almost_equals`.

        Returns
        -------
        bool
            ``True`` if the coordinates are almost equal. Otherwise ``False``.

        """
        return self.coords_almost_equals(other, max_distance=max_distance)

    def copy(self, x=None, y=None):
        """Create a shallow copy of the keypoint instance.

        Parameters
        ----------
        x : None or number, optional
            Coordinate of the keypoint on the x axis.
            If ``None``, the instance's value will be copied.

        y : None or number, optional
            Coordinate of the keypoint on the y axis.
            If ``None``, the instance's value will be copied.

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Shallow copy.

        """
        return self.deepcopy(x=x, y=y)

    def deepcopy(self, x=None, y=None):
        """Create a deep copy of the keypoint instance.

        Parameters
        ----------
        x : None or number, optional
            Coordinate of the keypoint on the x axis.
            If ``None``, the instance's value will be copied.

        y : None or number, optional
            Coordinate of the keypoint on the y axis.
            If ``None``, the instance's value will be copied.

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Deep copy.

        """
        x = self.x if x is None else x
        y = self.y if y is None else y
        return Keypoint(x=x, y=y)

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return "Keypoint(x=%.8f, y=%.8f)" % (self.x, self.y)

class KeypointsOnImage(IAugmentable):
    """Container for all keypoints on a single image.

    Parameters
    ----------
    keypoints : list of imgaug.augmentables.kps.Keypoint
        List of keypoints on the image.

    shape : tuple of int
        The shape of the image on which the objects are placed, i.e. the
        result of ``image.shape``.
        Should include the number of channels, not only height and width.

    Examples
    --------
    >>> import numpy as np
    >>> from imgaug.augmentables.kps import Keypoint, KeypointsOnImage
    >>>
    >>> image = np.zeros((70, 70))
    >>> kps = [Keypoint(x=10, y=20), Keypoint(x=34, y=60)]
    >>> kps_oi = KeypointsOnImage(kps, shape=image.shape)

    """

    def __init__(self, keypoints, shape):
        self.keypoints = keypoints
        self.shape = _handle_on_image_shape(shape, self)

    @property
    def items(self):
        """Get the keypoints in this container.

        Added in 0.4.0.

        Returns
        -------
        list of Keypoint
            Keypoints within this container.

        """
        return self.keypoints

    @items.setter
    def items(self, value):
        """Set the keypoints in this container.

        Added in 0.4.0.

        Parameters
        ----------
        value : list of Keypoint
            Keypoints within this container.

        """
        self.keypoints = value

    @property
    def height(self):
        """Get the image height.

        Returns
        -------
        int
            Image height.

        """
        return self.shape[0]

    @property
    def width(self):
        """Get the image width.

        Returns
        -------
        int
            Image width.

        """
        return self.shape[1]

    @property
    def empty(self):
        """Determine whether this object contains zero keypoints.

        Returns
        -------
        bool
            ``True`` if this object contains zero keypoints.

        """
        return len(self.keypoints) == 0

    def on_(self, image):
        """Project all keypoints from one image shape to a new one in-place.

        Added in 0.4.0.

        Parameters
        ----------
        image : ndarray or tuple of int
            New image onto which the keypoints are to be projected.
            May also simply be that new image's shape tuple.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Object containing all projected keypoints.
            The object may have been modified in-place.

        """
        # pylint: disable=invalid-name
        on_shape = normalize_imglike_shape(image)
        if on_shape[0:2] == self.shape[0:2]:
            self.shape = on_shape  # channels may differ
            return self

        for i, kp in enumerate(self.keypoints):
            self.keypoints[i] = kp.project_(self.shape, on_shape)
        self.shape = on_shape
        return self

    def on(self, image):
        """Project all keypoints from one image shape to a new one.

        Parameters
        ----------
        image : ndarray or tuple of int
            New image onto which the keypoints are to be projected.
            May also simply be that new image's shape tuple.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Object containing all projected keypoints.

        """
        # pylint: disable=invalid-name
        return self.deepcopy().on_(image)

    def draw_on_image(self, image, color=(0, 255, 0), alpha=1.0, size=3,
                      copy=True, raise_if_out_of_image=False):
        """Draw all keypoints onto a given image.

        Each keypoint is drawn as a square of provided color and size.

        Parameters
        ----------
        image : (H,W,3) ndarray
            The image onto which to draw the keypoints.
            This image should usually have the same shape as
            set in ``KeypointsOnImage.shape``.

        color : int or list of int or tuple of int or (3,) ndarray, optional
            The RGB color of all keypoints.
            If a single ``int`` ``C``, then that is equivalent to ``(C,C,C)``.

        alpha : float, optional
            The opacity of the drawn keypoint, where ``1.0`` denotes a fully
            visible keypoint and ``0.0`` an invisible one.

        size : int, optional
            The size of each point. If set to ``C``, each square will have
            size ``C x C``.

        copy : bool, optional
            Whether to copy the image before drawing the points.

        raise_if_out_of_image : bool, optional
            Whether to raise an exception if any keypoint is outside of the
            image.

        Returns
        -------
        (H,W,3) ndarray
            Image with drawn keypoints.

        """
        # pylint: disable=redefined-outer-name
        image = np.copy(image) if copy else image
        for keypoint in self.keypoints:
            image = keypoint.draw_on_image(
                image, color=color, alpha=alpha, size=size, copy=False,
                raise_if_out_of_image=raise_if_out_of_image)
        return image

    def remove_out_of_image_fraction_(self, fraction):
        """Remove all KPs with an OOI fraction of at least `fraction` in-place.

        'OOI' is the abbreviation for 'out of image'.

        This method exists for consistency with other augmentables, e.g.
        bounding boxes.

        Added in 0.4.0.

        Parameters
        ----------
        fraction : number
            Minimum out of image fraction that a keypoint has to have in
            order to be removed. Note that any keypoint can only have a
            fraction of either ``1.0`` (is outside) or ``0.0`` (is inside).
            Set this to ``0.0+eps`` to remove all points that are outside of
            the image. Setting this to ``0.0`` will remove all points.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Reduced set of keypoints, with those thathad an out of image
            fraction greater or equal the given one removed.
            The object may have been modified in-place.

        """
        return _remove_out_of_image_fraction_(self, fraction)

    def remove_out_of_image_fraction(self, fraction):
        """Remove all KPs with an out of image fraction of at least `fraction`.

        This method exists for consistency with other augmentables, e.g.
        bounding boxes.

        Added in 0.4.0.

        Parameters
        ----------
        fraction : number
            Minimum out of image fraction that a keypoint has to have in
            order to be removed. Note that any keypoint can only have a
            fraction of either ``1.0`` (is outside) or ``0.0`` (is inside).
            Set this to ``0.0+eps`` to remove all points that are outside of
            the image. Setting this to ``0.0`` will remove all points.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Reduced set of keypoints, with those thathad an out of image
            fraction greater or equal the given one removed.

        """
        return self.deepcopy().remove_out_of_image_fraction_(fraction)

    def clip_out_of_image_(self):
        """Remove all KPs that are outside of the image plane.

        This method exists for consistency with other augmentables, e.g.
        bounding boxes.

        Added in 0.4.0.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Keypoints that are inside the image plane.
            The object may have been modified in-place.

        """
        # we could use anything >0 here as the fraction
        return self.remove_out_of_image_fraction_(0.5)

    def clip_out_of_image(self):
        """Remove all KPs that are outside of the image plane.

        This method exists for consistency with other augmentables, e.g.
        bounding boxes.

        Added in 0.4.0.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Keypoints that are inside the image plane.

        """
        return self.deepcopy().clip_out_of_image_()

    def shift_(self, x=0, y=0):
        """Move the keypoints on the x/y-axis in-place.

        Added in 0.4.0.

        Parameters
        ----------
        x : number, optional
            Move each keypoint by this value on the x axis.

        y : number, optional
            Move each keypoint by this value on the y axis.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Keypoints after moving them.
            The object and its items may have been modified in-place.

        """
        for i, keypoint in enumerate(self.keypoints):
            self.keypoints[i] = keypoint.shift_(x=x, y=y)
        return self

    def shift(self, x=0, y=0):
        """Move the keypoints on the x/y-axis.

        Parameters
        ----------
        x : number, optional
            Move each keypoint by this value on the x axis.

        y : number, optional
            Move each keypoint by this value on the y axis.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Keypoints after moving them.

        """
        return self.deepcopy().shift_(x=x, y=y)

    @ia.deprecated(alt_func="KeypointsOnImage.to_xy_array()")
    def get_coords_array(self):
        """Convert all keypoint coordinates to an array of shape ``(N,2)``.

        Returns
        -------
        (N, 2) ndarray
            Array containing the coordinates of all keypoints.
            ``N`` denotes the number of keypoints. The second axis denotes
            the x/y-coordinates.

        """
        return self.to_xy_array()

    def to_xy_array(self):
        """Convert all keypoint coordinates to an array of shape ``(N,2)``.

        Returns
        -------
        (N, 2) ndarray
            Array containing the coordinates of all keypoints.
            ``N`` denotes the number of keypoints. The second axis denotes
            the x/y-coordinates.

        """
        result = np.zeros((len(self.keypoints), 2), dtype=np.float32)
        for i, keypoint in enumerate(self.keypoints):
            result[i, 0] = keypoint.x
            result[i, 1] = keypoint.y
        return result

    @staticmethod
    @ia.deprecated(alt_func="KeypointsOnImage.from_xy_array()")
    def from_coords_array(coords, shape):
        """Convert an ``(N,2)`` array to a ``KeypointsOnImage`` object.

        Parameters
        ----------
        coords : (N, 2) ndarray
            Coordinates of ``N`` keypoints on an image, given as a ``(N,2)``
            array of xy-coordinates.

        shape : tuple
            The shape of the image on which the keypoints are placed.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            :class:`KeypointsOnImage` object containing the array's keypoints.

        """
        return KeypointsOnImage.from_xy_array(coords, shape)

    @classmethod
    def from_xy_array(cls, xy, shape):
        """Convert an ``(N,2)`` array to a ``KeypointsOnImage`` object.

        Parameters
        ----------
        xy : (N, 2) ndarray or iterable of iterable of number
            Coordinates of ``N`` keypoints on an image, given as a ``(N,2)``
            array of xy-coordinates.

        shape : tuple of int or ndarray
            The shape of the image on which the keypoints are placed.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            :class:`KeypointsOnImage` object containing the array's keypoints.

        """
        xy = np.array(xy, dtype=np.float32)

        # note that np.array([]) is (0,), not (0, 2)
        if xy.shape[0] == 0:  # pylint: disable=unsubscriptable-object
            return KeypointsOnImage([], shape)

        assert xy.ndim == 2 and xy.shape[-1] == 2, (  # pylint: disable=unsubscriptable-object
            "Expected input array to have shape (N,2), "
            "got shape %s." % (xy.shape,))
        keypoints = [Keypoint(x=coord[0], y=coord[1]) for coord in xy]
        return KeypointsOnImage(keypoints, shape)

    def fill_from_xy_array_(self, xy):
        """Modify the keypoint coordinates of this instance in-place.

        .. note::

            This currently expects that `xy` contains exactly as many
            coordinates as there are keypoints in this instance. Otherwise,
            an ``AssertionError`` will be raised.

        Added in 0.4.0.

        Parameters
        ----------
        xy : (N, 2) ndarray or iterable of iterable of number
            Coordinates of ``N`` keypoints on an image, given as a ``(N,2)``
            array of xy-coordinates. ``N`` must match the number of keypoints
            in this instance.

        Returns
        -------
        KeypointsOnImage
            This instance itself, with updated keypoint coordinates.
            Note that the instance was modified in-place.

        """
        xy = np.array(xy, dtype=np.float32)

        # note that np.array([]) is (0,), not (0, 2)
        assert xy.shape[0] == 0 or (xy.ndim == 2 and xy.shape[-1] == 2), (  # pylint: disable=unsubscriptable-object
            "Expected input array to have shape (N,2), "
            "got shape %s." % (xy.shape,))

        assert len(xy) == len(self.keypoints), (
            "Expected to receive as many keypoint coordinates as there are "
            "currently keypoints in this instance. Got %d, expected %d." % (
                len(xy), len(self.keypoints)))

        for kp, (x, y) in zip(self.keypoints, xy):
            kp.x = x
            kp.y = y

        return self

    # TODO add to_gaussian_heatmaps(), from_gaussian_heatmaps()
    def to_keypoint_image(self, size=1):
        """Create an ``(H,W,N)`` image with keypoint coordinates set to ``255``.

        This method generates a new ``uint8`` array of shape ``(H,W,N)``,
        where ``H`` is the ``.shape`` height, ``W`` the ``.shape`` width and
        ``N`` is the number of keypoints. The array is filled with zeros.
        The coordinate of the ``n``-th keypoint is set to ``255`` in the
        ``n``-th channel.

        This function can be used as a helper when augmenting keypoints with
        a method that only supports the augmentation of images.

        Parameters
        -------
        size : int
            Size of each (squared) point.

        Returns
        -------
        (H,W,N) ndarray
            Image in which the keypoints are marked. ``H`` is the height,
            defined in ``KeypointsOnImage.shape[0]`` (analogous ``W``).
            ``N`` is the number of keypoints.

        """
        height, width = self.shape[0:2]
        image = np.zeros((height, width, len(self.keypoints)), dtype=np.uint8)
        assert size % 2 != 0, (
            "Expected 'size' to have an odd value, got %d instead." % (size,))
        sizeh = max(0, (size-1)//2)
        for i, keypoint in enumerate(self.keypoints):
            # TODO for float values spread activation over several cells
            # here and do voting at the end
            y = keypoint.y_int
            x = keypoint.x_int

            x1 = np.clip(x - sizeh, 0, width-1)
            x2 = np.clip(x + sizeh + 1, 0, width)
            y1 = np.clip(y - sizeh, 0, height-1)
            y2 = np.clip(y + sizeh + 1, 0, height)

            if x1 < x2 and y1 < y2:
                image[y1:y2, x1:x2, i] = 128
            if 0 <= y < height and 0 <= x < width:
                image[y, x, i] = 255
        return image

    @staticmethod
    def from_keypoint_image(image, if_not_found_coords={"x": -1, "y": -1},
                            threshold=1, nb_channels=None):
        """Convert ``to_keypoint_image()`` outputs to ``KeypointsOnImage``.

        This is the inverse of :func:`KeypointsOnImage.to_keypoint_image`.

        Parameters
        ----------
        image : (H,W,N) ndarray
            The keypoints image. N is the number of keypoints.

        if_not_found_coords : tuple or list or dict or None, optional
            Coordinates to use for keypoints that cannot be found in `image`.

            * If this is a ``list``/``tuple``, it must contain two ``int``
              values.
            * If it is a ``dict``, it must contain the keys ``x`` and
              ``y`` with each containing one ``int`` value.
            * If this is ``None``, then the keypoint will not be added to the
              final :class:`KeypointsOnImage` object.

        threshold : int, optional
            The search for keypoints works by searching for the argmax in
            each channel. This parameters contains the minimum value that
            the max must have in order to be viewed as a keypoint.

        nb_channels : None or int, optional
            Number of channels of the image on which the keypoints are placed.
            Some keypoint augmenters require that information.
            If set to ``None``, the keypoint's shape will be set
            to ``(height, width)``, otherwise ``(height, width, nb_channels)``.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            The extracted keypoints.

        """
        # pylint: disable=dangerous-default-value
        assert image.ndim == 3, (
            "Expected 'image' to have three dimensions, "
            "got %d with shape %s instead." % (image.ndim, image.shape))
        height, width, nb_keypoints = image.shape

        drop_if_not_found = False
        if if_not_found_coords is None:
            drop_if_not_found = True
            if_not_found_x = -1
            if_not_found_y = -1
        elif isinstance(if_not_found_coords, (tuple, list)):
            assert len(if_not_found_coords) == 2, (
                "Expected tuple 'if_not_found_coords' to contain exactly two "
                "values, got %d values." % (len(if_not_found_coords),))
            if_not_found_x = if_not_found_coords[0]
            if_not_found_y = if_not_found_coords[1]
        elif isinstance(if_not_found_coords, dict):
            if_not_found_x = if_not_found_coords["x"]
            if_not_found_y = if_not_found_coords["y"]
        else:
            raise Exception(
                "Expected if_not_found_coords to be None or tuple or list "
                "or dict, got %s." % (type(if_not_found_coords),))

        keypoints = []
        for i in sm.xrange(nb_keypoints):
            maxidx_flat = np.argmax(image[..., i])
            maxidx_ndim = np.unravel_index(maxidx_flat, (height, width))

            found = (image[maxidx_ndim[0], maxidx_ndim[1], i] >= threshold)
            if found:
                x = maxidx_ndim[1] + 0.5
                y = maxidx_ndim[0] + 0.5
                keypoints.append(Keypoint(x=x, y=y))
            else:
                if drop_if_not_found:
                    # dont add the keypoint to the result list, i.e. drop it
                    pass
                else:
                    keypoints.append(Keypoint(x=if_not_found_x,
                                              y=if_not_found_y))

        out_shape = (height, width)
        if nb_channels is not None:
            out_shape += (nb_channels,)
        return KeypointsOnImage(keypoints, shape=out_shape)

    def to_distance_maps(self, inverted=False):
        """Generate a ``(H,W,N)`` array of distance maps for ``N`` keypoints.

        The ``n``-th distance map contains at every location ``(y, x)`` the
        euclidean distance to the ``n``-th keypoint.

        This function can be used as a helper when augmenting keypoints with a
        method that only supports the augmentation of images.

        Parameters
        -------
        inverted : bool, optional
            If ``True``, inverted distance maps are returned where each
            distance value d is replaced by ``d/(d+1)``, i.e. the distance
            maps have values in the range ``(0.0, 1.0]`` with ``1.0`` denoting
            exactly the position of the respective keypoint.

        Returns
        -------
        (H,W,N) ndarray
            A ``float32`` array containing ``N`` distance maps for ``N``
            keypoints. Each location ``(y, x, n)`` in the array denotes the
            euclidean distance at ``(y, x)`` to the ``n``-th keypoint.
            If `inverted` is ``True``, the distance ``d`` is replaced
            by ``d/(d+1)``. The height and width of the array match the
            height and width in ``KeypointsOnImage.shape``.

        """
        height, width = self.shape[0:2]
        distance_maps = np.zeros((height, width, len(self.keypoints)),
                                 dtype=np.float32)

        yy = np.arange(0, height)
        xx = np.arange(0, width)
        grid_xx, grid_yy = np.meshgrid(xx, yy)

        for i, keypoint in enumerate(self.keypoints):
            y, x = keypoint.y, keypoint.x
            distance_maps[:, :, i] = (grid_xx - x) ** 2 + (grid_yy - y) ** 2
        distance_maps = np.sqrt(distance_maps)
        if inverted:
            return 1/(distance_maps+1)
        return distance_maps

    # TODO add option to if_not_found_coords to reuse old keypoint coords
    @staticmethod
    def from_distance_maps(distance_maps, inverted=False,
                           if_not_found_coords={"x": -1, "y": -1},
                           threshold=None, nb_channels=None):
        """Convert outputs of ``to_distance_maps()`` to ``KeypointsOnImage``.

        This is the inverse of :func:`KeypointsOnImage.to_distance_maps`.

        Parameters
        ----------
        distance_maps : (H,W,N) ndarray
            The distance maps. ``N`` is the number of keypoints.

        inverted : bool, optional
            Whether the given distance maps were generated in inverted mode
            (i.e. :func:`KeypointsOnImage.to_distance_maps` was called with
            ``inverted=True``) or in non-inverted mode.

        if_not_found_coords : tuple or list or dict or None, optional
            Coordinates to use for keypoints that cannot be found
            in `distance_maps`.

            * If this is a ``list``/``tuple``, it must contain two ``int``
              values.
            * If it is a ``dict``, it must contain the keys ``x`` and
              ``y`` with each containing one ``int`` value.
            * If this is ``None``, then the keypoint will not be added to the
              final :class:`KeypointsOnImage` object.

        threshold : float, optional
            The search for keypoints works by searching for the
            argmin (non-inverted) or argmax (inverted) in each channel. This
            parameters contains the maximum (non-inverted) or
            minimum (inverted) value to accept in order to view a hit as a
            keypoint. Use ``None`` to use no min/max.

        nb_channels : None or int, optional
            Number of channels of the image on which the keypoints are placed.
            Some keypoint augmenters require that information.
            If set to ``None``, the keypoint's shape will be set
            to ``(height, width)``, otherwise ``(height, width, nb_channels)``.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            The extracted keypoints.

        """
        # pylint: disable=dangerous-default-value
        assert distance_maps.ndim == 3, (
            "Expected three-dimensional input, got %d dimensions and "
            "shape %s." % (distance_maps.ndim, distance_maps.shape))
        height, width, nb_keypoints = distance_maps.shape

        drop_if_not_found = False
        if if_not_found_coords is None:
            drop_if_not_found = True
            if_not_found_x = -1
            if_not_found_y = -1
        elif isinstance(if_not_found_coords, (tuple, list)):
            assert len(if_not_found_coords) == 2, (
                "Expected tuple/list 'if_not_found_coords' to contain "
                "exactly two entries, got %d." % (len(if_not_found_coords),))
            if_not_found_x = if_not_found_coords[0]
            if_not_found_y = if_not_found_coords[1]
        elif isinstance(if_not_found_coords, dict):
            if_not_found_x = if_not_found_coords["x"]
            if_not_found_y = if_not_found_coords["y"]
        else:
            raise Exception(
                "Expected if_not_found_coords to be None or tuple or list or "
                "dict, got %s." % (type(if_not_found_coords),))

        keypoints = []
        for i in sm.xrange(nb_keypoints):
            # TODO introduce voting here among all distance values that have
            #      min/max values
            if inverted:
                hitidx_flat = np.argmax(distance_maps[..., i])
            else:
                hitidx_flat = np.argmin(distance_maps[..., i])
            hitidx_ndim = np.unravel_index(hitidx_flat, (height, width))
            if not inverted and threshold is not None:
                found = (distance_maps[hitidx_ndim[0], hitidx_ndim[1], i]
                         < threshold)
            elif inverted and threshold is not None:
                found = (distance_maps[hitidx_ndim[0], hitidx_ndim[1], i]
                         >= threshold)
            else:
                found = True
            if found:
                keypoints.append(Keypoint(x=hitidx_ndim[1], y=hitidx_ndim[0]))
            else:
                if drop_if_not_found:
                    # dont add the keypoint to the result list, i.e. drop it
                    pass
                else:
                    keypoints.append(Keypoint(x=if_not_found_x,
                                              y=if_not_found_y))

        out_shape = (height, width)
        if nb_channels is not None:
            out_shape += (nb_channels,)
        return KeypointsOnImage(keypoints, shape=out_shape)

    # TODO add to_keypoints_on_image_() and call that wherever possible
    def to_keypoints_on_image(self):
        """Convert the keypoints to one ``KeypointsOnImage`` instance.

        This method exists for consistency with ``BoundingBoxesOnImage``,
        ``PolygonsOnImage`` and ``LineStringsOnImage``.

        Added in 0.4.0.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Copy of this keypoints instance.

        """
        return self.deepcopy()

    def invert_to_keypoints_on_image_(self, kpsoi):
        """Invert the output of ``to_keypoints_on_image()`` in-place.

        This function writes in-place into this ``KeypointsOnImage``
        instance.

        Added in 0.4.0.

        Parameters
        ----------
        kpsoi : imgaug.augmentables.kps.KeypointsOnImages
            Keypoints to copy data from, i.e. the outputs of
            ``to_keypoints_on_image()``.

        Returns
        -------
        KeypointsOnImage
            Keypoints container with updated coordinates.
            Note that the instance is also updated in-place.

        """
        nb_points_exp = len(self.keypoints)
        assert len(kpsoi.keypoints) == nb_points_exp, (
            "Expected %d coordinates, got %d." % (
                nb_points_exp, len(kpsoi.keypoints)))

        for kp_target, kp_source in zip(self.keypoints, kpsoi.keypoints):
            kp_target.x = kp_source.x
            kp_target.y = kp_source.y

        self.shape = kpsoi.shape
        return self

    def copy(self, keypoints=None, shape=None):
        """Create a shallow copy of the ``KeypointsOnImage`` object.

        Parameters
        ----------
        keypoints : None or list of imgaug.Keypoint, optional
            List of keypoints on the image.
            If ``None``, the instance's keypoints will be copied.

        shape : tuple of int, optional
            The shape of the image on which the keypoints are placed.
            If ``None``, the instance's shape will be copied.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Shallow copy.

        """
        if keypoints is None:
            keypoints = self.keypoints[:]
        if shape is None:
            # use tuple() here in case the shape was provided as a list
            shape = tuple(self.shape)

        return KeypointsOnImage(keypoints, shape)

    def deepcopy(self, keypoints=None, shape=None):
        """Create a deep copy of the ``KeypointsOnImage`` object.

        Parameters
        ----------
        keypoints : None or list of imgaug.Keypoint, optional
            List of keypoints on the image.
            If ``None``, the instance's keypoints will be copied.

        shape : tuple of int, optional
            The shape of the image on which the keypoints are placed.
            If ``None``, the instance's shape will be copied.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Deep copy.

        """
        # Manual copy is far faster than deepcopy, so use manual copy here.
        if keypoints is None:
            keypoints = [kp.deepcopy() for kp in self.keypoints]
        if shape is None:
            # use tuple() here in case the shape was provided as a list
            shape = tuple(self.shape)

        return KeypointsOnImage(keypoints, shape)

    def __getitem__(self, indices):
        """Get the keypoint(s) with given indices.

        Added in 0.4.0.

        Returns
        -------
        list of imgaug.augmentables.kps.Keypoint
            Keypoint(s) with given indices.

        """
        return self.keypoints[indices]

    def __iter__(self):
        """Iterate over the keypoints in this container.

        Added in 0.4.0.

        Yields
        ------
        Keypoint
            A keypoint in this container.
            The order is identical to the order in the keypoint list
            provided upon class initialization.

        """
        return iter(self.items)

    def __len__(self):
        """Get the number of items in this instance.

        Added in 0.4.0.

        Returns
        -------
        int
            Number of items in this instance.

        """
        return len(self.items)

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return "KeypointsOnImage(%s, shape=%s)" % (
            str(self.keypoints), self.shape)

redpajama_set_name: RedPajamaGithub


Sorry, we are currently sold out of 'Guatemala El Socorro Maracaturra'. Please check back later.
New crop arrived mid September 2016 in grainpro.
Guatemala El Socorro y Anexos is multi award winning farm located within a half hour of Guatemala City in the town of Palencia. We have offered this coffee in the past and are fortunate enough to have procured it once again this year after a few years of its absence. At El Socorro y Anexos they grow a varietal called Maracaturra, an unusual hybrid that is formed by crossing very large Maragogype beans with the refined flavors of Caturra - a dwarf Bourbon that has its origins east of Africa. The farm began planting this varietal about 15 years ago and expanded production of it after having attained top rankings in the Guatemala Cup of Excellence competition. The competition, which has hundreds of submissions, is held once a year and seeks to find the best coffees in a given country. The winner's coffee are then sold at private, international live auctions.
This is 'washed' process coffee, meaning that the fruit pulp is washed away. Coffee is fruit and the cherries, once ripe and harvested, have their outer skin removed by a specialized machine. The beans, really the cherry's seeds, are encased in the center of the fruit's flesh which ferments over the course of a day or two and is then washed away before being dried. But El Socorro, has very unusual processing technique beyond this standard format. They believe that the warm fruit gets shocked with cold water during this process so they place the just picked cherries into a bath of warm, equal temperature water and let them cool gradually before being introduced to the full washing process. They attribute much of their accomplishment to this technique. The farm's success is the result of a strict quality control during whole process, since the management of the plantation, handpicking, wet mill and drying coffee is all done on the farm.
Cup Characteristics: Decidedly fruity and refined with delicate tropical fruit background notes. Complex, layered and silky smooth finish. Sophisticated coffee with considerable nuance and layers of flavor and texture. This a big, flavorful varietal that also delivers on acidity and finesse.
Roasting notes: A lighter style roast will highlight the coffee's lively flavors and going a bit darker, pulling as the coffee just begins second crack, will accentuate the jammy texture that this varietal offers.


General Motors reportedly developed the GM Diet to help its employees lose weight and feel healthier. GM is said to have collaborated on the diet with both the Food and Drug Administration and the US Department of Agriculture and that it was first used in field tests at Johns Hopkins Research Center in 1985.
This approach to weight loss—also known as "the cabbage soup diet" and "the Sacred Heart diet"—has been popular ever since.
This plan is said to work on the principle that the foods you eat will burn more calories than the amount of energy (calories) they provide for the body to store in the form of fat. People have reported losses of between 10 and 17 lbs per week on this plan.
While there is no evidence online that concludes that General Motors is the actual source of this plan (see this op-ed piece in the New York Times), there are plenty of reports of success by people who have done the plan.
The General Motors Diet is a seven-day eating plan that has been reported to bring weight losses of 10 to 17 lbs. in a week, compared to 1 to 2 lbs. per week on most conventional plans.
It not only reduces weight but puts the body through a detoxification process. This is because the content of it is mostly water: fruits, vegetables, milk and soup, as well as 6-8 glasses of water daily.
This detox will cleanse the body and set it up for better overall health after the seven days. After you have completed the detoxification process, you might find that you can no longer face the unhealthful, processed foods that may have led to your becoming overweight in the first place.
The main eating plan of the General Motors plan can be modified for people whose regular eating patterns may be different. This includes an Indian and vegetarian version. Hence, the GM eating plan is not as restrictive as some other plans.
Both the fruits and vegetables that are eaten on this plan and the amount of water that is drunk promote faster digestion. This can help you lose weight quicker as the body is not holding on to what it does not need. By drinking at least 6-8 glasses of water a day, the body will begin to realize that it does not need to retain water as it is getting all the water it needs on a regular basis.
The GM plan can be of particular benefit to people who have suffered from constipation, as this eating regimen promotes regular bowel movements (necessary for good overall health). This helps rid the body of waste products and toxins that can make you feel sluggish and unhealthy.
There is no specific exercise recommendation in the GM plan.
While this is a workable plan that has been around for decades (known variously as "the cabbage diet" or "Sacred Heart Diet" in addition to "the GM Diet"), no single plan is appropriate for all people.
If you're deciding whether or not to do this way of eating, you'll find this comparison useful. We've put together the details on how the GM plan stacks up against two of today's most popular — and our favorite — plans. The other plans, Venus Factor, The 3-Week Diet each have a wider range of benefits, including a supporting community of other dieters and detailed resources making it much easier to stay on track with the plans.
Depending on what you need from a program and your personal preferences, there may be a better plan for you than the GM plan.
Rapid and significant, with reported losses of 5 to 10 lbs. in a week.
Highly restricted, mostly fruit & vegetable menu.
No dietary restrictions other than moderation and effective food-combining.
Brian Flatt, a sports nutritionist and health coach with a biology degree.
Comparison Conclusion: Which Diet is Best For Me?
Information about the GM plan is free on the Internet, whereas the other three plans must be purchased. However, the quality of resources the other plans give you is probably worth the cost.
The GM plan, though evidently workable (based on testimonials on YouTube and elsewhere online), is a plan with mysterious (and possibly fictional) origins and no cohesive support and no guarantees.
On the other hand, the 3-Week Diet and Venus Factor come from known, reputable sources. Each has its own official published information (book, manual, etc.). And each is based on medical or scientific principles.
The Venus Factor and 3-week Diet also have cohesive support networks which we think is particularly important for a plan that's going to be challenging at times. And both the 3-week Diet and the Venus Factor come with a 60-day money-back guarantee, so if you don't get the results you were expecting, you can just return the product and you haven't lost anything.
Lastly, only the GM plan admits of possible adverse effects as well as a common "bounce-back" effect where your weight jumps back up again after you stop eating that way. That may be somewhat explained by this being as much a "detox" as a weight-loss way of eating, however bouncing right back up to your previous weight isn't what most of us are looking for.
If you're trying to make a decision on whether to do the GM plan, or a different plan, go ahead and skim through the rest of our guide which details the GM plan day-by-day and answers a few common questions. Then, check out the informational materials for the other plans we recommend so you can make an informed decision on which one will suit you best.
On each of the seven days, you will drink 6 -8 glasses of water, except where otherwise noted.
Day 1 You can eat any fruit but bananas. There is no limit on quantity; eat as much fruit as you want. It is recommended that you eat a lot of melons on the first day. In fact, if you limit your fruit consumption to melons, it will get your weight loss off to a great start.
Day 2 Fruits are replaced with vegetables on the second day. You can eat them either cooked or raw and there is restriction on the types or amount you can eat. You can even have a baked potato for breakfast on this day, with a pat of butter if you like. This will provide the body with the complex carbohydrates that will provide energy for the rest of the day. Vegetables provide plenty of essential nutrients and fiber and are virtually calorie-free.
Day 3 Except for bananas and potatoes, you can eat a mixture of fruit and vegetables on this day—as much variety as you like, in whatever quantities you choose. Potatoes are no longer needed, as carbohydrates will come from the fruit. By this stage the body is prepared to start burning excess pounds.
Day 4 Bananas, milk and soup make up the menu. You can eat up to eight bananas and three glasses of milk on this day (although you may find that you don't eat all the bananas). You may consume as much of the soup as you like. (Soup recipe below) The bananas are important because they will help to replace the potassium and sodium that the body would have lost in the previous three days. There should be fewer cravings for sweets by this point.
Day 5 Today, you will eat beef and tomatoes: six whole tomatoes and two 10 oz. portions of beef. The beef can be eaten in the form of hamburger patties. All of the tomatoes should be eaten but not all the beef needs to be consumed. Increase your water intake by one quart today to help the body cleanse itself of the uric acid that will be produced by digesting the beef. The meat will provide your body with iron and protein and tomatoes provide fiber, which aids digestion.
Day 6 You will eat beef again today but will replace the tomatoes with a variety of vegetables of your own choosing. You may eat as much of each as you like. Note that by this day, the body is completely inclined towards weight loss and you should see a noticeable difference in the way you look and feel compared to when you started the diet.
Day 7 On the last day of the plan, you eat brown rice, fruit juice and unlimited vegetables. After following the meal plan for the last seven days, you should have completely cleansed and flushed out your system and should also find that you are 10 to 17 lbs. lighter than you were a week ago.
Water is the recommended choice of beverage on this weight-loss plan and should be consumed in large quantities. However, there are a number of other drinks that are allowed, as long as they are consumed alongside water. These include black coffee, black tea and club soda.
What Happens When The Diet Has Finished?
If you still have more weight to lose after following the plan for one week, you can repeat it as many times as you require. Following the first week, you can reintroduce some alcohol (beer or white wine only) but it should not be consumed to excess.
The question of whether the weight will stay off after the person has finished the diet depends more on you than the diet itself.
The GM plan consists of fresh, unprocessed food. If you get into the habit of eating these types of foods, then this will make it easier for you to keep the weight off. However, if you go back to the same eating habits that led you to them become overweight, you will likely put the weight back on.
Throughout the week, you should undertake regular exercise along with the eating plan. You should aim for at least ten minutes every day. The body may experience a shock when you start it because it is such a different way of eating that what the body is used to. Exercise will help the body to deal with the shock.
Getting in the habit of regular exercise will also help you to keep the weight off after you have reached your target weight.
Are There Any Side Effects To The GM Diet?
You might experience sudden muscle weakness during the first few days. This is because you will not be consuming any protein during this time. Exercise can help to make the muscles feel stronger (and they will begin to feel strong again when protein is introduced later on in the week).
Another side effect is dehydration and incessant thirst. You can prevent this by increasing your intake of water. On the GM plan, you are encouraged to drink as much water as you possibly can. Feel free to increase the amount of water until you are satisfied.
You may also experience headaches initially. These will disappear once your body gets used to this new way of eating. Drinking a lot of water and engaging in regular exercise will also help alleviate these headaches.
The GM Soup is ridiculously easy to make and consists of mainly vegetable ingredients. This soup can be eaten throughout the week in unlimited quantities and the eating of the soup as often as possible is encouraged.
Tip: The soup helps you stay hydrated while your body is clearing out excess fat.


AASTOCKS.com Limited provides the information and services on an "AS IS" basis. The information and contents on this website are subject to change without notice.
AASTOCKS.com Limited reserves the right, in its sole discretion but without any obligation, to make improvements to, or correct any error or omissions in any portion of this website at any time. The subscriber or site visitor agrees not to reproduce, retransmit, disseminate, distribute, broadcast, publish, circulate, sell or commercially exploit the information and contents on this website in any manner without the express written consent of AASTOCKS.com Limited. Investing and trading in stocks, currencies and other securities are very risky. AASTOCKS.com Limited encourages you to use the risk management and educational tools on this website. AASTOCKS.com Limited cannot and does not give any assurance that the present or future buy/sell commentaries and signals on this website will be profitable. AASTOCKS.com Limited cannot guarantee, and the subscriber or site visitor should not assume, that the future performance will equal past performance.


text:
1970s, French cinema, Horror/Eerie
Lips of Blood (1975)
September 7, 2006 filmfreedoniaGrand Guignol, Vampires 4 Comments
Lèvres de Sang
Director: Jean Rollin
Jean Rollin was a whole grain cinema anarchist and one of the relatively few French horror directors of his time. He began with homemade shorts and rose all the way to directing homemade features. His films skirt soft-core pornography and, when circumstances require, plunge right in. But he's also one of the most authentic poets every to take up the art form. Rollin debut feature, Le Viol du Vampire (1967) arose from several shorts he was asked to make for a French distributor who needed to fill out a bill sporting a short American vampire film. Rollin The resulting film was a predictably uneven, but attention-winning mish-mash of surrealism, Grand Guignol, and black humor. Rollin became one of the few true heirs to arise from a long tradition of Parisian underground cinema whose forebears include Feuillade and Bunuel, as well as French Gothic literature (Leroux was his favorite author), and the vast, semivisible world of European S&M comics (one of the major artists of which, Druillet, designed Rollins' posters and appeared in Le Viol). Visually, Rollin's films, with their semiclothed females arranged in geometric forms and intensely fetishist poses, recreate that style vividly. As in Feuillade and the early Dali-Bunuel collaborations, he utilised Paris, that marvellous free set, and set up against it the most bizarre and impossible images he could concoct.
His masterpiece is Lèvres de Sang. When I say masterpiece I maintain proportions. It's not a film as free from defects and soaring in its ambitions as Les Enfants du Paradis or The Seven Samurai. In the murky realm of '70s Euro-cinema, experimental, genre, and off-beat directors maintained their careers by spicing their films with nudity to satisfy fleapit theatre crowds and the distributors who serviced them. For Rollin, this was hardly a problem; he was dedicated eroticist, and his films enact the sexual aspects most horror films depict only metaphorically. They're adult fairy tales, dressed in gothic-erotic clothing. To see how good Rollin was at this, it's an easy task to compare the unembarrassed sexuality of Lèvres de Sang with any late-period Hammer film, say, Twins Of Evil (1972), and outclassed many a more high-toned director's efforts to interrogate the genre.
In Lèvres de Sang, Rollin presents an uncompromisingly direct study of the incestuous that underlies many vampire mythology which has corrupt ancestors heave off the lids of their tombs and spread disease and death among their descendants. Simultaneously, Lèvres de Sang succeeds in capturing a note of wistful longing for the scenes, hints, landscapes, people that remain on the very horizon of childhood memory, which can, thanks to some small evocation—the right tint of light, a smell, a familiar face—lance right through your adult perceptions and memories to present unfulfilled chances and unanswered questions, even mysteries. The film begins in a dank crypt where a middle-aged woman with a girlish face, wearing a veil and furs, is supervising men who are placing in the crypt several coffins. Cut to an exterior shot of a ruined chateau—a pull-back reveals it's just a photo on the wall of a Parisian apartment, where a Bunuel-boring society party is occurring. A man in his thirties, tall, blonde-haired Frédéric (Jean-Lou Philippe, who also cowrote the screenplay with Rollin), is stricken in fascination by the image to the point of ignoring his girlfriend. He shakes himself from his reverie and finds her lounging on a divan with a black-haired woman, who, in reply to Frédéric's compliment of her perfume, suggests a pretty smell is like a memory or a beautiful woman, the most precious and transitory of thrills. Frédéric drops into a memory. As a boy, lost at night, he entered the ruin. Dwelling within it was a teenaged girl (Anne Briand) with short brown hair, a pale face, red lips, and draped in white clothes, who greeted him with delicate affection and settled him down to sleep for the night. In the morning, before dawn, she woke him up to send him on his way home. As he rushed from the ruin, he shut the gate, locking her in, but he called back that he loved her and would return to free her.
Frédéric's girlfriend finds his preoccupation sufficient to walk off in a huff. Frédéric asks guests about the picture, but no one knows the place it depicts. Frédéric appeals to his mother, who we recognise is the woman from the opening, and tries to explain the striking memory the photo evokes. The girl haunts him and, as he says, "I love her the way you love at twelve." There are yawning holes in Frédéric's childhood recollections, apparently caused by the traumatising death of his father. His mother impatiently, and a touch desperately, denies the event occurred. Frédéric is unconvinced, and gets a lead from another guest about a photographer who took the shot. This is the black-haired lady, who, when he visits her salon, is busy taking nude photos of a model (a quick-forward remote is advisable here, unless of course you dig it). The photographer tells Frédéric she was paid to keep the location of the ruin secret, but finds him sufficiently attractive (the advantages of coauthoring the script) that she promises to look up the location and meet him later, when she'll be on a midnight photo shoot at the Paris Aquarium.
To waste time until the rendezvous, Frédéric goes to a movie theatre (showing what looks awfully like one of Rollin's earlier films) and spies a familiar figure standing in the rear exit. Borrowing an usher's flashlight, he sees it's the girl of his memory before she disappears. He pursues her outside and sees her by the gates of Montmartre Cemetery. Bewildered but determined, Frédéric climbs the gate and follows her intermittent appearances until they lead him into the familiar crypt. Frédéric breaks open the coffins, and finds bats grotesquely entangled in shrouds. Frédéric runs off, and the bats turn into young vampire women—draped in see-through shrouds, natch—who look like bloodsucking, heroin-chic fashion models. Most striking are a pair of twins (Catherine and Marie-Pierre Castel), who begin stalking the rain-gleaming Parisian streets. Frédéric, unaware of this, encounters a tragic-looking woman wearing too much make-up,who claims to be the girl from the castle. But she's only a paid decoy who lures him into a room and locks him up. He is freed by the twins, who have torn the woman's throat out.
Frédéric arrives at the Aquarium, where he passes a suspicious man (who resembles a homicidal Ron Burgundy) and finds the photographer, murdered, in one of the displays. Frédéric pursues the assassin onto a metro train, where his quarry pulls a gun on him. Frédéric escapes from the train, jumps off an overpass, and is pursued. He is saved again by the vampires, who turn on a fountain, obscuring Frédéric from the assassin's aim. Frédéric, distraught, goes to his mother for help, but she has him hauled away by the men in white coats. Frédéric is brought straitjacketed before a psychiatrist, who cheerfully proposes using shock treatment on him, but finds—in the film's funniest pay-off—his two nurses are actually the vampire twins, and they kill the good doctor. Frédéric is free, but without hope of solving the mystery until the girl appears beside a blind postcard seller, pointing to one of the cards; it shows the chateau and its location.
Frédéric reaches the chateau, to find the vampire girls have congregated there. He penetrates the ruin and finds the belongings of the teenaged girl, and a sealed coffin, inside of which she lies with a pin in her heart. His mother appears and explains that the girl is his older sister, Jennifer. Made a vampire at the age of 16, she killed Frédéric's father and created the other vampires, who terrorized the countryside. The mother staked Jennifer, but could not bring herself to behead her or the other girls, so they were all imprisoned. Her tolerance is at an end. Outside, her paid killers hunt down and stake the vampire girls, and she requests that Frédéric perform the coup-de-grace of beheading his sister to end the evil. As the bodies of the vampires are incinerated in a pit, Frédéric appears with a severed head—but it is actually from one of the girl's dolls—that he throws in the fire. When his mother and the men have left, Frédéric removes the pin from Jennifer's heart. She awakens and the pair celebrate their joyful reunion. She explains that though she was paralysed, she had learned to project her thoughts, which is how she could appear to him. After having sex on the beach, she turns him into a vampire, and they seal themselves in a coffin to drift on the sea to an island where they will live off shipwrecked sailors. This is a splendidly antisocial twist on the traditional imperative of the vampire story, particularly of stories like Le Fanu's Carmilla, where the lesbian title character must be destroyed so the patriarchy remains unthreatened (and yet, Rollin comes closer than anyone else to capturing the nocturne tone of Le Fanu's writing).
In a less imaginative film, the image of threatening female sexuality would be obliterated, and the man's need to transgress, to break beyond the boundaries of society and memory dully punished or be retracted. Or worse yet, in the modern mould, the triumph of evil would be a facile punchline. Instead it's an oddly idealistic finale, reminiscent of Pasolini's principles. Frédéric blindly believes, from the beginning, that Jennifer's lost, wounded, caring beauty is worth defying death, madness, and all social values, and remains true to this instinct to the end. Even as Jennifer's vampire acolytes are murderous, the mother's methods of keeping the secret safe, the disease trapped, are just as bad. The brutality of the standard vampire-killing–phallic penetration by staking–is highlighted by the forlorn sight of the twins, a stake having gone right through one into the other, sinking to death clutching each other like children. The news that Jennifer killed his father only seems to confirm that her chief crime was not vampirism, but up-ending the bourgeois family structure. The patriarchy was destroyed early, and their mother's compensatory, viciously repressive matriarchy is finally outwitted. There is a sorrow to the finale as well as a liberation. Though Frédéric and Jennifer have found each other, death is death, no matter how animated.
Thematically interesting as Lèvres de Sang is, it exists entirely to justify Rollin's creation of gorgeously weird images, and evocation of a rare, haunted mood. Few other films in the genre that approach its sonorus, alien poetry, oddities like Theodor Dreyer's Vampyr (1931) and John Hancock's Let's Scare Jessica To Death (1971); only Fellini's 8½ (1963) equals it for evoking how childhood recollections bleed into the present. Dotted through the film are memorable touches, essayed in what is, considering the film's miniscule budget, obscenely pretty, silk-textured cinematography by Jean-François Robin. At the party, where a bunch of teenagers, flagrantly dressed down, dart between the evening-dressed guests and pinch food from the buffet. The tableaux vivant shots of the vampire girls around the chateau, semiclothed by wind-wafting silks. The hilarious-horrible flashback out of a BDSM comic where the vampire girls drag a nude, chained victim to their lair. The starkly nasty sight of the dead photographer, lying upside-down, bare-breasted and bloodless on water-washed rocks. The scenes where Frédéric pursues and is pursued by the assassin, which evoke Hitchcock, Lang, and Feuillade. Frédéric kissing the dollhead's lips in the deathly chill of dawn, and his mother's veiled face stony in triumph.
The finale offers a symphony of atavistic images as Jennifer invokes an orchestra in the sounds of nature, "conducted by a madman!", before Frédéric and Jennifer entwine naked forms, white as driftwood. Jennifer stands atop the cliffs like the human equivalent of the Wicker Man, arms raised in a rite of primal nature worship. Frédéric lowers himself into the coffin and stops momentarily to study her fine but deathly still face, a moment laced with both an awed sense of beauty and also a queasy feeling of strange, necrophiliac desire: love as stasis, death as the only way to enact perfect desire. Their coffin, buffeted by the waves, brushes against the black ribs of a groin before finally floating out into the ship-ridden sea. Lèvres de Sang was a flop, satisfying neither horror buffs out for blood nor porn patrons, and it's easy to see why. It's actually an assertion of primal innocence and places both gore and sex at the disposal of its playful narrative. Rollin survived–just–and limped along under various pseudonyms before nearly recapturing some of his old intensity with Fascination (1979) and La Nuit des Traqueés (1980), both featuring Brigitte Lahaie who, later, added memorable erotic shape to Henry & June (1990). l
→ The Hound of the Baskervilles (1959)
← Operazione Paura (1966)
4 thoughts on "Lips of Blood (1975)"
Spook says:
Hey!I'm big into old vampire and horror films especially from the late 60's early 70'sDid you see Lèvres de Sang or just grab a review for us. It's on my list though and I remember seeing Lets Scare Jessica to Death when I was about nine and I still remember it.Thanks
Hey, spook, welcome to Ferdy on Films. This review is by my colleague, Rod Heath. However, I'm a horror fan, and you mention one of my favorite horror films, Let's Scare Jessica to Death. I will write a review of it when I've had a chance to re-view it. It is one of the most effective films of its type and a favorite of mine–along with Sleepy Hollow–for Halloween viewing.
dana dearmond says:
what… this has absolutely nothing to do with lesbian bondage. sometimes google can lead to the most upredicatble places. nice blog btw. now im back to my bondage search.
Good luck, Dana. I fear your chances of finding lesbian bondage pics amidst the vast landscape of internet pornography are bleak indeed.

redpajama_set_name: RedPajamaCommonCrawl


text:
Authorities investigate fatal stabbing in Newark
Updated: Aug. 19, 2015, 9:51 p.m. |
Published: Aug. 19, 2015, 8:51 p.m.
Vernal Coleman | NJ Advance Media for NJ.com
-- Following
two early-morning fatal shootings
, authorities are investigating a stabbing death in the Ironbound district, county officials confirmed.
On Wednesday afternoon, investigators from the Essex County Prosecutor's Office could be seen at the scene of the incident near the intersection of Van Buren and Ferry Street.
Essex County Prosecutor's Office spokeswoman Katherine Carter said the male victim was killed during an apparent home burglary. Additional details of the incident are not immediately available, she said.
The stabbing follows two separate overnight shooting incidents, each of which left one person dead.
The first occurred near the 300 block of Sanford Avenue near midnight. Hours later, a second person was fatally shot in the 200 block of Ridgewood Avenue, Carter confirmed. Neither victim has been identified by authorities.
Vernal Coleman can be reached at vcoleman@njadvancemedia.com. Follow him on Twitter at @vernalcoleman. Find NJ.com on Facebook.


When you need to ensure that your company is marketing in an effective way, you have to try new strategies to stay ahead of the competition. A wise https://www.youtube.com/watch?v=5z46IXJdFL4/, effective way to do that is to try using video inside your marketing efforts. Video can be a personal way to talk to your clients. Below are a few great guidelines to make the most of video.
If you're intending to make an advertising and marketing video, ensure that it stays short and to the level. Lots of people do not possess an incredibly long attention span and they wish to learn their info straight away. If you would like have got a long video, tend not to make merely one. Split it in a series.
Videos help make your site more interactive but remember that they are certainly not an ideal solution for the search engine optimization campaign. You may optimize your videos by choosing descriptive titles loaded with keywords and adding a transcript or possibly a breakdown of the material in the video you need to feature.
Include a screenshot of your respective website within your video. This allows your viewers view your site when they watch. This really is pertinent in tutorial videos. Simply save a copy of your respective screenshot and utilize a youtube video editing computer software to include your screenshot into your videos.
Whenever anyone asks an issue within the comments on the videos, consider if you can answer them in another video. If you consider about it, you can come up with a humorous answer which supplies all of them with the information they seek together with a fun video if others would like to watch, every one of the better!
To aid garner even more views embed your video with your website. The majority of people once they consider video marketing think only of posting a youtube video on YouTube. Instead, post it on the website and may include a web link on the Facebook wall and Tweet concerning your new video on Twitter.
Be mindful of how long your video is. Users searching the world wide web are often in a big hurry. They don't want to watch a a few minute video. The truth is, research has shown that setting up a youtube video that is less than 30 seconds long is amongst the keys to success.
Write a script for your personal introduction and closing of each and every video. The video must start with an introduction and tell what information the recording will impart. With the conclusion in the video, put your organization name inside the video.
Do not try to do it all yourself. It is actually challenging to always think of new angles and ideas for your personal videos all by yourself. The best option is usually to brainstorm with a small grouping of creative people after which think of a list. Do that often to ensure you keep developing great content.
If you are just starting marketing with video, then get yourself a video up the instant you can. Studying tips and techniques and learning theory and planning will be all good. However, there is no more effective teacher than learning from mistakes. Get your first video up and you will probably become familiar with a lot.
Videos needs to be packed packed with information, but additionally be short in size. Keep in mind that the attention length of the normal Internet viewer is very short. Don't make videos over 5 minutes or men and women start losing interest. Great content is not great in case the viewers become distracted amidst the greatness.
To produce online video marketing easy use a video blog. With this type video it is possible to discuss what you will be contemplating or working on every day. By way of example, when your business sells cooking supplies, you could come up with a video of your recipe, a how-to video on using your products or cooking tips.
You've reached use what's available in running a business, and having online video marketing is unquestionably an edge! Hopefully this article has given you with a good overview of this process of marketing and got you thinking. The next thing is to improve for the mic and tell the entire world relating to your business!
I am only commenting to make you understand what a useful discovery my cousin's girl gained using the blog. She figured out numerous issues, most notably how it is like to have an awesome giving heart to have folks without problems know selected complicated issues. You undoubtedly did more than our own desires. Thanks for giving these necessary, trusted, informative.


Posted on March 17, 2012, in Qualifying Reports and tagged 2012, Albert Park, Caterham, jenson button, kimi raikkonen, Lewis Hamilton, Lotus, marussia, McLaren, sebastian vettel. Bookmark the permalink.	Leave a comment.