Пример #1
0
def detectfaultpatch(img,
                     mdl,
                     nzp=64,
                     nxp=64,
                     strdz=None,
                     strdx=None,
                     rectx=30,
                     rectz=30,
                     verb=False):
    """
  Detects if a fault is present within an image or not

  Parameters:
    img   - the input image [nz,nx]
    mdl   - the trained keras model
    nzp   - z-dimension of the patch provided to the CNN [128]
    nxp   - x-dimension of the patch provided to the CNN [128]
    strdz - z-dimension of the patch stride (50% overlap) [npz/2]
    strdx - x-dimension of the patch stride (50% overlap) [npx/2]
    rectz - number of points to smooth in z direction [30]
    rectx - number of points to smooth in x direction [30]

  Returns a smooth probability map of detected faults
  """
    # Resample to nearest power of 2
    rimg = resizepow2(img, kind='linear')
    # Perform the patch extraction
    if (strdz is None): strdz = int(nzp / 2)
    if (strdx is None): strdx = int(nxp / 2)
    pe = PatchExtractor((nzp, nxp), stride=(strdx, strdz))
    iptch = pe.extract(rimg)
    numpz = iptch.shape[0]
    numpx = iptch.shape[1]
    iptch = iptch.reshape([numpx * numpz, nzp, nxp, 1])
    # Normalize and predict for each patch
    iprd = np.zeros(iptch.shape)
    for ip in range(numpz * numpx):
        iprd[ip, :, :] = mdl.predict(
            np.expand_dims(normalize(iptch[ip, :, :]), axis=0))
    # Reconstruct the predictions
    ipra = iprd.reshape([numpz, numpx, nzp, nxp])
    iprb = pe.reconstruct(ipra)

    # Smooth the predictions
    smprb = smooth(iprb.astype('float32'), rect1=rectx, rect2=rectz)

    return smprb
Пример #2
0
def focdefocang(img,
                mdl,
                nzp=64,
                nxp=64,
                strdz=None,
                strdx=None,
                rectx=30,
                rectz=30,
                verb=False):
    """
  Classifies an angle gather as focused or defocused

  Parameters:
    img   - the input extended image [na,nz,nx]
    mdl   - the trained keras model
    nzp   - z-dimension of the patch provided to the CNN [64]
    nxp   - x-dimension of the patch provided to the CNN [64]
    strdz - z-dimension of the patch stride (50% overlap) [npz/2]
    strdx - x-dimension of the patch stride (50% overlap) [npx/2]
    rectz - number of points to smooth in z direction [30]
    rectx - number of points to smooth in x direction [30]

  Returns a smooth probability map of focused/defocused faults
  """

    # Get image dimensions
    na = img.shape[0]
    nz = img.shape[1]
    nx = img.shape[2]

    # Get strides
    if (strdz is None): strdz = int(nzp / 2)
    if (strdx is None): strdx = int(nxp / 2)

    # Build the Patch Extractors
    pea = PatchExtractor((na, nzp, nxp), stride=(na, strdz, strdx))
    aptch = np.squeeze(pea.extract(img))
    # Flatten patches and make a prediction on each
    numpz = aptch.shape[0]
    numpx = aptch.shape[1]
    aptchf = np.expand_dims(normalize(
        aptch.reshape([numpz * numpx, na, nzp, nxp])),
                            axis=-1)
    focprd = mdl.predict(aptchf)

    focprdptch = np.zeros([numpz * numpx, nzp, nxp])
    for iptch in range(numpz * numpx):
        focprdptch[iptch, :, :] = focprd[iptch]
    focprdptch = focprdptch.reshape([numpz, numpx, nzp, nxp])

    # Output probabilities
    per = PatchExtractor((nzp, nxp), stride=(strdz, strdx))
    focprdimg = np.zeros([nz, nx])
    _ = per.extract(focprdimg)

    focprdimg = per.reconstruct(focprdptch.reshape([numpz, numpx, nzp, nxp]))

    focprdimgsm = smooth(focprdimg.astype('float32'), rect1=rectx, rect2=rectz)

    return focprdimgsm
Пример #3
0
 def __init__(self, f3path, predpath, figpath, dsize, psize, ssize):
     # Load in the f3 data
     self.f3dat = load_allflddata(f3path, dsize)
     self.dsize = dsize
     # Create Patch extractor
     self.pe = PatchExtractor(psize, stride=ssize)
     # Dummy array to set dimensions
     self.dummy = np.zeros([512, 1024])
     dptch = self.pe.extract(self.dummy)
     # Plot one xline
     self.xlidx = 1
     self.fs = 200
     self.thresh = 0.5
     # Do it only every few epochs
     self.skip = 2
     # Save predictions and figures
     self.predpath = predpath
     self.figpath = figpath
Пример #4
0
 def __init__(self,
              fpath,
              rpath,
              ppath,
              psize=(19, 128, 128),
              ssize=(19, 64, 64),
              predpath=None,
              figpath=None):
     # Initialize SEPlib
     sep = seppy.sep()
     # Residual migration image
     raxes, res = sep.read_file(rpath)
     res = res.reshape(raxes.n, order='F')
     rzro = res[:, :, 16, :]
     #rzro = res[psize[1]:,:,16,:] # Remove first row of patches
     [nz, nx, nh, self.nro] = raxes.n
     [dz, dx, dh, self.dro] = raxes.d
     [ox, ox, oh, self.oro] = raxes.o
     # Perturbation
     paxes, ptb = sep.read_file(ppath)
     self.ptb = ptb.reshape(paxes.n, order='F')
     #self.ptb = self.ptb[psize[1]:,:] # Remove first row of patches
     # Well focused image
     iaxes, img = sep.read_file(fpath)
     img = img.reshape(iaxes.n, order='F')
     izro = img[:, :, 16]
     #izro = img[psize[1]:,:,16] # Remove first row of patches
     # Patch it
     self.pe = PatchExtractor(psize, stride=ssize)
     rzrop = np.squeeze(self.pe.extract(rzro.T))
     self.px = rzrop.shape[0]
     self.pz = rzrop.shape[1]
     rzrop = rzrop.reshape(
         [self.px * self.pz, self.nro, psize[1], psize[2]])
     self.rzropt = np.transpose(rzrop, (0, 2, 3, 1))
     # Compute ground truth
     self.rho = estro_tgt(rzro.T,
                          izro.T,
                          self.dro,
                          self.oro,
                          nzp=psize[2],
                          nxp=psize[1],
                          strdx=ssize[1],
                          strdz=ssize[2])
