Ejemplo n.º 1
0
        public void DetectExitTest()
        {
            var detector = new EntryDetector(Background)
            {
                CurrentState = DetectorState.Entry
            };

            var images = Enumerable.Range(1, 4)
                         .Select(i => new Image <Rgb, byte>($@"Resources\train-{i}.jpg"))
                         .Select(image => image.Convert <Gray, byte>())
                         .Reverse() // just by reversing, the train exits :)
                         .ToArray();

            var emptyImages = Enumerable.Range(1, 1)
                              .Select(i => new Image <Rgb, byte>(@"Resources\train-0.jpg"))
                              .Select(image => image.Convert <Gray, byte>())
                              .ToArray();

            detector.Tick(images);

            // Tick a few times with empty images should trigger exit
            for (var i = 0; i <= EntryDetector.ExitThreshold; i++)
            {
                detector.Tick(emptyImages);
            }

            Assert.AreEqual(DetectorState.Exit, detector.CurrentState);
        }
Ejemplo n.º 2
0
        public void TestFull()
        {
            var timeProvider = new ExternalTimeProvider {
                CurrentTime = Year2000
            };
            var detector = new EntryDetector(Background, timeProvider);

            for (var k = 0; k < 2; k++)
            {
                var enterRaised = false;
                var exitRaised  = false;

                detector.Enter += (sender, args) => enterRaised = true;
                detector.Exit  += (sender, args) => exitRaised = true;
                detector.Abort += (sender, args) => Assert.Fail("Abort not expected");

                // entry
                timeProvider.CurrentTime = timeProvider.CurrentTime.AddSeconds(5);
                detector.Tick(EntryImages);
                Assert.AreEqual(DetectorState.Entry, detector.CurrentState);
                Assert.IsTrue(enterRaised);

                // exit
                timeProvider.CurrentTime = timeProvider.CurrentTime.AddSeconds(5);
                for (var i = 0; i <= EntryDetector.ExitThreshold; i++)
                {
                    detector.Tick(EmptyImages);
                }
                Assert.AreEqual(DetectorState.Exit, detector.CurrentState);
                Assert.IsTrue(exitRaised);
            }
        }
Ejemplo n.º 3
0
        public void TestFastExitEntryRefusal()
        {
            var timeProvider = new ExternalTimeProvider();
            var detector     = new EntryDetector(Background, timeProvider);
            var enterRaised  = false;
            var exitRaised   = false;

            detector.Enter += (sender, args) => enterRaised = true;
            detector.Exit  += (sender, args) => exitRaised = true;
            detector.Abort += (sender, args) => Assert.Fail("Abort not expected");

            timeProvider.CurrentTime = Year2000;
            detector.Tick(EntryImages);
            Assert.AreEqual(DetectorState.Entry, detector.CurrentState);
            Assert.IsTrue(enterRaised);
            Assert.IsFalse(exitRaised);

            timeProvider.CurrentTime = timeProvider.CurrentTime.AddSeconds(EntryDetector.MinTimeAfterEntry + 1);
            for (var i = 0; i <= EntryDetector.ExitThreshold; i++)
            {
                detector.Tick(EmptyImages);
            }
            Assert.AreEqual(DetectorState.Exit, detector.CurrentState);
            Assert.IsTrue(exitRaised);
            enterRaised = false;

            timeProvider.CurrentTime = timeProvider.CurrentTime.AddSeconds(EntryDetector.MinTimeAfterExit - 1);
            detector.Tick(EntryImages);
            Assert.AreEqual(DetectorState.Exit, detector.CurrentState);
            Assert.IsFalse(enterRaised);
        }
Ejemplo n.º 4
0
        public void DetectEntryTest()
        {
            var detector = new EntryDetector(Background);

            var images = Enumerable.Range(0, 2)
                         .Select(i => new Image <Rgb, byte>(@"Resources\train-full.jpg"))
                         .Select(train => train.Convert <Gray, byte>())
                         .ToArray();

            detector.Tick(images);

            Assert.AreEqual(DetectorState.Entry, detector.CurrentState);
        }
Ejemplo n.º 5
0
        public void TestBird()
        {
            var detector = new EntryDetector(Background);

            var images = Enumerable.Range(0, 1)
                         .Select(i => new Image <Rgb, byte>(@"Resources\train-simulated-bird.jpg"))
                         .Select(train => train.Convert <Gray, byte>())
                         .ToArray();

            detector.Tick(images);

            Assert.AreEqual(DetectorState.Nothing, detector.CurrentState);
        }
Ejemplo n.º 6
0
        public void TestBackgrounLazilyInitialized()
        {
            var detector = new EntryDetector();

            var images = Enumerable.Range(0, 4)
                         .Select(i => new Image <Rgb, byte>($@"Resources\train-{(i == 0 ? "0" : "full")}.jpg"))
                         .Select(train => train.Convert <Gray, byte>())
                         .ToArray();

            detector.Tick(images);

            Assert.AreEqual(DetectorState.Entry, detector.CurrentState);
        }
