/// <summary> /// Create a rotation matrix for rotating an image /// </summary> /// <param name="angle">The rotation angle in degrees. Positive values mean couter-clockwise rotation (the coordiate origin is assumed at image centre). </param> /// <param name="center">The rotation center</param> /// <param name="srcImageSize">The source image size</param> /// <param name="dstImageSize">The minimun size of the destination image</param> /// <returns>The rotation matrix that rotate the source image to the destination image.</returns> public static RotationMatrix2D CreateRotationMatrix(PointF center, double angle, Size srcImageSize, out Size dstImageSize) { RotationMatrix2D rotationMatrix = new RotationMatrix2D(center, angle, 1); PointF[] corners = new PointF[] { new PointF(0, 0), new PointF(srcImageSize.Width - 1, 0), new PointF(srcImageSize.Width - 1, srcImageSize.Height - 1), new PointF(0, srcImageSize.Height - 1) }; rotationMatrix.RotatePoints(corners); int minX = (int)Math.Round(Math.Min(Math.Min(corners[0].X, corners[1].X), Math.Min(corners[2].X, corners[3].X))); int maxX = (int)Math.Round(Math.Max(Math.Max(corners[0].X, corners[1].X), Math.Max(corners[2].X, corners[3].X))); int minY = (int)Math.Round(Math.Min(Math.Min(corners[0].Y, corners[1].Y), Math.Min(corners[2].Y, corners[3].Y))); int maxY = (int)Math.Round(Math.Max(Math.Max(corners[0].Y, corners[1].Y), Math.Max(corners[2].Y, corners[3].Y))); using (Matrix <double> offset = new Matrix <double>(2, 3)) { offset[0, 2] = minX; offset[1, 2] = minY; CvInvoke.Subtract(rotationMatrix, offset, rotationMatrix); //rotationMatrix[0, 2] -= minX; //rotationMatrix[1, 2] -= minY; } dstImageSize = new Size(maxX - minX + 1, maxY - minY + 1); return(rotationMatrix); }
/// <summary> /// Return a clone of the Matrix /// </summary> /// <returns>A clone of the Matrix</returns> public new RotationMatrix2D <T> Clone() { RotationMatrix2D <T> clone = new RotationMatrix2D <T>(); CvInvoke.cvCopy(_ptr, clone, IntPtr.Zero); return(clone); }
/// <summary> /// Estimate rigid transformation between 2 point sets. /// </summary> /// <param name="src">The points from the source image</param> /// <param name="dest">The corresponding points from the destination image</param> /// <param name="fullAffine">Indicates if full affine should be performed</param> /// <returns>If success, the 2x3 rotation matrix that defines the Affine transform. Otherwise null is returned.</returns> public static RotationMatrix2D <double> EstimateRigidTransform(PointF[] src, PointF[] dest, bool fullAffine) { RotationMatrix2D <double> result = new RotationMatrix2D <double>(); GCHandle handleA = GCHandle.Alloc(src, GCHandleType.Pinned); GCHandle handleB = GCHandle.Alloc(dest, GCHandleType.Pinned); bool success; using (Matrix <float> a = new Matrix <float>(src.Length, 1, 2, handleA.AddrOfPinnedObject(), 2 * sizeof(float))) using (Matrix <float> b = new Matrix <float>(dest.Length, 1, 2, handleB.AddrOfPinnedObject(), 2 * sizeof(float))) { success = CvInvoke.cvEstimateRigidTransform(a, b, result, fullAffine); } handleA.Free(); handleB.Free(); if (success) { return(result); } else { result.Dispose(); return(null); } }
/// <summary> /// Return a clone of the Matrix /// </summary> /// <returns>A clone of the Matrix</returns> public new RotationMatrix2D Clone() { RotationMatrix2D clone = new RotationMatrix2D(); CopyTo(clone); //CvInvoke.cvCopy(_ptr, clone, IntPtr.Zero); return(clone); }
/// <summary> /// Calculates the matrix of an affine transform such that: /// (x'_i,y'_i)^T=map_matrix (x_i,y_i,1)^T /// where dst(i)=(x'_i,y'_i), src(i)=(x_i,y_i), i=0..2. /// </summary> /// <param name="src">Coordinates of 3 triangle vertices in the source image. If the array contains more than 3 points, only the first 3 will be used</param> /// <param name="dest">Coordinates of the 3 corresponding triangle vertices in the destination image. If the array contains more than 3 points, only the first 3 will be used</param> /// <returns>The 2x3 rotation matrix that defines the Affine transform</returns> public static RotationMatrix2D <double> GetAffineTransform(PointF[] src, PointF[] dest) { Debug.Assert(src.Length >= 3, "The source should contain at least 3 points"); Debug.Assert(dest.Length >= 3, "The destination should contain at least 3 points"); RotationMatrix2D <double> rot = new RotationMatrix2D <double>(); CvInvoke.cvGetAffineTransform(src, dest, rot); return(rot); }
/// <summary> /// Generate a random point cloud around the ellipse. /// </summary> /// <param name="e">The region where the point cloud will be generated. The axes of e corresponds to std of the random point cloud.</param> /// <param name="numberOfPoints">The number of points to be generated</param> /// <returns>A random point cloud around the ellipse</returns> public static PointF[] GeneratePointCloud(Ellipse e, int numberOfPoints) { PointF[] cloud = new PointF[numberOfPoints]; GCHandle handle = GCHandle.Alloc(cloud, GCHandleType.Pinned); using (Matrix <float> points = new Matrix <float>(numberOfPoints, 2, handle.AddrOfPinnedObject())) using (Matrix <float> xValues = points.GetCol(0)) using (Matrix <float> yValues = points.GetCol(1)) using (RotationMatrix2D <float> rotation = new RotationMatrix2D <float>(e.MCvBox2D.center, e.MCvBox2D.angle, 1.0)) { xValues.SetRandNormal(new MCvScalar(e.MCvBox2D.center.X), new MCvScalar(e.MCvBox2D.size.Width / 2.0f)); yValues.SetRandNormal(new MCvScalar(e.MCvBox2D.center.Y), new MCvScalar(e.MCvBox2D.size.Height / 2.0f)); rotation.RotatePoints(points); } handle.Free(); return(cloud); }
/* /// <summary> /// Re-project pixels on a 1-channel disparity map to array of 3D points. /// </summary> /// <param name="disparity">Disparity map</param> /// <param name="Q">The re-projection 4x4 matrix, can be arbitrary, e.g. the one, computed by cvStereoRectify</param> /// <returns>The reprojected 3D points</returns> public static MCvPoint3D32f[] ReprojectImageTo3D(Image<Gray, Byte> disparity, Matrix<double> Q) { Size size = disparity.Size; MCvPoint3D32f[] points3D = new MCvPoint3D32f[size.Width * size.Height]; GCHandle handle = GCHandle.Alloc(points3D, GCHandleType.Pinned); using (Matrix<float> pts = new Matrix<float>(size.Height, size.Width, 3, handle.AddrOfPinnedObject(), 0)) CvInvoke.ReprojectImageTo3D(disparity, pts, Q, false, CvEnum.DepthType.Cv32F); handle.Free(); return points3D; }*/ /// <summary> /// Generate a random point cloud around the ellipse. /// </summary> /// <param name="e">The region where the point cloud will be generated. The axes of e corresponds to std of the random point cloud.</param> /// <param name="numberOfPoints">The number of points to be generated</param> /// <returns>A random point cloud around the ellipse</returns> public static PointF[] GeneratePointCloud(Ellipse e, int numberOfPoints) { PointF[] cloud = new PointF[numberOfPoints]; GCHandle handle = GCHandle.Alloc(cloud, GCHandleType.Pinned); using (Matrix<float> points = new Matrix<float>(numberOfPoints, 2, handle.AddrOfPinnedObject())) using (Matrix<float> xValues = points.GetCol(0)) using (Matrix<float> yValues = points.GetCol(1)) using (RotationMatrix2D rotation = new RotationMatrix2D(e.RotatedRect.Center, e.RotatedRect.Angle, 1.0)) using (Mat tmp = new Mat()) { rotation.ConvertTo(tmp, DepthType.Cv32F); xValues.SetRandNormal(new MCvScalar(e.RotatedRect.Center.X), new MCvScalar(e.RotatedRect.Size.Width / 2.0f)); yValues.SetRandNormal(new MCvScalar(e.RotatedRect.Center.Y), new MCvScalar(e.RotatedRect.Size.Height / 2.0f)); rotation.RotatePoints(points); } handle.Free(); return cloud; }
/// <summary> /// Create a rotation matrix for rotating an image /// </summary> /// <param name="angle">The rotation angle in degrees. Positive values mean couter-clockwise rotation (the coordiate origin is assumed at image centre). </param> /// <param name="center">The rotation center</param> /// <param name="srcImageSize">The source image size</param> /// <param name="dstImageSize">The minimun size of the destination image</param> /// <returns>The rotation matrix that rotate the source image to the destination image.</returns> public static RotationMatrix2D <float> CreateRotationMatrix(PointF center, double angle, Size srcImageSize, out Size dstImageSize) { RotationMatrix2D <float> rotationMatrix = new RotationMatrix2D <float>(center, angle, 1); PointF[] corners = new PointF[] { new PointF(0, 0), new PointF(srcImageSize.Width - 1, 0), new PointF(srcImageSize.Width - 1, srcImageSize.Height - 1), new PointF(0, srcImageSize.Height - 1) }; rotationMatrix.RotatePoints(corners); int minX = (int)Math.Round(Math.Min(Math.Min(corners[0].X, corners[1].X), Math.Min(corners[2].X, corners[3].X))); int maxX = (int)Math.Round(Math.Max(Math.Max(corners[0].X, corners[1].X), Math.Max(corners[2].X, corners[3].X))); int minY = (int)Math.Round(Math.Min(Math.Min(corners[0].Y, corners[1].Y), Math.Min(corners[2].Y, corners[3].Y))); int maxY = (int)Math.Round(Math.Max(Math.Max(corners[0].Y, corners[1].Y), Math.Max(corners[2].Y, corners[3].Y))); rotationMatrix[0, 2] -= minX; rotationMatrix[1, 2] -= minY; dstImageSize = new Size(maxX - minX + 1, maxY - minY + 1); return(rotationMatrix); }