/** * Merge two clusters in the cluster list for given cluster indices. * * @param clusterCenterList The list of cluster centers. * @param clusterPair Indices of the two clusters to merge. */ private static void mergeClusters( final java.util.List<ClusterInfo> clusterCenterList, final int[] clusterPair) { final int idx1 = clusterPair[0]; final int idx2 = clusterPair[1]; final int size1 = clusterCenterList.get(idx1).size; final int size2 = clusterCenterList.get(idx2).size; final int newClusterSize = size1 + size2; final double[][] newCenterRe = new double[3][3]; final double[][] newCenterIm = new double[3][3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { newCenterRe[i][j] = (size1 * clusterCenterList.get(idx1).centerRe[i][j] + size2 * clusterCenterList.get(idx2).centerRe[i][j]) / newClusterSize; newCenterIm[i][j] = (size1 * clusterCenterList.get(idx1).centerIm[i][j] + size2 * clusterCenterList.get(idx2).centerIm[i][j]) / newClusterSize; } } if (idx1 < idx2) { clusterCenterList.remove(idx2); clusterCenterList.remove(idx1); } else { clusterCenterList.remove(idx1); clusterCenterList.remove(idx2); } ClusterInfo clusterCenter = new ClusterInfo(); clusterCenter.setClusterCenter( clusterCenterList.size(), newCenterRe, newCenterIm, newClusterSize); clusterCenterList.add(clusterCenter); }
/** * 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); } } }