Commit 33ffff60 authored by Guillaume Lazzara's avatar Guillaume Lazzara
Browse files

Improve Scribo demo.

	* demo/demat/demat.pro: Add new flags.

	* demo/demat/src/main.cc: Make use of MLN_WO_GLOBALS_VARS.

	* demo/demat/src/main_window.cc,
	* demo/demat/src/main_window.hh: Cropping is not required
	anymore. Improve visualization speed.

	* demo/demat/src/preprocessing_task.hh,
	* demo/demat/src/runner.cc,
	* demo/demat/src/runner.hh,
	* demo/demat/ui/main_window.ui: Add a new task for Sauvola ms
	split.

	* demo/review/src/main.cc,
	* demo/review/src/mainwindow.cc,
	* demo/review/src/mainwindow.hh: Start updating executable names
	and arguments.

	* demo/shared/src/crop_item.cc,
	* demo/shared/src/crop_item.hh,
	* demo/shared/src/image_viewer.cc,
	* demo/shared/src/image_viewer.hh,
	* demo/shared/src/image_viewer.hxx,
	* demo/shared/src/internal/interactive_scene.cc,
	* demo/shared/src/internal/interactive_scene.hh,
	* demo/shared/ui/image_viewer.ui: Improve look and feel and
	drawing speed of these components.

	* demo/wizard/src/load_page.cc,
	* demo/wizard/src/main_window.cc,
	* demo/wizard/src/runner.cc: Fix compilation.
