Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Olena
olena
Commits
619f727a
Commit
619f727a
authored
Feb 19, 2010
by
Guillaume Lazzara
Browse files
scribo/src/text_in_photo_ppm.cc: Improve output.
parent
ca034dd5
Changes
2
Show whitespace changes
Inline
Side-by-side
scribo/ChangeLog
View file @
619f727a
2010-02-19 Guillaume Lazzara <z@lrde.epita.fr>
* scribo/src/text_in_photo_ppm.cc: Improve output.
2010-02-19 Guillaume Lazzara <z@lrde.epita.fr>
Cleanup and avoid warnings in Sauvola related files.
...
...
scribo/src/text_in_photo_ppm.cc
View file @
619f727a
...
...
@@ -27,6 +27,7 @@
#include
<iostream>
#include
<mln/core/image/image2d.hh>
#include
<mln/core/image/imorph/tr_image.hh>
#include
<mln/core/alias/neighb2d.hh>
#include
<mln/labeling/colorize.hh>
...
...
@@ -38,12 +39,16 @@
#include
<mln/logical/not.hh>
#include
<mln/fun/v2v/rgb_to_int_u.hh>
#include
<mln/literal/colors.hh>
#include
<mln/value/rgb8.hh>
#include
<mln/value/label_16.hh>
#include
<mln/draw/box.hh>
#include
<mln/geom/translate.hh>
#include
<scribo/binarization/sauvola.hh>
#include
<scribo/draw/bounding_boxes.hh>
...
...
@@ -58,6 +63,7 @@
#include
<scribo/primitive/group/from_double_link.hh>
#include
<scribo/primitive/group/from_single_link.hh>
#include
<scribo/filter/objects_with_holes.hh>
#include
<scribo/filter/object_links_bbox_h_ratio.hh>
#include
<scribo/filter/object_links_bbox_overlap.hh>
...
...
@@ -68,7 +74,6 @@
#include
<scribo/debug/decision_image.hh>
#include
<scribo/debug/save_bboxes_image.hh>
#include
<scribo/debug/save_bboxes_image.hh>
#include
<scribo/debug/save_linked_bboxes_image.hh>
#include
<scribo/debug/usage.hh>
...
...
@@ -77,6 +82,9 @@
#include
<scribo/make/debug_filename.hh>
#include
<mln/util/timer.hh>
#include
<mln/core/var.hh>
const
char
*
args_desc
[][
2
]
=
{
{
"input.ppm"
,
"A color image."
},
...
...
@@ -86,20 +94,117 @@ const char *args_desc[][2] =
};
namespace
mln
{
struct
mask_non_text
:
Function_v2v
<
mask_non_text
>
{
typedef
value
::
rgb8
result
;
typedef
image2d
<
bool
>
I
;
mask_non_text
(
const
image2d
<
bool
>&
mask
)
:
mask_
(
mask
),
p_
(
mask_
)
{
p_
.
start
();
}
result
operator
()(
const
result
&
v
)
const
{
bool
b
=
p_
.
val
();
p_
.
next
();
if
(
!
b
)
return
v
/
2
;
else
return
v
;
}
I
mask_
;
mutable
mln_pixter_
(
I
)
p_
;
};
template
<
typename
I
,
typename
L
>
mln_concrete
(
I
)
compute_highlight_image
(
const
I
&
input_rgb
,
const
object_image
<
L
>&
objects
)
{
mln_ch_value
(
I
,
bool
)
mask
;
initialize
(
mask
,
input_rgb
);
data
::
fill
(
mask
,
false
);
for_all_components
(
i
,
objects
.
bboxes
())
data
::
fill
((
mask
|
objects
.
bbox
(
i
)).
rw
(),
true
);
mask_non_text
f
(
mask
);
mln_concrete
(
I
)
output
=
data
::
transform
(
input_rgb
,
f
);
for_all_components
(
i
,
objects
.
bboxes
())
mln
::
draw
::
box
(
output
,
objects
.
bbox
(
i
),
literal
::
red
);
return
output
;
}
template
<
typename
I
,
typename
L
>
mln_concrete
(
I
)
compute_text_image
(
const
I
&
input_rgb
,
const
object_image
<
L
>&
grouped_objects
)
{
const
util
::
array
<
mln_domain
(
L
)
>&
bboxes
=
grouped_objects
.
bboxes
();
unsigned
shift
=
5
;
float
height
=
1
,
width
=
0
;
for_all_components
(
i
,
bboxes
)
{
height
+=
bboxes
(
i
).
nrows
()
+
shift
;
width
=
math
::
max
(
static_cast
<
float
>
(
bboxes
(
i
).
ncols
()),
width
);
}
if
(
width
==
0
)
width
=
1
;
I
output
(
height
,
width
);
data
::
fill
(
output
,
literal
::
black
);
algebra
::
vec
<
2
,
float
>
dv
;
dv
[
0
]
=
0
;
dv
[
1
]
=
0
;
for_all_ncomponents
(
i
,
grouped_objects
.
nlabels
())
{
mln_VAR
(
tmp
,
duplicate
(
input_rgb
|
grouped_objects
.
bbox
(
i
)));
typedef
fun
::
x2x
::
translation
<
mln_site_
(
I
)
::
dim
,
float
>
trans_t
;
trans_t
trans
(
dv
-
grouped_objects
.
bbox
(
i
).
pmin
().
to_vec
());
mln_domain
(
I
)
tr_box
(
grouped_objects
.
bbox
(
i
).
pmin
().
to_vec
()
+
trans
.
t
(),
grouped_objects
.
bbox
(
i
).
pmax
().
to_vec
()
+
trans
.
t
());
tr_image
<
mln_domain
(
I
),
tmp_t
,
trans_t
>
tr_ima
(
tr_box
,
tmp
,
trans
);
data
::
paste
(
tr_ima
,
output
);
dv
[
0
]
+=
grouped_objects
.
bbox
(
i
).
nrows
()
+
shift
;
}
return
output
;
}
}
// end of namespace mln
int
main
(
int
argc
,
char
*
argv
[])
{
using
namespace
scribo
;
using
namespace
mln
;
if
(
argc
!=
3
&&
argc
!=
4
&&
argc
!=
5
)
if
(
argc
!=
3
&&
argc
!=
4
&&
argc
!=
5
&&
argc
!=
6
)
return
scribo
::
debug
::
usage
(
argv
,
"Find text in a photo."
,
"input.ppm output.ppm [debug_output_dir] [lambda]"
,
"input.ppm output.ppm
[bg/fg]
[debug_output_dir] [lambda]"
,
args_desc
,
"A color image where the text is highlighted."
);
if
(
argc
>
3
)
scribo
::
make
::
internal
::
debug_filename_prefix
=
argv
[
3
];
if
(
argc
>
4
)
scribo
::
make
::
internal
::
debug_filename_prefix
=
argv
[
4
];
trace
::
entering
(
"main"
);
...
...
@@ -108,22 +213,50 @@ int main(int argc, char* argv[])
unsigned
lambda
;
if
(
argc
==
5
)
lambda
=
atoi
(
argv
[
4
]);
if
(
argc
==
6
)
lambda
=
atoi
(
argv
[
5
]);
else
lambda
=
1.2
*
(
input_rgb
.
nrows
()
+
input_rgb
.
ncols
());
util
::
timer
timer_
;
// Extract foreground
image2d
<
value
::
int_u8
>
intensity_ima
;
std
::
cout
<<
"Extracting foreground..."
<<
std
::
endl
;
timer_
.
start
();
if
(
argc
>
3
&&
atoi
(
argv
[
3
])
!=
0
)
{
// Extract foreground
timer_
.
start
();
image2d
<
value
::
rgb8
>
fg
=
preprocessing
::
split_bg_fg
(
input_rgb
,
lambda
,
32
).
second
();
intensity_ima
=
data
::
transform
(
fg
,
mln
::
fun
::
v2v
::
rgb_to_int_u
<
8
>
());
float
t_
=
timer_
;
std
::
cout
<<
"Foreground extracted. "
<<
t_
<<
std
::
endl
;
}
else
{
timer_
.
start
();
intensity_ima
=
data
::
transform
(
input_rgb
,
mln
::
fun
::
v2v
::
rgb_to_int_u
<
8
>
());
float
t_
=
timer_
;
std
::
cout
<<
"Intensity image "
<<
t_
<<
std
::
endl
;
}
float
t_
=
timer_
;
std
::
cout
<<
"Foreground extracted. "
<<
t_
<<
std
::
endl
;
// Binarize foreground to use it in the processing chain.
// FIXME: TOO SLOW!
std
::
cout
<<
"Binarizing foreground..."
<<
std
::
endl
;
image2d
<
bool
>
input
=
binarization
::
sauvola
(
fg
);
timer_
.
restart
();
image2d
<
bool
>
input
=
binarization
::
sauvola
(
intensity_ima
,
11
);
io
::
pbm
::
save
(
input
,
"input.pbm"
);
t_
=
timer_
;
std
::
cout
<<
"Foreground binarized. "
<<
t_
<<
std
::
endl
;
...
...
@@ -131,25 +264,35 @@ int main(int argc, char* argv[])
/// Finding objects.
std
::
cout
<<
"Extracting objects..."
<<
std
::
endl
;
timer_
.
restart
();
value
::
label_16
nobjects
;
object_image
(
L
)
objects
=
scribo
::
primitive
::
extract
::
objects
(
input
,
c8
(),
nobjects
);
t_
=
timer_
;
std
::
cout
<<
"Object extracted"
<<
t_
<<
std
::
endl
;
/// First filtering.
std
::
cout
<<
"Filtering objects..."
<<
std
::
endl
;
timer_
.
restart
();
object_image
(
L
)
filtered_objects
=
filter
::
common
::
objects_photo
(
objects
);
t_
=
timer_
;
std
::
cout
<<
"Object filtered"
<<
t_
<<
std
::
endl
;
/// linking potential objects
std
::
cout
<<
"Linking objects..."
<<
std
::
endl
;
timer_
.
restart
();
object_links
<
L
>
left_link
=
primitive
::
link
::
with_single_left_link
(
filtered_objects
,
30
);
t_
=
timer_
;
std
::
cout
<<
"Left Link done"
<<
t_
<<
std
::
endl
;
timer_
.
restart
();
object_links
<
L
>
right_link
=
primitive
::
link
::
with_single_right_link
(
filtered_objects
,
30
);
t_
=
timer_
;
std
::
cout
<<
"Right Link done"
<<
t_
<<
std
::
endl
;
...
...
@@ -170,16 +313,22 @@ int main(int argc, char* argv[])
// Validating left and right links.
timer_
.
restart
();
object_links
<
L
>
merged_links
=
primitive
::
link
::
merge_double_link
(
filtered_objects
,
left_link
,
right_link
);
t_
=
timer_
;
std
::
cout
<<
"Right/Left Validation. "
<<
t_
<<
std
::
endl
;
// Remove links if bboxes have too different sizes.
std
::
cout
<<
"Filtering object links..."
<<
std
::
endl
;
timer_
.
restart
();
object_links
<
L
>
hratio_filtered_links
=
filter
::
object_links_bbox_h_ratio
(
filtered_objects
,
merged_links
,
0.7
f
);
1.50
f
);
...
...
@@ -221,8 +370,11 @@ int main(int argc, char* argv[])
#endif
t_
=
timer_
;
std
::
cout
<<
"Objects links filtered. "
<<
t_
<<
std
::
endl
;
std
::
cout
<<
"Grouping objects..."
<<
std
::
endl
;
timer_
.
restart
();
object_groups
<
L
>
groups
=
primitive
::
group
::
from_single_link
(
filtered_objects
,
overlap_filtered_links
);
...
...
@@ -234,11 +386,31 @@ int main(int argc, char* argv[])
raw_group_image
=
primitive
::
group
::
apply
(
filtered_objects
,
filter
::
object_groups_small
(
groups
,
2
));
t_
=
timer_
;
std
::
cout
<<
"Objects grouped. "
<<
t_
<<
std
::
endl
;
#ifndef NOUT
if
(
argc
>
3
)
scribo
::
debug
::
save_bboxes_image
(
input
,
raw_group_image
.
bboxes
(),
literal
::
red
,
scribo
::
make
::
debug_filename
(
"group_image.ppm"
));
#endif // !NOUT
std
::
cout
<<
"Filtering groups..."
<<
std
::
endl
;
util
::
timer
g_timer
;
timer_
.
restart
();
// Remove objects part of groups with strictly less than 3 objects.
g_timer
.
start
();
object_groups
<
L
>
filtered_small_groups
=
filter
::
object_groups_small
(
groups
,
3
);
t_
=
g_timer
;
std
::
cout
<<
"Small groups removed "
<<
t_
<<
std
::
endl
;
#ifndef NOUT
...
...
@@ -256,8 +428,11 @@ int main(int argc, char* argv[])
// Remove objects part of groups having a mean thickness lower than 8.
g_timer
.
restart
();
object_groups
<
L
>
filtered_thin_groups
=
filter
::
object_groups_v_thickness
(
filtered_small_groups
,
8
);
t_
=
g_timer
;
std
::
cout
<<
"Groups too thin "
<<
t_
<<
std
::
endl
;
#ifndef NOUT
...
...
@@ -275,14 +450,19 @@ int main(int argc, char* argv[])
/// Apply grouping in the object image.
g_timer
.
restart
();
object_image
(
L
)
grouped_objects
=
primitive
::
group
::
apply
(
filtered_objects
,
filtered_thin_groups
);
t_
=
g_timer
;
std
::
cout
<<
"Group applied to object image "
<<
t_
<<
std
::
endl
;
/// Objects have been grouped. We try to link groups together.
/// This time a single link is enough since non-wanted objects have
/// been removed.
g_timer
.
restart
();
left_link
=
primitive
::
link
::
with_single_left_link
(
grouped_objects
,
30
);
...
...
@@ -292,8 +472,28 @@ int main(int argc, char* argv[])
grouped_objects
=
primitive
::
group
::
apply
(
grouped_objects
,
groups
);
t_
=
g_timer
;
std
::
cout
<<
"Link and group again "
<<
t_
<<
std
::
endl
;
timer_
.
stop
();
io
::
ppm
::
save
(
mln
::
labeling
::
colorize
(
value
::
rgb8
(),
grouped_objects
,
grouped_objects
.
nlabels
()),
scribo
::
make
::
debug_filename
(
"out_before_hole_filter.ppm"
));
timer_
.
resume
();
g_timer
.
restart
();
/// Filter grouped objects not having enough background components.
grouped_objects
=
scribo
::
filter
::
objects_with_holes_slow
(
grouped_objects
,
2
);
// grouped_objects = scribo::filter::objects_with_holes(grouped_objects, 2, 2);
t_
=
g_timer
;
std
::
cout
<<
"Objects_with_holes "
<<
t_
<<
std
::
endl
;
t_
=
timer_
;
std
::
cout
<<
"Objects groups filtered. "
<<
t_
<<
std
::
endl
;
#ifndef NOUT
if
(
argc
>
3
)
...
...
@@ -313,6 +513,20 @@ int main(int argc, char* argv[])
grouped_objects
.
nlabels
()),
argv
[
2
]);
#ifndef NOUT
io
::
ppm
::
save
(
compute_highlight_image
(
input_rgb
,
grouped_objects
),
scribo
::
make
::
debug_filename
(
"orig_with_bboxes.ppm"
));
// scribo::debug::save_bboxes_image(input_rgb, grouped_objects.bboxes(),
// literal::red,
// scribo::make::debug_filename("orig_with_bboxes.ppm"));
#endif
io
::
ppm
::
save
(
compute_text_image
(
input_rgb
,
grouped_objects
),
scribo
::
make
::
debug_filename
(
"out_text.ppm"
));
std
::
cout
<<
"# objects = "
<<
grouped_objects
.
nlabels
()
<<
std
::
endl
;
trace
::
exiting
(
"main"
);
return
grouped_objects
.
nlabels
()
!=
0
;
}
Write
Preview
Supports
Markdown
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