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
30e073d6
Commit
30e073d6
authored
Dec 29, 2011
by
Davis King
Browse files
Reworked the scan_image() routine to make it run faster. Also added
a new function called sum_filter().
parent
6c0f5980
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
206 additions
and
111 deletions
+206
-111
dlib/image_processing/scan_image.h
dlib/image_processing/scan_image.h
+102
-111
dlib/image_processing/scan_image_abstract.h
dlib/image_processing/scan_image_abstract.h
+25
-0
dlib/test/scan_image.cpp
dlib/test/scan_image.cpp
+79
-0
No files found.
dlib/image_processing/scan_image.h
View file @
30e073d6
...
@@ -9,6 +9,7 @@
...
@@ -9,6 +9,7 @@
#include "../matrix.h"
#include "../matrix.h"
#include "../algs.h"
#include "../algs.h"
#include "../rand.h"
#include "../rand.h"
#include "../array2d.h"
namespace
dlib
namespace
dlib
{
{
...
@@ -106,6 +107,100 @@ namespace dlib
...
@@ -106,6 +107,100 @@ namespace dlib
return
static_cast
<
double
>
(
temp
);
return
static_cast
<
double
>
(
temp
);
}
}
// ----------------------------------------------------------------------------------------
template
<
typename
image_type1
,
typename
image_type2
>
void
sum_filter
(
const
image_type1
&
img
,
image_type2
&
out
,
const
rectangle
&
rect
)
{
DLIB_ASSERT
(
img
.
nr
()
==
out
.
nr
()
&&
img
.
nc
()
==
out
.
nc
(),
"
\t
void sum_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
()
);
typedef
typename
image_type1
::
type
pixel_type
;
typedef
typename
promote
<
pixel_type
>::
type
ptype
;
std
::
vector
<
ptype
>
column_sum
;
column_sum
.
resize
(
img
.
nc
()
+
rect
.
width
(),
0
);
const
long
top
=
-
1
+
rect
.
top
();
const
long
bottom
=
-
1
+
rect
.
bottom
();
long
left
=
rect
.
left
()
-
1
;
// initialize column_sum at row -1
for
(
unsigned
long
j
=
0
;
j
<
column_sum
.
size
();
++
j
)
{
rectangle
strip
(
left
,
top
,
left
,
bottom
);
strip
=
strip
.
intersect
(
get_rect
(
img
));
if
(
!
strip
.
is_empty
())
{
column_sum
[
j
]
=
sum
(
matrix_cast
<
ptype
>
(
subm
(
array_to_matrix
(
img
),
strip
)));
}
++
left
;
}
const
rectangle
area
=
get_rect
(
img
);
// save width to avoid computing them over and over
const
long
width
=
rect
.
width
();
// Now do the bulk of the scanning work.
for
(
long
r
=
0
;
r
<
img
.
nr
();
++
r
)
{
// set to sum at point(-1,r). i.e. should be equal to sum_of_rects_in_images(images, rects, point(-1,r))
// We compute it's value in the next loop.
ptype
cur_sum
=
0
;
// Update the first part of column_sum since we only work on the c+width part of column_sum
// in the main loop.
const
long
top
=
r
+
rect
.
top
()
-
1
;
const
long
bottom
=
r
+
rect
.
bottom
();
for
(
long
k
=
0
;
k
<
width
;
++
k
)
{
const
long
right
=
k
-
width
+
rect
.
right
();
const
ptype
br_corner
=
area
.
contains
(
right
,
bottom
)
?
img
[
bottom
][
right
]
:
0
;
const
ptype
tr_corner
=
area
.
contains
(
right
,
top
)
?
img
[
top
][
right
]
:
0
;
// update the sum in this column now that we are on the next row
column_sum
[
k
]
=
column_sum
[
k
]
+
br_corner
-
tr_corner
;
cur_sum
+=
column_sum
[
k
];
}
for
(
long
c
=
0
;
c
<
img
.
nc
();
++
c
)
{
const
long
top
=
r
+
rect
.
top
()
-
1
;
const
long
bottom
=
r
+
rect
.
bottom
();
const
long
right
=
c
+
rect
.
right
();
const
ptype
br_corner
=
area
.
contains
(
right
,
bottom
)
?
img
[
bottom
][
right
]
:
0
;
const
ptype
tr_corner
=
area
.
contains
(
right
,
top
)
?
img
[
top
][
right
]
:
0
;
// update the sum in this column now that we are on the next row
column_sum
[
c
+
width
]
=
column_sum
[
c
+
width
]
+
br_corner
-
tr_corner
;
// add in the new right side of the rect and subtract the old right side.
cur_sum
=
cur_sum
+
column_sum
[
c
+
width
]
-
column_sum
[
c
];
out
[
r
][
c
]
+=
cur_sum
;
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template
<
template
<
...
@@ -143,127 +238,23 @@ namespace dlib
...
@@ -143,127 +238,23 @@ namespace dlib
if
(
max_dets
==
0
)
if
(
max_dets
==
0
)
return
;
return
;
dlib
::
rand
rnd
;
typedef
typename
image_array_type
::
type
::
type
pixel_type
;
typedef
typename
image_array_type
::
type
::
type
pixel_type
;
typedef
typename
promote
<
pixel_type
>::
type
ptype
;
typedef
typename
promote
<
pixel_type
>::
type
ptype
;
std
::
vector
<
std
::
vector
<
ptype
>
>
column_sums
(
rects
.
size
());
array2d
<
ptype
>
accum
(
images
[
0
].
nr
(),
images
[
0
].
nc
());
for
(
unsigned
long
i
=
0
;
i
<
column_sums
.
size
();
++
i
)
assign_all_pixels
(
accum
,
0
);
{
const
typename
image_array_type
::
type
&
img
=
images
[
rects
[
i
].
first
];
column_sums
[
i
].
resize
(
img
.
nc
()
+
rects
[
i
].
second
.
width
(),
0
);
const
long
top
=
-
1
+
rects
[
i
].
second
.
top
();
const
long
bottom
=
-
1
+
rects
[
i
].
second
.
bottom
();
long
left
=
rects
[
i
].
second
.
left
()
-
1
;
// initialize column_sums[i] at row -1
for
(
unsigned
long
j
=
0
;
j
<
column_sums
[
i
].
size
();
++
j
)
{
rectangle
strip
(
left
,
top
,
left
,
bottom
);
strip
=
strip
.
intersect
(
get_rect
(
img
));
if
(
!
strip
.
is_empty
())
{
column_sums
[
i
][
j
]
=
sum
(
matrix_cast
<
ptype
>
(
subm
(
array_to_matrix
(
img
),
strip
)));
}
++
left
;
}
}
const
rectangle
area
=
get_rect
(
images
[
0
]);
// Figure out the area of the image where we won't need to do boundary checking
// when sliding the boxes around.
rectangle
bound
=
dlib
::
impl
::
bounding_box_of_rects
(
rects
,
point
(
0
,
0
));
rectangle
free_area
=
get_rect
(
images
[
0
]);
free_area
.
left
()
-=
bound
.
left
();
free_area
.
top
()
-=
bound
.
top
()
-
1
;
free_area
.
right
()
-=
bound
.
right
();
free_area
.
bottom
()
-=
bound
.
bottom
();
// save widths to avoid computing them over and over
std
::
vector
<
long
>
widths
(
rects
.
size
());
for
(
unsigned
long
i
=
0
;
i
<
rects
.
size
();
++
i
)
for
(
unsigned
long
i
=
0
;
i
<
rects
.
size
();
++
i
)
widths
[
i
]
=
rects
[
i
].
second
.
width
(
);
sum_filter
(
images
[
rects
[
i
].
first
],
accum
,
rects
[
i
].
second
);
unsigned
long
count
=
0
;
unsigned
long
count
=
0
;
dlib
::
rand
rnd
;
// Now do the bulk of the scanning work.
for
(
long
r
=
0
;
r
<
accum
.
nr
();
++
r
)
for
(
long
r
=
0
;
r
<
images
[
0
].
nr
();
++
r
)
{
{
// set to sum at point(-1,r). i.e. should be equal to sum_of_rects_in_images(images, rects, point(-1,r))
for
(
long
c
=
0
;
c
<
accum
.
nc
();
++
c
)
// We compute it's value in the next loop.
ptype
cur_sum
=
0
;
// Update the first part of column_sums since we only work on the c+width part of column_sums
// in the main loop.
for
(
unsigned
long
i
=
0
;
i
<
rects
.
size
();
++
i
)
{
const
typename
image_array_type
::
type
&
img
=
images
[
rects
[
i
].
first
];
const
long
top
=
r
+
rects
[
i
].
second
.
top
()
-
1
;
const
long
bottom
=
r
+
rects
[
i
].
second
.
bottom
();
const
long
width
=
rects
[
i
].
second
.
width
();
for
(
long
k
=
0
;
k
<
width
;
++
k
)
{
const
long
right
=
k
-
width
+
rects
[
i
].
second
.
right
();
const
ptype
br_corner
=
area
.
contains
(
right
,
bottom
)
?
img
[
bottom
][
right
]
:
0
;
const
ptype
tr_corner
=
area
.
contains
(
right
,
top
)
?
img
[
top
][
right
]
:
0
;
// update the sum in this column now that we are on the next row
column_sums
[
i
][
k
]
=
column_sums
[
i
][
k
]
+
br_corner
-
tr_corner
;
cur_sum
+=
column_sums
[
i
][
k
];
}
}
for
(
long
c
=
0
;
c
<
images
[
0
].
nc
();
++
c
)
{
{
// if we don't need to do the bounds checking on the image
const
ptype
cur_sum
=
accum
[
r
][
c
];
if
(
free_area
.
contains
(
c
,
r
))
{
for
(
unsigned
long
i
=
0
;
i
<
rects
.
size
();
++
i
)
{
const
typename
image_array_type
::
type
&
img
=
images
[
rects
[
i
].
first
];
const
long
top
=
r
+
rects
[
i
].
second
.
top
()
-
1
;
const
long
bottom
=
r
+
rects
[
i
].
second
.
bottom
();
const
long
right
=
c
+
rects
[
i
].
second
.
right
();
const
long
width
=
widths
[
i
];
const
ptype
br_corner
=
img
[
bottom
][
right
];
const
ptype
tr_corner
=
img
[
top
][
right
];
// update the sum in this column now that we are on the next row
column_sums
[
i
][
c
+
width
]
=
column_sums
[
i
][
c
+
width
]
+
br_corner
-
tr_corner
;
// add in the new right side of the rect and subtract the old right side.
cur_sum
=
cur_sum
+
column_sums
[
i
][
c
+
width
]
-
column_sums
[
i
][
c
];
}
}
else
{
for
(
unsigned
long
i
=
0
;
i
<
rects
.
size
();
++
i
)
{
const
typename
image_array_type
::
type
&
img
=
images
[
rects
[
i
].
first
];
const
long
top
=
r
+
rects
[
i
].
second
.
top
()
-
1
;
const
long
bottom
=
r
+
rects
[
i
].
second
.
bottom
();
const
long
right
=
c
+
rects
[
i
].
second
.
right
();
const
long
width
=
widths
[
i
];
const
ptype
br_corner
=
area
.
contains
(
right
,
bottom
)
?
img
[
bottom
][
right
]
:
0
;
const
ptype
tr_corner
=
area
.
contains
(
right
,
top
)
?
img
[
top
][
right
]
:
0
;
// update the sum in this column now that we are on the next row
column_sums
[
i
][
c
+
width
]
=
column_sums
[
i
][
c
+
width
]
+
br_corner
-
tr_corner
;
// add in the new right side of the rect and subtract the old right side.
cur_sum
=
cur_sum
+
column_sums
[
i
][
c
+
width
]
-
column_sums
[
i
][
c
];
}
}
if
(
cur_sum
>=
thresh
)
if
(
cur_sum
>=
thresh
)
{
{
++
count
;
++
count
;
...
...
dlib/image_processing/scan_image_abstract.h
View file @
30e073d6
...
@@ -10,6 +10,31 @@
...
@@ -10,6 +10,31 @@
namespace
dlib
namespace
dlib
{
{
// ----------------------------------------------------------------------------------------
template
<
typename
image_type1
,
typename
image_type2
>
void
sum_filter
(
const
image_type1
&
img
,
image_type2
&
out
,
const
rectangle
&
rect
)
/*!
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
ensures
- for all valid r and c:
- let SUM(r,c) == sum of pixels inside the rectangle translate_rect(rect, point(c,r))
- #out[r][c] == out[r][c] + SUM(r,c)
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template
<
template
<
...
...
dlib/test/scan_image.cpp
View file @
30e073d6
...
@@ -28,6 +28,30 @@ namespace
...
@@ -28,6 +28,30 @@ namespace
// should start with "test."
// should start with "test."
logger
dlog
(
"test.scan_image"
);
logger
dlog
(
"test.scan_image"
);
// ----------------------------------------------------------------------------------------
template
<
typename
image_type1
,
typename
image_type2
>
void
sum_filter_i
(
const
image_type1
&
img
,
image_type2
&
out
,
const
rectangle
&
rect
)
{
typedef
typename
image_type1
::
type
pixel_type
;
typedef
typename
promote
<
pixel_type
>::
type
ptype
;
integral_image_generic
<
ptype
>
iimg
;
iimg
.
load
(
img
);
for
(
long
r
=
0
;
r
<
img
.
nr
();
++
r
)
{
for
(
long
c
=
0
;
c
<
img
.
nc
();
++
c
)
{
const
rectangle
temp
=
translate_rect
(
rect
,
point
(
c
,
r
)).
intersect
(
get_rect
(
iimg
));
if
(
temp
.
is_empty
()
==
false
)
out
[
r
][
c
]
+=
iimg
.
get_sum_of_area
(
temp
);
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
...
@@ -364,6 +388,58 @@ namespace
...
@@ -364,6 +388,58 @@ namespace
}
}
}
}
// ----------------------------------------------------------------------------------------
template
<
typename
pixel_type
>
void
test_sum_filter
(
)
{
dlib
::
rand
rnd
;
for
(
int
k
=
0
;
k
<
20
;
++
k
)
{
print_spinner
();
array2d
<
pixel_type
>
img
(
1
+
rnd
.
get_random_32bit_number
()
%
100
,
1
+
rnd
.
get_random_32bit_number
()
%
100
);
for
(
long
r
=
0
;
r
<
img
.
nr
();
++
r
)
{
for
(
long
c
=
0
;
c
<
img
.
nc
();
++
c
)
{
img
[
r
][
c
]
=
100
*
(
rnd
.
get_random_double
()
-
0.5
);
}
}
array2d
<
long
>
test1
(
img
.
nr
(),
img
.
nc
());
array2d
<
double
>
test2
(
img
.
nr
(),
img
.
nc
());
array2d
<
long
>
test1_i
(
img
.
nr
(),
img
.
nc
());
array2d
<
double
>
test2_i
(
img
.
nr
(),
img
.
nc
());
assign_all_pixels
(
test1
,
0
);
assign_all_pixels
(
test2
,
0
);
assign_all_pixels
(
test1_i
,
0
);
assign_all_pixels
(
test2_i
,
0
);
for
(
int
i
=
0
;
i
<
10
;
++
i
)
{
const
long
width
=
rnd
.
get_random_32bit_number
()
%
10
+
1
;
const
long
height
=
rnd
.
get_random_32bit_number
()
%
10
+
1
;
const
point
p
(
rnd
.
get_random_32bit_number
()
%
img
.
nc
(),
rnd
.
get_random_32bit_number
()
%
img
.
nr
());
const
rectangle
rect
=
centered_rect
(
p
,
width
,
height
);
sum_filter
(
img
,
test1
,
rect
);
sum_filter
(
img
,
test2
,
rect
);
sum_filter
(
img
,
test1_i
,
rect
);
sum_filter
(
img
,
test2_i
,
rect
);
DLIB_TEST
(
array_to_matrix
(
test1
)
==
array_to_matrix
(
test1_i
));
DLIB_TEST
(
array_to_matrix
(
test2
)
==
array_to_matrix
(
test2_i
));
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class
scan_image_tester
:
public
tester
class
scan_image_tester
:
public
tester
...
@@ -384,6 +460,9 @@ namespace
...
@@ -384,6 +460,9 @@ namespace
run_test3
<
unsigned
char
>
(
-
1
);
run_test3
<
unsigned
char
>
(
-
1
);
run_test3
<
double
>
(
1
);
run_test3
<
double
>
(
1
);
run_test3
<
double
>
(
-
1
);
run_test3
<
double
>
(
-
1
);
test_sum_filter
<
unsigned
char
>
();
test_sum_filter
<
double
>
();
}
}
}
a
;
}
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