Пример #5
0
def segmentfaults(img,net,nzp=128,nxp=128,strdz=None,strdx=None,resize=False):
  """
  Segments faults on a 2D image. Returns the probablility of each
  pixel being a fault or not.

  Parameters:
    img    - the input image [nz,nx]
    net    - the torch network with trained weights
    nzp    - z-dimension of the patch provided to the CNN [128]
    nxp    - x-dimension of the patch provided to the CNN [128]
    strdz  - z-dimension of the patch stride (50% overlap) [npz/2]
    strdx  - x-dimension of the patch stride (50% overlap) [npx/2]
    resize - option to resize the image to a power of two in each dimension [False]
    verb   - verbosity flag [False]

  Returns the spatial fault probability map [nz,nx]
  """
  # Resample to nearest power of 2
  if(resize):
    rimg = resizepow2(img,kind='linear')
  else:
    rimg = img
  # Perform the patch extraction
  if(strdz is None): strdz = int(nzp/2)
  if(strdx is None): strdx = int(nxp/2)
  pe = PatchExtractor((nzp,nxp),stride=(strdx,strdz))
  iptch = pe.extract(rimg)
  numpz = iptch.shape[0]; numpx = iptch.shape[1]
  iptch = iptch.reshape([numpx*numpz,1,nzp,nxp])
  # Normalize each patch
  niptch = np.zeros(iptch.shape)
  for ip in range(numpz*numpx):
    niptch[ip,:,:] = normalize(iptch[ip,:,:])
  # Convert to torch tensor
  tniptch = torch.from_numpy(niptch.astype('float32'))
  # Make a prediction
  with torch.no_grad():
    iprd  = torch.sigmoid(net(tniptch)).numpy()
  # Reconstruct the predictions
  ipra  = iprd.reshape([numpz,numpx,nzp,nxp])
  iprb  = pe.reconstruct(ipra)

  return iprb
Пример #6
0
def onehot2rho(oehs,dro,oro,nz=512,nx=1024,nzp=128,nxp=128,strdz=64,strdx=64,patches=False):
  """
  Builds a spatial rho map from onehot encoded vectors

  Parameters:
    oehs    - the input one-hot-encoded vectors [numpx,numpz,nro]
    dro     - the sampling along the rho axis
    oro     - the origin of the rho axis
    nz      - number of z samples of output rho image [512]
    nx      - number of x samples of output rho image [1024]
    nzp     - size of patch in z [128]
    nxp     - size of patch in x [128]
    strdx   - size of stride in x [64]
    strdz   - size of stride in z [64]
    patches - return rho as patches [False]

  Returns a spatial rho map
  """
  # Build patch extractor
  numpx = oehs.shape[0]; numpz = oehs.shape[1]
  pe = PatchExtractor((nxp,nzp),stride=(strdx,strdz))

  # Create output rhos
  rhoi = np.zeros([nx,nz])
  rhop = pe.extract(rhoi)

  # Loop over each patch
  for ixp in range(numpx):
    for izp in range(numpz):
      idx = np.argmax(oehs[ixp,izp])
      rhop[ixp,izp,:,:] = oro + idx*dro

  # Reconstruct the rho field
  rhoi = pe.reconstruct(rhop)

  if(patches):
    return rhoi,rhop
  else:
    return rhoi
Пример #7
0
def normextract(img,nzp=64,nxp=64,strdz=None,strdx=None,norm=True,flat=True):
  """
  Extract patches from an image and normalize each patch. Works for 2D
  and for 3D when the third dimension stride is one.

  Parameters:
    img   - the input image [n3,nz,nx]
    nzp   - size of the patch in z dimension [64]
    nxp   - size of the patch in x dimension [64]
    strdz - size of patch stride in z dimension [32]
    strdx - size of patch stride in x dimension [32]
    norm  - normalize the patches [True]
    flat  - return the patches flattened [nptch,nzp,nxp] or in a grid [numpz,numpx,nzp,nxp]

    Returns normalized image patches
  """
  if(strdz is None): strdz = int(nzp/2 + 0.5)
  if(strdx is None): strdx = int(nxp/2 + 0.5)
  if(len(img.shape) == 2):
    # Extract patches
    pe = PatchExtractor((nzp,nxp),stride=(strdz,strdx))
    ptch = pe.extract(img)

    # Get patch dimensions
    numpz = ptch.shape[0]; numpx = ptch.shape[1]

    # Flatten and normalize
    if(norm):
      ptchf = normalize(ptch.reshape([numpz*numpx,nzp,nxp]),mode='2d')
    else:
      ptchf = ptch.reshape([numpz*numpx,nzp,nxp])

  elif(len(img.shape) == 3):
    # Get size of third dimension
    n3 = img.shape[0]

    # Extract patches
    pea = PatchExtractor((n3,nzp,nxp),stride=(1,strdz,strdx))
    ptch = np.squeeze(pea.extract(img))

    # Get patch dimensions
    numpz = ptch.shape[0]; numpx = ptch.shape[1]

    # Flatten and normalize
    if(norm):
      ptchf = normalize(ptch.reshape([numpz*numpx,n3,nzp,nxp]),mode='3d')
    else:
      ptchf = ptch.reshape([numpz*numpx,n3,nzp,nxp])
  else:
    raise Exception("function supported only up to 3D")

  return ptchf
