Browse Source

-Fix a bug in EllipseLeastSquareFitting, such that a positive value of the angle of the ellipse indicates counter-clock-wise rotation. Now it is consistent with the ellipse drawing function.

-Added  GeneratePointCloud function

git-svn-id: https://emgucv.svn.sourceforge.net/svnroot/emgucv/trunk@556 d7f09016-e345-0410-b530-edf29a71df78
UWP10
canming 16 years ago
parent
commit
1673fb7aff
  1. 19
      Emgu.CV.Test/AutoTestVarious.cs
  2. 32
      Emgu.CV/PointAndLine/PointCollection.cs

19
Emgu.CV.Test/AutoTestVarious.cs

@ -1092,7 +1092,6 @@ namespace Emgu.CV.Test
}
}
[Test]
public void TestEllipseFitting()
{
@ -1100,22 +1099,18 @@ namespace Emgu.CV.Test
int sampleCount = 100;
Image<Bgr, byte> img = new Image<Bgr, byte>(400, 400, new Bgr(Color.White));
PointF[] pts = new PointF[sampleCount];
for (int i = 0; i < pts.Length; i++)
{
int x = r.Next(200) + 50;
int y = r.Next(300) + 50;
pts[i] = new PointF(x, y);
img.Draw(new CircleF(pts[i], 2), new Bgr(Color.Green), 1);
}
Ellipse modelEllipse = new Ellipse(new PointF(200, 200), new SizeF(150, 60), 30);
PointF[] pts = PointCollection.GeneratePointCloud(modelEllipse, sampleCount);
foreach (PointF p in pts)
img.Draw(new CircleF(p, 2), new Bgr(Color.Green), 1);
Stopwatch watch = Stopwatch.StartNew();
Ellipse e = PointCollection.EllipseLeastSquareFitting(pts);
Ellipse fittedEllipse = PointCollection.EllipseLeastSquareFitting(pts);
watch.Stop();
img.Draw(e, new Bgr(Color.Red), 2);
//img.Draw(modelEllipse, new Bgr(Color.Orange), 2);
img.Draw(fittedEllipse, new Bgr(Color.Red), 2);
//ImageViewer.Show(img, String.Format("Time used: {0}milliseconds", watch.ElapsedMilliseconds));
}

32
Emgu.CV/PointAndLine/PointCollection.cs

@ -116,6 +116,15 @@ namespace Emgu.CV
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);
@ -278,5 +287,28 @@ namespace Emgu.CV
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<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;
}
}
}
Loading…
Cancel
Save