using System; using System.Collections.Generic; using System.Linq; using System.Drawing; using System.Text; using System.Threading.Tasks; using Emgu.CV; using Emgu.CV.Structure; namespace bbiwarg.Utility { /// /// Computes and stores a homography matrix and provides functions to export it and project points. /// class Projection2DTo2D { /// /// size of the image the original points are in /// private ImageSize sizeA; /// /// size of the image the projected points are in /// private ImageSize sizeB; /// /// calibration points in the first image (match points in calibrationPointsB) /// private List calibrationPointsA; /// /// calibration points in the second image (match points in calibrationPointsA) /// private List calibrationPointsB; /// /// number of points used for the calibration /// private int numPointsForCalibration; /// /// homography matrix used to compute the projected points /// private HomographyMatrix homography; /// /// true iff the calibration is finished /// public bool IsCalibrated { get; private set; } /// /// Constructs a Projection2DTo2D. /// /// size of the image the original points are in /// size of the image the projected points are in /// number of points used for the calibration public Projection2DTo2D(ImageSize sizeA, ImageSize sizeB, int numPointsForCalibration = 4) { this.sizeA = sizeA; this.sizeB = sizeB; this.numPointsForCalibration = numPointsForCalibration; reset(); } /// /// Resets the calibration. /// public void reset() { homography = null; IsCalibrated = false; calibrationPointsA = new List(); calibrationPointsB = new List(); } /// /// Adds a pair of calibration points. /// /// point in the first image /// point in the second image public void addCalibrationPoints(Vector2D pointA, Vector2D pointB) { calibrationPointsA.Add(sizeA.getRelativePoint(pointA)); calibrationPointsB.Add(sizeB.getRelativePoint(pointB)); if (calibrationPointsA.Count == numPointsForCalibration) calibrate(); } /// /// Projects a point. /// /// the point to project /// projected point public Vector2D projectPoint(Vector2D pointA) { PointF[] pointfsB = new PointF[1] { sizeA.getRelativePoint(pointA) }; homography.ProjectPoints(pointfsB); return sizeB.getAbsolutePoint(new Vector2D(pointfsB[0])); } /// /// Computes the homography from the lists of calibration points. /// private void calibrate() { homography = CameraCalibration.FindHomography(calibrationPointsA.ToArray(), calibrationPointsB.ToArray(), Emgu.CV.CvEnum.HOMOGRAPHY_METHOD.DEFAULT, 0.995); calibrationPointsA.Clear(); calibrationPointsB.Clear(); IsCalibrated = true; exportHomography(); } /// /// Writes the homography to a file. /// private void exportHomography() { String[] fileData = new String[homography.Size.Height]; StringBuilder sb = new StringBuilder(); for (int r = 0; r < homography.Size.Height; r++) { for (int c = 0; c < homography.Size.Width; c++) { sb.Append(homography.Data[r, c]); sb.Append(" "); } fileData[r] = sb.ToString(); sb.Clear(); } System.IO.File.WriteAllLines(Parameters.HomographyFileName, fileData); } } }