use of qupath.lib.objects.PathObject in project qupath by qupath.
the class ClassifierBuilderPane method selectAllFeatures.
/**
* Try to select all features, forcing an update to check for current objects
*/
private void selectAllFeatures() {
Map<PathClass, List<PathObject>> map = getTrainingMap();
Set<String> featureNames = new TreeSet<>();
for (List<PathObject> list : map.values()) {
for (PathObject temp : list) {
featureNames.addAll(temp.getMeasurementList().getMeasurementNames());
}
}
// If we don't have any training features, let feature panel try to get them itself for current ImageDat
if (featureNames.isEmpty())
featurePanel.ensureMeasurementsUpdated();
else
featurePanel.updateMeasurementsByNames(featureNames);
featurePanel.selectAllAvailableFeatures();
updateSelectedFeaturesLabel();
}
use of qupath.lib.objects.PathObject in project qupath by qupath.
the class PathClassificationLabellingHelper method getClassificationMap.
/**
* Get a map of training data, based on the child objects of some classified annotations.
*
* @param hierarchy the hierarchy containing all the objects and annotations.
* @param pointsOnly if true, only Point annotations will be used for training.
*
* @return
*/
public static Map<PathClass, List<PathObject>> getClassificationMap(final PathObjectHierarchy hierarchy, final boolean pointsOnly) {
Map<PathClass, List<PathObject>> classifications = new TreeMap<>();
// Get the annotations & filter out those that are useful
List<PathObject> annotations = new ArrayList<>(getAnnotations(hierarchy));
Iterator<PathObject> iter = annotations.iterator();
while (iter.hasNext()) {
PathObject pathObject = iter.next();
// We need a PathClass, and may need to only include points
if (pathObject.getPathClass() == null || pathObject.getPathClass() == PathClassFactory.getPathClass(StandardPathClasses.REGION) || (pointsOnly && !PathObjectTools.hasPointROI(pathObject)))
iter.remove();
else
classifications.put(pathObject.getPathClass(), new ArrayList<>());
}
// from the hierarchy
if (annotations.size() > 1) {
annotations.sort(new Comparator<PathObject>() {
@Override
public int compare(PathObject o1, PathObject o2) {
PathAnnotationObject p1 = (PathAnnotationObject) o1;
PathAnnotationObject p2 = (PathAnnotationObject) o2;
int comp = 0;
if (p1.hasROI()) {
if (p2.hasROI()) {
comp = Double.compare(p1.getROI().getCentroidY(), p2.getROI().getCentroidY());
if (comp == 0)
comp = Double.compare(p1.getROI().getCentroidX(), p2.getROI().getCentroidX());
if (comp == 0)
comp = p1.getROI().toString().compareTo(p2.getROI().toString());
}
}
if (comp == 0)
return Integer.compare(o1.hashCode(), o2.hashCode());
else
return comp;
}
});
}
// StringBuilder sb = new StringBuilder("DETECTIONS:\t");
for (PathObject pathObject : annotations) {
PathClass pathClass = pathObject.getPathClass();
List<PathObject> list = classifications.get(pathClass);
// sb.append(list.size() + ", ");
if (PathObjectTools.hasPointROI(pathObject)) {
for (Point2 p : ((PointsROI) pathObject.getROI()).getAllPoints()) {
// TODO: Pay attention to z & t position!
Collection<PathObject> pathObjectsTemp = PathObjectTools.getObjectsForLocation(hierarchy, p.getX(), p.getY(), 0, 0, -1);
pathObjectsTemp = PathObjectTools.getObjectsOfClass(pathObjectsTemp, PathDetectionObject.class);
// Clumsy way to avoid duplicates...
list.removeAll(pathObjectsTemp);
list.addAll(pathObjectsTemp);
}
} else
list.addAll(hierarchy.getObjectsForROI(PathDetectionObject.class, pathObject.getROI()));
}
for (Entry<PathClass, List<PathObject>> entry : classifications.entrySet()) {
logger.info(entry.getKey() + ": " + entry.getValue().size());
}
return classifications;
}
use of qupath.lib.objects.PathObject in project qupath by qupath.
the class PathClassificationLabellingHelper method resampleClassificationMap.
/**
* Resample a training map (PathClass label & lists of PathObjects that should have the specified classifications) so that
* it contains only a specified proportion of entries.
*
* @param map
* @param splitType
* @param proportion between 0 (empty map) and 1
* @param seed
* @return
*/
public static Map<PathClass, List<PathObject>> resampleClassificationMap(final Map<PathClass, List<PathObject>> map, final SplitType splitType, final double proportion, final long seed) {
if (proportion > 1 || proportion == 0)
throw new IllegalArgumentException("Proportion of samples to use for training cannot be < 0 or > 1!");
if (proportion == 0)
return Collections.emptyMap();
if (proportion == 1 && splitType != SplitType.RANDOM_WITH_REPLACEMENT)
return map;
int n = 0;
for (List<PathObject> temp : map.values()) n += temp.size();
int maxTrainingInstances = (int) (n * proportion + .5);
List<TrainingEntry> entries = new ArrayList<>();
for (Entry<PathClass, List<PathObject>> entry : map.entrySet()) {
List<PathObject> list = entry.getValue();
if (splitType == SplitType.LAST_SAMPLES)
Collections.reverse(list);
int maxCount = Integer.MAX_VALUE;
if (splitType == SplitType.LAST_SAMPLES || splitType == SplitType.FIRST_SAMPLES)
maxCount = (int) (list.size() * proportion + .9);
PathClass pathClass = entry.getKey();
int count = 0;
for (PathObject temp : list) {
entries.add(new TrainingEntry(pathClass, temp));
count++;
if (count >= maxCount)
break;
}
}
Map<PathClass, List<PathObject>> map2 = new TreeMap<>();
Random random = new Random(seed);
switch(splitType) {
case EQUIDISTANT:
double increment = 1.0 / proportion;
for (double i = 0; i < entries.size(); i += increment) {
int ind = (int) i;
TrainingEntry entry = entries.get(ind);
addToMap(map2, entry.pathClass, entry.pathObject);
}
;
return map2;
// return resampleClassificationMapEquidistantly(map, proportion);
case RANDOM_NO_REPLACEMENT:
Collections.shuffle(entries, random);
// Fall through...
case FIRST_SAMPLES:
// Fall through...
case LAST_SAMPLES:
for (int i = 0; i < maxTrainingInstances; i++) {
TrainingEntry entry = entries.get(i);
addToMap(map2, entry.pathClass, entry.pathObject);
}
;
return map2;
case RANDOM_WITH_REPLACEMENT:
for (int i = 0; i < maxTrainingInstances; i++) {
int ind = random.nextInt(n);
TrainingEntry entry = entries.get(ind);
addToMap(map2, entry.pathClass, entry.pathObject);
}
;
return map2;
default:
break;
}
return map;
}
use of qupath.lib.objects.PathObject in project qupath by qupath.
the class PathClassifierPane method runClassifier.
void runClassifier() {
QuPathViewer viewer = viewerValue.getValue();
if (viewer == null)
return;
ImageData<BufferedImage> imageData = viewer.getImageData();
if (classifier == null || imageData == null || !classifier.isValid())
return;
Collection<PathObject> pathObjects = imageData.getHierarchy().getDetectionObjects();
var availableFeatures = PathClassifierTools.getAvailableFeatures(pathObjects);
var requiredFeatures = classifier.getRequiredMeasurements();
String missingFeatures = requiredFeatures.stream().filter(p -> !availableFeatures.contains(p)).collect(Collectors.joining("\n\t"));
if (!missingFeatures.isEmpty())
logger.warn("Detection objects are missing the following feature(s):\n\t" + missingFeatures + "\nWill proceed with classification anyway..");
// SwingUtilities.getRoot(viewer).setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
PathClassifierTools.runClassifier(imageData.getHierarchy(), classifier);
// Log the classifier
if (pathClassifier != null) {
imageData.getHistoryWorkflow().addStep(new RunSavedClassifierWorkflowStep(pathClassifier));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// SwingUtilities.getRoot(viewer).setCursor(cursor);
// Update displayed list - names may have changed - and classifier summary
updateClassifierSummary();
}
}
use of qupath.lib.objects.PathObject in project qupath by qupath.
the class RetainedTrainingObjects method addToTrainingMap.
/**
* Append retained objects, grouped by classification, to an existing training map.
*
* @param map
* @return
*/
public int addToTrainingMap(final Map<PathClass, List<PathObject>> map) {
int retainedImageCount = 0;
for (Entry<String, Map<PathClass, List<PathObject>>> entry : retainedObjectsMap.entrySet()) {
// Put any retained objects into the map
Map<PathClass, List<PathObject>> map2 = entry.getValue();
for (Entry<PathClass, List<PathObject>> entry2 : map2.entrySet()) {
PathClass pathClassTemp = entry2.getKey();
List<PathObject> listMain = map.get(pathClassTemp);
if (listMain == null) {
listMain = new ArrayList<>();
map.put(pathClassTemp, listMain);
}
listMain.addAll(entry2.getValue());
}
retainedImageCount++;
}
return retainedImageCount;
}
Aggregations