예제 #1
0
  /**
   * Initializes this operator and sets the one and only target product.
   *
   * <p>The target product can be either defined by a field of type {@link Product} annotated with
   * the {@link TargetProduct TargetProduct} annotation or by calling {@link #setTargetProduct}
   * method.
   *
   * <p>The framework calls this method after it has created this operator. Any client code that
   * must be performed before computation of tile data should be placed here.
   *
   * @throws OperatorException If an error occurs during operator initialisation.
   * @see #getTargetProduct()
   */
  @Override
  public void initialize() throws OperatorException {

    try {
      absRoot = AbstractMetadata.getAbstractedMetadata(sourceProduct);

      getSourceImageDimension();

      getMetadata();

      computeSensorPositionsAndVelocities();

      createTargetProduct();

      if (externalDEMFile == null) {
        DEMFactory.checkIfDEMInstalled(demName);
      }

      DEMFactory.validateDEM(demName, sourceProduct);

      if (reGridMethod) {
        computeDEMTraversalSampleInterval();
      } else if (orbitMethod) {
        meta = new SLCImage(absRoot);
        jOrbit = new Orbit(absRoot, 3);
      }
    } catch (Throwable e) {
      OperatorUtils.catchOperatorException(getId(), e);
    }
  }
예제 #2
0
  /**
   * Compute initial cluster centers for clusters in all 3 categories: vol, dbl, suf.
   *
   * @param srcBandList the input bands
   * @param tileRectangles Array of rectangles for all source tiles of the image
   * @param op the operator
   */
  private void computeInitialTerrainClusterCenters(
      final double[][] fdd,
      final java.util.List<ClusterInfo> pvCenterList,
      final java.util.List<ClusterInfo> pdCenterList,
      final java.util.List<ClusterInfo> psCenterList,
      final PolBandUtils.PolSourceBand srcBandList,
      final Rectangle[] tileRectangles,
      final PolarimetricClassificationOp op) {

    try {
      // Step 1. Create initial 30 clusters in each of the 3 categories (vol, dbl, surf).
      // System.out.println("Step 1");
      createInitialClusters(fdd, srcBandList, tileRectangles, op);

      // Step 2. Compute cluster centers for all 90 clusters in the 3 categories
      // System.out.println("Step 2");
      getClusterCenters(pvCenterList, pdCenterList, psCenterList, srcBandList, tileRectangles, op);

      // Step 3. Merge small clusters in each category until user specified total number of clusters
      // is reached
      // System.out.println("Step 3");
      mergeInitialClusters(pvCenterList, pdCenterList, psCenterList);

    } catch (Throwable e) {
      OperatorUtils.catchOperatorException(op.getId() + " computeInitialClusterCenters ", e);
    }
  }
예제 #3
0
  /**
   * Compute centers for all numClasses clusters
   *
   * @param srcBandList the input bands
   * @param op the operator
   */
  private synchronized void computeTerrainClusterCenters(
      final PolBandUtils.PolSourceBand srcBandList, final PolarimetricClassificationOp op) {

    if (clusterCentersComputed) {
      return;
    }

    mask = new byte[srcHeight][srcWidth];
    final double[][] fdd = new double[srcHeight][srcWidth];
    final java.util.List<ClusterInfo> pvCenterList = new ArrayList<>(numInitialClusters);
    final java.util.List<ClusterInfo> pdCenterList = new ArrayList<>(numInitialClusters);
    final java.util.List<ClusterInfo> psCenterList = new ArrayList<>(numInitialClusters);

    maxClusterSize = 2 * srcHeight * srcWidth / numFinalClasses;

    final Dimension tileSize = new Dimension(256, 256);
    final Rectangle[] tileRectangles =
        OperatorUtils.getAllTileRectangles(op.getSourceProduct(), tileSize, 0);

    computeInitialTerrainClusterCenters(
        fdd, pvCenterList, pdCenterList, psCenterList, srcBandList, tileRectangles, op);

    computeFinalTerrainClusterCenters(
        fdd, pvCenterList, pdCenterList, psCenterList, srcBandList, tileRectangles, op);

    clusterCentersComputed = true;
  }
