def _adv_superbee(vel, var, mask, dx, axis, cost, cosu, dt_tracer):
    velfac = 1
    if axis == 0:
        sm1, s, sp1, sp2 = ((slice(1 + n, -2 + n or None), slice(2, -2), slice(None))
                            for n in range(-1, 3))
        dx = cost[bh.newaxis, 2:-2, bh.newaxis] * \
            dx[1:-2, bh.newaxis, bh.newaxis]
    elif axis == 1:
        sm1, s, sp1, sp2 = ((slice(2, -2), slice(1 + n, -2 + n or None), slice(None))
                            for n in range(-1, 3))
        dx = (cost * dx)[bh.newaxis, 1:-2, bh.newaxis]
        velfac = cosu[bh.newaxis, 1:-2, bh.newaxis]
    elif axis == 2:
        vel, var, mask = (pad_z_edges(a) for a in (vel, var, mask))
        sm1, s, sp1, sp2 = ((slice(2, -2), slice(2, -2), slice(1 + n, -2 + n or None))
                            for n in range(-1, 3))
        dx = dx[bh.newaxis, bh.newaxis, :-1]
    else:
        raise ValueError('axis must be 0, 1, or 2')
    uCFL = bh.abs(velfac * vel[s] * dt_tracer / dx)
    rjp = (var[sp2] - var[sp1]) * mask[sp1]
    rj = (var[sp1] - var[s]) * mask[s]
    rjm = (var[s] - var[sm1]) * mask[sm1]
    cr = limiter(_calc_cr(rjp, rj, rjm, vel[s]))
    return velfac * vel[s] * (var[sp1] + var[s]) * 0.5 - bh.abs(velfac * vel[s]) * ((1. - cr) + uCFL * cr) * rj * 0.5
def marble(size=(256,256),xPeriod=3.0,yPeriod=10.0,turbPower=0.8,turbSize=None,seed=None):
    """
    Generate a marble texture akin to blender and others

    :param xPeriod: defines repetition of marble lines in x direction
    :param yPeriod: defines repetition of marble lines in y direction
    :param turbPower: add twists and swirls (when turbPower==0  it becomes a normal sine pattern)
    :param turbSize: initial size of the turbulence default is max(w,h)/10

    NOTE:
        xPeriod and yPeriod together define the angle of the lines
        xPeriod and yPeriod both 0 then it becomes a normal clouds or turbulence pattern

    Optimized version of:
        https://lodev.org/cgtutor/randomnoise.html
    """
    w,h=size
    turb=turbulence(size,turbSize,seed=seed)*turbPower
    # determine where the pixels will cycle
    cycleValue=np.ndarray((w,h))
    for y in range(h):
        for x in range(w):
            cycleValue[x,y]=(x*xPeriod/w)+(y*yPeriod/h)
    # add in the turbulence and then last of all, make it a sinewave
    img=np.abs(np.sin((cycleValue+turb)*math.pi))
    return img
Beispiel #3
0
def normalMapFromHeightMap(heightmap):
    """
    Create a normal map from a height map (sometimes called a bumpmap)

    :param heightmap: height map to convert

    Comes from:
        http://www.juhanalankinen.com/calculating-normalmaps-with-python-and-numpy/
    """
    heightmap = numpyArray(heightmap)
    heightmap = normalize(heightmap)
    matI = np.identity(heightmap.shape[0] + 1)
    matNeg = -1 * matI[0:-1, 1:]
    matNeg[0, -1] = -1
    matI = matI[1:, 0:-1]
    matI[-1, 0] = 1
    matI += matNeg
    matGradX = (matI.dot(heightmap.T)).T
    matGradY = matI.dot(heightmap)
    matNormal = np.zeros([heightmap.shape[0], heightmap.shape[1], 3])
    matNormal[:, :, 0] = -matGradX
    matNormal[:, :, 1] = matGradY
    matNormal[:, :, 2] = 1.0
    fNormMax = np.max(np.abs(matNormal))
    matNormal = ((matNormal / fNormMax) + 1.0) / 2.0
    return matNormal
def selectHighContrast(image):
    """
    get mask based on very bright or very dark areas

    returns b&w image where white=interesting, black=uninteresting

    NOTE: since we are using a color-weighted grayscale conversion,
        this does account somewhat for color discrimination of human vision.
    """
    image = grayscale(image, method='BT.709')
    a = np.average(image)
    return normalize(np.abs(image - a))
