Exemple #1
0
        private void ParseTimeline(XmlReader r, PointF scale, TimestampMapper timeMapper)
        {
            trackTimeline.Clear();

            bool isEmpty = r.IsEmptyElement;

            r.ReadStartElement();

            while (r.NodeType == XmlNodeType.Element)
            {
                switch (r.Name)
                {
                case "Frame":
                    TrackFrame frame = new TrackFrame(r, scale, timeMapper);
                    trackTimeline.Insert(frame.Time, frame);
                    break;

                default:
                    string unparsed = r.ReadOuterXml();
                    break;
                }
            }

            if (!isEmpty)
            {
                r.ReadEndElement();
            }
        }
Exemple #2
0
        /// <summary>
        /// Returns the position of the point nearest to that time.
        /// This is used by linear kinematics.
        /// </summary>
        public PointF GetLocation(long time)
        {
            if (trackTimeline.Count == 0)
            {
                return(currentValue);
            }

            TrackFrame closestFrame = trackTimeline.ClosestFrom(time);

            return(closestFrame.Location);
        }
Exemple #3
0
        /// <summary>
        /// Track the point in the current image, or use the existing data if already known.
        /// </summary>
        /// <param name="context"></param>
        public void Track(TrackingContext context)
        {
            this.context = context;

            if (!isTracking)
            {
                return;
            }

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

            if (closestFrame == null)
            {
                currentValue = nonTrackingValue;
                trackTimeline.Insert(context.Time, CreateTrackFrame(currentValue, PositionningSource.Manual));
                return;
            }

            if (closestFrame.Template == null)
            {
                // We may not have the template if the timeline was imported from KVA.
                trackTimeline.Insert(context.Time, CreateTrackFrame(closestFrame.Location, closestFrame.PositionningSource));
                currentValue = closestFrame.Location;
                return;
            }

            if (closestFrame.Time == context.Time)
            {
                currentValue = closestFrame.Location;
                return;
            }

            TrackResult result = Tracker.Track(trackerParameters.SearchWindow, closestFrame, context.Image);

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

                if (result.Similarity > trackerParameters.TemplateUpdateThreshold)
                {
                    Bitmap     template = closestFrame.Template.CloneDeep();
                    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));
                }
            }
            else
            {
                currentValue = closestFrame.Location;
            }
        }
Exemple #4
0
        /// <summary>
        /// Tracks a reference template in the given image. Returns similarity score and position of best candidate.
        /// </summary>
        public static TrackResult Track(Size searchWindow, TrackFrame reference, Bitmap image)
        {
            if (image == null || reference.Template == null)
            {
                throw new ArgumentException("image");
            }

            Rectangle searchZone  = reference.Location.Box(searchWindow).ToRectangle();
            Rectangle imageBounds = new Rectangle(0, 0, image.Width, image.Height);

            searchZone.Intersect(imageBounds);

            if (searchZone == Rectangle.Empty)
            {
                return(new TrackResult(0, Point.Empty));
            }

            Bitmap    template       = reference.Template;
            Rectangle templateBounds = new Rectangle(0, 0, template.Width, template.Height);

            if (searchZone.Width < template.Width || searchZone.Height < template.Height)
            {
                return(new TrackResult(0, Point.Empty));
            }

            BitmapData imageData    = image.LockBits(imageBounds, ImageLockMode.ReadOnly, image.PixelFormat);
            BitmapData templateData = template.LockBits(templateBounds, ImageLockMode.ReadOnly, template.PixelFormat);

            Image <Bgra, Byte> cvImage    = new Image <Bgra, Byte>(imageData.Width, imageData.Height, imageData.Stride, imageData.Scan0);
            Image <Bgra, Byte> cvTemplate = new Image <Bgra, Byte>(templateData.Width, templateData.Height, templateData.Stride, templateData.Scan0);

            cvImage.ROI = searchZone;

            int similarityMapWidth             = searchZone.Width - template.Width + 1;
            int similarityMapHeight            = searchZone.Height - template.Height + 1;
            Image <Gray, Single> similarityMap = new Image <Gray, Single>(similarityMapWidth, similarityMapHeight);

            CvInvoke.cvMatchTemplate(cvImage.Ptr, cvTemplate.Ptr, similarityMap.Ptr, TM_TYPE.CV_TM_CCOEFF_NORMED);

            image.UnlockBits(imageData);
            template.UnlockBits(templateData);

            Point  minLoc        = new Point(0, 0);
            Point  maxLoc        = new Point(0, 0);
            double minSimilarity = 0;
            double maxSimilarity = 0;

            CvInvoke.cvMinMaxLoc(similarityMap.Ptr, ref minSimilarity, ref maxSimilarity, ref minLoc, ref maxLoc, IntPtr.Zero);

            Point location = new Point(searchZone.Left + maxLoc.X + template.Width / 2, searchZone.Top + maxLoc.Y + template.Height / 2);

            return(new TrackResult(maxSimilarity, location));
        }
        public void ForceInsertClosestLocation()
        {
            // This function is used when a drawing containing multiple trackable points has some of the points failing the template matching and others succeeding.
            // We must always keep the same number of entries in the timelines of all trackable points of a given drawing.
            // In this function we force the points that failed tracking to insert a dummy value in their timeline.
            if (!isTracking)
            {
                return;
            }

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

            if (closestFrame == null)
            {
                return;
            }

            currentValue = closestFrame.Location;
            trackTimeline.Insert(context.Time, CreateTrackFrame(currentValue, PositionningSource.ForcedClosest));
        }
Exemple #6
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);
        }