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
9124a76a
Commit
9124a76a
authored
Feb 12, 2013
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
converted moments function to C++
parent
59a5ba89
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
241 additions
and
276 deletions
+241
-276
moments.cpp
modules/imgproc/src/moments.cpp
+239
-276
test_moments.cpp
modules/imgproc/test/test_moments.cpp
+2
-0
No files found.
modules/imgproc/src/moments.cpp
View file @
9124a76a
...
...
@@ -40,21 +40,22 @@
//M*/
#include "precomp.hpp"
namespace
cv
{
// The function calculates center of gravity and the central second order moments
static
void
icvCompleteMomentState
(
Cv
Moments
*
moments
)
static
void
completeMomentState
(
Moments
*
moments
)
{
double
cx
=
0
,
cy
=
0
;
double
mu20
,
mu11
,
mu02
;
assert
(
moments
!=
0
);
moments
->
inv_sqrt_m00
=
0
;
if
(
fabs
(
moments
->
m00
)
>
DBL_EPSILON
)
{
double
inv_m00
=
1.
/
moments
->
m00
;
cx
=
moments
->
m10
*
inv_m00
;
cy
=
moments
->
m01
*
inv_m00
;
moments
->
inv_sqrt_m00
=
std
::
sqrt
(
fabs
(
inv_m00
)
);
}
// mu20 = m20 - m10*cx
...
...
@@ -80,115 +81,111 @@ static void icvCompleteMomentState( CvMoments* moments )
}
static
void
icvContourMoments
(
CvSeq
*
contour
,
CvMoments
*
moments
)
static
Moments
contourMoments
(
const
Mat
&
contour
)
{
int
is_float
=
CV_SEQ_ELTYPE
(
contour
)
==
CV_32FC2
;
Moments
m
;
int
lpt
=
contour
.
checkVector
(
2
);
int
is_float
=
contour
.
depth
()
==
CV_32F
;
const
Point
*
ptsi
=
(
const
Point
*
)
contour
.
data
;
const
Point2f
*
ptsf
=
(
const
Point2f
*
)
contour
.
data
;
if
(
contour
->
total
)
{
CvSeqReader
reader
;
double
a00
,
a10
,
a01
,
a20
,
a11
,
a02
,
a30
,
a21
,
a12
,
a03
;
double
xi
,
yi
,
xi2
,
yi2
,
xi_1
,
yi_1
,
xi_12
,
yi_12
,
dxy
,
xii_1
,
yii_1
;
int
lpt
=
contour
->
total
;
CV_Assert
(
contour
.
depth
()
==
CV_32S
||
contour
.
depth
()
==
CV_32F
);
a00
=
a10
=
a01
=
a20
=
a11
=
a02
=
a30
=
a21
=
a12
=
a03
=
0
;
if
(
lpt
==
0
)
return
m
;
double
a00
=
0
,
a10
=
0
,
a01
=
0
,
a20
=
0
,
a11
=
0
,
a02
=
0
,
a30
=
0
,
a21
=
0
,
a12
=
0
,
a03
=
0
;
double
xi
,
yi
,
xi2
,
yi2
,
xi_1
,
yi_1
,
xi_12
,
yi_12
,
dxy
,
xii_1
,
yii_1
;
if
(
!
is_float
)
{
xi_1
=
ptsi
[
lpt
-
1
].
x
;
yi_1
=
ptsi
[
lpt
-
1
].
y
;
}
else
{
xi_1
=
ptsf
[
lpt
-
1
].
x
;
yi_1
=
ptsf
[
lpt
-
1
].
y
;
}
cvStartReadSeq
(
contour
,
&
reader
,
0
);
xi_12
=
xi_1
*
xi_1
;
yi_12
=
yi_1
*
yi_1
;
for
(
int
i
=
0
;
i
<
lpt
;
i
++
)
{
if
(
!
is_float
)
{
xi
_1
=
((
CvPoint
*
)(
reader
.
ptr
))
->
x
;
yi
_1
=
((
CvPoint
*
)(
reader
.
ptr
))
->
y
;
xi
=
ptsi
[
i
].
x
;
yi
=
ptsi
[
i
].
y
;
}
else
{
xi
_1
=
((
CvPoint2D32f
*
)(
reader
.
ptr
))
->
x
;
yi
_1
=
((
CvPoint2D32f
*
)(
reader
.
ptr
))
->
y
;
xi
=
ptsf
[
i
].
x
;
yi
=
ptsf
[
i
].
y
;
}
CV_NEXT_SEQ_ELEM
(
contour
->
elem_size
,
reader
);
xi_12
=
xi_1
*
xi_1
;
yi_12
=
yi_1
*
yi_1
;
xi2
=
xi
*
xi
;
yi2
=
yi
*
yi
;
dxy
=
xi_1
*
yi
-
xi
*
yi_1
;
xii_1
=
xi_1
+
xi
;
yii_1
=
yi_1
+
yi
;
a00
+=
dxy
;
a10
+=
dxy
*
xii_1
;
a01
+=
dxy
*
yii_1
;
a20
+=
dxy
*
(
xi_1
*
xii_1
+
xi2
);
a11
+=
dxy
*
(
xi_1
*
(
yii_1
+
yi_1
)
+
xi
*
(
yii_1
+
yi
));
a02
+=
dxy
*
(
yi_1
*
yii_1
+
yi2
);
a30
+=
dxy
*
xii_1
*
(
xi_12
+
xi2
);
a03
+=
dxy
*
yii_1
*
(
yi_12
+
yi2
);
a21
+=
dxy
*
(
xi_12
*
(
3
*
yi_1
+
yi
)
+
2
*
xi
*
xi_1
*
yii_1
+
xi2
*
(
yi_1
+
3
*
yi
));
a12
+=
dxy
*
(
yi_12
*
(
3
*
xi_1
+
xi
)
+
2
*
yi
*
yi_1
*
xii_1
+
yi2
*
(
xi_1
+
3
*
xi
));
xi_1
=
xi
;
yi_1
=
yi
;
xi_12
=
xi2
;
yi_12
=
yi2
;
}
while
(
lpt
--
>
0
)
if
(
fabs
(
a00
)
>
FLT_EPSILON
)
{
double
db1_2
,
db1_6
,
db1_12
,
db1_24
,
db1_20
,
db1_60
;
if
(
a00
>
0
)
{
if
(
!
is_float
)
{
xi
=
((
CvPoint
*
)(
reader
.
ptr
))
->
x
;
yi
=
((
CvPoint
*
)(
reader
.
ptr
))
->
y
;
}
else
{
xi
=
((
CvPoint2D32f
*
)(
reader
.
ptr
))
->
x
;
yi
=
((
CvPoint2D32f
*
)(
reader
.
ptr
))
->
y
;
}
CV_NEXT_SEQ_ELEM
(
contour
->
elem_size
,
reader
);
xi2
=
xi
*
xi
;
yi2
=
yi
*
yi
;
dxy
=
xi_1
*
yi
-
xi
*
yi_1
;
xii_1
=
xi_1
+
xi
;
yii_1
=
yi_1
+
yi
;
a00
+=
dxy
;
a10
+=
dxy
*
xii_1
;
a01
+=
dxy
*
yii_1
;
a20
+=
dxy
*
(
xi_1
*
xii_1
+
xi2
);
a11
+=
dxy
*
(
xi_1
*
(
yii_1
+
yi_1
)
+
xi
*
(
yii_1
+
yi
));
a02
+=
dxy
*
(
yi_1
*
yii_1
+
yi2
);
a30
+=
dxy
*
xii_1
*
(
xi_12
+
xi2
);
a03
+=
dxy
*
yii_1
*
(
yi_12
+
yi2
);
a21
+=
dxy
*
(
xi_12
*
(
3
*
yi_1
+
yi
)
+
2
*
xi
*
xi_1
*
yii_1
+
xi2
*
(
yi_1
+
3
*
yi
));
a12
+=
dxy
*
(
yi_12
*
(
3
*
xi_1
+
xi
)
+
2
*
yi
*
yi_1
*
xii_1
+
yi2
*
(
xi_1
+
3
*
xi
));
xi_1
=
xi
;
yi_1
=
yi
;
xi_12
=
xi2
;
yi_12
=
yi2
;
db1_2
=
0.5
;
db1_6
=
0.16666666666666666666666666666667
;
db1_12
=
0.083333333333333333333333333333333
;
db1_24
=
0.041666666666666666666666666666667
;
db1_20
=
0.05
;
db1_60
=
0.016666666666666666666666666666667
;
}
double
db1_2
,
db1_6
,
db1_12
,
db1_24
,
db1_20
,
db1_60
;
if
(
fabs
(
a00
)
>
FLT_EPSILON
)
else
{
if
(
a00
>
0
)
{
db1_2
=
0.5
;
db1_6
=
0.16666666666666666666666666666667
;
db1_12
=
0.083333333333333333333333333333333
;
db1_24
=
0.041666666666666666666666666666667
;
db1_20
=
0.05
;
db1_60
=
0.016666666666666666666666666666667
;
}
else
{
db1_2
=
-
0.5
;
db1_6
=
-
0.16666666666666666666666666666667
;
db1_12
=
-
0.083333333333333333333333333333333
;
db1_24
=
-
0.041666666666666666666666666666667
;
db1_20
=
-
0.05
;
db1_60
=
-
0.016666666666666666666666666666667
;
}
// spatial moments
moments
->
m00
=
a00
*
db1_2
;
moments
->
m10
=
a10
*
db1_6
;
moments
->
m01
=
a01
*
db1_6
;
moments
->
m20
=
a20
*
db1_12
;
moments
->
m11
=
a11
*
db1_24
;
moments
->
m02
=
a02
*
db1_12
;
moments
->
m30
=
a30
*
db1_20
;
moments
->
m21
=
a21
*
db1_60
;
moments
->
m12
=
a12
*
db1_60
;
moments
->
m03
=
a03
*
db1_20
;
icvCompleteMomentState
(
moments
);
db1_2
=
-
0.5
;
db1_6
=
-
0.16666666666666666666666666666667
;
db1_12
=
-
0.083333333333333333333333333333333
;
db1_24
=
-
0.041666666666666666666666666666667
;
db1_20
=
-
0.05
;
db1_60
=
-
0.016666666666666666666666666666667
;
}
// spatial moments
m
.
m00
=
a00
*
db1_2
;
m
.
m10
=
a10
*
db1_6
;
m
.
m01
=
a01
*
db1_6
;
m
.
m20
=
a20
*
db1_12
;
m
.
m11
=
a11
*
db1_24
;
m
.
m02
=
a02
*
db1_12
;
m
.
m30
=
a30
*
db1_20
;
m
.
m21
=
a21
*
db1_60
;
m
.
m12
=
a12
*
db1_60
;
m
.
m03
=
a03
*
db1_20
;
completeMomentState
(
&
m
);
}
return
m
;
}
...
...
@@ -197,9 +194,9 @@ static void icvContourMoments( CvSeq* contour, CvMoments* moments )
\****************************************************************************************/
template
<
typename
T
,
typename
WT
,
typename
MT
>
static
void
momentsInTile
(
const
cv
::
Mat
&
img
,
double
*
moments
)
static
void
momentsInTile
(
const
Mat
&
img
,
double
*
moments
)
{
cv
::
Size
size
=
img
.
size
();
Size
size
=
img
.
size
();
int
x
,
y
;
MT
mom
[
10
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
...
...
@@ -247,10 +244,10 @@ template<> void momentsInTile<uchar, int, int>( const cv::Mat& img, double* mome
typedef
uchar
T
;
typedef
int
WT
;
typedef
int
MT
;
cv
::
Size
size
=
img
.
size
();
Size
size
=
img
.
size
();
int
y
;
MT
mom
[
10
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
bool
useSIMD
=
c
v
::
c
heckHardwareSupport
(
CV_CPU_SSE2
);
bool
useSIMD
=
checkHardwareSupport
(
CV_CPU_SSE2
);
for
(
y
=
0
;
y
<
size
.
height
;
y
++
)
{
...
...
@@ -318,62 +315,89 @@ template<> void momentsInTile<uchar, int, int>( const cv::Mat& img, double* mome
#endif
typedef
void
(
*
CvMomentsInTileFunc
)(
const
cv
::
Mat
&
img
,
double
*
moments
);
typedef
void
(
*
MomentsInTileFunc
)(
const
Mat
&
img
,
double
*
moments
);
CV_IMPL
void
cvMoments
(
const
void
*
array
,
CvMoments
*
moments
,
int
binary
)
Moments
::
Moments
(
)
{
const
int
TILE_SIZE
=
32
;
int
type
,
depth
,
cn
,
coi
=
0
;
CvMat
stub
,
*
mat
=
(
CvMat
*
)
array
;
CvMomentsInTileFunc
func
=
0
;
CvContour
contourHeader
;
CvSeq
*
contour
=
0
;
CvSeqBlock
block
;
double
buf
[
TILE_SIZE
*
TILE_SIZE
];
uchar
nzbuf
[
TILE_SIZE
*
TILE_SIZE
];
m00
=
m10
=
m01
=
m20
=
m11
=
m02
=
m30
=
m21
=
m12
=
m03
=
mu20
=
mu11
=
mu02
=
mu30
=
mu21
=
mu12
=
mu03
=
nu20
=
nu11
=
nu02
=
nu30
=
nu21
=
nu12
=
nu03
=
0.
;
}
Moments
::
Moments
(
double
_m00
,
double
_m10
,
double
_m01
,
double
_m20
,
double
_m11
,
double
_m02
,
double
_m30
,
double
_m21
,
double
_m12
,
double
_m03
)
{
m00
=
_m00
;
m10
=
_m10
;
m01
=
_m01
;
m20
=
_m20
;
m11
=
_m11
;
m02
=
_m02
;
m30
=
_m30
;
m21
=
_m21
;
m12
=
_m12
;
m03
=
_m03
;
if
(
CV_IS_SEQ
(
array
))
double
cx
=
0
,
cy
=
0
,
inv_m00
=
0
;
if
(
std
::
abs
(
m00
)
>
DBL_EPSILON
)
{
contour
=
(
CvSeq
*
)
array
;
if
(
!
CV_IS_SEQ_POINT_SET
(
contour
))
CV_Error
(
CV_StsBadArg
,
"The passed sequence is not a valid contour"
);
inv_m00
=
1.
/
m00
;
cx
=
m10
*
inv_m00
;
cy
=
m01
*
inv_m00
;
}
if
(
!
moments
)
CV_Error
(
CV_StsNullPtr
,
""
);
mu20
=
m20
-
m10
*
cx
;
mu11
=
m11
-
m10
*
cy
;
mu02
=
m02
-
m01
*
cy
;
memset
(
moments
,
0
,
sizeof
(
*
moments
));
mu30
=
m30
-
cx
*
(
3
*
mu20
+
cx
*
m10
);
mu21
=
m21
-
cx
*
(
2
*
mu11
+
cx
*
m01
)
-
cy
*
mu20
;
mu12
=
m12
-
cy
*
(
2
*
mu11
+
cy
*
m10
)
-
cx
*
mu02
;
mu03
=
m03
-
cy
*
(
3
*
mu02
+
cy
*
m01
);
if
(
!
contour
)
{
mat
=
cvGetMat
(
mat
,
&
stub
,
&
coi
);
type
=
CV_MAT_TYPE
(
mat
->
type
);
double
inv_sqrt_m00
=
std
::
sqrt
(
std
::
abs
(
inv_m00
));
double
s2
=
inv_m00
*
inv_m00
,
s3
=
s2
*
inv_sqrt_m00
;
if
(
type
==
CV_32SC2
||
type
==
CV_32FC2
)
{
contour
=
cvPointSeqFromMat
(
CV_SEQ_KIND_CURVE
|
CV_SEQ_FLAG_CLOSED
,
mat
,
&
contourHeader
,
&
block
);
}
}
nu20
=
mu20
*
s2
;
nu11
=
mu11
*
s2
;
nu02
=
mu02
*
s2
;
nu30
=
mu30
*
s3
;
nu21
=
mu21
*
s3
;
nu12
=
mu12
*
s3
;
nu03
=
mu03
*
s3
;
}
if
(
contour
)
{
icvContourMoments
(
contour
,
moments
);
return
;
}
Moments
::
Moments
(
const
CvMoments
&
m
)
{
*
this
=
Moments
(
m
.
m00
,
m
.
m10
,
m
.
m01
,
m
.
m20
,
m
.
m11
,
m
.
m02
,
m
.
m30
,
m
.
m21
,
m
.
m12
,
m
.
m03
);
}
Moments
::
operator
CvMoments
()
const
{
CvMoments
m
;
m
.
m00
=
m00
;
m
.
m10
=
m10
;
m
.
m01
=
m01
;
m
.
m20
=
m20
;
m
.
m11
=
m11
;
m
.
m02
=
m02
;
m
.
m30
=
m30
;
m
.
m21
=
m21
;
m
.
m12
=
m12
;
m
.
m03
=
m03
;
m
.
mu20
=
mu20
;
m
.
mu11
=
mu11
;
m
.
mu02
=
mu02
;
m
.
mu30
=
mu30
;
m
.
mu21
=
mu21
;
m
.
mu12
=
mu12
;
m
.
mu03
=
mu03
;
double
am00
=
std
::
abs
(
m00
);
m
.
inv_sqrt_m00
=
am00
>
DBL_EPSILON
?
1.
/
std
::
sqrt
(
am00
)
:
0
;
return
m
;
}
}
cv
::
Moments
cv
::
moments
(
InputArray
_src
,
bool
binary
)
{
const
int
TILE_SIZE
=
32
;
Mat
mat
=
_src
.
getMat
();
MomentsInTileFunc
func
=
0
;
double
buf
[
TILE_SIZE
*
TILE_SIZE
];
uchar
nzbuf
[
TILE_SIZE
*
TILE_SIZE
];
Moments
m
;
int
type
=
mat
.
type
();
int
depth
=
CV_MAT_DEPTH
(
type
);
int
cn
=
CV_MAT_CN
(
type
);
type
=
CV_MAT_TYPE
(
mat
->
type
);
depth
=
CV_MAT_DEPTH
(
type
);
cn
=
CV_MAT_CN
(
type
);
if
(
mat
.
checkVector
(
2
)
>=
0
&&
(
depth
==
CV_32F
||
depth
==
CV_32S
))
return
contourMoments
(
mat
);
cv
::
Size
size
=
cvGetMatSize
(
mat
);
Size
size
=
mat
.
size
(
);
if
(
cn
>
1
&&
coi
==
0
)
if
(
cn
>
1
)
CV_Error
(
CV_StsBadArg
,
"Invalid image type"
);
if
(
size
.
width
<=
0
||
size
.
height
<=
0
)
return
;
return
m
;
if
(
binary
||
depth
==
CV_8U
)
func
=
momentsInTile
<
uchar
,
int
,
int
>
;
...
...
@@ -388,25 +412,18 @@ CV_IMPL void cvMoments( const void* array, CvMoments* moments, int binary )
else
CV_Error
(
CV_StsUnsupportedFormat
,
""
);
cv
::
Mat
src0
(
mat
);
Mat
src0
(
mat
);
for
(
int
y
=
0
;
y
<
size
.
height
;
y
+=
TILE_SIZE
)
{
cv
::
Size
tileSize
;
Size
tileSize
;
tileSize
.
height
=
std
::
min
(
TILE_SIZE
,
size
.
height
-
y
);
for
(
int
x
=
0
;
x
<
size
.
width
;
x
+=
TILE_SIZE
)
{
tileSize
.
width
=
std
::
min
(
TILE_SIZE
,
size
.
width
-
x
);
cv
::
Mat
src
(
src0
,
cv
::
Rect
(
x
,
y
,
tileSize
.
width
,
tileSize
.
height
));
Mat
src
(
src0
,
cv
::
Rect
(
x
,
y
,
tileSize
.
width
,
tileSize
.
height
));
if
(
coi
>
0
)
{
cv
::
Mat
tmp
(
tileSize
,
depth
,
buf
);
int
pairs
[]
=
{
coi
-
1
,
0
};
cv
::
mixChannels
(
&
src
,
1
,
&
tmp
,
1
,
pairs
,
1
);
src
=
tmp
;
}
if
(
binary
)
{
cv
::
Mat
tmp
(
tileSize
,
CV_8U
,
nzbuf
);
...
...
@@ -429,77 +446,89 @@ CV_IMPL void cvMoments( const void* array, CvMoments* moments, int binary )
// accumulate moments computed in each tile
// + m00 ( = m00' )
m
oments
->
m00
+=
mom
[
0
];
m
.
m00
+=
mom
[
0
];
// + m10 ( = m10' + x*m00' )
m
oments
->
m10
+=
mom
[
1
]
+
xm
;
m
.
m10
+=
mom
[
1
]
+
xm
;
// + m01 ( = m01' + y*m00' )
m
oments
->
m01
+=
mom
[
2
]
+
ym
;
m
.
m01
+=
mom
[
2
]
+
ym
;
// + m20 ( = m20' + 2*x*m10' + x*x*m00' )
m
oments
->
m20
+=
mom
[
3
]
+
x
*
(
mom
[
1
]
*
2
+
xm
);
m
.
m20
+=
mom
[
3
]
+
x
*
(
mom
[
1
]
*
2
+
xm
);
// + m11 ( = m11' + x*m01' + y*m10' + x*y*m00' )
m
oments
->
m11
+=
mom
[
4
]
+
x
*
(
mom
[
2
]
+
ym
)
+
y
*
mom
[
1
];
m
.
m11
+=
mom
[
4
]
+
x
*
(
mom
[
2
]
+
ym
)
+
y
*
mom
[
1
];
// + m02 ( = m02' + 2*y*m01' + y*y*m00' )
m
oments
->
m02
+=
mom
[
5
]
+
y
*
(
mom
[
2
]
*
2
+
ym
);
m
.
m02
+=
mom
[
5
]
+
y
*
(
mom
[
2
]
*
2
+
ym
);
// + m30 ( = m30' + 3*x*m20' + 3*x*x*m10' + x*x*x*m00' )
m
oments
->
m30
+=
mom
[
6
]
+
x
*
(
3.
*
mom
[
3
]
+
x
*
(
3.
*
mom
[
1
]
+
xm
));
m
.
m30
+=
mom
[
6
]
+
x
*
(
3.
*
mom
[
3
]
+
x
*
(
3.
*
mom
[
1
]
+
xm
));
// + m21 ( = m21' + x*(2*m11' + 2*y*m10' + x*m01' + x*y*m00') + y*m20')
m
oments
->
m21
+=
mom
[
7
]
+
x
*
(
2
*
(
mom
[
4
]
+
y
*
mom
[
1
])
+
x
*
(
mom
[
2
]
+
ym
))
+
y
*
mom
[
3
];
m
.
m21
+=
mom
[
7
]
+
x
*
(
2
*
(
mom
[
4
]
+
y
*
mom
[
1
])
+
x
*
(
mom
[
2
]
+
ym
))
+
y
*
mom
[
3
];
// + m12 ( = m12' + y*(2*m11' + 2*x*m01' + y*m10' + x*y*m00') + x*m02')
m
oments
->
m12
+=
mom
[
8
]
+
y
*
(
2
*
(
mom
[
4
]
+
x
*
mom
[
2
])
+
y
*
(
mom
[
1
]
+
xm
))
+
x
*
mom
[
5
];
m
.
m12
+=
mom
[
8
]
+
y
*
(
2
*
(
mom
[
4
]
+
x
*
mom
[
2
])
+
y
*
(
mom
[
1
]
+
xm
))
+
x
*
mom
[
5
];
// + m03 ( = m03' + 3*y*m02' + 3*y*y*m01' + y*y*y*m00' )
m
oments
->
m03
+=
mom
[
9
]
+
y
*
(
3.
*
mom
[
5
]
+
y
*
(
3.
*
mom
[
2
]
+
ym
));
m
.
m03
+=
mom
[
9
]
+
y
*
(
3.
*
mom
[
5
]
+
y
*
(
3.
*
mom
[
2
]
+
ym
));
}
}
icvCompleteMomentState
(
moments
);
completeMomentState
(
&
m
);
return
m
;
}
CV_IMPL
void
cvGetHuMoments
(
CvMoments
*
mState
,
CvHuMoments
*
HuState
)
void
cv
::
HuMoments
(
const
Moments
&
m
,
double
hu
[
7
]
)
{
if
(
!
mState
||
!
HuState
)
CV_Error
(
CV_StsNullPtr
,
""
);
double
m00s
=
mState
->
inv_sqrt_m00
,
m00
=
m00s
*
m00s
,
s2
=
m00
*
m00
,
s3
=
s2
*
m00s
;
double
nu20
=
mState
->
mu20
*
s2
,
nu11
=
mState
->
mu11
*
s2
,
nu02
=
mState
->
mu02
*
s2
,
nu30
=
mState
->
mu30
*
s3
,
nu21
=
mState
->
mu21
*
s3
,
nu12
=
mState
->
mu12
*
s3
,
nu03
=
mState
->
mu03
*
s3
;
double
t0
=
nu30
+
nu12
;
double
t1
=
nu21
+
nu03
;
double
t0
=
m
.
nu30
+
m
.
nu12
;
double
t1
=
m
.
nu21
+
m
.
nu03
;
double
q0
=
t0
*
t0
,
q1
=
t1
*
t1
;
double
n4
=
4
*
nu11
;
double
s
=
nu20
+
nu02
;
double
d
=
nu20
-
nu02
;
double
n4
=
4
*
m
.
nu11
;
double
s
=
m
.
nu20
+
m
.
nu02
;
double
d
=
m
.
nu20
-
m
.
nu02
;
HuState
->
hu1
=
s
;
HuState
->
hu2
=
d
*
d
+
n4
*
nu11
;
HuState
->
hu4
=
q0
+
q1
;
HuState
->
hu6
=
d
*
(
q0
-
q1
)
+
n4
*
t0
*
t1
;
hu
[
0
]
=
s
;
hu
[
1
]
=
d
*
d
+
n4
*
m
.
nu11
;
hu
[
3
]
=
q0
+
q1
;
hu
[
5
]
=
d
*
(
q0
-
q1
)
+
n4
*
t0
*
t1
;
t0
*=
q0
-
3
*
q1
;
t1
*=
3
*
q0
-
q1
;
q0
=
nu30
-
3
*
nu12
;
q1
=
3
*
nu21
-
nu03
;
q0
=
m
.
nu30
-
3
*
m
.
nu12
;
q1
=
3
*
m
.
nu21
-
m
.
nu03
;
HuState
->
hu3
=
q0
*
q0
+
q1
*
q1
;
HuState
->
hu5
=
q0
*
t0
+
q1
*
t1
;
HuState
->
hu7
=
q1
*
t0
-
q0
*
t1
;
hu
[
2
]
=
q0
*
q0
+
q1
*
q1
;
hu
[
4
]
=
q0
*
t0
+
q1
*
t1
;
hu
[
6
]
=
q1
*
t0
-
q0
*
t1
;
}
void
cv
::
HuMoments
(
const
Moments
&
m
,
OutputArray
_hu
)
{
_hu
.
create
(
7
,
1
,
CV_64F
);
Mat
hu
=
_hu
.
getMat
();
CV_Assert
(
hu
.
isContinuous
()
);
HuMoments
(
m
,
(
double
*
)
hu
.
data
);
}
CV_IMPL
void
cvMoments
(
const
CvArr
*
arr
,
CvMoments
*
moments
,
int
binary
)
{
const
IplImage
*
img
=
(
const
IplImage
*
)
arr
;
cv
::
Mat
src
;
if
(
CV_IS_IMAGE
(
arr
)
&&
img
->
roi
&&
img
->
roi
->
coi
>
0
)
cv
::
extractImageCOI
(
arr
,
src
,
img
->
roi
->
coi
-
1
);
else
src
=
cv
::
cvarrToMat
(
arr
);
cv
::
Moments
m
=
cv
::
moments
(
src
,
binary
!=
0
);
CV_Assert
(
moments
!=
0
);
*
moments
=
m
;
}
...
...
@@ -526,7 +555,7 @@ CV_IMPL double cvGetCentralMoment( CvMoments * moments, int x_order, int y_order
CV_Error
(
CV_StsOutOfRange
,
""
);
return
order
>=
2
?
(
&
(
moments
->
m00
))[
4
+
order
*
3
+
y_order
]
:
order
==
0
?
moments
->
m00
:
0
;
order
==
0
?
moments
->
m00
:
0
;
}
...
...
@@ -543,109 +572,43 @@ CV_IMPL double cvGetNormalizedCentralMoment( CvMoments * moments, int x_order, i
}
namespace
cv
{
Moments
::
Moments
()
{
m00
=
m10
=
m01
=
m20
=
m11
=
m02
=
m30
=
m21
=
m12
=
m03
=
mu20
=
mu11
=
mu02
=
mu30
=
mu21
=
mu12
=
mu03
=
nu20
=
nu11
=
nu02
=
nu30
=
nu21
=
nu12
=
nu03
=
0.
;
}
Moments
::
Moments
(
double
_m00
,
double
_m10
,
double
_m01
,
double
_m20
,
double
_m11
,
double
_m02
,
double
_m30
,
double
_m21
,
double
_m12
,
double
_m03
)
{
m00
=
_m00
;
m10
=
_m10
;
m01
=
_m01
;
m20
=
_m20
;
m11
=
_m11
;
m02
=
_m02
;
m30
=
_m30
;
m21
=
_m21
;
m12
=
_m12
;
m03
=
_m03
;
double
cx
=
0
,
cy
=
0
,
inv_m00
=
0
;
if
(
std
::
abs
(
m00
)
>
DBL_EPSILON
)
{
inv_m00
=
1.
/
m00
;
cx
=
m10
*
inv_m00
;
cy
=
m01
*
inv_m00
;
}
mu20
=
m20
-
m10
*
cx
;
mu11
=
m11
-
m10
*
cy
;
mu02
=
m02
-
m01
*
cy
;
mu30
=
m30
-
cx
*
(
3
*
mu20
+
cx
*
m10
);
mu21
=
m21
-
cx
*
(
2
*
mu11
+
cx
*
m01
)
-
cy
*
mu20
;
mu12
=
m12
-
cy
*
(
2
*
mu11
+
cy
*
m10
)
-
cx
*
mu02
;
mu03
=
m03
-
cy
*
(
3
*
mu02
+
cy
*
m01
);
double
inv_sqrt_m00
=
std
::
sqrt
(
std
::
abs
(
inv_m00
));
double
s2
=
inv_m00
*
inv_m00
,
s3
=
s2
*
inv_sqrt_m00
;
nu20
=
mu20
*
s2
;
nu11
=
mu11
*
s2
;
nu02
=
mu02
*
s2
;
nu30
=
mu30
*
s3
;
nu21
=
mu21
*
s3
;
nu12
=
mu12
*
s3
;
nu03
=
mu03
*
s3
;
}
Moments
::
Moments
(
const
CvMoments
&
m
)
{
*
this
=
Moments
(
m
.
m00
,
m
.
m10
,
m
.
m01
,
m
.
m20
,
m
.
m11
,
m
.
m02
,
m
.
m30
,
m
.
m21
,
m
.
m12
,
m
.
m03
);
}
Moments
::
operator
CvMoments
()
const
CV_IMPL
void
cvGetHuMoments
(
CvMoments
*
mState
,
CvHuMoments
*
HuState
)
{
CvMoments
m
;
m
.
m00
=
m00
;
m
.
m10
=
m10
;
m
.
m01
=
m01
;
m
.
m20
=
m20
;
m
.
m11
=
m11
;
m
.
m02
=
m02
;
m
.
m30
=
m30
;
m
.
m21
=
m21
;
m
.
m12
=
m12
;
m
.
m03
=
m03
;
m
.
mu20
=
mu20
;
m
.
mu11
=
mu11
;
m
.
mu02
=
mu02
;
m
.
mu30
=
mu30
;
m
.
mu21
=
mu21
;
m
.
mu12
=
mu12
;
m
.
mu03
=
mu03
;
double
am00
=
std
::
abs
(
m00
);
m
.
inv_sqrt_m00
=
am00
>
DBL_EPSILON
?
1.
/
std
::
sqrt
(
am00
)
:
0
;
return
m
;
}
if
(
!
mState
||
!
HuState
)
CV_Error
(
CV_StsNullPtr
,
""
);
}
double
m00s
=
mState
->
inv_sqrt_m00
,
m00
=
m00s
*
m00s
,
s2
=
m00
*
m00
,
s3
=
s2
*
m00s
;
cv
::
Moments
cv
::
moments
(
InputArray
_array
,
bool
binaryImage
)
{
CvMoments
om
;
Mat
arr
=
_array
.
getMat
();
CvMat
c_array
=
arr
;
cvMoments
(
&
c_array
,
&
om
,
binaryImage
);
return
om
;
}
double
nu20
=
mState
->
mu20
*
s2
,
nu11
=
mState
->
mu11
*
s2
,
nu02
=
mState
->
mu02
*
s2
,
nu30
=
mState
->
mu30
*
s3
,
nu21
=
mState
->
mu21
*
s3
,
nu12
=
mState
->
mu12
*
s3
,
nu03
=
mState
->
mu03
*
s3
;
void
cv
::
HuMoments
(
const
Moments
&
m
,
double
hu
[
7
]
)
{
double
t0
=
m
.
nu30
+
m
.
nu12
;
double
t1
=
m
.
nu21
+
m
.
nu03
;
double
t0
=
nu30
+
nu12
;
double
t1
=
nu21
+
nu03
;
double
q0
=
t0
*
t0
,
q1
=
t1
*
t1
;
double
n4
=
4
*
m
.
nu11
;
double
s
=
m
.
nu20
+
m
.
nu02
;
double
d
=
m
.
nu20
-
m
.
nu02
;
double
n4
=
4
*
nu11
;
double
s
=
nu20
+
nu02
;
double
d
=
nu20
-
nu02
;
hu
[
0
]
=
s
;
hu
[
1
]
=
d
*
d
+
n4
*
m
.
nu11
;
hu
[
3
]
=
q0
+
q1
;
hu
[
5
]
=
d
*
(
q0
-
q1
)
+
n4
*
t0
*
t1
;
HuState
->
hu1
=
s
;
HuState
->
hu2
=
d
*
d
+
n4
*
nu11
;
HuState
->
hu4
=
q0
+
q1
;
HuState
->
hu6
=
d
*
(
q0
-
q1
)
+
n4
*
t0
*
t1
;
t0
*=
q0
-
3
*
q1
;
t1
*=
3
*
q0
-
q1
;
q0
=
m
.
nu30
-
3
*
m
.
nu12
;
q1
=
3
*
m
.
nu21
-
m
.
nu03
;
q0
=
nu30
-
3
*
nu12
;
q1
=
3
*
nu21
-
nu03
;
hu
[
2
]
=
q0
*
q0
+
q1
*
q1
;
hu
[
4
]
=
q0
*
t0
+
q1
*
t1
;
hu
[
6
]
=
q1
*
t0
-
q0
*
t1
;
HuState
->
hu3
=
q0
*
q0
+
q1
*
q1
;
HuState
->
hu5
=
q0
*
t0
+
q1
*
t1
;
HuState
->
hu7
=
q1
*
t0
-
q0
*
t1
;
}
void
cv
::
HuMoments
(
const
Moments
&
m
,
OutputArray
_hu
)
{
_hu
.
create
(
7
,
1
,
CV_64F
);
Mat
hu
=
_hu
.
getMat
();
CV_Assert
(
hu
.
isContinuous
()
);
HuMoments
(
m
,
(
double
*
)
hu
.
data
);
}
/* End of file. */
modules/imgproc/test/test_moments.cpp
View file @
9124a76a
...
...
@@ -111,6 +111,8 @@ void CV_MomentsTest::get_test_array_types_and_sizes( int test_case_idx,
types
[
INPUT
][
0
]
=
CV_MAKETYPE
(
depth
,
cn
);
types
[
OUTPUT
][
0
]
=
types
[
REF_OUTPUT
][
0
]
=
CV_64FC1
;
sizes
[
OUTPUT
][
0
]
=
sizes
[
REF_OUTPUT
][
0
]
=
cvSize
(
MOMENT_COUNT
,
1
);
if
(
CV_MAT_DEPTH
(
types
[
INPUT
][
0
])
>=
CV_32S
)
sizes
[
INPUT
][
0
].
width
=
MAX
(
sizes
[
INPUT
][
0
].
width
,
3
);
is_binary
=
cvtest
::
randInt
(
rng
)
%
2
!=
0
;
coi
=
0
;
...
...
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