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
f2845f15
Commit
f2845f15
authored
May 16, 2018
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added find_peaks()
parent
5a2e0d6a
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
194 additions
and
0 deletions
+194
-0
scan_image.h
dlib/image_processing/scan_image.h
+138
-0
scan_image_abstract.h
dlib/image_processing/scan_image_abstract.h
+56
-0
No files found.
dlib/image_processing/scan_image.h
View file @
f2845f15
...
...
@@ -11,6 +11,7 @@
#include "../rand.h"
#include "../array2d.h"
#include "../image_transforms/spatial_filtering.h"
#include "../image_transforms/thresholding.h"
namespace
dlib
{
...
...
@@ -235,6 +236,143 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
template
<
typename
image_type
>
std
::
vector
<
point
>
find_peaks
(
const
image_type
&
img_
,
const
double
non_max_suppression_radius
,
const
typename
pixel_traits
<
typename
image_traits
<
image_type
>::
pixel_type
>::
basic_pixel_type
&
thresh
)
{
DLIB_CASSERT
(
non_max_suppression_radius
>=
0
);
const_image_view
<
image_type
>
img
(
img_
);
using
basic_pixel_type
=
typename
pixel_traits
<
typename
image_traits
<
image_type
>::
pixel_type
>::
basic_pixel_type
;
std
::
vector
<
std
::
pair
<
basic_pixel_type
,
point
>>
peaks
;
for
(
long
r
=
1
;
r
+
1
<
img
.
nr
();
++
r
)
{
for
(
long
c
=
1
;
c
+
1
<
img
.
nc
();
++
c
)
{
auto
val
=
img
[
r
][
c
];
if
(
val
<
thresh
)
continue
;
if
(
val
<=
img
[
r
-
1
][
c
]
||
val
<=
img
[
r
+
1
][
c
]
||
val
<=
img
[
r
][
c
+
1
]
||
val
<=
img
[
r
][
c
-
1
]
||
val
<=
img
[
r
-
1
][
c
-
1
]
||
val
<=
img
[
r
+
1
][
c
+
1
]
||
val
<=
img
[
r
-
1
][
c
+
1
]
||
val
<=
img
[
r
+
1
][
c
-
1
]
)
{
continue
;
}
peaks
.
emplace_back
(
val
,
point
(
c
,
r
));
}
}
// now do non-max suppression of the peaks according to the supplied radius.
using
pt
=
std
::
pair
<
basic_pixel_type
,
point
>
;
// First sort the peaks so the strongest peaks come first. We will greedily accept
// them and then do the normal peak sorting/non-max suppression thing.
std
::
sort
(
peaks
.
rbegin
(),
peaks
.
rend
(),
[](
pt
&
a
,
pt
&
b
){
return
a
.
first
<
b
.
first
;
});
std
::
vector
<
point
>
final_peaks
;
const
double
radius_sqr
=
non_max_suppression_radius
*
non_max_suppression_radius
;
// If there are a lot of peaks then we will make a mask image and use that to do
// the non-max suppression since this is fast when peaks.size() is large. Otherwise we
// will do the simpler thing in the else block that doesn't require us to allocate a
// temporary mask image.
if
(
peaks
.
size
()
>
500
&&
radius_sqr
!=
0
)
{
// hit will record which areas of the image have already been accounted for by some
// peak. So it is our mask image.
matrix
<
unsigned
char
>
hit
(
img
.
nr
(),
img
.
nc
());
// initially nothing has been hit.
hit
=
0
;
const
unsigned
long
win_size
=
std
::
round
(
2
*
non_max_suppression_radius
);
const
rectangle
area
=
get_rect
(
img
);
for
(
auto
&
pp
:
peaks
)
{
auto
&
p
=
pp
.
second
;
if
(
!
hit
(
p
.
y
(),
p
.
x
()))
{
final_peaks
.
emplace_back
(
p
);
// mask out a circle around this new peak
rectangle
win
=
centered_rect
(
p
,
win_size
,
win_size
).
intersect
(
area
);
for
(
long
r
=
win
.
top
();
r
<=
win
.
bottom
();
++
r
)
{
for
(
long
c
=
win
.
left
();
c
<=
win
.
right
();
++
c
)
{
if
(
length_squared
(
point
(
c
,
r
)
-
p
)
<=
radius_sqr
)
hit
(
r
,
c
)
=
1
;
}
}
}
}
}
else
{
// if peaks.size() is relatively small then this is a faster way to do the non-max
// suppression.
for
(
auto
&
p
:
peaks
)
{
bool
hits_any_existing_peak
=
false
;
// If the user set the radius to 0 then just copy the peaks to the output without
// checking anything.
if
(
radius_sqr
!=
0
)
{
for
(
auto
&
v
:
final_peaks
)
{
if
(
length_squared
(
p
.
second
-
v
)
<=
radius_sqr
)
{
hits_any_existing_peak
=
true
;
break
;
}
}
}
if
(
!
hits_any_existing_peak
)
{
final_peaks
.
emplace_back
(
p
.
second
);
}
}
}
return
final_peaks
;
}
template
<
typename
image_type
>
std
::
vector
<
point
>
find_peaks
(
const
image_type
&
img
)
{
return
find_peaks
(
img
,
0
,
partition_pixels
(
img
));
}
template
<
typename
image_type
>
std
::
vector
<
point
>
find_peaks
(
const
image_type
&
img
,
const
double
non_max_suppression_radius
)
{
return
find_peaks
(
img
,
non_max_suppression_radius
,
partition_pixels
(
img
));
}
// ----------------------------------------------------------------------------------------
template
<
...
...
dlib/image_processing/scan_image_abstract.h
View file @
f2845f15
...
...
@@ -132,6 +132,62 @@ namespace dlib
- #dets == all the points which passed the threshold test.
!*/
// ----------------------------------------------------------------------------------------
template
<
typename
image_type
>
std
::
vector
<
point
>
find_peaks
(
const
image_type
&
img
,
const
double
non_max_suppression_radius
,
const
typename
pixel_traits
<
typename
image_traits
<
image_type
>::
pixel_type
>::
basic_pixel_type
&
thresh
);
/*!
requires
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h. Moreover, these it must contain a
scalar pixel type (e.g. int rather than rgb_pixel)
- non_max_suppression_radius >= 0
ensures
- Scans the given image and finds all pixels with values >= thresh that are
also local maximums within their 8-connected neighborhood of the image. Such
pixels are collected, sorted in decreasing order of their pixel values, and
then non-maximum suppression is applied to this list of points using the
given non_max_suppression_radius. The final list of peaks is then returned.
Therefore, the returned list, V, will have these properties:
- V.size() == the number of peaks found in the image.
- When measured in image coordinates, no elements of V are within
non_max_suppression_radius distance of each other. That is, for all valid i!=j
it is true that length(V[i]-V[j]) > non_max_suppression_radius.
- For each element of V, that element has the maximum pixel value of all
pixels in the ball centered on that pixel with radius
non_max_suppression_radius.
!*/
template
<
typename
image_type
>
std
::
vector
<
point
>
find_peaks
(
const
image_type
&
img
);
/*!
ensures
- performs: return find_peaks(img, 0, partition_pixels(img))
!*/
template
<
typename
image_type
>
std
::
vector
<
point
>
find_peaks
(
const
image_type
&
img
,
const
double
non_max_suppression_radius
);
/*!
ensures
- performs: return find_peaks(img, non_max_suppression_radius, partition_pixels(img))
!*/
// ----------------------------------------------------------------------------------------
template
<
...
...
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