parent 31216d34
2010-06-03 Guillaume Lazzara <z@lrde.epita.fr>
Improve Scribo demo.
* demo/demat/demat.pro: Add new flags.
* demo/demat/src/main.cc: Make use of MLN_WO_GLOBALS_VARS.
* demo/demat/src/main_window.cc,
* demo/demat/src/main_window.hh: Cropping is not required
anymore. Improve visualization speed.
* demo/demat/src/preprocessing_task.hh,
* demo/demat/src/runner.cc,
* demo/demat/src/runner.hh,
* demo/demat/ui/main_window.ui: Add a new task for Sauvola ms
split.
* demo/review/src/main.cc,
* demo/review/src/mainwindow.cc,
* demo/review/src/mainwindow.hh: Start updating executable names
and arguments.
* demo/shared/src/crop_item.cc,
* demo/shared/src/crop_item.hh,
* demo/shared/src/image_viewer.cc,
* demo/shared/src/image_viewer.hh,
* demo/shared/src/image_viewer.hxx,
* demo/shared/src/internal/interactive_scene.cc,
* demo/shared/src/internal/interactive_scene.hh,
* demo/shared/ui/image_viewer.ui: Improve look and feel and
drawing speed of these components.
* demo/wizard/src/load_page.cc,
* demo/wizard/src/main_window.cc,
* demo/wizard/src/runner.cc: Fix compilation.
2010-06-03 Guillaume Lazzara <z@lrde.epita.fr>
Small fixes.
......
......@@ -8,26 +8,31 @@ TARGET =
DEPENDPATH += . src
INCLUDEPATH += . ../ ../shared $(OLN)/milena $(OLN)
QMAKE_CXXFLAGS += -g
QMAKE_CXXFLAGS += -g -O0
LIBS += `Magick++-config --ldflags --libs`
LIBS +=/usr/lib/libMagick++.so
DEFINES += NDEBUG MLN_INCLUDE_ONLY
# `Magick++-config --ldflags --libs`
DEFINES += NDEBUG MLN_WO_GLOBAL_VARS
# Input
HEADERS += \
../shared/src/crop_item.hh \
../shared/src/image_viewer.hh \
../shared/src/internal/interactive_scene.hh \
../shared/src/crop_item.hh \
../shared/src/browse_widget.hh \
src/runner.hh \
src/main_window.hh
src/main_window.hh \
src/runner.hh
SOURCES += \
../shared/src/crop_item.cc \
../shared/src/image_viewer.cc \
../shared/src/internal/interactive_scene.cc \
../shared/src/browse_widget.cc \
src/mln_widgets.cc
src/main_window.cc \
src/main.cc \
src/runner.cc
FORMS += \
../shared/ui/image_viewer.ui \
......
#undef MLN_WO_GLOBAL_VARS
#include <mln/core/image/image2d.hh>
#include <mln/trace/all.hh>
#include <QtGui>
#include <src/main_window.hh>
#include <src/preprocessing_task.hh>
......
......@@ -45,10 +45,6 @@ namespace scribo
namespace demat
{
// FIXME: move it as attribute.
static mln::image2d<mln::value::rgb8> input_;
main_window::main_window()
{
setupUi(this);
......@@ -86,6 +82,9 @@ namespace scribo
progress_->setCancelButton(0);
progress_->setAutoClose(true);
action_Reload->setEnabled(false);
run_btn->setEnabled(false);
// Setup crop tool.
viewer_->set_selection_enabled(true);
connect(viewer_, SIGNAL(ready_for_crop()), this, SLOT(crop_slot()));
......@@ -114,13 +113,16 @@ namespace scribo
void main_window::load()
{
text_->hide();
text_->hide();
mln::io::magick::load(input_, current_image_.toStdString());
mln::io::magick::load(input_, current_image_.toStdString());
input_dsp_ = QPixmap::fromImage(mln::convert::to_qimage_nocopy(input_));
viewer_->draw_image(input_dsp_);
action_Reload->setEnabled(true);
run_btn->setEnabled(true);
}
......@@ -132,7 +134,8 @@ namespace scribo
process_args args; // Nothing for now.
runner_.start(current_image_, input_, Text_Doc, tasks, args);
runner_.start(current_image_, get_crop_image(), Text_Doc, tasks, args);
setEnabled(false);
}
......@@ -161,6 +164,8 @@ namespace scribo
tasks.insert(BinarizationSauvola);
else if (binarizationCBox->currentIndex() == 2)
tasks.insert(BinarizationSauvolaMs);
else if (binarizationCBox->currentIndex() == 3)
tasks.insert(BinarizationSauvolaMsSplit);
return tasks;
}
......@@ -199,15 +204,24 @@ namespace scribo
while (!in.atEnd())
{
QString line = in.readLine();
line = line.section(' ', 4);
text_->append(line);
}
text_->show();
setEnabled(true);
}
void main_window::crop_slot()
void main_window::on_action_Reload_triggered(bool)
{
load();
}
mln::image2d<mln::value::rgb8>
main_window::get_crop_image() const
{
mln::box2d b = input_.domain();
QRectF selection = viewer_->selection();
......@@ -224,15 +238,27 @@ namespace scribo
// Update underlying data.
mln::image2d<mln::value::rgb8> output(sbox);
mln::data::fill(output, input_);
input_ = output;
return output;
}
// No crop performed.
return input_;
}
void main_window::crop_slot()
{
mln::image2d<mln::value::rgb8> tmp = get_crop_image();
if (tmp.buffer() != input_.buffer()) // A crop has been performed.
{
input_ = tmp;
// Update display
viewer_->draw_image(input_);
}
viewer_->enable_crop_tool(false); // Disable crop tool
}
} // end of namespace scribo::demo::demat
} // end of namespace scribo::demo
......
......@@ -64,12 +64,15 @@ namespace scribo
void crop_slot();
void on_action_Reload_triggered(bool b);
private: // members
void load();
void prepare_progress_bar(unsigned max);
Doc_Type get_doc_type();
preprocessing_task_set_t get_tasks();
mln::image2d<mln::value::rgb8> get_crop_image() const;
private: // attributes
QPixmap input_dsp_;
......@@ -78,6 +81,8 @@ namespace scribo
QProgressDialog* progress_;
runner runner_;
mln::image2d<mln::value::rgb8> input_;
};
......
......@@ -46,6 +46,7 @@ namespace scribo
BinarizationSimple,
BinarizationSauvola,
BinarizationSauvolaMs,
BinarizationSauvolaMsSplit,
PREPROCESSING_TASK_COUNT // Invalid task.
};
......
......@@ -18,10 +18,11 @@
#include <scribo/preprocessing/split_bg_fg.hh>
#include <scribo/preprocessing/denoise.hh>
#include <scribo/preprocessing/homogeneous_contrast.hh>
#include <scribo/preprocessing/unskew.hh>
#include <scribo/preprocessing/deskew.hh>
#include <scribo/binarization/sauvola.hh>
#include <scribo/binarization/sauvola_ms.hh>
#include <scribo/binarization/simple.hh>
#include <scribo/binarization/sauvola_ms_split.hh>
#include <scribo/binarization/global_threshold_auto.hh>
#include <mln/logical/not.hh>
......@@ -33,9 +34,6 @@ namespace scribo
QString basedir_ = "";
// FIXME: move as attribute.
mln::image2d<mln::value::rgb8> input_;
runner::runner(QObject *parent)
: QThread(parent)
......@@ -97,6 +95,19 @@ namespace scribo
image2d<value::rgb8> tmp_color = duplicate(ima);
//
//==========
// Subsample
//==========
if (tasks_.contains(ReduceSize))
{
emit new_progress_label("Subsampling input image");
tmp_color = mln::subsampling::antialiased(tmp_color,
find_best_scale(tmp_color));
emit progress(1);
}
//==================
// Remove background
//==================
......@@ -121,16 +132,16 @@ namespace scribo
emit progress(1);
// FIXME: SUbsampling should be done at the very beginning!!!!
//
//==========
// Subsample
//==========
if (tasks_.contains(ReduceSize))
//=======
// Deskew
//=======
if (tasks_.contains(Unskew))
{
emit new_progress_label("Subsampling input image");
intensity_ima = mln::subsampling::antialiased(intensity_ima,
find_best_scale(intensity_ima));
std::cout << "Deskew" << std::endl;
emit new_progress_label("Deskew");
intensity_ima = scribo::preprocessing::deskew(intensity_ima);
emit progress(1);
}
......@@ -168,12 +179,20 @@ namespace scribo
{
// FIXME: sauvola should not negate the image.
std::cout << "Binarization Sauvola_ms" << std::endl;
out_bool = binarization::sauvola_ms(intensity_ima, 51, 2, 67);
out_bool = binarization::sauvola_ms(intensity_ima, 51, 2);
}
else if (tasks_.contains(BinarizationSauvolaMsSplit))
{
// FIXME: sauvola should not negate the image.
// FIXME: WARNING: work directly on the color image -> it is
// NOT deskewed nor contrast improved.
std::cout << "Binarization Sauvola_ms_split" << std::endl;
out_bool = binarization::sauvola_ms_split(tmp_color, 51, 2, 2);
}
else if (tasks_.contains(BinarizationSimple))
{
std::cout << "Binarization Simple" << std::endl;
out_bool = scribo::binarization::simple(intensity_ima);
out_bool = scribo::binarization::global_threshold_auto(intensity_ima);
}
else
{
......@@ -185,30 +204,18 @@ namespace scribo
// FIXME: remove!
// logical::not_inplace(out_bool);
logical::not_inplace(out_bool);
//========
// Denoise
//========
// if (tasks_.contains(RemoveNoise))
// {
// std::cout << "Remove noise" << std::endl;
// emit new_progress_label("Remove noise");
// out_bool = preprocessing::denoise(out_bool, c8(), 2, 2);
// emit progress(1);
// }
//=======
// Unskew
//=======
if (tasks_.contains(Unskew))
if (tasks_.contains(RemoveNoise))
{
std::cout << "Unskew" << std::endl;
emit new_progress_label("Unskew");
std::cout << "Remove noise" << std::endl;
emit new_progress_label("Remove noise");
out_bool = scribo::preprocessing::unskew(out_bool).first();
out_bool = preprocessing::denoise(out_bool, c8(), 2, 2);
emit progress(1);
}
......@@ -232,7 +239,7 @@ namespace scribo
{
case Text_Doc:
emit new_progress_label("Finding text in document...");
qDebug() << "Running text_in_article_pbm";
qDebug() << "Running pbm_text_in_doc";
args << "/tmp/tmp.pbm" << "/tmp/out.txt";
// Denoise.
......@@ -246,20 +253,24 @@ namespace scribo
args << "/tmp/";
if (process_.execute(basedir_ + "/text_in_article_pbm", args))
qDebug() << "Running:"
<< basedir_ + "/pbm_text_in_doc"
<< args;
if (process_.execute(basedir_ + "/pbm_text_in_doc", args))
{
qDebug() << "Error while running text_in_article_pbm.";
qDebug() << "Error while running pbm_text_in_doc.";
return;
}
break;
case Picture:
emit new_progress_label("Finding text in picture...");
qDebug() << "Running text_in_photo_pbm_fast";
qDebug() << "Running text_in_picture";
args << "/tmp/tmp.pbm" << "/tmp/out.ppm" << "1" << "1" << "1";
if (process_.execute(basedir_ + "/text_in_photo_pbm_fast", args))
if (process_.execute(basedir_ + "/text_in_picture", args))
{
qDebug() << "Error while running text_in_photo_pbm_fast.";
qDebug() << "Error while running text_in_picture.";
return;
}
break;
......
......@@ -81,6 +81,7 @@ namespace scribo
QSet<Preprocessing_Task> tasks_;
QString filename_;
process_args args_;
mln::image2d<mln::value::rgb8> input_;
};
......
......@@ -64,6 +64,8 @@
</property>
<addaction name="action_Open" />
<addaction name="separator" />
<addaction name="action_Reload" />
<addaction name="separator" />
<addaction name="action_Quit" />
</widget>
<widget class="QMenu" name="menuWindow" >
......@@ -270,6 +272,11 @@
<string>Local threshold multi-scale</string>
</property>
</item>
<item>
<property name="text" >
<string>Local threshold multi-scale (3-channels)</string>
</property>
</item>
</widget>
</item>
</layout>
......@@ -336,6 +343,14 @@
<string>Advanced options</string>
</property>
</action>
<action name="action_Reload" >
<property name="text" >
<string>&amp;Reload</string>
</property>
<property name="shortcut" >
<string>F5, Ctrl+R</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
......
......@@ -30,12 +30,19 @@
int main(int argc, char *argv[])
{
if (argc < 2 || argc > 4)
{
qDebug() << "Usage: "
<< argv[0] << " <path_to_scribo_src> [base_img_dir]";
return 0;
}
QApplication app(argc, argv);
scribo::demo::MainWindow win;
scribo::demo::MainWindow win(argv[1]);
if (argc == 2)
win.set_base_img_dir(argv[1]);
if (argc == 3)
win.set_base_img_dir(argv[2]);
win.show();
return app.exec();
......
......@@ -34,41 +34,41 @@
const char * modes[][4] = {
{ "Text in pictures", "pics", "../src/text_in_photo_ppm", "image-x-generic.png" },
{ "Text in docs", "doc", "../src/text_in_doc", "edit-find.png" },
{ "Text in pictures", "pics", "text_in_picture", "image-x-generic.png" },
{ "Text in docs", "doc", "text_in_doc", "edit-find.png" },
{ (const char *)(1), 0, 0, 0}, // Separator
{ "Handwritten text lines", "hsc", "../../milena/sandbox/icdar/2009/hsc/input_to_lines", "text-x-generic.png" },
{ "Handwritten text words", "hsc", "../../milena/sandbox/icdar/2009/hsc/input_to_words", "text-x-generic.png" },
{ (const char *)(1), 0, 0, 0}, // Separator
{ "Horizontal and Vertical Lines", "hvl", "../src/extract/primitive/find_discontinued_lines", "list-add.png" },
{ "Tables", "hvl", "../src/table/extract", "x-office-spreadsheet.png" },
{ "Pre-processing", "pproc", "../src/preprocess", "format-indent-more.png" },
{ "OCR", "ocr", "../src/recognition", "edit-find.png" },
{ "Horizontal and Vertical Lines", "hvl", "extract/primitive/find_discontinued_lines", "list-add.png" },
{ "Tables", "hvl", "table/extract", "x-office-spreadsheet.png" },
{ "Pre-processing", "pproc", "preprocess", "format-indent-more.png" },
{ "OCR", "ocr", "recognition", "edit-find.png" },
{ 0, 0, 0 } // Empty line, do NOT delete.
};
// Allow to set up to 3 extra arguments to the binaries.
// Allow to set up to 5 extra arguments to the binaries.
//
// A program will be launched as follow:
//
// ./my_program input.pbm <arg1> <arg2> <arg3> output.ppm
// ./my_program input.pbm output <arg1> <arg2> <arg3> <arg4> <arg5>
//
// Unused arguments are set to 0.
// Each line must be mapped to the related on in the previous
// array "modes". So DO preserve the order.
//
const char *args_list[][3] = {
{ 0, 0, 0 }, // Text in Pictures
{ 0, 0, 0 }, // Text in Docs
{ (const char *)(1), 0, 0}, // Separator
{ "/dev/null", 0, 0 }, // Handwritten text lines
{ "/dev/null", 0, 0 }, // Handwritten text words
{ (const char *)(1), 0, 0}, // Separator
{ "51", 0, 0 }, // Horizontal and Vertical lines
{ "/dev/null", 0, 0 }, // Tables
{ 0, 0, 0 }, // Pre-processing
{ 0, 0, 0 }, // OCR
const char *args_list[][6] = {
{ "1", "1", "1", "1", "1", 0 }, // Text in Pictures
{ 0, 0, 0, 0, 0, 0 }, // Text in Docs
{ (const char *)(1), 0, 0, 0, 0, 0 }, // Separator
{ "/dev/null", 0, 0, 0, 0, 0 }, // Handwritten text lines
{ "/dev/null", 0, 0, 0, 0, 0 }, // Handwritten text words
{ (const char *)(1), 0, 0, 0, 0, 0 }, // Separator
{ "51", 0, 0, 0, 0, 0 }, // Horizontal and Vertical lines
{ "/dev/null", 0, 0, 0, 0, 0 }, // Tables
{ 0, 0, 0, 0, 0, 0 }, // Pre-processing
{ 0, 0, 0, 0, 0, 0 }, // OCR
// Not empty line needed.
};
......@@ -80,8 +80,8 @@ namespace scribo
namespace demo
{
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), context_(this)
MainWindow::MainWindow(const QString& exec_prefix, QWidget *parent)
: QMainWindow(parent), exec_prefix_(exec_prefix + "/"), context_(this)
{
setupUi(this);
......@@ -92,7 +92,6 @@ namespace scribo
cached_result_.resize(nmodes);
mainRefItem_ = 0;
mainResultItem_ = 0;
exec_prefix_ = "";
base_img_dir_ = QCoreApplication::applicationDirPath();
pdialog_.setRange(0,0);
......@@ -165,7 +164,7 @@ namespace scribo
action->setCheckable(true);
action->setData(i);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_0 + i));
action->setEnabled(QFile::exists(modes[i][2]));
action->setEnabled(QFile::exists(exec_prefix_ + modes[i][2]));
if (modes[i][3] != 0)
action->setIcon(QIcon(QString(":/icons/") + modes[i][3]));
......@@ -185,7 +184,7 @@ namespace scribo
filename = QFileDialog::getOpenFileName(this,
tr("Open Image."),
base_img_dir_ + "/" + current_dir,
tr("Images (*.pbm *.pgm *.ppm)"));
tr("Images (*.pbm *.pgm *.ppm *.jpg *.png *.tiff)"));
prepare_for_run(filename);
}
......@@ -221,18 +220,21 @@ namespace scribo
QString input = filepath->text();
args << input;
QTemporaryFile f;
f.open();
args << f.fileName();
last_output_ = f.fileName();
for (unsigned i = 0; args_list[mode_][i]; ++i)
args << args_list[mode_][i];
// if (!is_in_ocr_mode())
// {
QTemporaryFile f;
f.open();
args << f.fileName();
last_output_ = f.fileName();
// }
// reset_progress_dialog();
qDebug() << "Running " << exec_prefix_ + modes[mode_][2]
<< " " << args;
exec_.start(exec_prefix_ + modes[mode_][2], args);
}
......
......@@ -45,7 +45,7 @@ namespace scribo
public:
MainWindow(QWidget *parent = 0);
MainWindow(const QString& exec_prefix, QWidget *parent = 0);
~MainWindow();
void set_base_img_dir(const QString& dir);
......
......@@ -35,17 +35,36 @@ namespace scribo
namespace shared
{
crop_item::crop_item(QGraphicsItem *parent)
: QGraphicsItem(parent)
{
mousePress_ = false;
setAcceptHoverEvents(true);
// draw_rect_ = scene()->sceneRect();