Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
ff190b1e
Commit
ff190b1e
authored
Oct 27, 2017
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #9802 from Nickolays:Fix#9797
parents
1a495a58
b2b56b68
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
120 additions
and
110 deletions
+120
-110
shapedescr.cpp
modules/imgproc/src/shapedescr.cpp
+63
-110
test_convhull.cpp
modules/imgproc/test/test_convhull.cpp
+57
-0
No files found.
modules/imgproc/src/shapedescr.cpp
View file @
ff190b1e
...
@@ -42,11 +42,7 @@
...
@@ -42,11 +42,7 @@
namespace
cv
namespace
cv
{
{
// inner product
const
float
EPS
=
1.0e-4
f
;
static
float
innerProduct
(
Point2f
&
v1
,
Point2f
&
v2
)
{
return
v1
.
x
*
v2
.
y
-
v1
.
y
*
v2
.
x
;
}
static
void
findCircle3pts
(
Point2f
*
pts
,
Point2f
&
center
,
float
&
radius
)
static
void
findCircle3pts
(
Point2f
*
pts
,
Point2f
&
center
,
float
&
radius
)
{
{
...
@@ -54,72 +50,21 @@ 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
v1
=
pts
[
1
]
-
pts
[
0
];
Point2f
v2
=
pts
[
2
]
-
pts
[
0
];
Point2f
v2
=
pts
[
2
]
-
pts
[
0
];
if
(
innerProduct
(
v1
,
v2
)
==
0.0
f
)
// center is intersection of midperpendicular lines of the two edges v1, v2
{
// a1*x + b1*y = c1 where a1 = v1.x, b1 = v1.y
// v1, v2 colineation, can not determine a unique circle
// a2*x + b2*y = c2 where a2 = v2.x, b2 = v2.y
// find the longtest distance as diameter line
Point2f
midPoint1
=
(
pts
[
0
]
+
pts
[
1
])
/
2.0
f
;
float
d1
=
(
float
)
norm
(
pts
[
0
]
-
pts
[
1
]);
float
c1
=
midPoint1
.
x
*
v1
.
x
+
midPoint1
.
y
*
v1
.
y
;
float
d2
=
(
float
)
norm
(
pts
[
0
]
-
pts
[
2
]);
Point2f
midPoint2
=
(
pts
[
0
]
+
pts
[
2
])
/
2.0
f
;
float
d3
=
(
float
)
norm
(
pts
[
1
]
-
pts
[
2
]);
float
c2
=
midPoint2
.
x
*
v2
.
x
+
midPoint2
.
y
*
v2
.
y
;
if
(
d1
>=
d2
&&
d1
>=
d3
)
float
det
=
v1
.
x
*
v2
.
y
-
v1
.
y
*
v2
.
x
;
{
float
cx
=
(
c1
*
v2
.
y
-
c2
*
v1
.
y
)
/
det
;
center
=
(
pts
[
0
]
+
pts
[
1
])
/
2.0
f
;
float
cy
=
(
v1
.
x
*
c2
-
v2
.
x
*
c1
)
/
det
;
radius
=
(
d1
/
2.0
f
);
center
.
x
=
(
float
)
cx
;
}
center
.
y
=
(
float
)
cy
;
else
if
(
d2
>=
d1
&&
d2
>=
d3
)
cx
-=
pts
[
0
].
x
;
{
cy
-=
pts
[
0
].
y
;
center
=
(
pts
[
0
]
+
pts
[
2
])
/
2.0
f
;
radius
=
(
float
)(
std
::
sqrt
(
cx
*
cx
+
cy
*
cy
))
+
EPS
;
radius
=
(
d2
/
2.0
f
);
}
else
if
(
d3
>=
d1
&&
d3
>=
d2
)
{
center
=
(
pts
[
1
]
+
pts
[
2
])
/
2.0
f
;
radius
=
(
d3
/
2.0
f
);
}
}
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.0
f
;
float
c1
=
midPoint1
.
x
*
v1
.
x
+
midPoint1
.
y
*
v1
.
y
;
Point2f
midPoint2
=
(
pts
[
0
]
+
pts
[
2
])
/
2.0
f
;
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-4
f
;
static
void
findEnclosingCircle3pts_orLess_32f
(
Point2f
*
pts
,
int
count
,
Point2f
&
center
,
float
&
radius
)
{
switch
(
count
)
{
case
1
:
center
=
pts
[
0
];
radius
=
0.0
f
;
break
;
case
2
:
center
.
x
=
(
pts
[
0
].
x
+
pts
[
1
].
x
)
/
2.0
f
;
center
.
y
=
(
pts
[
0
].
y
+
pts
[
1
].
y
)
/
2.0
f
;
radius
=
(
float
)(
norm
(
pts
[
0
]
-
pts
[
1
])
/
2.0
);
break
;
case
3
:
findCircle3pts
(
pts
,
center
,
radius
);
break
;
default:
break
;
}
radius
+=
EPS
;
}
}
template
<
typename
PT
>
template
<
typename
PT
>
...
@@ -145,7 +90,7 @@ static void findThirdPoint(const PT *pts, int i, int j, Point2f ¢er, float &
...
@@ -145,7 +90,7 @@ static void findThirdPoint(const PT *pts, int i, int j, Point2f ¢er, float &
ptsf
[
0
]
=
(
Point2f
)
pts
[
i
];
ptsf
[
0
]
=
(
Point2f
)
pts
[
i
];
ptsf
[
1
]
=
(
Point2f
)
pts
[
j
];
ptsf
[
1
]
=
(
Point2f
)
pts
[
j
];
ptsf
[
2
]
=
(
Point2f
)
pts
[
k
];
ptsf
[
2
]
=
(
Point2f
)
pts
[
k
];
find
EnclosingCircle3pts_orLess_32f
(
ptsf
,
3
,
center
,
radius
);
find
Circle3pts
(
ptsf
,
center
,
radius
);
}
}
}
}
}
}
...
@@ -210,8 +155,6 @@ void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radiu
...
@@ -210,8 +155,6 @@ void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radiu
Mat
points
=
_points
.
getMat
();
Mat
points
=
_points
.
getMat
();
int
count
=
points
.
checkVector
(
2
);
int
count
=
points
.
checkVector
(
2
);
int
depth
=
points
.
depth
();
int
depth
=
points
.
depth
();
Point2f
center
;
float
radius
=
0.
f
;
CV_Assert
(
count
>=
0
&&
(
depth
==
CV_32F
||
depth
==
CV_32S
));
CV_Assert
(
count
>=
0
&&
(
depth
==
CV_32F
||
depth
==
CV_32S
));
_center
.
x
=
_center
.
y
=
0.
f
;
_center
.
x
=
_center
.
y
=
0.
f
;
...
@@ -224,52 +167,62 @@ void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radiu
...
@@ -224,52 +167,62 @@ void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radiu
const
Point
*
ptsi
=
points
.
ptr
<
Point
>
();
const
Point
*
ptsi
=
points
.
ptr
<
Point
>
();
const
Point2f
*
ptsf
=
points
.
ptr
<
Point2f
>
();
const
Point2f
*
ptsf
=
points
.
ptr
<
Point2f
>
();
// point count <= 3
switch
(
count
)
if
(
count
<=
3
)
{
{
Point2f
ptsf3
[
3
];
case
1
:
for
(
int
i
=
0
;
i
<
count
;
++
i
)
{
{
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
);
case
2
:
_center
=
center
;
_radius
=
radius
;
return
;
}
if
(
is_float
)
{
findMinEnclosingCircle
<
Point2f
>
(
ptsf
,
count
,
center
,
radius
);
#if 0
for (size_t m = 0; m < count; ++m)
{
{
float d = (float)norm(ptsf[m] - center);
Point2f
p1
=
(
is_float
)
?
ptsf
[
0
]
:
Point2f
((
float
)
ptsi
[
0
].
x
,
(
float
)
ptsi
[
0
].
y
);
if (d > radius)
Point2f
p2
=
(
is_float
)
?
ptsf
[
1
]
:
Point2f
((
float
)
ptsi
[
1
].
x
,
(
float
)
ptsi
[
1
].
y
);
{
_center
.
x
=
(
p1
.
x
+
p2
.
x
)
/
2.0
f
;
printf("error!\n");
_center
.
y
=
(
p1
.
y
+
p2
.
y
)
/
2.0
f
;
}
_radius
=
(
float
)(
norm
(
p1
-
p2
)
/
2.0
)
+
EPS
;
break
;
}
}
#endif
default
:
}
else
{
findMinEnclosingCircle
<
Point
>
(
ptsi
,
count
,
center
,
radius
);
#if 0
for (size_t m = 0; m < count; ++m)
{
{
double dx = ptsi[m].x - center.x;
Point2f
center
;
double dy = ptsi[m].y - center.y;
float
radius
=
0.
f
;
double d = std::sqrt(dx * dx + dy * dy);
if
(
is_float
)
if (d > radius)
{
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
}
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
;
}
}
...
...
modules/imgproc/test/test_convhull.cpp
View file @
ff190b1e
...
@@ -1017,6 +1017,62 @@ _exit_:
...
@@ -1017,6 +1017,62 @@ _exit_:
return
code
;
return
code
;
}
}
/****************************************************************************************\
* MinEnclosingCircle Test 2 *
\****************************************************************************************/
class
CV_MinCircleTest2
:
public
CV_BaseShapeDescrTest
{
public
:
CV_MinCircleTest2
();
protected
:
RNG
rng
;
void
run_func
(
void
);
int
validate_test_results
(
int
test_case_idx
);
float
delta
;
};
CV_MinCircleTest2
::
CV_MinCircleTest2
()
{
rng
=
ts
->
get_rng
();
}
void
CV_MinCircleTest2
::
run_func
()
{
Point2f
center
=
Point2f
(
rng
.
uniform
(
0.0
f
,
1000.0
f
),
rng
.
uniform
(
0.0
f
,
1000.0
f
));;
float
radius
=
rng
.
uniform
(
0.0
f
,
500.0
f
);
float
angle
=
(
float
)
rng
.
uniform
(
0.0
f
,
(
float
)(
CV_2PI
));
vector
<
Point2f
>
pts
;
pts
.
push_back
(
center
+
Point2f
(
radius
*
cos
(
angle
),
radius
*
sin
(
angle
)));
angle
+=
(
float
)
CV_PI
;
pts
.
push_back
(
center
+
Point2f
(
radius
*
cos
(
angle
),
radius
*
sin
(
angle
)));
float
radius2
=
radius
*
radius
;
float
x
=
rng
.
uniform
(
center
.
x
-
radius
,
center
.
x
+
radius
);
float
deltaX
=
x
-
center
.
x
;
float
upperBoundY
=
sqrt
(
radius2
-
deltaX
*
deltaX
);
float
y
=
rng
.
uniform
(
center
.
y
-
upperBoundY
,
center
.
y
+
upperBoundY
);
pts
.
push_back
(
Point2f
(
x
,
y
));
// Find the minimum area enclosing circle
Point2f
calcCenter
;
float
calcRadius
;
minEnclosingCircle
(
pts
,
calcCenter
,
calcRadius
);
delta
=
(
float
)
norm
(
calcCenter
-
center
)
+
abs
(
calcRadius
-
radius
);
}
int
CV_MinCircleTest2
::
validate_test_results
(
int
test_case_idx
)
{
float
eps
=
1.0
F
;
int
code
=
CV_BaseShapeDescrTest
::
validate_test_results
(
test_case_idx
);
if
(
delta
>
eps
)
{
ts
->
printf
(
cvtest
::
TS
::
LOG
,
"Delta center and calcCenter > %f
\n
"
,
eps
);
code
=
cvtest
::
TS
::
FAIL_BAD_ACCURACY
;
ts
->
set_failed_test_info
(
code
);
}
return
code
;
}
/****************************************************************************************\
/****************************************************************************************\
* Perimeter Test *
* Perimeter Test *
...
@@ -1905,6 +1961,7 @@ TEST(Imgproc_ConvexHull, accuracy) { CV_ConvHullTest test; test.safe_run(); }
...
@@ -1905,6 +1961,7 @@ TEST(Imgproc_ConvexHull, accuracy) { CV_ConvHullTest test; test.safe_run(); }
TEST
(
Imgproc_MinAreaRect
,
accuracy
)
{
CV_MinAreaRectTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_MinAreaRect
,
accuracy
)
{
CV_MinAreaRectTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_MinTriangle
,
accuracy
)
{
CV_MinTriangleTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_MinTriangle
,
accuracy
)
{
CV_MinTriangleTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_MinCircle
,
accuracy
)
{
CV_MinCircleTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_MinCircle
,
accuracy
)
{
CV_MinCircleTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_MinCircle2
,
accuracy
)
{
CV_MinCircleTest2
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_ContourPerimeter
,
accuracy
)
{
CV_PerimeterTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_ContourPerimeter
,
accuracy
)
{
CV_PerimeterTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_FitEllipse
,
accuracy
)
{
CV_FitEllipseTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_FitEllipse
,
accuracy
)
{
CV_FitEllipseTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_FitEllipse
,
parallel
)
{
CV_FitEllipseParallelTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_FitEllipse
,
parallel
)
{
CV_FitEllipseParallelTest
test
;
test
.
safe_run
();
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment