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
2a42960f
Commit
2a42960f
authored
Dec 15, 2012
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://github.com/nevion/opencv
into cc
parents
aabb40e3
ad0bfdfb
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
620 additions
and
21 deletions
+620
-21
structural_analysis_and_shape_descriptors.rst
...imgproc/doc/structural_analysis_and_shape_descriptors.rst
+42
-0
imgproc.hpp
modules/imgproc/include/opencv2/imgproc/imgproc.hpp
+9
-0
connectedcomponents.cpp
modules/imgproc/src/connectedcomponents.cpp
+437
-0
test_connectedcomponents.cpp
modules/imgproc/test/test_connectedcomponents.cpp
+108
-0
cv2.cpp
modules/python/src2/cv2.cpp
+9
-2
connected_components.cpp
samples/cpp/connected_components.cpp
+15
-19
No files found.
modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst
View file @
2a42960f
...
...
@@ -118,6 +118,48 @@ These values are proved to be invariants to the image scale, rotation, and refle
.. seealso:: :ocv:func:`matchShapes`
connectedComponents
-----------
computes the connected components labeled image of boolean image I with 4 or 8 way connectivity - returns N, the total
number of labels [0, N-1] where 0 represents the background label. L's value type determines the label type, an important
consideration based on the total number of labels or alternatively the total number of pixels.
.. ocv:function:: uint64 connectedComponents(Mat &L, const Mat &I, int connectivity = 8)
.. ocv:function:: uint64 connectedComponentsWithStats(Mat &L, const Mat &I, std::vector<ConnectedComponentStats> &statsv, int connectivity = 8)
:param L: destitination Labeled image
:param I: the image to be labeled
:param connectivity: 8 or 4 for 8-way or 4-way connectivity respectively
:param statsv: statistics for each label, including the background label
Statistics information such as bounding box, area, and centroid is exported via the ``ConnectComponentStats`` structure defined as: ::
class CV_EXPORTS ConnectedComponentStats
{
public:
//! lower left corner column
int lower_x;
//! lower left corner row
int lower_y;
//! upper right corner column
int upper_x;
//! upper right corner row
int upper_y;
//! centroid column
double centroid_x;
//! centroid row
double centroid_y;
//! sum of all columns where the image was non-zero
uint64 integral_x;
//! sum of all rows where the image was non-zero
uint64 integral_y;
//! count of all non-zero pixels
unsigned int area;
};
findContours
----------------
...
...
modules/imgproc/include/opencv2/imgproc/imgproc.hpp
View file @
2a42960f
...
...
@@ -1102,6 +1102,15 @@ enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF
CV_EXPORTS_W
void
matchTemplate
(
InputArray
image
,
InputArray
templ
,
OutputArray
result
,
int
method
);
enum
{
CC_STAT_LEFT
=
0
,
CC_STAT_TOP
=
1
,
CC_STAT_WIDTH
=
2
,
CC_STAT_HEIGHT
=
3
,
CC_STAT_AREA
=
4
,
CC_STAT_MAX
=
5
};
//! computes the connected components labeled image of boolean image I with 4 or 8 way connectivity - returns N, the total
//number of labels [0, N-1] where 0 represents the background label. L's value type determines the label type, an important
//consideration based on the total number of labels or alternatively the total number of pixels.
CV_EXPORTS_W
int
connectedComponents
(
InputArray
image
,
OutputArray
labels
,
int
connectivity
=
8
,
int
ltype
=
CV_32S
);
CV_EXPORTS_W
int
connectedComponentsWithStats
(
InputArray
image
,
OutputArray
labels
,
OutputArray
stats
,
OutputArray
centroids
,
int
connectivity
=
8
,
int
ltype
=
CV_32S
);
//! mode of the contour retrieval algorithm
enum
{
...
...
modules/imgproc/src/connectedcomponents.cpp
0 → 100644
View file @
2a42960f
/*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 Corporation 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 Corporation 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.
//
// 2011 Jason Newton <nevion@gmail.com>
//M*/
//
#include "precomp.hpp"
#include <vector>
#if defined _MSC_VER
#pragma warning(disable: 4127)
#endif
namespace
cv
{
namespace
connectedcomponents
{
template
<
typename
LabelT
>
struct
NoOp
{
NoOp
(){
}
void
init
(
const
LabelT
labels
){
(
void
)
labels
;
}
inline
void
operator
()(
int
r
,
int
c
,
LabelT
l
){
(
void
)
r
;
(
void
)
c
;
(
void
)
l
;
}
void
finish
(){}
};
struct
Point2ui64
{
uint64
x
,
y
;
Point2ui64
(
uint64
_x
,
uint64
_y
)
:
x
(
_x
),
y
(
_y
){}
};
template
<
typename
LabelT
>
struct
CCStatsOp
{
OutputArray
_mstatsv
;
cv
::
Mat
statsv
;
OutputArray
_mcentroidsv
;
cv
::
Mat
centroidsv
;
std
::
vector
<
Point2ui64
>
integrals
;
CCStatsOp
(
OutputArray
_statsv
,
OutputArray
_centroidsv
)
:
_mstatsv
(
_statsv
),
_mcentroidsv
(
_centroidsv
){
}
inline
void
init
(
const
LabelT
nlabels
){
_mstatsv
.
create
(
cv
::
Size
(
nlabels
,
CC_STAT_MAX
),
cv
::
DataType
<
int
>::
type
);
statsv
=
_mstatsv
.
getMat
();
_mcentroidsv
.
create
(
cv
::
Size
(
nlabels
,
2
),
cv
::
DataType
<
double
>::
type
);
centroidsv
=
_mcentroidsv
.
getMat
();
for
(
int
l
=
0
;
l
<
(
int
)
nlabels
;
++
l
){
unsigned
int
*
row
=
(
unsigned
int
*
)
&
statsv
.
at
<
int
>
(
l
,
0
);
row
[
CC_STAT_LEFT
]
=
std
::
numeric_limits
<
LabelT
>::
max
();
row
[
CC_STAT_TOP
]
=
std
::
numeric_limits
<
LabelT
>::
max
();
row
[
CC_STAT_WIDTH
]
=
std
::
numeric_limits
<
LabelT
>::
min
();
row
[
CC_STAT_HEIGHT
]
=
std
::
numeric_limits
<
LabelT
>::
min
();
//row[CC_STAT_CX] = 0;
//row[CC_STAT_CY] = 0;
row
[
CC_STAT_AREA
]
=
0
;
}
integrals
.
resize
(
nlabels
,
Point2ui64
(
0
,
0
));
}
void
operator
()(
int
r
,
int
c
,
LabelT
l
){
int
*
row
=
&
statsv
.
at
<
int
>
(
l
,
0
);
unsigned
int
*
urow
=
(
unsigned
int
*
)
row
;
if
(
c
>
row
[
CC_STAT_WIDTH
]){
row
[
CC_STAT_WIDTH
]
=
c
;
}
else
{
if
(
c
<
row
[
CC_STAT_LEFT
]){
row
[
CC_STAT_LEFT
]
=
c
;
}
}
if
(
r
>
row
[
CC_STAT_HEIGHT
]){
row
[
CC_STAT_HEIGHT
]
=
r
;
}
else
{
if
(
r
<
row
[
CC_STAT_TOP
]){
row
[
CC_STAT_TOP
]
=
r
;
}
}
urow
[
CC_STAT_AREA
]
++
;
Point2ui64
&
integral
=
integrals
[
l
];
integral
.
x
+=
c
;
integral
.
y
+=
r
;
}
void
finish
(){
for
(
int
l
=
0
;
l
<
statsv
.
rows
;
++
l
){
unsigned
int
*
row
=
(
unsigned
int
*
)
&
statsv
.
at
<
int
>
(
l
,
0
);
row
[
CC_STAT_LEFT
]
=
std
::
min
(
row
[
CC_STAT_LEFT
],
row
[
CC_STAT_WIDTH
]);
row
[
CC_STAT_WIDTH
]
=
row
[
CC_STAT_WIDTH
]
-
row
[
CC_STAT_LEFT
]
+
1
;
row
[
CC_STAT_TOP
]
=
std
::
min
(
row
[
CC_STAT_TOP
],
row
[
CC_STAT_HEIGHT
]);
row
[
CC_STAT_HEIGHT
]
=
row
[
CC_STAT_HEIGHT
]
-
row
[
CC_STAT_TOP
]
+
1
;
Point2ui64
&
integral
=
integrals
[
l
];
double
*
centroid
=
&
centroidsv
.
at
<
double
>
(
l
,
0
);
centroid
[
0
]
=
double
(
integral
.
x
)
/
row
[
CC_STAT_AREA
];
centroid
[
1
]
=
double
(
integral
.
y
)
/
row
[
CC_STAT_AREA
];
}
}
};
//Find the root of the tree of node i
template
<
typename
LabelT
>
inline
static
LabelT
findRoot
(
const
LabelT
*
P
,
LabelT
i
){
LabelT
root
=
i
;
while
(
P
[
root
]
<
root
){
root
=
P
[
root
];
}
return
root
;
}
//Make all nodes in the path of node i point to root
template
<
typename
LabelT
>
inline
static
void
setRoot
(
LabelT
*
P
,
LabelT
i
,
LabelT
root
){
while
(
P
[
i
]
<
i
){
LabelT
j
=
P
[
i
];
P
[
i
]
=
root
;
i
=
j
;
}
P
[
i
]
=
root
;
}
//Find the root of the tree of the node i and compress the path in the process
template
<
typename
LabelT
>
inline
static
LabelT
find
(
LabelT
*
P
,
LabelT
i
){
LabelT
root
=
findRoot
(
P
,
i
);
setRoot
(
P
,
i
,
root
);
return
root
;
}
//unite the two trees containing nodes i and j and return the new root
template
<
typename
LabelT
>
inline
static
LabelT
set_union
(
LabelT
*
P
,
LabelT
i
,
LabelT
j
){
LabelT
root
=
findRoot
(
P
,
i
);
if
(
i
!=
j
){
LabelT
rootj
=
findRoot
(
P
,
j
);
if
(
root
>
rootj
){
root
=
rootj
;
}
setRoot
(
P
,
j
,
root
);
}
setRoot
(
P
,
i
,
root
);
return
root
;
}
//Flatten the Union Find tree and relabel the components
template
<
typename
LabelT
>
inline
static
LabelT
flattenL
(
LabelT
*
P
,
LabelT
length
){
LabelT
k
=
1
;
for
(
LabelT
i
=
1
;
i
<
length
;
++
i
){
if
(
P
[
i
]
<
i
){
P
[
i
]
=
P
[
P
[
i
]];
}
else
{
P
[
i
]
=
k
;
k
=
k
+
1
;
}
}
return
k
;
}
//Based on "Two Strategies to Speed up Connected Components Algorithms", the SAUF (Scan array union find) variant
//using decision trees
//Kesheng Wu, et al
//Note: rows are encoded as position in the "rows" array to save lookup times
//reference for 4-way: {{-1, 0}, {0, -1}};//b, d neighborhoods
const
int
G4
[
2
][
2
]
=
{{
1
,
0
},
{
0
,
-
1
}};
//b, d neighborhoods
//reference for 8-way: {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}};//a, b, c, d neighborhoods
const
int
G8
[
4
][
2
]
=
{{
1
,
-
1
},
{
1
,
0
},
{
1
,
1
},
{
0
,
-
1
}};
//a, b, c, d neighborhoods
template
<
typename
LabelT
,
typename
PixelT
,
typename
StatsOp
=
NoOp
<
LabelT
>
,
int
connectivity
=
8
>
struct
LabelingImpl
{
LabelT
operator
()(
const
cv
::
Mat
&
I
,
cv
::
Mat
&
L
,
StatsOp
&
sop
){
CV_Assert
(
L
.
rows
==
I
.
rows
);
CV_Assert
(
L
.
cols
==
I
.
cols
);
const
int
rows
=
L
.
rows
;
const
int
cols
=
L
.
cols
;
size_t
Plength
=
(
size_t
(
rows
+
3
-
1
)
/
3
)
*
(
size_t
(
cols
+
3
-
1
)
/
3
);
if
(
connectivity
==
4
){
Plength
=
4
*
Plength
;
//a quick and dirty upper bound, an exact answer exists if you want to find it
//the 4 comes from the fact that a 3x3 block can never have more than 4 unique labels
}
LabelT
*
P
=
(
LabelT
*
)
fastMalloc
(
sizeof
(
LabelT
)
*
Plength
);
P
[
0
]
=
0
;
LabelT
lunique
=
1
;
//scanning phase
for
(
int
r_i
=
0
;
r_i
<
rows
;
++
r_i
){
LabelT
*
Lrow
=
(
LabelT
*
)(
L
.
data
+
L
.
step
.
p
[
0
]
*
r_i
);
LabelT
*
Lrow_prev
=
(
LabelT
*
)(((
char
*
)
Lrow
)
-
L
.
step
.
p
[
0
]);
const
PixelT
*
Irow
=
(
PixelT
*
)(
I
.
data
+
I
.
step
.
p
[
0
]
*
r_i
);
const
PixelT
*
Irow_prev
=
(
const
PixelT
*
)(((
char
*
)
Irow
)
-
I
.
step
.
p
[
0
]);
LabelT
*
Lrows
[
2
]
=
{
Lrow
,
Lrow_prev
};
const
PixelT
*
Irows
[
2
]
=
{
Irow
,
Irow_prev
};
if
(
connectivity
==
8
){
const
int
a
=
0
;
const
int
b
=
1
;
const
int
c
=
2
;
const
int
d
=
3
;
const
bool
T_a_r
=
(
r_i
-
G8
[
a
][
0
])
>=
0
;
const
bool
T_b_r
=
(
r_i
-
G8
[
b
][
0
])
>=
0
;
const
bool
T_c_r
=
(
r_i
-
G8
[
c
][
0
])
>=
0
;
for
(
int
c_i
=
0
;
Irows
[
0
]
!=
Irow
+
cols
;
++
Irows
[
0
],
c_i
++
){
if
(
!*
Irows
[
0
]){
Lrow
[
c_i
]
=
0
;
continue
;
}
Irows
[
1
]
=
Irow_prev
+
c_i
;
Lrows
[
0
]
=
Lrow
+
c_i
;
Lrows
[
1
]
=
Lrow_prev
+
c_i
;
const
bool
T_a
=
T_a_r
&&
(
c_i
+
G8
[
a
][
1
])
>=
0
&&
*
(
Irows
[
G8
[
a
][
0
]]
+
G8
[
a
][
1
]);
const
bool
T_b
=
T_b_r
&&
*
(
Irows
[
G8
[
b
][
0
]]
+
G8
[
b
][
1
]);
const
bool
T_c
=
T_c_r
&&
(
c_i
+
G8
[
c
][
1
])
<
cols
&&
*
(
Irows
[
G8
[
c
][
0
]]
+
G8
[
c
][
1
]);
const
bool
T_d
=
(
c_i
+
G8
[
d
][
1
])
>=
0
&&
*
(
Irows
[
G8
[
d
][
0
]]
+
G8
[
d
][
1
]);
//decision tree
if
(
T_b
){
//copy(b)
*
Lrows
[
0
]
=
*
(
Lrows
[
G8
[
b
][
0
]]
+
G8
[
b
][
1
]);
}
else
{
//not b
if
(
T_c
){
if
(
T_a
){
//copy(c, a)
*
Lrows
[
0
]
=
set_union
(
P
,
*
(
Lrows
[
G8
[
c
][
0
]]
+
G8
[
c
][
1
]),
*
(
Lrows
[
G8
[
a
][
0
]]
+
G8
[
a
][
1
]));
}
else
{
if
(
T_d
){
//copy(c, d)
*
Lrows
[
0
]
=
set_union
(
P
,
*
(
Lrows
[
G8
[
c
][
0
]]
+
G8
[
c
][
1
]),
*
(
Lrows
[
G8
[
d
][
0
]]
+
G8
[
d
][
1
]));
}
else
{
//copy(c)
*
Lrows
[
0
]
=
*
(
Lrows
[
G8
[
c
][
0
]]
+
G8
[
c
][
1
]);
}
}
}
else
{
//not c
if
(
T_a
){
//copy(a)
*
Lrows
[
0
]
=
*
(
Lrows
[
G8
[
a
][
0
]]
+
G8
[
a
][
1
]);
}
else
{
if
(
T_d
){
//copy(d)
*
Lrows
[
0
]
=
*
(
Lrows
[
G8
[
d
][
0
]]
+
G8
[
d
][
1
]);
}
else
{
//new label
*
Lrows
[
0
]
=
lunique
;
P
[
lunique
]
=
lunique
;
lunique
=
lunique
+
1
;
}
}
}
}
}
}
else
{
//B & D only
assert
(
connectivity
==
4
);
const
int
b
=
0
;
const
int
d
=
1
;
const
bool
T_b_r
=
(
r_i
-
G4
[
b
][
0
])
>=
0
;
for
(
int
c_i
=
0
;
Irows
[
0
]
!=
Irow
+
cols
;
++
Irows
[
0
],
c_i
++
){
if
(
!*
Irows
[
0
]){
Lrow
[
c_i
]
=
0
;
continue
;
}
Irows
[
1
]
=
Irow_prev
+
c_i
;
Lrows
[
0
]
=
Lrow
+
c_i
;
Lrows
[
1
]
=
Lrow_prev
+
c_i
;
const
bool
T_b
=
T_b_r
&&
*
(
Irows
[
G4
[
b
][
0
]]
+
G4
[
b
][
1
]);
const
bool
T_d
=
(
c_i
+
G4
[
d
][
1
])
>=
0
&&
*
(
Irows
[
G4
[
d
][
0
]]
+
G4
[
d
][
1
]);
if
(
T_b
){
if
(
T_d
){
//copy(d, b)
*
Lrows
[
0
]
=
set_union
(
P
,
*
(
Lrows
[
G4
[
d
][
0
]]
+
G4
[
d
][
1
]),
*
(
Lrows
[
G4
[
b
][
0
]]
+
G4
[
b
][
1
]));
}
else
{
//copy(b)
*
Lrows
[
0
]
=
*
(
Lrows
[
G4
[
b
][
0
]]
+
G4
[
b
][
1
]);
}
}
else
{
if
(
T_d
){
//copy(d)
*
Lrows
[
0
]
=
*
(
Lrows
[
G4
[
d
][
0
]]
+
G4
[
d
][
1
]);
}
else
{
//new label
*
Lrows
[
0
]
=
lunique
;
P
[
lunique
]
=
lunique
;
lunique
=
lunique
+
1
;
}
}
}
}
}
//analysis
LabelT
nLabels
=
flattenL
(
P
,
lunique
);
sop
.
init
(
nLabels
);
for
(
int
r_i
=
0
;
r_i
<
rows
;
++
r_i
){
LabelT
*
Lrow_start
=
(
LabelT
*
)(
L
.
data
+
L
.
step
.
p
[
0
]
*
r_i
);
LabelT
*
Lrow_end
=
Lrow_start
+
cols
;
LabelT
*
Lrow
=
Lrow_start
;
for
(
int
c_i
=
0
;
Lrow
!=
Lrow_end
;
++
Lrow
,
++
c_i
){
const
LabelT
l
=
P
[
*
Lrow
];
*
Lrow
=
l
;
sop
(
r_i
,
c_i
,
l
);
}
}
sop
.
finish
();
fastFree
(
P
);
return
nLabels
;
}
//End function LabelingImpl operator()
};
//End struct LabelingImpl
}
//end namespace connectedcomponents
//L's type must have an appropriate depth for the number of pixels in I
template
<
typename
StatsOp
>
static
int
connectedComponents_sub1
(
const
cv
::
Mat
&
I
,
cv
::
Mat
&
L
,
int
connectivity
,
StatsOp
&
sop
){
CV_Assert
(
L
.
channels
()
==
1
&&
I
.
channels
()
==
1
);
CV_Assert
(
connectivity
==
8
||
connectivity
==
4
);
int
lDepth
=
L
.
depth
();
int
iDepth
=
I
.
depth
();
using
connectedcomponents
::
LabelingImpl
;
//warn if L's depth is not sufficient?
if
(
lDepth
==
CV_8U
){
if
(
iDepth
==
CV_8U
||
iDepth
==
CV_8S
){
if
(
connectivity
==
4
){
return
(
int
)
LabelingImpl
<
uchar
,
uchar
,
StatsOp
,
4
>
()(
I
,
L
,
sop
);
}
else
{
return
(
int
)
LabelingImpl
<
uchar
,
uchar
,
StatsOp
,
8
>
()(
I
,
L
,
sop
);
}
}
else
{
CV_Assert
(
false
);
}
}
else
if
(
lDepth
==
CV_16U
){
if
(
iDepth
==
CV_8U
||
iDepth
==
CV_8S
){
if
(
connectivity
==
4
){
return
(
int
)
LabelingImpl
<
ushort
,
uchar
,
StatsOp
,
4
>
()(
I
,
L
,
sop
);
}
else
{
return
(
int
)
LabelingImpl
<
ushort
,
uchar
,
StatsOp
,
8
>
()(
I
,
L
,
sop
);
}
}
else
{
CV_Assert
(
false
);
}
}
else
if
(
lDepth
==
CV_32S
){
//note that signed types don't really make sense here and not being able to use unsigned matters for scientific projects
//OpenCV: how should we proceed? .at<T> typechecks in debug mode
if
(
iDepth
==
CV_8U
||
iDepth
==
CV_8S
){
if
(
connectivity
==
4
){
return
(
int
)
LabelingImpl
<
int
,
uchar
,
StatsOp
,
4
>
()(
I
,
L
,
sop
);
}
else
{
return
(
int
)
LabelingImpl
<
int
,
uchar
,
StatsOp
,
8
>
()(
I
,
L
,
sop
);
}
}
else
{
CV_Assert
(
false
);
}
}
CV_Error
(
CV_StsUnsupportedFormat
,
"unsupported label/image type"
);
return
-
1
;
}
int
connectedComponents
(
InputArray
_I
,
OutputArray
_L
,
int
connectivity
,
int
ltype
){
const
cv
::
Mat
I
=
_I
.
getMat
();
_L
.
create
(
I
.
size
(),
CV_MAT_TYPE
(
ltype
));
cv
::
Mat
L
=
_L
.
getMat
();
if
(
ltype
==
CV_16U
){
connectedcomponents
::
NoOp
<
ushort
>
sop
;
return
connectedComponents_sub1
(
I
,
L
,
connectivity
,
sop
);
}
else
if
(
ltype
==
CV_32S
){
connectedcomponents
::
NoOp
<
unsigned
>
sop
;
return
connectedComponents_sub1
(
I
,
L
,
connectivity
,
sop
);
}
else
{
CV_Assert
(
false
);
return
0
;
}
}
int
connectedComponentsWithStats
(
InputArray
_I
,
OutputArray
_L
,
OutputArray
statsv
,
OutputArray
centroids
,
int
connectivity
,
int
ltype
){
const
cv
::
Mat
I
=
_I
.
getMat
();
_L
.
create
(
I
.
size
(),
CV_MAT_TYPE
(
ltype
));
cv
::
Mat
L
=
_L
.
getMat
();
if
(
ltype
==
CV_16U
){
connectedcomponents
::
CCStatsOp
<
ushort
>
sop
(
statsv
,
centroids
);
return
connectedComponents_sub1
(
I
,
L
,
connectivity
,
sop
);
}
else
if
(
ltype
==
CV_32S
){
connectedcomponents
::
CCStatsOp
<
unsigned
>
sop
(
statsv
,
centroids
);
return
connectedComponents_sub1
(
I
,
L
,
connectivity
,
sop
);
}
else
{
CV_Assert
(
false
);
return
0
;
}
}
}
modules/imgproc/test/test_connectedcomponents.cpp
0 → 100644
View file @
2a42960f
/*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-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., 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 the copyright holders 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 Corporation 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 "test_precomp.hpp"
#include <string>
using
namespace
cv
;
using
namespace
std
;
class
CV_ConnectedComponentsTest
:
public
cvtest
::
BaseTest
{
public
:
CV_ConnectedComponentsTest
();
~
CV_ConnectedComponentsTest
();
protected
:
void
run
(
int
);
};
CV_ConnectedComponentsTest
::
CV_ConnectedComponentsTest
()
{}
CV_ConnectedComponentsTest
::~
CV_ConnectedComponentsTest
()
{}
void
CV_ConnectedComponentsTest
::
run
(
int
/* start_from */
)
{
string
exp_path
=
string
(
ts
->
get_data_path
())
+
"connectedcomponents/ccomp_exp.png"
;
Mat
exp
=
imread
(
exp_path
,
0
);
Mat
orig
=
imread
(
string
(
ts
->
get_data_path
())
+
"connectedcomponents/concentric_circles.png"
,
0
);
if
(
orig
.
empty
())
{
ts
->
set_failed_test_info
(
cvtest
::
TS
::
FAIL_INVALID_TEST_DATA
);
return
;
}
Mat
bw
=
orig
>
128
;
Mat
labelImage
;
int
nLabels
=
connectedComponents
(
bw
,
labelImage
,
8
,
CV_32S
);
for
(
int
r
=
0
;
r
<
labelImage
.
rows
;
++
r
){
for
(
int
c
=
0
;
c
<
labelImage
.
cols
;
++
c
){
int
l
=
labelImage
.
at
<
int
>
(
r
,
c
);
bool
pass
=
l
>=
0
&&
l
<=
nLabels
;
if
(
!
pass
){
ts
->
set_failed_test_info
(
cvtest
::
TS
::
FAIL_INVALID_OUTPUT
);
return
;
}
}
}
if
(
exp
.
empty
()
||
orig
.
size
()
!=
exp
.
size
()
)
{
imwrite
(
exp_path
,
labelImage
);
exp
=
labelImage
;
}
if
(
0
!=
norm
(
labelImage
>
0
,
exp
>
0
,
NORM_INF
))
{
ts
->
set_failed_test_info
(
cvtest
::
TS
::
FAIL_MISMATCH
);
return
;
}
if
(
nLabels
!=
norm
(
labelImage
,
NORM_INF
)
+
1
)
{
ts
->
set_failed_test_info
(
cvtest
::
TS
::
FAIL_MISMATCH
);
return
;
}
ts
->
set_failed_test_info
(
cvtest
::
TS
::
OK
);
}
TEST
(
Imgproc_ConnectedComponents
,
regression
)
{
CV_ConnectedComponentsTest
test
;
test
.
safe_run
();
}
modules/python/src2/cv2.cpp
View file @
2a42960f
...
...
@@ -410,7 +410,7 @@ static bool pyopencv_to(PyObject* obj, bool& value, const char* name = "<unknown
static
PyObject
*
pyopencv_from
(
size_t
value
)
{
return
PyLong_From
UnsignedLong
((
unsigned
long
)
value
);
return
PyLong_From
Size_t
(
value
);
}
static
bool
pyopencv_to
(
PyObject
*
obj
,
size_t
&
value
,
const
char
*
name
=
"<unknown>"
)
...
...
@@ -497,9 +497,16 @@ static bool pyopencv_to(PyObject* obj, float& value, const char* name = "<unknow
static
PyObject
*
pyopencv_from
(
int64
value
)
{
return
Py
Float_FromDouble
((
double
)
value
);
return
Py
Long_FromLongLong
(
value
);
}
#if !defined(__LP64__)
static
PyObject
*
pyopencv_from
(
uint64
value
)
{
return
PyLong_FromUnsignedLongLong
(
value
);
}
#endif
static
PyObject
*
pyopencv_from
(
const
string
&
value
)
{
return
PyString_FromString
(
value
.
empty
()
?
""
:
value
.
c_str
());
...
...
samples/cpp/connected_components.cpp
View file @
2a42960f
...
...
@@ -11,23 +11,19 @@ int threshval = 100;
static
void
on_trackbar
(
int
,
void
*
)
{
Mat
bw
=
threshval
<
128
?
(
img
<
threshval
)
:
(
img
>
threshval
);
vector
<
vector
<
Point
>
>
contours
;
vector
<
Vec4i
>
hierarchy
;
findContours
(
bw
,
contours
,
hierarchy
,
CV_RETR_CCOMP
,
CV_CHAIN_APPROX_SIMPLE
);
Mat
dst
=
Mat
::
zeros
(
img
.
size
(),
CV_8UC3
);
if
(
!
contours
.
empty
()
&&
!
hierarchy
.
empty
()
)
{
// iterate through all the top-level contours,
// draw each connected component with its own random color
int
idx
=
0
;
for
(
;
idx
>=
0
;
idx
=
hierarchy
[
idx
][
0
]
)
{
Scalar
color
(
(
rand
()
&
255
),
(
rand
()
&
255
),
(
rand
()
&
255
)
);
drawContours
(
dst
,
contours
,
idx
,
color
,
CV_FILLED
,
8
,
hierarchy
);
Mat
labelImage
(
img
.
size
(),
CV_32S
);
int
nLabels
=
connectedComponents
(
bw
,
labelImage
,
8
);
std
::
vector
<
Vec3b
>
colors
(
nLabels
);
colors
[
0
]
=
Vec3b
(
0
,
0
,
0
);
//background
for
(
int
label
=
1
;
label
<
nLabels
;
++
label
){
colors
[
label
]
=
Vec3b
(
(
rand
()
&
255
),
(
rand
()
&
255
),
(
rand
()
&
255
)
);
}
Mat
dst
(
img
.
size
(),
CV_8UC3
);
for
(
int
r
=
0
;
r
<
dst
.
rows
;
++
r
){
for
(
int
c
=
0
;
c
<
dst
.
cols
;
++
c
){
int
label
=
labelImage
.
at
<
int
>
(
r
,
c
);
Vec3b
&
pixel
=
dst
.
at
<
Vec3b
>
(
r
,
c
);
pixel
=
colors
[
label
];
}
}
...
...
@@ -45,14 +41,14 @@ static void help()
const
char
*
keys
=
{
"{@image
|stuff.jpg|image for converting to a grayscale}"
"{@image|stuff.jpg|image for converting to a grayscale}"
};
int
main
(
int
argc
,
const
char
**
argv
)
{
help
();
CommandLineParser
parser
(
argc
,
argv
,
keys
);
string
inputImage
=
parser
.
get
<
string
>
(
1
);
string
inputImage
=
parser
.
get
<
string
>
(
"@image"
);
img
=
imread
(
inputImage
.
c_str
(),
0
);
if
(
img
.
empty
())
...
...
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