Esempio n. 1
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);
      }
    }
  }
Esempio n. 2
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;
        }
      }
    }
  }