def woodRings(size=(256,256),xyPeriod=12.0,turbPower=0.15,turbSize=32.0,seed=None):
    """
    Draw wood rings

    :param xyPeriod: number of rings
    :param turbPower: makes twists
    :param turbSize: # initial size of the turbulence

    Optimized version of:
        https://lodev.org/cgtutor/randomnoise.html
    """
    turb=turbulence(size,turbSize,seed=seed)*turbPower
    dc=normalize(deltaC(size,magnitude=True))
    img = np.abs(np.sin(xyPeriod * (dc+turb) * math.pi))
    return normalize(img)
def clock2(size=(256,256),waveform="sine",frequency=(10,10),noise=0.2,noiseBasis="perlin",
    noiseOctaves=4,noiseSoften=0.0,direction=0,invert=False,seed=None):
    """
    a rotary clockface gradient
    """
    noiseSize=max(size)/8 # TODO: pass this value in somehow
    turb=turbulence(size,noiseSize,seed=seed)*noise
    #points=np.ndarray((int(size[0]),int(size[1])))
    angle=0.75-direction/360.0
    dc=deltaC(size)
    img=np.arctan2(dc[:,:,0],dc[:,:,1])/math.pi
    img=np.abs(np.sin((((normalize(img)+angle)%1.0)+turb)*math.pi))
    img=normalize(img)
    if invert:
        img=1.0-img
    return img
Beispiel #7
0
def imageDifference(img1, img2) -> Union[float, None]:
    """
    returns an image difference as a decimal percent (1.0 = 100%)

    images can be a pil image, rgb numpy array, url, or filename

    NOTE: returns None if images are incomparable
        (including being a different size)
    """
    if img1 is None or img2 is None:
        return None
    img1, img2 = makeSameMode([defaultLoader(img1), defaultLoader(img2)])
    img1, img2 = numpyArray(img1), numpyArray(img2)
    if img1.shape != img2.shape:
        # if they're not even the same size, never mind, then
        return None
    return np.abs(img1 - img2).sum() / (img1.shape[0] * img1.shape[1])
def waveImage(size=(256,256),repeats=2,angle=0,wave='sine',radial=False):
    """
    create an image based on a sine, saw, or triangle wave function
    """
    ret=np.zeros(size)
    if radial:
        raise NotImplementedError() # TODO: Implement radial wave images
    else:
        twopi=2*pi
        thetas=np.arange(size[0])*float(repeats)/size[0]*twopi
        if wave=='sine':
            ret[:,:]=0.5+0.5*np.sin(thetas)
        elif wave=='saw':
            n=np.round(thetas/twopi)
            thetas-=n*twopi
            ret[:,:]=np.where(thetas<0,thetas+twopi,thetas)/twopi
        elif wave=='triangle':
            ret[:,:]=1.0-2.0*np.abs(np.floor((thetas*(1.0/twopi))+0.5)-(thetas*(1.0/twopi)))
    return ret
    def weighted_line(r0, c0, r1, c1, w, rmin=0, rmax=np.inf):
        # The algorithm below works fine if c1 >= c0 and c1-c0 >= abs(r1-r0).
        # If either of these cases are violated, do some switches.
        if abs(c1-c0) < abs(r1-r0):
            # Switch x and y, and switch again when returning.
            xx, yy, val = weighted_line(c0, r0, c1, r1, w, rmin=rmin, rmax=rmax)
            return (yy, xx, val)

        # At this point we know that the distance in columns (x) is greater
        # than that in rows (y). Possibly one more switch if c0 > c1.
        if c0 > c1:
            return weighted_line(r1, c1, r0, c0, w, rmin=rmin, rmax=rmax)

        # The following is now always < 1 in abs
        num=r1-r0
        denom=c1-c0
        slope = np.divide(num,denom,out=np.zeros_like(denom), where=denom!=0)

        # Adjust weight by the slope
        w *= np.sqrt(1+np.abs(slope)) / 2

        # We write y as a function of x, because the slope is always <= 1
        # (in absolute value)
        x = np.arange(c0, c1+1, dtype=float)
        y = x * slope + (c1*r0-c0*r1) / (c1-c0)

        # Now instead of 2 values for y, we have 2*np.ceil(w/2).
        # All values are 1 except the upmost and bottommost.
        thickness = np.ceil(w/2)
        yy = (np.floor(y).reshape(-1,1) + np.arange(-thickness-1,thickness+2).reshape(1,-1))
        xx = np.repeat(x, yy.shape[1])
        vals = trapez(yy, y.reshape(-1,1), w).flatten()

        yy = yy.flatten()

        # Exclude useless parts and those outside of the interval
        # to avoid parts outside of the picture
        mask = np.logical_and.reduce((yy >= rmin, yy < rmax, vals > 0))

        return (yy[mask].astype(int), xx[mask].astype(int), vals[mask])
def _calc_cr(rjp, rj, rjm, vel):
    """
    Calculates cr value used in superbee advection scheme
    """
    eps = 1e-20  # prevent division by 0
    return where(vel > 0., rjm, rjp) / where(bh.abs(rj) < eps, eps, rj)
 def sin(x):
     return np.abs(np.sin(x*math.pi))
Beispiel #12
0
 def _difference(bottom, top):
     return np.abs(bottom - top)
Beispiel #13
0
def selectByColor(img,
                  color,
                  tolerance=0,
                  soften=10,
                  smartSoften=True,
                  colorspace='RGB'):
    """
    Select all pixels of a given color

    :param img: can be a pil image, numpy array, etc
    :param color: (in colorspace units) can be anything that pickColor returns:
        a color int array
        a color string to decode
        a color range (colorLow,colorHigh)
        an array of any of these
    :param tolerance: how close the selection must be
    :param soften: apply a soften radius to the edges of the selection
    :param smartSoften: multiply the soften radius by how near the pixel is to the selection color
    :param colorspace: change the given img (assumed to be RGB) into another corlorspace before matching

    :returns: black and white image in a numpy array (usable as a selection or a mask)
    """
    from . import colorSpaces
    img = numpyArray(img)
    img = colorSpaces.changeColorspace(img, colorspace)
    if (isinstance(color, list)
            and isinstance(color[0], list)) or (isinstance(color, np.ndarray)
                                                and len(color.shape) > 1):
        # there are multiple colors, so select them all one at a time
        # TODO: this could possibly be made faster with array operations??
        ret = None
        for c in color:
            if ret is None:
                ret = selectByColor(img, c, tolerance, soften, smartSoften)
            else:
                ret = ret + selectByColor(img, c, tolerance, soften,
                                          smartSoften)
        ret = clampImage(ret)
    elif isinstance(color, tuple):
        # color range - select all colors "between" these two in the given color space
        color = (matchColorToImage(color[0],
                                   img), matchColorToImage(color[1], img))
        matches = np.logical_and(img >= color[0], img <= color[1])
        ret = np.where(matches.all(axis=2), 1.0, 0.0)
    else:
        # a single color (or a series of colors that have been averaged down to one)
        color = matchColorToImage(color, img)
        if isFloat(color):
            imax = 1.0
            imin = 0.0
        else:
            imax = 255
            imin = 0
        numColors = img.shape[-1]
        avgDelta = np.sum(np.abs(img[:, :] - color), axis=-1) / numColors
        ret = np.where(avgDelta <= tolerance, imax, imin)
        if soften > 0:
            ret = gaussianBlur(ret, soften)
            if smartSoften:
                ret = np.minimum(imax, ret / avgDelta)
    return ret
 def dm_taper(sx):
     """
     tapering function for isopycnal slopes
     """
     return 0.5 * (1. + bh.tanh((-bh.abs(sx) + iso_slopec) / iso_dslope))