Пример #8
0
def segmentfaults(img,
                  mdl,
                  nzp=128,
                  nxp=128,
                  strdz=None,
                  strdx=None,
                  resize=False,
                  verb=False):
    """
  Segments faults on a 2D image. Returns the probablility of each
  pixel being a fault or not.

  Parameters:
    img    - the input image [nz,nx]
    mdl    - the trained keras model
    nzp    - z-dimension of the patch provided to the CNN [128]
    nxp    - x-dimension of the patch provided to the CNN [128]
    strdz  - z-dimension of the patch stride (50% overlap) [npz/2]
    strdx  - x-dimension of the patch stride (50% overlap) [npx/2]
    resize - option to resize the image to a power of two in each dimension [False]
    verb   - verbosity flag [False]

  Returns the spatial fault probability map [nz,nx]
  """
    # Resample to nearest power of 2
    if (resize):
        rimg = resizepow2(img, kind='linear')
    else:
        rimg = img
    # Perform the patch extraction
    if (strdz is None): strdz = int(nzp / 2)
    if (strdx is None): strdx = int(nxp / 2)
    pe = PatchExtractor((nzp, nxp), stride=(strdx, strdz))
    iptch = pe.extract(rimg)
    numpz = iptch.shape[0]
    numpx = iptch.shape[1]
    iptch = iptch.reshape([numpx * numpz, nzp, nxp, 1])
    # Normalize each patch
    niptch = np.zeros(iptch.shape)
    for ip in range(numpz * numpx):
        niptch[ip, :, :] = normalize(iptch[ip, :, :])
    # Make a prediction
    iprd = mdl.predict(niptch, verbose=verb)
    # Reconstruct the predictions
    ipra = iprd.reshape([numpz, numpx, nzp, nxp])
    iprb = pe.reconstruct(ipra)
    if (iprb.shape != rimg.shape):
        iptch = pe.extract(rimg)
        rimg = pe.reconstruct(iptch)
        return iprb, rimg
    else:
        return iprb
Пример #9
0
def focdefocflt_labels(dimg,
                       fimg,
                       fltlbl,
                       nxp=64,
                       nzp=64,
                       strdx=32,
                       strdz=32,
                       pixthresh=20,
                       metric='mse',
                       focthresh=0.5,
                       norm=True,
                       imgs=False,
                       qcptchgrd=False,
                       dz=10,
                       dx=10):
    """
  Computes the fault-based focused and defocused labels

  Parameters
    dimg      - Input defocused image [nz,nx]
    fimg      - Input focused image [nz,nx]
    fltlbl    - Input fault labels [nz,nx]
    nxp       - Size of patch in x [64]
    nzp       - Size of patch in z [64]
    strdx     - Patch stride in x [32]
    strdz     - Patch stride in z [32]
    pixthresh - Number of fault pixels to determine if patch has fault [20]
    metric    - Metric for determining if fault is focused or not (['mse'] or 'ssim')
    focthresh - Threshold applied to metric to determining focusing [0.5]
    norm      - Normalize the images [True]
    imgs      - Return the label image and the norm image [False]
    qcptchgrd - Makes a plot of the patch grid on the image [False]
    dx        - Lateral sampling for plotting patch grid [10]
    dz        - Vertical sampling for plotting patch grid [10]
  """
    # Check that dimg, fimg and fltlbl are the same size
    if (dimg.shape[0] != fltlbl.shape[0] or dimg.shape[1] != fltlbl.shape[1]):
        raise Exception(
            "Input image and fault label must have same dimensions")

    if (dimg.shape[0] != fimg.shape[0] or dimg.shape[1] != fimg.shape[1]):
        raise Exception(
            "Input defocused image and defocused image must have same dimensions"
        )

    # Patch extraction on the images
    pe = PatchExtractor((nzp, nxp), stride=(strdz, strdx))
    dptch = pe.extract(dimg)
    fptch = pe.extract(fimg)
    lptch = pe.extract(fltlbl)
    numpz = dptch.shape[0]
    numpx = dptch.shape[1]

    if (qcptchgrd):
        nz = img.shape[0]
        nx = img.shape[1]
        # Plot the patch grid
        bgz = 0
        egz = (nz) * dz / 1000.0
        dgz = nzp * dz / 1000.0
        bgx = 0
        egx = (nx) * dx / 1000.0
        dgx = nxp * dx / 1000.0
        zticks = np.arange(bgz, egz, dgz)
        xticks = np.arange(bgx, egx, dgx)
        fig = plt.figure(figsize=(10, 6))
        ax = fig.gca()
        ax.imshow(img,
                  extent=[0, (nx) * dx / 1000.0, (nz) * dz / 1000.0, 0],
                  cmap='gray',
                  interpolation='sinc')
        ax.set_xticks(xticks)
        ax.set_yticks(zticks)
        ax.grid(linestyle='-', color='k', linewidth=2)
        plt.show()

    # Output image patches
    dptcho = []
    fptcho = []

    # Output patch label
    ptchlbl = np.zeros(lptch.shape)
    lptcho = []

    # Norm image
    ptchnrm = np.zeros(lptch.shape)

    # Loop over each patch
    for izp in range(numpz):
        for ixp in range(numpx):
            # Check if patch contains faults
            if (np.sum(lptch[izp, ixp]) >= pixthresh):
                # Compute the desired norm between the two images
                if (metric == 'mse'):
                    ptchnrm[izp, ixp, :, :] = mse(dptch[izp, ixp], fptch[izp,
                                                                         ixp])
                    if (ptchnrm[izp, ixp, int(nzp / 2),
                                int(nxp / 2)] >= focthresh):
                        ptchlbl[izp, ixp, :, :] = 0
                    else:
                        ptchlbl[izp, ixp, :, :] = 1
                elif (metric == 'ssim'):
                    ptchnrm[izp, ixp] = ssim(dptch[izp, ixp], fptch[izp, ixp])
                    if (ptchnrm[izp, ixp, int(nzp / 2),
                                int(nxp / 2)] >= focthresh):
                        ptchlbl[izp, ixp, :, :] = 1
                    else:
                        ptchlbl[izp, ixp, :, :] = 0
                elif (metric == 'corr'):
                    ndptch = normalize(dptch[izp, ixp])
                    nfptch = normalize(fptch[izp, ixp])
                    #ptchnrm[izp,ixp] = np.max(correlate2d(ndptch,nfptch),mode='same'))
                else:
                    raise Exception(
                        "Norm %s not yet implemented. Please try 'ssim' or 'mse'"
                        % (metric))
                # Append label and image to output lists
                lptcho.append(ptchlbl[izp, ixp, int(nzp / 2), int(nxp / 2)])
                if (norm):
                    dptcho.append(normalize(dptch[izp, ixp, :, :]))
                    fptcho.append(normalize(fptch[izp, ixp, :, :]))
                else:
                    dptcho.append(dptch[izp, ixp])
                    fptcho.append(fptch[izp, ixp])

    # Convert to numpy arrays
    dptcho = np.asarray(dptcho)
    fptcho = np.asarray(fptcho)
    lptcho = np.asarray(lptcho)

    # Reconstruct the patch label image and patch norm image (for QC purposes)
    ptchlblimg = pe.reconstruct(ptchlbl)
    ptchnrmimg = pe.reconstruct(ptchnrm)

    if (imgs):
        return dptcho, fptcho, lptcho, ptchlblimg, ptchnrmimg
    else:
        return dptcho, fptcho, lptcho
