mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Merge pull request #9802 from Nickolays:Fix#9797
This commit is contained in:
@@ -42,11 +42,7 @@
|
||||
namespace cv
|
||||
{
|
||||
|
||||
// inner product
|
||||
static float innerProduct(Point2f &v1, Point2f &v2)
|
||||
{
|
||||
return v1.x * v2.y - v1.y * v2.x;
|
||||
}
|
||||
const float EPS = 1.0e-4f;
|
||||
|
||||
static void findCircle3pts(Point2f *pts, Point2f ¢er, float &radius)
|
||||
{
|
||||
@@ -54,72 +50,21 @@ static void findCircle3pts(Point2f *pts, Point2f ¢er, float &radius)
|
||||
Point2f v1 = pts[1] - pts[0];
|
||||
Point2f v2 = pts[2] - pts[0];
|
||||
|
||||
if (innerProduct(v1, v2) == 0.0f)
|
||||
{
|
||||
// v1, v2 colineation, can not determine a unique circle
|
||||
// find the longtest distance as diameter line
|
||||
float d1 = (float)norm(pts[0] - pts[1]);
|
||||
float d2 = (float)norm(pts[0] - pts[2]);
|
||||
float d3 = (float)norm(pts[1] - pts[2]);
|
||||
if (d1 >= d2 && d1 >= d3)
|
||||
{
|
||||
center = (pts[0] + pts[1]) / 2.0f;
|
||||
radius = (d1 / 2.0f);
|
||||
}
|
||||
else if (d2 >= d1 && d2 >= d3)
|
||||
{
|
||||
center = (pts[0] + pts[2]) / 2.0f;
|
||||
radius = (d2 / 2.0f);
|
||||
}
|
||||
else if (d3 >= d1 && d3 >= d2)
|
||||
{
|
||||
center = (pts[1] + pts[2]) / 2.0f;
|
||||
radius = (d3 / 2.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// center is intersection of midperpendicular lines of the two edges v1, v2
|
||||
// a1*x + b1*y = c1 where a1 = v1.x, b1 = v1.y
|
||||
// a2*x + b2*y = c2 where a2 = v2.x, b2 = v2.y
|
||||
Point2f midPoint1 = (pts[0] + pts[1]) / 2.0f;
|
||||
float c1 = midPoint1.x * v1.x + midPoint1.y * v1.y;
|
||||
Point2f midPoint2 = (pts[0] + pts[2]) / 2.0f;
|
||||
float c2 = midPoint2.x * v2.x + midPoint2.y * v2.y;
|
||||
float det = v1.x * v2.y - v1.y * v2.x;
|
||||
float cx = (c1 * v2.y - c2 * v1.y) / det;
|
||||
float cy = (v1.x * c2 - v2.x * c1) / det;
|
||||
center.x = (float)cx;
|
||||
center.y = (float)cy;
|
||||
cx -= pts[0].x;
|
||||
cy -= pts[0].y;
|
||||
radius = (float)(std::sqrt(cx *cx + cy * cy));
|
||||
}
|
||||
}
|
||||
|
||||
const float EPS = 1.0e-4f;
|
||||
|
||||
static void findEnclosingCircle3pts_orLess_32f(Point2f *pts, int count, Point2f ¢er, float &radius)
|
||||
{
|
||||
switch (count)
|
||||
{
|
||||
case 1:
|
||||
center = pts[0];
|
||||
radius = 0.0f;
|
||||
break;
|
||||
case 2:
|
||||
center.x = (pts[0].x + pts[1].x) / 2.0f;
|
||||
center.y = (pts[0].y + pts[1].y) / 2.0f;
|
||||
radius = (float)(norm(pts[0] - pts[1]) / 2.0);
|
||||
break;
|
||||
case 3:
|
||||
findCircle3pts(pts, center, radius);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
radius += EPS;
|
||||
// center is intersection of midperpendicular lines of the two edges v1, v2
|
||||
// a1*x + b1*y = c1 where a1 = v1.x, b1 = v1.y
|
||||
// a2*x + b2*y = c2 where a2 = v2.x, b2 = v2.y
|
||||
Point2f midPoint1 = (pts[0] + pts[1]) / 2.0f;
|
||||
float c1 = midPoint1.x * v1.x + midPoint1.y * v1.y;
|
||||
Point2f midPoint2 = (pts[0] + pts[2]) / 2.0f;
|
||||
float c2 = midPoint2.x * v2.x + midPoint2.y * v2.y;
|
||||
float det = v1.x * v2.y - v1.y * v2.x;
|
||||
float cx = (c1 * v2.y - c2 * v1.y) / det;
|
||||
float cy = (v1.x * c2 - v2.x * c1) / det;
|
||||
center.x = (float)cx;
|
||||
center.y = (float)cy;
|
||||
cx -= pts[0].x;
|
||||
cy -= pts[0].y;
|
||||
radius = (float)(std::sqrt(cx *cx + cy * cy)) + EPS;
|
||||
}
|
||||
|
||||
template<typename PT>
|
||||
@@ -145,7 +90,7 @@ static void findThirdPoint(const PT *pts, int i, int j, Point2f ¢er, float &
|
||||
ptsf[0] = (Point2f)pts[i];
|
||||
ptsf[1] = (Point2f)pts[j];
|
||||
ptsf[2] = (Point2f)pts[k];
|
||||
findEnclosingCircle3pts_orLess_32f(ptsf, 3, center, radius);
|
||||
findCircle3pts(ptsf, center, radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,8 +155,6 @@ void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radiu
|
||||
Mat points = _points.getMat();
|
||||
int count = points.checkVector(2);
|
||||
int depth = points.depth();
|
||||
Point2f center;
|
||||
float radius = 0.f;
|
||||
CV_Assert(count >= 0 && (depth == CV_32F || depth == CV_32S));
|
||||
|
||||
_center.x = _center.y = 0.f;
|
||||
@@ -224,52 +167,62 @@ void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radiu
|
||||
const Point* ptsi = points.ptr<Point>();
|
||||
const Point2f* ptsf = points.ptr<Point2f>();
|
||||
|
||||
// point count <= 3
|
||||
if (count <= 3)
|
||||
switch (count)
|
||||
{
|
||||
Point2f ptsf3[3];
|
||||
for (int i = 0; i < count; ++i)
|
||||
case 1:
|
||||
{
|
||||
ptsf3[i] = (is_float) ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
|
||||
_center = (is_float) ? ptsf[0] : Point2f((float)ptsi[0].x, (float)ptsi[0].y);
|
||||
_radius = EPS;
|
||||
break;
|
||||
}
|
||||
findEnclosingCircle3pts_orLess_32f(ptsf3, count, center, radius);
|
||||
_center = center;
|
||||
_radius = radius;
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_float)
|
||||
{
|
||||
findMinEnclosingCircle<Point2f>(ptsf, count, center, radius);
|
||||
#if 0
|
||||
for (size_t m = 0; m < count; ++m)
|
||||
case 2:
|
||||
{
|
||||
float d = (float)norm(ptsf[m] - center);
|
||||
if (d > radius)
|
||||
Point2f p1 = (is_float) ? ptsf[0] : Point2f((float)ptsi[0].x, (float)ptsi[0].y);
|
||||
Point2f p2 = (is_float) ? ptsf[1] : Point2f((float)ptsi[1].x, (float)ptsi[1].y);
|
||||
_center.x = (p1.x + p2.x) / 2.0f;
|
||||
_center.y = (p1.y + p2.y) / 2.0f;
|
||||
_radius = (float)(norm(p1 - p2) / 2.0) + EPS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Point2f center;
|
||||
float radius = 0.f;
|
||||
if (is_float)
|
||||
{
|
||||
printf("error!\n");
|
||||
findMinEnclosingCircle<Point2f>(ptsf, count, center, radius);
|
||||
#if 0
|
||||
for (size_t m = 0; m < count; ++m)
|
||||
{
|
||||
float d = (float)norm(ptsf[m] - center);
|
||||
if (d > radius)
|
||||
{
|
||||
printf("error!\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
findMinEnclosingCircle<Point>(ptsi, count, center, radius);
|
||||
#if 0
|
||||
for (size_t m = 0; m < count; ++m)
|
||||
{
|
||||
double dx = ptsi[m].x - center.x;
|
||||
double dy = ptsi[m].y - center.y;
|
||||
double d = std::sqrt(dx * dx + dy * dy);
|
||||
if (d > radius)
|
||||
else
|
||||
{
|
||||
printf("error!\n");
|
||||
findMinEnclosingCircle<Point>(ptsi, count, center, radius);
|
||||
#if 0
|
||||
for (size_t m = 0; m < count; ++m)
|
||||
{
|
||||
double dx = ptsi[m].x - center.x;
|
||||
double dy = ptsi[m].y - center.y;
|
||||
double d = std::sqrt(dx * dx + dy * dy);
|
||||
if (d > radius)
|
||||
{
|
||||
printf("error!\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
_center = center;
|
||||
_radius = radius;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
_center = center;
|
||||
_radius = radius;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user