Ejemplo n.º 7
0
        public void DetectNothingTest()
        {
            var detector = new EntryDetector(Background);

            // confusing the algorithm should just say "nothing"
            var image1 = new Image <Rgb, byte>(@"Resources\train-1.jpg");
            var image2 = new Image <Rgb, byte>(@"Resources\train-2.jpg");
            var image3 = new Image <Rgb, byte>(@"Resources\train-3.jpg");
            var image4 = new Image <Rgb, byte>(@"Resources\train-2.jpg");

            var images = new[] { image1, image2, image3, image4 }
            .Select(image => image.Convert <Gray, byte>())
            .ToArray();

            detector.CurrentState = DetectorState.Exit;

            detector.Tick(images);

            Assert.AreEqual(DetectorState.Nothing, detector.CurrentState);
        }
Ejemplo n.º 8
0
        public void TestStopTooLong()
        {
            var timeProvider = new ExternalTimeProvider();
            var detector     = new EntryDetector(Background, timeProvider);
            var enterRaised  = false;
            var exitRaised   = false;

            detector.Enter += (sender, args) => enterRaised = true;
            detector.Exit  += (sender, args) => exitRaised = true;
            detector.Abort += (sender, args) => Assert.Fail("Abort not expected");

            timeProvider.CurrentTime = Year2000;
            detector.Tick(EntryImages);
            Assert.AreEqual(DetectorState.Entry, detector.CurrentState);
            Assert.IsTrue(enterRaised);
            Assert.IsFalse(exitRaised);

            timeProvider.CurrentTime = timeProvider.CurrentTime.AddSeconds(EntryDetector.MaxRecordingDuration + 1);
            detector.Tick(SlowlyMovingTrain);
            Assert.AreEqual(DetectorState.Exit, detector.CurrentState);
            Assert.IsTrue(exitRaised);
        }
        private void DetectIncomingTrains()
        {
            _camera.StreamGrabber.Start(GrabStrategy.LatestImages, GrabLoop.ProvidedByUser);

            // Detection class
            var detector = new EntryDetector(() =>
            {
                // correct exposure
                var exposureTime          = _camera.Parameters[PLCamera.ExposureTime].GetValue();
                var gain                  = _camera.Parameters[PLCamera.Gain].GetValue();
                var formattedExposureTime = string.Format(CultureInfo.CurrentCulture, "{0:0,0}", exposureTime);
                var formattedGain         = string.Format(CultureInfo.CurrentCulture, "{0:0,0}", gain);
                Log.Info($"Exposure is {formattedExposureTime}μs. Gain is {formattedGain}db. Automatically adjusting");

                _camera.Parameters[PLCamera.ExposureAuto].SetValue(PLCamera.ExposureAuto.Off);
                _camera.Parameters[PLCamera.GainAuto].TrySetValue(PLCamera.GainAuto.Off);

                _camera.Parameters[PLCamera.ExposureAuto].SetValue(PLCamera.ExposureAuto.Once);
                _camera.Parameters[PLCamera.GainAuto].TrySetValue(PLCamera.GainAuto.Once);
            });

            // Event handlers
            detector.Enter += (sender, args) => Publish(Commands.CaptureStart, FileUtil.GenerateTimestampFilename());
            detector.Exit  += (sender, args) => Publish(Commands.CaptureStop);
            detector.Abort += (sender, args) => Publish(Commands.CaptureAbort);

            // Array to contain images that will be collected until it's full and we analyze them.
            var images = new Image <Gray, byte> [AnalyzeSequenceImages];

            // Analyze image array counter
            var i = 0;

            // Buffer to put debayered RGB image into (3 channels)
            var convertedBuffer = new byte[_size.Width * _size.Height * 3];

            // Some precalculated constants that we'll use later
            var roi            = new Rectangle(0, _size.Height - RoiY, _size.Width, RoiHeight);
            var downscaledSize = new Size(_size.Width / 2, RoiHeight / 2);

            // Count error frames
            var errorCount = 0;

            // Grab images.
            while (true)
            {
                HandleStateChange();

                // Wait for an image and then retrieve it. A timeout of 5000 ms is used.
                var grabResult = _camera.StreamGrabber.RetrieveResult(5000, TimeoutHandling.ThrowException);

                using (grabResult)
                {
                    // Image grabbed successfully?
                    if (!grabResult.GrabSucceeded)
                    {
                        Log.Error($"Error: {grabResult.ErrorCode} {grabResult.ErrorDescription}");
                        errorCount++;

                        if (errorCount > ErrorThreshold)
                        {
                            Log.Error("Too many errors. Exiting detection. Not exiting recoding.");
                            break;
                        }

                        continue;
                    }

                    // Debayering RGB image
                    _converter.Convert(convertedBuffer, grabResult);

                    // Convert into EmguCV image type
                    var image = new Image <Rgb, byte>(grabResult.Width, grabResult.Height)
                    {
                        Bytes = convertedBuffer
                    };

                    // Write to recorder (if the recorder is not recording, it will discard it)
                    _recorder.Write(image.Mat);

                    // Convert to grayscale image for further analysis and cut down the region of interest
                    var grayImage = image.Convert <Gray, byte>();
                    grayImage.ROI = roi;
                    CvInvoke.Resize(grayImage, grayImage, downscaledSize);

                    // Append to analyze array
                    images[i] = grayImage;
                    i++;

                    // Skip analysation step until we collected a full array of images
                    if (i != images.Length)
                    {
                        continue;
                    }

                    // Reset array counter
                    i = 0;

                    // Let the detector do it's thing (is a train entering? exiting?)
                    detector.Tick(images);

                    // dispose of references to lower memory consumption
                    for (var k = 0; k < images.Length; k++)
                    {
                        images[k] = null;
                    }
                }
            }
        }