Пример #10
0
def estro_fltfocdefoc(rimgs,foccnn,dro,oro,nzp=64,nxp=64,strdz=None,strdx=None, # Patching parameters
                      hasfault=None,rectz=30,rectx=30,qcimgs=True):
  """
  Estimates rho by choosing the residually migrated patch that has
  highest fault focus probability given by the neural network

  Parameters
    rimgs      - residually migrated images [nro,nz,nx]
    foccnn     - CNN for determining if fault is focused or not
    dro        - residual migration sampling
    oro        - residual migration origin
    nzp        - size of patch in z dimension [64]
    nxp        - size of patch in x dimension [64]
    strdz      - size of stride in z dimension [nzp/2]
    strdx      - size of stride in x dimension [nxp/2]
    hasfault   - array indicating if a patch has faults or not [None]
                 If None, all patches are considered to have faults
    rectz      - length of smoother in z dimension [30]
    rectx      - length of smoother in x dimension [30]
    qcimgs     - flag for returning the fault focusing probabilities [nro,nz,nx]
                 and fault patches [nz,nx]

  Returns an estimate of rho(x,z)
  """
  # Get image dimensions
  nro = rimgs.shape[0]; nz = rimgs.shape[1]; nx = rimgs.shape[2]

  # Get strides
  if(strdz is None): strdz = int(nzp/2)
  if(strdx is None): strdx = int(nxp/2)

  # Extract patches from residual migration image
  per = PatchExtractor((nro,nzp,nxp),stride=(nro,strdz,strdx))
  rptch = np.squeeze(per.extract(rimgs))
  # Flatten patches and make a prediction on each
  numpz = rptch.shape[0]; numpx = rptch.shape[1]
  rptchf = np.expand_dims(normalize(rptch.reshape([nro*numpz*numpx,nzp,nxp])),axis=-1)
  focprd = foccnn.predict(rptchf)

  # Assign prediction to entire patch for QC
  focprdptch = np.zeros(rptchf.shape)
  for iptch in range(nro*numpz*numpx): focprdptch[iptch,:,:] = focprd[iptch]
  focprdptch = focprdptch.reshape([numpz,numpx,nro,nzp,nxp])

  if(hasfault is None):
    hasfault = np.ones([numpz,numpx,nzp,nxp],dtype='int')

  # Output rho image
  rho = np.zeros([nz,nx])
  pe = PatchExtractor((nzp,nxp),stride=(strdz,strdx))
  rhop = pe.extract(rho)

  # Using hasfault array, estimate rho from fault focus probabilities
  hlfz = int(nzp/2); hlfx = int(nxp/2)
  for izp in range(numpz):
    for ixp in range(numpx):
      if(hasfault[izp,ixp,hlfz,hlfx]):
        # Find maximum probability and compute rho
        iprb = focprdptch[izp,ixp,:,hlfz,hlfx]
        rhop[izp,ixp,:,:] = np.argmax(iprb)*dro + oro
      else:
        rhop[izp,ixp,:,:] = 1.0

  # Reconstruct the rho, fault patches and fault probabiliites
  rho       = pe.reconstruct(rhop)
  focprdimg = per.reconstruct(focprdptch.reshape([1,numpz,numpx,nro,nzp,nxp]))

  # Smooth and return rho, fault patches and fault probabilities
  rhosm = smooth(rho.astype('float32'),rect1=rectx,rect2=rectz)
  if(qcimgs):
    focprdimgsm = np.zeros(focprdimg.shape)
    # Smooth the fault focusing for each rho
    for iro in range(nro):
      focprdimgsm[iro] = smooth(focprdimg[iro].astype('float32'),rect1=rectx,rect2=rectz)
    # Return images
    return rhosm,focprdimgsm
  else:
    return rhosm
