Example #1
0
        public TrackFrame(XmlReader r, PointF scale, TimestampMapper timestampMapper)
        {
            bool isEmpty = r.IsEmptyElement;

            long time = 0;
            PositionningSource source   = PositionningSource.Manual;
            PointF             location = PointF.Empty;

            if (r.MoveToAttribute("time"))
            {
                time = timestampMapper(r.ReadContentAsLong());
            }

            if (r.MoveToAttribute("source"))
            {
                source = (PositionningSource)Enum.Parse(typeof(PositionningSource), r.ReadContentAsString());
            }

            if (r.MoveToAttribute("location"))
            {
                location = XmlHelper.ParsePointF(r.ReadContentAsString());
                location = location.Scale(scale.X, scale.Y);
            }

            r.ReadStartElement();

            if (!isEmpty)
            {
                r.ReadEndElement();
            }

            this.time               = time;
            this.location           = location;
            this.positionningSource = source;
        }
Example #2
0
 public TrackFrame(long time, PointF location, Bitmap template, PositionningSource positionningSource)
 {
     this.time               = time;
     this.location           = location;
     this.template           = template;
     this.positionningSource = positionningSource;
 }
Example #3
0
        /// <summary>
        /// Creates a timeline entry (TrackFrame) from an existing location.
        /// Does not perform any tracking.
        /// Extracts the pattern from the image.
        /// </summary>
        private TrackFrame CreateTrackFrame(PointF location, PositionningSource positionningSource)
        {
            Rectangle region   = location.Box(trackerParameters.BlockWindow).ToRectangle();
            Bitmap    template = context.Image.ExtractTemplate(region);

            return(new TrackFrame(context.Time, location, template, positionningSource));
        }
Example #4
0
        private void WriteTrackablePoint(XmlTextWriter w, int frameCount, long time)
        {
            PointF nonTrackingValue = random.NextPointF(0, imageSize.Width, 0, imageSize.Height);
            PointF currentValue     = random.NextPointF(0, imageSize.Width, 0, imageSize.Height);

            WriteTrackerParameters(w);
            w.WriteElementString("NonTrackingValue", XmlHelper.WritePointF(nonTrackingValue));
            w.WriteElementString("CurrentValue", XmlHelper.WritePointF(currentValue));

            w.WriteStartElement("Timeline");
            List <PointF> points = GetRandomTrajectory(frameCount);

            for (int i = 0; i < frameCount; i++)
            {
                Array values = Enum.GetValues(typeof(PositionningSource));
                PositionningSource source = (PositionningSource)values.GetValue(random.Next(values.Length));
                long currentTime          = time + (i * averageTimestampPerFrame);
                w.WriteStartElement("Frame");
                w.WriteAttributeString("time", currentTime.ToString());
                w.WriteAttributeString("location", XmlHelper.WritePointF(points[i]));
                w.WriteAttributeString("source", source.ToString());
                w.WriteEndElement();
            }

            w.WriteEndElement();
        }
Example #5
0
        /// <summary>
        /// Track the point in the current image, or use the existing data if already known.
        /// We do this even if the drawing is currently not tracking, to push the existing tracked data in the object.
        /// Important: for drawings containing multiple trackable points, either all or none of them should have a new value.
        /// If some of them successfully track and some other don't, the one that didn't must insert the closest frame value.
        /// This way we ensure the timelines are always of the same length.
        /// </summary>
        /// <param name="context"></param>
        public bool Track(TrackingContext context)
        {
            bool inserted = false;

            this.context = context;

            if (!trackTimeline.HasData())
            {
                // Not a single entry in the timeline.
                // This drawing has never been activated for tracking so far.
                currentValue   = nonTrackingValue;
                timeDifference = -1;

                if (isTracking)
                {
                    // Use the current user-set position as a first tracked point.
                    trackTimeline.Insert(context.Time, CreateTrackFrame(currentValue, PositionningSource.Manual));
                    timeDifference = 0;
                }

                return(isTracking);
            }

            TrackFrame closestFrame = trackTimeline.ClosestFrom(context.Time);

            if (closestFrame.Template == null)
            {
                // This point has entries in the timeline but doesn't have the corresponding image pattern.
                // This happen when the timeline is imported from a KVA.
                currentValue   = closestFrame.Location;
                timeDifference = Math.Abs(context.Time - closestFrame.Time);

                if (isTracking)
                {
                    // Make sure we extract the pattern and update the entry at this time.
                    // Note: the position we are using could come from a different time.
                    // But since we are actively tracking we need to end up adding an entry at this time.
                    // But since we don't have any specific template to look for, we will just create an entry at the same location.
                    // If we are on the right time, perfect. If not, it will use the location from the closest and comit it to this time.
                    // When the user switched tracking ON for this drawing, they saw where the point was.
                    // If they moved it manually before changing frame, it will be handled in SetUserValue.
                    // If not, it means they are content with the position it has and thus this insertion is correct.
                    PositionningSource source = timeDifference == 0 ? closestFrame.PositionningSource : PositionningSource.ForcedClosest;
                    trackTimeline.Insert(context.Time, CreateTrackFrame(closestFrame.Location, source));
                    timeDifference = 0;
                }

                return(isTracking);
            }

            if (closestFrame.Time == context.Time)
            {
                // We found an entry at the exact time requested.
                currentValue   = closestFrame.Location;
                timeDifference = 0;
                return(false);
            }

            if (!isTracking)
            {
                // We did not find the exact requested time in the timeline, and we are not currently tracking.
                currentValue   = closestFrame.Location;
                timeDifference = Math.Abs(context.Time - closestFrame.Time);
                return(false);
            }

            // We did not find the exact requested time in the timeline, but tracking is active so let's look for the pattern.
            TrackResult result = Tracker.Track(trackerParameters.SearchWindow, closestFrame, context.Image);

            if (result.Similarity >= trackerParameters.SimilarityThreshold)
            {
                currentValue   = result.Location;
                timeDifference = 0;

                if (result.Similarity > trackerParameters.TemplateUpdateThreshold)
                {
                    Bitmap     template = BitmapHelper.Copy(closestFrame.Template);
                    TrackFrame newFrame = new TrackFrame(context.Time, result.Location, template, PositionningSource.TemplateMatching);
                    trackTimeline.Insert(context.Time, newFrame);
                }
                else
                {
                    trackTimeline.Insert(context.Time, CreateTrackFrame(result.Location, PositionningSource.TemplateMatching));
                }

                inserted = true;
            }
            else
            {
                // Tracking failure.
                currentValue   = closestFrame.Location;
                timeDifference = Math.Abs(context.Time - closestFrame.Time);
                inserted       = false;
            }

            return(inserted);
        }