Asymmetric orientation in Emgu or OpenCv

I am trying to get the orientation of a form (binary or outline). The shape is mostly rectangular, but has a large hole on one side. I want my orientation to match this asymmetry in the object.

I considered several articles that use spatial and central moments for this. For instance. The orientation of the binary images but it seems that the orientation that I get with this sometimes turns off with a multiple of 90 degrees.

The following document states that there is some ambiguity: http://public.cranfield.ac.uk/c5354/teaching/dip/opencv/SimpleImageAnalysisbyMoments.pdf

If I implement this using

private void GetCenterAndOrientationViaMoments(Contour<Point> cont, Size imageSize) { // obtain the orientation of the found object // first draw the binary blob in a separate image // I do this for the hole(s) in the image, but I'm not sure if it is needed. // Possibly I can tak the moments directly from the contour Image<Gray, byte> instanceImage = new Image<Gray, byte>(imageSize); instanceImage.FillConvexPoly(cont.ToArray(), new Gray(255)); for (Contour<Point> hole = cont.VNext; hole != null; hole = hole.HNext) instanceImage.FillConvexPoly(hole.ToArray(), new Gray(0)); // calculate the moments MCvMoments m = instanceImage.GetMoments(true); // MCvMoments m = cont.GetMoments(); double m00 = m.GetSpatialMoment(0, 0); double m10 = m.GetSpatialMoment(1, 0); double m01 = m.GetSpatialMoment(0, 1); double mu11 = m.GetCentralMoment(1, 1); double mu20 = m.GetCentralMoment(2, 0); double mu02 = m.GetCentralMoment(0, 2); // calculate the center PointF center = new PointF((float)(m10 / m00), (float)(m01 / m00)); // calculate the orientation // http://public.cranfield.ac.uk/c5354/teaching/dip/opencv/SimpleImageAnalysisbyMoments.pdf double theta = 0; double mu20_mu02 = (mu20 - mu02); if ((mu20_mu02 == 0) & (mu11 == 0)) theta = 0; else if ((mu20_mu02 == 0) & (mu11 > 0)) theta = Math.PI / 4; else if ((mu20_mu02 == 0) & (mu11 < 0)) theta = -Math.PI / 4; else if ((mu20_mu02 > 0) & (mu11 == 0)) theta = 0; else if ((mu20_mu02 < 0) & (mu11 == 0)) theta = -Math.PI / 2; else if ((mu20_mu02 > 0) & (mu11 > 0)) theta = 0.5 * Math.Atan((2 * mu11) / mu20_mu02); else if ((mu20_mu02 > 0) & (mu11 < 0)) theta = 0.5 * Math.Atan((2 * mu11) / mu20_mu02); else if ((mu20_mu02 < 0) & (mu11 > 0)) theta = 0.5 * Math.Atan((2 * mu11) / mu20_mu02) + Math.PI / 2; else if ((mu20_mu02 < 0) & (mu11 < 0)) theta = 0.5 * Math.Atan((2 * mu11) / mu20_mu02) - Math.PI / 2; #if DEBUG int radius = 25; instanceImage.Draw(new CircleF(center, radius), new Gray(100), 2); instanceImage.Draw( new LineSegment2DF( center, new PointF( (float)(center.X + radius * Math.Cos(theta)), (float)(center.Y + radius * Math.Sin(theta)))), new Gray(100), 2); ImageViewer.Show(instanceImage, string.Format("Center and orientation")); #endif } 

My orientation is correct, but does not always point to the same end of the object. In other words, I'm sometimes 180 degrees.

I assume that the method cannot provide exactly what I want, because it uses distribution covariance ( http://en.wikipedia.org/wiki/Image_moments#Examples_2 ), which gives it does not take into account the asymmetry caused by the hole, right?

Is there a way to resolve the ambiguity 180 degrees?

Regards, Tom

+4
source share

Source: https://habr.com/ru/post/1484574/


All Articles