/// <summary> /// Initialize the projective mapping. /// </summary> /// <param name="size">Real world dimension of the reference rectangle.</param> /// <param name="quadImage">Image coordinates of the reference rectangle.</param> public void Initialize(SizeF size, QuadrilateralF quadImage) { PointF originImage = initialized ? Untransform(PointF.Empty) : quadImage.D; this.size = size; this.quadImage = quadImage.Clone(); mapping.Update(new QuadrilateralF(size.Width, size.Height), quadImage); SetOrigin(originImage); this.initialized = true; valid = quadImage.IsConvex; }
/// <summary> /// Initialize the projective mapping from a quadrilateral. /// size: Real world dimension of the reference rectangle. /// quadImage: Image coordinates of the reference rectangle. /// </summary> public void Initialize(SizeF sizeWorld, QuadrilateralF quadImage) { //PointF originImage = initialized ? Untransform(PointF.Empty) : quadImage.D; PointF originImage = quadImage.D; this.size = sizeWorld; this.quadImage = quadImage.Clone(); mapping.Update(new QuadrilateralF(size.Width, size.Height), quadImage); origin = mapping.Backward(originImage); this.initialized = true; valid = quadImage.IsConvex; perspective = !quadImage.IsAxisAlignedRectangle; }
/// <summary> /// Takes a circle in image space and returns a cooresponding ellipse in image space. /// This is an ill posed problem. The center is respected but the radius could be taken /// anywhere around the circle in image space, and that yields different radii in world space. /// We use the point along the X axis as the radius. /// </summary> public Ellipse GetEllipseFromCircle(PointF center, float radius, out PointF radiusLeftInImage, out PointF radiusRightInImage) { radiusLeftInImage = new PointF(center.X - radius, center.Y); radiusRightInImage = new PointF(center.X + radius, center.Y); if (calibratorType == CalibratorType.Line) { return(new Ellipse(center, radius, radius, 0)); } // Rebuild the world-space circle based on center and radius alone. PointF centerInWorld = GetPoint(center); // Estimate the radius in world space. // Get scalar will assumes reference direction to be X-axis in image space. float radiusInWorld = GetScalar(radius); // Get the intersection points of a horizontal diameter. // This is used to draw a line from the center to the outline of the ellipse in perspective. radiusLeftInImage = GetImagePoint(centerInWorld.Translate(-radiusInWorld, 0)); radiusRightInImage = GetImagePoint(centerInWorld.Translate(radiusInWorld, 0)); // Get the square enclosing the circle for mapping. PointF a = GetImagePoint(centerInWorld.Translate(-radiusInWorld, -radiusInWorld)); PointF b = GetImagePoint(centerInWorld.Translate(radiusInWorld, -radiusInWorld)); PointF c = GetImagePoint(centerInWorld.Translate(radiusInWorld, radiusInWorld)); PointF d = GetImagePoint(centerInWorld.Translate(-radiusInWorld, radiusInWorld)); QuadrilateralF quadImage = new QuadrilateralF(a, b, c, d); ProjectiveMapping mapping = new ProjectiveMapping(); mapping.Update(QuadrilateralF.CenteredUnitSquare, quadImage); return(mapping.Ellipse()); }
public override void Draw(Graphics canvas, DistortionHelper distorter, IImageToViewportTransformer transformer, bool selected, long currentTimestamp) { double opacityFactor = infosFading.GetOpacityTrackable(trackingTimestamps, currentTimestamp); if (opacityFactor <= 0) { return; } QuadrilateralF quad = transformer.Transform(quadImage); bool drawEdgesOnly = !planeIsConvex || (!styleHelper.Perspective && !quadImage.IsAxisAlignedRectangle); using (penEdges = styleHelper.GetPen(opacityFactor, 1.0)) using (SolidBrush br = styleHelper.GetBrush(opacityFactor)) { foreach (PointF p in quad) { canvas.FillEllipse(br, p.Box(4)); } if (!drawEdgesOnly) { if (distorter != null && distorter.Initialized) { QuadrilateralF undistortedQuadImage = distorter.Undistort(quadImage); projectiveMapping.Update(quadPlane, undistortedQuadImage); } else { projectiveMapping.Update(quadPlane, quadImage); } DrawGrid(canvas, penEdges, projectiveMapping, distorter, transformer); } else { // Non convex quadrilateral or non rectangle 2d grid: only draw the edges. canvas.DrawLine(penEdges, quad.A, quad.B); canvas.DrawLine(penEdges, quad.B, quad.C); canvas.DrawLine(penEdges, quad.C, quad.D); canvas.DrawLine(penEdges, quad.D, quad.A); } } }
public override void Draw(Graphics canvas, DistortionHelper distorter, IImageToViewportTransformer transformer, bool selected, long currentTimestamp) { double opacityFactor = infosFading.GetOpacityFactor(currentTimestamp); if (opacityFactor <= 0) { return; } QuadrilateralF quad = transformer.Transform(quadImage); using (penEdges = styleHelper.GetPen(opacityFactor, 1.0)) using (SolidBrush br = styleHelper.GetBrush(opacityFactor)) { foreach (PointF p in quad) { canvas.FillEllipse(br, p.Box(4)); } if (planeIsConvex) { if (distorter != null && distorter.Initialized) { QuadrilateralF undistortedQuadImage = distorter.Undistort(quadImage); projectiveMapping.Update(quadPlane, undistortedQuadImage); } else { projectiveMapping.Update(quadPlane, quadImage); } //DrawDiagonals(canvas, penEdges, quadPlane, projectiveMapping, distorter, transformer); DrawGrid(canvas, penEdges, projectiveMapping, distorter, transformer); } else { // Non convex quadrilateral: only draw the edges. canvas.DrawLine(penEdges, quad.A, quad.B); canvas.DrawLine(penEdges, quad.B, quad.C); canvas.DrawLine(penEdges, quad.C, quad.D); canvas.DrawLine(penEdges, quad.D, quad.A); } } }
/// <summary> /// Takes a circle in real world coordinates and returns a cooresponding ellipse in image coordinates. /// </summary> public Ellipse GetEllipseFromCircle(PointF center, float radius) { if (calibratorType == CalibratorType.Line) { return(new Ellipse(GetImagePoint(center), GetImageScalar(radius), GetImageScalar(radius), 0)); } // Get the square enclosing the circle for mapping. PointF a = GetImagePoint(center.Translate(-radius, -radius)); PointF b = GetImagePoint(center.Translate(radius, -radius)); PointF c = GetImagePoint(center.Translate(radius, radius)); PointF d = GetImagePoint(center.Translate(-radius, radius)); QuadrilateralF quadImage = new QuadrilateralF(a, b, c, d); ProjectiveMapping mapping = new ProjectiveMapping(); mapping.Update(QuadrilateralF.CenteredUnitSquare, quadImage); return(mapping.Ellipse()); }