package com.elphel.imagej.orthomosaic; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import com.elphel.imagej.common.ShowDoubleFloatArrays; import ij.ImagePlus; import ij.Prefs; import ij.gui.PointRoi; import ij.io.FileSaver; public class ItemMatch { public double [] combo_pxy; // combo image {pixel_x, pixel_y} public double [] lla; // add later public HashMap<String, ItemPatternMatch> pattern_matches = new HashMap<String, ItemPatternMatch>(); public double abs_contrast = 0; public CorrelationPeakStats[][] filter_data; // [scene][half/full] public double [][] extracted_objects; // [scene][pix] public double [][] extracted_nodc; // [scene][pix] public double [][] extracted_masked; // [scene][pix] public double [][][] extr_corr; // [scene][pix][patt] public double [][] extr_corr_half; // [scene][pix][h/f] public boolean removed = false; public ItemMatch ( int num_scenes, double [] combo_pxy) { setComboPXY(combo_pxy); this.combo_pxy = combo_pxy; filter_data = new CorrelationPeakStats[num_scenes][2]; extracted_objects = new double [num_scenes][]; extracted_nodc = new double [num_scenes][]; extracted_masked = new double [num_scenes][]; extr_corr = new double [num_scenes][][]; extr_corr_half = new double [num_scenes][]; removed = false; } public void setRemoved (boolean removed) { this.removed = removed; } public void remove () { this.removed = true; } public boolean isRemoved() { return removed; } public void setCorrFull( int scene_num, int num_patt, double [] corr_data) { extr_corr[scene_num] = new double [num_patt][]; extr_corr[scene_num][0] = corr_data; } public void setCorr( int scene_num, int patt_index, double [] corr_data) { extr_corr[scene_num][patt_index] = corr_data; } public double [] getCorr( int scene_num, int patt_index) { return extr_corr[scene_num][patt_index]; } public double [][] getCorrs( int scene_num) { return extr_corr[scene_num]; } public void setCorrHalf( int scene_num, int best_patt, // 0-full boolean combine_full) { extr_corr_half[scene_num] = extr_corr[scene_num][best_patt].clone(); if (combine_full) { double full_max_value = filter_data[scene_num][0].best_d; // [0]; if (!Double.isNaN(full_max_value)) { // multiply by full correlation, delete by full correlation maximum for (int i = 0; i < extr_corr_half[scene_num].length; i++){ extr_corr_half[scene_num][i] *= Math.max(0, extr_corr[scene_num][0][i]/full_max_value); } } } } public void setCorrHalf( int scene_num, double [] corr_data) { extr_corr_half[scene_num] = corr_data; } public double [] getCorrHalf( int scene_num) { return extr_corr_half[scene_num]; } public void setComboPXY(double [] combo_pxy) { this.combo_pxy = combo_pxy; } public void setAbsoluteContrast(double contrast) { abs_contrast = contrast; // only for main scene } public double getAbsoluteContrast() { return abs_contrast; } public double [] getXY() { return combo_pxy; } public int [] getIntXY() { return new int [] {(int) Math.round(combo_pxy[0]), (int) Math.round(combo_pxy[1])}; } public void addPatternMatches( // updates existing too GroundObjectPattern groundObjectPattern, double [] matches, int best_sub) { String pattern_path = groundObjectPattern.getPatternPath(); ItemPatternMatch match = pattern_matches.get(pattern_path); if (match == null) { match = new ItemPatternMatch(groundObjectPattern); pattern_matches.put(pattern_path, match); } match.setMatches(matches); match.setBestSub(best_sub); } public ItemPatternMatch getPatternMatch(GroundObjectPattern groundObjectPattern) { return getPatternMatch(groundObjectPattern.getPatternPath()); } public ItemPatternMatch getPatternMatch(String pattern_path) { return pattern_matches.get(pattern_path); } public double [] getMatchValues(String pattern_path) { ItemPatternMatch match = pattern_matches.get(pattern_path); if (match == null) { System.out.println("No matches found for pattern "+pattern_path); return null; } return match.getMatches(); } public double [] getMatchValues(GroundObjectPattern groundObjectPattern) { return getMatchValues(groundObjectPattern.getPatternPath()); } /** * Get ratio of the worst and best partial pattern correlation values * @param groundObjectPattern * @return */ public double getRoundness (GroundObjectPattern groundObjectPattern) { return getRoundness(groundObjectPattern.getPatternPath()); } public double getRoundness (String pattern_path) { ItemPatternMatch match = pattern_matches.get(pattern_path); if (match == null) { System.out.println("No matches found for pattern "+pattern_path); return Double.NaN; } double [] matches = match.getMatches(); double best = matches[1]; double worst = matches[1]; for (int i = 1; i < matches.length; i++) { if (matches[i] < worst) { worst = matches[i]; } if (matches[i] > best) { best = matches[i]; } } return worst/best; } public double getMatchValue(String pattern_path, int indx) { ItemPatternMatch match = pattern_matches.get(pattern_path); if (match == null) { System.out.println("No matches found for pattern "+pattern_path); return Double.NaN; } return match.getMatch(indx); } public double getMatchBestValue(String pattern_path) { ItemPatternMatch match = pattern_matches.get(pattern_path); if (match == null) { System.out.println("No matches found for pattern "+pattern_path); return Double.NaN; } return match.getBestMatchValue(); } /** * Return correlation value as the one of the pattern correlations pointed * by the best subpattern index. * @param groundObjectPattern * @return selected correlation value */ public double getMatchValue(GroundObjectPattern groundObjectPattern) { return getMatchValue(groundObjectPattern.getPatternPath()); } /** * Return actual best correlation value regardless of where best subpattern index * points to - it may be forced to point to the full pattern by absolute contrast * @param groundObjectPattern * @return maximal correlation value amoong the full pattern and all half-patterns. */ public double getMatchBestValue(GroundObjectPattern groundObjectPattern) { return getMatchBestValue(groundObjectPattern.getPatternPath()); } public double getMatchValue(String pattern_path) { int indx = getPatternMatch(pattern_path).getBestSub(); // -1; return getMatchValue(pattern_path,indx); } public double getMatchValue(GroundObjectPattern groundObjectPattern, int indx) { return getMatchValue(groundObjectPattern.getPatternPath(), indx); } public static ArrayList<Integer> sortByMatch( ArrayList<ItemMatch> match_list, GroundObjectPattern groundObjectPattern, boolean keep_removed, int indx){ String pattern_path = groundObjectPattern.getPatternPath(); return sortByMatch(match_list, pattern_path, keep_removed, indx); } public static ArrayList<Integer> sortByMatch( ArrayList<ItemMatch> match_list, String pattern_path, boolean keep_removed, int indx){ if (indx < 0) { return sortByBestMatch (match_list, pattern_path, keep_removed); } double large_enough = 1.0; ArrayList<Integer> result_list= new ArrayList<Integer>(match_list.size()); for (int i = 0; i < match_list.size(); i++) { if (keep_removed || !match_list.get(i).isRemoved()) { result_list.add(i); } } Collections.sort(result_list, new Comparator<Integer>() { @Override public int compare(Integer lhs, Integer rhs) { ItemMatch rhsm = match_list.get(rhs); ItemMatch lhsm = match_list.get(lhs); double rhsd = rhsm.getMatchValue(pattern_path, indx) - (rhsm.isRemoved() ? large_enough:0 ); double lhsd = lhsm.getMatchValue(pattern_path, indx) - (lhsm.isRemoved() ? large_enough:0 ); return (rhsd > lhsd) ? 1 : (rhsd < lhsd) ? -1 : 0; // decreasing } }); return result_list; } public static ArrayList<Integer> sortByBestMatch( ArrayList<ItemMatch> match_list, String pattern_path, boolean keep_removed){ double large_enough = 1.0; ArrayList<Integer> result_list= new ArrayList<Integer>(match_list.size()); for (int i = 0; i < match_list.size(); i++) { if (keep_removed || !match_list.get(i).isRemoved()) { result_list.add(i); } } Collections.sort(result_list, new Comparator<Integer>() { @Override public int compare(Integer lhs, Integer rhs) { ItemMatch rhsm = match_list.get(rhs); ItemMatch lhsm = match_list.get(lhs); double rhsd = rhsm.getMatchBestValue(pattern_path) - (rhsm.isRemoved() ? large_enough:0 ); double lhsd = lhsm.getMatchBestValue(pattern_path) - (lhsm.isRemoved() ? large_enough:0 ); return (rhsd > lhsd) ? 1 : (rhsd < lhsd) ? -1 : 0; // decreasing } }); return result_list; } public static void setExtractedObjects( int scene_num, int extr_size, GroundObjectPattern gop, ArrayList <ItemMatch> matches_list, ArrayList<Integer> match_sort, double[] data, int width, int debugLevel) { if (match_sort.isEmpty()) { System.out.println("List of detected objects is empty, nothing to process"); return; } for (int mn=0; mn < match_sort.size(); mn++) { int indx =match_sort.get(mn); ItemMatch match = matches_list.get(indx); match.extractObject( data, // double [] data, width, // int width, scene_num, // int scene_num, extr_size); // int extr_size); } } public void extractObject( double [] data, int width, int scene_num, int extr_size) { double [] center_xy = getXY(); double [] extr_data = ObjectLocation.extractObjectImage( center_xy, // double [] center_xy, extr_size, // int size, data, // double [] src_img, width); // int width) setExtractedObject(extr_data, scene_num); } public void extractCorrs( double [][] corr_data, int width, int scene_num, int extr_size) { double [] center_xy = getXY(); extr_corr[scene_num] = new double [corr_data.length][]; for (int i = 0; i < corr_data.length; i++) { extr_corr[scene_num][i] = ObjectLocation.extractObjectImage( center_xy, // double [] center_xy, extr_size, // int size, corr_data[i], // double [] src_img, width); // int width) } } public void setExtractedObject( double [] data, int scene_num) { extracted_objects[scene_num] = data; extracted_nodc[scene_num] = data.clone(); OrthoMap.removeDC(extracted_nodc[scene_num]); } public void setMaskedObject( double [] data, int scene_num) { extracted_masked[scene_num] = data; } public void setCorrData( double [] data, int scene_num, int half_full) { // 1 - half, 0 - full extr_corr[scene_num][half_full] = data; } public static ImagePlus getImageExtracts( String prefix, // include PC, filter here String suffix, // w/o .tiff boolean show, boolean save, boolean show_removed, String save_dir, int scene_num, boolean nodc, int mode, // 0 - extract, 1 - masked, 2 - corr full, 3 - corr half boolean show_centers, int extr_size, GroundObjectPattern gop, ArrayList <ItemMatch> matches_list, ArrayList<Integer> match_sort, int debugLevel) { if (match_sort.isEmpty()) { System.out.println("List of detected objects is empty, nothing to display"); return null; } PointRoi roi = new PointRoi(); roi.setOptions("nolabel"); // label"); for (int mn=0; mn < match_sort.size(); mn++) { roi.addPoint(extr_size/2,extr_size/2,mn+1); // ,1); } int num_slices = match_sort.size(); if (!show_removed) { num_slices=0; for (int mn=0; mn < match_sort.size(); mn++) { if (!matches_list.get(match_sort.get(mn)).isRemoved()) { num_slices++; } } } String [] extr_titles = new String [num_slices]; double [][] extr_data = new double [num_slices][]; String title = prefix; switch (mode) { case 0: title += "_objects_" + scene_num + (nodc ? "_no-DC":"_with-DC"); break; case 1: title += "_contrast-masks"; break; case 2: title += "_objects_"+scene_num+"_corr_full"; break; case 3: title += "_objects_"+scene_num+"_corr_halves"; break; } if (suffix != null) { title += suffix; } title += ".tiff"; int indx = 0; for (int mn=0; mn < match_sort.size(); mn++) { ItemMatch match = matches_list.get(match_sort.get(mn)); if (show_removed || !matches_list.get(match_sort.get(mn)).isRemoved()) { int [] ixy = match.getIntXY(); extr_titles[indx] = ixy[0]+"/"+ ixy[1]+":"+String.format("%7.5f", match.getMatchValue(gop)); switch (mode) { case 0: extr_data[indx] = nodc ? match.extracted_nodc[scene_num] : match.extracted_objects[scene_num]; break; case 1: extr_data[indx] = match.extracted_masked[scene_num]; break; case 2: extr_data[indx] = match.extr_corr[scene_num][0]; break; case 3: extr_data[indx] = match.extr_corr_half[scene_num]; break; } indx++; } } ImagePlus imp = ShowDoubleFloatArrays.makeArrays( extr_data, extr_size, extr_size, title, // +"-objects_"+scene_num, extr_titles); // test_titles, if (imp == null) { return null; } if (show_centers) { imp.setRoi(roi); // null } if (show) { imp.show(); } if (save && (save_dir != null)) { if (!save_dir.endsWith(Prefs.getFileSeparator())) { save_dir+=Prefs.getFileSeparator(); } String save_path = save_dir+title; FileSaver imp_fs = new FileSaver(imp); imp_fs.saveAsTiff(save_path); if (debugLevel > -4) { System.out.println("Saved "+save_path); } } return imp; } }