use of org.vitrivr.cineast.core.data.entities.MediaSegmentDescriptor in project cineast by vitrivr.
the class VideoHistogramSegmenter method run.
/**
* When an object implementing interface <code>Runnable</code> is used to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may take any action whatsoever.
*
* @see Thread#run()
*/
@Override
public void run() {
/* Begin: Set running to false. */
synchronized (this) {
this.isrunning = true;
}
try {
while (!this.decoder.complete()) {
if (this.videoFrameList.isEmpty()) {
queueFrames();
}
VideoSegment _return = null;
if (!preShotList.isEmpty()) {
_return = new VideoSegment();
while (!preShotList.isEmpty()) {
_return.addVideoFrame(preShotList.removeFirst().first);
}
}
if (this.videoFrameList.isEmpty()) {
this.segments.put(_return);
// no more shots to segment
continue;
}
if (_return == null) {
_return = new VideoSegment();
}
VideoFrame videoFrame = this.videoFrameList.poll();
MediaSegmentDescriptor bounds = this.knownShotBoundaries.size() > 0 ? this.knownShotBoundaries.remove(0) : null;
if (bounds != null && videoFrame.getId() >= bounds.getStart() && videoFrame.getId() <= bounds.getEnd()) {
_return.addVideoFrame(videoFrame);
queueFrames(bounds.getEnd() - bounds.getStart());
do {
videoFrame = this.videoFrameList.poll();
if (videoFrame != null) {
_return.addVideoFrame(videoFrame);
} else {
break;
}
} while (videoFrame.getId() < bounds.getEnd());
this.segments.put(_return);
continue;
} else {
Histogram hPrev, h = getHistogram(videoFrame);
_return.addVideoFrame(videoFrame);
while (true) {
if ((videoFrame = this.videoFrameList.poll()) == null) {
queueFrames();
if ((videoFrame = this.videoFrameList.poll()) == null) {
this.segments.put(_return);
_return = null;
break;
}
}
hPrev = h;
h = getHistogram(videoFrame);
double distance = hPrev.getDistance(h);
preShotList.offer(new Pair<>(videoFrame, distance));
if (preShotList.size() > PRESHOT_QUEUE_LENGTH) {
double max = 0;
int index = -1, i = 0;
for (Pair<VideoFrame, Double> pair : preShotList) {
if (pair.second > max) {
index = i;
max = pair.second;
}
i++;
}
if (max <= this.threshold && _return.getNumberOfFrames() < this.maxShotLength) {
// no cut
for (Pair<VideoFrame, Double> pair : preShotList) {
_return.addVideoFrame(pair.first);
}
preShotList.clear();
} else {
for (i = 0; i < index; ++i) {
_return.addVideoFrame(preShotList.removeFirst().first);
}
break;
}
}
}
if (_return != null) {
this.segments.put(_return);
}
}
}
} catch (InterruptedException e) {
LOGGER.log(Level.ERROR, "The thread that runs the VideoHistogramSegmenter was interrupted: {}", e);
}
/* End: Reset running to false. */
synchronized (this) {
this.isrunning = false;
}
}
use of org.vitrivr.cineast.core.data.entities.MediaSegmentDescriptor in project cineast by vitrivr.
the class SequentialTemporalScoringAlgorithm method score.
/**
* Score the information given to the class upon the creation of the class according to the sequential scoring algorithm.
*
* @return List of {@link TemporalObject}
*/
@Override
public List<TemporalObject> score() {
/* Calculate the best path for every segment in the result set given to the class. */
for (Map<Integer, ScoredSegment> segments : scoredSegmentStorage.values()) {
for (ScoredSegment scoredSegment : segments.values()) {
MediaSegmentDescriptor mediaSegmentDescriptor = segmentMap.get(scoredSegment.getSegmentId());
SequentialPath sequentialPath = this.getBestPathForSegment(mediaSegmentDescriptor, scoredSegment);
objectPaths.putIfAbsent(mediaSegmentDescriptor.getObjectId(), new ArrayList<>());
this.objectPaths.get(mediaSegmentDescriptor.getObjectId()).add(sequentialPath);
}
}
List<TemporalObject> results = new ArrayList<>();
/*
Calculate the max value of a segment of every objectId and remove duplicates from the result list and sort by segmentId. We are maxpooling scores and declare all segments of an object as a path and we ignore all previous information from the individual paths of all segments.
*/
this.objectPaths.forEach((objectId, paths) -> {
double max = paths.stream().mapToDouble(n -> (n.getScore() / (this.maxContainerId + 1))).max().orElse(0D);
List<String> segmentIds = paths.stream().flatMap(listContainer -> listContainer.getSegmentIds().stream()).distinct().collect(Collectors.toList());
List<Integer> sequenceNumbers = this.getSequenceNumbers(segmentIds);
List<String> sortedSegments = new ArrayList<>(IntStream.range(0, segmentIds.size()).boxed().collect(Collectors.toMap(sequenceNumbers::get, segmentIds::get, (s, a) -> s + ", " + a, TreeMap::new)).values());
TemporalObject temporalObject = new TemporalObject(sortedSegments, objectId, max);
if (max > 0d) {
results.add(temporalObject);
}
});
/* Return the sorted temporal objects. */
return results.stream().sorted(Comparator.comparingDouble(TemporalObject::getScore).reversed()).collect(Collectors.toList());
}
use of org.vitrivr.cineast.core.data.entities.MediaSegmentDescriptor in project cineast by vitrivr.
the class TimeDistanceTemporalScoringAlgorithm method getBestTemporalObject.
private TemporalObject getBestTemporalObject(ScoredSegment item, boolean lsc) throws NoSuchElementException {
List<String> segments = new ArrayList<>();
segments.add(item.getSegmentId());
MediaSegmentDescriptor currentDescriptor = segmentMap.get(item.getSegmentId());
/* The following shouldn't happen, if it does nonetheless please let the developers know */
if (currentDescriptor == null) {
throw new NoSuchElementException("Item with segmentId " + item.getSegmentId() + " was not provided for scoring");
}
double score = item.getScore();
float end = lsc ? currentDescriptor.getEnd() : currentDescriptor.getEndabs();
ScoredSegment currentSegment = new ScoredSegment(item);
/* Go through all container ids and calculate the element that maximizes the score of the element */
for (int innerContainerId = item.getContainerId() + 1; innerContainerId <= this.maxContainerId; innerContainerId++) {
final int lambdaInnerId = innerContainerId;
/* Get the set of values with a higher container id or a higher segment id. */
SortedSet<ScoredSegment> setFromElement = this.scoredSegmentSets.get(currentSegment.getObjectId()).tailSet(item);
List<ScoredSegment> candidates = setFromElement.stream().filter(c -> c.getContainerId() == lambdaInnerId).filter(c -> lsc ? c.getEnd() - item.getStart() >= 0 : c.getEndAbs() - item.getStartAbs() >= 0).filter(c -> lsc ? c.getEnd() - item.getStart() <= this.maxLength : c.getEndAbs() - item.getStartAbs() <= this.maxLength).filter(c -> !c.getSegmentId().equals(item.getSegmentId())).collect(Collectors.toList());
if (candidates.size() == 0) {
continue;
}
ScoredSegment bestSegment = null;
double bestScore = 0D;
/* Go through all candidates from the currentSegment */
for (ScoredSegment candidate : candidates) {
MediaSegmentDescriptor innerDescriptor = this.segmentMap.get(candidate.getSegmentId());
if (innerDescriptor == null) {
continue;
}
/* Calculate the inverse decay score of the candidate */
double innerScore = calculateInverseDecayScore(end, candidate, this.timeDistances.get(innerContainerId - 1), innerDescriptor, lsc);
if (innerScore > bestScore) {
bestScore = innerScore;
bestSegment = candidate;
}
}
/* If there is a best segment, store it and update current End abs, otherwise update end abs with time distances */
if (bestSegment != null) {
currentSegment = bestSegment;
end = lsc ? this.segmentMap.get(bestSegment.getSegmentId()).getEnd() : this.segmentMap.get(bestSegment.getSegmentId()).getEndabs();
segments.add(bestSegment.getSegmentId());
} else {
end += timeDistances.get(innerContainerId - 1);
}
score += bestScore;
}
return new TemporalObject(segments, item.getObjectId(), score / (this.maxContainerId + 1));
}
Aggregations