예제 #4
0
  /**
   * Retrieve required data from Abstracted Metadata
   *
   * @throws Exception if metadata not found
   */
  private void getMetadata() throws Exception {

    srgrFlag = AbstractMetadata.getAttributeBoolean(absRoot, AbstractMetadata.srgr_flag);
    wavelength = SARUtils.getRadarFrequency(absRoot);
    rangeSpacing = AbstractMetadata.getAttributeDouble(absRoot, AbstractMetadata.range_spacing);
    firstLineUTC = absRoot.getAttributeUTC(AbstractMetadata.first_line_time).getMJD(); // in days
    lastLineUTC = absRoot.getAttributeUTC(AbstractMetadata.last_line_time).getMJD(); // in days
    lineTimeInterval =
        absRoot.getAttributeDouble(AbstractMetadata.line_time_interval)
            / Constants.secondsInDay; // s to day
    orbitStateVectors = AbstractMetadata.getOrbitStateVectors(absRoot);

    if (srgrFlag) {
      srgrConvParams = AbstractMetadata.getSRGRCoefficients(absRoot);
    } else {
      nearEdgeSlantRange =
          AbstractMetadata.getAttributeDouble(absRoot, AbstractMetadata.slant_range_to_first_pixel);
    }

    final TiePointGrid incidenceAngle = OperatorUtils.getIncidenceAngle(sourceProduct);
    nearRangeOnLeft = SARGeocoding.isNearRangeOnLeft(incidenceAngle, sourceImageWidth);
  }
예제 #5
0
  private double fillHole(final int xx, final int yy, final double[][] srcArray) throws Exception {

    try {
      final int h = srcArray.length;
      final int w = srcArray[0].length;

      double vU = noDataValue, vD = noDataValue, vL = noDataValue, vR = noDataValue;
      int yU = -1, yD = -1, xL = -1, xR = -1;
      for (int y = yy; y >= 0; y--) {
        if (srcArray[y][xx] != noDataValue) {
          vU = srcArray[y][xx];
          yU = y;
          break;
        }
      }

      for (int y = yy; y < h; y++) {
        if (srcArray[y][xx] != noDataValue) {
          if (vU != noDataValue) {
            vD = srcArray[y][xx];
            yD = y;
            break;
          } else {
            vU = srcArray[y][xx];
            yU = y;
          }
        }
      }

      for (int x = xx; x >= 0; x--) {
        if (srcArray[yy][x] != noDataValue) {
          vL = srcArray[yy][x];
          xL = x;
          break;
        }
      }

      for (int x = xx; x < w; x++) {
        if (srcArray[yy][x] != noDataValue) {
          if (vL != noDataValue) {
            vR = srcArray[yy][x];
            xR = x;
            break;
          } else {
            vL = srcArray[yy][x];
            xL = x;
          }
        }
      }

      if (vU != noDataValue && vD != noDataValue && vL != noDataValue && vR != noDataValue) {
        final double vY = vU + (vD - vU) * (yy - yU) / (yD - yU);
        final double vX = vL + (vR - vL) * (xx - xL) / (xR - xL);
        return 0.5 * (vY + vX);
      } else if (vU != noDataValue && vD != noDataValue) {
        return vU + (vD - vU) * (yy - yU) / (yD - yU);
      } else if (vL != noDataValue && vR != noDataValue) {
        return vL + (vR - vL) * (xx - xL) / (xR - xL);
      } else if (vL != noDataValue) {
        return vL;
      } else if (vR != noDataValue) {
        return vR;
      } else if (vU != noDataValue) {
        return vU;
      } else if (vD != noDataValue) {
        return vD;
      }

    } catch (Exception e) {
      OperatorUtils.catchOperatorException(getId(), e);
    }

    return noDataValue;
  }
예제 #6
0
  /**
   * Called by the framework in order to compute the stack of tiles for the given target bands.
   *
   * <p>The default implementation throws a runtime exception with the message "not implemented".
   *
   * @param targetTiles The current tiles to be computed for each target band.
   * @param targetRectangle The area in pixel coordinates to be computed (same for all rasters in
   *     <code>targetRasters</code>).
   * @param pm A progress monitor which should be used to determine computation cancelation
   *     requests.
   * @throws OperatorException if an error occurs during computation of the target rasters.
   */
  @Override
  public void computeTileStack(
      Map<Band, Tile> targetTiles, Rectangle targetRectangle, ProgressMonitor pm)
      throws OperatorException {

    final int x0 = targetRectangle.x;
    final int y0 = targetRectangle.y;
    final int w = targetRectangle.width;
    final int h = targetRectangle.height;
    // System.out.println("x0 = " + x0 + ", y0 = " + y0 + ", w = " + w + ", h = " + h);

    double[] tileOverlapPercentage = {0.0, 0.0};
    try {
      if (!isElevationModelAvailable) {
        getElevationModel();
      }
      computeTileOverlapPercentage(x0, y0, w, h, tileOverlapPercentage);
      // System.out.println("x0 = " + x0 + ", y0 = " + y0 + ", w = " + w + ", h = " + h +
      //                   ", tileOverlapPercentageMin = " + tileOverlapPercentage[0] +
      //                   ", tileOverlapPercentageMax = " + tileOverlapPercentage[1]);
    } catch (Exception e) {
      throw new OperatorException(e);
    }

    final Tile latTile = targetTiles.get(targetProduct.getBand(LATITUDE_BAND_NAME));
    final Tile lonTile = targetTiles.get(targetProduct.getBand(LONGITUDE_BAND_NAME));
    final ProductData latData = latTile.getDataBuffer();
    final ProductData lonData = lonTile.getDataBuffer();
    final double[][] latArray = new double[h][w];
    final double[][] lonArray = new double[h][w];
    for (int r = 0; r < h; r++) {
      Arrays.fill(latArray[r], noDataValue);
      Arrays.fill(lonArray[r], noDataValue);
    }

    final int ymin = Math.max(y0 - (int) (tileSize * tileOverlapPercentage[1]), 0);
    final int ymax = y0 + h + (int) (tileSize * Math.abs(tileOverlapPercentage[0]));
    final int xmax = x0 + w;

    final PositionData posData = new PositionData();
    final GeoPos geoPos = new GeoPos();

    try {
      if (reGridMethod) {
        final double[] latLonMinMax = new double[4];
        computeImageGeoBoundary(x0, xmax, ymin, ymax, latLonMinMax);

        final double latMin = latLonMinMax[0];
        final double latMax = latLonMinMax[1];
        final double lonMin = latLonMinMax[2];
        final double lonMax = latLonMinMax[3];
        final int nLat = (int) ((latMax - latMin) / delLat) + 1;
        final int nLon = (int) ((lonMax - lonMin) / delLon) + 1;

        final double[][] tileDEM = new double[nLat + 1][nLon + 1];
        double alt;

        for (int i = 0; i < nLat; i++) {
          final double lat = latMin + i * delLat;
          for (int j = 0; j < nLon; j++) {
            double lon = lonMin + j * delLon;
            if (lon >= 180.0) {
              lon -= 360.0;
            }
            geoPos.setLocation(lat, lon);
            alt = dem.getElevation(geoPos);
            if (alt == demNoDataValue) {
              continue;
            }

            tileDEM[i][j] = alt;

            if (!getPosition(lat, lon, alt, x0, y0, w, h, posData)) {
              continue;
            }

            final int ri = (int) Math.round(posData.rangeIndex);
            final int ai = (int) Math.round(posData.azimuthIndex);
            if (ri < x0 || ri >= x0 + w || ai < y0 || ai >= y0 + h) {
              continue;
            }

            latArray[ai - y0][ri - x0] = lat;
            lonArray[ai - y0][ri - x0] = lon;
          }
        }

      } else {

        final double[][] localDEM = new double[ymax - ymin + 2][w + 2];
        final TileGeoreferencing tileGeoRef =
            new TileGeoreferencing(sourceProduct, x0, ymin, w, ymax - ymin);

        final boolean valid =
            DEMFactory.getLocalDEM(
                dem,
                demNoDataValue,
                demResamplingMethod,
                tileGeoRef,
                x0,
                ymin,
                w,
                ymax - ymin,
                sourceProduct,
                true,
                localDEM);

        if (!valid) {
          return;
        }

        for (int y = ymin; y < ymax; y++) {
          final int yy = y - ymin;

          for (int x = x0; x < xmax; x++) {
            final int xx = x - x0;
            double alt = localDEM[yy + 1][xx + 1];

            if (alt == demNoDataValue) {
              continue;
            }

            tileGeoRef.getGeoPos(x, y, geoPos);
            if (!geoPos.isValid()) {
              continue;
            }

            double lat = geoPos.lat;
            double lon = geoPos.lon;
            if (lon >= 180.0) {
              lon -= 360.0;
            }

            if (orbitMethod) {
              double[] latlon = jOrbit.lp2ell(new Point(x + 0.5, y + 0.5), meta);
              lat = latlon[0] * Constants.RTOD;
              lon = latlon[1] * Constants.RTOD;
              alt = dem.getElevation(new GeoPos(lat, lon));
            }

            if (!getPosition(lat, lon, alt, x0, y0, w, h, posData)) {
              continue;
            }

            final int ri = (int) Math.round(posData.rangeIndex);
            final int ai = (int) Math.round(posData.azimuthIndex);
            if (ri < x0 || ri >= x0 + w || ai < y0 || ai >= y0 + h) {
              continue;
            }

            latArray[ai - y0][ri - x0] = lat;
            lonArray[ai - y0][ri - x0] = lon;
          }
        }
      }

      // todo should replace the following code with Delaunay interpolation
      final TileIndex trgIndex = new TileIndex(latTile);
      for (int y = y0; y < y0 + h; y++) {
        final int yy = y - y0;
        trgIndex.calculateStride(y);
        for (int x = x0; x < x0 + w; x++) {
          final int xx = x - x0;
          final int index = trgIndex.getIndex(x);

          if (latArray[yy][xx] == noDataValue) {
            latData.setElemDoubleAt(index, fillHole(xx, yy, latArray));
          } else {
            latData.setElemDoubleAt(index, latArray[yy][xx]);
          }

          if (lonArray[yy][xx] == noDataValue) {
            lonData.setElemDoubleAt(index, fillHole(xx, yy, lonArray));
          } else {
            lonData.setElemDoubleAt(index, lonArray[yy][xx]);
          }
        }
      }

    } catch (Throwable e) {
      OperatorUtils.catchOperatorException(getId(), e);
    }
  }
예제 #7
0
  /**
   * Compute final cluster centers for all clusters using K-mean clustering method
   *
   * @param srcBandList the input bands
   * @param tileRectangles Array of rectangles for all source tiles of the image
   * @param op the operator
   */
  private void computeFinalTerrainClusterCenters(
      final double[][] fdd,
      final java.util.List<ClusterInfo> pvCenterList,
      final java.util.List<ClusterInfo> pdCenterList,
      final java.util.List<ClusterInfo> psCenterList,
      final PolBandUtils.PolSourceBand srcBandList,
      final Rectangle[] tileRectangles,
      final PolarimetricClassificationOp op) {

    boolean endIteration = false;

    final StatusProgressMonitor status =
        new StatusProgressMonitor(StatusProgressMonitor.TYPE.SUBTASK);
    status.beginTask("Computing Final Cluster Centres... ", tileRectangles.length * maxIterations);

    final int pvNumClusters = pvCenterList.size();
    final int pdNumClusters = pdCenterList.size();
    final int psNumClusters = psCenterList.size();

    final int maxNumClusters = Math.max(pvNumClusters, Math.max(pdNumClusters, psNumClusters));
    final int[][] clusterCounter = new int[3][maxNumClusters];

    final ThreadManager threadManager = new ThreadManager();

    try {
      for (int it = 0; (it < maxIterations && !endIteration); ++it) {
        // System.out.println("Iteration: " + it);

        //                final long startTime = System.nanoTime();
        //                final long endTime;
        final double[][][] pvSumRe = new double[pvNumClusters][3][3];
        final double[][][] pvSumIm = new double[pvNumClusters][3][3];
        final double[][][] pdSumRe = new double[pdNumClusters][3][3];
        final double[][][] pdSumIm = new double[pdNumClusters][3][3];
        final double[][][] psSumRe = new double[psNumClusters][3][3];
        final double[][][] psSumIm = new double[psNumClusters][3][3];

        java.util.Arrays.fill(clusterCounter[0], 0);
        java.util.Arrays.fill(clusterCounter[1], 0);
        java.util.Arrays.fill(clusterCounter[2], 0);

        for (final Rectangle rectangle : tileRectangles) {

          final Thread worker =
              new Thread() {

                final Tile[] sourceTiles = new Tile[srcBandList.srcBands.length];
                final ProductData[] dataBuffers = new ProductData[srcBandList.srcBands.length];

                final double[][] Tr = new double[3][3];
                final double[][] Ti = new double[3][3];

                @Override
                public void run() {
                  op.checkIfCancelled();

                  final int x0 = rectangle.x;
                  final int y0 = rectangle.y;
                  final int w = rectangle.width;
                  final int h = rectangle.height;
                  final int xMax = x0 + w;
                  final int yMax = y0 + h;

                  final Rectangle sourceRectangle = getSourceRectangle(x0, y0, w, h);
                  for (int i = 0; i < sourceTiles.length; ++i) {
                    sourceTiles[i] = op.getSourceTile(srcBandList.srcBands[i], sourceRectangle);
                    dataBuffers[i] = sourceTiles[i].getDataBuffer();
                  }
                  final TileIndex srcIndex = new TileIndex(sourceTiles[0]);

                  for (int y = y0; y < yMax; ++y) {
                    for (int x = x0; x < xMax; ++x) {

                      PolOpUtils.getMeanCoherencyMatrix(
                          x,
                          y,
                          halfWindowSizeX,
                          halfWindowSizeY,
                          srcWidth,
                          srcHeight,
                          sourceProductType,
                          srcIndex,
                          dataBuffers,
                          Tr,
                          Ti);

                      int clusterIdx;
                      synchronized (clusterCounter) {
                        if (mask[y][x] < -64) { // pv
                          clusterIdx = findClosestCluster(Tr, Ti, pvCenterList);
                          computeSummationOfT3(clusterIdx + 1, Tr, Ti, pvSumRe, pvSumIm);
                          clusterCounter[0][clusterIdx] += 1;
                          mask[y][x] = (byte) (-128 + clusterIdx);

                        } else if (mask[y][x] < 0) { // pd
                          clusterIdx = findClosestCluster(Tr, Ti, pdCenterList);
                          computeSummationOfT3(clusterIdx + 1, Tr, Ti, pdSumRe, pdSumIm);
                          clusterCounter[1][clusterIdx] += 1;
                          mask[y][x] = (byte) (-64 + clusterIdx);

                        } else if (mask[y][x] < 64) { // ps
                          clusterIdx = findClosestCluster(Tr, Ti, psCenterList);
                          computeSummationOfT3(clusterIdx + 1, Tr, Ti, psSumRe, psSumIm);
                          clusterCounter[2][clusterIdx] += 1;
                          mask[y][x] = (byte) clusterIdx;

                        } else { // mixed

                          java.util.List<ClusterInfo> allCenterList = new ArrayList<>();
                          allCenterList.addAll(pvCenterList);
                          allCenterList.addAll(pdCenterList);
                          allCenterList.addAll(psCenterList);
                          clusterIdx = findClosestCluster(Tr, Ti, allCenterList);

                          if (clusterIdx >= pvNumClusters + pdNumClusters) { // ps
                            clusterIdx -= pvNumClusters + pdNumClusters;
                            computeSummationOfT3(clusterIdx + 1, Tr, Ti, psSumRe, psSumIm);
                            clusterCounter[2][clusterIdx] += 1;
                            mask[y][x] = (byte) clusterIdx;

                          } else if (clusterIdx >= pvNumClusters) { // pd
                            clusterIdx -= pvNumClusters;
                            computeSummationOfT3(clusterIdx + 1, Tr, Ti, pdSumRe, pdSumIm);
                            clusterCounter[1][clusterIdx] += 1;
                            mask[y][x] = (byte) (-64 + clusterIdx);

                          } else { // pv
                            computeSummationOfT3(clusterIdx + 1, Tr, Ti, pvSumRe, pvSumIm);
                            clusterCounter[0][clusterIdx] += 1;
                            mask[y][x] = (byte) (-128 + clusterIdx);
                          }
                        }
                      }
                    }
                  }
                }
              };
          threadManager.add(worker);

          status.worked(1);
        }
        threadManager.finish();

        /*
        endTime = System.nanoTime();
        final long duration = endTime - startTime;
        System.out.println("duration = " + duration);
        */
        updateClusterCenter(pvCenterList, clusterCounter[0], pvSumRe, pvSumIm);
        updateClusterCenter(pdCenterList, clusterCounter[1], pdSumRe, pdSumIm);
        updateClusterCenter(psCenterList, clusterCounter[2], psSumRe, psSumIm);
      }
      /*
      System.out.println("# of clusters in Pv: " + pvNumClusters);
      System.out.print("Pixels in each Pv cluster: ");
      for (int i = 0; i < pvNumClusters; i++) {
          System.out.print(clusterCounter[0][i] + ", ");
      }
      System.out.println();
      System.out.println("# of clusters in Pd: " + pdNumClusters);
      System.out.print("Pixels in each Pd cluster: ");
      for (int i = 0; i < pdNumClusters; i++) {
          System.out.print(clusterCounter[1][i] + ", ");
      }
      System.out.println();
      System.out.println("# of clusters in Ps: " + psNumClusters);
      System.out.print("Pixels in each Ps cluster: ");
      for (int i = 0; i < psNumClusters; i++) {
          System.out.print(clusterCounter[2][i] + ", ");
      }
      System.out.println();
      */

      // todo the average cluster power should be used in colour selection for each cluster, not
      // used now
      // compute average power for each cluster
      final double[] pvAvgClusterPower = new double[pvNumClusters];
      final double[] pdAvgClusterPower = new double[pdNumClusters];
      final double[] psAvgClusterPower = new double[psNumClusters];

      int clusterIdx = -1;
      for (int y = 0; y < srcHeight; y++) {
        for (int x = 0; x < srcWidth; x++) {
          if (mask[y][x] < -64) { // pv
            clusterIdx = mask[y][x] + 128;
            pvAvgClusterPower[clusterIdx] += fdd[y][x];
          } else if (mask[y][x] < 0) { // pd
            clusterIdx = mask[y][x] + 64;
            pdAvgClusterPower[clusterIdx] += fdd[y][x];
          } else { // ps
            clusterIdx = mask[y][x];
            psAvgClusterPower[clusterIdx] += fdd[y][x];
          }
        }
      }

      for (int c = 0; c < pvNumClusters; c++) {
        pvAvgClusterPower[c] /= clusterCounter[0][c];
      }

      for (int c = 0; c < pdNumClusters; c++) {
        pdAvgClusterPower[c] /= clusterCounter[1][c];
      }

      for (int c = 0; c < psNumClusters; c++) {
        psAvgClusterPower[c] /= clusterCounter[2][c];
      }

      // map cluster index to colour index, colour index ranges for the 3 categories are given by
      // surf: [0,29], vol: [30, 59] and dbl: [60,89], currently the clusters are evenly distributed
      // in the
      // colour range
      pvColourIndexMap = new int[pvNumClusters];
      pdColourIndexMap = new int[pdNumClusters];
      psColourIndexMap = new int[psNumClusters];
      for (int c = 0; c < pvNumClusters; c++) {
        pvColourIndexMap[c] =
            numInitialClusters + getColourIndex(c, pvAvgClusterPower, numInitialClusters) + 1;
      }
      for (int c = 0; c < pdNumClusters; c++) {
        pdColourIndexMap[c] =
            2 * numInitialClusters + getColourIndex(c, pdAvgClusterPower, numInitialClusters) + 1;
      }
      for (int c = 0; c < psNumClusters; c++) {
        psColourIndexMap[c] = getColourIndex(c, psAvgClusterPower, numInitialClusters) + 1;
      }

    } catch (Throwable e) {
      OperatorUtils.catchOperatorException(op.getId() + " computeInitialClusterCenters ", e);
    } finally {
      status.done();
    }
  }
