from skimage import measure
import scipy.ndimage as ndimage 
import numpy as np
import planktonator as plktor

def threshold(img,t=240):
    '''
    Create a mask of objects by applying a pixel threshold

    Parameters
    ----------
    arr : array_like
        2D image array, uint8
    t : int 
        pixel threshold

    Returns
    -------
    object image mask
    '''
    mask            = np.array(np.zeros(np.shape(img)))
    highidx         = img>=t
    lowidx          = img<t
    mask[highidx]   = 255
    mask[lowidx]    = 0
    return mask


def convolution(img,kernel):
    return ndimage.convolve(img,kernel)

def find_contours(mask):
    '''
        Use skimage to find contours in image mask
    '''
    return measure.find_contours(mask, 0)


def removescale(img, a=[1200,1230,0,500], p=255):
    '''
        Remove the scale bar from image
    '''
    img[a[0]:a[1],a[2]:a[3]] = p
    return img

def maskfill(mask,contours):
    '''
        Ensure that any gaps in blobs are filled within the mask

        Assumes mask is black on white background
    '''
    
    # Create an empty image to store the masked array
    r_mask = np.zeros_like(mask, dtype='bool')

    for contour in contours:
        # Create a contour image by using the contour coordinates rounded to their nearest integer value
        r_mask[np.round(contour[:, 0]).astype('int'), np.round(contour[:, 1]).astype('int')] = 1

    # Fill in the hole created by the contour boundary
    r_mask = ndimage.binary_fill_holes(r_mask)

    # Invert the mask since you want pixels outside of the region
    r_mask = np.multiply(~r_mask,255)

    # Make sure original mask values are retained 
    r_mask[mask == 0] = 0
    return r_mask.astype('uint8') 


def draw_contours(img, contours):
    '''
        draw contours on an image
    '''
    # if not RGB, convert 
    if not len(np.shape(img)) == 3:
        cdraw_img = np.array(np.zeros((np.shape(img)[0],np.shape(img)[1],3)))
        cdraw_img[:,:,0],cdraw_img[:,:,1],cdraw_img[:,:,2] = img,img,img 

    for contour in contours:
        cdraw_img[contour[:, 0].astype(int), contour[:, 1].astype(int)] = [255,0,0]

    return cdraw_img


def particle_crop(img,contour):
    '''
        Use skimage contours to produce crop of individual.

        Make area outside of contour white
    '''
    xmin,xmax       = int(min(contour[:, 1])), int(max(contour[:, 1]))+1
    ymin,ymax       = int(min(contour[:, 0])), int(max(contour[:, 0]))+1
    bwidth,bheight  = xmax-xmin, ymax-ymin

    # Create a contour image by using the contour coordinates rounded to their nearest integer value
    cropmask        = np.array(np.zeros((bheight,bwidth)),dtype=bool)
    cropmask[np.subtract(contour[:, 0],ymin).astype(int), np.subtract(contour[:, 1],xmin).astype(int)] = 1

    # Fill in the hole created by the contour boundary
    cropmask = np.multiply(ndimage.morphology.binary_fill_holes(cropmask),255).astype('uint8')
    zeroidx     = cropmask == 0
    onesidx     = cropmask == 255

    # Copy the crop area from the image
    crop            = img[ymin:ymax,xmin:xmax].copy()
    # Change all values outside of the contour mask to 255
    crop[zeroidx]   = 255

    return np.clip(crop,0,255),cropmask


def flatten(img,mask,maskval=0,bgval=255):
    '''
    Flattens an image with only values contained 
    in a mask and excluding background vals
    '''
    imgflat = img.flatten()[np.where((mask.flatten()==maskval)==True)[0]]
    return imgflat[imgflat != bgval]



from skimage import measure
import scipy.ndimage as ndimage 
import numpy as np
import planktonator as plktor

def threshold(img,t=240):
    '''
    Create a mask of objects by applying a pixel threshold

    Parameters
    ----------
    arr : array_like
        2D image array, uint8
    t : int 
        pixel threshold

    Returns
    -------
    object image mask
    '''
    mask            = np.array(np.zeros(np.shape(img)))
    highidx         = img>=t
    lowidx          = img<t
    mask[highidx]   = 255
    mask[lowidx]    = 0
    return mask