Пример #11
0
class ShowPred(callbacks.Callback):
    def __init__(self,
                 fpath,
                 rpath,
                 ppath,
                 psize=(19, 128, 128),
                 ssize=(19, 64, 64),
                 predpath=None,
                 figpath=None):
        # Initialize SEPlib
        sep = seppy.sep()
        # Residual migration image
        raxes, res = sep.read_file(rpath)
        res = res.reshape(raxes.n, order='F')
        rzro = res[:, :, 16, :]
        #rzro = res[psize[1]:,:,16,:] # Remove first row of patches
        [nz, nx, nh, self.nro] = raxes.n
        [dz, dx, dh, self.dro] = raxes.d
        [ox, ox, oh, self.oro] = raxes.o
        # Perturbation
        paxes, ptb = sep.read_file(ppath)
        self.ptb = ptb.reshape(paxes.n, order='F')
        #self.ptb = self.ptb[psize[1]:,:] # Remove first row of patches
        # Well focused image
        iaxes, img = sep.read_file(fpath)
        img = img.reshape(iaxes.n, order='F')
        izro = img[:, :, 16]
        #izro = img[psize[1]:,:,16] # Remove first row of patches
        # Patch it
        self.pe = PatchExtractor(psize, stride=ssize)
        rzrop = np.squeeze(self.pe.extract(rzro.T))
        self.px = rzrop.shape[0]
        self.pz = rzrop.shape[1]
        rzrop = rzrop.reshape(
            [self.px * self.pz, self.nro, psize[1], psize[2]])
        self.rzropt = np.transpose(rzrop, (0, 2, 3, 1))
        # Compute ground truth
        self.rho = estro_tgt(rzro.T,
                             izro.T,
                             self.dro,
                             self.oro,
                             nzp=psize[2],
                             nxp=psize[1],
                             strdx=ssize[1],
                             strdz=ssize[2])

    def on_epoch_end(self, epoch, logs={}):
        # Make a prediction on the input image
        print("Predicting on test image...")
        pred = self.model.predict(self.rzropt, verbose=1)
        #print(pred)
        # Apply threshold
        pred = pred.reshape([self.px, self.pz, self.nro])
        print(np.isnan(np.sum(pred)))
        #prho = onehot2rho(pred,self.dro,self.oro,nz=512-128)
        prho = onehot2rho(pred,
                          self.dro,
                          self.oro,
                          nz=512,
                          nzp=64,
                          nxp=64,
                          strdz=32,
                          strdx=32)
        if (epoch % 10 == 0):
            fig, ax = plt.subplots(1, 3, figsize=(14, 7))
            ax[0].imshow(prho.T, cmap='seismic', vmin=0.97, vmax=1.03)
            ax[1].imshow(self.rho.T, cmap='seismic', vmin=0.97, vmax=1.03)
            ax[2].imshow(self.ptb, cmap='jet', vmin=-100, vmax=100)
            plt.savefig("./fig/trainresfind/resfind%d.png" % (epoch),
                        dpi=150,
                        bbox_inches='tight',
                        transparent=True)
            plt.close()
Пример #12
0
def estro_fltangfocdefoc(rimgs,foccnn,dro,oro,nzp=64,nxp=64,strdz=None,strdx=None, # Patching parameters
                         rectz=30,rectx=30,fltthresh=75,fltlbls=None,qcimgs=True,verb=False,
                         fmwrk='torch',device=None):
  """
  Estimates rho by choosing the residually migrated patch that has
  highest angle gather and fault focus probability given by the neural network

  Parameters
    rimgs      - residually migrated angle gathers images [nro,na,nz,nx]
    foccnn     - CNN for determining if angle gather/fault is focused or not
    dro        - residual migration sampling
    oro        - residual migration origin
    nzp        - size of patch in z dimension [64]
    nxp        - size of patch in x dimension [64]
    strdz      - size of stride in z dimension [nzp/2]
    strdx      - size of stride in x dimension [nxp/2]
    rectz      - length of smoother in z dimension [30]
    rectx      - length of smoother in x dimension [30]
    fltlbls    - input fault segmentation labels [None]
    qcimgs     - flag for returning the fault focusing probabilities [nro,nz,nx]
                 and fault patches [nz,nx]
    verb       - verbosity flag [False]
    fmwrk      - deep learning framework to be used for the prediction [torch]
    device     - device for pytorch networks

  Returns an estimate of rho(x,z)
  """
  # Get image dimensions
  nro = rimgs.shape[0]; na = rimgs.shape[1]; nz = rimgs.shape[2]; nx = rimgs.shape[3]

  # Get strides
  if(strdz is None): strdz = int(nzp/2)
  if(strdx is None): strdx = int(nxp/2)

  # Build the Patch Extractors
  pea = PatchExtractor((nro,na,nzp,nxp),stride=(nro,na,strdz,strdx))
  aptch = np.squeeze(pea.extract(rimgs))
  # Flatten patches and make a prediction on each
  numpz = aptch.shape[0]; numpx = aptch.shape[1]
  if(fmwrk == 'torch'):
    aptchf = normalize(aptch.reshape([nro*numpz*numpx,1,na,nzp,nxp]))
    with(torch.no_grad()):
      aptchft = torch.tensor(aptchf)
      focprdt = torch.zeros([nro*numpz*numpx,1])
      for iptch in progressbar(range(aptchf.shape[0]),verb=verb):
        gptch = aptchft[iptch].to(device)
        focprdt[iptch] = torch.sigmoid(foccnn(gptch.unsqueeze(0)))
      focprd = focprdt.cpu().numpy()
  elif(fmwrk == 'tf'):
    aptchf = np.expand_dims(normalize(aptch.reshape([nro*numpz*numpx,na,nzp,nxp])),axis=-1)
    focprd = foccnn.predict(aptchf,verbose=verb)
  elif(fmwrk is None):
    aptchf = normalize(aptch.reshape([nro*numpz*numpx,na,nzp,nxp]))
    focprd = np.zeros([nro*numpz*numpx,1])
    for iptch in progressbar(range(aptchf.shape[0]),verb=verb):
      focprd[iptch] = semblance_power(aptchf[iptch])

  # Assign prediction to entire patch for QC
  focprdptch = np.zeros([numpz*numpx*nro,nzp,nxp])
  for iptch in range(nro*numpz*numpx): focprdptch[iptch,:,:] = focprd[iptch]
  focprdptch = focprdptch.reshape([numpz,numpx,nro,nzp,nxp])

  # Save predictions as a function of rho only
  focprdr = focprd.reshape([numpz,numpx,nro])

  # Output rho image
  pe = PatchExtractor((nzp,nxp),stride=(strdz,strdx))
  rho = np.zeros([nz,nx])
  rhop = pe.extract(rho)

  # Output probabilities
  focprdnrm = np.zeros(focprdptch.shape)
  per = PatchExtractor((nro,nzp,nxp),stride=(nro,strdz,strdx))
  focprdimg = np.zeros([nro,nz,nx])
  _ = per.extract(focprdimg)

  if(fltlbls is None):
    fltptch = np.ones([numpz,numpx,nzp,nxp],dtype='int')
  else:
    pef = PatchExtractor((nzp,nxp),stride=(strdz,strdx))
    fltptch = pef.extract(fltlbls)

  # Estimate rho from angle-fault focus probabilities
  hlfz = int(nzp/2); hlfx = int(nxp/2)
  for izp in range(numpz):
    for ixp in range(numpx):
      if(np.sum(fltptch[izp,ixp]) > fltthresh):
        # Find maximum probability and compute rho
        iprb = focprdptch[izp,ixp,:,hlfz,hlfx]
        rhop[izp,ixp,:,:] = np.argmax(iprb)*dro + oro
        # Normalize across rho within a patch for QC
        if(np.max(focprdptch[izp,ixp,:,hlfz,hlfx]) == 0.0):
          focprdnrm[izp,ixp,:,:,:] = 0.0
        else:
          focprdnrm[izp,ixp,:,:,:] = focprdptch[izp,ixp,:,:,:]/np.max(focprdptch[izp,ixp,:,hlfz,hlfx])
      else:
        rhop[izp,ixp,:,:] = 1.0

  # Reconstruct rho and probabiliites
  rho       = pe.reconstruct(rhop)
  focprdimg = per.reconstruct(focprdnrm.reshape([1,numpz,numpx,nro,nzp,nxp]))

  # Smooth and return rho, fault patches and fault probabilities
  rhosm = smooth(rho.astype('float32'),rect1=rectx,rect2=rectz)
  if(qcimgs):
    focprdimgsm = np.zeros(focprdimg.shape)
    # Smooth the fault focusing for each rho
    for iro in range(nro):
      focprdimgsm[iro] = smooth(focprdimg[iro].astype('float32'),rect1=rectx,rect2=rectz)
    # Return images
    return rhosm,focprdimgsm,focprdr
  else:
    return rhosm
