public static CV_MAKETYPE ( int depth, int cn ) : int | ||
depth | int | The type of depth |
cn | int | The number of channels |
return | int |
/// <summary> /// Fit an ellipse to the points collection /// </summary> /// <param name="points">The points to be fitted</param> /// <returns>An ellipse</returns> public static Ellipse EllipseLeastSquareFitting(PointF[] points) { IntPtr seq = Marshal.AllocHGlobal(StructSize.MCvSeq); IntPtr block = Marshal.AllocHGlobal(StructSize.MCvSeqBlock); GCHandle handle = GCHandle.Alloc(points, GCHandleType.Pinned); CvInvoke.cvMakeSeqHeaderForArray( CvInvoke.CV_MAKETYPE((int)CvEnum.MAT_DEPTH.CV_32F, 2), StructSize.MCvSeq, StructSize.PointF, handle.AddrOfPinnedObject(), points.Length, seq, block); Ellipse e = new Ellipse(CvInvoke.cvFitEllipse2(seq)); //The angle returned by cvFitEllipse2 has the wrong sign. //Returned angle is clock wise rotation, what we need for the definition of MCvBox is the counter clockwise rotation. //For this, we needs to change the sign of the angle MCvBox2D b = e.MCvBox2D; b.angle = -b.angle; if (b.angle < 0) { b.angle += 360; } e.MCvBox2D = b; handle.Free(); Marshal.FreeHGlobal(seq); Marshal.FreeHGlobal(block); return(e); }
/// <summary> /// Fix the input element type and return the correct one /// </summary> /// <param name="seqType">The input sequence type</param> /// <returns>The best element type that match this sequence</returns> protected static int FixElementType(int seqType) { int elementTypeID; Type elementType = typeof(T); if (elementType == typeof(PointF)) { elementTypeID = CvInvoke.CV_MAKETYPE((int)CvEnum.MAT_DEPTH.CV_32F, 2); } else if (elementType == typeof(Point)) { elementTypeID = CvInvoke.CV_MAKETYPE((int)CvEnum.MAT_DEPTH.CV_32S, 2); } else if (elementType == typeof(MCvPoint2D64f)) { elementTypeID = CvInvoke.CV_MAKETYPE((int)CvEnum.MAT_DEPTH.CV_64F, 2); } else { // if no match found simply return the original value return(seqType); } return((seqType & (~(int)CvEnum.SeqConst.CV_SEQ_ELTYPE_MASK)) + elementTypeID); }
/// <summary> /// Find the bounding rectangle for the specific array of points /// </summary> /// <param name="points">The collection of points</param> /// <returns>The bounding rectangle for the array of points</returns> public static MCvBox2D MinAreaRect(PointF[] points) { IntPtr seq = Marshal.AllocHGlobal(StructSize.MCvContour); IntPtr block = Marshal.AllocHGlobal(StructSize.MCvSeqBlock); GCHandle handle = GCHandle.Alloc(points, GCHandleType.Pinned); CvInvoke.cvMakeSeqHeaderForArray( CvInvoke.CV_MAKETYPE((int)CvEnum.MAT_DEPTH.CV_32F, 2), StructSize.MCvSeq, StructSize.PointF, handle.AddrOfPinnedObject(), points.Length, seq, block); MCvBox2D rect = CvInvoke.cvMinAreaRect2(seq, IntPtr.Zero); handle.Free(); Marshal.FreeHGlobal(seq); Marshal.FreeHGlobal(block); return(rect); }
/// <summary> /// Finds convex hull of 2D point set using Sklansky's algorithm /// </summary> /// <param name="points">The points to find convex hull from</param> /// <param name="storage">the storage used by the resulting sequence</param> /// <param name="orientation">The orientation of the convex hull</param> /// <returns>The convex hull of the points</returns> public static Seq <PointF> ConvexHull(PointF[] points, MemStorage storage, CvEnum.ORIENTATION orientation) { IntPtr seq = Marshal.AllocHGlobal(StructSize.MCvSeq); IntPtr block = Marshal.AllocHGlobal(StructSize.MCvSeqBlock); GCHandle handle = GCHandle.Alloc(points, GCHandleType.Pinned); CvInvoke.cvMakeSeqHeaderForArray( CvInvoke.CV_MAKETYPE((int)CvEnum.MAT_DEPTH.CV_32F, 2), StructSize.MCvSeq, StructSize.PointF, handle.AddrOfPinnedObject(), points.Length, seq, block); Seq <PointF> convexHull = new Seq <PointF>(CvInvoke.cvConvexHull2(seq, storage.Ptr, orientation, 1), storage); handle.Free(); Marshal.FreeHGlobal(seq); Marshal.FreeHGlobal(block); return(convexHull); }
/// <summary> /// Find the minimum enclosing circle for the specific array of points /// </summary> /// <param name="points">The collection of points</param> /// <returns>The minimum enclosing circle for the array of points</returns> public static CircleF MinEnclosingCircle(PointF[] points) { IntPtr seq = Marshal.AllocHGlobal(StructSize.MCvContour); IntPtr block = Marshal.AllocHGlobal(StructSize.MCvSeqBlock); GCHandle handle = GCHandle.Alloc(points, GCHandleType.Pinned); CvInvoke.cvMakeSeqHeaderForArray( CvInvoke.CV_MAKETYPE((int)CvEnum.MAT_DEPTH.CV_32F, 2), StructSize.MCvSeq, StructSize.PointF, handle.AddrOfPinnedObject(), points.Length, seq, block); PointF center; float radius; CvInvoke.cvMinEnclosingCircle(seq, out center, out radius); handle.Free(); Marshal.FreeHGlobal(seq); Marshal.FreeHGlobal(block); return(new CircleF(center, radius)); }
/* * /// <summary> * /// A comparator which compares only the X value of the point * /// </summary> * private class XValueOfPointComparator : IComparer<PointF> * { * public int Compare(PointF p1, PointF p2) * { * return p1.X.CompareTo(p2.X); * } * } * * /// <summary> * /// Perform a first degree interpolation to lookup the y coordinate given the x coordinate * /// </summary> * /// <param name="points">The collection of points. Must be sorted by the x value.</param> * /// <param name="index">the x coordinate</param> * /// <returns>the y coordinate as the result of the first degree interpolation</returns> * public static float FirstDegreeInterpolate(PointF[] points, float index) * { * XValueOfPointComparator comparator = new XValueOfPointComparator(); * int idx = Array.BinarySearch<PointF>(points, new PointF(index, 0.0f), comparator); * * if (idx >= 0) // an exact index is matched * return points[idx].Y; * * // the index fall into a range, in this case we do interpolation * idx = -idx; * * if (idx == 1) * // the specific index is smaller than all indexes * idx = 0; * else if (idx == points.Length + 1) * // the specific index is larger than all indexes * idx = points.Length - 2; * else * idx -= 2; * * LineSegment2DF line = new LineSegment2DF(points[idx], points[idx + 1]); * return line.YByX(index); * } * * /// <summary> * /// Perform a first degree interpolation to lookup the y coordinates given the x coordinates * /// </summary> * /// <param name="points">The collection of points, Must be sorted by x value</param> * /// <param name="indexes">the x coordinates</param> * /// <returns>The y coordinates as the result of the first degree interpolation</returns> * public static float[] FirstDegreeInterpolate(PointF[] points, float[] indexes) * { * return Array.ConvertAll<float, float>( * indexes, * delegate(float d) { return FirstDegreeInterpolate(points, d); }); * }*/ /// <summary> /// Fit a line to the points collection /// </summary> /// <param name="points">The points to be fitted</param> /// <param name="type">The type of the fitting</param> /// <param name="normalizedDirection">The normalized direction of the fitted line</param> /// <param name="aPointOnLine">A point on the fitted line</param> public static void Line2DFitting(PointF[] points, CvEnum.DIST_TYPE type, out PointF normalizedDirection, out PointF aPointOnLine) { float[] data = new float[6]; IntPtr seq = Marshal.AllocHGlobal(StructSize.MCvSeq); IntPtr block = Marshal.AllocHGlobal(StructSize.MCvSeqBlock); GCHandle handle = GCHandle.Alloc(points, GCHandleType.Pinned); CvInvoke.cvMakeSeqHeaderForArray( CvInvoke.CV_MAKETYPE((int)CvEnum.MAT_DEPTH.CV_32F, 2), StructSize.MCvSeq, StructSize.PointF, handle.AddrOfPinnedObject(), points.Length, seq, block); CvInvoke.cvFitLine(seq, type, 0.0, 0.01, 0.01, data); handle.Free(); Marshal.FreeHGlobal(seq); Marshal.FreeHGlobal(block); normalizedDirection = new PointF(data[0], data[1]); aPointOnLine = new PointF(data[2], data[3]); }
/// <summary> /// Create a Matrix (only header is allocated) using the Pinned/Unmanaged <paramref name="data"/>. The <paramref name="data"/> is not freed by the disposed function of this class /// </summary> /// <param name="rows">The number of rows</param> /// <param name="cols">The number of cols</param> /// <param name="channels">The number of channels</param> /// <param name="data">The Pinned/Unmanaged data, the data must not be release before the Matrix is Disposed</param> /// <param name="step">The step (row stride in bytes)</param> /// <remarks>The caller is responsible for allocating and freeing the block of memory specified by the data parameter, however, the memory should not be released until the related Matrix is released. </remarks> public Matrix(int rows, int cols, int channels, IntPtr data, int step) { AllocateHeader(); CvInvoke.cvInitMatHeader(_ptr, rows, cols, CvInvoke.CV_MAKETYPE((int)Util.GetMatrixDepth(typeof(TDepth)), channels), data, step); }