def convolution(img,kernel):
    return ndimage.convolve(img,kernel)

def find_contours(mask):
    '''
        Use skimage to find contours in image mask
    '''
    return measure.find_contours(mask, 0)


def removescale(img, a=[1200,1230,0,500], p=255):
    '''
        Remove the scale bar from image
    '''
    img[a[0]:a[1],a[2]:a[3]] = p
    return img

def maskfill(mask,contours):
    '''
        Ensure that any gaps in blobs are filled within the mask

        Assumes mask is black on white background
    '''
    
    # Create an empty image to store the masked array
    r_mask = np.zeros_like(mask, dtype='bool')

    for contour in contours:
        # Create a contour image by using the contour coordinates rounded to their nearest integer value
        r_mask[np.round(contour[:, 0]).astype('int'), np.round(contour[:, 1]).astype('int')] = 1

    # Fill in the hole created by the contour boundary
    r_mask = ndimage.binary_fill_holes(r_mask)

    # Invert the mask since you want pixels outside of the region
    r_mask = np.multiply(~r_mask,255)

    # Make sure original mask values are retained 
    r_mask[mask == 0] = 0
    return r_mask.astype('uint8') 


def draw_contours(img, contours):
    '''
        draw contours on an image
    '''
    # if not RGB, convert 
    if not len(np.shape(img)) == 3:
        cdraw_img = np.array(np.zeros((np.shape(img)[0],np.shape(img)[1],3)))
        cdraw_img[:,:,0],cdraw_img[:,:,1],cdraw_img[:,:,2] = img,img,img 

    for contour in contours:
        cdraw_img[contour[:, 0].astype(int), contour[:, 1].astype(int)] = [255,0,0]

    return cdraw_img


def particle_crop(img,contour):
    '''
        Use skimage contours to produce crop of individual.

        Make area outside of contour white
    '''
    xmin,xmax       = int(min(contour[:, 1])), int(max(contour[:, 1]))+1
    ymin,ymax       = int(min(contour[:, 0])), int(max(contour[:, 0]))+1
    bwidth,bheight  = xmax-xmin, ymax-ymin

    # Create a contour image by using the contour coordinates rounded to their nearest integer value
    cropmask        = np.array(np.zeros((bheight,bwidth)),dtype=bool)
    cropmask[np.subtract(contour[:, 0],ymin).astype(int), np.subtract(contour[:, 1],xmin).astype(int)] = 1

    # Fill in the hole created by the contour boundary
    cropmask = np.multiply(ndimage.morphology.binary_fill_holes(cropmask),255).astype('uint8')
    zeroidx     = cropmask == 0
    onesidx     = cropmask == 255

    # Copy the crop area from the image
    crop            = img[ymin:ymax,xmin:xmax].copy()
    # Change all values outside of the contour mask to 255
    crop[zeroidx]   = 255

    return np.clip(crop,0,255),cropmask


def flatten(img,mask,maskval=0,bgval=255):
    '''
    Flattens an image with only values contained 
    in a mask and excluding background vals
    '''
    imgflat = img.flatten()[np.where((mask.flatten()==maskval)==True)[0]]
    return imgflat[imgflat != bgval]



Create a mask of objects by applying a pixel threshold      Parameters     ----------     arr : array_like         2D image array, uint8     t : int          pixel threshold      Returns     -------     object image mask Use skimage to find contours in image mask Remove the scale bar from image Ensure that any gaps in blobs are filled within the mask          Assumes mask is black on white background # Create an empty image to store the masked array # Create a contour image by using the contour coordinates rounded to their nearest integer value # Fill in the hole created by the contour boundary # Invert the mask since you want pixels outside of the region # Make sure original mask values are retained draw contours on an image # if not RGB, convert Use skimage contours to produce crop of individual.          Make area outside of contour white # Create a contour image by using the contour coordinates rounded to their nearest integer value # Fill in the hole created by the contour boundary # Copy the crop area from the image # Change all values outside of the contour mask to 255 Flattens an image with only values contained      in a mask and excluding background vals