private void FindMarker(Image<Rgb, byte> image, int offsetX, int offsetY, int width, int height, ref Image<Rgb, byte> outputImage) { if (_glyphRecognizer != null) { // go through all found glyphs, highlight them and put the recognized ones in a list _recognizedGlyphs.Clear(); _recognizedQuads.Clear(); var glyphs = _glyphRecognizer.FindGlyphs(image.Bitmap); foreach (var glyph in glyphs) { // highlight quadrilateral (of all found glyphs) var quad = glyph.Quadrilateral; if (IsRenderContent && quad != null && quad.Count == 4) { outputImage.DrawPolyline( new[] { new Point(quad[0].X + offsetX, quad[0].Y + offsetY), new Point(quad[1].X + offsetX, quad[1].Y + offsetY), new Point(quad[2].X + offsetX, quad[2].Y + offsetY), new Point(quad[3].X + offsetX, quad[3].Y + offsetY) }, true, Rgbs.Red, 1); // write numbers on edge points (of all found glyphs) var i = 0; foreach (var point in quad) { outputImage.Draw(i++.ToString(CultureInfo.InvariantCulture), ref EmguFont, new Point(point.X + offsetX, point.Y + offsetY), Rgbs.TrueRed); } } // if glyphs are recognized then store and draw name var recQuad = glyph.RecognizedQuadrilateral; var recGlyph = glyph.RecognizedGlyph; if (recQuad != null && recGlyph != null) { _recognizedGlyphs.Add(recGlyph.Name, recGlyph); _recognizedQuads.Add(recGlyph.Name, recQuad); if (IsRenderContent) { String label = recGlyph.Name; Point labelPos = new Point(recQuad[2].X + offsetX, recQuad[2].Y + offsetY); outputImage.Draw(label, ref EmguFontBig, labelPos, Rgbs.Green); } } } // update all entries in glyph table using recognized glyphs for (int i = 0; i < _glyphTable.Length; i++) { var name = i.ToString(CultureInfo.InvariantCulture); Glyph glyph = null; List<IntPoint> quad = null; if (_recognizedGlyphs.ContainsKey(name)) glyph = _recognizedGlyphs[name]; if (_recognizedQuads.ContainsKey(name)) quad = _recognizedQuads[name]; // if glyph for this entry was recognized, update entry if (glyph != null && quad != null) { // if there is no entry yet, create it if (_glyphTable[i] == null) _glyphTable[i] = new GlyphMetadata(); var gmd = _glyphTable[i]; gmd.aliveFrames++; IntPoint upVector1 = quad[0] - quad[3]; IntPoint upVector2 = quad[1] - quad[2]; upVector1 = (upVector1 + upVector2) / 2; double orientation = Math.Atan2(upVector1.Y, upVector2.X); // always keep only the last X frames in list if (gmd.prevX.Count == MinFramesProperty) { gmd.prevX.RemoveAt(0); gmd.prevY.RemoveAt(0); gmd.prevOrientations.RemoveAt(0); } gmd.prevX.Add(quad[0].X); gmd.prevY.Add(quad[0].Y); gmd.prevOrientations.Add(orientation); // check if marker stops moving and rotating if (Math.Abs(gmd.prevX.Max() - gmd.prevX.Min()) < 5 && Math.Abs(gmd.prevY.Max() - gmd.prevY.Min()) < 5 && gmd.aliveFrames >= MinFramesProperty) { double radOrientation = gmd.prevOrientations.Average() + Math.PI / 2; if (IsRenderContent) { Point p1 = new Point(quad[0].X + offsetX, quad[0].Y + offsetY); Point p2 = new Point( (int)(quad[0].X + offsetX + Math.Cos(orientation) * 100.0), (int)(quad[0].Y + offsetY + Math.Sin(orientation) * 100.0) ); outputImage.Draw(new LineSegment2D(p1, p2), Rgbs.Yellow, 2); } double degOrientation = orientation.RadiansToDegree() + 90; // find bounding rectangle float minX = image.Width; float minY = image.Height; float maxX = 0; float maxY = 0; foreach (IntPoint p in quad) { minX = Math.Min(minX, p.X); minY = Math.Min(minY, p.Y); maxX = Math.Max(maxX, p.X); maxY = Math.Max(maxY, p.Y); } float centerX = offsetX + minX + (maxX - minX) / 2.0f; float centerY = offsetY + minY + (maxY - minY) / 2.0f; if (IsRenderContent) outputImage.Draw(new Cross2DF(new PointF(centerX, centerY), 6, 6), Rgbs.Red, 1); // Stage data for later push Stage(new Marker(this, string.Format("Glyph{0}", name)) { Id = name, Center = new System.Windows.Point(centerX / width, centerY / height), Angle = degOrientation }); if (IsRenderContent) { // bring to human readable form radOrientation = Math.Round(radOrientation, 2); degOrientation = Math.Round(degOrientation, 2); String label = radOrientation + " " + degOrientation; Point labelPos = new Point(quad[0].X + offsetX, quad[0].Y + offsetY); outputImage.Draw(label, ref EmguFontBig, labelPos, Rgbs.Yellow); } } } else { // if glyph disappeared remove entry from table _recognizedGlyphs[name] = null; } } } }
private void FindMarker(Image <Rgb, byte> image, int offsetX, int offsetY, int width, int height, ref Image <Rgb, byte> outputImage) { if (_glyphRecognizer != null) { // go through all found glyphs, highlight them and put the recognized ones in a list _recognizedGlyphs.Clear(); _recognizedQuads.Clear(); var glyphs = _glyphRecognizer.FindGlyphs(image.Bitmap); foreach (var glyph in glyphs) { // highlight quadrilateral (of all found glyphs) var quad = glyph.Quadrilateral; if (IsRenderContent && quad != null && quad.Count == 4) { outputImage.DrawPolyline( new[] { new Point(quad[0].X + offsetX, quad[0].Y + offsetY), new Point(quad[1].X + offsetX, quad[1].Y + offsetY), new Point(quad[2].X + offsetX, quad[2].Y + offsetY), new Point(quad[3].X + offsetX, quad[3].Y + offsetY) }, true, Rgbs.Red, 1); // write numbers on edge points (of all found glyphs) var i = 0; foreach (var point in quad) { outputImage.Draw(i++.ToString(CultureInfo.InvariantCulture), ref EmguFont, new Point(point.X + offsetX, point.Y + offsetY), Rgbs.TrueRed); } } // if glyphs are recognized then store and draw name var recQuad = glyph.RecognizedQuadrilateral; var recGlyph = glyph.RecognizedGlyph; if (recQuad != null && recGlyph != null) { _recognizedGlyphs.Add(recGlyph.Name, recGlyph); _recognizedQuads.Add(recGlyph.Name, recQuad); if (IsRenderContent) { String label = recGlyph.Name; Point labelPos = new Point(recQuad[2].X + offsetX, recQuad[2].Y + offsetY); outputImage.Draw(label, ref EmguFontBig, labelPos, Rgbs.Green); } } } // update all entries in glyph table using recognized glyphs for (int i = 0; i < _glyphTable.Length; i++) { var name = i.ToString(CultureInfo.InvariantCulture); Glyph glyph = null; List <IntPoint> quad = null; if (_recognizedGlyphs.ContainsKey(name)) { glyph = _recognizedGlyphs[name]; } if (_recognizedQuads.ContainsKey(name)) { quad = _recognizedQuads[name]; } // if glyph for this entry was recognized, update entry if (glyph != null && quad != null) { // if there is no entry yet, create it if (_glyphTable[i] == null) { _glyphTable[i] = new GlyphMetadata(); } var gmd = _glyphTable[i]; gmd.aliveFrames++; IntPoint upVector1 = quad[0] - quad[3]; IntPoint upVector2 = quad[1] - quad[2]; upVector1 = (upVector1 + upVector2) / 2; double orientation = Math.Atan2(upVector1.Y, upVector2.X); // always keep only the last X frames in list if (gmd.prevX.Count == MinFramesProperty) { gmd.prevX.RemoveAt(0); gmd.prevY.RemoveAt(0); gmd.prevOrientations.RemoveAt(0); } gmd.prevX.Add(quad[0].X); gmd.prevY.Add(quad[0].Y); gmd.prevOrientations.Add(orientation); // check if marker stops moving and rotating if (Math.Abs(gmd.prevX.Max() - gmd.prevX.Min()) < 5 && Math.Abs(gmd.prevY.Max() - gmd.prevY.Min()) < 5 && gmd.aliveFrames >= MinFramesProperty) { double radOrientation = gmd.prevOrientations.Average() + Math.PI / 2; if (IsRenderContent) { Point p1 = new Point(quad[0].X + offsetX, quad[0].Y + offsetY); Point p2 = new Point( (int)(quad[0].X + offsetX + Math.Cos(orientation) * 100.0), (int)(quad[0].Y + offsetY + Math.Sin(orientation) * 100.0) ); outputImage.Draw(new LineSegment2D(p1, p2), Rgbs.Yellow, 2); } double degOrientation = orientation.RadiansToDegree() + 90; // find bounding rectangle float minX = image.Width; float minY = image.Height; float maxX = 0; float maxY = 0; foreach (IntPoint p in quad) { minX = Math.Min(minX, p.X); minY = Math.Min(minY, p.Y); maxX = Math.Max(maxX, p.X); maxY = Math.Max(maxY, p.Y); } float centerX = offsetX + minX + (maxX - minX) / 2.0f; float centerY = offsetY + minY + (maxY - minY) / 2.0f; if (IsRenderContent) { outputImage.Draw(new Cross2DF(new PointF(centerX, centerY), 6, 6), Rgbs.Red, 1); } // Stage data for later push Stage(new Marker(this, string.Format("Glyph{0}", name)) { Id = name, Center = new System.Windows.Point(centerX / width, centerY / height), Angle = degOrientation }); if (IsRenderContent) { // bring to human readable form radOrientation = Math.Round(radOrientation, 2); degOrientation = Math.Round(degOrientation, 2); String label = radOrientation + " " + degOrientation; Point labelPos = new Point(quad[0].X + offsetX, quad[0].Y + offsetY); outputImage.Draw(label, ref EmguFontBig, labelPos, Rgbs.Yellow); } } } else { // if glyph disappeared remove entry from table _recognizedGlyphs[name] = null; } } } }