use of org.vitrivr.cineast.core.data.score.ScoreElement in project cineast by vitrivr.
the class SpatialDistance method getSimilar.
/**
* Returns similar <i>objects</i> to the feature data contained in the given segment container.
*/
@Override
public List<ScoreElement> getSimilar(SegmentContainer sc, ReadableQueryConfig qc) {
final QueryConfig mqc = QueryConfig.clone(qc);
if (sc instanceof ParameterisedLocationQueryTermContainer) {
if (((ParameterisedLocationQueryTermContainer) sc).getParameter().isPresent()) {
final String param = ((ParameterisedLocationQueryTermContainer) sc).getParameter().get();
mqc.setCorrespondenceFunctionIfEmpty(CorrespondenceFunction.hyperbolic(parseAndEvaluateHalfSimilarityDistance(param)));
}
}
return this.extractFeature(sc).map(ReadableFloatVector::toArray).map(array -> this.getSimilar(array, new ReadableQueryConfig(mqc))).orElse(Collections.emptyList());
}
use of org.vitrivr.cineast.core.data.score.ScoreElement in project cineast by vitrivr.
the class MFCCShingle method postprocessQuery.
/**
* This method represents the last step that's executed when processing a query. A list of partial-results (DistanceElements) returned by the lookup stage is processed based on some internal method and finally converted to a list of ScoreElements. The filtered list of ScoreElements is returned by the feature module during retrieval.
*
* @param partialResults List of partial results returned by the lookup stage.
* @param qc A ReadableQueryConfig object that contains query-related configuration parameters.
* @return List of final results. Is supposed to be de-duplicated and the number of items should not exceed the number of items per module.
*/
@Override
protected List<ScoreElement> postprocessQuery(List<SegmentDistanceElement> partialResults, ReadableQueryConfig qc) {
/* Prepare helper data-structures. */
final List<ScoreElement> results = new ArrayList<>();
final TObjectIntHashMap<String> scoreMap = new TObjectIntHashMap<>();
/* Set QueryConfig and extract correspondence function. */
qc = this.setQueryConfig(qc);
final CorrespondenceFunction correspondence = qc.getCorrespondenceFunction().orElse(this.correspondence);
for (DistanceElement hit : partialResults) {
if (hit.getDistance() < this.distanceThreshold) {
scoreMap.adjustOrPutValue(hit.getId(), 1, scoreMap.get(hit.getId()) / 2);
}
}
/* Prepare final result-set. */
scoreMap.forEachEntry((key, value) -> results.add(new SegmentScoreElement(key, 1.0 - 1.0 / value)));
ScoreElement.filterMaximumScores(results.stream());
return results;
}
use of org.vitrivr.cineast.core.data.score.ScoreElement in project cineast by vitrivr.
the class ContinuousQueryDispatcher method addRetrievalResult.
private void addRetrievalResult(TObjectDoubleMap<String> scoreByObjectId, TObjectDoubleMap<String> scoreBySegmentId, RetrievalTask task, List<ScoreElement> scoreElements) {
if (scoreElements == null) {
LOGGER.warn("Retrieval task {} returned 'null' results.", task);
return;
}
for (RetrievalResultListener listener : resultListeners) {
listener.notify(scoreElements, task);
}
double retrieverWeight = this.retrieverWeights.get(task.getRetriever());
for (ScoreElement element : scoreElements) {
TObjectDoubleMap<String> scoreById;
if (element instanceof ObjectScoreElement) {
scoreById = scoreByObjectId;
} else if (element instanceof SegmentScoreElement) {
scoreById = scoreBySegmentId;
} else if (element instanceof BooleanSegmentScoreElement) {
// TODO: Cleanup?
scoreById = scoreBySegmentId;
} else {
LOGGER.error("Unknown subclass {} of ScoreElement in ContinuousQueryDispatcher.addRetrievalResult.", element.getClass().getSimpleName());
continue;
}
this.addScoreElement(scoreById, element, retrieverWeight);
}
}
use of org.vitrivr.cineast.core.data.score.ScoreElement in project cineast by vitrivr.
the class RetrievalResultCSVExporter method notify.
@Override
public void notify(List<ScoreElement> resultList, RetrievalTask task) {
ReadableQueryConfig qc = task.getConfig();
String queryIdString;
if (qc == null || qc.getQueryId() == null) {
LOGGER.error("could not determine query id, using 'null'");
queryIdString = "null";
} else {
queryIdString = qc.getQueryId().toString();
}
String filename = task.getRetriever().getClass().getSimpleName() + ".csv";
File outFolder = new File(baseFolder, queryIdString);
outFolder.mkdirs();
File out = new File(outFolder, filename);
ArrayList<String> ids = new ArrayList<>(resultList.size());
for (ScoreElement e : resultList) {
ids.add(e.getId());
}
Map<String, MediaSegmentDescriptor> segments = mediaSegmentReader.lookUpSegments(ids);
Set<String> objectIds = new HashSet<>();
for (MediaSegmentDescriptor sd : segments.values()) {
objectIds.add(sd.getObjectId());
}
Map<String, MediaObjectDescriptor> objects = mediaObjectReader.lookUpObjects(objectIds);
try (PrintWriter writer = new PrintWriter(out)) {
// header
writer.println("\"rank\", \"id\", \"score\", \"path\"");
int rank = 1;
for (ScoreElement e : resultList) {
writer.print(rank++);
writer.print(',');
writer.print(e.getId());
writer.print(',');
writer.print(e.getScore());
writer.print(',');
writer.print('"');
writer.print(objects.get(segments.get(e.getId()).getObjectId()).getPath().replace('\\', '/'));
writer.println('"');
}
writer.flush();
} catch (FileNotFoundException e) {
LOGGER.error("could not write file '{}': {}", out.getAbsolutePath(), LogHelper.getStackTrace(e));
}
}
use of org.vitrivr.cineast.core.data.score.ScoreElement in project cineast by vitrivr.
the class SegmentTags method getSimilar.
private List<ScoreElement> getSimilar(Iterable<WeightedTag> tags, ReadableQueryConfig qc) {
ArrayList<String> tagids = new ArrayList<>();
TObjectFloatHashMap<String> tagWeights = new TObjectFloatHashMap<>();
float weightSum = 0f;
/* Sum weights for normalization at a later point*/
for (WeightedTag wt : tags) {
tagids.add(wt.getId());
tagWeights.put(wt.getId(), wt.getWeight());
if (wt.getWeight() > 1) {
LOGGER.error("Weight is > 1 -- this makes little sense.");
}
weightSum += Math.min(1, wt.getWeight());
}
if (tagids.isEmpty() || weightSum <= 0f) {
return Collections.emptyList();
}
/* Retrieve all elements matching the provided ids */
List<Map<String, PrimitiveTypeProvider>> rows = this.selector.getRows("tagid", tagids.stream().map(StringTypeProvider::new).collect(Collectors.toList()));
Map<String, TObjectFloatHashMap<String>> maxScoreByTag = new HashMap<>();
/* Prepare the set of relevant ids (if this entity is used for filtering at a later stage) */
Set<String> relevant = null;
if (qc != null && qc.hasRelevantSegmentIds()) {
relevant = qc.getRelevantSegmentIds();
}
/* Iterate over all matches */
for (Map<String, PrimitiveTypeProvider> row : rows) {
String segmentId = row.get("id").getString();
/* Skip segments which are not desired by the query-config */
if (relevant != null && !relevant.contains(segmentId)) {
continue;
}
String tagid = row.get("tagid").getString();
float score = row.get("score").getFloat() * (tagWeights.containsKey(tagid) ? tagWeights.get(tagid) : 0f);
if (score > 1) {
LOGGER.warn("Score is larger than 1 - this makes little sense");
score = 1f;
}
/* Update maximum score by tag*/
maxScoreByTag.putIfAbsent(segmentId, new TObjectFloatHashMap<>());
float prev = maxScoreByTag.get(segmentId).get(tagid);
if (prev == Constants.DEFAULT_FLOAT_NO_ENTRY_VALUE) {
maxScoreByTag.get(segmentId).put(tagid, score);
} else {
maxScoreByTag.get(segmentId).put(tagid, Math.max(score, prev));
}
}
ArrayList<ScoreElement> _return = new ArrayList<>();
final float normalizer = weightSum;
/* per segment, the max score for all tags is summed and divided by the normalizer */
maxScoreByTag.forEach((segmentId, tagScores) -> _return.add(new SegmentScoreElement(segmentId, MathHelper.sum(tagScores.values()) / normalizer)));
return _return;
}
Aggregations