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
73a34f7f
Commit
73a34f7f
authored
Sep 09, 2011
by
Davis King
Browse files
Added an overload of spatially_filter_image() that uses a separable filter.
parent
16ae5eac
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
248 additions
and
2 deletions
+248
-2
dlib/image_transforms/spatial_filtering.h
dlib/image_transforms/spatial_filtering.h
+109
-0
dlib/image_transforms/spatial_filtering_abstract.h
dlib/image_transforms/spatial_filtering_abstract.h
+49
-2
dlib/test/image.cpp
dlib/test/image.cpp
+90
-0
No files found.
dlib/image_transforms/spatial_filtering.h
View file @
73a34f7f
...
...
@@ -7,6 +7,7 @@
#include "spatial_filtering_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include "../array2d.h"
#include <limits>
namespace
dlib
...
...
@@ -102,6 +103,114 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
template
<
typename
in_image_type
,
typename
out_image_type
,
typename
filter_type
,
long
M
,
long
N
>
void
spatially_filter_image
(
const
in_image_type
&
in_img
,
out_image_type
&
out_img
,
const
filter_type
(
&
row_filter
)[
N
],
const
filter_type
(
&
col_filter
)[
M
],
unsigned
long
scale
=
1
,
bool
use_abs
=
false
)
{
COMPILE_TIME_ASSERT
(
pixel_traits
<
typename
in_image_type
::
type
>::
has_alpha
==
false
);
COMPILE_TIME_ASSERT
(
pixel_traits
<
typename
out_image_type
::
type
>::
has_alpha
==
false
);
COMPILE_TIME_ASSERT
(
M
%
2
==
1
);
COMPILE_TIME_ASSERT
(
N
%
2
==
1
);
DLIB_ASSERT
(
scale
>
0
,
"
\t
void spatially_filter_image()"
<<
"
\n\t
You can't give a scale of zero"
);
DLIB_ASSERT
(
is_same_object
(
in_img
,
out_img
)
==
false
,
"
\t
void spatially_filter_image()"
<<
"
\n\t
You must give two different image objects"
);
// if there isn't any input image then don't do anything
if
(
in_img
.
size
()
==
0
)
{
out_img
.
clear
();
return
;
}
out_img
.
set_size
(
in_img
.
nr
(),
in_img
.
nc
());
zero_border_pixels
(
out_img
,
M
/
2
,
N
/
2
);
// figure out the range that we should apply the filter to
const
long
first_row
=
M
/
2
;
const
long
first_col
=
N
/
2
;
const
long
last_row
=
in_img
.
nr
()
-
M
/
2
;
const
long
last_col
=
in_img
.
nc
()
-
N
/
2
;
typedef
typename
pixel_traits
<
typename
in_image_type
::
type
>::
basic_pixel_type
bp_type
;
typedef
typename
out_image_type
::
mem_manager_type
mem_manager_type
;
array2d
<
typename
promote
<
bp_type
>::
type
,
mem_manager_type
>
temp_img
;
temp_img
.
set_size
(
in_img
.
nr
(),
in_img
.
nc
());
// apply the row filter
for
(
long
r
=
0
;
r
<
in_img
.
nr
();
++
r
)
{
for
(
long
c
=
first_col
;
c
<
last_col
;
++
c
)
{
typename
promote
<
bp_type
>::
type
p
;
typename
promote
<
bp_type
>::
type
temp
=
0
;
for
(
long
n
=
0
;
n
<
N
;
++
n
)
{
// pull out the current pixel and put it into p
p
=
get_pixel_intensity
(
in_img
[
r
][
c
-
N
/
2
+
n
]);
temp
+=
p
*
row_filter
[
n
];
}
temp_img
[
r
][
c
]
=
temp
;
}
}
// apply the column filter
for
(
long
r
=
first_row
;
r
<
last_row
;
++
r
)
{
for
(
long
c
=
first_col
;
c
<
last_col
;
++
c
)
{
typename
promote
<
bp_type
>::
type
temp
=
0
;
for
(
long
m
=
0
;
m
<
M
;
++
m
)
{
temp
+=
temp_img
[
r
-
M
/
2
+
m
][
c
]
*
col_filter
[
m
];
}
temp
/=
scale
;
// Catch any underflow or apply abs as appropriate
if
(
temp
<
0
)
{
if
(
use_abs
)
{
temp
=
-
temp
;
}
else
{
temp
=
0
;
}
}
// save this pixel to the output image
assign_pixel
(
out_img
[
r
][
c
],
in_img
[
r
][
c
]);
assign_pixel_intensity
(
out_img
[
r
][
c
],
temp
);
}
}
}
// ----------------------------------------------------------------------------------------
template
<
...
...
dlib/image_transforms/spatial_filtering_abstract.h
View file @
73a34f7f
...
...
@@ -47,8 +47,55 @@ namespace dlib
- else
- pixel values after filtering that are < 0 are assigned the value of 0
- Pixels close enough to the edge of in_img to not have the filter still fit
inside the image are not modified. i.e. Whatever value the border of out_img
had to begin with is what it will have after this function returns.
inside the image are set to zero.
- #out_img.nc() == in_img.nc()
- #out_img.nr() == in_img.nr()
!*/
// ----------------------------------------------------------------------------------------
template
<
typename
in_image_type
,
typename
out_image_type
,
typename
filter_type
,
long
M
,
long
N
>
void
spatially_filter_image
(
const
in_image_type
&
in_img
,
out_image_type
&
out_img
,
const
filter_type
(
&
row_filter
)[
N
],
const
filter_type
(
&
col_filter
)[
M
],
unsigned
long
scale
=
1
,
bool
use_abs
=
false
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- is_same_object(in_img, out_img) == false
- scale > 0
- M % 2 == 1 (i.e. M must be odd)
- N % 2 == 1 (i.e. N must be odd)
ensures
- Applies the given separable spatial filter to in_img and stores the result in out_img.
Also divides each resulting pixel by scale. Calling this function has the same
effect as calling the regular spatially_filter_image() routine with a filter,
FILT, defined as follows:
- FILT[r][c] == col_filter[r]*row_filter[c]
- pixel values after filtering that are > pixel_traits<out_image_type>::max() are
set to pixel_traits<out_image_type>::max()
- if (pixel_traits<typename in_image_type::type>::grayscale == false) then
- the pixel values are converted to the HSI color space and the filtering
is done on the intensity channel only.
- if (use_abs == true) then
- pixel values after filtering that are < 0 are converted to their absolute values
- else
- pixel values after filtering that are < 0 are assigned the value of 0
- Pixels close enough to the edge of in_img to not have the filter still fit
inside the image are set to zero.
- #out_img.nc() == in_img.nc()
- #out_img.nr() == in_img.nr()
!*/
...
...
dlib/test/image.cpp
View file @
73a34f7f
...
...
@@ -762,6 +762,87 @@ namespace
}
template
<
typename
T
>
void
test_filtering
(
bool
use_abs
,
unsigned
long
scale
)
{
print_spinner
();
dlog
<<
LINFO
<<
"test_filtering("
<<
use_abs
<<
","
<<
scale
<<
")"
;
array2d
<
T
>
img
,
img2
,
img3
;
img
.
set_size
(
10
,
11
);
assign_all_pixels
(
img
,
10
);
int
filter
[
3
][
3
]
=
{
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
};
assign_all_pixels
(
img2
,
3
);
spatially_filter_image
(
img
,
img2
,
filter
);
for
(
long
r
=
0
;
r
<
img2
.
nr
();
++
r
)
{
for
(
long
c
=
0
;
c
<
img2
.
nc
();
++
c
)
{
if
(
shrink_rect
(
get_rect
(
img2
),
1
).
contains
(
c
,
r
))
{
DLIB_TEST
(
img2
[
r
][
c
]
==
90
);
}
else
{
DLIB_TEST
(
img2
[
r
][
c
]
==
0
);
}
}
}
assign_all_pixels
(
img2
,
3
);
assign_all_pixels
(
img3
,
3
);
spatially_filter_image
(
img
,
img2
,
filter
);
int
row_filter
[]
=
{
1
,
1
,
1
};
int
col_filter
[]
=
{
1
,
1
,
1
};
spatially_filter_image
(
img
,
img3
,
row_filter
,
col_filter
);
DLIB_TEST
(
array_to_matrix
(
img2
)
==
array_to_matrix
(
img3
));
dlib
::
rand
rnd
;
for
(
int
i
=
0
;
i
<
30
;
++
i
)
{
for
(
long
r
=
0
;
r
<
img
.
nr
();
++
r
)
{
for
(
long
c
=
0
;
c
<
img
.
nc
();
++
c
)
{
img
[
r
][
c
]
=
rnd
.
get_random_8bit_number
();
}
}
row_filter
[
0
]
=
((
int
)
rnd
.
get_random_8bit_number
()
-
100
)
/
10
;
row_filter
[
1
]
=
((
int
)
rnd
.
get_random_8bit_number
()
-
100
)
/
10
;
row_filter
[
2
]
=
((
int
)
rnd
.
get_random_8bit_number
()
-
100
)
/
10
;
col_filter
[
0
]
=
((
int
)
rnd
.
get_random_8bit_number
()
-
100
)
/
10
;
col_filter
[
1
]
=
((
int
)
rnd
.
get_random_8bit_number
()
-
100
)
/
10
;
col_filter
[
2
]
=
((
int
)
rnd
.
get_random_8bit_number
()
-
100
)
/
10
;
for
(
long
rr
=
0
;
rr
<
3
;
++
rr
)
{
for
(
long
cc
=
0
;
cc
<
3
;
++
cc
)
{
filter
[
rr
][
cc
]
=
row_filter
[
cc
]
*
col_filter
[
rr
];
}
}
assign_all_pixels
(
img2
,
3
);
assign_all_pixels
(
img3
,
3
);
// Just make sure both filtering methods give the same results.
spatially_filter_image
(
img
,
img2
,
filter
,
scale
,
use_abs
);
spatially_filter_image
(
img
,
img3
,
row_filter
,
col_filter
,
scale
,
use_abs
);
DLIB_TEST
(
array_to_matrix
(
img2
)
==
array_to_matrix
(
img3
));
}
}
class
image_tester
:
public
tester
{
...
...
@@ -780,6 +861,15 @@ namespace
test_integral_image
<
double
,
int
>
();
test_integral_image
<
long
,
unsigned
char
>
();
test_integral_image
<
double
,
float
>
();
test_filtering
<
unsigned
char
>
(
false
,
1
);
test_filtering
<
unsigned
char
>
(
true
,
1
);
test_filtering
<
unsigned
char
>
(
false
,
3
);
test_filtering
<
unsigned
char
>
(
true
,
3
);
test_filtering
<
int
>
(
false
,
1
);
test_filtering
<
int
>
(
true
,
1
);
test_filtering
<
int
>
(
false
,
3
);
test_filtering
<
int
>
(
true
,
3
);
}
}
a
;
...
...
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