/// <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); }
/// <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?"); } }
/// <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); }