diff --git a/dbm-service/src/main/java/com/devbeh/DbmProperties.java b/dbm-service/src/main/java/com/devbeh/DbmProperties.java index d0c897e2dcc82f58f89a7da2931b615ed09ef263..7fbc39b3269af9c62378fce9aaf1569d137c51ec 100644 --- a/dbm-service/src/main/java/com/devbeh/DbmProperties.java +++ b/dbm-service/src/main/java/com/devbeh/DbmProperties.java @@ -115,6 +115,12 @@ public class DbmProperties */ private String perceptionResultDirPath; + /** + * Путь к директории, в которую будут запиÑаны файлы атомарных знаний или ÑÑ‚Ð°Ñ Ñтрока (null), еÑли Ñбор таких + * файлов не требуетÑÑ. + */ + private String atomicKnowledgeDirPath; + /** * Идентификатор начального кадра, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ необходимо формировать результирующее видео. */ @@ -455,6 +461,18 @@ public class DbmProperties } + public String getAtomicKnowledgeDirPath() + { + return atomicKnowledgeDirPath; + } + + + public void setAtomicKnowledgeDirPath(String atomicKnowledgeDirPath) + { + this.atomicKnowledgeDirPath = atomicKnowledgeDirPath; + } + + public long getPerceptionInitialConsumedFrameId() { return perceptionInitialConsumedFrameId; @@ -649,6 +667,13 @@ public class DbmProperties public static class FileVideoProviderProperties { + /** + * Ðеотрицательный идентификатор видео или -1, еÑли идентификатор должен быть выбран в ÑоответÑтвии Ñ + * порÑдковым номером. ЕÑли Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один видеопоток имеет идентификатор, отличный от -1 (заданный вручную), + * Ð´Ð»Ñ Ð²Ñех видеопотоков идентификатор также должен быть задан вручную. + */ + private int videoId = -1; + /** * Ð˜Ð¼Ñ Ð¿Ð¾Ñ‚Ð¾ÐºÐ° видеозапиÑи. */ @@ -681,11 +706,28 @@ public class DbmProperties private float cameraHeightMm; /** - * Путь к файлу (в формате .pl), Ñодержащему Ñпецифичные Ð´Ð»Ñ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð¾Ð³Ð¾ видеопотока Ð·Ð½Ð°Ð½Ð¸Ñ (например, Ñ Ð¾Ð¿Ð¸Ñанием - * Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÑтатичеÑких объектов) или null. + * Путь к файлу (в формате .pl), Ñодержащему Ñпецифичные Ð´Ð»Ñ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð¾Ð³Ð¾ видеопотока Ð·Ð½Ð°Ð½Ð¸Ñ (например, Ñ + * опиÑанием Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÑтатичеÑких объектов) или null. */ private String cameraKbRulesFilePath = null; + /** + * ЕÑли уÑтановлено true, топики Ñ ÑоÑтоÑнием БЗ и результатами Ð´ÐµÑ‚ÐµÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ удалены. + */ + private boolean clearKbState = false; + + + public int getVideoId() + { + return videoId; + } + + + public void setVideoId(int videoId) + { + this.videoId = videoId; + } + public String getName() { @@ -769,5 +811,17 @@ public class DbmProperties { this.cameraKbRulesFilePath = cameraKbRulesFilePath; } + + + public boolean isClearKbState() + { + return clearKbState; + } + + + public void setClearKbState(boolean clearKbState) + { + this.clearKbState = clearKbState; + } } } diff --git a/dbm-service/src/main/java/com/devbeh/DeviantBehaviourManagerStarter.java b/dbm-service/src/main/java/com/devbeh/DeviantBehaviourManagerStarter.java index f1b85e70e06039497390e00043d3d22efc690c31..9c72d5513defea431f7ab8e8213f3cf8823b7f75 100644 --- a/dbm-service/src/main/java/com/devbeh/DeviantBehaviourManagerStarter.java +++ b/dbm-service/src/main/java/com/devbeh/DeviantBehaviourManagerStarter.java @@ -37,6 +37,7 @@ import org.apache.kafka.common.Node; import org.apache.kafka.common.config.ConfigResource; import org.apache.kafka.common.errors.InvalidPartitionsException; import org.apache.kafka.common.errors.TopicExistsException; +import org.apache.kafka.common.errors.UnknownTopicOrPartitionException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; @@ -131,8 +132,22 @@ public class DeviantBehaviourManagerStarter implements InitializingBean, Disposa "General kb rules file '" + prop.getGeneralKbRulesFilePath() + "' can't be read"); Set<String> videoStreamNames = new HashSet<>(); + boolean manualPartition = false; + boolean automaticPartition = false; for (DbmProperties.FileVideoProviderProperties fvpProp : prop.getFileVideoProviders()) { + checkCondition(fvpProp.getVideoId() >= -1, "dbm.file-video-providers[].video-id " + + "must be specified"); + + if (fvpProp.getVideoId() == -1) + { + automaticPartition = true; + } + else if (fvpProp.getVideoId() >= 0) + { + manualPartition = true; + } + checkCondition(!Utils.isEmpty(fvpProp.getName()), "dbm.file-video-providers[].name must be specified"); checkCondition(videoStreamNames.add(fvpProp.getName()), "dbm.file-video-providers[].name must be unique, but got duplicate " + fvpProp.getName()); @@ -151,6 +166,17 @@ public class DeviantBehaviourManagerStarter implements InitializingBean, Disposa fvpProp.setMaxFps(fvpProp.getMaxFps() > 0 ? fvpProp.getMaxFps() : prop.getMaxFps()); } + + checkCondition(!(manualPartition && automaticPartition), "All video id's must be either specified " + + "manually or assigned automatically"); + + if (automaticPartition) + { + for (int i = 0; i < prop.getFileVideoProviders().size(); i++) + { + prop.getFileVideoProviders().get(i).setVideoId(i); + } + } } @@ -169,9 +195,10 @@ public class DeviantBehaviourManagerStarter implements InitializingBean, Disposa DbmProperties prop = dbmProperties(); validateAndFixProperties(prop); - // Создаем необходимые партиции + // Создаем необходимые партиции и очищаем данные KB, при необходимоÑти - int partitionsCount = prop.getFileVideoProviders().size(); + int partitionsCount = prop.getFileVideoProviders().stream() + .mapToInt(DbmProperties.FileVideoProviderProperties::getVideoId).max().orElse(-1) + 1; if (partitionsCount == 0) { return; @@ -243,6 +270,32 @@ public class DeviantBehaviourManagerStarter implements InitializingBean, Disposa } } } + + // При необходимоÑти, удалÑем данные KB + Set<String> topicsToDelete = new HashSet<>(); + for (DbmProperties.FileVideoProviderProperties fvpProp : prop.getFileVideoProviders()) + { + if (fvpProp.isClearKbState()) + { + topicsToDelete.add(prop.getKbStateTopicPrefix() + fvpProp.getVideoId()); + topicsToDelete.add(prop.getDevBehDetectionsTopicPrefix() + fvpProp.getVideoId()); + } + } + + if (!topicsToDelete.isEmpty()) + { + try + { + ac.deleteTopics(topicsToDelete).all().get(); + } + catch (ExecutionException e) + { + if (!(e.getCause() instanceof UnknownTopicOrPartitionException)) + { + throw e; + } + } + } } // Инициализируем конвейеры обработки видеозапиÑей @@ -250,23 +303,20 @@ public class DeviantBehaviourManagerStarter implements InitializingBean, Disposa List<Actor> managers = new ArrayList<>(); MetricService metricService = new MetricService(metricRegistry); - int videoId = -1; for (DbmProperties.FileVideoProviderProperties fvpProp : prop.getFileVideoProviders()) { - videoId++; - // ТеоретичеÑки, еÑли два потока одновременно запуÑÑ‚ÑÑ‚ оÑтановку pipeline, они могут заджойнитьÑÑ Ð´Ñ€ÑƒÐ³ на // друге, но Ñчитаем, что Ñто маловероÑтно, и еÑли такое возникнет, Ñработает ограничение макÑимального // времени Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ PipelineStopper pipelineStopper = new PipelineStopper(); - CompletableFuture<Double> fpsFuture = new CompletableFuture<>(); + CompletableFuture<VideoInfo> fpsFuture = new CompletableFuture<>(); // Создаем компонент визуализации результатов Ð´ÐµÑ‚ÐµÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ FileVideoProvider dvmVideoProvider = new FileVideoProvider(fvpProp.getFilePath(), fvpProp.getMaxFps()); DetectionsVisualizationManager detectionsVisualizationManager = new DetectionsVisualizationManager( - fvpProp.getName(), videoId, prop.getBootstrapServer(), prop.getUsername(), prop.getPassword(), - prop.getDevBehDetectionsTopicPrefix(), prop.getDevBehDetectionsDirPath(), + fvpProp.getName(), fvpProp.getVideoId(), prop.getBootstrapServer(), prop.getUsername(), + prop.getPassword(), prop.getDevBehDetectionsTopicPrefix(), prop.getDevBehDetectionsDirPath(), prop.getDevBehDetectionsStartFrameId(), dvmVideoProvider, prop.getMaxFrameSizePixels(), pipelineStopper::stop, metricService); @@ -277,44 +327,48 @@ public class DeviantBehaviourManagerStarter implements InitializingBean, Disposa pipelineStopper::stop, metricService); // Создание менеджера базы знаний - KBManager kbManager = new KBManager(fvpProp.getName(), videoId, prop.getBootstrapServer(), + KBManager kbManager = new KBManager(fvpProp.getName(), fvpProp.getVideoId(), prop.getBootstrapServer(), prop.getUsername(), prop.getPassword(), prop.getKbStateTopicPrefix(), prop.getDevBehDetectionsTopicPrefix(), prop.getKbHistoryIntervalSec(), prop.getInferencePeriodSec(), prop.getDevBehIgnorePeriodSec(), fpsFuture, prop.getMaxQueuedFrames(), prop.getKbWorkerJarPath(), prop.getKbWorkerMemory(), prop.getLibjplJavaLibraryPath(), prop.getGeneralKbRulesFilePath(), - fvpProp.getCameraKbRulesFilePath(), prop.getMaxActionDurationSec(), - prop.getMaxChildSkeletonLengthMm(), pipelineStopper::stop, metricService); + fvpProp.getCameraKbRulesFilePath(), prop.getAtomicKnowledgeDirPath(), + prop.getMaxActionDurationSec(), prop.getMaxChildSkeletonLengthMm(), pipelineStopper::stop, + metricService); // Создание менеджера Ð´ÐµÑ‚ÐµÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´ÐµÐ¹Ñтвий - ActionsManager actionsManager = new ActionsManager(fvpProp.getName(), videoId, prop.getBootstrapServer(), - prop.getUsername(), prop.getPassword(), prop.getActionsRequestTopicName(), - prop.getActionsResponseTopicPrefix(), prop.getMaxQueuedFrames(), prop.getMaxProcessingFrames(), - kbManager, perceptionVisualizationManager, pipelineStopper::stop, metricService); + ActionsManager actionsManager = new ActionsManager(fvpProp.getName(), fvpProp.getVideoId(), + prop.getBootstrapServer(), prop.getUsername(), prop.getPassword(), + prop.getActionsRequestTopicName(), prop.getActionsResponseTopicPrefix(), prop.getMaxQueuedFrames(), + prop.getMaxProcessingFrames(), kbManager, perceptionVisualizationManager, pipelineStopper::stop, + metricService); // Создание менеджера оценки раÑÑтоÑÐ½Ð¸Ñ Ð´Ð¾ объектов DistanceEstimationManager distanceEstimationManager = new DistanceEstimationManager(fvpProp.getName(), - videoId, fvpProp.getCameraHeightMm(), fvpProp.getFocalLengthMm(), fvpProp.getPixelSizeMm(), - prop.getBootstrapServer(), prop.getUsername(), prop.getPassword(), + fvpProp.getVideoId(), fvpProp.getCameraHeightMm(), fvpProp.getFocalLengthMm(), + fvpProp.getPixelSizeMm(), prop.getBootstrapServer(), prop.getUsername(), prop.getPassword(), prop.getDistanceRequestTopicName(), prop.getDistanceResponseTopicPrefix(), prop.getBoxContactPointLiftPercent(), prop.getMaxQueuedFrames(), prop.getMaxProcessingFrames(), actionsManager, kbManager, perceptionVisualizationManager, pipelineStopper::stop, metricService); // Создание менеджера оценки трехмерного Ñкелета людей - PoseEstimationManager poseEstimationManager = new PoseEstimationManager(fvpProp.getName(), videoId, - prop.getBootstrapServer(), prop.getUsername(), prop.getPassword(), prop.getPoseRequestTopicName(), - prop.getPoseResponseTopicPrefix(), prop.getMaxQueuedFrames(), prop.getMaxProcessingFrames(), - distanceEstimationManager, perceptionVisualizationManager, pipelineStopper::stop, metricService); + PoseEstimationManager poseEstimationManager = new PoseEstimationManager(fvpProp.getName(), + fvpProp.getVideoId(), prop.getBootstrapServer(), prop.getUsername(), prop.getPassword(), + prop.getPoseRequestTopicName(), prop.getPoseResponseTopicPrefix(), prop.getMaxQueuedFrames(), + prop.getMaxProcessingFrames(), distanceEstimationManager, perceptionVisualizationManager, + pipelineStopper::stop, metricService); // Создание менеджера отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð»ÑŽÐ´ÐµÐ¹ и объектов - TrackingManager trackingManager = new TrackingManager(fvpProp.getName(), videoId, prop.getBootstrapServer(), - prop.getUsername(), prop.getPassword(), prop.getTrackingRequestTopicName(), - prop.getTrackingResponseTopicPrefix(), prop.getTrackingManagerStateTopicPrefix(), - prop.getMaxOccludedDurationSec(), fpsFuture, prop.getMaxQueuedFrames(), - prop.getMaxProcessingFrames(), distanceEstimationManager, poseEstimationManager, actionsManager, - kbManager, perceptionVisualizationManager, pipelineStopper::stop, metricService); + TrackingManager trackingManager = new TrackingManager(fvpProp.getName(), fvpProp.getVideoId(), + prop.getBootstrapServer(), prop.getUsername(), prop.getPassword(), + prop.getTrackingRequestTopicName(), prop.getTrackingResponseTopicPrefix(), + prop.getTrackingManagerStateTopicPrefix(), prop.getMaxOccludedDurationSec(), fpsFuture, + prop.getMaxQueuedFrames(), prop.getMaxProcessingFrames(), distanceEstimationManager, + poseEstimationManager, actionsManager, kbManager, perceptionVisualizationManager, + pipelineStopper::stop, metricService); // Создание менеджера Ð´ÐµÑ‚ÐµÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð»ÑŽÐ´ÐµÐ¹ и объектов - DetectionManager detectionManager = new DetectionManager(fvpProp.getName(), videoId, + DetectionManager detectionManager = new DetectionManager(fvpProp.getName(), fvpProp.getVideoId(), prop.getBootstrapServer(), prop.getUsername(), prop.getPassword(), prop.getDetectionRequestTopicName(), prop.getDetectionResponseTopicPrefix(), prop.getMaxQueuedFrames(), prop.getMaxProcessingFrames(), trackingManager, poseEstimationManager, diff --git a/dbm-service/src/main/java/com/devbeh/VideoInfo.java b/dbm-service/src/main/java/com/devbeh/VideoInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..7beb867cb36e0ea5e717d43634f798286afaa80b --- /dev/null +++ b/dbm-service/src/main/java/com/devbeh/VideoInfo.java @@ -0,0 +1,20 @@ +package com.devbeh; + + +/** + * ИнициализируетÑÑ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ€Ð¾Ð¼ видеопотока. + */ +public class VideoInfo +{ + public final int frameHeight; + public final int frameWidth; + public final double fps; + + + public VideoInfo(int frameHeight, int frameWidth, double fps) + { + this.frameHeight = frameHeight; + this.frameWidth = frameWidth; + this.fps = fps; + } +} diff --git a/dbm-service/src/main/java/com/devbeh/managers/DetectionsVisualizationManager.java b/dbm-service/src/main/java/com/devbeh/managers/DetectionsVisualizationManager.java index e41da4e2ff622a447e6ac930845787c6a53c66d3..2491ea09e1eb815266a10ff5b4b5264c35189db8 100644 --- a/dbm-service/src/main/java/com/devbeh/managers/DetectionsVisualizationManager.java +++ b/dbm-service/src/main/java/com/devbeh/managers/DetectionsVisualizationManager.java @@ -286,8 +286,8 @@ public class DetectionsVisualizationManager extends Actor } } - double fps = videoProvider.initFps(); - videoProvider.initFrameParameters(entry.getStartFrameId(), maxFrameSizePixels); + videoProvider.initVideoInfo(maxFrameSizePixels); + videoProvider.initInitialFrameId(entry.getStartFrameId()); try { FFmpegFrameRecorder frameRecorder = new FFmpegFrameRecorder(resultVideoFile, @@ -295,7 +295,7 @@ public class DetectionsVisualizationManager extends Actor try (frameRecorder) { frameRecorder.setFormat("mp4"); - frameRecorder.setFrameRate(fps); + frameRecorder.setFrameRate(videoProvider.getFps()); frameRecorder.setVideoQuality(0); frameRecorder.start(); diff --git a/dbm-service/src/main/java/com/devbeh/managers/KBManager.java b/dbm-service/src/main/java/com/devbeh/managers/KBManager.java index 54ad668114bb4e165a9c536d9c11284992996cae..5798ac0c4816f33822233630777329fb653a0bd1 100644 --- a/dbm-service/src/main/java/com/devbeh/managers/KBManager.java +++ b/dbm-service/src/main/java/com/devbeh/managers/KBManager.java @@ -3,6 +3,7 @@ package com.devbeh.managers; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -29,6 +30,7 @@ import com.devbeh.Actor; import com.devbeh.DetectionClass; import com.devbeh.MetricService; import com.devbeh.Utils; +import com.devbeh.VideoInfo; import com.devbeh.commondata.DevBehDetections; import com.devbeh.commondata.Empty; import com.devbeh.commondata.KBEntry; @@ -131,7 +133,7 @@ public class KBManager extends Actor implements TrackingConsumer, DistanceDataCo /** * ПредоÑтавлÑет fps обрабатываемого видеопотока. ИÑпользуетÑÑ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð¸Ñ€ÑƒÑŽÑ‰ÐµÐ³Ð¾ видео. */ - private final Future<Double> fpsFuture; + private final Future<VideoInfo> fpsFuture; /** * Путь к jar компонента-обертки над базой знаний. @@ -158,6 +160,11 @@ public class KBManager extends Actor implements TrackingConsumer, DistanceDataCo */ private final String cameraKbRulesFilePath; + /** + * Путь к файлу, в который необходимо запиÑать детектированные атомарные знаниÑ, или пуÑÑ‚Ð°Ñ Ñтрока. + */ + private final String atomicKnowledgeFilePath; + /** * МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾ÑÑ‚ÑŒ дейÑÑ‚Ð²Ð¸Ñ Ð² Ñекундах, по доÑтижению которой будет отправлено Ñообщение о завершении * дейÑтвиÑ. @@ -288,10 +295,10 @@ public class KBManager extends Actor implements TrackingConsumer, DistanceDataCo public KBManager(String videoName, int videoId, String bootstrapServer, String username, String password, String kbStateTopicPrefix, String devBehDetectionsTopicPrefix, int kbHistorySec, int inferencePeriodSec, - int devBehIgnorePeriodSec, Future<Double> fpsFuture, int maxQueuedRequests, String kbWorkerJarPath, + int devBehIgnorePeriodSec, Future<VideoInfo> fpsFuture, int maxQueuedRequests, String kbWorkerJarPath, String kbWorkerMemory, String libjplJavaLibraryPath, String generalKbRulesFilePath, - String cameraKbRulesFilePath, int maxActionDurationSec, int maxChildSkeletonLengthMm, - Runnable pipelineStopper, MetricService metricService) + String cameraKbRulesFilePath, String atomicKnowledgeDirPath, int maxActionDurationSec, + int maxChildSkeletonLengthMm, Runnable pipelineStopper, MetricService metricService) { this.managerName = "KBManager-" + videoName; this.bootstrapServer = bootstrapServer; @@ -309,6 +316,8 @@ public class KBManager extends Actor implements TrackingConsumer, DistanceDataCo this.libjplJavaLibraryPath = libjplJavaLibraryPath; this.generalKbRulesFilePath = generalKbRulesFilePath; this.cameraKbRulesFilePath = Utils.isEmpty(cameraKbRulesFilePath) ? "" : cameraKbRulesFilePath; + this.atomicKnowledgeFilePath = atomicKnowledgeDirPath == null || atomicKnowledgeDirPath.trim().isEmpty() ? "" : + new File(atomicKnowledgeDirPath, videoName + ".pl").getAbsolutePath(); this.maxActionDurationSec = maxActionDurationSec; this.maxChildSkeletonLengthMm = maxChildSkeletonLengthMm; this.pipelineStopper = pipelineStopper; @@ -375,10 +384,10 @@ public class KBManager extends Actor implements TrackingConsumer, DistanceDataCo @Override protected void doFirst() { - double fps; + VideoInfo videoInfo; try { - fps = fpsFuture.get(); + videoInfo = fpsFuture.get(); } catch (Exception e) { @@ -390,12 +399,12 @@ public class KBManager extends Actor implements TrackingConsumer, DistanceDataCo return; } - kbHistoryFrames = (int) (fps * kbHistorySec); - inferencePeriodFrames = (int) (fps * inferencePeriodSec); - devBehIgnorePeriodFrames = (int) (fps * devBehIgnorePeriodSec); - maxActionDurationFrames = (int) (fps * maxActionDurationSec); + kbHistoryFrames = (int) (videoInfo.fps * kbHistorySec); + inferencePeriodFrames = (int) (videoInfo.fps * inferencePeriodSec); + devBehIgnorePeriodFrames = (int) (videoInfo.fps * devBehIgnorePeriodSec); + maxActionDurationFrames = (int) (videoInfo.fps * maxActionDurationSec); - initKb(fps); + initKb(videoInfo.frameHeight, videoInfo.frameWidth, videoInfo.fps); loadKbHistory(); if (getDoStop()) @@ -924,13 +933,14 @@ public class KBManager extends Actor implements TrackingConsumer, DistanceDataCo /** * ЗапиÑывает в базу знаний ÑтатичеÑкие правила, в чаÑтноÑти, опиÑÐ°Ð½Ð¸Ñ Ð¸Ð½Ñ‚ÐµÑ€ÐµÑующих Ñцен девиантного поведениÑ. */ - private void initKb(double fps) + private void initKb(int frameHeight, int frameWidth, double fps) { // -Djava.library.path=/usr/lib/swi-prolog/lib/x86_64-linux ProcessBuilder builder = new ProcessBuilder("java", "-Xmx" + kbWorkerMemory, "-Xms" + kbWorkerMemory, "-Djava.library.path=" + libjplJavaLibraryPath, "-jar", kbWorkerJarPath, generalKbRulesFilePath, cameraKbRulesFilePath, Integer.toString(kbHistoryFrames), Integer.toString(devBehIgnorePeriodFrames), - Double.toString(fps)); + Integer.toString(frameHeight), Integer.toString(frameWidth), Double.toString(fps), + atomicKnowledgeFilePath); try { kbWorkerProcess = builder.start(); @@ -1014,6 +1024,12 @@ public class KBManager extends Actor implements TrackingConsumer, DistanceDataCo */ private void handleKbWorkerError(String errorMsg, Exception e) throws RuntimeException { + long startTimeMs = System.currentTimeMillis(); + while (kbWorkerProcess.isAlive() && System.currentTimeMillis() < startTimeMs + 5000) + { + sleep(100); + } + String workerError = null; if (!kbWorkerProcess.isAlive()) { diff --git a/dbm-service/src/main/java/com/devbeh/managers/PerceptionVisualizationManager.java b/dbm-service/src/main/java/com/devbeh/managers/PerceptionVisualizationManager.java index 48999af93faac0cac3e43e23fc063de087b8bf87..ee878b197080876525bcda9f0172db678f8c71b3 100644 --- a/dbm-service/src/main/java/com/devbeh/managers/PerceptionVisualizationManager.java +++ b/dbm-service/src/main/java/com/devbeh/managers/PerceptionVisualizationManager.java @@ -13,6 +13,7 @@ import com.devbeh.Actor; import com.devbeh.DetectionClass; import com.devbeh.FrameIdAndBytes; import com.devbeh.MetricService; +import com.devbeh.VideoInfo; import com.devbeh.data.Action; import com.devbeh.data.DetectionEntryOrBuilder; import com.devbeh.data.DistanceEstimationEntry; @@ -91,7 +92,7 @@ public class PerceptionVisualizationManager extends Actor implements FrameConsum /** * ПредоÑтавлÑет fps обрабатываемого видеопотока. ИÑпользуетÑÑ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð¸Ñ€ÑƒÑŽÑ‰ÐµÐ³Ð¾ видео. */ - private final Future<Double> fpsFuture; + private final Future<VideoInfo> fpsFuture; /** * ИÑпользуетÑÑ Ð´Ð»Ñ Ð¾Ñтановки конвейера обработки видео в Ñлучае критичной ошибки. @@ -165,7 +166,7 @@ public class PerceptionVisualizationManager extends Actor implements FrameConsum public PerceptionVisualizationManager(String videoName, String resultVideoDirPath, long initialConsumedFrameId, - boolean enabled, int maxQueuedRequests, Future<Double> fpsFuture, Runnable pipelineStopper, + boolean enabled, int maxQueuedRequests, Future<VideoInfo> fpsFuture, Runnable pipelineStopper, MetricService metricService) { this.managerName = "PerceptionVisualizationManager-" + videoName; @@ -317,7 +318,7 @@ public class PerceptionVisualizationManager extends Actor implements FrameConsum frameRecorder = new FFmpegFrameRecorder(resultVideoFile, currentFrameInfo.frameMat.arrayWidth(), currentFrameInfo.frameMat.arrayHeight()); frameRecorder.setFormat("mp4"); - frameRecorder.setFrameRate(fpsFuture.get()); + frameRecorder.setFrameRate(fpsFuture.get().fps); frameRecorder.setVideoQuality(0); frameRecorder.start(); } diff --git a/dbm-service/src/main/java/com/devbeh/managers/TrackingManager.java b/dbm-service/src/main/java/com/devbeh/managers/TrackingManager.java index d21f5f48817337d3dd27d5f035965b6a979ac706..23d68e185402f5e11528ec2bf661cdb2dc21b830 100644 --- a/dbm-service/src/main/java/com/devbeh/managers/TrackingManager.java +++ b/dbm-service/src/main/java/com/devbeh/managers/TrackingManager.java @@ -22,6 +22,7 @@ import com.devbeh.Actor; import com.devbeh.FrameIdAndBytes; import com.devbeh.MetricService; import com.devbeh.ReducibleSemaphore; +import com.devbeh.VideoInfo; import com.devbeh.data.DetectionEntry; import com.devbeh.data.PerceptionRequest; import com.devbeh.data.PerceptionResponse; @@ -134,7 +135,7 @@ public class TrackingManager extends AbstractDistributor implements FrameConsume * Может вызыватьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ поÑле инициализации начального запрашиваемого кадра, поÑтому можно иÑпользовать в любом * меÑте {@link #postDoFirst(long)}. */ - private final Future<Double> fpsFuture; + private final Future<VideoInfo> fpsFuture; /** * МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾ÑÑ‚ÑŒ Ð¿ÐµÑ€ÐµÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð° в кадрах. ЗадаетÑÑ Ð²Ð¾ Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ на оÑнове fps. @@ -154,7 +155,7 @@ public class TrackingManager extends AbstractDistributor implements FrameConsume public TrackingManager(String videoName, int videoId, String bootstrapServer, String username, String password, String requestTopicName, String responseTopicPrefix, String tmStateTopicPrefix, int maxOccludedDurationSec, - Future<Double> fpsFuture, int maxQueuedRequests, int maxProcessingRequests, DistanceEstimationManager dem, + Future<VideoInfo> fpsFuture, int maxQueuedRequests, int maxProcessingRequests, DistanceEstimationManager dem, PoseEstimationManager pem, ActionsManager am, KBManager kbm, PerceptionVisualizationManager pvm, Runnable pipelineStopper, MetricService metricService) { @@ -168,7 +169,7 @@ public class TrackingManager extends AbstractDistributor implements FrameConsume private TrackingManager(String videoName, int videoId, String bootstrapServer, String username, String password, String clientId, TopicPartition requestTopicPartition, TopicPartition responseTopicPartition, - String tmStateTopicPrefix, int maxOccludedDurationSec, Future<Double> fpsFuture, + String tmStateTopicPrefix, int maxOccludedDurationSec, Future<VideoInfo> fpsFuture, CompletableFuture<Long> initialFrameIdFuture, int maxQueuedRequests, int maxProcessingRequests, ReducibleSemaphore processingRequestsSem, DistanceEstimationManager dem, PoseEstimationManager pem, ActionsManager am, KBManager kbm, PerceptionVisualizationManager pvm, Runnable pipelineStopper, @@ -243,7 +244,7 @@ public class TrackingManager extends AbstractDistributor implements FrameConsume double fps; try { - fps = fpsFuture.get(); + fps = fpsFuture.get().fps; } catch (ExecutionException e) { @@ -412,6 +413,7 @@ public class TrackingManager extends AbstractDistributor implements FrameConsume lastFrameIdToGlobalTrackIds.remove(ti.lastFrameId); } ti.lastFrameId = frameId; + ti.detectionId = detectionId; } lastFrameIdToGlobalTrackIds.computeIfAbsent(frameId, f -> new HashSet<>()).add(globalTrackId); @@ -425,7 +427,7 @@ public class TrackingManager extends AbstractDistributor implements FrameConsume while (lastFrameIdIterator.hasNext()) { Map.Entry<Long, Set<Long>> e = lastFrameIdIterator.next(); - if (e.getKey() >= frameId - maxOccludedDurationFrames) + if (frameId - e.getKey() <= maxOccludedDurationFrames) { break; } @@ -454,17 +456,28 @@ public class TrackingManager extends AbstractDistributor implements FrameConsume Set<Long> gIds = lastFrameIdToGlobalTrackIds.get(frameId); if (gIds != null) { - for (long globalTrackId : gIds) + Iterator<Long> globalTrackIdIter = gIds.iterator(); + while (globalTrackIdIter.hasNext()) { + long globalTrackId = globalTrackIdIter.next(); TrackInfo ti = globalTrackIdToTrackInfo.get(globalTrackId); Long newTrackId = detectionIdToTrackId.get(ti.detectionId); - if (newTrackId == null || ti.trackId == newTrackId) + if (newTrackId == null) + { + // УдалÑем трек, которому не нашлоÑÑŒ Ñквивалента в новом наборе + globalTrackIdIter.remove(); + globalTrackIdToTrackInfo.remove(globalTrackId); + trackIdToGlobalTrackId.remove(ti.trackId); + continue; + } + else if (ti.trackId == newTrackId) { // ТеоретичеÑки, newTrackId может отÑутÑтвовать, еÑли трекер вернет новый набор detection // при запуÑке его Ñ Ð½Ð¾Ð²Ð¾Ð¹ конфигурацией. ПоÑтому минимизируем возможную ошибку continue; } trackIdToGlobalTrackId.remove(ti.trackId); + // Может быть вытеÑнен трек, который отноÑитÑÑ Ðº "будущему". Такой Ñлемент будет обработан далее trackIdToGlobalTrackId.put(newTrackId, globalTrackId); ti.trackId = newTrackId; @@ -472,6 +485,11 @@ public class TrackingManager extends AbstractDistributor implements FrameConsume stateChange.addEntriesBuilder().setGlobalTrackId(globalTrackId).setTrackId(newTrackId) .setDetectionId(ti.detectionId); } + + if (gIds.isEmpty()) + { + lastFrameIdToGlobalTrackIds.remove(frameId); + } } } stateChange.setGlobalTrackIdCounter(globalTrackIdCounter); @@ -668,7 +686,7 @@ public class TrackingManager extends AbstractDistributor implements FrameConsume /** * Идентификатор объекта в рамках поÑледнего кадра. */ - private final long detectionId; + private long detectionId; public TrackInfo(long trackId, long lastFrameId, long detectionId) @@ -677,5 +695,16 @@ public class TrackingManager extends AbstractDistributor implements FrameConsume this.lastFrameId = lastFrameId; this.detectionId = detectionId; } + + + @Override + public String toString() + { + return "TrackInfo{" + + "trackId=" + trackId + + ", lastFrameId=" + lastFrameId + + ", detectionId=" + detectionId + + '}'; + } } } diff --git a/dbm-service/src/main/java/com/devbeh/managers/VideoProvisionManager.java b/dbm-service/src/main/java/com/devbeh/managers/VideoProvisionManager.java index 6998e3d1713a2d39a4886eab1529b126414757bc..66b043581c7602b83a699e18085d71103d842e70 100644 --- a/dbm-service/src/main/java/com/devbeh/managers/VideoProvisionManager.java +++ b/dbm-service/src/main/java/com/devbeh/managers/VideoProvisionManager.java @@ -8,6 +8,7 @@ import java.util.concurrent.atomic.AtomicLong; import com.devbeh.Actor; import com.devbeh.FrameIdAndBytes; import com.devbeh.MetricService; +import com.devbeh.VideoInfo; import com.devbeh.videoproviders.VideoProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,7 +45,7 @@ public class VideoProvisionManager extends Actor /** * Должна быть инициализирована fps обрабатываемого видеопотока. */ - private final CompletableFuture<Double> fpsFuture; + private final CompletableFuture<VideoInfo> fpsFuture; // Получатели кадров видеозапиÑи private final DetectionManager dm; @@ -75,7 +76,7 @@ public class VideoProvisionManager extends Actor public VideoProvisionManager(String videoName, VideoProvider videoProvider, int maxFrameSizePixels, - CompletableFuture<Double> fpsFuture, DetectionManager dm, TrackingManager tm, + CompletableFuture<VideoInfo> fpsFuture, DetectionManager dm, TrackingManager tm, PoseEstimationManager pem, DistanceEstimationManager dem, PerceptionVisualizationManager pvm, Runnable pipelineStopper, MetricService metricService) { @@ -110,7 +111,9 @@ public class VideoProvisionManager extends Actor { // Инициализируем videoProvider Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ fps даже еÑли потребителÑм не требуютÑÑ Ð´Ð°Ð½Ð½Ñ‹Ðµ, при Ñтом // провайдер может определить Long.MAX_VALUE - fpsFuture.complete(videoProvider.initFps()); + videoProvider.initVideoInfo(maxFrameSizePixels); + fpsFuture.complete(new VideoInfo(videoProvider.getHeight(), videoProvider.getWidth(), + videoProvider.getFps())); long lastConsumedByAllFrameId = Math.min( Math.min( @@ -120,7 +123,7 @@ public class VideoProvisionManager extends Actor long initialFrameId = lastConsumedByAllFrameId == Long.MAX_VALUE ? Long.MAX_VALUE : lastConsumedByAllFrameId + 1; - videoProvider.initFrameParameters(initialFrameId, maxFrameSizePixels); + videoProvider.initInitialFrameId(initialFrameId); if (initialFrameId == Long.MAX_VALUE) { diff --git a/dbm-service/src/main/java/com/devbeh/videoproviders/FileVideoProvider.java b/dbm-service/src/main/java/com/devbeh/videoproviders/FileVideoProvider.java index 458d6edf7cf6c29ebed54611c4ddf5c5ef1f0feb..3d3f7474b85f1d75464293d43acdc4168ed64515 100644 --- a/dbm-service/src/main/java/com/devbeh/videoproviders/FileVideoProvider.java +++ b/dbm-service/src/main/java/com/devbeh/videoproviders/FileVideoProvider.java @@ -95,7 +95,7 @@ public class FileVideoProvider implements VideoProvider @Override - public double initFps() throws FrameGrabber.Exception + public void initVideoInfo(int maxFrameSizePixels) throws FrameGrabber.Exception { converterToMat = new OpenCVFrameConverter.ToMat(); outputPointer = new BytePointer(); @@ -109,27 +109,27 @@ public class FileVideoProvider implements VideoProvider videoFrameIntervalMs = 1000.0 / fg.getFrameRate(); frameIntervalMs = Math.max(1000.0 / maxFps, videoFrameIntervalMs); - return 1000 / frameIntervalMs; - } - - - @Override - public void initFrameParameters(long initialFrameId, int maxFrameSizePixels) - { - this.initialFrameId = initialFrameId; double frameScaleFactor = Math.sqrt((double) maxFrameSizePixels / (fg.getImageHeight() * fg.getImageWidth())); if (frameScaleFactor >= 1) { width = fg.getImageWidth(); height = fg.getImageHeight(); - alteredSize = null; } else { width = (int) (fg.getImageWidth() * frameScaleFactor); height = (int) (fg.getImageHeight() * frameScaleFactor); - alteredSize = new Size(width, height); } + // Ð”Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ Mat в отдельной облаÑти памÑти определÑем данный объект даже при неизменноÑти размера + // кадра + alteredSize = new Size(width, height); + } + + + @Override + public void initInitialFrameId(long initialFrameId) + { + this.initialFrameId = initialFrameId; } @@ -147,6 +147,13 @@ public class FileVideoProvider implements VideoProvider } + @Override + public double getFps() + { + return 1000 / frameIntervalMs; + } + + @Override public Optional<FrameIdAndBytes> read(long timeoutMs) throws IOException { diff --git a/dbm-service/src/main/java/com/devbeh/videoproviders/VideoProvider.java b/dbm-service/src/main/java/com/devbeh/videoproviders/VideoProvider.java index f2c91b976f08978447a2c16a275926666d7da323..c1d094543c3dc7da096f5667dbf27e375c36e236 100644 --- a/dbm-service/src/main/java/com/devbeh/videoproviders/VideoProvider.java +++ b/dbm-service/src/main/java/com/devbeh/videoproviders/VideoProvider.java @@ -12,27 +12,26 @@ import com.devbeh.FrameIdAndBytes; public interface VideoProvider { /** - * ВыполнÑет первый Ñтап инициализации, в результате которого определÑетÑÑ fps. - * Далее должен быть выполнен второй Ñтап инициализации поÑредÑтвом вызова {@link #initFrameParameters(long, int)}. + * ВыполнÑет первый Ñтап инициализации, в результате которого определÑетÑÑ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ‹ видеопотока - размер кадра и + * fps. + * Далее должен быть выполнен второй Ñтап инициализации поÑредÑтвом вызова {@link #initInitialFrameId(long)}. * + * @param maxFrameSizePixels макÑимальный размер кадра видеозапиÑи, полученный как height * width, в Ñлучае + * Ð¿Ñ€ÐµÐ²Ñ‹ÑˆÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ оÑущеÑтвлÑÑ‚ÑŒÑÑ Ñ€ÐµÑайз * @throws Exception Ð’ Ñлучае критичной ошибки, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ñ€Ð¸Ð²Ð¾Ð´Ð¸Ñ‚ к невозможноÑти запуÑка обработки видео. Ошибки, * которые могут иметь временный характер, будут обработаны в реализации провайдера и не будут выброшены наружу. * Такие ошибки могут привеÑти только к временной недоÑтупноÑти кадров. - * - * @return количеÑтво кадров в Ñекунду */ - double initFps() throws Exception; + void initVideoInfo(int maxFrameSizePixels) throws Exception; /** - * ВыполнÑет второй Ñтап инициализации. Данный метод необходимо вызывать поÑле {@link #initFps()}. + * ВыполнÑет второй Ñтап инициализации. Данный метод необходимо вызывать поÑле {@link #initVideoInfo(int)}. * * @param initialFrameId идентификатор кадра, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ ожидаетÑÑ Ð²Ð¸Ð´ÐµÐ¾Ð·Ð°Ð¿Ð¸ÑÑŒ (включаÑ), * или {@link Long#MAX_VALUE}, еÑли от провайдера требуетÑÑ Ð»Ð¸ÑˆÑŒ определить fps (кадры при * Ñтом запрашиватьÑÑ Ð½Ðµ будут) - * @param maxFrameSizePixels макÑимальный размер кадра видеозапиÑи, полученный как height * width, в Ñлучае - * Ð¿Ñ€ÐµÐ²Ñ‹ÑˆÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ оÑущеÑтвлÑÑ‚ÑŒÑÑ Ñ€ÐµÑайз */ - void initFrameParameters(long initialFrameId, int maxFrameSizePixels); + void initInitialFrameId(long initialFrameId); /** * Возвращает выÑоту кадка. @@ -48,6 +47,13 @@ public interface VideoProvider */ int getHeight(); + /** + * Возвращает количеÑтво кадров в Ñекунду. + * + * @return количеÑтво кадров в Ñекунду + */ + double getFps(); + /** * Считывает кадр видеозапиÑи. * frameId ожидаетÑÑ Ð¿Ð¾Ñледовательным, но по каким-либо причинам допуÑкаетÑÑ Ñкачек. Кроме того, начальный frameId diff --git a/kb-worker/src/main/java/com/devbeh/KBWorkerStarter.java b/kb-worker/src/main/java/com/devbeh/KBWorkerStarter.java index 6228253a65ca22f10743e4917d3c474998730104..a22ab5edd6f1dbb204599397aff57569e5c97fa5 100644 --- a/kb-worker/src/main/java/com/devbeh/KBWorkerStarter.java +++ b/kb-worker/src/main/java/com/devbeh/KBWorkerStarter.java @@ -3,9 +3,14 @@ package com.devbeh; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -49,7 +54,7 @@ public class KBWorkerStarter private static final OutputStream KB_OUT = new BufferedOutputStream(System.out); // Шаблоны ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ‚ÐµÑ€Ð¼Ð¾Ð² - private static final Term OBJ_INFO_TERM = Term.textToTerm("timeBetween(?, ?, Time), bounds(?, box(TLx, TLy, BRx, BRy), Time)"); + private static final Term OBJ_INFO_TERM = Term.textToTerm("timeBetween(?, ?, Time), correctedBounds(?, box(TLx, TLy, BRx, BRy), Time)"); private static final Term BOUNDS_TERM = Term.textToTerm("bounds(?, box(?, ?, ?, ?), ?)"); private static final Term POSITION_TERM = Term.textToTerm("position(?, point(?, ?, ?), ?)"); private static final Term PERSON_TERM = Term.textToTerm("person(?, ?)"); @@ -94,6 +99,11 @@ public class KBWorkerStarter */ private static long LAST_FRAME_ID = 0; + /** + * ИÑпользуетÑÑ Ð´Ð»Ñ + */ + private static PrintWriter ATOMIC_KNOWLEDGE_OUT = null; + /** * Принимает: @@ -125,9 +135,9 @@ public class KBWorkerStarter * @param args параметры kb-процеÑÑа * @throws RuntimeException иÑключение в Ñлучае критичеÑкой ошибки */ - private static void run(String[] args) throws RuntimeException + private static void run(String[] args) throws Exception { - if (args.length < 5) + if (args.length < 8) { throw new RuntimeException("Invalid arguments: " + Arrays.toString(args)); } @@ -138,9 +148,26 @@ public class KBWorkerStarter KB_HISTORY_FRAMES = Integer.parseInt(args[2]); KNOWLEDGE_WINDOW = new ArrayBlockingQueue<>(KB_HISTORY_FRAMES + 1); DEV_BEH_IGNORE_PERIOD_FRAMES = Integer.parseInt(args[3]); - double fps = Double.parseDouble(args[4]); + int frameHeight = Integer.parseInt(args[4]); + int frameWidth = Integer.parseInt(args[5]); + double fps = Double.parseDouble(args[6]); FRAME_INTERVAL_MS = (int) Math.round(1000 / fps); + if (!args[7].isEmpty()) + { + File atomicKnowledgeFile = new File(args[7]); + if (!atomicKnowledgeFile.getParentFile().exists()) + { + if (!atomicKnowledgeFile.getParentFile().mkdirs()) + { + throw new RuntimeException("Can't create directories for atomic knowledge file: " + + atomicKnowledgeFile.getAbsolutePath()); + } + } + ATOMIC_KNOWLEDGE_OUT = new PrintWriter(new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(atomicKnowledgeFile)))); + } + runQuery(new Query("consult", new Term[] { new Atom(generalKbRulesFilePath) }), "KB general rules consulting error"); if (!cameraKbRulesFilePath.isEmpty()) @@ -148,8 +175,26 @@ public class KBWorkerStarter runQuery(new Query("consult", new Term[] { new Atom(cameraKbRulesFilePath) }), "KB camera specific rules consulting error"); } - runQuery(new Query(Term.textParamsToTerm("assert(timeStep(?))", - new Term[] {new org.jpl7.Integer(FRAME_INTERVAL_MS)})), "Time step insertion error"); + + addAtomicKnowledge(Term.textParamsToTerm("timeStep(?)", + new Term[] {new org.jpl7.Integer(FRAME_INTERVAL_MS)})); + + addAtomicKnowledge(Term.textParamsToTerm("frameHeight(?)", new Term[] {new org.jpl7.Integer(frameHeight)})); + addAtomicKnowledge(Term.textParamsToTerm("frameWidth(?)", new Term[] {new org.jpl7.Integer(frameWidth)})); + + // ЗапиÑываем Ð·Ð½Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ð¸ÑÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¸ отÑутÑÑ‚Ð²Ð¸Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹ + addAtomicKnowledge(Term.textToTerm("person(p, -1)")); + addAtomicKnowledge(Term.textToTerm("bounds(p, box(0, 0, 0, 0), -1)")); + addAtomicKnowledge(Term.textToTerm("position(p, point(0, 0, 0), -1)")); + addAtomicKnowledge(Term.textToTerm("vehicle(v, v, -1)")); + addAtomicKnowledge(Term.textToTerm("animal(a, a, -1)")); + addAtomicKnowledge(Term.textToTerm("bag(b, -1)")); + addAtomicKnowledge(Term.textToTerm("phone(ph, -1)")); + addAtomicKnowledge(Term.textToTerm("child(c, -1)")); + addAtomicKnowledge(Term.textToTerm("lookDirection(p, vector(0, 0, 0), -1)")); + addAtomicKnowledge(Term.textToTerm("volumetricPosition(v, [], -1)")); + + flushAtomicKnowledge(); // РодительÑкий процеÑÑ Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ‚ Ñообщение поÑле уÑпешной инициализации writeResponse(KBServiceResponse.newBuilder().setEmpty(Empty.newBuilder().setEmpty(true)).build()); @@ -171,6 +216,35 @@ public class KBWorkerStarter } + /** + * ЗапиÑывает атомарное знание в БЗ и файл. + * + * @param term терм, запиÑываемый в БЗ и файл + */ + private static void addAtomicKnowledge(Term term) + { + runQuery(new Query(new Compound("asserta", new Term[] {term})), + "Static knowledge insertion error (" + term.toString() + ")"); + if (ATOMIC_KNOWLEDGE_OUT != null) + { + ATOMIC_KNOWLEDGE_OUT.print(term); + ATOMIC_KNOWLEDGE_OUT.println("."); + } + } + + + /** + * ОтправлÑет буферизированные файлы в файл. + */ + private static void flushAtomicKnowledge() + { + if (ATOMIC_KNOWLEDGE_OUT != null) + { + ATOMIC_KNOWLEDGE_OUT.flush(); + } + } + + /** * ВыполнÑет переданный запроÑ, Ð²Ñ‹Ð·Ñ‹Ð²Ð°Ñ {@link Query#hasSolution()}. ЕÑли метод возвращает false, выбраÑывает * иÑключение. @@ -256,8 +330,10 @@ public class KBWorkerStarter // ЗапиÑываем Ð·Ð½Ð°Ð½Ð¸Ñ Ð² бз for (Term t : frameKnowledge) { - runQuery(new Query("asserta", new Term[] {t}), "KB knowledge asserta error"); + addAtomicKnowledge(t); } + flushAtomicKnowledge(); + LAST_FRAME_ID = knowledge.getFrameId(); KNOWLEDGE_WINDOW.add(new FrameKnowledge(knowledge.getFrameId(), frameKnowledge)); @@ -515,7 +591,8 @@ public class KBWorkerStarter .setEndFrameId(finishFrameId) .setInferenceInfo(""); // Пока оÑтавлÑем данное поле пуÑтым - Map<Long, List<DevBehFrameObject>> frameInfoMap = new HashMap<>(); + // ВнутреннÑÑ Map на Ñлучай Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€ÐµÐ½Ð¸Ñ Ð´ÐµÑ‚ÐµÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ объекта в кадре + Map<Long, Map<Long, DevBehFrameObject>> frameInfoMap = new HashMap<>(); for (Term obj : devBeh.args()) { for (Map<String, Term> devBehObjInfo : new Query(OBJ_INFO_TERM.putParams( @@ -527,7 +604,8 @@ public class KBWorkerStarter float bottomRightX = devBehObjInfo.get("BRx").floatValue(); float bottomRightY = devBehObjInfo.get("BRy").floatValue(); - frameInfoMap.computeIfAbsent(frameId, f -> new ArrayList<>()).add( + frameInfoMap.computeIfAbsent(frameId, f -> new HashMap<>()).put( + obj.longValue(), DevBehFrameObject.newBuilder() .setId(obj.longValue()) .setBox(KBBox.newBuilder() @@ -543,7 +621,7 @@ public class KBWorkerStarter frameInfoMap.entrySet().stream().sorted(Map.Entry.comparingByKey()) .forEach(frameInfo -> devBehEntryBuilder.addFrameInfoBuilder().setFrameId(frameInfo.getKey()) - .addAllObjects(frameInfo.getValue())); + .addAllObjects(frameInfo.getValue().values())); } // ОтправлÑем результат детектированиÑ