Пример #13
0
class F3Pred(callbacks.Callback):
    def __init__(self, f3path, predpath, figpath, dsize, psize, ssize):
        # Load in the f3 data
        self.f3dat = load_allflddata(f3path, dsize)
        self.dsize = dsize
        # Create Patch extractor
        self.pe = PatchExtractor(psize, stride=ssize)
        # Dummy array to set dimensions
        self.dummy = np.zeros([512, 1024])
        dptch = self.pe.extract(self.dummy)
        # Plot one xline
        self.xlidx = 1
        self.fs = 200
        self.thresh = 0.5
        # Do it only every few epochs
        self.skip = 2
        # Save predictions and figures
        self.predpath = predpath
        self.figpath = figpath

    def on_epoch_end(self, epoch, logs={}):
        if (epoch % self.skip == 0):
            # Make a prediction on the f3 data and save it
            print("Predicting on F3 dataset...")
            pred = self.model.predict(self.f3dat, verbose=1)
            # Save predictions to file
            with h5py.File(
                    self.predpath + '/ep%s.h5' % (create_inttag(epoch, 100)),
                    "w") as hf:
                hf.create_dataset("pred",
                                  self.f3dat.shape,
                                  data=pred,
                                  dtype=np.float32)
            # Reconstruct a single inline
            iimg = self.f3dat[self.xlidx * self.dsize:(self.xlidx + 1) *
                              self.dsize, :, :]
            iimg = iimg.reshape([7, 15, 128, 128])
            rimg = self.pe.reconstruct(iimg)
            # Reconstruct the predictions
            ipred = pred[self.xlidx * self.dsize:(self.xlidx + 1) *
                         self.dsize, :, :]
            ipred = ipred.reshape([7, 15, 128, 128])
            rpred = self.pe.reconstruct(ipred)
            # Apply threshold and plot
            tpred = thresh(rpred, self.thresh)
            nt = rimg.shape[0]
            nx = rimg.shape[1]
            plotseglabel(rimg[self.fs:, :],
                         tpred[self.fs:, :],
                         color='blue',
                         xlabel='Inline',
                         ylabel='Time (s)',
                         xmin=0.0,
                         xmax=(nx - 1) * 25 / 1000.0,
                         zmin=(self.fs - 1) * 0.004,
                         zmax=(nt - 1) * 0.004,
                         vmin=-2.5,
                         vmax=2.5,
                         interp='sinc',
                         aratio=6.5)
            plt.savefig(self.figpath + '/ep%s.png' %
                        (create_inttag(epoch, 100)),
                        bbox_inches='tight',
                        dpi=150)
Пример #14
0
def find_flt_patches(img,
                     mdl,
                     dz,
                     mindepth,
                     nzp=64,
                     nxp=64,
                     strdz=None,
                     strdx=None,
                     pthresh=0.2,
                     nthresh=50,
                     oz=0.0,
                     qcimgs=True):
    """
  Determines if patches contain a fault or not

  Parameters:
    img       - input fault seismic image [nz,nx]
    mdl       - fault segmentation keras CNN
    dz        - depth sampling
    mindepth  - minimum depth after which to look for faults
    nzp       - size of patch in x dimension [64]
    nxp       - size of patch in z dimension [64]
    strdz     - size of stride in z dimension [None]
    strdx     - size of stride in x dimension [None]
    pthresh   - probability threshold for determining if a pixel contains a fault [0.2]
    nthresh   - number of fault pixels in a patch to determined if it has a fault [50]
    oz        - depth origin [0.0]
    qcimgs    - flag for returning segmented fault image as well as fault patches
                for QC

  Returns a patch array where the patches are valued at either
  one (if patch contains a fault) or zero (if it does not have a fault)
  """
    # Get image dimensions
    nz = img.shape[0]
    nx = img.shape[1]

    # Get strides
    if (strdz is None): strdz = int(nzp / 2)
    if (strdx is None): strdx = int(nxp / 2)

    # Extract patches on the image
    pe = PatchExtractor((nzp, nxp), stride=(strdz, strdx))
    iptch = pe.extract(img)
    # Flatten patches and make a prediction on each
    numpz = iptch.shape[0]
    numpx = iptch.shape[1]
    iptchf = np.expand_dims(normalize(iptch.reshape([numpz * numpx, nzp,
                                                     nxp])),
                            axis=-1)
    fltpred = mdl.predict(iptchf)

    # Reshape the fault prediction array
    fltpred = fltpred.reshape([numpz, numpx, nzp, nxp])

    # Output arrays
    hasfault = np.zeros(iptch.shape)
    flttrsh = np.zeros(iptch.shape)
    # Check if patch has a fault
    for izp in range(numpz):
        for ixp in range(numpx):
            # Compute current depth
            z = izp * strdz * dz + oz
            if (z > mindepth):
                # Threshold the patch
                flttrsh[izp, ixp] = thresh(fltpred[izp, ixp], pthresh)
                if (np.sum(flttrsh[izp, ixp]) > nthresh):
                    hasfault[izp, ixp, :, :] = 1.0

    # Reconstruct the images for QC
    if (qcimgs):
        faultimg = pe.reconstruct(fltpred)
        thrshimg = pe.reconstruct(flttrsh)
        hsfltimg = pe.reconstruct(hasfault)

        return hasfault, hsfltimg, thresh(thrshimg, 0.0), faultimg

    else:
        return hasfault
