Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
dlib
Commits
fce8eaab
Commit
fce8eaab
authored
Jun 30, 2012
by
Davis King
Browse files
Added the max_filter() routine.
parent
c1c8267b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
323 additions
and
0 deletions
+323
-0
dlib/image_transforms/spatial_filtering.h
dlib/image_transforms/spatial_filtering.h
+183
-0
dlib/image_transforms/spatial_filtering_abstract.h
dlib/image_transforms/spatial_filtering_abstract.h
+39
-0
dlib/test/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