/// <summary>
        /// Estimates the pen position on a certain time.
        /// </summary>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        public Point GetPenPoint(long timestamp)
        {
            PointFrame previousFrame = null;

            List <PointFrame> .Enumerator enumerator;

            lock (this._penPoints)
            {
                enumerator = this._penPoints.ToList().GetEnumerator();
                // Search a predecessor and a successor
                while (enumerator.MoveNext() && timestamp < enumerator.Current.Timestamp)
                {
                    if (timestamp == enumerator.Current.Timestamp)
                    {
                        return(enumerator.Current.Point);
                    }
                    previousFrame = enumerator.Current;
                }
                // Calculate interpolation
                if (previousFrame != null && enumerator.Current != null)
                {
                    long ratio = previousFrame.Timestamp / enumerator.Current.Timestamp;
                    return(PointTools.CalculateIntermediatePoint(previousFrame.Point, enumerator.Current.Point, ratio));
                }
            }

            return(Point.Empty);
        }
Example #2
0
        /// <summary>
        /// Delivers a concrete interpretation of the algorithms resulting candidates.
        /// </summary>
        /// <param name="candidates">Zero or multiple found pen candidates</param>
        /// <returns>This is our final result: A pen position</returns>
        private Point FindPen(List <PenCandidate> candidates)
        {
            // Return intermediate point
            switch (candidates.Count())
            {
            case 0:
                // No pen found or pen is not moving
                // TODO (0,0) is actually a valid position!
                return(Point.Empty);

            case 1:
                // Take center of the only found rectangle
                return(candidates.First().WeightedCenter);

            case 2:
                var candidateOne = candidates.ElementAt(0);
                var candidateTwo = candidates.ElementAt(1);
                return(PointTools.CalculateCenterPoint(
                           candidateOne.WeightedCenter,
                           candidateTwo.WeightedCenter));

            default:
                throw new NotImplementedException("TODO Error Handling: more than two points are bad! Wrong Camera adjustment?");
            }
        }
        /// <summary>
        /// This is the time consuming part. We try to find pen candidates in two pictures
        /// by their filtered difference in a specified area.
        /// </summary>
        /// <param name="previous">Previous video picture</param>
        /// <param name="current">Current video picture</param>
        /// <returns>Candidates</returns>
        private IEnumerable <PenCandidate> findPenCandidatesInArea(Bitmap previous, Bitmap current, Rectangle searchArea)
        {
            if (!searchArea.IsEmpty)
            {
                Crop cropFilter = new Crop(searchArea);
                previous = cropFilter.Apply(previous);
                current  = cropFilter.Apply(current);
            }

            // calculate difference image
            this.Strategy.DifferenceFilter.OverlayImage = previous;
            Bitmap diffImage = current; //this.Strategy.DifferenceFilter.Apply(current);
            //diffImage.Save(@"c:\temp\images\diff-"+CurrentMillis.Millis+".png");

            // translate red parts to gray image
            Bitmap grayImage = this.Strategy.GrayFilter.Apply(diffImage);
            //a.Save(@"c:\temp\images\r2_grey16.bmp");

            // treshold the gray image
            Bitmap tresholdImage = this.Strategy.ThresholdFilter.Apply(grayImage);

            //tresholdImage.Save(@"c:\temp\images\blobs-" + CurrentMillis.Millis + ".png");

#if DEBUG
            if (DebugPicture != null)
            {
                DebugPicture(this, new DebugPictureEventArgs(new List <Bitmap>()
                {
                    diffImage, grayImage, tresholdImage
                }));
            }
#endif

            // count white blobs (TODO ev. kann man den thresholdFilter wegschmeissen, siehe ctr parameter von BlobCounter)
            this.Strategy.BlobCounter.ProcessImage(tresholdImage);

            // frame found blobs and add information
            Rectangle[]         rawCandidates = this.Strategy.BlobCounter.GetObjectsRectangles();
            List <PenCandidate> candidates    = new List <PenCandidate>();
            foreach (Rectangle r in rawCandidates)
            {
                r.Offset(searchArea.Location); // Adjust Blob Location to search area
                candidates.Add(new PenCandidate()
                {
                    Rectangle      = r,
                    WeightedCenter = PointTools.CalculateCenterPoint(r) // TODO more precise weightening
                });
            }

            return(candidates);
        }
        /// <summary>
        /// Delivers a concrete interpretation of the algorithms resulting candidates.
        /// </summary>
        /// <param name="candidates">Zero or multiple found pen candidates</param>
        /// <returns>This is our final result: A pen position</returns>
        private Point findPen(IEnumerable <PenCandidate> candidates)
        {
            // Return intermediate point
            switch (candidates.Count())
            {
            case 0:
                // No pen found or pen is not moving
                // TODO (0,0) is actually a valid position!
                return(Point.Empty);

            case 1:
                // Take center of the only found rectangle
                return(candidates.First().WeightedCenter);

            case 2:
                PenCandidate candidateOne = candidates.ElementAt(0);
                PenCandidate candidateTwo = candidates.ElementAt(1);

                //PointFrame previousPointFrame = this.GetLastFrame();
                //if (previousPointFrame == null)
                //{
                //    // If we don't have a previous point, then we can't say in which direction
                //    // the pen is moving. We just interpolate.
                //    return PointTools.CalculateCenterPoint(
                //        candidateOne.WeightedCenter,
                //        candidateTwo.WeightedCenter);
                //}

                //// We search the candidates for the previously recognized pen point
                //// and return just the new one.
                //if (candidateOne.Rectangle.Contains(previousPointFrame.Point))
                //{
                //    return candidateTwo.WeightedCenter;
                //}
                //if (candidateTwo.Rectangle.Contains(previousPointFrame.Point))
                //{
                //    return candidateOne.WeightedCenter;
                //}

                //// Both points are unknown!
                //throw new NotImplementedException("TODO Invalid State. What to do?");

                return(PointTools.CalculateCenterPoint(
                           candidateOne.WeightedCenter,
                           candidateTwo.WeightedCenter));

            default:
                throw new NotImplementedException("TODO Error Handling: more than two points are bad! Wrong Camera adjustment?");
            }
        }
