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
dc4d0398
Commit
dc4d0398
authored
Jan 22, 2013
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
converted few more comp. geometry functions to C++
parent
c2241dcc
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1165 additions
and
1476 deletions
+1165
-1476
_geom.h
modules/imgproc/src/_geom.h
+0
-10
contours.cpp
modules/imgproc/src/contours.cpp
+0
-81
geometry.cpp
modules/imgproc/src/geometry.cpp
+40
-102
matchcontours.cpp
modules/imgproc/src/matchcontours.cpp
+84
-121
rotcalipers.cpp
modules/imgproc/src/rotcalipers.cpp
+331
-371
shapedescr.cpp
modules/imgproc/src/shapedescr.cpp
+709
-790
minarea.cpp
samples/cpp/minarea.cpp
+1
-1
No files found.
modules/imgproc/src/_geom.h
View file @
dc4d0398
...
...
@@ -52,16 +52,6 @@ CV_INLINE float icvDistanceL2_32f( CvPoint2D32f pt1, CvPoint2D32f pt2 )
}
int
icvIntersectLines
(
double
x1
,
double
dx1
,
double
y1
,
double
dy1
,
double
x2
,
double
dx2
,
double
y2
,
double
dy2
,
double
*
t2
);
void
icvIntersectLines3
(
double
*
a0
,
double
*
b0
,
double
*
c0
,
double
*
a1
,
double
*
b1
,
double
*
c1
,
CvPoint2D32f
*
point
);
/* curvature: 0 - 1-curvature, 1 - k-cosine curvature. */
CvSeq
*
icvApproximateChainTC89
(
CvChain
*
chain
,
int
header_size
,
CvMemStorage
*
storage
,
int
method
);
...
...
modules/imgproc/src/contours.cpp
View file @
dc4d0398
...
...
@@ -1753,85 +1753,4 @@ void cv::findContours( InputOutputArray _image, OutputArrayOfArrays _contours,
findContours
(
_image
,
_contours
,
noArray
(),
mode
,
method
,
offset
);
}
double
cv
::
arcLength
(
InputArray
_curve
,
bool
closed
)
{
Mat
curve
=
_curve
.
getMat
();
CV_Assert
(
curve
.
checkVector
(
2
)
>=
0
&&
(
curve
.
depth
()
==
CV_32F
||
curve
.
depth
()
==
CV_32S
));
CvMat
_ccurve
=
curve
;
return
cvArcLength
(
&
_ccurve
,
CV_WHOLE_SEQ
,
closed
);
}
cv
::
Rect
cv
::
boundingRect
(
InputArray
_points
)
{
Mat
points
=
_points
.
getMat
();
CV_Assert
(
points
.
checkVector
(
2
)
>=
0
&&
(
points
.
depth
()
==
CV_32F
||
points
.
depth
()
==
CV_32S
));
CvMat
_cpoints
=
points
;
return
cvBoundingRect
(
&
_cpoints
,
0
);
}
double
cv
::
contourArea
(
InputArray
_contour
,
bool
oriented
)
{
Mat
contour
=
_contour
.
getMat
();
CV_Assert
(
contour
.
checkVector
(
2
)
>=
0
&&
(
contour
.
depth
()
==
CV_32F
||
contour
.
depth
()
==
CV_32S
));
CvMat
_ccontour
=
contour
;
return
cvContourArea
(
&
_ccontour
,
CV_WHOLE_SEQ
,
oriented
);
}
cv
::
RotatedRect
cv
::
minAreaRect
(
InputArray
_points
)
{
Mat
points
=
_points
.
getMat
();
CV_Assert
(
points
.
checkVector
(
2
)
>=
0
&&
(
points
.
depth
()
==
CV_32F
||
points
.
depth
()
==
CV_32S
));
CvMat
_cpoints
=
points
;
return
cvMinAreaRect2
(
&
_cpoints
,
0
);
}
void
cv
::
minEnclosingCircle
(
InputArray
_points
,
Point2f
&
center
,
float
&
radius
)
{
Mat
points
=
_points
.
getMat
();
CV_Assert
(
points
.
checkVector
(
2
)
>=
0
&&
(
points
.
depth
()
==
CV_32F
||
points
.
depth
()
==
CV_32S
));
CvMat
_cpoints
=
points
;
cvMinEnclosingCircle
(
&
_cpoints
,
(
CvPoint2D32f
*
)
&
center
,
&
radius
);
}
double
cv
::
matchShapes
(
InputArray
_contour1
,
InputArray
_contour2
,
int
method
,
double
parameter
)
{
Mat
contour1
=
_contour1
.
getMat
(),
contour2
=
_contour2
.
getMat
();
CV_Assert
(
contour1
.
checkVector
(
2
)
>=
0
&&
contour2
.
checkVector
(
2
)
>=
0
&&
(
contour1
.
depth
()
==
CV_32F
||
contour1
.
depth
()
==
CV_32S
)
&&
contour1
.
depth
()
==
contour2
.
depth
());
CvMat
c1
=
Mat
(
contour1
),
c2
=
Mat
(
contour2
);
return
cvMatchShapes
(
&
c1
,
&
c2
,
method
,
parameter
);
}
cv
::
RotatedRect
cv
::
fitEllipse
(
InputArray
_points
)
{
Mat
points
=
_points
.
getMat
();
CV_Assert
(
points
.
checkVector
(
2
)
>=
0
&&
(
points
.
depth
()
==
CV_32F
||
points
.
depth
()
==
CV_32S
));
CvMat
_cpoints
=
points
;
return
cvFitEllipse2
(
&
_cpoints
);
}
double
cv
::
pointPolygonTest
(
InputArray
_contour
,
Point2f
pt
,
bool
measureDist
)
{
Mat
contour
=
_contour
.
getMat
();
CV_Assert
(
contour
.
checkVector
(
2
)
>=
0
&&
(
contour
.
depth
()
==
CV_32F
||
contour
.
depth
()
==
CV_32S
));
CvMat
c
=
Mat
(
contour
);
return
cvPointPolygonTest
(
&
c
,
pt
,
measureDist
);
}
/* End of file. */
modules/imgproc/src/geometry.cpp
View file @
dc4d0398
...
...
@@ -92,97 +92,38 @@ cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] )
}
int
icvIntersectLines
(
double
x1
,
double
dx1
,
double
y1
,
double
dy1
,
double
x2
,
double
dx2
,
double
y2
,
double
dy2
,
double
*
t2
)
{
double
d
=
dx1
*
dy2
-
dx2
*
dy1
;
int
result
=
-
1
;
if
(
d
!=
0
)
{
*
t2
=
((
x2
-
x1
)
*
dy1
-
(
y2
-
y1
)
*
dx1
)
/
d
;
result
=
0
;
}
return
result
;
}
void
icvIntersectLines3
(
double
*
a0
,
double
*
b0
,
double
*
c0
,
double
*
a1
,
double
*
b1
,
double
*
c1
,
CvPoint2D32f
*
point
)
{
double
det
=
a0
[
0
]
*
b1
[
0
]
-
a1
[
0
]
*
b0
[
0
];
if
(
det
!=
0
)
{
det
=
1.
/
det
;
point
->
x
=
(
float
)
((
b0
[
0
]
*
c1
[
0
]
-
b1
[
0
]
*
c0
[
0
])
*
det
);
point
->
y
=
(
float
)
((
a1
[
0
]
*
c0
[
0
]
-
a0
[
0
]
*
c1
[
0
])
*
det
);
}
else
{
point
->
x
=
point
->
y
=
FLT_MAX
;
}
}
CV_IMPL
double
cvPointPolygonTest
(
const
CvArr
*
_contour
,
CvPoint2D32f
pt
,
int
measure_dist
)
double
cv
::
pointPolygonTest
(
InputArray
_contour
,
Point2f
pt
,
bool
measureDist
)
{
double
result
=
0
;
Mat
contour
=
_contour
.
getMat
();
int
i
,
total
=
contour
.
checkVector
(
2
),
counter
=
0
;
int
depth
=
contour
.
depth
();
CV_Assert
(
total
>=
0
&&
(
depth
==
CV_32S
||
depth
==
CV_32F
));
CvSeqBlock
block
;
CvContour
header
;
CvSeq
*
contour
=
(
CvSeq
*
)
_contour
;
CvSeqReader
reader
;
int
i
,
total
,
counter
=
0
;
int
is_float
;
bool
is_float
=
depth
==
CV_32F
;
double
min_dist_num
=
FLT_MAX
,
min_dist_denom
=
1
;
CvPoint
ip
=
{
0
,
0
}
;
Point
ip
(
cvRound
(
pt
.
x
),
cvRound
(
pt
.
y
))
;
if
(
!
CV_IS_SEQ
(
contour
)
)
{
contour
=
cvPointSeqFromMat
(
CV_SEQ_KIND_CURVE
+
CV_SEQ_FLAG_CLOSED
,
_contour
,
&
header
,
&
block
);
}
else
if
(
CV_IS_SEQ_POINT_SET
(
contour
)
)
{
if
(
contour
->
header_size
==
sizeof
(
CvContour
)
&&
!
measure_dist
)
{
CvRect
r
=
((
CvContour
*
)
contour
)
->
rect
;
if
(
pt
.
x
<
r
.
x
||
pt
.
y
<
r
.
y
||
pt
.
x
>=
r
.
x
+
r
.
width
||
pt
.
y
>=
r
.
y
+
r
.
height
)
return
-
1
;
}
}
else
if
(
CV_IS_SEQ_CHAIN
(
contour
)
)
{
CV_Error
(
CV_StsBadArg
,
"Chains are not supported. Convert them to polygonal representation using cvApproxChains()"
);
}
else
CV_Error
(
CV_StsBadArg
,
"Input contour is neither a valid sequence nor a matrix"
);
if
(
total
==
0
)
return
measureDist
?
-
DBL_MAX
:
-
1
;
total
=
contour
->
total
;
is_float
=
CV_SEQ_ELTYPE
(
contour
)
==
CV_32FC2
;
cvStartReadSeq
(
contour
,
&
reader
,
-
1
);
const
Point
*
cnt
=
(
const
Point
*
)
contour
.
data
;
const
Point2f
*
cntf
=
(
const
Point2f
*
)
cnt
;
if
(
!
is_float
&&
!
measure
_dist
&&
(
ip
.
x
=
cvRound
(
pt
.
x
))
==
pt
.
x
&&
(
ip
.
y
=
cvRound
(
pt
.
y
))
==
pt
.
y
)
if
(
!
is_float
&&
!
measure
Dist
&&
ip
.
x
==
pt
.
x
&&
ip
.
y
==
pt
.
y
)
{
// the fastest "pure integer" branch
CvPoint
v0
,
v
;
CV_READ_SEQ_ELEM
(
v
,
reader
);
// the fastest "purely integer" branch
Point
v0
,
v
=
cnt
[
total
-
1
];
for
(
i
=
0
;
i
<
total
;
i
++
)
{
int
dist
;
v0
=
v
;
CV_READ_SEQ_ELEM
(
v
,
reader
)
;
v
=
cnt
[
i
]
;
if
(
(
v0
.
y
<=
ip
.
y
&&
v
.
y
<=
ip
.
y
)
||
(
v0
.
y
>
ip
.
y
&&
v
.
y
>
ip
.
y
)
||
(
v0
.
x
<
ip
.
x
&&
v
.
x
<
ip
.
x
)
)
(
v0
.
y
>
ip
.
y
&&
v
.
y
>
ip
.
y
)
||
(
v0
.
x
<
ip
.
x
&&
v
.
x
<
ip
.
x
)
)
{
if
(
ip
.
y
==
v
.
y
&&
(
ip
.
x
==
v
.
x
||
(
ip
.
y
==
v0
.
y
&&
((
v0
.
x
<=
ip
.
x
&&
ip
.
x
<=
v
.
x
)
||
(
v
.
x
<=
ip
.
x
&&
ip
.
x
<=
v0
.
x
))))
)
...
...
@@ -202,38 +143,32 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
}
else
{
CvPoint2D3
2f
v0
,
v
;
Cv
Point
iv
;
Point
2f
v0
,
v
;
Point
iv
;
if
(
is_float
)
{
CV_READ_SEQ_ELEM
(
v
,
reader
)
;
v
=
cntf
[
total
-
1
]
;
}
else
{
CV_READ_SEQ_ELEM
(
iv
,
reader
);
v
=
cvPointTo32f
(
iv
);
v
=
cnt
[
total
-
1
];
}
if
(
!
measure
_d
ist
)
if
(
!
measure
D
ist
)
{
for
(
i
=
0
;
i
<
total
;
i
++
)
{
double
dist
;
v0
=
v
;
if
(
is_float
)
{
CV_READ_SEQ_ELEM
(
v
,
reader
);
}
v
=
cntf
[
i
];
else
{
CV_READ_SEQ_ELEM
(
iv
,
reader
);
v
=
cvPointTo32f
(
iv
);
}
v
=
cnt
[
i
];
if
(
(
v0
.
y
<=
pt
.
y
&&
v
.
y
<=
pt
.
y
)
||
(
v0
.
y
>
pt
.
y
&&
v
.
y
>
pt
.
y
)
||
(
v0
.
x
<
pt
.
x
&&
v
.
x
<
pt
.
x
)
)
(
v0
.
y
>
pt
.
y
&&
v
.
y
>
pt
.
y
)
||
(
v0
.
x
<
pt
.
x
&&
v
.
x
<
pt
.
x
)
)
{
if
(
pt
.
y
==
v
.
y
&&
(
pt
.
x
==
v
.
x
||
(
pt
.
y
==
v0
.
y
&&
((
v0
.
x
<=
pt
.
x
&&
pt
.
x
<=
v
.
x
)
||
(
v
.
x
<=
pt
.
x
&&
pt
.
x
<=
v0
.
x
))))
)
...
...
@@ -259,14 +194,9 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
v0
=
v
;
if
(
is_float
)
{
CV_READ_SEQ_ELEM
(
v
,
reader
);
}
v
=
cntf
[
i
];
else
{
CV_READ_SEQ_ELEM
(
iv
,
reader
);
v
=
cvPointTo32f
(
iv
);
}
v
=
cnt
[
i
];
dx
=
v
.
x
-
v0
.
x
;
dy
=
v
.
y
-
v0
.
y
;
dx1
=
pt
.
x
-
v0
.
x
;
dy1
=
pt
.
y
-
v0
.
y
;
...
...
@@ -292,8 +222,8 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
}
if
(
(
v0
.
y
<=
pt
.
y
&&
v
.
y
<=
pt
.
y
)
||
(
v0
.
y
>
pt
.
y
&&
v
.
y
>
pt
.
y
)
||
(
v0
.
x
<
pt
.
x
&&
v
.
x
<
pt
.
x
)
)
(
v0
.
y
>
pt
.
y
&&
v
.
y
>
pt
.
y
)
||
(
v0
.
x
<
pt
.
x
&&
v
.
x
<
pt
.
x
)
)
continue
;
dist_num
=
dy1
*
dx
-
dx1
*
dy
;
...
...
@@ -301,17 +231,25 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
dist_num
=
-
dist_num
;
counter
+=
dist_num
>
0
;
}
result
=
sqrt
(
min_dist_num
/
min_dist_denom
);
if
(
counter
%
2
==
0
)
result
=
-
result
;
}
}
return
result
;
}
CV_IMPL
double
cvPointPolygonTest
(
const
CvArr
*
_contour
,
CvPoint2D32f
pt
,
int
measure_dist
)
{
cv
::
AutoBuffer
<
double
>
abuf
;
cv
::
Mat
contour
=
cv
::
cvarrToMat
(
_contour
,
false
,
false
,
0
,
&
abuf
);
return
cv
::
pointPolygonTest
(
contour
,
pt
,
measure_dist
!=
0
);
}
/*
This code is described in "Computational Geometry in C" (Second Edition),
Chapter 7. It is not written to be comprehensible without the
...
...
modules/imgproc/src/matchcontours.cpp
View file @
dc4d0398
...
...
@@ -40,159 +40,122 @@
//M*/
#include "precomp.hpp"
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvMatchContours
// Purpose:
// Calculates matching of the two contours
// Context:
// Parameters:
// contour_1 - pointer to the first input contour object.
// contour_2 - pointer to the second input contour object.
// method - method for the matching calculation
// (now CV_IPPI_CONTOURS_MATCH_I1, CV_CONTOURS_MATCH_I2 or
// CV_CONTOURS_MATCH_I3 only )
// rezult - output calculated measure
//
//F*/
CV_IMPL
double
cvMatchShapes
(
const
void
*
contour1
,
const
void
*
contour2
,
int
method
,
double
/*parameter*/
)
double
cv
::
matchShapes
(
InputArray
contour1
,
InputArray
contour2
,
int
method
,
double
)
{
CvMoments
moments
;
CvHuMoments
huMoments
;
double
ma
[
7
],
mb
[
7
];
int
i
,
sma
,
smb
;
double
eps
=
1.e-5
;
double
mmm
;
double
result
=
0
;
if
(
!
contour1
||
!
contour2
)
CV_Error
(
CV_StsNullPtr
,
""
);
// calculate moments of the first shape
cvMoments
(
contour1
,
&
moments
);
cvGetHuMoments
(
&
moments
,
&
huMoments
);
ma
[
0
]
=
huMoments
.
hu1
;
ma
[
1
]
=
huMoments
.
hu2
;
ma
[
2
]
=
huMoments
.
hu3
;
ma
[
3
]
=
huMoments
.
hu4
;
ma
[
4
]
=
huMoments
.
hu5
;
ma
[
5
]
=
huMoments
.
hu6
;
ma
[
6
]
=
huMoments
.
hu7
;
// calculate moments of the second shape
cvMoments
(
contour2
,
&
moments
);
cvGetHuMoments
(
&
moments
,
&
huMoments
);
mb
[
0
]
=
huMoments
.
hu1
;
mb
[
1
]
=
huMoments
.
hu2
;
mb
[
2
]
=
huMoments
.
hu3
;
mb
[
3
]
=
huMoments
.
hu4
;
mb
[
4
]
=
huMoments
.
hu5
;
mb
[
5
]
=
huMoments
.
hu6
;
mb
[
6
]
=
huMoments
.
hu7
;
HuMoments
(
moments
(
contour1
),
ma
);
HuMoments
(
moments
(
contour2
),
mb
);
switch
(
method
)
{
case
1
:
for
(
i
=
0
;
i
<
7
;
i
++
)
{
for
(
i
=
0
;
i
<
7
;
i
++
)
double
ama
=
fabs
(
ma
[
i
]
);
double
amb
=
fabs
(
mb
[
i
]
);
if
(
ma
[
i
]
>
0
)
sma
=
1
;
else
if
(
ma
[
i
]
<
0
)
sma
=
-
1
;
else
sma
=
0
;
if
(
mb
[
i
]
>
0
)
smb
=
1
;
else
if
(
mb
[
i
]
<
0
)
smb
=
-
1
;
else
smb
=
0
;
if
(
ama
>
eps
&&
amb
>
eps
)
{
double
ama
=
fabs
(
ma
[
i
]
);
double
amb
=
fabs
(
mb
[
i
]
);
if
(
ma
[
i
]
>
0
)
sma
=
1
;
else
if
(
ma
[
i
]
<
0
)
sma
=
-
1
;
else
sma
=
0
;
if
(
mb
[
i
]
>
0
)
smb
=
1
;
else
if
(
mb
[
i
]
<
0
)
smb
=
-
1
;
else
smb
=
0
;
if
(
ama
>
eps
&&
amb
>
eps
)
{
ama
=
1.
/
(
sma
*
log10
(
ama
));
amb
=
1.
/
(
smb
*
log10
(
amb
));
result
+=
fabs
(
-
ama
+
amb
);
}
ama
=
1.
/
(
sma
*
log10
(
ama
));
amb
=
1.
/
(
smb
*
log10
(
amb
));
result
+=
fabs
(
-
ama
+
amb
);
}
break
;
}
break
;
case
2
:
for
(
i
=
0
;
i
<
7
;
i
++
)
{
for
(
i
=
0
;
i
<
7
;
i
++
)
double
ama
=
fabs
(
ma
[
i
]
);
double
amb
=
fabs
(
mb
[
i
]
);
if
(
ma
[
i
]
>
0
)
sma
=
1
;
else
if
(
ma
[
i
]
<
0
)
sma
=
-
1
;
else
sma
=
0
;
if
(
mb
[
i
]
>
0
)
smb
=
1
;
else
if
(
mb
[
i
]
<
0
)
smb
=
-
1
;
else
smb
=
0
;
if
(
ama
>
eps
&&
amb
>
eps
)
{
double
ama
=
fabs
(
ma
[
i
]
);
double
amb
=
fabs
(
mb
[
i
]
);
if
(
ma
[
i
]
>
0
)
sma
=
1
;
else
if
(
ma
[
i
]
<
0
)
sma
=
-
1
;
else
sma
=
0
;
if
(
mb
[
i
]
>
0
)
smb
=
1
;
else
if
(
mb
[
i
]
<
0
)
smb
=
-
1
;
else
smb
=
0
;
if
(
ama
>
eps
&&
amb
>
eps
)
{
ama
=
sma
*
log10
(
ama
);
amb
=
smb
*
log10
(
amb
);
result
+=
fabs
(
-
ama
+
amb
);
}
ama
=
sma
*
log10
(
ama
);
amb
=
smb
*
log10
(
amb
);
result
+=
fabs
(
-
ama
+
amb
);
}
break
;
}
break
;
case
3
:
for
(
i
=
0
;
i
<
7
;
i
++
)
{
for
(
i
=
0
;
i
<
7
;
i
++
)
double
ama
=
fabs
(
ma
[
i
]
);
double
amb
=
fabs
(
mb
[
i
]
);
if
(
ma
[
i
]
>
0
)
sma
=
1
;
else
if
(
ma
[
i
]
<
0
)
sma
=
-
1
;
else
sma
=
0
;
if
(
mb
[
i
]
>
0
)
smb
=
1
;
else
if
(
mb
[
i
]
<
0
)
smb
=
-
1
;
else
smb
=
0
;
if
(
ama
>
eps
&&
amb
>
eps
)
{
double
ama
=
fabs
(
ma
[
i
]
);
double
amb
=
fabs
(
mb
[
i
]
);
if
(
ma
[
i
]
>
0
)
sma
=
1
;
else
if
(
ma
[
i
]
<
0
)
sma
=
-
1
;
else
sma
=
0
;
if
(
mb
[
i
]
>
0
)
smb
=
1
;
else
if
(
mb
[
i
]
<
0
)
smb
=
-
1
;
else
smb
=
0
;
if
(
ama
>
eps
&&
amb
>
eps
)
{
ama
=
sma
*
log10
(
ama
);
amb
=
smb
*
log10
(
amb
);
mmm
=
fabs
(
(
ama
-
amb
)
/
ama
);
if
(
result
<
mmm
)
result
=
mmm
;
}
ama
=
sma
*
log10
(
ama
);
amb
=
smb
*
log10
(
amb
);
mmm
=
fabs
(
(
ama
-
amb
)
/
ama
);
if
(
result
<
mmm
)
result
=
mmm
;
}
break
;
}
break
;
default
:
CV_Error
(
CV_StsBadArg
,
"Unknown comparison method"
);
}
return
result
;
}
CV_IMPL
double
cvMatchShapes
(
const
void
*
_contour1
,
const
void
*
_contour2
,
int
method
,
double
parameter
)
{
cv
::
AutoBuffer
<
double
>
abuf1
,
abuf2
;
cv
::
Mat
contour1
=
cv
::
cvarrToMat
(
_contour1
,
false
,
false
,
0
,
&
abuf1
);
cv
::
Mat
contour2
=
cv
::
cvarrToMat
(
_contour2
,
false
,
false
,
0
,
&
abuf2
);
return
cv
::
matchShapes
(
contour1
,
contour2
,
method
,
parameter
);
}
/* End of file. */
modules/imgproc/src/rotcalipers.cpp
View file @
dc4d0398
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel
License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corpor
ation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corpor
ation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
//
License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of OpenCV Found
ation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the OpenCV Found
ation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
typedef
struct
namespace
cv
{
int
bottom
;
int
left
;
float
height
;
float
width
;
float
base_a
;
float
base_b
;
}
icvMinAreaState
;
#define CV_CALIPERS_MAXHEIGHT 0
#define CV_CALIPERS_MINAREARECT 1
#define CV_CALIPERS_MAXDIST 2
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvRotatingCalipers
// Purpose:
// Rotating calipers algorithm with some applications
//
// Context:
// Parameters:
// points - convex hull vertices ( any orientation )
// n - number of vertices
// mode - concrete application of algorithm
// can be CV_CALIPERS_MAXDIST or
// CV_CALIPERS_MINAREARECT
// left, bottom, right, top - indexes of extremal points
// out - output info.
// In case CV_CALIPERS_MAXDIST it points to float value -
// maximal height of polygon.
// In case CV_CALIPERS_MINAREARECT
// ((CvPoint2D32f*)out)[0] - corner
// ((CvPoint2D32f*)out)[1] - vector1
// ((CvPoint2D32f*)out)[0] - corner2
//
// ^
// |
// vector2 |
// |
// |____________\
// corner /
// vector1
//
// Returns:
// Notes:
//F*/
/* we will use usual cartesian coordinates */
static
void
icvRotatingCalipers
(
CvPoint2D32f
*
points
,
int
n
,
int
mode
,
float
*
out
)
{
float
minarea
=
FLT_MAX
;
float
max_dist
=
0
;
char
buffer
[
32
]
=
{};
int
i
,
k
;
CvPoint2D32f
*
vect
=
(
CvPoint2D32f
*
)
cvAlloc
(
n
*
sizeof
(
vect
[
0
])
);
float
*
inv_vect_length
=
(
float
*
)
cvAlloc
(
n
*
sizeof
(
inv_vect_length
[
0
])
);
int
left
=
0
,
bottom
=
0
,
right
=
0
,
top
=
0
;
int
seq
[
4
]
=
{
-
1
,
-
1
,
-
1
,
-
1
};
/* rotating calipers sides will always have coordinates
(a,b) (-b,a) (-a,-b) (b, -a)
*/
/* this is a first base bector (a,b) initialized by (1,0) */
float
orientation
=
0
;
float
base_a
;
float
base_b
=
0
;
float
left_x
,
right_x
,
top_y
,
bottom_y
;
CvPoint2D32f
pt0
=
points
[
0
];
left_x
=
right_x
=
pt0
.
x
;
top_y
=
bottom_y
=
pt0
.
y
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
double
dx
,
dy
;
if
(
pt0
.
x
<
left_x
)
left_x
=
pt0
.
x
,
left
=
i
;
struct
MinAreaState
{
int
bottom
;
int
left
;
float
height
;
float
width
;
float
base_a
;
float
base_b
;
};
enum
{
CALIPERS_MAXHEIGHT
=
0
,
CALIPERS_MINAREARECT
=
1
,
CALIPERS_MAXDIST
=
2
};
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: rotatingCalipers
// Purpose:
// Rotating calipers algorithm with some applications
//
// Context:
// Parameters:
// points - convex hull vertices ( any orientation )
// n - number of vertices
// mode - concrete application of algorithm
// can be CV_CALIPERS_MAXDIST or
// CV_CALIPERS_MINAREARECT
// left, bottom, right, top - indexes of extremal points
// out - output info.
// In case CV_CALIPERS_MAXDIST it points to float value -
// maximal height of polygon.
// In case CV_CALIPERS_MINAREARECT
// ((CvPoint2D32f*)out)[0] - corner
// ((CvPoint2D32f*)out)[1] - vector1
// ((CvPoint2D32f*)out)[0] - corner2
//
// ^
// |
// vector2 |
// |
// |____________\
// corner /
// vector1
//
// Returns:
// Notes:
//F*/
/* we will use usual cartesian coordinates */
static
void
rotatingCalipers
(
const
Point2f
*
points
,
int
n
,
int
mode
,
float
*
out
)
{
float
minarea
=
FLT_MAX
;
float
max_dist
=
0
;
char
buffer
[
32
]
=
{};
int
i
,
k
;
AutoBuffer
<
float
>
buf
(
n
*
3
);
float
*
inv_vect_length
=
buf
;
Point2f
*
vect
=
(
Point2f
*
)(
inv_vect_length
+
n
);
int
left
=
0
,
bottom
=
0
,
right
=
0
,
top
=
0
;
int
seq
[
4
]
=
{
-
1
,
-
1
,
-
1
,
-
1
};
/* rotating calipers sides will always have coordinates
(a,b) (-b,a) (-a,-b) (b, -a)
*/
/* this is a first base bector (a,b) initialized by (1,0) */
float
orientation
=
0
;
float
base_a
;
float
base_b
=
0
;
float
left_x
,
right_x
,
top_y
,
bottom_y
;
Point2f
pt0
=
points
[
0
];
left_x
=
right_x
=
pt0
.
x
;
top_y
=
bottom_y
=
pt0
.
y
;
if
(
pt0
.
x
>
right_x
)
right_x
=
pt0
.
x
,
right
=
i
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
double
dx
,
dy
;
if
(
pt0
.
y
>
top_y
)
top_y
=
pt0
.
y
,
top
=
i
;
if
(
pt0
.
x
<
left_x
)
left_x
=
pt0
.
x
,
left
=
i
;
if
(
pt0
.
y
<
bottom_y
)
bottom_y
=
pt0
.
y
,
bottom
=
i
;
if
(
pt0
.
x
>
right_x
)
right_x
=
pt0
.
x
,
right
=
i
;
CvPoint2D32f
pt
=
points
[(
i
+
1
)
&
(
i
+
1
<
n
?
-
1
:
0
)];
if
(
pt0
.
y
>
top_y
)
top_y
=
pt0
.
y
,
top
=
i
;
dx
=
pt
.
x
-
pt0
.
x
;
dy
=
pt
.
y
-
pt0
.
y
;
if
(
pt0
.
y
<
bottom_y
)
bottom_y
=
pt0
.
y
,
bottom
=
i
;
vect
[
i
].
x
=
(
float
)
dx
;
vect
[
i
].
y
=
(
float
)
dy
;
inv_vect_length
[
i
]
=
(
float
)(
1.
/
sqrt
(
dx
*
dx
+
dy
*
dy
));
Point2f
pt
=
points
[(
i
+
1
)
&
(
i
+
1
<
n
?
-
1
:
0
)];
pt0
=
pt
;
}
dx
=
pt
.
x
-
pt0
.
x
;
dy
=
pt
.
y
-
pt0
.
y
;
//cvbInvSqrt( inv_vect_length, inv_vect_length, n );
vect
[
i
].
x
=
(
float
)
dx
;
vect
[
i
].
y
=
(
float
)
dy
;
inv_vect_length
[
i
]
=
(
float
)(
1.
/
sqrt
(
dx
*
dx
+
dy
*
dy
));
/* find convex hull orientation */
{
double
ax
=
vect
[
n
-
1
].
x
;
double
ay
=
vect
[
n
-
1
].
y
;
pt0
=
pt
;
}
for
(
i
=
0
;
i
<
n
;
i
++
)
// find convex hull orientation
{
double
bx
=
vect
[
i
].
x
;
double
by
=
vect
[
i
].
y
;
double
convexity
=
ax
*
by
-
ay
*
bx
;
double
ax
=
vect
[
n
-
1
].
x
;
double
ay
=
vect
[
n
-
1
].
y
;
if
(
convexity
!=
0
)
for
(
i
=
0
;
i
<
n
;
i
++
)
{
orientation
=
(
convexity
>
0
)
?
1.
f
:
(
-
1.
f
);
break
;
double
bx
=
vect
[
i
].
x
;
double
by
=
vect
[
i
].
y
;
double
convexity
=
ax
*
by
-
ay
*
bx
;
if
(
convexity
!=
0
)
{
orientation
=
(
convexity
>
0
)
?
1.
f
:
(
-
1.
f
);
break
;
}
ax
=
bx
;
ay
=
by
;
}
ax
=
bx
;
ay
=
by
;
CV_Assert
(
orientation
!=
0
);
}
assert
(
orientation
!=
0
);
}
base_a
=
orientation
;
/*****************************************************************************************/
/* init calipers position */
seq
[
0
]
=
bottom
;
seq
[
1
]
=
right
;
seq
[
2
]
=
top
;
seq
[
3
]
=
left
;
/*****************************************************************************************/
/* Main loop - evaluate angles and rotate calipers */
/* all of edges will be checked while rotating calipers by 90 degrees */
for
(
k
=
0
;
k
<
n
;
k
++
)
{
/* sinus of minimal angle */
/*float sinus;*/
/* compute cosine of angle between calipers side and polygon edge */
/* dp - dot product */
float
dp0
=
base_a
*
vect
[
seq
[
0
]].
x
+
base_b
*
vect
[
seq
[
0
]].
y
;
float
dp1
=
-
base_b
*
vect
[
seq
[
1
]].
x
+
base_a
*
vect
[
seq
[
1
]].
y
;
float
dp2
=
-
base_a
*
vect
[
seq
[
2
]].
x
-
base_b
*
vect
[
seq
[
2
]].
y
;
float
dp3
=
base_b
*
vect
[
seq
[
3
]].
x
-
base_a
*
vect
[
seq
[
3
]].
y
;
float
cosalpha
=
dp0
*
inv_vect_length
[
seq
[
0
]];
float
maxcos
=
cosalpha
;
/* number of calipers edges, that has minimal angle with edge */
int
main_element
=
0
;
/* choose minimal angle */
cosalpha
=
dp1
*
inv_vect_length
[
seq
[
1
]];
maxcos
=
(
cosalpha
>
maxcos
)
?
(
main_element
=
1
,
cosalpha
)
:
maxcos
;
cosalpha
=
dp2
*
inv_vect_length
[
seq
[
2
]];
maxcos
=
(
cosalpha
>
maxcos
)
?
(
main_element
=
2
,
cosalpha
)
:
maxcos
;
cosalpha
=
dp3
*
inv_vect_length
[
seq
[
3
]];
maxcos
=
(
cosalpha
>
maxcos
)
?
(
main_element
=
3
,
cosalpha
)
:
maxcos
;
/*rotate calipers*/
base_a
=
orientation
;
/*****************************************************************************************/
/* init calipers position */
seq
[
0
]
=
bottom
;
seq
[
1
]
=
right
;
seq
[
2
]
=
top
;
seq
[
3
]
=
left
;
/*****************************************************************************************/
/* Main loop - evaluate angles and rotate calipers */
/* all of edges will be checked while rotating calipers by 90 degrees */
for
(
k
=
0
;
k
<
n
;
k
++
)
{
//get next base
int
pindex
=
seq
[
main_element
];
float
lead_x
=
vect
[
pindex
].
x
*
inv_vect_length
[
pindex
];
float
lead_y
=
vect
[
pindex
].
y
*
inv_vect_length
[
pindex
];
switch
(
main_element
)
/* sinus of minimal angle */
/*float sinus;*/
/* compute cosine of angle between calipers side and polygon edge */
/* dp - dot product */
float
dp0
=
base_a
*
vect
[
seq
[
0
]].
x
+
base_b
*
vect
[
seq
[
0
]].
y
;
float
dp1
=
-
base_b
*
vect
[
seq
[
1
]].
x
+
base_a
*
vect
[
seq
[
1
]].
y
;
float
dp2
=
-
base_a
*
vect
[
seq
[
2
]].
x
-
base_b
*
vect
[
seq
[
2
]].
y
;
float
dp3
=
base_b
*
vect
[
seq
[
3
]].
x
-
base_a
*
vect
[
seq
[
3
]].
y
;
float
cosalpha
=
dp0
*
inv_vect_length
[
seq
[
0
]];
float
maxcos
=
cosalpha
;
/* number of calipers edges, that has minimal angle with edge */
int
main_element
=
0
;
/* choose minimal angle */
cosalpha
=
dp1
*
inv_vect_length
[
seq
[
1
]];
maxcos
=
(
cosalpha
>
maxcos
)
?
(
main_element
=
1
,
cosalpha
)
:
maxcos
;
cosalpha
=
dp2
*
inv_vect_length
[
seq
[
2
]];
maxcos
=
(
cosalpha
>
maxcos
)
?
(
main_element
=
2
,
cosalpha
)
:
maxcos
;
cosalpha
=
dp3
*
inv_vect_length
[
seq
[
3
]];
maxcos
=
(
cosalpha
>
maxcos
)
?
(
main_element
=
3
,
cosalpha
)
:
maxcos
;
/*rotate calipers*/
{
case
0
:
base_a
=
lead_x
;
base_b
=
lead_y
;
break
;
case
1
:
base_a
=
lead_y
;
base_b
=
-
lead_x
;
break
;
case
2
:
base_a
=
-
lead_x
;
base_b
=
-
lead_y
;
break
;
case
3
:
base_a
=
-
lead_y
;
base_b
=
lead_x
;
break
;
default:
assert
(
0
);
//get next base
int
pindex
=
seq
[
main_element
];
float
lead_x
=
vect
[
pindex
].
x
*
inv_vect_length
[
pindex
];
float
lead_y
=
vect
[
pindex
].
y
*
inv_vect_length
[
pindex
];
switch
(
main_element
)
{
case
0
:
base_a
=
lead_x
;
base_b
=
lead_y
;
break
;
case
1
:
base_a
=
lead_y
;
base_b
=
-
lead_x
;
break
;
case
2
:
base_a
=
-
lead_x
;
base_b
=
-
lead_y
;
break
;
case
3
:
base_a
=
-
lead_y
;
base_b
=
lead_x
;
break
;
default:
CV_Error
(
CV_StsError
,
"main_element should be 0, 1, 2 or 3"
);
}
}
}
/* change base point of main edge */
seq
[
main_element
]
+=
1
;
seq
[
main_element
]
=
(
seq
[
main_element
]
==
n
)
?
0
:
seq
[
main_element
];
switch
(
mode
)
{
case
CV_CALIPERS_MAXHEIGHT
:
{
/* now main element lies on edge alligned to calipers side */
/* find opposite element i.e. transform */
/* 0->2, 1->3, 2->0, 3->1 */
int
opposite_el
=
main_element
^
2
;
float
dx
=
points
[
seq
[
opposite_el
]].
x
-
points
[
seq
[
main_element
]].
x
;
float
dy
=
points
[
seq
[
opposite_el
]].
y
-
points
[
seq
[
main_element
]].
y
;
float
dist
;
if
(
main_element
&
1
)
dist
=
(
float
)
fabs
(
dx
*
base_a
+
dy
*
base_b
);
else
dist
=
(
float
)
fabs
(
dx
*
(
-
base_b
)
+
dy
*
base_a
);
/* change base point of main edge */
seq
[
main_element
]
+=
1
;
seq
[
main_element
]
=
(
seq
[
main_element
]
==
n
)
?
0
:
seq
[
main_element
];
if
(
dist
>
max_dist
)
max_dist
=
dist
;
break
;
}
case
CV_CALIPERS_MINAREARECT
:
/* find area of rectangle */
switch
(
mode
)
{
float
height
;
float
area
;
case
CALIPERS_MAXHEIGHT
:
{
/* now main element lies on edge alligned to calipers side */
/* find vector left-right
*/
float
dx
=
points
[
seq
[
1
]].
x
-
points
[
seq
[
3
]].
x
;
float
dy
=
points
[
seq
[
1
]].
y
-
points
[
seq
[
3
]].
y
;
/* find opposite element i.e. transform
*/
/* 0->2, 1->3, 2->0, 3->1 */
int
opposite_el
=
main_element
^
2
;
/* dotproduct */
float
width
=
dx
*
base_a
+
dy
*
base_b
;
float
dx
=
points
[
seq
[
opposite_el
]].
x
-
points
[
seq
[
main_element
]].
x
;
float
dy
=
points
[
seq
[
opposite_el
]].
y
-
points
[
seq
[
main_element
]].
y
;
float
dist
;
/* find vector left-right */
dx
=
points
[
seq
[
2
]].
x
-
points
[
seq
[
0
]].
x
;
dy
=
points
[
seq
[
2
]].
y
-
points
[
seq
[
0
]].
y
;
if
(
main_element
&
1
)
dist
=
(
float
)
fabs
(
dx
*
base_a
+
dy
*
base_b
);
else
dist
=
(
float
)
fabs
(
dx
*
(
-
base_b
)
+
dy
*
base_a
);
/* dotproduct */
height
=
-
dx
*
base_b
+
dy
*
base_a
;
if
(
dist
>
max_dist
)
max_dist
=
dist
;
area
=
width
*
height
;
if
(
area
<=
minarea
)
break
;
}
case
CALIPERS_MINAREARECT
:
/* find area of rectangle */
{
float
*
buf
=
(
float
*
)
buffer
;
minarea
=
area
;
/* leftist point */
((
int
*
)
buf
)[
0
]
=
seq
[
3
];
buf
[
1
]
=
base_a
;
buf
[
2
]
=
width
;
buf
[
3
]
=
base_b
;
buf
[
4
]
=
height
;
/* bottom point */
((
int
*
)
buf
)[
5
]
=
seq
[
0
];
buf
[
6
]
=
area
;
float
height
;
float
area
;
/* find vector left-right */
float
dx
=
points
[
seq
[
1
]].
x
-
points
[
seq
[
3
]].
x
;
float
dy
=
points
[
seq
[
1
]].
y
-
points
[
seq
[
3
]].
y
;
/* dotproduct */
float
width
=
dx
*
base_a
+
dy
*
base_b
;
/* find vector left-right */
dx
=
points
[
seq
[
2
]].
x
-
points
[
seq
[
0
]].
x
;
dy
=
points
[
seq
[
2
]].
y
-
points
[
seq
[
0
]].
y
;
/* dotproduct */
height
=
-
dx
*
base_b
+
dy
*
base_a
;
area
=
width
*
height
;
if
(
area
<=
minarea
)
{
float
*
buf
=
(
float
*
)
buffer
;
minarea
=
area
;
/* leftist point */
((
int
*
)
buf
)[
0
]
=
seq
[
3
];
buf
[
1
]
=
base_a
;
buf
[
2
]
=
width
;
buf
[
3
]
=
base_b
;
buf
[
4
]
=
height
;
/* bottom point */
((
int
*
)
buf
)[
5
]
=
seq
[
0
];
buf
[
6
]
=
area
;
}
break
;
}
break
;
}
}
/*switch */
}
/* for */
}
/*switch */
}
/* for */
switch
(
mode
)
{
case
CV_CALIPERS_MINAREARECT
:
switch
(
mode
)
{
float
*
buf
=
(
float
*
)
buffer
;
float
A1
=
buf
[
1
];
float
B1
=
buf
[
3
];
float
A2
=
-
buf
[
3
];
float
B2
=
buf
[
1
];
case
CALIPERS_MINAREARECT
:
{
float
*
buf
=
(
float
*
)
buffer
;
float
C1
=
A1
*
points
[((
int
*
)
buf
)[
0
]].
x
+
points
[((
int
*
)
buf
)[
0
]].
y
*
B1
;
float
C2
=
A2
*
points
[((
int
*
)
buf
)[
5
]].
x
+
points
[((
int
*
)
buf
)[
5
]].
y
*
B2
;
float
A1
=
buf
[
1
]
;
float
B1
=
buf
[
3
]
;
float
idet
=
1.
f
/
(
A1
*
B2
-
A2
*
B1
);
float
A2
=
-
buf
[
3
];
float
B2
=
buf
[
1
];
float
px
=
(
C1
*
B2
-
C2
*
B1
)
*
idet
;
float
py
=
(
A1
*
C2
-
A2
*
C1
)
*
idet
;
float
C1
=
A1
*
points
[((
int
*
)
buf
)[
0
]].
x
+
points
[((
int
*
)
buf
)[
0
]].
y
*
B1
;
float
C2
=
A2
*
points
[((
int
*
)
buf
)[
5
]].
x
+
points
[((
int
*
)
buf
)[
5
]].
y
*
B2
;
out
[
0
]
=
px
;
out
[
1
]
=
py
;
float
idet
=
1.
f
/
(
A1
*
B2
-
A2
*
B1
);
out
[
2
]
=
A1
*
buf
[
2
]
;
out
[
3
]
=
B1
*
buf
[
2
]
;
float
px
=
(
C1
*
B2
-
C2
*
B1
)
*
idet
;
float
py
=
(
A1
*
C2
-
A2
*
C1
)
*
idet
;
out
[
4
]
=
A2
*
buf
[
4
];
out
[
5
]
=
B2
*
buf
[
4
];
}
break
;
case
CV_CALIPERS_MAXHEIGHT
:
{
out
[
0
]
=
max_dist
;
out
[
0
]
=
px
;
out
[
1
]
=
py
;
out
[
2
]
=
A1
*
buf
[
2
];
out
[
3
]
=
B1
*
buf
[
2
];
out
[
4
]
=
A2
*
buf
[
4
];
out
[
5
]
=
B2
*
buf
[
4
];
}
break
;
case
CALIPERS_MAXHEIGHT
:
{
out
[
0
]
=
max_dist
;
}
break
;
}
break
;
}
cvFree
(
&
vect
);
cvFree
(
&
inv_vect_length
);
}
CV_IMPL
CvBox2D
cvMinAreaRect2
(
const
CvArr
*
array
,
CvMemStorage
*
storage
)
cv
::
RotatedRect
cv
::
minAreaRect
(
InputArray
_points
)
{
cv
::
Ptr
<
CvMemStorage
>
temp_storage
;
CvBox2D
box
;
cv
::
AutoBuffer
<
CvPoint2D32f
>
_points
;
CvPoint2D32f
*
points
;
memset
(
&
box
,
0
,
sizeof
(
box
));
int
i
,
n
;
CvSeqReader
reader
;
CvContour
contour_header
;
CvSeqBlock
block
;
CvSeq
*
ptseq
=
(
CvSeq
*
)
array
;
CvPoint2D32f
out
[
3
];
if
(
CV_IS_SEQ
(
ptseq
)
)
{
if
(
!
CV_IS_SEQ_POINT_SET
(
ptseq
)
&&
(
CV_SEQ_KIND
(
ptseq
)
!=
CV_SEQ_KIND_CURVE
||
CV_SEQ_ELTYPE
(
ptseq
)
!=
CV_SEQ_ELTYPE_PPOINT
))
CV_Error
(
CV_StsUnsupportedFormat
,
"Input sequence must consist of 2d points or pointers to 2d points"
);
if
(
!
storage
)
storage
=
ptseq
->
storage
;
}
else
{
ptseq
=
cvPointSeqFromMat
(
CV_SEQ_KIND_GENERIC
,
array
,
&
contour_header
,
&
block
);
}
if
(
storage
)
{
temp_storage
=
cvCreateChildMemStorage
(
storage
);
}
else
Mat
hull
;
Point2f
out
[
3
];
RotatedRect
box
;
convexHull
(
_points
,
hull
,
true
,
true
);
if
(
hull
.
depth
()
!=
CV_32F
)
{
temp_storage
=
cvCreateMemStorage
(
1
<<
10
);
Mat
temp
;
hull
.
convertTo
(
temp
,
CV_32F
);
hull
=
temp
;
}
ptseq
=
cvConvexHull2
(
ptseq
,
temp_storage
,
CV_CLOCKWISE
,
1
);
n
=
ptseq
->
total
;
_points
.
allocate
(
n
);
points
=
_points
;
cvStartReadSeq
(
ptseq
,
&
reader
);
if
(
CV_SEQ_ELTYPE
(
ptseq
)
==
CV_32SC2
)
{
for
(
i
=
0
;
i
<
n
;
i
++
)
{
CvPoint
pt
;
CV_READ_SEQ_ELEM
(
pt
,
reader
);
points
[
i
].
x
=
(
float
)
pt
.
x
;
points
[
i
].
y
=
(
float
)
pt
.
y
;
}
}
else
{
for
(
i
=
0
;
i
<
n
;
i
++
)
{
CV_READ_SEQ_ELEM
(
points
[
i
],
reader
);
}
}
int
n
=
hull
.
checkVector
(
2
);
const
Point2f
*
hpoints
=
(
const
Point2f
*
)
hull
.
data
;
if
(
n
>
2
)
{
icvRotatingCalipers
(
points
,
n
,
CV_
CALIPERS_MINAREARECT
,
(
float
*
)
out
);
rotatingCalipers
(
hpoints
,
n
,
CALIPERS_MINAREARECT
,
(
float
*
)
out
);
box
.
center
.
x
=
out
[
0
].
x
+
(
out
[
1
].
x
+
out
[
2
].
x
)
*
0.5
f
;
box
.
center
.
y
=
out
[
0
].
y
+
(
out
[
1
].
y
+
out
[
2
].
y
)
*
0.5
f
;
box
.
size
.
width
=
(
float
)
sqrt
((
double
)
out
[
1
].
x
*
out
[
1
].
x
+
(
double
)
out
[
1
].
y
*
out
[
1
].
y
);
...
...
@@ -421,10 +370,10 @@ cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
}
else
if
(
n
==
2
)
{
box
.
center
.
x
=
(
points
[
0
].
x
+
points
[
1
].
x
)
*
0.5
f
;
box
.
center
.
y
=
(
points
[
0
].
y
+
points
[
1
].
y
)
*
0.5
f
;
double
dx
=
points
[
1
].
x
-
points
[
0
].
x
;
double
dy
=
points
[
1
].
y
-
points
[
0
].
y
;
box
.
center
.
x
=
(
hpoints
[
0
].
x
+
h
points
[
1
].
x
)
*
0.5
f
;
box
.
center
.
y
=
(
hpoints
[
0
].
y
+
h
points
[
1
].
y
)
*
0.5
f
;
double
dx
=
hpoints
[
1
].
x
-
hpoints
[
0
].
x
;
double
dy
=
hpoints
[
1
].
y
-
h
points
[
0
].
y
;
box
.
size
.
width
=
(
float
)
sqrt
(
dx
*
dx
+
dy
*
dy
);
box
.
size
.
height
=
0
;
box
.
angle
=
(
float
)
atan2
(
dy
,
dx
);
...
...
@@ -432,10 +381,21 @@ cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
else
{
if
(
n
==
1
)
box
.
center
=
points
[
0
];
box
.
center
=
h
points
[
0
];
}
box
.
angle
=
(
float
)(
box
.
angle
*
180
/
CV_PI
);
return
box
;
}
CV_IMPL
CvBox2D
cvMinAreaRect2
(
const
CvArr
*
array
,
CvMemStorage
*
storage
)
{
cv
::
AutoBuffer
<
double
>
abuf
;
cv
::
Mat
points
=
cv
::
cvarrToMat
(
array
,
false
,
false
,
0
,
&
abuf
);
cv
::
RotatedRect
rr
=
cv
::
minAreaRect
(
points
);
return
(
CvBox2D
)
rr
;
}
modules/imgproc/src/shapedescr.cpp
View file @
dc4d0398
...
...
@@ -40,97 +40,25 @@
//M*/
#include "precomp.hpp"
/* calculates length of a curve (e.g. contour perimeter) */
CV_IMPL
double
cvArcLength
(
const
void
*
array
,
CvSlice
slice
,
int
is_closed
)
namespace
cv
{
double
perimeter
=
0
;
int
i
,
j
=
0
,
count
;
const
int
N
=
16
;
float
buf
[
N
];
CvMat
buffer
=
cvMat
(
1
,
N
,
CV_32F
,
buf
);
CvSeqReader
reader
;
CvContour
contour_header
;
CvSeq
*
contour
=
0
;
CvSeqBlock
block
;
static
int
intersectLines
(
double
x1
,
double
dx1
,
double
y1
,
double
dy1
,
double
x2
,
double
dx2
,
double
y2
,
double
dy2
,
double
*
t2
)
{
double
d
=
dx1
*
dy2
-
dx2
*
dy1
;
int
result
=
-
1
;
if
(
CV_IS_SEQ
(
array
))
{
contour
=
(
CvSeq
*
)
array
;
if
(
!
CV_IS_SEQ_POLYLINE
(
contour
))
CV_Error
(
CV_StsBadArg
,
"Unsupported sequence type"
);
if
(
is_closed
<
0
)
is_closed
=
CV_IS_SEQ_CLOSED
(
contour
);
}
else
if
(
d
!=
0
)
{
is_closed
=
is_closed
>
0
;
contour
=
cvPointSeqFromMat
(
CV_SEQ_KIND_CURVE
|
(
is_closed
?
CV_SEQ_FLAG_CLOSED
:
0
),
array
,
&
contour_header
,
&
block
);
*
t2
=
((
x2
-
x1
)
*
dy1
-
(
y2
-
y1
)
*
dx1
)
/
d
;
result
=
0
;
}
if
(
contour
->
total
>
1
)
{
int
is_float
=
CV_SEQ_ELTYPE
(
contour
)
==
CV_32FC2
;
cvStartReadSeq
(
contour
,
&
reader
,
0
);
cvSetSeqReaderPos
(
&
reader
,
slice
.
start_index
);
count
=
cvSliceLength
(
slice
,
contour
);
count
-=
!
is_closed
&&
count
==
contour
->
total
;
/* scroll the reader by 1 point */
reader
.
prev_elem
=
reader
.
ptr
;
CV_NEXT_SEQ_ELEM
(
sizeof
(
CvPoint
),
reader
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
float
dx
,
dy
;
if
(
!
is_float
)
{
CvPoint
*
pt
=
(
CvPoint
*
)
reader
.
ptr
;
CvPoint
*
prev_pt
=
(
CvPoint
*
)
reader
.
prev_elem
;
dx
=
(
float
)
pt
->
x
-
(
float
)
prev_pt
->
x
;
dy
=
(
float
)
pt
->
y
-
(
float
)
prev_pt
->
y
;
}
else
{
CvPoint2D32f
*
pt
=
(
CvPoint2D32f
*
)
reader
.
ptr
;
CvPoint2D32f
*
prev_pt
=
(
CvPoint2D32f
*
)
reader
.
prev_elem
;
dx
=
pt
->
x
-
prev_pt
->
x
;
dy
=
pt
->
y
-
prev_pt
->
y
;
}
reader
.
prev_elem
=
reader
.
ptr
;
CV_NEXT_SEQ_ELEM
(
contour
->
elem_size
,
reader
);
// Bugfix by Axel at rubico.com 2010-03-22, affects closed slices only
// wraparound not handled by CV_NEXT_SEQ_ELEM
if
(
is_closed
&&
i
==
count
-
2
)
cvSetSeqReaderPos
(
&
reader
,
slice
.
start_index
);
buffer
.
data
.
fl
[
j
]
=
dx
*
dx
+
dy
*
dy
;
if
(
++
j
==
N
||
i
==
count
-
1
)
{
buffer
.
cols
=
j
;
cvPow
(
&
buffer
,
&
buffer
,
0.5
);
for
(
;
j
>
0
;
j
--
)
perimeter
+=
buffer
.
data
.
fl
[
j
-
1
];
}
}
}
return
perimeter
;
return
result
;
}
static
CvStatus
icvFindCircle
(
CvPoint2D32f
pt0
,
CvPoint2D32f
pt1
,
CvPoint2D32f
pt2
,
CvPoint2D32f
*
center
,
float
*
radius
)
static
bool
findCircle
(
Point2f
pt0
,
Point2f
pt1
,
Point2f
pt2
,
Point2f
*
center
,
float
*
radius
)
{
double
x1
=
(
pt0
.
x
+
pt1
.
x
)
*
0.5
;
double
dy1
=
pt0
.
x
-
pt1
.
x
;
...
...
@@ -142,26 +70,21 @@ icvFindCircle( CvPoint2D32f pt0, CvPoint2D32f pt1,
double
dx2
=
pt2
.
y
-
pt1
.
y
;
double
t
=
0
;
CvStatus
result
=
CV_OK
;
if
(
icvIntersectLines
(
x1
,
dx1
,
y1
,
dy1
,
x2
,
dx2
,
y2
,
dy2
,
&
t
)
>=
0
)
if
(
intersectLines
(
x1
,
dx1
,
y1
,
dy1
,
x2
,
dx2
,
y2
,
dy2
,
&
t
)
>=
0
)
{
center
->
x
=
(
float
)
(
x2
+
dx2
*
t
);
center
->
y
=
(
float
)
(
y2
+
dy2
*
t
);
*
radius
=
(
float
)
icvDistanceL2_32f
(
*
center
,
pt0
);
}
else
{
center
->
x
=
center
->
y
=
0.
f
;
radius
=
0
;
result
=
CV_NOTDEFINED_ERR
;
*
radius
=
(
float
)
norm
(
*
center
-
pt0
);
return
true
;
}
return
result
;
center
->
x
=
center
->
y
=
0.
f
;
radius
=
0
;
return
false
;
}
CV_INLINE
double
icvIsPtInCircle
(
CvPoint2D32f
pt
,
CvPoint2D3
2f
center
,
float
radius
)
static
double
pointInCircle
(
Point2f
pt
,
Point
2f
center
,
float
radius
)
{
double
dx
=
pt
.
x
-
center
.
x
;
double
dy
=
pt
.
y
-
center
.
y
;
...
...
@@ -169,18 +92,17 @@ CV_INLINE double icvIsPtInCircle( CvPoint2D32f pt, CvPoint2D32f center, float ra
}
static
int
icvFindEnslosingCicle4pts_32f
(
CvPoint2D32f
*
pts
,
CvPoint2D32f
*
_center
,
float
*
_radius
)
static
int
findEnslosingCicle4pts_32f
(
Point2f
*
pts
,
Point2f
&
_center
,
float
&
_radius
)
{
int
shuffles
[
4
][
4
]
=
{
{
0
,
1
,
2
,
3
},
{
0
,
1
,
3
,
2
},
{
2
,
3
,
0
,
1
},
{
2
,
3
,
1
,
0
}
};
int
idxs
[
4
]
=
{
0
,
1
,
2
,
3
};
int
i
,
j
,
k
=
1
,
mi
=
0
;
float
max_dist
=
0
;
CvPoint2D3
2f
center
;
CvPoint2D3
2f
min_center
;
Point
2f
center
;
Point
2f
min_center
;
float
radius
,
min_radius
=
FLT_MAX
;
CvPoint2D3
2f
res_pts
[
4
];
Point
2f
res_pts
[
4
];
center
=
min_center
=
pts
[
0
];
radius
=
1.
f
;
...
...
@@ -188,7 +110,7 @@ icvFindEnslosingCicle4pts_32f( CvPoint2D32f * pts, CvPoint2D32f * _center, float
for
(
i
=
0
;
i
<
4
;
i
++
)
for
(
j
=
i
+
1
;
j
<
4
;
j
++
)
{
float
dist
=
icvDistanceL2_32f
(
pts
[
i
],
pts
[
j
]
);
float
dist
=
norm
(
pts
[
i
]
-
pts
[
j
]
);
if
(
max_dist
<
dist
)
{
...
...
@@ -198,65 +120,62 @@ icvFindEnslosingCicle4pts_32f( CvPoint2D32f * pts, CvPoint2D32f * _center, float
}
}
if
(
max_dist
==
0
)
goto
function_exit
;
k
=
2
;
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
max_dist
>
0
)
{
for
(
j
=
0
;
j
<
k
;
j
++
)
if
(
i
==
idxs
[
j
]
)
break
;
if
(
j
==
k
)
idxs
[
k
++
]
=
i
;
}
k
=
2
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
for
(
j
=
0
;
j
<
k
;
j
++
)
if
(
i
==
idxs
[
j
]
)
break
;
if
(
j
==
k
)
idxs
[
k
++
]
=
i
;
}
center
=
cvPoint2D32f
(
(
pts
[
idxs
[
0
]].
x
+
pts
[
idxs
[
1
]].
x
)
*
0.5
f
,
(
pts
[
idxs
[
0
]].
y
+
pts
[
idxs
[
1
]].
y
)
*
0.5
f
);
radius
=
(
float
)(
icvDistanceL2_32f
(
pts
[
idxs
[
0
]],
center
)
*
1.03
);
if
(
radius
<
1.
f
)
radius
=
1.
f
;
center
=
Point2f
(
(
pts
[
idxs
[
0
]].
x
+
pts
[
idxs
[
1
]].
x
)
*
0.5
f
,
(
pts
[
idxs
[
0
]].
y
+
pts
[
idxs
[
1
]].
y
)
*
0.5
f
);
radius
=
(
float
)(
norm
(
pts
[
idxs
[
0
]]
-
center
)
*
1.03
);
if
(
radius
<
1.
f
)
radius
=
1.
f
;
if
(
icvIsPtInCircle
(
pts
[
idxs
[
2
]],
center
,
radius
)
>=
0
&&
icvIsPtInCircle
(
pts
[
idxs
[
3
]],
center
,
radius
)
>=
0
)
{
k
=
2
;
//rand()%2+2;
}
else
{
mi
=
-
1
;
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
pointInCircle
(
pts
[
idxs
[
2
]],
center
,
radius
)
>=
0
&&
pointInCircle
(
pts
[
idxs
[
3
]],
center
,
radius
)
>=
0
)
{
if
(
icvFindCircle
(
pts
[
shuffles
[
i
][
0
]],
pts
[
shuffles
[
i
][
1
]],
pts
[
shuffles
[
i
][
2
]],
&
center
,
&
radius
)
>=
0
)
k
=
2
;
//rand()%2+2;
}
else
{
mi
=
-
1
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
radius
*=
1.03
f
;
if
(
radius
<
2.
f
)
radius
=
2.
f
;
if
(
icvIsPtInCircle
(
pts
[
shuffles
[
i
][
3
]],
center
,
radius
)
>=
0
&&
min_radius
>
radius
)
if
(
findCircle
(
pts
[
shuffles
[
i
][
0
]],
pts
[
shuffles
[
i
][
1
]],
pts
[
shuffles
[
i
][
2
]],
&
center
,
&
radius
)
>=
0
)
{
min_radius
=
radius
;
min_center
=
center
;
mi
=
i
;
radius
*=
1.03
f
;
if
(
radius
<
2.
f
)
radius
=
2.
f
;
if
(
pointInCircle
(
pts
[
shuffles
[
i
][
3
]],
center
,
radius
)
>=
0
&&
min_radius
>
radius
)
{
min_radius
=
radius
;
min_center
=
center
;
mi
=
i
;
}
}
}
CV_Assert
(
mi
>=
0
);
if
(
mi
<
0
)
mi
=
0
;
k
=
3
;
center
=
min_center
;
radius
=
min_radius
;
for
(
i
=
0
;
i
<
4
;
i
++
)
idxs
[
i
]
=
shuffles
[
mi
][
i
];
}
assert
(
mi
>=
0
);
if
(
mi
<
0
)
mi
=
0
;
k
=
3
;
center
=
min_center
;
radius
=
min_radius
;
for
(
i
=
0
;
i
<
4
;
i
++
)
idxs
[
i
]
=
shuffles
[
mi
][
i
];
}
function_exit:
*
_center
=
center
;
*
_radius
=
radius
;
_center
=
center
;
_radius
=
radius
;
/* reorder output points */
for
(
i
=
0
;
i
<
4
;
i
++
)
...
...
@@ -265,159 +184,88 @@ icvFindEnslosingCicle4pts_32f( CvPoint2D32f * pts, CvPoint2D32f * _center, float
for
(
i
=
0
;
i
<
4
;
i
++
)
{
pts
[
i
]
=
res_pts
[
i
];
assert
(
icvIsP
tInCircle
(
pts
[
i
],
center
,
radius
)
>=
0
);
CV_Assert
(
poin
tInCircle
(
pts
[
i
],
center
,
radius
)
>=
0
);
}
return
k
;
}
}
CV_IMPL
int
cvMinEnclosingCircle
(
const
void
*
array
,
CvPoint2D32f
*
_center
,
float
*
_radius
)
void
cv
::
minEnclosingCircle
(
InputArray
_points
,
Point2f
&
_center
,
float
&
_radius
)
{
const
int
max_iters
=
100
;
int
max_iters
=
100
;
const
float
eps
=
FLT_EPSILON
*
2
;
CvPoint2D32f
center
=
{
0
,
0
};
float
radius
=
0
;
int
result
=
0
;
bool
result
=
false
;
Mat
points
=
_points
.
getMat
();
int
i
,
j
,
k
,
count
=
points
.
checkVector
(
2
);
int
depth
=
points
.
depth
();
Point2f
center
;
float
radius
=
0.
f
;
CV_Assert
(
count
>=
0
&&
(
depth
==
CV_32F
||
depth
==
CV_32S
));
if
(
_center
)
_center
->
x
=
_center
->
y
=
0.
f
;
if
(
_radius
)
*
_radius
=
0
;
CvSeqReader
reader
;
int
k
,
count
;
CvPoint2D32f
pts
[
8
];
CvContour
contour_header
;
CvSeqBlock
block
;
CvSeq
*
sequence
=
0
;
int
is_float
;
if
(
!
_center
||
!
_radius
)
CV_Error
(
CV_StsNullPtr
,
"Null center or radius pointers"
);
if
(
CV_IS_SEQ
(
array
)
)
{
sequence
=
(
CvSeq
*
)
array
;
if
(
!
CV_IS_SEQ_POINT_SET
(
sequence
))
CV_Error
(
CV_StsBadArg
,
"The passed sequence is not a valid contour"
);
}
else
{
sequence
=
cvPointSeqFromMat
(
CV_SEQ_KIND_GENERIC
,
array
,
&
contour_header
,
&
block
);
}
_center
.
x
=
_center
.
y
=
0.
f
;
_radius
=
0.
f
;
if
(
sequence
->
total
<
=
0
)
CV_Error
(
CV_StsBadSize
,
""
)
;
if
(
count
=
=
0
)
return
;
cvStartReadSeq
(
sequence
,
&
reader
,
0
);
bool
is_float
=
depth
==
CV_32F
;
const
Point
*
ptsi
=
(
const
Point
*
)
points
.
data
;
const
Point2f
*
ptsf
=
(
const
Point2f
*
)
points
.
data
;
count
=
sequence
->
total
;
is_float
=
CV_SEQ_ELTYPE
(
sequence
)
==
CV_32FC2
;
Point2f
pt
=
is_float
?
ptsf
[
0
]
:
Point2f
((
float
)
ptsi
[
0
].
x
,(
float
)
ptsi
[
0
].
y
)
;
Point2f
pts
[
4
]
=
{
pt
,
pt
,
pt
,
pt
}
;
if
(
!
is_float
)
for
(
int
i
=
1
;
i
<
count
;
i
++
)
{
CvPoint
*
pt_left
,
*
pt_right
,
*
pt_top
,
*
pt_bottom
;
CvPoint
pt
;
pt_left
=
pt_right
=
pt_top
=
pt_bottom
=
(
CvPoint
*
)(
reader
.
ptr
);
CV_READ_SEQ_ELEM
(
pt
,
reader
);
for
(
int
i
=
1
;
i
<
count
;
i
++
)
{
CvPoint
*
pt_ptr
=
(
CvPoint
*
)
reader
.
ptr
;
CV_READ_SEQ_ELEM
(
pt
,
reader
);
if
(
pt
.
x
<
pt_left
->
x
)
pt_left
=
pt_ptr
;
if
(
pt
.
x
>
pt_right
->
x
)
pt_right
=
pt_ptr
;
if
(
pt
.
y
<
pt_top
->
y
)
pt_top
=
pt_ptr
;
if
(
pt
.
y
>
pt_bottom
->
y
)
pt_bottom
=
pt_ptr
;
}
pts
[
0
]
=
cvPointTo32f
(
*
pt_left
);
pts
[
1
]
=
cvPointTo32f
(
*
pt_right
);
pts
[
2
]
=
cvPointTo32f
(
*
pt_top
);
pts
[
3
]
=
cvPointTo32f
(
*
pt_bottom
);
}
else
{
CvPoint2D32f
*
pt_left
,
*
pt_right
,
*
pt_top
,
*
pt_bottom
;
CvPoint2D32f
pt
;
pt_left
=
pt_right
=
pt_top
=
pt_bottom
=
(
CvPoint2D32f
*
)
(
reader
.
ptr
);
CV_READ_SEQ_ELEM
(
pt
,
reader
);
for
(
int
i
=
1
;
i
<
count
;
i
++
)
{
CvPoint2D32f
*
pt_ptr
=
(
CvPoint2D32f
*
)
reader
.
ptr
;
CV_READ_SEQ_ELEM
(
pt
,
reader
);
if
(
pt
.
x
<
pt_left
->
x
)
pt_left
=
pt_ptr
;
if
(
pt
.
x
>
pt_right
->
x
)
pt_right
=
pt_ptr
;
if
(
pt
.
y
<
pt_top
->
y
)
pt_top
=
pt_ptr
;
if
(
pt
.
y
>
pt_bottom
->
y
)
pt_bottom
=
pt_ptr
;
}
pts
[
0
]
=
*
pt_left
;
pts
[
1
]
=
*
pt_right
;
pts
[
2
]
=
*
pt_top
;
pts
[
3
]
=
*
pt_bottom
;
Point2f
pt
=
is_float
?
ptsf
[
i
]
:
Point2f
((
float
)
ptsi
[
i
].
x
,
(
float
)
ptsi
[
i
].
y
);
if
(
pt
.
x
<
pts
[
0
].
x
)
pts
[
0
]
=
pt
;
if
(
pt
.
x
>
pts
[
1
].
x
)
pts
[
1
]
=
pt
;
if
(
pt
.
y
<
pts
[
2
].
y
)
pts
[
2
]
=
pt
;
if
(
pt
.
y
>
pts
[
3
].
y
)
pts
[
3
]
=
pt
;
}
for
(
k
=
0
;
k
<
max_iters
;
k
++
)
{
double
min_delta
=
0
,
delta
;
CvPoint2D32f
ptfl
,
farAway
=
{
0
,
0
}
;
Point2f
ptf
,
farAway
(
0
,
0
)
;
/*only for first iteration because the alg is repared at the loop's foot*/
if
(
k
==
0
)
icvFindEnslosingCicle4pts_32f
(
pts
,
&
center
,
&
radius
);
cvStartReadSeq
(
sequence
,
&
reader
,
0
);
if
(
k
==
0
)
findEnslosingCicle4pts_32f
(
pts
,
center
,
radius
);
for
(
int
i
=
0
;
i
<
count
;
i
++
)
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
!
is_float
)
{
ptfl
.
x
=
(
float
)((
CvPoint
*
)
reader
.
ptr
)
->
x
;
ptfl
.
y
=
(
float
)((
CvPoint
*
)
reader
.
ptr
)
->
y
;
}
else
{
ptfl
=
*
(
CvPoint2D32f
*
)
reader
.
ptr
;
}
CV_NEXT_SEQ_ELEM
(
sequence
->
elem_size
,
reader
);
ptf
=
is_float
?
ptsf
[
i
]
:
Point2f
((
float
)
ptsi
[
i
].
x
,(
float
)
ptsi
[
i
].
y
);
delta
=
icvIsPtInCircle
(
ptfl
,
center
,
radius
);
delta
=
pointInCircle
(
ptf
,
center
,
radius
);
if
(
delta
<
min_delta
)
{
min_delta
=
delta
;
farAway
=
ptf
l
;
farAway
=
ptf
;
}
}
result
=
min_delta
>=
0
;
if
(
result
)
break
;
CvPoint2D3
2f
ptsCopy
[
4
];
/
*
find good replacement partner for the point which is at most far away,
starting with the one that lays in the actual circle (i=3) */
for
(
int
i
=
3
;
i
>=
0
;
i
--
)
Point
2f
ptsCopy
[
4
];
/
/
find good replacement partner for the point which is at most far away,
// starting with the one that lays in the actual circle (i=3)
for
(
i
=
3
;
i
>=
0
;
i
--
)
{
for
(
int
j
=
0
;
j
<
4
;
j
++
)
{
ptsCopy
[
j
]
=
(
i
!=
j
)
?
pts
[
j
]
:
farAway
;
}
for
(
j
=
0
;
j
<
4
;
j
++
)
ptsCopy
[
j
]
=
i
!=
j
?
pts
[
j
]
:
farAway
;
icvFindEnslosingCicle4pts_32f
(
ptsCopy
,
&
center
,
&
radius
);
if
(
icvIsPtInCircle
(
pts
[
i
],
center
,
radius
)
>=
0
){
// replaced one again in the new circle?
findEnslosingCicle4pts_32f
(
ptsCopy
,
center
,
radius
);
if
(
pointInCircle
(
pts
[
i
],
center
,
radius
)
>=
0
)
{
// replaced one again in the new circle?
pts
[
i
]
=
farAway
;
break
;
}
...
...
@@ -426,121 +274,462 @@ cvMinEnclosingCircle( const void* array, CvPoint2D32f * _center, float *_radius
if
(
!
result
)
{
cvStartReadSeq
(
sequence
,
&
reader
,
0
);
radius
=
0.
f
;
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
CvPoint2D32f
ptfl
;
float
t
,
dx
,
dy
;
Point2f
ptf
=
is_float
?
ptsf
[
i
]
:
Point2f
((
float
)
ptsi
[
i
].
x
,(
float
)
ptsi
[
i
].
y
);
float
dx
=
center
.
x
-
ptf
.
x
,
dy
=
center
.
y
-
ptf
.
y
;
float
t
=
dx
*
dx
+
dy
*
dy
;
radius
=
MAX
(
radius
,
t
);
}
if
(
!
is_float
)
{
ptfl
.
x
=
(
float
)((
CvPoint
*
)
reader
.
ptr
)
->
x
;
ptfl
.
y
=
(
float
)((
CvPoint
*
)
reader
.
ptr
)
->
y
;
}
else
{
ptfl
=
*
(
CvPoint2D32f
*
)
reader
.
ptr
;
}
radius
=
(
float
)(
sqrt
(
radius
)
*
(
1
+
eps
));
}
_center
=
center
;
_radius
=
radius
;
}
// calculates length of a curve (e.g. contour perimeter)
double
cv
::
arcLength
(
InputArray
_curve
,
bool
is_closed
)
{
Mat
curve
=
_curve
.
getMat
();
int
count
=
curve
.
checkVector
(
2
);
int
depth
=
curve
.
depth
();
CV_Assert
(
count
>=
0
&&
(
depth
==
CV_32F
||
depth
==
CV_32S
));
double
perimeter
=
0
;
CV_NEXT_SEQ_ELEM
(
sequence
->
elem_size
,
reader
);
dx
=
center
.
x
-
ptfl
.
x
;
dy
=
center
.
y
-
ptfl
.
y
;
t
=
dx
*
dx
+
dy
*
dy
;
radius
=
MAX
(
radius
,
t
);
int
i
,
j
=
0
;
const
int
N
=
16
;
float
buf
[
N
];
if
(
count
<=
1
)
return
0.
;
bool
is_float
=
depth
==
CV_32F
;
int
last
=
is_closed
?
count
-
1
:
0
;
const
Point
*
pti
=
(
const
Point
*
)
curve
.
data
;
const
Point2f
*
ptf
=
(
const
Point2f
*
)
curve
.
data
;
Point2f
prev
=
is_float
?
ptf
[
last
]
:
Point2f
((
float
)
pti
[
last
].
x
,(
float
)
pti
[
last
].
y
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
Point2f
p
=
is_float
?
ptf
[
i
]
:
Point2f
((
float
)
pti
[
i
].
x
,(
float
)
pti
[
i
].
y
);
float
dx
=
p
.
x
-
prev
.
x
,
dy
=
p
.
y
-
prev
.
y
;
buf
[
j
]
=
dx
*
dx
+
dy
*
dy
;
if
(
++
j
==
N
||
i
==
count
-
1
)
{
Mat
bufmat
(
1
,
j
,
CV_32F
,
buf
);
sqrt
(
bufmat
,
bufmat
);
for
(
;
j
>
0
;
j
--
)
perimeter
+=
buf
[
j
-
1
];
}
prev
=
p
;
}
radius
=
(
float
)(
sqrt
(
radius
)
*
(
1
+
eps
));
result
=
1
;
return
perimeter
;
}
// area of a whole sequence
double
cv
::
contourArea
(
InputArray
_contour
,
bool
oriented
)
{
Mat
contour
=
_contour
.
getMat
();
int
npoints
=
contour
.
checkVector
(
2
);
int
depth
=
contour
.
depth
();
CV_Assert
(
npoints
>=
0
&&
(
depth
==
CV_32F
||
depth
==
CV_32S
));
if
(
npoints
==
0
)
return
0.
;
double
a00
=
0
;
bool
is_float
=
depth
==
CV_32F
;
const
Point
*
ptsi
=
(
const
Point
*
)
contour
.
data
;
const
Point2f
*
ptsf
=
(
const
Point2f
*
)
contour
.
data
;
Point2f
prev
=
is_float
?
ptsf
[
npoints
-
1
]
:
Point2f
((
float
)
ptsi
[
npoints
-
1
].
x
,
(
float
)
ptsi
[
npoints
-
1
].
y
);
for
(
int
i
=
0
;
i
<
npoints
;
i
++
)
{
Point2f
p
=
is_float
?
ptsf
[
i
]
:
Point2f
((
float
)
ptsi
[
i
].
x
,
(
float
)
ptsi
[
i
].
y
);
a00
+=
(
double
)
prev
.
x
*
p
.
y
-
(
double
)
prev
.
y
*
p
.
x
;
prev
=
p
;
}
*
_center
=
center
;
*
_radius
=
radius
;
a00
*=
0.5
;
if
(
!
oriented
)
a00
=
fabs
(
a00
);
return
result
;
return
a00
;
}
/* area of a whole sequence */
static
CvStatus
icvContourArea
(
const
CvSeq
*
contour
,
double
*
area
)
cv
::
RotatedRect
cv
::
fitEllipse
(
InputArray
_points
)
{
if
(
contour
->
total
)
Mat
points
=
_points
.
getMat
();
int
i
,
n
=
points
.
checkVector
(
2
);
int
depth
=
points
.
depth
();
CV_Assert
(
n
>=
0
&&
(
depth
==
CV_32F
||
depth
==
CV_32S
));
RotatedRect
box
;
if
(
n
<
5
)
CV_Error
(
CV_StsBadSize
,
"There should be at least 5 points to fit the ellipse"
);
// New fitellipse algorithm, contributed by Dr. Daniel Weiss
Point2f
c
(
0
,
0
);
double
gfp
[
5
],
rp
[
5
],
t
;
const
double
min_eps
=
1e-6
;
bool
is_float
=
depth
==
CV_32F
;
const
Point
*
ptsi
=
(
const
Point
*
)
points
.
data
;
const
Point2f
*
ptsf
=
(
const
Point2f
*
)
points
.
data
;
AutoBuffer
<
double
>
_Ad
(
n
*
5
),
_bd
(
n
);
double
*
Ad
=
_Ad
,
*
bd
=
_bd
;
// first fit for parameters A - E
Mat
A
(
n
,
5
,
CV_64F
,
Ad
);
Mat
b
(
n
,
1
,
CV_64F
,
bd
);
Mat
x
(
5
,
1
,
CV_64F
,
gfp
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
Point2f
p
=
is_float
?
ptsf
[
i
]
:
Point2f
((
float
)
ptsi
[
i
].
x
,
(
float
)
ptsi
[
i
].
y
);
c
+=
p
;
}
c
.
x
/=
n
;
c
.
y
/=
n
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
CvSeqReader
reader
;
int
lpt
=
contour
->
total
;
double
a00
=
0
,
xi_1
,
yi_1
;
int
is_float
=
CV_SEQ_ELTYPE
(
contour
)
==
CV_32FC2
;
Point2f
p
=
is_float
?
ptsf
[
i
]
:
Point2f
((
float
)
ptsi
[
i
].
x
,
(
float
)
ptsi
[
i
].
y
);
p
-=
c
;
cvStartReadSeq
(
contour
,
&
reader
,
0
);
bd
[
i
]
=
10000.0
;
// 1.0?
Ad
[
i
*
5
]
=
-
(
double
)
p
.
x
*
p
.
x
;
// A - C signs inverted as proposed by APP
Ad
[
i
*
5
+
1
]
=
-
(
double
)
p
.
y
*
p
.
y
;
Ad
[
i
*
5
+
2
]
=
-
(
double
)
p
.
x
*
p
.
y
;
Ad
[
i
*
5
+
3
]
=
p
.
x
;
Ad
[
i
*
5
+
4
]
=
p
.
y
;
}
solve
(
A
,
b
,
x
,
DECOMP_SVD
);
// now use general-form parameters A - E to find the ellipse center:
// differentiate general form wrt x/y to get two equations for cx and cy
A
=
Mat
(
2
,
2
,
CV_64F
,
Ad
);
b
=
Mat
(
2
,
1
,
CV_64F
,
bd
);
x
=
Mat
(
2
,
1
,
CV_64F
,
rp
);
Ad
[
0
]
=
2
*
gfp
[
0
];
Ad
[
1
]
=
Ad
[
2
]
=
gfp
[
2
];
Ad
[
3
]
=
2
*
gfp
[
1
];
bd
[
0
]
=
gfp
[
3
];
bd
[
1
]
=
gfp
[
4
];
solve
(
A
,
b
,
x
,
DECOMP_SVD
);
// re-fit for parameters A - C with those center coordinates
A
=
Mat
(
n
,
3
,
CV_64F
,
Ad
);
b
=
Mat
(
n
,
1
,
CV_64F
,
bd
);
x
=
Mat
(
3
,
1
,
CV_64F
,
gfp
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
Point2f
p
=
is_float
?
ptsf
[
i
]
:
Point2f
((
float
)
ptsi
[
i
].
x
,
(
float
)
ptsi
[
i
].
y
);
p
-=
c
;
bd
[
i
]
=
1.0
;
Ad
[
i
*
3
]
=
(
p
.
x
-
rp
[
0
])
*
(
p
.
x
-
rp
[
0
]);
Ad
[
i
*
3
+
1
]
=
(
p
.
y
-
rp
[
1
])
*
(
p
.
y
-
rp
[
1
]);
Ad
[
i
*
3
+
2
]
=
(
p
.
x
-
rp
[
0
])
*
(
p
.
y
-
rp
[
1
]);
}
solve
(
A
,
b
,
x
,
DECOMP_SVD
);
// store angle and radii
rp
[
4
]
=
-
0.5
*
atan2
(
gfp
[
2
],
gfp
[
1
]
-
gfp
[
0
]);
// convert from APP angle usage
t
=
sin
(
-
2.0
*
rp
[
4
]);
if
(
fabs
(
t
)
>
fabs
(
gfp
[
2
])
*
min_eps
)
t
=
gfp
[
2
]
/
t
;
else
t
=
gfp
[
1
]
-
gfp
[
0
];
rp
[
2
]
=
fabs
(
gfp
[
0
]
+
gfp
[
1
]
-
t
);
if
(
rp
[
2
]
>
min_eps
)
rp
[
2
]
=
sqrt
(
2.0
/
rp
[
2
]);
rp
[
3
]
=
fabs
(
gfp
[
0
]
+
gfp
[
1
]
+
t
);
if
(
rp
[
3
]
>
min_eps
)
rp
[
3
]
=
sqrt
(
2.0
/
rp
[
3
]);
box
.
center
.
x
=
(
float
)
rp
[
0
]
+
c
.
x
;
box
.
center
.
y
=
(
float
)
rp
[
1
]
+
c
.
y
;
box
.
size
.
width
=
(
float
)(
rp
[
2
]
*
2
);
box
.
size
.
height
=
(
float
)(
rp
[
3
]
*
2
);
if
(
box
.
size
.
width
>
box
.
size
.
height
)
{
float
tmp
;
CV_SWAP
(
box
.
size
.
width
,
box
.
size
.
height
,
tmp
);
box
.
angle
=
(
float
)(
90
+
rp
[
4
]
*
180
/
CV_PI
);
}
if
(
box
.
angle
<
-
180
)
box
.
angle
+=
360
;
if
(
box
.
angle
>
360
)
box
.
angle
-=
360
;
return
box
;
}
namespace
cv
{
// Calculates bounding rectagnle of a point set or retrieves already calculated
static
Rect
pointSetBoundingRect
(
const
Mat
&
points
)
{
int
npoints
=
points
.
checkVector
(
2
);
int
depth
=
points
.
depth
();
CV_Assert
(
npoints
>=
0
&&
(
depth
==
CV_32F
||
depth
==
CV_32S
));
int
xmin
=
0
,
ymin
=
0
,
xmax
=
-
1
,
ymax
=
-
1
,
i
;
bool
is_float
=
depth
==
CV_32F
;
if
(
npoints
==
0
)
return
Rect
();
const
Point
*
pts
=
(
const
Point
*
)
points
.
data
;
Point
pt
=
pts
[
0
];
#if CV_SSE4_2
if
(
cv
::
checkHardwareSupport
(
CV_CPU_SSE4_2
))
{
if
(
!
is_float
)
{
xi_1
=
((
CvPoint
*
)(
reader
.
ptr
))
->
x
;
yi_1
=
((
CvPoint
*
)(
reader
.
ptr
))
->
y
;
__m128i
minval
,
maxval
;
minval
=
maxval
=
_mm_loadl_epi64
((
const
__m128i
*
)(
&
pt
));
//min[0]=pt.x, min[1]=pt.y
for
(
i
=
1
;
i
<
npoints
;
i
++
)
{
__m128i
ptXY
=
_mm_loadl_epi64
((
const
__m128i
*
)
&
pts
[
i
]);
minval
=
_mm_min_epi32
(
ptXY
,
minval
);
maxval
=
_mm_max_epi32
(
ptXY
,
maxval
);
}
xmin
=
_mm_cvtsi128_si32
(
minval
);
ymin
=
_mm_cvtsi128_si32
(
_mm_srli_si128
(
minval
,
4
));
xmax
=
_mm_cvtsi128_si32
(
maxval
);
ymax
=
_mm_cvtsi128_si32
(
_mm_srli_si128
(
maxval
,
4
));
}
else
{
xi_1
=
((
CvPoint2D32f
*
)(
reader
.
ptr
))
->
x
;
yi_1
=
((
CvPoint2D32f
*
)(
reader
.
ptr
))
->
y
;
}
CV_NEXT_SEQ_ELEM
(
contour
->
elem_size
,
reader
);
__m128
minvalf
,
maxvalf
,
z
=
_mm_setzero_ps
(),
ptXY
=
_mm_setzero_ps
();
minvalf
=
maxvalf
=
_mm_loadl_pi
(
z
,
(
const
__m64
*
)(
&
pt
));
for
(
i
=
1
;
i
<
npoints
;
i
++
)
{
ptXY
=
_mm_loadl_pi
(
ptXY
,
(
const
__m64
*
)
&
pts
[
i
]);
minvalf
=
_mm_min_ps
(
minvalf
,
ptXY
);
maxvalf
=
_mm_max_ps
(
maxvalf
,
ptXY
);
}
while
(
lpt
--
>
0
)
float
xyminf
[
2
],
xymaxf
[
2
];
_mm_storel_pi
((
__m64
*
)
xyminf
,
minvalf
);
_mm_storel_pi
((
__m64
*
)
xymaxf
,
maxvalf
);
xmin
=
cvFloor
(
xyminf
[
0
]);
ymin
=
cvFloor
(
xyminf
[
1
]);
xmax
=
cvFloor
(
xymaxf
[
0
]);
ymax
=
cvFloor
(
xymaxf
[
1
]);
}
}
else
#endif
{
if
(
!
is_float
)
{
double
dxy
,
xi
,
yi
;
xmin
=
xmax
=
pt
.
x
;
ymin
=
ymax
=
pt
.
y
;
if
(
!
is_float
)
for
(
i
=
1
;
i
<
npoints
;
i
++
)
{
xi
=
((
CvPoint
*
)(
reader
.
ptr
))
->
x
;
yi
=
((
CvPoint
*
)(
reader
.
ptr
))
->
y
;
pt
=
pts
[
i
];
if
(
xmin
>
pt
.
x
)
xmin
=
pt
.
x
;
if
(
xmax
<
pt
.
x
)
xmax
=
pt
.
x
;
if
(
ymin
>
pt
.
y
)
ymin
=
pt
.
y
;
if
(
ymax
<
pt
.
y
)
ymax
=
pt
.
y
;
}
else
}
else
{
Cv32suf
v
;
// init values
xmin
=
xmax
=
CV_TOGGLE_FLT
(
pt
.
x
);
ymin
=
ymax
=
CV_TOGGLE_FLT
(
pt
.
y
);
for
(
i
=
1
;
i
<
npoints
;
i
++
)
{
xi
=
((
CvPoint2D32f
*
)(
reader
.
ptr
))
->
x
;
yi
=
((
CvPoint2D32f
*
)(
reader
.
ptr
))
->
y
;
pt
=
pts
[
i
];
pt
.
x
=
CV_TOGGLE_FLT
(
pt
.
x
);
pt
.
y
=
CV_TOGGLE_FLT
(
pt
.
y
);
if
(
xmin
>
pt
.
x
)
xmin
=
pt
.
x
;
if
(
xmax
<
pt
.
x
)
xmax
=
pt
.
x
;
if
(
ymin
>
pt
.
y
)
ymin
=
pt
.
y
;
if
(
ymax
<
pt
.
y
)
ymax
=
pt
.
y
;
}
CV_NEXT_SEQ_ELEM
(
contour
->
elem_size
,
reader
);
dxy
=
xi_1
*
yi
-
xi
*
yi_1
;
a00
+=
dxy
;
xi_1
=
xi
;
yi_1
=
yi
;
v
.
i
=
CV_TOGGLE_FLT
(
xmin
);
xmin
=
cvFloor
(
v
.
f
);
v
.
i
=
CV_TOGGLE_FLT
(
ymin
);
ymin
=
cvFloor
(
v
.
f
);
// because right and bottom sides of the bounding rectangle are not inclusive
// (note +1 in width and height calculation below), cvFloor is used here instead of cvCeil
v
.
i
=
CV_TOGGLE_FLT
(
xmax
);
xmax
=
cvFloor
(
v
.
f
);
v
.
i
=
CV_TOGGLE_FLT
(
ymax
);
ymax
=
cvFloor
(
v
.
f
);
}
*
area
=
a00
*
0.5
;
}
else
*
area
=
0
;
return
Rect
(
xmin
,
ymin
,
xmax
-
xmin
+
1
,
ymax
-
ymin
+
1
);
}
return
CV_OK
;
static
Rect
maskBoundingRect
(
const
Mat
&
img
)
{
CV_Assert
(
img
.
depth
()
<=
CV_8S
&&
img
.
channels
()
==
1
);
Size
size
=
img
.
size
();
int
xmin
=
size
.
width
,
ymin
=
-
1
,
xmax
=
-
1
,
ymax
=
-
1
,
i
,
j
,
k
;
for
(
i
=
0
;
i
<
size
.
height
;
i
++
)
{
const
uchar
*
_ptr
=
img
.
ptr
(
i
);
const
uchar
*
ptr
=
(
const
uchar
*
)
alignPtr
(
_ptr
,
4
);
int
have_nz
=
0
,
k_min
,
offset
=
(
int
)(
ptr
-
_ptr
);
j
=
0
;
offset
=
MIN
(
offset
,
size
.
width
);
for
(
;
j
<
offset
;
j
++
)
if
(
_ptr
[
j
]
)
{
have_nz
=
1
;
break
;
}
if
(
j
<
offset
)
{
if
(
j
<
xmin
)
xmin
=
j
;
if
(
j
>
xmax
)
xmax
=
j
;
}
if
(
offset
<
size
.
width
)
{
xmin
-=
offset
;
xmax
-=
offset
;
size
.
width
-=
offset
;
j
=
0
;
for
(
;
j
<=
xmin
-
4
;
j
+=
4
)
if
(
*
((
int
*
)(
ptr
+
j
))
)
break
;
for
(
;
j
<
xmin
;
j
++
)
if
(
ptr
[
j
]
)
{
xmin
=
j
;
if
(
j
>
xmax
)
xmax
=
j
;
have_nz
=
1
;
break
;
}
k_min
=
MAX
(
j
-
1
,
xmax
);
k
=
size
.
width
-
1
;
for
(
;
k
>
k_min
&&
(
k
&
3
)
!=
3
;
k
--
)
if
(
ptr
[
k
]
)
break
;
if
(
k
>
k_min
&&
(
k
&
3
)
==
3
)
{
for
(
;
k
>
k_min
+
3
;
k
-=
4
)
if
(
*
((
int
*
)(
ptr
+
k
-
3
))
)
break
;
}
for
(
;
k
>
k_min
;
k
--
)
if
(
ptr
[
k
]
)
{
xmax
=
k
;
have_nz
=
1
;
break
;
}
if
(
!
have_nz
)
{
j
&=
~
3
;
for
(
;
j
<=
k
-
3
;
j
+=
4
)
if
(
*
((
int
*
)(
ptr
+
j
))
)
break
;
for
(
;
j
<=
k
;
j
++
)
if
(
ptr
[
j
]
)
{
have_nz
=
1
;
break
;
}
}
xmin
+=
offset
;
xmax
+=
offset
;
size
.
width
+=
offset
;
}
if
(
have_nz
)
{
if
(
ymin
<
0
)
ymin
=
i
;
ymax
=
i
;
}
}
if
(
xmin
>=
size
.
width
)
xmin
=
ymin
=
0
;
return
Rect
(
xmin
,
ymin
,
xmax
-
xmin
+
1
,
ymax
-
ymin
+
1
);
}
}
/****************************************************************************************\
cv
::
Rect
cv
::
boundingRect
(
InputArray
array
)
{
Mat
m
=
array
.
getMat
();
return
m
.
depth
()
<=
CV_8U
?
maskBoundingRect
(
m
)
:
pointSetBoundingRect
(
m
);
}
copy data from one buffer to other buffer
////////////////////////////////////////////// C API ///////////////////////////////////////////
\****************************************************************************************/
CV_IMPL
int
cvMinEnclosingCircle
(
const
void
*
array
,
CvPoint2D32f
*
_center
,
float
*
_radius
)
{
cv
::
AutoBuffer
<
double
>
abuf
;
cv
::
Mat
points
=
cv
::
cvarrToMat
(
array
,
false
,
false
,
0
,
&
abuf
);
cv
::
Point2f
center
;
float
radius
;
cv
::
minEnclosingCircle
(
points
,
center
,
radius
);
if
(
_center
)
*
_center
=
center
;
if
(
_radius
)
*
_radius
=
radius
;
return
1
;
}
static
CvStatus
static
void
icvMemCopy
(
double
**
buf1
,
double
**
buf2
,
double
**
buf3
,
int
*
b_max
)
{
int
bb
;
if
(
(
*
buf1
==
NULL
&&
*
buf2
==
NULL
)
||
*
buf3
==
NULL
)
return
CV_NULLPTR_ERR
;
CV_Assert
(
(
*
buf1
!=
NULL
||
*
buf2
!=
NULL
)
&&
*
buf3
!=
NULL
);
bb
=
*
b_max
;
int
bb
=
*
b_max
;
if
(
*
buf2
==
NULL
)
{
*
b_max
=
2
*
(
*
b_max
);
*
buf2
=
(
double
*
)
cvAlloc
(
(
*
b_max
)
*
sizeof
(
double
));
if
(
*
buf2
==
NULL
)
return
CV_OUTOFMEM_ERR
;
memcpy
(
*
buf2
,
*
buf3
,
bb
*
sizeof
(
double
));
*
buf3
=
*
buf2
;
...
...
@@ -552,21 +741,17 @@ icvMemCopy( double **buf1, double **buf2, double **buf3, int *b_max )
*
b_max
=
2
*
(
*
b_max
);
*
buf1
=
(
double
*
)
cvAlloc
(
(
*
b_max
)
*
sizeof
(
double
));
if
(
*
buf1
==
NULL
)
return
CV_OUTOFMEM_ERR
;
memcpy
(
*
buf1
,
*
buf3
,
bb
*
sizeof
(
double
));
*
buf3
=
*
buf1
;
cvFree
(
buf2
);
*
buf2
=
NULL
;
}
return
CV_OK
;
}
/* area of a contour sector */
static
CvStatus
icvContourSecArea
(
CvSeq
*
contour
,
CvSlice
slice
,
double
*
area
)
static
double
icvContourSecArea
(
CvSeq
*
contour
,
CvSlice
slice
)
{
CvPoint
pt
;
/* pointer to points */
CvPoint
pt_s
,
pt_e
;
/* first and last points */
...
...
@@ -579,14 +764,9 @@ static CvStatus icvContourSecArea( CvSeq * contour, CvSlice slice, double *area
double
x_s
,
y_s
,
nx
,
ny
,
dx
,
dy
,
du
,
dv
;
double
eps
=
1.e-5
;
double
*
p_are1
,
*
p_are2
,
*
p_are
;
double
area
=
0
;
assert
(
contour
!=
NULL
);
if
(
contour
==
NULL
)
return
CV_NULLPTR_ERR
;
if
(
!
CV_IS_SEQ_POINT_SET
(
contour
))
return
CV_BADFLAG_ERR
;
CV_Assert
(
contour
!=
NULL
&&
CV_IS_SEQ_POINT_SET
(
contour
));
lpt
=
cvSliceLength
(
slice
,
contour
);
/*if( n2 >= n1 )
...
...
@@ -594,143 +774,138 @@ static CvStatus icvContourSecArea( CvSeq * contour, CvSlice slice, double *area
else
lpt = contour->total - n1 + n2 + 1;*/
if
(
contour
->
total
&&
lpt
>
2
)
{
a00
=
x0
=
y0
=
xi_1
=
yi_1
=
0
;
sk1
=
0
;
flag
=
0
;
dxy
=
0
;
p_are1
=
(
double
*
)
cvAlloc
(
p_max
*
sizeof
(
double
));
if
(
contour
->
total
<=
0
||
lpt
<=
2
)
return
0.
;
if
(
p_are1
==
NULL
)
return
CV_OUTOFMEM_ERR
;
a00
=
x0
=
y0
=
xi_1
=
yi_1
=
0
;
sk1
=
0
;
flag
=
0
;
dxy
=
0
;
p_are1
=
(
double
*
)
cvAlloc
(
p_max
*
sizeof
(
double
));
p_are
=
p_are1
;
p_are2
=
NULL
;
p_are
=
p_are1
;
p_are2
=
NULL
;
cvStartReadSeq
(
contour
,
&
reader
,
0
);
cvSetSeqReaderPos
(
&
reader
,
slice
.
start_index
);
CV_READ_SEQ_ELEM
(
pt_s
,
reader
);
p_ind
=
0
;
cvSetSeqReaderPos
(
&
reader
,
slice
.
end_index
);
CV_READ_SEQ_ELEM
(
pt_e
,
reader
);
cvStartReadSeq
(
contour
,
&
reader
,
0
);
cvSetSeqReaderPos
(
&
reader
,
slice
.
start_index
);
CV_READ_SEQ_ELEM
(
pt_s
,
reader
);
p_ind
=
0
;
cvSetSeqReaderPos
(
&
reader
,
slice
.
end_index
);
CV_READ_SEQ_ELEM
(
pt_e
,
reader
);
/* normal coefficients */
nx
=
pt_s
.
y
-
pt_e
.
y
;
ny
=
pt_e
.
x
-
pt_s
.
x
;
cvSetSeqReaderPos
(
&
reader
,
slice
.
start_index
);
nx
=
pt_s
.
y
-
pt_e
.
y
;
ny
=
pt_e
.
x
-
pt_s
.
x
;
cvSetSeqReaderPos
(
&
reader
,
slice
.
start_index
);
while
(
lpt
--
>
0
)
{
CV_READ_SEQ_ELEM
(
pt
,
reader
);
while
(
lpt
--
>
0
)
{
CV_READ_SEQ_ELEM
(
pt
,
reader
);
if
(
flag
==
0
)
{
xi_1
=
(
double
)
pt
.
x
;
yi_1
=
(
double
)
pt
.
y
;
x0
=
xi_1
;
y0
=
yi_1
;
sk1
=
0
;
flag
=
1
;
}
else
{
xi
=
(
double
)
pt
.
x
;
yi
=
(
double
)
pt
.
y
;
if
(
flag
==
0
)
{
xi_1
=
(
double
)
pt
.
x
;
yi_1
=
(
double
)
pt
.
y
;
x0
=
xi_1
;
y0
=
yi_1
;
sk1
=
0
;
flag
=
1
;
}
else
{
xi
=
(
double
)
pt
.
x
;
yi
=
(
double
)
pt
.
y
;
/**************** edges intersection examination **************************/
sk
=
nx
*
(
xi
-
pt_s
.
x
)
+
ny
*
(
yi
-
pt_s
.
y
);
if
(
(
fabs
(
sk
)
<
eps
&&
lpt
>
0
)
||
sk
*
sk1
<
-
eps
)
sk
=
nx
*
(
xi
-
pt_s
.
x
)
+
ny
*
(
yi
-
pt_s
.
y
);
if
(
(
fabs
(
sk
)
<
eps
&&
lpt
>
0
)
||
sk
*
sk1
<
-
eps
)
{
if
(
fabs
(
sk
)
<
eps
)
{
dxy
=
xi_1
*
yi
-
xi
*
yi_1
;
a00
=
a00
+
dxy
;
dxy
=
xi
*
y0
-
x0
*
yi
;
a00
=
a00
+
dxy
;
if
(
p_ind
>=
p_max
)
icvMemCopy
(
&
p_are1
,
&
p_are2
,
&
p_are
,
&
p_max
);
p_are
[
p_ind
]
=
a00
/
2.
;
p_ind
++
;
a00
=
0
;
sk1
=
0
;
x0
=
xi
;
y0
=
yi
;
dxy
=
0
;
}
else
{
if
(
fabs
(
sk
)
<
eps
)
/* define intersection point */
dv
=
yi
-
yi_1
;
du
=
xi
-
xi_1
;
dx
=
ny
;
dy
=
-
nx
;
if
(
fabs
(
du
)
>
eps
)
t
=
((
yi_1
-
pt_s
.
y
)
*
du
+
dv
*
(
pt_s
.
x
-
xi_1
))
/
(
du
*
dy
-
dx
*
dv
);
else
t
=
(
xi_1
-
pt_s
.
x
)
/
dx
;
if
(
t
>
eps
&&
t
<
1
-
eps
)
{
dxy
=
xi_1
*
yi
-
xi
*
yi_1
;
a00
=
a00
+
dxy
;
dxy
=
xi
*
y0
-
x0
*
yi
;
a00
=
a00
+
dxy
;
x_s
=
pt_s
.
x
+
t
*
dx
;
y_s
=
pt_s
.
y
+
t
*
dy
;
dxy
=
xi_1
*
y_s
-
x_s
*
yi_1
;
a00
+=
dxy
;
dxy
=
x_s
*
y0
-
x0
*
y_s
;
a00
+=
dxy
;
if
(
p_ind
>=
p_max
)
icvMemCopy
(
&
p_are1
,
&
p_are2
,
&
p_are
,
&
p_max
);
p_are
[
p_ind
]
=
a00
/
2.
;
p_ind
++
;
a00
=
0
;
sk1
=
0
;
x0
=
xi
;
y0
=
yi
;
dxy
=
0
;
}
else
{
/* define intersection point */
dv
=
yi
-
yi_1
;
du
=
xi
-
xi_1
;
dx
=
ny
;
dy
=
-
nx
;
if
(
fabs
(
du
)
>
eps
)
t
=
((
yi_1
-
pt_s
.
y
)
*
du
+
dv
*
(
pt_s
.
x
-
xi_1
))
/
(
du
*
dy
-
dx
*
dv
);
else
t
=
(
xi_1
-
pt_s
.
x
)
/
dx
;
if
(
t
>
eps
&&
t
<
1
-
eps
)
{
x_s
=
pt_s
.
x
+
t
*
dx
;
y_s
=
pt_s
.
y
+
t
*
dy
;
dxy
=
xi_1
*
y_s
-
x_s
*
yi_1
;
a00
+=
dxy
;
dxy
=
x_s
*
y0
-
x0
*
y_s
;
a00
+=
dxy
;
if
(
p_ind
>=
p_max
)
icvMemCopy
(
&
p_are1
,
&
p_are2
,
&
p_are
,
&
p_max
);
p_are
[
p_ind
]
=
a00
/
2.
;
p_ind
++
;
a00
=
0
;
sk1
=
0
;
x0
=
x_s
;
y0
=
y_s
;
dxy
=
x_s
*
yi
-
xi
*
y_s
;
}
x0
=
x_s
;
y0
=
y_s
;
dxy
=
x_s
*
yi
-
xi
*
y_s
;
}
}
else
dxy
=
xi_1
*
yi
-
xi
*
yi_1
;
}
else
dxy
=
xi_1
*
yi
-
xi
*
yi_1
;
a00
+=
dxy
;
xi_1
=
xi
;
yi_1
=
yi
;
sk1
=
sk
;
a00
+=
dxy
;
xi_1
=
xi
;
yi_1
=
yi
;
sk1
=
sk
;
}
}
}
xi
=
x0
;
yi
=
y0
;
dxy
=
xi_1
*
yi
-
xi
*
yi_1
;
xi
=
x0
;
yi
=
y0
;
dxy
=
xi_1
*
yi
-
xi
*
yi_1
;
a00
+=
dxy
;
a00
+=
dxy
;
if
(
p_ind
>=
p_max
)
icvMemCopy
(
&
p_are1
,
&
p_are2
,
&
p_are
,
&
p_max
);
if
(
p_ind
>=
p_max
)
icvMemCopy
(
&
p_are1
,
&
p_are2
,
&
p_are
,
&
p_max
);
p_are
[
p_ind
]
=
a00
/
2.
;
p_ind
++
;
p_are
[
p_ind
]
=
a00
/
2.
;
p_ind
++
;
/* common area calculation */
*
area
=
0
;
for
(
i
=
0
;
i
<
p_ind
;
i
++
)
(
*
area
)
+=
fabs
(
p_are
[
i
]
);
// common area calculation
area
=
0
;
for
(
i
=
0
;
i
<
p_ind
;
i
++
)
area
+=
fabs
(
p_are
[
i
]
);
if
(
p_are1
!=
NULL
)
cvFree
(
&
p_are1
);
else
if
(
p_are2
!=
NULL
)
cvFree
(
&
p_are2
);
if
(
p_are1
!=
NULL
)
cvFree
(
&
p_are1
);
else
if
(
p_are2
!=
NULL
)
cvFree
(
&
p_are2
);
return
CV_OK
;
}
else
return
CV_BADSIZE_ERR
;
return
area
;
}
...
...
@@ -757,178 +932,115 @@ cvContourArea( const void *array, CvSlice slice, int oriented )
if
(
cvSliceLength
(
slice
,
contour
)
==
contour
->
total
)
{
IPPI_CALL
(
icvContourArea
(
contour
,
&
area
));
}
else
{
if
(
CV_SEQ_ELTYPE
(
contour
)
!=
CV_32SC2
)
CV_Error
(
CV_StsUnsupportedFormat
,
"Only curves with integer coordinates are supported in case of contour slice"
);
IPPI_CALL
(
icvContourSecArea
(
contour
,
slice
,
&
area
));
cv
::
AutoBuffer
<
double
>
abuf
;
cv
::
Mat
points
=
cv
::
cvarrToMat
(
contour
,
false
,
false
,
0
,
&
abuf
);
return
cv
::
contourArea
(
points
,
oriented
!=
0
);
}
if
(
CV_SEQ_ELTYPE
(
contour
)
!=
CV_32SC2
)
CV_Error
(
CV_StsUnsupportedFormat
,
"Only curves with integer coordinates are supported in case of contour slice"
);
area
=
icvContourSecArea
(
contour
,
slice
);
return
oriented
?
area
:
fabs
(
area
);
}
CV_IMPL
CvBox2D
cvFitEllipse2
(
const
CvArr
*
array
)
/* calculates length of a curve (e.g. contour perimeter) */
CV_IMPL
double
cvArcLength
(
const
void
*
array
,
CvSlice
slice
,
int
is_closed
)
{
CvBox2D
box
;
cv
::
AutoBuffer
<
double
>
Ad
,
bd
;
memset
(
&
box
,
0
,
sizeof
(
box
));
double
perimeter
=
0
;
int
i
,
j
=
0
,
count
;
const
int
N
=
16
;
float
buf
[
N
];
CvMat
buffer
=
cvMat
(
1
,
N
,
CV_32F
,
buf
);
CvSeqReader
reader
;
CvContour
contour_header
;
CvSeq
*
ptseq
=
0
;
CvSeq
*
contour
=
0
;
CvSeqBlock
block
;
int
n
;
if
(
CV_IS_SEQ
(
array
))
{
ptseq
=
(
CvSeq
*
)
array
;
if
(
!
CV_IS_SEQ_PO
INT_SET
(
ptseq
))
contour
=
(
CvSeq
*
)
array
;
if
(
!
CV_IS_SEQ_PO
LYLINE
(
contour
))
CV_Error
(
CV_StsBadArg
,
"Unsupported sequence type"
);
if
(
is_closed
<
0
)
is_closed
=
CV_IS_SEQ_CLOSED
(
contour
);
}
else
{
ptseq
=
cvPointSeqFromMat
(
CV_SEQ_KIND_GENERIC
,
array
,
&
contour_header
,
&
block
);
is_closed
=
is_closed
>
0
;
contour
=
cvPointSeqFromMat
(
CV_SEQ_KIND_CURVE
|
(
is_closed
?
CV_SEQ_FLAG_CLOSED
:
0
),
array
,
&
contour_header
,
&
block
);
}
n
=
ptseq
->
total
;
if
(
n
<
5
)
CV_Error
(
CV_StsBadSize
,
"Number of points should be >= 5"
);
/*
* New fitellipse algorithm, contributed by Dr. Daniel Weiss
*/
CvPoint2D32f
c
=
{
0
,
0
};
double
gfp
[
5
],
rp
[
5
],
t
;
CvMat
A
,
b
,
x
;
const
double
min_eps
=
1e-6
;
int
i
,
is_float
;
CvSeqReader
reader
;
if
(
contour
->
total
>
1
)
{
int
is_float
=
CV_SEQ_ELTYPE
(
contour
)
==
CV_32FC2
;
Ad
.
allocate
(
n
*
5
);
bd
.
allocate
(
n
);
cvStartReadSeq
(
contour
,
&
reader
,
0
);
cvSetSeqReaderPos
(
&
reader
,
slice
.
start_index
);
count
=
cvSliceLength
(
slice
,
contour
);
// first fit for parameters A - E
A
=
cvMat
(
n
,
5
,
CV_64F
,
Ad
);
b
=
cvMat
(
n
,
1
,
CV_64F
,
bd
);
x
=
cvMat
(
5
,
1
,
CV_64F
,
gfp
);
count
-=
!
is_closed
&&
count
==
contour
->
total
;
cvStartReadSeq
(
ptseq
,
&
reader
);
is_float
=
CV_SEQ_ELTYPE
(
ptseq
)
==
CV_32FC2
;
// scroll the reader by 1 point
reader
.
prev_elem
=
reader
.
ptr
;
CV_NEXT_SEQ_ELEM
(
sizeof
(
CvPoint
),
reader
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
CvPoint2D32f
p
;
if
(
is_float
)
p
=
*
(
CvPoint2D32f
*
)(
reader
.
ptr
);
else
for
(
i
=
0
;
i
<
count
;
i
++
)
{
p
.
x
=
(
float
)((
int
*
)
reader
.
ptr
)[
0
];
p
.
y
=
(
float
)((
int
*
)
reader
.
ptr
)[
1
];
}
CV_NEXT_SEQ_ELEM
(
sizeof
(
p
),
reader
);
c
.
x
+=
p
.
x
;
c
.
y
+=
p
.
y
;
}
c
.
x
/=
n
;
c
.
y
/=
n
;
float
dx
,
dy
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
CvPoint2D32f
p
;
if
(
is_float
)
p
=
*
(
CvPoint2D32f
*
)(
reader
.
ptr
);
else
{
p
.
x
=
(
float
)((
int
*
)
reader
.
ptr
)[
0
];
p
.
y
=
(
float
)((
int
*
)
reader
.
ptr
)[
1
];
}
CV_NEXT_SEQ_ELEM
(
sizeof
(
p
),
reader
);
p
.
x
-=
c
.
x
;
p
.
y
-=
c
.
y
;
if
(
!
is_float
)
{
CvPoint
*
pt
=
(
CvPoint
*
)
reader
.
ptr
;
CvPoint
*
prev_pt
=
(
CvPoint
*
)
reader
.
prev_elem
;
bd
[
i
]
=
10000.0
;
// 1.0?
Ad
[
i
*
5
]
=
-
(
double
)
p
.
x
*
p
.
x
;
// A - C signs inverted as proposed by APP
Ad
[
i
*
5
+
1
]
=
-
(
double
)
p
.
y
*
p
.
y
;
Ad
[
i
*
5
+
2
]
=
-
(
double
)
p
.
x
*
p
.
y
;
Ad
[
i
*
5
+
3
]
=
p
.
x
;
Ad
[
i
*
5
+
4
]
=
p
.
y
;
}
dx
=
(
float
)
pt
->
x
-
(
float
)
prev_pt
->
x
;
dy
=
(
float
)
pt
->
y
-
(
float
)
prev_pt
->
y
;
}
else
{
CvPoint2D32f
*
pt
=
(
CvPoint2D32f
*
)
reader
.
ptr
;
CvPoint2D32f
*
prev_pt
=
(
CvPoint2D32f
*
)
reader
.
prev_elem
;
cvSolve
(
&
A
,
&
b
,
&
x
,
CV_SVD
);
dx
=
pt
->
x
-
prev_pt
->
x
;
dy
=
pt
->
y
-
prev_pt
->
y
;
}
// now use general-form parameters A - E to find the ellipse center:
// differentiate general form wrt x/y to get two equations for cx and cy
A
=
cvMat
(
2
,
2
,
CV_64F
,
Ad
);
b
=
cvMat
(
2
,
1
,
CV_64F
,
bd
);
x
=
cvMat
(
2
,
1
,
CV_64F
,
rp
);
Ad
[
0
]
=
2
*
gfp
[
0
];
Ad
[
1
]
=
Ad
[
2
]
=
gfp
[
2
];
Ad
[
3
]
=
2
*
gfp
[
1
];
bd
[
0
]
=
gfp
[
3
];
bd
[
1
]
=
gfp
[
4
];
cvSolve
(
&
A
,
&
b
,
&
x
,
CV_SVD
);
reader
.
prev_elem
=
reader
.
ptr
;
CV_NEXT_SEQ_ELEM
(
contour
->
elem_size
,
reader
);
// Bugfix by Axel at rubico.com 2010-03-22, affects closed slices only
// wraparound not handled by CV_NEXT_SEQ_ELEM
if
(
is_closed
&&
i
==
count
-
2
)
cvSetSeqReaderPos
(
&
reader
,
slice
.
start_index
);
// re-fit for parameters A - C with those center coordinates
A
=
cvMat
(
n
,
3
,
CV_64F
,
Ad
);
b
=
cvMat
(
n
,
1
,
CV_64F
,
bd
);
x
=
cvMat
(
3
,
1
,
CV_64F
,
gfp
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
CvPoint2D32f
p
;
if
(
is_float
)
p
=
*
(
CvPoint2D32f
*
)(
reader
.
ptr
);
else
{
p
.
x
=
(
float
)((
int
*
)
reader
.
ptr
)[
0
];
p
.
y
=
(
float
)((
int
*
)
reader
.
ptr
)[
1
];
buffer
.
data
.
fl
[
j
]
=
dx
*
dx
+
dy
*
dy
;
if
(
++
j
==
N
||
i
==
count
-
1
)
{
buffer
.
cols
=
j
;
cvPow
(
&
buffer
,
&
buffer
,
0.5
);
for
(
;
j
>
0
;
j
--
)
perimeter
+=
buffer
.
data
.
fl
[
j
-
1
];
}
}
CV_NEXT_SEQ_ELEM
(
sizeof
(
p
),
reader
);
p
.
x
-=
c
.
x
;
p
.
y
-=
c
.
y
;
bd
[
i
]
=
1.0
;
Ad
[
i
*
3
]
=
(
p
.
x
-
rp
[
0
])
*
(
p
.
x
-
rp
[
0
]);
Ad
[
i
*
3
+
1
]
=
(
p
.
y
-
rp
[
1
])
*
(
p
.
y
-
rp
[
1
]);
Ad
[
i
*
3
+
2
]
=
(
p
.
x
-
rp
[
0
])
*
(
p
.
y
-
rp
[
1
]);
}
cvSolve
(
&
A
,
&
b
,
&
x
,
CV_SVD
);
// store angle and radii
rp
[
4
]
=
-
0.5
*
atan2
(
gfp
[
2
],
gfp
[
1
]
-
gfp
[
0
]);
// convert from APP angle usage
t
=
sin
(
-
2.0
*
rp
[
4
]);
if
(
fabs
(
t
)
>
fabs
(
gfp
[
2
])
*
min_eps
)
t
=
gfp
[
2
]
/
t
;
else
t
=
gfp
[
1
]
-
gfp
[
0
];
rp
[
2
]
=
fabs
(
gfp
[
0
]
+
gfp
[
1
]
-
t
);
if
(
rp
[
2
]
>
min_eps
)
rp
[
2
]
=
sqrt
(
2.0
/
rp
[
2
]);
rp
[
3
]
=
fabs
(
gfp
[
0
]
+
gfp
[
1
]
+
t
);
if
(
rp
[
3
]
>
min_eps
)
rp
[
3
]
=
sqrt
(
2.0
/
rp
[
3
]);
return
perimeter
;
}
box
.
center
.
x
=
(
float
)
rp
[
0
]
+
c
.
x
;
box
.
center
.
y
=
(
float
)
rp
[
1
]
+
c
.
y
;
box
.
size
.
width
=
(
float
)(
rp
[
2
]
*
2
);
box
.
size
.
height
=
(
float
)(
rp
[
3
]
*
2
);
if
(
box
.
size
.
width
>
box
.
size
.
height
)
{
float
tmp
;
CV_SWAP
(
box
.
size
.
width
,
box
.
size
.
height
,
tmp
);
box
.
angle
=
(
float
)(
90
+
rp
[
4
]
*
180
/
CV_PI
);
}
if
(
box
.
angle
<
-
180
)
box
.
angle
+=
360
;
if
(
box
.
angle
>
360
)
box
.
angle
-=
360
;
return
box
;
CV_IMPL
CvBox2D
cvFitEllipse2
(
const
CvArr
*
array
)
{
cv
::
AutoBuffer
<
double
>
abuf
;
cv
::
Mat
points
=
cv
::
cvarrToMat
(
array
,
false
,
false
,
0
,
&
abuf
);
return
cv
::
fitEllipse
(
points
);
}
/* Calculates bounding rectagnle of a point set or retrieves already calculated */
CV_IMPL
CvRect
cvBoundingRect
(
CvArr
*
array
,
int
update
)
...
...
@@ -977,210 +1089,17 @@ cvBoundingRect( CvArr* array, int update )
if
(
mat
)
{
CvSize
size
=
cvGetMatSize
(
mat
);
xmin
=
size
.
width
;
ymin
=
-
1
;
for
(
i
=
0
;
i
<
size
.
height
;
i
++
)
{
uchar
*
_ptr
=
mat
->
data
.
ptr
+
i
*
mat
->
step
;
uchar
*
ptr
=
(
uchar
*
)
cvAlignPtr
(
_ptr
,
4
);
int
have_nz
=
0
,
k_min
,
offset
=
(
int
)(
ptr
-
_ptr
);
j
=
0
;
offset
=
MIN
(
offset
,
size
.
width
);
for
(
;
j
<
offset
;
j
++
)
if
(
_ptr
[
j
]
)
{
have_nz
=
1
;
break
;
}
if
(
j
<
offset
)
{
if
(
j
<
xmin
)
xmin
=
j
;
if
(
j
>
xmax
)
xmax
=
j
;
}
if
(
offset
<
size
.
width
)
{
xmin
-=
offset
;
xmax
-=
offset
;
size
.
width
-=
offset
;
j
=
0
;
for
(
;
j
<=
xmin
-
4
;
j
+=
4
)
if
(
*
((
int
*
)(
ptr
+
j
))
)
break
;
for
(
;
j
<
xmin
;
j
++
)
if
(
ptr
[
j
]
)
{
xmin
=
j
;
if
(
j
>
xmax
)
xmax
=
j
;
have_nz
=
1
;
break
;
}
k_min
=
MAX
(
j
-
1
,
xmax
);
k
=
size
.
width
-
1
;
for
(
;
k
>
k_min
&&
(
k
&
3
)
!=
3
;
k
--
)
if
(
ptr
[
k
]
)
break
;
if
(
k
>
k_min
&&
(
k
&
3
)
==
3
)
{
for
(
;
k
>
k_min
+
3
;
k
-=
4
)
if
(
*
((
int
*
)(
ptr
+
k
-
3
))
)
break
;
}
for
(
;
k
>
k_min
;
k
--
)
if
(
ptr
[
k
]
)
{
xmax
=
k
;
have_nz
=
1
;
break
;
}
if
(
!
have_nz
)
{
j
&=
~
3
;
for
(
;
j
<=
k
-
3
;
j
+=
4
)
if
(
*
((
int
*
)(
ptr
+
j
))
)
break
;
for
(
;
j
<=
k
;
j
++
)
if
(
ptr
[
j
]
)
{
have_nz
=
1
;
break
;
}
}
xmin
+=
offset
;
xmax
+=
offset
;
size
.
width
+=
offset
;
}
if
(
have_nz
)
{
if
(
ymin
<
0
)
ymin
=
i
;
ymax
=
i
;
}
}
if
(
xmin
>=
size
.
width
)
xmin
=
ymin
=
0
;
rect
=
cv
::
maskBoundingRect
(
cv
::
cvarrToMat
(
mat
));
}
else
if
(
ptseq
->
total
)
{
int
is_float
=
CV_SEQ_ELTYPE
(
ptseq
)
==
CV_32FC2
;
cvStartReadSeq
(
ptseq
,
&
reader
,
0
);
CvPoint
pt
;
CV_READ_SEQ_ELEM
(
pt
,
reader
);
#if CV_SSE4_2
if
(
cv
::
checkHardwareSupport
(
CV_CPU_SSE4_2
))
{
if
(
!
is_float
)
{
__m128i
minval
,
maxval
;
minval
=
maxval
=
_mm_loadl_epi64
((
const
__m128i
*
)(
&
pt
));
//min[0]=pt.x, min[1]=pt.y
for
(
i
=
1
;
i
<
ptseq
->
total
;
i
++
)
{
__m128i
ptXY
=
_mm_loadl_epi64
((
const
__m128i
*
)(
reader
.
ptr
));
CV_NEXT_SEQ_ELEM
(
sizeof
(
pt
),
reader
);
minval
=
_mm_min_epi32
(
ptXY
,
minval
);
maxval
=
_mm_max_epi32
(
ptXY
,
maxval
);
}
xmin
=
_mm_cvtsi128_si32
(
minval
);
ymin
=
_mm_cvtsi128_si32
(
_mm_srli_si128
(
minval
,
4
));
xmax
=
_mm_cvtsi128_si32
(
maxval
);
ymax
=
_mm_cvtsi128_si32
(
_mm_srli_si128
(
maxval
,
4
));
}
else
{
__m128
minvalf
,
maxvalf
,
z
=
_mm_setzero_ps
(),
ptXY
=
_mm_setzero_ps
();
minvalf
=
maxvalf
=
_mm_loadl_pi
(
z
,
(
const
__m64
*
)(
&
pt
));
for
(
i
=
1
;
i
<
ptseq
->
total
;
i
++
)
{
ptXY
=
_mm_loadl_pi
(
ptXY
,
(
const
__m64
*
)
reader
.
ptr
);
CV_NEXT_SEQ_ELEM
(
sizeof
(
pt
),
reader
);
minvalf
=
_mm_min_ps
(
minvalf
,
ptXY
);
maxvalf
=
_mm_max_ps
(
maxvalf
,
ptXY
);
}
float
xyminf
[
2
],
xymaxf
[
2
];
_mm_storel_pi
((
__m64
*
)
xyminf
,
minvalf
);
_mm_storel_pi
((
__m64
*
)
xymaxf
,
maxvalf
);
xmin
=
cvFloor
(
xyminf
[
0
]);
ymin
=
cvFloor
(
xyminf
[
1
]);
xmax
=
cvFloor
(
xymaxf
[
0
]);
ymax
=
cvFloor
(
xymaxf
[
1
]);
}
}
else
#endif
{
if
(
!
is_float
)
{
xmin
=
xmax
=
pt
.
x
;
ymin
=
ymax
=
pt
.
y
;
for
(
i
=
1
;
i
<
ptseq
->
total
;
i
++
)
{
CV_READ_SEQ_ELEM
(
pt
,
reader
);
if
(
xmin
>
pt
.
x
)
xmin
=
pt
.
x
;
if
(
xmax
<
pt
.
x
)
xmax
=
pt
.
x
;
if
(
ymin
>
pt
.
y
)
ymin
=
pt
.
y
;
if
(
ymax
<
pt
.
y
)
ymax
=
pt
.
y
;
}
}
else
{
Cv32suf
v
;
// init values
xmin
=
xmax
=
CV_TOGGLE_FLT
(
pt
.
x
);
ymin
=
ymax
=
CV_TOGGLE_FLT
(
pt
.
y
);
for
(
i
=
1
;
i
<
ptseq
->
total
;
i
++
)
{
CV_READ_SEQ_ELEM
(
pt
,
reader
);
pt
.
x
=
CV_TOGGLE_FLT
(
pt
.
x
);
pt
.
y
=
CV_TOGGLE_FLT
(
pt
.
y
);
if
(
xmin
>
pt
.
x
)
xmin
=
pt
.
x
;
if
(
xmax
<
pt
.
x
)
xmax
=
pt
.
x
;
if
(
ymin
>
pt
.
y
)
ymin
=
pt
.
y
;
if
(
ymax
<
pt
.
y
)
ymax
=
pt
.
y
;
}
v
.
i
=
CV_TOGGLE_FLT
(
xmin
);
xmin
=
cvFloor
(
v
.
f
);
v
.
i
=
CV_TOGGLE_FLT
(
ymin
);
ymin
=
cvFloor
(
v
.
f
);
// because right and bottom sides of the bounding rectangle are not inclusive
// (note +1 in width and height calculation below), cvFloor is used here instead of cvCeil
v
.
i
=
CV_TOGGLE_FLT
(
xmax
);
xmax
=
cvFloor
(
v
.
f
);
v
.
i
=
CV_TOGGLE_FLT
(
ymax
);
ymax
=
cvFloor
(
v
.
f
);
}
}
rect
.
x
=
xmin
;
rect
.
y
=
ymin
;
rect
.
width
=
xmax
-
xmin
+
1
;
rect
.
height
=
ymax
-
ymin
+
1
;
cv
::
AutoBuffer
<
double
>
abuf
;
rect
=
cv
::
pointSetBoundingRect
(
cv
::
cvarrToMat
(
ptseq
,
false
,
false
,
0
,
&
abuf
));
}
if
(
update
)
((
CvContour
*
)
ptseq
)
->
rect
=
rect
;
return
rect
;
}
/* End of file. */
samples/cpp/minarea.cpp
View file @
dc4d0398
...
...
@@ -13,7 +13,7 @@ static void help()
"Random points are generated and then enclosed.
\n
"
"Call:
\n
"
"./minarea
\n
"
"Using OpenCV v
ersion %s
\n
"
<<
CV_VERSION
<<
"
\n
"
<<
endl
;
"Using OpenCV v"
<<
CV_VERSION
<<
"
\n
"
<<
endl
;
}
int
main
(
int
/*argc*/
,
char
**
/*argv*/
)
...
...
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