Пример #15
0
def extract_focfltptchs(fimg,
                        fltlbl,
                        nxp=64,
                        nzp=64,
                        strdx=32,
                        strdz=32,
                        pixthresh=20,
                        norm=True,
                        qcptchgrd=False,
                        dz=10,
                        dx=10):
    """
  Extracts patches from a faulted image
  """
    # Check that dimg, fimg and fltlbl are the same size
    if (fimg.shape[0] != fltlbl.shape[0] or fimg.shape[1] != fltlbl.shape[1]):
        raise Exception(
            "Input image and fault label must have same dimensions")

    # Patch extraction on the images
    pe = PatchExtractor((nzp, nxp), stride=(strdz, strdx))
    fptch = pe.extract(fimg)
    lptch = pe.extract(fltlbl)
    numpz = fptch.shape[0]
    numpx = fptch.shape[1]

    # Output normalized patches
    nptch = []

    if (qcptchgrd):
        nz = fimg.shape[0]
        nx = fimg.shape[1]
        # Plot the patch grid
        nz = fimg.shape[0]
        nx = fimg.shape[1]
        # Plot the patch grid
        bgz = 0
        egz = (nz) * dz / 1000.0
        dgz = nzp * dz / 1000.0
        bgx = 0
        egx = (nx) * dx / 1000.0
        dgx = nxp * dx / 1000.0
        zticks = np.arange(bgz, egz, dgz)
        xticks = np.arange(bgx, egx, dgx)
        fig = plt.figure(figsize=(10, 6))
        ax = fig.gca()
        ax.imshow(fimg,
                  extent=[0, (nx) * dx / 1000.0, (nz) * dz / 1000.0, 0],
                  cmap='gray',
                  interpolation='sinc',
                  vmin=-2.5,
                  vmax=2.5)
        ax.set_xlabel('X (km)', fontsize=15)
        ax.set_xlabel('Z (km)', fontsize=15)
        ax.tick_params(labelsize=15)
        ax.set_xticks(xticks)
        ax.set_yticks(zticks)
        ax.grid(linestyle='-', color='k', linewidth=2)
        plt.show()

    # Loop over each patch
    for izp in range(numpz):
        for ixp in range(numpx):
            # Check if patch contains faults
            if (np.sum(lptch[izp, ixp]) >= pixthresh):
                if (norm):
                    nptch.append(normalize(fptch[izp, ixp]))
                else:
                    nptch.append(fptch[izp, ixp])

    return np.asarray(nptch)
Пример #16
0
def faultpatch_labels(img,
                      fltlbl,
                      nxp=64,
                      nzp=64,
                      strdx=32,
                      strdz=32,
                      pixthresh=20,
                      norm=True,
                      ptchimg=False,
                      qcptchgrd=False,
                      dz=10,
                      dx=10):
    """
  Assigns a zero or one to an image patch based on the number
  of fault pixels present within an image patch

  Parameters:
    img       - Input seismic image (to be patched) [nz,nx]
    fltlbl    - Input segmentation fault label [nz,nx]
    nxp       - Size of patch in x [64]
    nzp       - Size of patch in z [64]
    strdx     - Patch stride in x [32]
    strdz     - Patch stride in z [32]
    pixthresh - Number of fault pixels to determine if patch has fault
    ptchimg   - Return the reconstructed patch image [False]
    qcptchgrd - Makes a plot of the patch grid on the image
    dx        - Lateral sampling for plotting patch grid
    dz        - Vertical sampling for plotting patch grid

  Returns:
    Image and label patches [numpz,numpx,nzp,nxp] and the reconstructed
    label image
  """
    # Check that img and fltlbl are the same size
    if (img.shape[0] != fltlbl.shape[0] or img.shape[1] != fltlbl.shape[1]):
        raise Exception(
            "Input image and fault label must have same dimensions")

    # Extract the patches
    pe = PatchExtractor((nzp, nxp), stride=(strdz, strdx))
    iptch = pe.extract(img)
    lptch = pe.extract(fltlbl)
    numpz = iptch.shape[0]
    numpx = iptch.shape[1]

    if (qcptchgrd):
        nz = img.shape[0]
        nx = img.shape[1]
        # Plot the patch grid
        bgz = 0
        egz = (nz) * dz / 1000.0
        dgz = nzp * dz / 1000.0
        bgx = 0
        egx = (nx) * dx / 1000.0
        dgx = nxp * dx / 1000.0
        zticks = np.arange(bgz, egz, dgz)
        xticks = np.arange(bgx, egx, dgx)
        fig = plt.figure(figsize=(10, 6))
        ax = fig.gca()
        ax.imshow(img,
                  extent=[0, (nx) * dx / 1000.0, (nz) * dz / 1000.0, 0],
                  cmap='gray',
                  interpolation='sinc')
        ax.set_xticks(xticks)
        ax.set_yticks(zticks)
        ax.grid(linestyle='-', color='k', linewidth=2)
        plt.show()

    # Output image patches
    iptcho = np.zeros(iptch.shape)

    # Output patch label
    ptchlbl = np.zeros(lptch.shape)

    # Check if patch contains faults
    for izp in range(numpz):
        for ixp in range(numpx):
            if (np.sum(lptch[izp, ixp]) >= pixthresh):
                ptchlbl[izp, ixp, :, :] = 1
            if (norm):
                iptcho[izp, ixp] = normalize(iptch[izp, ixp, :, :])
            else:
                iptcho[izp, ixp] = iptch[izp, ixp]

    # Reconstruct the patch label image
    ptchlblimg = pe.reconstruct(ptchlbl)

    if (ptchimg):
        return iptcho, ptchlbl, ptchlblimg
    else:
        return iptcho, ptchlbl
