Generate 1-D data ``y=f(x)`` from a black/white image.

    Suppose we have an image like that:

    .. image:: images/waveform.png
        :align: center

    Put some codes::

        >>> from weatherlab.math.img2waveform import img2wav
        >>> import matplotlib.pyplot as plt
        >>> x, y = img2wav(r"testdata\img2waveform\waveform.png", 
        ...                  min_x=0.0, max_x=288, 
        ...                  min_y=15.0, max_y=35.0, 
        ...                  window_size=15)
        >>> plt.plot(x, y)
        >>> plt.show()

    Then you got nicely sampled data:

    .. image:: images\waveform_pyplot.png
        :align: center

    :param path: the image file path
    :type path: string
    :param min_x: minimum value of x axis
    :type min_x: number
    :param max_x: maximum value of x axis
    :type max_x: number
    :param min_y: minimum value of y axis
    :type min_y: number
    :param max_y: maximum value of y axis
    :type max_y: number
    :param window_size: the slide window
    :type window_size: int

    Note:

    In python, a numpy array that represent a image is from left to the right, 
    top to the bottom, but in coordinate, it's from bottom to the top. So we 
    use ::-1 for a reverse output

def img2wav(path, min_x, max_x, min_y, max_y, window_size=3):
    """Generate 1-D data ``y=f(x)`` from a black/white image.

    Suppose we have an image like that:

    .. image:: images/waveform.png
        :align: center

    Put some codes::

        >>> from weatherlab.math.img2waveform import img2wav
        >>> import matplotlib.pyplot as plt
        >>> x, y = img2wav(r"testdata\img2waveform\waveform.png", 
        ...                  min_x=0.0, max_x=288, 
        ...                  min_y=15.0, max_y=35.0, 
        ...                  window_size=15)
        >>> plt.plot(x, y)
        >>> plt.show()

    Then you got nicely sampled data:

    .. image:: images\waveform_pyplot.png
        :align: center

    :param path: the image file path
    :type path: string
    :param min_x: minimum value of x axis
    :type min_x: number
    :param max_x: maximum value of x axis
    :type max_x: number
    :param min_y: minimum value of y axis
    :type min_y: number
    :param max_y: maximum value of y axis
    :type max_y: number
    :param window_size: the slide window
    :type window_size: int

    Note:

    In python, a numpy array that represent a image is from left to the right, 
    top to the bottom, but in coordinate, it's from bottom to the top. So we 
    use ::-1 for a reverse output
    """
    image = Image.open(path).convert("L")
    matrix = np.array(image)[::-1]

    # you can customize the gray scale fix behavior to fit color image
    matrix[np.where(matrix >= 128)] = 255
    matrix[np.where(matrix < 128)] = 0

    tick_x = (max_x - min_x) / matrix.shape[1]
    tick_y = (max_y - min_y) / matrix.shape[0]

    x, y = list(), list()
    for i in range(matrix.shape[1]):
        window = expand_window(  # slide margin window
            i, window_size, matrix.shape[1])
        margin_dots_y_indices = np.where(matrix[:, window] == 0)[0]
        # if found at least one dots in margin
        if len(margin_dots_y_indices) > 0:
            x.append(min_x + (i + 1) * tick_x)
            y.append(min_y + margin_dots_y_indices.mean() * tick_y)

    return np.array(x), np.array(y)