예제 #8
0
  /**
   * Compute the centers of the 90 clusters in the 3 categories.
   *
   * @param srcBandList the input bands
   * @param tileRectangles Array of rectangles for all source tiles of the image
   * @param op the operator
   */
  private void getClusterCenters(
      final java.util.List<ClusterInfo> pvCenterList,
      final java.util.List<ClusterInfo> pdCenterList,
      final java.util.List<ClusterInfo> psCenterList,
      final PolBandUtils.PolSourceBand srcBandList,
      final Rectangle[] tileRectangles,
      final PolarimetricClassificationOp op) {

    final StatusProgressMonitor status =
        new StatusProgressMonitor(StatusProgressMonitor.TYPE.SUBTASK);
    status.beginTask("Computing Initial Cluster Centres... ", tileRectangles.length);

    final ThreadManager threadManager = new ThreadManager();

    final double[][][] pvSumRe = new double[numInitialClusters][3][3];
    final double[][][] pvSumIm = new double[numInitialClusters][3][3];
    final double[][][] pdSumRe = new double[numInitialClusters][3][3];
    final double[][][] pdSumIm = new double[numInitialClusters][3][3];
    final double[][][] psSumRe = new double[numInitialClusters][3][3];
    final double[][][] psSumIm = new double[numInitialClusters][3][3];

    // counter for the number of pixels in each cluster in the 3 categories: vol, dbl, suf
    final int[][] clusterCounter = new int[3][numInitialClusters];

    try {
      for (final Rectangle rectangle : tileRectangles) {
        op.checkIfCancelled();

        final Thread worker =
            new Thread() {

              final Tile[] sourceTiles = new Tile[srcBandList.srcBands.length];
              final ProductData[] dataBuffers = new ProductData[srcBandList.srcBands.length];

              final double[][] Sr = new double[2][2];
              final double[][] Si = new double[2][2];
              final double[][] Tr = new double[3][3];
              final double[][] Ti = new double[3][3];

              @Override
              public void run() {
                final int x0 = rectangle.x;
                final int y0 = rectangle.y;
                final int w = rectangle.width;
                final int h = rectangle.height;
                final int xMax = x0 + w;
                final int yMax = y0 + h;
                // System.out.println("x0 = " + x0 + ", y0 = " + y0 + ", w = " + w + ", h = " + h);

                for (int i = 0; i < sourceTiles.length; ++i) {
                  sourceTiles[i] = op.getSourceTile(srcBandList.srcBands[i], rectangle);
                  dataBuffers[i] = sourceTiles[i].getDataBuffer();
                }

                final TileIndex srcIndex = new TileIndex(sourceTiles[0]);
                for (int y = y0; y < yMax; ++y) {
                  srcIndex.calculateStride(y);
                  for (int x = x0; x < xMax; ++x) {

                    PolOpUtils.getT3(srcIndex.getIndex(x), sourceProductType, dataBuffers, Tr, Ti);

                    synchronized (clusterCounter) {
                      int clusterIdx;
                      if (mask[y][x] < -64) { // pv
                        clusterIdx = mask[y][x] + 128;
                        computeSummationOfT3(clusterIdx + 1, Tr, Ti, pvSumRe, pvSumIm);
                        clusterCounter[0][clusterIdx]++;
                      } else if (mask[y][x] < 0) { // pd
                        clusterIdx = mask[y][x] + 64;
                        computeSummationOfT3(clusterIdx + 1, Tr, Ti, pdSumRe, pdSumIm);
                        clusterCounter[1][clusterIdx]++;
                      } else if (mask[y][x] < 64) { // ps
                        clusterIdx = mask[y][x];
                        computeSummationOfT3(clusterIdx + 1, Tr, Ti, psSumRe, psSumIm);
                        clusterCounter[2][clusterIdx]++;
                      }
                    }
                  }
                }
              }
            };
        threadManager.add(worker);

        status.worked(1);
      }
      threadManager.finish();

    } catch (Throwable e) {
      OperatorUtils.catchOperatorException(op.getId() + " getClusterCenters ", e);
    } finally {
      status.done();
    }

    // compute centers for all 90 clusters
    for (int c = 0; c < numInitialClusters; c++) {
      double[][] centerRe = new double[3][3];
      double[][] centerIm = new double[3][3];

      if (clusterCounter[0][c] > 0) {
        for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 3; j++) {
            centerRe[i][j] = pvSumRe[c][i][j] / clusterCounter[0][c];
            centerIm[i][j] = pvSumIm[c][i][j] / clusterCounter[0][c];
          }
        }
        ClusterInfo clusterCenter = new ClusterInfo();
        clusterCenter.setClusterCenter(c, centerRe, centerIm, clusterCounter[0][c]);
        pvCenterList.add(clusterCenter);
      }

      if (clusterCounter[1][c] > 0) {
        for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 3; j++) {
            centerRe[i][j] = pdSumRe[c][i][j] / clusterCounter[1][c];
            centerIm[i][j] = pdSumIm[c][i][j] / clusterCounter[1][c];
          }
        }
        ClusterInfo clusterCenter = new ClusterInfo();
        clusterCenter.setClusterCenter(c, centerRe, centerIm, clusterCounter[1][c]);
        pdCenterList.add(clusterCenter);
      }

      if (clusterCounter[2][c] > 0) {
        for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 3; j++) {
            centerRe[i][j] = psSumRe[c][i][j] / clusterCounter[2][c];
            centerIm[i][j] = psSumIm[c][i][j] / clusterCounter[2][c];
          }
        }
        ClusterInfo clusterCenter = new ClusterInfo();
        clusterCenter.setClusterCenter(c, centerRe, centerIm, clusterCounter[2][c]);
        psCenterList.add(clusterCenter);
      }
    }
  }