Example #5
0
        /// <summary>
        /// This is the time consuming part. We try to find pen candidates in two pictures
        /// by their filtered difference in a specified area.
        /// </summary>
        /// <param name="previous">Previous video picture</param>
        /// <param name="current">Current video picture</param>
        /// <param name="searchArea"></param>
        /// <returns>Candidates</returns>
        private IEnumerable <PenCandidate> FindPenCandidatesInArea(Bitmap previous, Bitmap current, Rectangle searchArea)
        {
            if (!searchArea.IsEmpty)
            {
                var cropFilter = new Crop(searchArea);
                previous = cropFilter.Apply(previous);
                current  = cropFilter.Apply(current);
            }

            // calculate difference image
            Strategy.DifferenceFilter.OverlayImage = previous;
            var diffImage = current;

            // translate red parts to gray image
            var grayImage = Strategy.GrayFilter.Apply(diffImage);

            // treshold the gray image
            var tresholdImage = Strategy.ThresholdFilter.Apply(grayImage);

            // count white blobs (TODO ev. kann man den thresholdFilter wegschmeissen, siehe ctr parameter von BlobCounter)
            Strategy.BlobCounter.ProcessImage(tresholdImage);

            // frame found blobs and add information
            var rawCandidates = Strategy.BlobCounter.GetObjectsRectangles();
            var candidates    = new List <PenCandidate>();

            foreach (var r in rawCandidates)
            {
                r.Offset(searchArea.Location); // Adjust Blob Location to search area
                candidates.Add(new PenCandidate
                {
                    Rectangle      = r,
                    WeightedCenter = PointTools.CalculateCenterPoint(r) // TODO more precise weightening
                });
            }

            return(candidates);
        }