Пример #17
0
def estro_varimax(rimgs,dro,oro,nzp=64,nxp=64,strdz=None,strdx=None,rectz=30,rectx=30,qcimgs=True):
  """
  Estimates rho by choosing the residually migrated patch that has
  the highest image entropy computed via the varimax norm

  Parameters
    rimgs      - residually migrated images [nro,nz,nx]
    dro        - residual migration sampling
    oro        - residual migration origin
    nzp        - size of patch in z dimension [64]
    nxp        - size of patch in x dimension [64]
    strdz      - size of stride in z dimension [nzp/2]
    strdx      - size of stride in x dimension [nxp/2]
    rectz      - length of smoother in z dimension [30]
    rectx      - length of smoother in x dimension [30]
    qcimgs     - flag for returning the smoothed varimax norm [nro,nz,nx]

  Returns an estimate of rho(x,z)
  """
  # Get image dimensions
  nro = rimgs.shape[0]; nz = rimgs.shape[1]; nx = rimgs.shape[2]

  # Get strides
  if(strdz is None): strdz = int(nzp/2)
  if(strdx is None): strdx = int(nxp/2)

  # Extract patches from residual migration image
  per = PatchExtractor((nro,nzp,nxp),stride=(nro,strdz,strdx))
  rptch = np.squeeze(per.extract(rimgs))
  # Flatten patches and make a prediction on each
  numpz = rptch.shape[0]; numpx = rptch.shape[1]
  nptch  = nro*numpz*numpx
  rptchf = rptch.reshape([nptch,nzp,nxp])
  norm = np.zeros(rptchf.shape)
  for iptch in range(nptch):
    norm[iptch,:,:] = varimax(rptchf[iptch])

  # Assign prediction to entire patch for QC
  normptch = norm.reshape([numpz,numpx,nro,nzp,nxp])

  # Output rho image
  rho = np.zeros([nz,nx])
  pe = PatchExtractor((nzp,nxp),stride=(strdz,strdx))
  rhop = pe.extract(rho)

  # Using hasfault array, estimate rho from fault focus probabilities
  hlfz = int(nzp/2); hlfx = int(nxp/2)
  for izp in range(numpz):
    for ixp in range(numpx):
      # Find maximum entropy and compute rho
      ient = normptch[izp,ixp,:,hlfz,hlfx]
      rhop[izp,ixp,:,:] = np.argmax(ient)*dro + oro

  # Reconstruct the rho, fault patches and fault probabiliites
  rho     = pe.reconstruct(rhop)
  normimg = per.reconstruct(normptch.reshape([1,numpz,numpx,nro,nzp,nxp]))

  # Smooth and return rho, fault patches and fault probabilities
  rhosm = smooth(rho.astype('float32'),rect1=rectx,rect2=rectz)
  if(qcimgs):
    normimgsm = np.zeros(normimg.shape)
    # Smooth the fault focusing for each rho
    for iro in range(nro):
      normimgsm[iro] = smooth(normimg[iro].astype('float32'),rect1=rectx,rect2=rectz)
    # Return images
    return rhosm,normimgsm
  else:
    return rhosm
Пример #18
0
def estro_tgt(rimgs,fimg,dro,oro,nzp=128,nxp=128,strdx=64,strdz=64,transp=False,patches=False,onehot=False):
  """
  Estimates rho by comparing residual migration images with a
  well-focused "target image"

  Parameters
    rimgs   - input residual migration images [nro,nx,nz]
    fimg    - input target image [nx,nz]
    dro     - sampling along trial rho axis
    oro     - origin of rho axis
    nzp     - size of patches in z direction [128]
    nxp     - size of patches in x direction [128]
    strdx   - patch stride in x direction [128]
    strdz   - patch stride in z direction [128]
    transp  - transpose the input to have dimensions of [nro,nz,nx]
    patches - return the estimated rho in patch form  [numpx,numpz,nxp,nzp]
    onehot  - return the estimated rho in one-hot encoded form ((numpx,numpz,nro) with a one at the estimated rho)

  Returns the estimated rho in a map, patches and/or onehot form
  """
  if(transp):
    rimgst = np.transpose(rimgs,(0,2,1))
    fimgt  = fimg.T
  else:
    rimgst = rimgs
    fimgt  = fimg

  # Get dimensions
  [nro,nx,nz] = rimgst.shape

  if(nx != fimgt.shape[0] or nz != fimgt.shape[1]):
    raise Exception("Residual migration and focused image must have same spatial dimensions")

  # Extract patches on target image
  pe   = PatchExtractor((nxp,nzp),stride=(strdx,strdz))
  ptch = pe.extract(fimgt)
  numpx = ptch.shape[0]; numpz = ptch.shape[1]

  # Extract patches on residual migration image
  per = PatchExtractor((nro,nxp,nzp),stride=(nro,strdx,strdz))
  rptch = np.squeeze(per.extract(rimgst))

  # Allocate the output rho
  rhop = np.zeros(ptch.shape)
  oehs = np.zeros([numpx,numpz,nro])

  # Loop over each patch and compute the ssim for each rho
  for ixp in range(numpx):
    for izp in range(numpz):
      idx = ssim_ro(rptch[ixp,izp],ptch[ixp,izp])
      # Compute rho and save idx
      rhop[ixp,izp,:,:] = oro + idx*dro
      oehs[ixp,izp,idx] = 1.0

  # Reconstruct the rho field
  rhoi = pe.reconstruct(rhop)

  if(patches and onehot):
    return rhoi,rhop,oehs
  elif(patches):
    return rhoi,rhop
  elif(onehot):
    return rhoi,oehs
  else:
    return rhoi