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
f196dd5f
Commit
f196dd5f
authored
Mar 24, 2012
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
preliminary version of a multi-level findcontours
parent
9b2d7e19
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
306 additions
and
73 deletions
+306
-73
imgproc.hpp
modules/imgproc/include/opencv2/imgproc/imgproc.hpp
+2
-1
types_c.h
modules/imgproc/include/opencv2/imgproc/types_c.h
+2
-1
contours.cpp
modules/imgproc/src/contours.cpp
+302
-71
No files found.
modules/imgproc/include/opencv2/imgproc/imgproc.hpp
View file @
f196dd5f
...
...
@@ -971,7 +971,8 @@ enum
RETR_EXTERNAL
=
CV_RETR_EXTERNAL
,
//!< retrieve only the most external (top-level) contours
RETR_LIST
=
CV_RETR_LIST
,
//!< retrieve all the contours without any hierarchical information
RETR_CCOMP
=
CV_RETR_CCOMP
,
//!< retrieve the connected components (that can possibly be nested)
RETR_TREE
=
CV_RETR_TREE
//!< retrieve all the contours and the whole hierarchy
RETR_TREE
=
CV_RETR_TREE
,
//!< retrieve all the contours and the whole hierarchy
RETR_FLOODFILL
=
CV_RETR_FLOODFILL
};
//! the contour approximation algorithm
...
...
modules/imgproc/include/opencv2/imgproc/types_c.h
View file @
f196dd5f
...
...
@@ -309,7 +309,8 @@ enum
CV_RETR_EXTERNAL
=
0
,
CV_RETR_LIST
=
1
,
CV_RETR_CCOMP
=
2
,
CV_RETR_TREE
=
3
CV_RETR_TREE
=
3
,
CV_RETR_FLOODFILL
=
4
};
/* Contour approximation methods */
...
...
modules/imgproc/src/contours.cpp
View file @
f196dd5f
...
...
@@ -156,7 +156,10 @@ typedef struct _CvContourScanner
0 - external only
1 - all the contours w/o any hierarchy
2 - connected components (i.e. two-level structure -
external contours and holes) */
external contours and holes),
3 - full hierarchy;
4 - connected components of a multi-level image
*/
int
subst_flag
;
int
seq_type1
;
/* type of fetched contours */
int
header_size1
;
/* hdr size of fetched contours */
...
...
@@ -164,7 +167,7 @@ typedef struct _CvContourScanner
int
seq_type2
;
/* */
int
header_size2
;
/* the same for approx. contours */
int
elem_size2
;
/* */
_CvContourInfo
*
cinfo_table
[
12
6
];
_CvContourInfo
*
cinfo_table
[
12
8
];
}
_CvContourScanner
;
...
...
@@ -180,23 +183,21 @@ cvStartFindContours( void* _img, CvMemStorage* storage,
int
header_size
,
int
mode
,
int
method
,
CvPoint
offset
)
{
int
y
;
int
step
;
CvSize
size
;
uchar
*
img
=
0
;
CvContourScanner
scanner
=
0
;
if
(
!
storage
)
CV_Error
(
CV_StsNullPtr
,
""
);
CvMat
stub
,
*
mat
=
cvGetMat
(
_img
,
&
stub
);
if
(
!
CV_IS_MASK_ARR
(
mat
))
CV_Error
(
CV_StsUnsupportedFormat
,
"[Start]FindContours support only 8uC1 images"
);
if
(
CV_MAT_TYPE
(
mat
->
type
)
==
CV_32SC1
&&
mode
==
CV_RETR_CCOMP
)
mode
=
CV_RETR_FLOODFILL
;
if
(
!
((
CV_IS_MASK_ARR
(
mat
)
&&
mode
<
CV_RETR_FLOODFILL
)
||
(
CV_MAT_TYPE
(
mat
->
type
)
==
CV_32SC1
&&
mode
==
CV_RETR_FLOODFILL
))
)
CV_Error
(
CV_StsUnsupportedFormat
,
"[Start]FindContours support only 8uC1 and 32sC1 images"
);
size
=
cvSize
(
mat
->
width
,
mat
->
height
);
step
=
mat
->
step
;
img
=
(
uchar
*
)(
mat
->
data
.
ptr
);
CvSize
size
=
cvSize
(
mat
->
width
,
mat
->
height
);
int
step
=
mat
->
step
;
uchar
*
img
=
(
uchar
*
)(
mat
->
data
.
ptr
);
if
(
method
<
0
||
method
>
CV_CHAIN_APPROX_TC89_KCOS
)
CV_Error
(
CV_StsOutOfRange
,
""
);
...
...
@@ -204,9 +205,9 @@ cvStartFindContours( void* _img, CvMemStorage* storage,
if
(
header_size
<
(
int
)
(
method
==
CV_CHAIN_CODE
?
sizeof
(
CvChain
)
:
sizeof
(
CvContour
)))
CV_Error
(
CV_StsBadSize
,
""
);
scanner
=
(
CvContourScanner
)
cvAlloc
(
sizeof
(
*
scanner
));
memset
(
scanner
,
0
,
sizeof
(
*
scanner
)
);
CvContourScanner
scanner
=
(
CvContourScanner
)
cvAlloc
(
sizeof
(
*
scanner
));
memset
(
scanner
,
0
,
sizeof
(
*
scanner
)
);
scanner
->
storage1
=
scanner
->
storage2
=
storage
;
scanner
->
img0
=
(
schar
*
)
img
;
scanner
->
img
=
(
schar
*
)
(
img
+
step
);
...
...
@@ -284,16 +285,20 @@ cvStartFindContours( void* _img, CvMemStorage* storage,
}
/* make zero borders */
memset
(
img
,
0
,
size
.
width
);
memset
(
img
+
step
*
(
size
.
height
-
1
),
0
,
size
.
width
);
int
esz
=
CV_ELEM_SIZE
(
mat
->
type
);
memset
(
img
,
0
,
size
.
width
*
esz
);
memset
(
img
+
step
*
(
size
.
height
-
1
),
0
,
size
.
width
*
esz
);
for
(
y
=
1
,
img
+=
step
;
y
<
size
.
height
-
1
;
y
++
,
img
+=
step
)
img
+=
step
;
for
(
int
y
=
1
;
y
<
size
.
height
-
1
;
y
++
,
img
+=
step
)
{
img
[
0
]
=
img
[
size
.
width
-
1
]
=
0
;
for
(
int
k
=
0
;
k
<
esz
;
k
++
)
img
[
k
]
=
img
[(
size
.
width
-
1
)
*
esz
+
k
]
=
(
schar
)
0
;
}
/* converts all pixels to 0 or 1 */
cvThreshold
(
mat
,
mat
,
0
,
1
,
CV_THRESH_BINARY
);
if
(
CV_MAT_TYPE
(
mat
->
type
)
!=
CV_32S
)
cvThreshold
(
mat
,
mat
,
0
,
1
,
CV_THRESH_BINARY
);
return
scanner
;
}
...
...
@@ -790,44 +795,251 @@ icvFetchContourEx( schar* ptr,
}
static
int
icvTraceContour_32s
(
int
*
ptr
,
int
step
,
int
*
stop_ptr
,
int
is_hole
)
{
int
deltas
[
16
];
int
*
i0
=
ptr
,
*
i1
,
*
i3
,
*
i4
;
int
s
,
s_end
;
const
int
right_flag
=
INT_MIN
;
const
int
new_flag
=
(
int
)((
unsigned
)
INT_MIN
>>
1
);
const
int
value_mask
=
~
(
right_flag
|
new_flag
);
const
int
ccomp_val
=
*
i0
&
value_mask
;
/* initialize local state */
CV_INIT_3X3_DELTAS
(
deltas
,
step
,
1
);
memcpy
(
deltas
+
8
,
deltas
,
8
*
sizeof
(
deltas
[
0
]
));
s_end
=
s
=
is_hole
?
0
:
4
;
do
{
s
=
(
s
-
1
)
&
7
;
i1
=
i0
+
deltas
[
s
];
if
(
(
*
i1
&
value_mask
)
==
ccomp_val
)
break
;
}
while
(
s
!=
s_end
);
i3
=
i0
;
/* check single pixel domain */
if
(
s
!=
s_end
)
{
/* follow border */
for
(
;;
)
{
s_end
=
s
;
for
(
;;
)
{
i4
=
i3
+
deltas
[
++
s
];
if
(
(
*
i4
&
value_mask
)
==
ccomp_val
)
break
;
}
if
(
i3
==
stop_ptr
||
(
i4
==
i0
&&
i3
==
i1
)
)
break
;
i3
=
i4
;
s
=
(
s
+
4
)
&
7
;
}
/* end of border following loop */
}
return
i3
==
stop_ptr
;
}
static
void
icvFetchContourEx_32s
(
int
*
ptr
,
int
step
,
CvPoint
pt
,
CvSeq
*
contour
,
int
_method
,
CvRect
*
_rect
)
{
int
deltas
[
16
];
CvSeqWriter
writer
;
int
*
i0
=
ptr
,
*
i1
,
*
i3
,
*
i4
;
CvRect
rect
;
int
prev_s
=
-
1
,
s
,
s_end
;
int
method
=
_method
-
1
;
const
int
right_flag
=
INT_MIN
;
const
int
new_flag
=
(
int
)((
unsigned
)
INT_MIN
>>
1
);
const
int
value_mask
=
~
(
right_flag
|
new_flag
);
const
int
ccomp_val
=
*
i0
&
value_mask
;
const
int
nbd0
=
ccomp_val
|
new_flag
;
const
int
nbd1
=
nbd0
|
right_flag
;
assert
(
(
unsigned
)
_method
<=
CV_CHAIN_APPROX_SIMPLE
);
/* initialize local state */
CV_INIT_3X3_DELTAS
(
deltas
,
step
,
1
);
memcpy
(
deltas
+
8
,
deltas
,
8
*
sizeof
(
deltas
[
0
]
));
/* initialize writer */
cvStartAppendToSeq
(
contour
,
&
writer
);
if
(
method
<
0
)
((
CvChain
*
)
contour
)
->
origin
=
pt
;
rect
.
x
=
rect
.
width
=
pt
.
x
;
rect
.
y
=
rect
.
height
=
pt
.
y
;
s_end
=
s
=
CV_IS_SEQ_HOLE
(
contour
)
?
0
:
4
;
do
{
s
=
(
s
-
1
)
&
7
;
i1
=
i0
+
deltas
[
s
];
if
(
(
*
i1
&
value_mask
)
==
ccomp_val
)
break
;
}
while
(
s
!=
s_end
);
if
(
s
==
s_end
)
/* single pixel domain */
{
*
i0
=
nbd1
;
if
(
method
>=
0
)
{
CV_WRITE_SEQ_ELEM
(
pt
,
writer
);
}
}
else
{
i3
=
i0
;
prev_s
=
s
^
4
;
/* follow border */
for
(
;;
)
{
s_end
=
s
;
for
(
;;
)
{
i4
=
i3
+
deltas
[
++
s
];
if
(
(
*
i4
&
value_mask
)
==
ccomp_val
)
break
;
}
s
&=
7
;
/* check "right" bound */
if
(
(
unsigned
)
(
s
-
1
)
<
(
unsigned
)
s_end
)
{
*
i3
=
nbd1
;
}
else
if
(
*
i3
==
ccomp_val
)
{
*
i3
=
nbd0
;
}
if
(
method
<
0
)
{
schar
_s
=
(
schar
)
s
;
CV_WRITE_SEQ_ELEM
(
_s
,
writer
);
}
else
if
(
s
!=
prev_s
||
method
==
0
)
{
CV_WRITE_SEQ_ELEM
(
pt
,
writer
);
}
if
(
s
!=
prev_s
)
{
/* update bounds */
if
(
pt
.
x
<
rect
.
x
)
rect
.
x
=
pt
.
x
;
else
if
(
pt
.
x
>
rect
.
width
)
rect
.
width
=
pt
.
x
;
if
(
pt
.
y
<
rect
.
y
)
rect
.
y
=
pt
.
y
;
else
if
(
pt
.
y
>
rect
.
height
)
rect
.
height
=
pt
.
y
;
}
prev_s
=
s
;
pt
.
x
+=
icvCodeDeltas
[
s
].
x
;
pt
.
y
+=
icvCodeDeltas
[
s
].
y
;
if
(
i4
==
i0
&&
i3
==
i1
)
break
;
i3
=
i4
;
s
=
(
s
+
4
)
&
7
;
}
/* end of border following loop */
}
rect
.
width
-=
rect
.
x
-
1
;
rect
.
height
-=
rect
.
y
-
1
;
cvEndWriteSeq
(
&
writer
);
if
(
_method
!=
CV_CHAIN_CODE
)
((
CvContour
*
)
contour
)
->
rect
=
rect
;
assert
(
(
writer
.
seq
->
total
==
0
&&
writer
.
seq
->
first
==
0
)
||
writer
.
seq
->
total
>
writer
.
seq
->
first
->
count
||
(
writer
.
seq
->
first
->
prev
==
writer
.
seq
->
first
&&
writer
.
seq
->
first
->
next
==
writer
.
seq
->
first
)
);
if
(
_rect
)
*
_rect
=
rect
;
}
CvSeq
*
cvFindNextContour
(
CvContourScanner
scanner
)
{
schar
*
img0
;
schar
*
img
;
int
step
;
int
width
,
height
;
int
x
,
y
;
int
prev
;
CvPoint
lnbd
;
int
nbd
;
int
mode
;
if
(
!
scanner
)
CV_Error
(
CV_StsNullPtr
,
""
);
icvEndProcessContour
(
scanner
);
/* initialize local state */
img0
=
scanner
->
img0
;
img
=
scanner
->
img
;
step
=
scanner
->
img_step
;
x
=
scanner
->
pt
.
x
;
y
=
scanner
->
pt
.
y
;
width
=
scanner
->
img_size
.
width
;
height
=
scanner
->
img_size
.
height
;
mode
=
scanner
->
mode
;
lnbd
=
scanner
->
lnbd
;
nbd
=
scanner
->
nbd
;
prev
=
img
[
x
-
1
];
schar
*
img0
=
scanner
->
img0
;
schar
*
img
=
scanner
->
img
;
int
step
=
scanner
->
img_step
;
int
step_i
=
step
/
sizeof
(
int
);
int
x
=
scanner
->
pt
.
x
;
int
y
=
scanner
->
pt
.
y
;
int
width
=
scanner
->
img_size
.
width
;
int
height
=
scanner
->
img_size
.
height
;
int
mode
=
scanner
->
mode
;
CvPoint
lnbd
=
scanner
->
lnbd
;
int
nbd
=
scanner
->
nbd
;
int
prev
=
img
[
x
-
1
];
int
new_mask
=
-
2
;
if
(
mode
==
CV_RETR_FLOODFILL
)
{
prev
=
((
int
*
)
img
)[
x
-
1
];
new_mask
=
INT_MIN
>>
1
;
}
for
(
;
y
<
height
;
y
++
,
img
+=
step
)
{
int
*
img0_i
=
0
;
int
*
img_i
=
0
;
int
p
=
0
;
if
(
mode
==
CV_RETR_FLOODFILL
)
{
img0_i
=
(
int
*
)
img0
;
img_i
=
(
int
*
)
img
;
}
for
(
;
x
<
width
;
x
++
)
{
int
p
=
img
[
x
];
if
(
p
!=
prev
)
if
(
img_i
)
{
for
(
;
x
<
width
&&
((
p
=
img_i
[
x
])
==
prev
||
(
p
&
~
new_mask
)
==
(
prev
&
~
new_mask
));
x
++
)
prev
=
p
;
}
else
{
for
(
;
x
<
width
&&
(
p
=
img
[
x
])
==
prev
;
x
++
)
;
}
if
(
x
>=
width
)
break
;
{
_CvContourInfo
*
par_info
=
0
;
_CvContourInfo
*
l_cinfo
=
0
;
...
...
@@ -835,13 +1047,16 @@ cvFindNextContour( CvContourScanner scanner )
int
is_hole
=
0
;
CvPoint
origin
;
if
(
!
(
prev
==
0
&&
p
==
1
)
)
/* if not external contour */
/* if not external contour */
if
(
(
!
img_i
&&
!
(
prev
==
0
&&
p
==
1
))
||
(
img_i
&&
!
(((
prev
&
new_mask
)
!=
0
||
prev
==
0
)
&&
(
p
&
new_mask
)
==
0
))
)
{
/* check hole */
if
(
p
!=
0
||
prev
<
1
)
if
(
(
!
img_i
&&
(
p
!=
0
||
prev
<
1
))
||
(
img_i
&&
((
prev
&
new_mask
)
!=
0
||
(
p
&
new_mask
)
!=
0
)))
goto
resume_scan
;
if
(
prev
&
-
2
)
if
(
prev
&
new_mask
)
{
lnbd
.
x
=
x
-
1
;
}
...
...
@@ -855,16 +1070,16 @@ cvFindNextContour( CvContourScanner scanner )
origin
.
x
=
x
-
is_hole
;
/* find contour parent */
if
(
mode
<=
1
||
(
!
is_hole
&&
mode
==
2
)
||
lnbd
.
x
<=
0
)
if
(
mode
<=
1
||
(
!
is_hole
&&
(
mode
==
CV_RETR_CCOMP
||
mode
==
CV_RETR_FLOODFILL
)
)
||
lnbd
.
x
<=
0
)
{
par_info
=
&
(
scanner
->
frame_info
);
}
else
{
int
lval
=
img0
[
lnbd
.
y
*
step
+
lnbd
.
x
]
&
0x7f
;
_CvContourInfo
*
cur
=
scanner
->
cinfo_table
[
lval
-
2
];
assert
(
lval
>=
2
)
;
int
lval
=
(
img0_i
?
img0_i
[
lnbd
.
y
*
step_i
+
lnbd
.
x
]
:
(
int
)
img0
[
lnbd
.
y
*
step
+
lnbd
.
x
])
&
0x7f
;
_CvContourInfo
*
cur
=
scanner
->
cinfo_table
[
lval
]
;
/* find the first bounding contour */
while
(
cur
)
...
...
@@ -874,10 +1089,14 @@ cvFindNextContour( CvContourScanner scanner )
{
if
(
par_info
)
{
if
(
icvTraceContour
(
scanner
->
img0
+
par_info
->
origin
.
y
*
step
+
par_info
->
origin
.
x
,
step
,
img
+
lnbd
.
x
,
par_info
->
is_hole
)
>
0
)
if
(
(
img0_i
&&
icvTraceContour_32s
(
img0_i
+
par_info
->
origin
.
y
*
step_i
+
par_info
->
origin
.
x
,
step_i
,
img_i
+
lnbd
.
x
,
par_info
->
is_hole
)
>
0
)
||
(
!
img0_i
&&
icvTraceContour
(
img0
+
par_info
->
origin
.
y
*
step
+
par_info
->
origin
.
x
,
step
,
img
+
lnbd
.
x
,
par_info
->
is_hole
)
>
0
)
)
break
;
}
par_info
=
cur
;
...
...
@@ -929,21 +1148,34 @@ cvFindNextContour( CvContourScanner scanner )
v
.
ci
=
l_cinfo
;
cvSetAdd
(
scanner
->
cinfo_set
,
0
,
&
v
.
se
);
l_cinfo
=
v
.
ci
;
int
lval
;
icvFetchContourEx
(
img
+
x
-
is_hole
,
step
,
cvPoint
(
origin
.
x
+
scanner
->
offset
.
x
,
origin
.
y
+
scanner
->
offset
.
y
),
seq
,
scanner
->
approx_method1
,
nbd
,
&
(
l_cinfo
->
rect
)
);
if
(
img_i
)
{
lval
=
img_i
[
x
-
is_hole
]
&
127
;
icvFetchContourEx_32s
(
img_i
+
x
-
is_hole
,
step_i
,
cvPoint
(
origin
.
x
+
scanner
->
offset
.
x
,
origin
.
y
+
scanner
->
offset
.
y
),
seq
,
scanner
->
approx_method1
,
&
(
l_cinfo
->
rect
)
);
}
else
{
lval
=
nbd
;
// change nbd
nbd
=
(
nbd
+
1
)
&
127
;
nbd
+=
nbd
==
0
?
3
:
0
;
icvFetchContourEx
(
img
+
x
-
is_hole
,
step
,
cvPoint
(
origin
.
x
+
scanner
->
offset
.
x
,
origin
.
y
+
scanner
->
offset
.
y
),
seq
,
scanner
->
approx_method1
,
lval
,
&
(
l_cinfo
->
rect
)
);
}
l_cinfo
->
rect
.
x
-=
scanner
->
offset
.
x
;
l_cinfo
->
rect
.
y
-=
scanner
->
offset
.
y
;
l_cinfo
->
next
=
scanner
->
cinfo_table
[
nbd
-
2
];
scanner
->
cinfo_table
[
nbd
-
2
]
=
l_cinfo
;
/* change nbd */
nbd
=
(
nbd
+
1
)
&
127
;
nbd
+=
nbd
==
0
?
3
:
0
;
l_cinfo
->
next
=
scanner
->
cinfo_table
[
lval
];
scanner
->
cinfo_table
[
lval
]
=
l_cinfo
;
}
l_cinfo
->
is_hole
=
is_hole
;
...
...
@@ -979,7 +1211,7 @@ cvFindNextContour( CvContourScanner scanner )
cvSaveMemStoragePos
(
scanner
->
storage2
,
&
(
scanner
->
backup_pos2
)
);
scanner
->
l_cinfo
=
l_cinfo
;
scanner
->
pt
.
x
=
x
+
1
;
scanner
->
pt
.
x
=
!
img_i
?
x
+
1
:
x
+
1
-
is_hole
;
scanner
->
pt
.
y
=
y
;
scanner
->
lnbd
=
lnbd
;
scanner
->
img
=
(
schar
*
)
img
;
...
...
@@ -1001,7 +1233,6 @@ cvFindNextContour( CvContourScanner scanner )
lnbd
.
y
=
y
+
1
;
x
=
1
;
prev
=
0
;
}
/* end of loop on y */
return
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