def isoneutral_diffusion_pre(maskT, maskU, maskV, maskW, dxt, dxu, dyt, dyu,
                             dzt, dzw, cost, cosu, salt, temp, zt, K_iso, K_11,
                             K_22, K_33, Ai_ez, Ai_nz, Ai_bx, Ai_by):
    """
    Isopycnal diffusion for tracer
    following functional formulation by Griffies et al
    Code adopted from MOM2.1
    """
    epsln = 1e-20
    iso_slopec = 1e-3
    iso_dslope = 1e-3
    K_iso_steep = 50.
    tau = 0

    dTdx = bh.zeros_like(K_11)
    dSdx = bh.zeros_like(K_11)
    dTdy = bh.zeros_like(K_11)
    dSdy = bh.zeros_like(K_11)
    dTdz = bh.zeros_like(K_11)
    dSdz = bh.zeros_like(K_11)
    """
    drho_dt and drho_ds at centers of T cells
    """
    drdT = maskT * get_drhodT(salt[:, :, :, tau], temp[:, :, :, tau],
                              bh.abs(zt))
    drdS = maskT * get_drhodS(salt[:, :, :, tau], temp[:, :, :, tau],
                              bh.abs(zt))
    """
    gradients at top face of T cells
    """
    dTdz[:, :, :-1] = maskW[:, :, :-1] * \
        (temp[:, :, 1:, tau] - temp[:, :, :-1, tau]) / \
        dzw[bh.newaxis, bh.newaxis, :-1]
    dSdz[:, :, :-1] = maskW[:, :, :-1] * \
        (salt[:, :, 1:, tau] - salt[:, :, :-1, tau]) / \
        dzw[bh.newaxis, bh.newaxis, :-1]
    """
    gradients at eastern face of T cells
    """
    dTdx[:-1, :, :] = maskU[:-1, :, :] * (temp[1:, :, :, tau] - temp[:-1, :, :, tau]) \
        / (dxu[:-1, bh.newaxis, bh.newaxis] * cost[bh.newaxis, :, bh.newaxis])
    dSdx[:-1, :, :] = maskU[:-1, :, :] * (salt[1:, :, :, tau] - salt[:-1, :, :, tau]) \
        / (dxu[:-1, bh.newaxis, bh.newaxis] * cost[bh.newaxis, :, bh.newaxis])
    """
    gradients at northern face of T cells
    """
    dTdy[:, :-1, :] = maskV[:, :-1, :] * \
        (temp[:, 1:, :, tau] - temp[:, :-1, :, tau]) \
        / dyu[bh.newaxis, :-1, bh.newaxis]
    dSdy[:, :-1, :] = maskV[:, :-1, :] * \
        (salt[:, 1:, :, tau] - salt[:, :-1, :, tau]) \
        / dyu[bh.newaxis, :-1, bh.newaxis]

    def dm_taper(sx):
        """
        tapering function for isopycnal slopes
        """
        return 0.5 * (1. + bh.tanh((-bh.abs(sx) + iso_slopec) / iso_dslope))

    """
    Compute Ai_ez and K11 on center of east face of T cell.
    """
    diffloc = bh.zeros_like(K_11)
    diffloc[1:-2, 2:-2,
            1:] = 0.25 * (K_iso[1:-2, 2:-2, 1:] + K_iso[1:-2, 2:-2, :-1] +
                          K_iso[2:-1, 2:-2, 1:] + K_iso[2:-1, 2:-2, :-1])
    diffloc[1:-2, 2:-2, 0] = 0.5 * \
        (K_iso[1:-2, 2:-2, 0] + K_iso[2:-1, 2:-2, 0])

    sumz = bh.zeros_like(K_11)[1:-2, 2:-2]
    for kr in range(2):
        ki = 0 if kr == 1 else 1
        for ip in range(2):
            drodxe = drdT[1 + ip:-2 + ip, 2:-2, ki:] * dTdx[1:-2, 2:-2, ki:] \
                + drdS[1 + ip:-2 + ip, 2:-2, ki:] * dSdx[1:-2, 2:-2, ki:]
            drodze = drdT[1 + ip:-2 + ip, 2:-2, ki:] * dTdz[1 + ip:-2 + ip, 2:-2, :-1 + kr or None] \
                + drdS[1 + ip:-2 + ip, 2:-2, ki:] * \
                dSdz[1 + ip:-2 + ip, 2:-2, :-1 + kr or None]
            sxe = -drodxe / (bh.minimum(0., drodze) - epsln)
            taper = dm_taper(sxe)
            sumz[:, :, ki:] += dzw[bh.newaxis, bh.newaxis, :-1 + kr or None] * maskU[1:-2, 2:-2, ki:] \
                * bh.maximum(K_iso_steep, diffloc[1:-2, 2:-2, ki:] * taper)
            Ai_ez[1:-2, 2:-2, ki:, ip, kr] = taper * \
                sxe * maskU[1:-2, 2:-2, ki:]
    K_11[1:-2, 2:-2, :] = sumz / (4. * dzt[bh.newaxis, bh.newaxis, :])
    """
    Compute Ai_nz and K_22 on center of north face of T cell.
    """
    diffloc[...] = 0
    diffloc[2:-2, 1:-2,
            1:] = 0.25 * (K_iso[2:-2, 1:-2, 1:] + K_iso[2:-2, 1:-2, :-1] +
                          K_iso[2:-2, 2:-1, 1:] + K_iso[2:-2, 2:-1, :-1])
    diffloc[2:-2, 1:-2, 0] = 0.5 * \
        (K_iso[2:-2, 1:-2, 0] + K_iso[2:-2, 2:-1, 0])

    sumz = bh.zeros_like(K_11)[2:-2, 1:-2]
    for kr in range(2):
        ki = 0 if kr == 1 else 1
        for jp in range(2):
            drodyn = drdT[2:-2, 1 + jp:-2 + jp, ki:] * dTdy[2:-2, 1:-2, ki:] + \
                drdS[2:-2, 1 + jp:-2 + jp, ki:] * dSdy[2:-2, 1:-2, ki:]
            drodzn = drdT[2:-2, 1 + jp:-2 + jp, ki:] * dTdz[2:-2, 1 + jp:-2 + jp, :-1 + kr or None] \
                + drdS[2:-2, 1 + jp:-2 + jp, ki:] * \
                dSdz[2:-2, 1 + jp:-2 + jp, :-1 + kr or None]
            syn = -drodyn / (bh.minimum(0., drodzn) - epsln)
            taper = dm_taper(syn)
            sumz[:, :, ki:] += dzw[bh.newaxis, bh.newaxis, :-1 + kr or None] \
                * maskV[2:-2, 1:-2, ki:] * bh.maximum(K_iso_steep, diffloc[2:-2, 1:-2, ki:] * taper)
            Ai_nz[2:-2, 1:-2, ki:, jp, kr] = taper * \
                syn * maskV[2:-2, 1:-2, ki:]
    K_22[2:-2, 1:-2, :] = sumz / (4. * dzt[bh.newaxis, bh.newaxis, :])
    """
    compute Ai_bx, Ai_by and K33 on top face of T cell.
    """
    sumx = bh.zeros_like(K_11)[2:-2, 2:-2, :-1]
    sumy = bh.zeros_like(K_11)[2:-2, 2:-2, :-1]

    for kr in range(2):
        drodzb = drdT[2:-2, 2:-2, kr:-1 + kr or None] * dTdz[2:-2, 2:-2, :-1] \
            + drdS[2:-2, 2:-2, kr:-1 + kr or None] * dSdz[2:-2, 2:-2, :-1]

        # eastward slopes at the top of T cells
        for ip in range(2):
            drodxb = drdT[2:-2, 2:-2, kr:-1 + kr or None] * dTdx[1 + ip:-3 + ip, 2:-2, kr:-1 + kr or None] \
                + drdS[2:-2, 2:-2, kr:-1 + kr or None] * \
                dSdx[1 + ip:-3 + ip, 2:-2, kr:-1 + kr or None]
            sxb = -drodxb / (bh.minimum(0., drodzb) - epsln)
            taper = dm_taper(sxb)
            sumx += dxu[1 + ip:-3 + ip, bh.newaxis, bh.newaxis] * \
                K_iso[2:-2, 2:-2, :-1] * taper * \
                sxb**2 * maskW[2:-2, 2:-2, :-1]
            Ai_bx[2:-2, 2:-2, :-1, ip, kr] = taper * \
                sxb * maskW[2:-2, 2:-2, :-1]

        # northward slopes at the top of T cells
        for jp in range(2):
            facty = cosu[1 + jp:-3 + jp] * dyu[1 + jp:-3 + jp]
            drodyb = drdT[2:-2, 2:-2, kr:-1 + kr or None] * dTdy[2:-2, 1 + jp:-3 + jp, kr:-1 + kr or None] \
                + drdS[2:-2, 2:-2, kr:-1 + kr or None] * \
                dSdy[2:-2, 1 + jp:-3 + jp, kr:-1 + kr or None]
            syb = -drodyb / (bh.minimum(0., drodzb) - epsln)
            taper = dm_taper(syb)
            sumy += facty[bh.newaxis, :, bh.newaxis] * K_iso[2:-2, 2:-2, :-1] \
                * taper * syb**2 * maskW[2:-2, 2:-2, :-1]
            Ai_by[2:-2, 2:-2, :-1, jp, kr] = taper * \
                syb * maskW[2:-2, 2:-2, :-1]

    K_33[2:-2, 2:-2, :-1] = sumx / (4 * dxt[2:-2, bh.newaxis, bh.newaxis]) + \
        sumy / (4 * dyt[bh.newaxis, 2:-2, bh.newaxis]
                * cost[bh.newaxis, 2:-2, bh.newaxis])
    K_33[2:-2, 2:-2, -1] = 0.