Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dlib
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
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
钟尚武
dlib
Commits
7f5b85a0
Commit
7f5b85a0
authored
Dec 19, 2014
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added skeleton()
parent
f16022e2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
193 additions
and
0 deletions
+193
-0
morphological_operations.h
dlib/image_transforms/morphological_operations.h
+169
-0
morphological_operations_abstract.h
dlib/image_transforms/morphological_operations_abstract.h
+24
-0
No files found.
dlib/image_transforms/morphological_operations.h
View file @
7f5b85a0
...
...
@@ -6,6 +6,7 @@
#include "../pixel.h"
#include "thresholding.h"
#include "morphological_operations_abstract.h"
#include "assign_image.h"
namespace
dlib
{
...
...
@@ -662,6 +663,174 @@ namespace dlib
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
namespace
impl
{
template
<
typename
image_type
>
inline
bool
should_remove_pixel
(
const
image_type
&
img
,
long
r
,
long
c
,
int
iter
)
{
unsigned
int
p2
=
img
[
r
-
1
][
c
];
unsigned
int
p3
=
img
[
r
-
1
][
c
+
1
];
unsigned
int
p4
=
img
[
r
][
c
+
1
];
unsigned
int
p5
=
img
[
r
+
1
][
c
+
1
];
unsigned
int
p6
=
img
[
r
+
1
][
c
];
unsigned
int
p7
=
img
[
r
+
1
][
c
-
1
];
unsigned
int
p8
=
img
[
r
][
c
-
1
];
unsigned
int
p9
=
img
[
r
-
1
][
c
-
1
];
int
A
=
(
p2
==
0
&&
p3
==
255
)
+
(
p3
==
0
&&
p4
==
255
)
+
(
p4
==
0
&&
p5
==
255
)
+
(
p5
==
0
&&
p6
==
255
)
+
(
p6
==
0
&&
p7
==
255
)
+
(
p7
==
0
&&
p8
==
255
)
+
(
p8
==
0
&&
p9
==
255
)
+
(
p9
==
0
&&
p2
==
255
);
int
B
=
p2
+
p3
+
p4
+
p5
+
p6
+
p7
+
p8
+
p9
;
int
m1
=
iter
==
0
?
(
p2
*
p4
*
p6
)
:
(
p2
*
p4
*
p8
);
int
m2
=
iter
==
0
?
(
p4
*
p6
*
p8
)
:
(
p2
*
p6
*
p8
);
// Decide if we should remove the pixel img[r][c].
return
(
A
==
1
&&
(
B
>=
2
*
255
&&
B
<=
6
*
255
)
&&
m1
==
0
&&
m2
==
0
);
}
template
<
typename
image_type
>
inline
void
add_to_remove
(
std
::
vector
<
point
>&
to_remove
,
array2d
<
unsigned
char
>&
marker
,
const
rectangle
&
area
,
const
image_type
&
img
,
long
r
,
long
c
,
int
iter
)
{
if
(
marker
[
r
][
c
]
&&
area
.
contains
(
c
,
r
)
&&
should_remove_pixel
(
img
,
r
,
c
,
iter
))
{
to_remove
.
push_back
(
point
(
c
,
r
));
marker
[
r
][
c
]
=
0
;
}
}
template
<
typename
image_type
>
inline
bool
is_bw_border_pixel
(
const
image_type
&
img
,
long
r
,
long
c
)
{
unsigned
int
p2
=
img
[
r
-
1
][
c
];
unsigned
int
p3
=
img
[
r
-
1
][
c
+
1
];
unsigned
int
p4
=
img
[
r
][
c
+
1
];
unsigned
int
p5
=
img
[
r
+
1
][
c
+
1
];
unsigned
int
p6
=
img
[
r
+
1
][
c
];
unsigned
int
p7
=
img
[
r
+
1
][
c
-
1
];
unsigned
int
p8
=
img
[
r
][
c
-
1
];
unsigned
int
p9
=
img
[
r
-
1
][
c
-
1
];
int
B
=
p2
+
p3
+
p4
+
p5
+
p6
+
p7
+
p8
+
p9
;
// If you are on but at least one of your neighbors isn't.
return
B
<
8
*
255
&&
img
[
r
][
c
];
}
inline
void
add_if
(
std
::
vector
<
point
>&
to_check2
,
const
array2d
<
unsigned
char
>&
marker
,
long
c
,
long
r
)
{
if
(
marker
[
r
][
c
])
to_check2
.
push_back
(
point
(
c
,
r
));
}
}
// end namespace impl
// ----------------------------------------------------------------------------------------
template
<
typename
image_type
>
void
skeleton
(
image_type
&
img_
)
{
/*
The implementation of this function is based on the paper
"A fast parallel algorithm for thinning digital patterns” by T.Y. Zhang and C.Y. Suen.
and also the excellent discussion of it at:
http://opencv-code.com/quick-tips/implementation-of-thinning-algorithm-in-opencv/
*/
typedef
typename
image_traits
<
image_type
>::
pixel_type
pixel_type
;
// This function only works on grayscale images
COMPILE_TIME_ASSERT
(
pixel_traits
<
pixel_type
>::
grayscale
);
using
namespace
impl
;
zero_border_pixels
(
img_
,
1
,
1
);
image_view
<
image_type
>
img
(
img_
);
// We use the marker to keep track of pixels we have committed to removing but
// haven't yet removed from img.
array2d
<
unsigned
char
>
marker
(
img
.
nr
(),
img
.
nc
());
assign_image
(
marker
,
img
);
// Begin by making a list of the pixels on the borders of binary blobs.
std
::
vector
<
point
>
to_remove
,
to_check
,
to_check2
;
for
(
int
r
=
1
;
r
<
img
.
nr
()
-
1
;
r
++
)
{
for
(
int
c
=
1
;
c
<
img
.
nc
()
-
1
;
c
++
)
{
if
(
is_bw_border_pixel
(
img
,
r
,
c
))
{
to_check
.
push_back
(
point
(
c
,
r
));
}
}
}
// Now start iteratively looking at the border pixels and removing them.
const
rectangle
area
=
shrink_rect
(
get_rect
(
img
),
1
);
while
(
to_check
.
size
()
!=
0
)
{
for
(
int
iter
=
0
;
iter
<=
1
;
++
iter
)
{
// Check which pixels we should remove
to_remove
.
clear
();
for
(
unsigned
long
i
=
0
;
i
<
to_check
.
size
();
++
i
)
{
long
r
=
to_check
[
i
].
y
();
long
c
=
to_check
[
i
].
x
();
add_to_remove
(
to_remove
,
marker
,
area
,
img
,
r
,
c
,
iter
);
}
// Now remove those pixels. Also add their neighbors into the "to check"
// pixel list for the next iteration.
for
(
unsigned
long
i
=
0
;
i
<
to_remove
.
size
();
++
i
)
{
long
r
=
to_remove
[
i
].
y
();
long
c
=
to_remove
[
i
].
x
();
// remove the pixel
img
[
r
][
c
]
=
0
;
add_if
(
to_check2
,
marker
,
c
-
1
,
r
-
1
);
add_if
(
to_check2
,
marker
,
c
,
r
-
1
);
add_if
(
to_check2
,
marker
,
c
+
1
,
r
-
1
);
add_if
(
to_check2
,
marker
,
c
-
1
,
r
);
add_if
(
to_check2
,
marker
,
c
+
1
,
r
);
add_if
(
to_check2
,
marker
,
c
-
1
,
r
+
1
);
add_if
(
to_check2
,
marker
,
c
,
r
+
1
);
add_if
(
to_check2
,
marker
,
c
+
1
,
r
+
1
);
}
}
to_check
.
clear
();
to_check
.
swap
(
to_check2
);
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
}
...
...
dlib/image_transforms/morphological_operations_abstract.h
View file @
7f5b85a0
...
...
@@ -283,6 +283,30 @@ namespace dlib
- calls binary_complement(img,img);
!*/
// ----------------------------------------------------------------------------------------
template
<
typename
image_type
>
void
skeleton
(
image_type
&
img
);
/*!
requires
- image_type is an object that implement the interface defined in
dlib/image_processing/generic_image.h
- img must contain a grayscale pixel type.
- all pixels in img are set to either on_pixel or off_pixel.
(i.e. it must be a binary image)
ensures
- This function computes the skeletonization of img and stores the result in
#img. That is, given a binary image, we progressively thin the binary blobs
(composed of on_pixel values) until only a single pixel wide skeleton of the
original blobs remains.
- #img.nc() == img.nc()
- #img.nr() == img.nr()
!*/
// ----------------------------------------------------------------------------------------
}
...
...
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