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
fce8eaab
Commit
fce8eaab
authored
Jun 30, 2012
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added the max_filter() routine.
parent
c1c8267b
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
323 additions
and
0 deletions
+323
-0
spatial_filtering.h
dlib/image_transforms/spatial_filtering.h
+183
-0
spatial_filtering_abstract.h
dlib/image_transforms/spatial_filtering_abstract.h
+39
-0
scan_image.cpp
dlib/test/scan_image.cpp
+101
-0
No files found.
dlib/image_transforms/spatial_filtering.h
View file @
fce8eaab
...
@@ -715,6 +715,189 @@ namespace dlib
...
@@ -715,6 +715,189 @@ namespace dlib
}
}
}
}
// ----------------------------------------------------------------------------------------
namespace
impl
{
template
<
typename
T
>
class
fast_deque
{
/*
This is a fast and minimal implementation of std::deque for
use with the max_filter.
This object assumes that no more than max_size elements
will ever be pushed into it at a time.
*/
public
:
explicit
fast_deque
(
unsigned
long
max_size
)
{
// find a power of two that upper bounds max_size
mask
=
2
;
while
(
mask
<
max_size
)
mask
*=
2
;
clear
();
data
.
resize
(
mask
);
--
mask
;
// make into bit mask
}
void
clear
()
{
first
=
1
;
last
=
0
;
size
=
0
;
}
bool
empty
()
const
{
return
size
==
0
;
}
void
pop_back
()
{
last
=
(
last
-
1
)
&
mask
;
--
size
;
}
void
push_back
(
const
T
&
item
)
{
last
=
(
last
+
1
)
&
mask
;
++
size
;
data
[
last
]
=
item
;
}
void
pop_front
()
{
first
=
(
first
+
1
)
&
mask
;
--
size
;
}
const
T
&
front
()
const
{
return
data
[
first
];
}
const
T
&
back
()
const
{
return
data
[
last
];
}
private
:
std
::
vector
<
T
>
data
;
unsigned
long
mask
;
unsigned
long
first
;
unsigned
long
last
;
unsigned
long
size
;
};
}
// ----------------------------------------------------------------------------------------
template
<
typename
image_type1
,
typename
image_type2
>
void
max_filter
(
image_type1
&
img
,
image_type2
&
out
,
const
long
width
,
const
long
height
,
const
typename
image_type1
::
type
&
thresh
)
{
DLIB_ASSERT
((
width
%
2
)
==
1
&&
(
height
%
2
)
==
1
&&
width
>
0
&&
height
>
0
&&
out
.
nr
()
==
img
.
nr
()
&&
out
.
nc
()
==
img
.
nc
()
&&
is_same_object
(
img
,
out
)
==
false
,
"
\t
void max_filter()"
<<
"
\n\t
Invalid arguments given to this function."
<<
"
\n\t
img.nr(): "
<<
img
.
nr
()
<<
"
\n\t
img.nc(): "
<<
img
.
nc
()
<<
"
\n\t
out.nr(): "
<<
out
.
nr
()
<<
"
\n\t
out.nc(): "
<<
out
.
nc
()
<<
"
\n\t
width: "
<<
width
<<
"
\n\t
height: "
<<
height
<<
"
\n\t
is_same_object(img,out): "
<<
is_same_object
(
img
,
out
)
);
typedef
typename
image_type1
::
type
pixel_type
;
dlib
::
impl
::
fast_deque
<
std
::
pair
<
long
,
pixel_type
>
>
Q
(
std
::
max
(
width
,
height
));
const
long
last_col
=
std
::
max
(
img
.
nc
(),
(
width
/
2
));
const
long
last_row
=
std
::
max
(
img
.
nr
(),
(
height
/
2
));
// run max filter along rows of img
for
(
long
r
=
0
;
r
<
img
.
nr
();
++
r
)
{
Q
.
clear
();
for
(
long
c
=
0
;
c
<
width
/
2
&&
c
<
img
.
nc
();
++
c
)
{
while
(
!
Q
.
empty
()
&&
img
[
r
][
c
]
>=
Q
.
back
().
second
)
Q
.
pop_back
();
Q
.
push_back
(
make_pair
(
c
,
img
[
r
][
c
]));
}
for
(
long
c
=
width
/
2
;
c
<
img
.
nc
();
++
c
)
{
while
(
!
Q
.
empty
()
&&
img
[
r
][
c
]
>=
Q
.
back
().
second
)
Q
.
pop_back
();
while
(
!
Q
.
empty
()
&&
Q
.
front
().
first
<=
c
-
width
)
Q
.
pop_front
();
Q
.
push_back
(
make_pair
(
c
,
img
[
r
][
c
]));
img
[
r
][
c
-
(
width
/
2
)]
=
Q
.
front
().
second
;
}
for
(
long
c
=
last_col
;
c
<
img
.
nc
()
+
(
width
/
2
);
++
c
)
{
while
(
!
Q
.
empty
()
&&
Q
.
front
().
first
<=
c
-
width
)
Q
.
pop_front
();
img
[
r
][
c
-
(
width
/
2
)]
=
Q
.
front
().
second
;
}
}
// run max filter along columns of img. Store result in out.
for
(
long
cc
=
0
;
cc
<
img
.
nc
();
++
cc
)
{
Q
.
clear
();
for
(
long
rr
=
0
;
rr
<
height
/
2
&&
rr
<
img
.
nr
();
++
rr
)
{
while
(
!
Q
.
empty
()
&&
img
[
rr
][
cc
]
>=
Q
.
back
().
second
)
Q
.
pop_back
();
Q
.
push_back
(
make_pair
(
rr
,
img
[
rr
][
cc
]));
}
for
(
long
rr
=
height
/
2
;
rr
<
img
.
nr
();
++
rr
)
{
while
(
!
Q
.
empty
()
&&
img
[
rr
][
cc
]
>=
Q
.
back
().
second
)
Q
.
pop_back
();
while
(
!
Q
.
empty
()
&&
Q
.
front
().
first
<=
rr
-
height
)
Q
.
pop_front
();
Q
.
push_back
(
make_pair
(
rr
,
img
[
rr
][
cc
]));
out
[
rr
-
(
height
/
2
)][
cc
]
+=
std
::
max
(
Q
.
front
().
second
,
thresh
);
}
for
(
long
rr
=
last_row
;
rr
<
img
.
nr
()
+
(
height
/
2
);
++
rr
)
{
while
(
!
Q
.
empty
()
&&
Q
.
front
().
first
<=
rr
-
height
)
Q
.
pop_front
();
out
[
rr
-
(
height
/
2
)][
cc
]
+=
std
::
max
(
Q
.
front
().
second
,
thresh
);
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
}
}
...
...
dlib/image_transforms/spatial_filtering_abstract.h
View file @
fce8eaab
...
@@ -338,6 +338,45 @@ namespace dlib
...
@@ -338,6 +338,45 @@ namespace dlib
- #out[r][c] == out[r][c] + SUM(r,c)
- #out[r][c] == out[r][c] + SUM(r,c)
!*/
!*/
// ----------------------------------------------------------------------------------------
template
<
typename
image_type1
,
typename
image_type2
>
void
max_filter
(
image_type1
&
img
,
image_type2
&
out
,
const
long
width
,
const
long
height
,
const
typename
image_type1
::
type
&
thresh
);
/*!
requires
- out.nr() == img.nr()
- out.nc() == img.nc()
- image_type1 == an implementation of array2d/array2d_kernel_abstract.h
and it must contain a scalar type
- image_type2 == an implementation of array2d/array2d_kernel_abstract.h
and it must contain a scalar type
- is_same_object(img,out) == false
- (width%2)==1 && (height%2)==1
(i.e. width and height must be odd)
- width > 0 && height > 0
ensures
- for all valid r and c:
- let MAX(r,c) == maximum of pixels from img which are inside the rectangle
centered_rect(point(c,r), width, height)
- if (MAX(r,c) >= thresh)
- #out[r][c] == out[r][c] + MAX(r,c)
- else
- #out[r][c] == out[r][c] + thresh
- Does not change the size of img.
- Uses img as scratch space. Therefore, the pixel values in img will have
been modified by this function. That is, max_filter() destroys the contents
of img.
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
}
}
...
...
dlib/test/scan_image.cpp
View file @
fce8eaab
...
@@ -440,6 +440,105 @@ namespace
...
@@ -440,6 +440,105 @@ namespace
}
}
}
}
// ----------------------------------------------------------------------------------------
template
<
typename
image_type1
,
typename
image_type2
>
void
naive_max_filter
(
const
image_type1
&
img
,
image_type2
&
out
,
const
rectangle
&
rect
,
typename
image_type1
::
type
thresh
)
{
typedef
typename
image_type1
::
type
pixel_type
;
const
rectangle
area
=
get_rect
(
img
);
for
(
long
r
=
0
;
r
<
img
.
nr
();
++
r
)
{
for
(
long
c
=
0
;
c
<
img
.
nc
();
++
c
)
{
const
rectangle
win
=
translate_rect
(
rect
,
point
(
c
,
r
)).
intersect
(
area
);
if
(
!
win
.
is_empty
())
out
[
r
][
c
]
+=
std
::
max
(
dlib
::
max
(
subm
(
array_to_matrix
(
img
),
win
)),
thresh
);
else
out
[
r
][
c
]
+=
thresh
;
}
}
}
// ----------------------------------------------------------------------------------------
void
test_max_filter
(
long
rows
,
long
cols
,
long
width
,
long
height
,
dlib
::
rand
&
rnd
)
{
array2d
<
int
>
img
(
rows
,
cols
);
rectangle
rect
=
centered_rect
(
0
,
0
,
width
,
height
);
array2d
<
int
>
out
(
img
.
nr
(),
img
.
nc
());
assign_all_pixels
(
out
,
0
);
array2d
<
int
>
out2
(
img
.
nr
(),
img
.
nc
());
assign_all_pixels
(
out2
,
0
);
for
(
long
r
=
0
;
r
<
img
.
nr
();
++
r
)
{
for
(
long
c
=
0
;
c
<
img
.
nc
();
++
c
)
{
img
[
r
][
c
]
=
rnd
.
get_random_32bit_number
();
}
}
const
int
thresh
=
rnd
.
get_random_32bit_number
();
naive_max_filter
(
img
,
out2
,
rect
,
thresh
);
max_filter
(
img
,
out
,
rect
.
width
(),
rect
.
height
(),
thresh
);
DLIB_TEST_MSG
(
array_to_matrix
(
out
)
==
array_to_matrix
(
out2
),
"rows: "
<<
rows
<<
"
\n
cols: "
<<
rows
<<
"
\n
width: "
<<
width
<<
"
\n
height: "
<<
height
);
}
// ----------------------------------------------------------------------------------------
void
test_max_filter
()
{
dlib
::
rand
rnd
;
for
(
int
iter
=
0
;
iter
<
300
;
++
iter
)
{
print_spinner
();
test_max_filter
(
0
,
0
,
1
,
1
,
rnd
);
test_max_filter
(
0
,
0
,
3
,
1
,
rnd
);
test_max_filter
(
0
,
0
,
3
,
3
,
rnd
);
test_max_filter
(
0
,
0
,
1
,
3
,
rnd
);
test_max_filter
(
1
,
1
,
1
,
1
,
rnd
);
test_max_filter
(
2
,
2
,
1
,
1
,
rnd
);
test_max_filter
(
3
,
3
,
1
,
1
,
rnd
);
test_max_filter
(
3
,
3
,
3
,
3
,
rnd
);
test_max_filter
(
3
,
3
,
3
,
5
,
rnd
);
test_max_filter
(
20
,
20
,
901
,
901
,
rnd
);
test_max_filter
(
5
,
5
,
1
,
5
,
rnd
);
test_max_filter
(
50
,
50
,
9
,
9
,
rnd
);
test_max_filter
(
50
,
50
,
9
,
9
,
rnd
);
test_max_filter
(
50
,
50
,
9
,
9
,
rnd
);
test_max_filter
(
20
,
20
,
1
,
901
,
rnd
);
test_max_filter
(
20
,
20
,
3
,
901
,
rnd
);
test_max_filter
(
20
,
20
,
901
,
1
,
rnd
);
}
for
(
int
iter
=
0
;
iter
<
200
;
++
iter
)
{
print_spinner
();
test_max_filter
((
int
)
rnd
.
get_random_8bit_number
()
%
100
+
1
,
(
int
)
rnd
.
get_random_8bit_number
()
%
100
+
1
,
(
int
)
rnd
.
get_random_8bit_number
()
*
2
+
1
,
(
int
)
rnd
.
get_random_8bit_number
()
*
2
+
1
,
rnd
);
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class
scan_image_tester
:
public
tester
class
scan_image_tester
:
public
tester
...
@@ -454,6 +553,8 @@ namespace
...
@@ -454,6 +553,8 @@ namespace
void
perform_test
(
void
perform_test
(
)
)
{
{
test_max_filter
();
run_test1
();
run_test1
();
run_test2
();
run_test2
();
run_test3
<
unsigned
char
>
(
1
);
run_test3
<
unsigned
char
>
(
1
);
...
...
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