예제 #9
0
  /**
   * Create 30 initial clusters in each of the 3 categories (vol, dbl and surf). The pixels are
   * first classified into 4 categories (vol, dbl, urf and mixed) based on its Freeman-Durder
   * decomposition result. Then pixels in each category (not include mixed) are grouped into 30
   * clusters based on their power values.
   *
   * @param srcBandList the input bands
   * @param tileRectangles Array of rectangles for all source tiles of the image
   * @param op the operator
   */
  private void createInitialClusters(
      final double[][] fdd,
      final PolBandUtils.PolSourceBand srcBandList,
      final Rectangle[] tileRectangles,
      final PolarimetricClassificationOp op) {

    // Here mask[][] is used in recording the category index for each pixel with -128 for vol, -64
    // for dbl,
    // 0 for surf and 64 for mixed. Later mask[][] will be used in recording for each pixel the
    // cluster index
    // in each category. [-128, -63] are for clusters in vol category, [-64, -1] are for clusters in
    // dbl
    // category and [0, 63] are for clusters in surf category.
    //
    // fdd[][] is used in recording the dominant power of the Freeman-Durden decomposition result
    // for each
    // pixel.

    final StatusProgressMonitor status =
        new StatusProgressMonitor(StatusProgressMonitor.TYPE.SUBTASK);
    status.beginTask("Creating Initial Clusters... ", tileRectangles.length);

    final int[] counter =
        new int[4]; // number of pixels in each of the 4 categories: vol, dbl, suf, mix

    final ThreadManager threadManager = new ThreadManager();

    final double[] pv = new double[srcHeight * srcWidth];
    final double[] pd = new double[srcHeight * srcWidth];
    final double[] ps = new double[srcHeight * srcWidth];

    try {
      for (final Rectangle rectangle : tileRectangles) {
        op.checkIfCancelled();

        final Thread worker =
            new Thread() {

              final Tile[] sourceTiles = new Tile[srcBandList.srcBands.length];
              final ProductData[] dataBuffers = new ProductData[srcBandList.srcBands.length];

              final double[][] Cr = new double[3][3];
              final double[][] Ci = new double[3][3];

              @Override
              public void run() {
                final int x0 = rectangle.x;
                final int y0 = rectangle.y;
                final int w = rectangle.width;
                final int h = rectangle.height;
                final int xMax = x0 + w;
                final int yMax = y0 + h;
                // System.out.println("x0 = " + x0 + ", y0 = " + y0 + ", w = " + w + ", h = " + h);

                final Rectangle sourceRectangle = getSourceRectangle(x0, y0, w, h);
                for (int i = 0; i < sourceTiles.length; ++i) {
                  sourceTiles[i] = op.getSourceTile(srcBandList.srcBands[i], sourceRectangle);
                  dataBuffers[i] = sourceTiles[i].getDataBuffer();
                }

                for (int y = y0; y < yMax; ++y) {
                  for (int x = x0; x < xMax; ++x) {

                    PolOpUtils.getMeanCovarianceMatrix(
                        x,
                        y,
                        halfWindowSizeX,
                        halfWindowSizeY,
                        sourceProductType,
                        sourceTiles,
                        dataBuffers,
                        Cr,
                        Ci);

                    final FreemanDurden.FDD data =
                        FreemanDurden.getFreemanDurdenDecomposition(Cr, Ci);

                    synchronized (counter) {
                      if (!Double.isNaN(data.pv)
                          && !Double.isNaN(data.pd)
                          && !Double.isNaN(data.ps)) {
                        Categories cat =
                            getCategory(data.pv, data.pd, data.ps, mixedCategoryThreshold);
                        if (cat == Categories.vol) {
                          mask[y][x] = -128;
                          fdd[y][x] = data.pv;
                          pv[counter[0]] = data.pv;
                          counter[0] += 1;
                        } else if (cat == Categories.dbl) {
                          mask[y][x] = -64;
                          fdd[y][x] = data.pd;
                          pd[counter[1]] = data.pd;
                          counter[1] += 1;
                        } else if (cat == Categories.suf) {
                          mask[y][x] = 0;
                          fdd[y][x] = data.ps;
                          ps[counter[2]] = data.ps;
                          counter[2] += 1;
                        } else { // cat == Categories.mix
                          mask[y][x] = 64;
                          fdd[y][x] = (data.pv + data.pd + data.ps) / 3.0;
                          counter[3] += 1;
                        }
                      }
                    }
                  }
                }
              }
            };
        threadManager.add(worker);

        status.worked(1);
      }
      threadManager.finish();

    } catch (Throwable e) {
      OperatorUtils.catchOperatorException(op.getId() + " createInitialClusters ", e);
    } finally {
      status.done();
    }

    // for each category, compute 29 thresholds which will be used later in dividing each category
    // into 30 small
    // clusters with roughly equal number of pixels based on the pixel values.
    final int pvClusterSize = counter[0] / numInitialClusters;
    final int pdClusterSize = counter[1] / numInitialClusters;
    final int psClusterSize = counter[2] / numInitialClusters;

    if (pvClusterSize > 0) {
      Arrays.sort(pv, 0, counter[0] - 1);
    }
    if (pdClusterSize > 0) {
      Arrays.sort(pd, 0, counter[1] - 1);
    }
    if (psClusterSize > 0) {
      Arrays.sort(ps, 0, counter[2] - 1);
    }

    final double[] pvThreshold = new double[numInitialClusters - 1];
    final double[] pdThreshold = new double[numInitialClusters - 1];
    final double[] psThreshold = new double[numInitialClusters - 1];
    for (int i = 0; i < numInitialClusters - 1; i++) {
      pvThreshold[i] = pv[(i + 1) * pvClusterSize];
      pdThreshold[i] = pd[(i + 1) * pdClusterSize];
      psThreshold[i] = ps[(i + 1) * psClusterSize];
    }

    // classify pixels into 30 clusters within each category, record number of pixels in each
    // cluster
    int clusterIdx = -1;
    for (int y = 0; y < srcHeight; y++) {
      for (int x = 0; x < srcWidth; x++) {
        if (mask[y][x] == -128) {
          clusterIdx = computePixelClusterIdx(fdd[y][x], pvThreshold, numInitialClusters);
          mask[y][x] += clusterIdx;
        } else if (mask[y][x] == -64) {
          clusterIdx = computePixelClusterIdx(fdd[y][x], pdThreshold, numInitialClusters);
          mask[y][x] += clusterIdx;
        } else if (mask[y][x] == 0) {
          clusterIdx = computePixelClusterIdx(fdd[y][x], psThreshold, numInitialClusters);
          mask[y][x] += clusterIdx;
        }
      }
    }
  }